feat: Multi-agent support — Pi, OpenCode, and agent-agnostic hook layer#8
Open
alfredosdpiii wants to merge 23 commits intoalexfazio:mainfrom
Open
feat: Multi-agent support — Pi, OpenCode, and agent-agnostic hook layer#8alfredosdpiii wants to merge 23 commits intoalexfazio:mainfrom
alfredosdpiii wants to merge 23 commits intoalexfazio:mainfrom
Conversation
- Replace hardcoded CLAUDE_PROJECT_DIR with PLANKTON_PROJECT_DIR fallback - Add _resolve_config_path() for .plankton/config.json > .claude/hooks/config.json - Dynamic PLANKTON_PROTECTED_DIRS for multi-agent config directory protection - Add PLANKTON_DELEGATE_CMD and PLANKTON_ASK_TOOL for agent CLI abstraction - Update test assertions to match new PROJECT_DIR variable names
- Detect claude/pi/opencode CLIs on PATH - Migrate legacy .claude/hooks/config.json to .plankton/config.json - Generate Pi extension adapter at .pi/extensions/plankton.ts - Generate OpenCode plugin adapter at .opencode/plugins/plankton.ts - Add delegate_cmd config for agent CLI abstraction - Update scan exclusions to include .plankton directory
- Add .plankton/config.json as canonical config location - Hooks resolve config via .plankton/ with .claude/hooks/ fallback
- Bridge plankton hooks to pi's tool_call/tool_result events - Protect linter configs by blocking write/edit via tool_call handler - Enforce package managers by blocking bash commands via tool_call handler - Run multi_linter.sh post-edit via tool_result handler with async exec - Add AGENTS.md with linting behavior documentation
- Add opencode.json config pointing to plankton plugin - Add plugin scaffold at .opencode/plugins/plankton.ts - Add package.json with bun dependencies for plugin
- Use fully qualified model IDs (anthropic/claude-haiku-4-5, etc.) to avoid pi resolving fuzzy 'haiku' pattern to amazon-bedrock - Add --no-extensions flag to prevent recursive hook invocation when pi subprocess loads .pi/extensions/plankton.ts
tool.execute.before: read args from output.args, block via throw Error
instead of returning {blocked: true}. tool.execute.after: read args
from input.args, inject linter feedback into output.output instead of
nonexistent systemMessage property. Handle both camelCase (filePath)
and snake_case (file_path) arg names. Add patch/multiedit to file tool
set.
Primary agent with restricted tools (edit/read/write only), auto-approve permissions, temperature 0, and 8-step cap. Used by _delegate_opencode() to constrain subprocess behavior without --disallowedTools flag.
…sing
Replace hardcoded Anthropic model IDs with provider-agnostic defaults
via PLANKTON_OC_MODEL_{HAIKU,SONNET,OPUS} env vars. Route subprocess
through plankton-fixer agent for tool restriction. Add -- separator
before prompt to prevent --file array flag from swallowing it. Add
OPENCODE_PERMISSION env var for auto-approve fallback.
Contributor
|
merge this @alexfazio and i will implement gemini cli on top of this |
Move hooks and tests under .plankton, add the Pi extension package, and remove legacy Claude/OpenCode adapters.
Credo now respects a 'credo' boolean under languages.elixir, defaulting to true for backward compatibility.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Describe the change
I love this and would love to use this for Pi and Opencode ( everything else below is written by my agents )
what this does
Decouples Plankton's linting hooks from Claude Code so the same bash scripts work identically under **Claude Co
Why
Plankton's value is in the hook scripts — multi-phase linting, config protection, package-manager enforcement,
Changes
1. Agent-agnostic hook layer (
enforce_package_managers.sh,multi_linter.sh,protect_linter_configs.shCLAUDE_PROJECT_DIRwithPROJECT_DIRresolved fromPLANKTON_PROJECT_DIR→ `CLAUDE_PROJ_resolve_config_path()for config lookup:PLANKTON_CONFIG→.plankton/config.json→ `.claude/hooks/PLANKTON_PROTECTED_DIRS(colon-separated) instead of hardcoded.claude/path checksPLANKTON_DELEGATE_CMDfor agent CLI routing (claude,pi,opencode,auto,none)PLANKTON_ASK_TOOLfor agent-specific user prompt tool names instop_config_guardian.shtest_hook.shto match renamed variable2. Plankton config directory (
.plankton/config.json).plankton/config.json, agent-neutral_resolve_config_path()with legacy.claude/hooks/config.jsonfallbacksubprocess.delegate_cmdconfig field for per-project agent CLI override3. Pi coding agent extension (
.pi/extensions/plankton.ts,.pi/AGENTS.md)tool_callhandler runsprotect_linter_configs.shbeforewrite/editandenforce_package_managers.shtool_resulthandler runsmulti_linter.shafterwrite/edit; appends lint findings to tool result conteevent.toolName(notevent.tool) and asyncexecAsyncfor the 600s lint timeout to avoid freezing thPLANKTON_DELEGATE_CMD=piandPLANKTON_PROTECTED_DIRS=.claude:.plankton:.pianthropic/claude-haiku-4-5, etc.) instead of fuzzy `haiku--no-extensionsto Pi subprocess invocation to prevent infinite loop4. OpenCode plugin adapter (
.opencode/plugins/plankton.ts,.opencode/agents/plankton-fixer.md, `opencodtool.execute.beforeblocks config writes and wrong package managers (throwsError)tool.execute.afterrunsmulti_linter.shpost-edit, appends findings tooutput.outputedit/read/writeonly, temp 0, 8-step limit) for subprocess fix tasks@opencode-ai/pluginAPI contract (named export,directoryparam, return-objePLANKTON_OC_MODEL_*env var overrides and--agent plankton-fixerrouting5. Setup wizard updates (
scripts/setup.py)detect_agents()probes$PATHforclaude,pi,opencode_migrate_legacy_config()copies.claude/hooks/config.json→.plankton/config.jsonsetup_pi_adapter()/setup_opencode_adapter()scaffold adapter files when CLIs are detected.plankton/config.json;.plankton/added to scan exclusionsArchitecture
Backward compatibility
CLAUDE_PROJECT_DIRand `.claude/hooks/config.json_resolve_config_path()falls back to.claude/hooks/config.json. Setup wizard offersCommits
7c55bdarefactor: make hooks agent-agnostic with plankton env varse9f5c1ffeat: add multi-agent support to setup wizardfa240e3feat: add plankton config directory0b2e1d1feat: add pi coding agent extension adapter32c4de3feat: add opencode plugin adapter42687bcfix: pi delegation model resolution and recursion guard174fc9bfix: align opencode plugin with actual plugin API contract7703a2afeat: add plankton-fixer agent for opencode subprocess delegation73a6ae4fix: opencode delegation model resolution, agent routing, and arg parsinghow to test
Shared hooks (agent-agnostic)
Config protection (pre-tool block):
Package manager enforcement (pre-tool block):
Self-test suite (139 tests):
Python test suite (345 tests):
Pi end-to-end
OpenCode end-to-end
Prerequisites:
Plugin smoke test (requires restarting opencode after any plugin changes):
Subprocess delegation (runs outside opencode session):
Plugin API contract verification:
Known limitations (OpenCode)
--disallowedToolsequivalent, so theplankton-fixer agent uses a fixed tool set (edit/read/write) for all tiers. Claude Code's
haiku tier gets Edit+Read only; opus gets Bash too. OpenCode delegates always get the same set.
--max-turns: iteration control uses the agent'ssteps: 8config instead of a CLI flag.Timeout (
timeout ${tier_timeout}) is the hard backstop.--modelby default and uses whatever model the user has configured globally. Override per tier with
PLANKTON_OC_MODEL_HAIKU,PLANKTON_OC_MODEL_SONNET,PLANKTON_OC_MODEL_OPUSenv vars..opencode/plugins/are loaded at startup.After editing
plankton.ts, you must restart opencode for changes to take effect.mode: primarybecauseopencode run --agentrequires a primary agent. This means it appears in the Tab agent switcher. It has nopractical effect since it only runs as a subprocess.
checklist
.claude/hooks/test_hook.sh --self-testpasses (139/139)uv run pytest tests/ -qpasses (345/345)