@doingdev/opencode-claude-manager-plugin
v0.1.100
Published
OpenCode plugin that orchestrates Claude Code sessions.
Maintainers
Readme
@doingdev/opencode-claude-manager-plugin
OpenCode plugin that adds a manager-style orchestration layer over Claude Code sessions. A cto agent reads the repo, asks focused questions, and delegates to named engineers who each run work in their own persistent Claude Code session.
Useful when you want OpenCode to investigate first, split work across named engineers with session continuity, and keep git and review controls at the manager layer.
What it adds
ctoorchestrator that reads, delegates, reviews diffs, and owns all manager tools. Never edits files directly.- Five persistent general engineers — Tom, John, Maya, Sara, Alex — each backed by its own Claude Code session that survives across assignments in the same CTO session. Dispatched directly by the CTO via
dispatch_engineer; not registered as OpenCode subagents. plan_with_teamCTO tool that runs two engineers in parallel and returns a single synthesized plan.- BrowserQA verification specialist dispatched directly by the CTO via the
run_browser_qatool using Playwright-oriented prompting. Not registered as an OpenCode subagent. Does not implement code. - Manager tools for team state, git, transcript/history inspection, and tool approval policy.
- Local runtime state under
.claude-manager/persisted across turns.
Requirements
- Node
>=22 - OpenCode with plugin loading enabled
- Claude Agent SDK (
@anthropic-ai/claude-agent-sdk) available to the Node process - Git - required for the git tools
- OpenCode Playwright skill/command - required for
browser-qa
Install
pnpm add @doingdev/opencode-claude-manager-plugin
# npm install @doingdev/opencode-claude-manager-plugin
# yarn add @doingdev/opencode-claude-manager-pluginSetup
Add the plugin to opencode.json in your project root:
{
"plugin": ["@doingdev/opencode-claude-manager-plugin"]
}Agents register automatically at runtime. No manual agent entries needed.
Key concepts
Delegation model. The CTO reads the repo and context, decides what to do, and dispatches a named engineer via the dispatch_engineer tool. The engineer runs that assignment inside its own persistent Claude Code session. BrowserQA is dispatched the same way through the run_browser_qa tool. The CTO never edits files directly.
Engineer persistence. Each engineer's Claude Code session persists within a CTO session. A follow-up assignment to the same engineer resumes with prior context, which helps with multi-step tasks or when the engineer already understands a subsystem.
Modes. When delegating, the CTO picks a mode:
explore— read-only investigation. No file edits.implement— hands-on implementation work.verify— tests, lint, spot-checks after changes.
Teams. Each CTO session has its own team. State is keyed by CTO session ID under .claude-manager/teams/.
Agents
| Agent | Role |
| ----- | --------------------------------------------------------------------------------- |
| cto | Orchestrator. Reads, delegates, reviews, owns manager tools. Does not edit files. |
cto is the only OpenCode subagent registered by this plugin. General engineers (Tom, John, Maya, Sara, Alex) are dispatched directly by the CTO via the dispatch_engineer tool. BrowserQA is dispatched directly via the run_browser_qa tool. None of them are registered as OpenCode subagents.
Tools
CTO tools
| Tool | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| dispatch_engineer | Dispatch a named general engineer (Tom/John/Maya/Sara/Alex) directly to its persistent Claude Code session. Takes engineer, mode, goal, plus optional context, deliverable, constraints, verification, references rendered as labeled sections. |
| run_browser_qa | Run BrowserQA's persistent Claude Code session in verify mode. Takes goal plus optional context and verification. |
| run_code_review | Run a structured code review and save the artifact under .claude-manager/reviews/. When focus is omitted, a review focus is inferred from the changed paths (public-api, state-persistence, approval-security, prompts, plugin-wiring, undo-history, ui-accessibility, build-config, test-only, docs-only) and returned as effectiveFocus. Explicit focus always wins. |
| plan_with_team | Runs two general engineers in parallel on the same planning task, then synthesizes one recommended plan. browser-qa is not part of the planning pool. |
| team_status | Show current team: engineers, sessions, context levels. |
| reset_engineer | Clear a stuck engineer's Claude session, assignment history, or both. |
| git_add | Stage changes for commit. |
| git_diff | Diff with optional path filter, staged flag, or ref. |
| git_commit | Commit staged changes with a message and optional file list. |
| git_reset | Destructive. Runs git reset --hard HEAD && git clean -fd. |
| git_status | Short status and cleanliness check. |
| git_log | Recent commit log. |
| list_transcripts | List saved Claude session transcripts in .claude-manager/transcripts/. |
| list_history | List saved team state in .claude-manager/teams/. |
| approval_policy | Read the active tool approval policy. |
| approval_decisions | Read the logged approval decisions. Returns { total, decisions, denialSummary } — decisions/total honor limit/deniedOnly; denialSummary is always global. |
| approval_update | Update the tool approval policy. |
Slash commands
| Command | Description |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| /reflect | Asks each general engineer used in this CTO session (those with lastUsedAt set, subset of Tom/John/Maya/Sara/Alex) in parallel, in explore mode, to surface advisory suggestions for instruction changes, memory additions, and process improvements. The CTO also self-reflects, then deduplicates and synthesizes. BrowserQA is excluded. Must be run in a CTO session. |
Approval policy
Each engineer's Claude Code session runs under a tool approval manager. The policy is deny-list based: unmatched tools stay allowed and defaultAction is always allow.
Rule fields:
pattern— glob matching the tool name.inputPattern(optional) — substring match against tool input.action—allowordeny.message(optional) — shown when the rule fires.
Default rules block patterns like rm -rf /, git push --force, and git reset --hard. Read the active policy with approval_policy, inspect logged decisions with approval_decisions, and change rules with approval_update.
approval_decisions returns { total, decisions, denialSummary }. decisions is the caller-scoped slice (honors limit and deniedOnly, most-recent first) and total is that slice's length. denialSummary is always computed over the full decision log — it groups recurring denies by toolName + matchedRuleId with counts, timestamps, and a truncated sample of the most recent denied input — so denialSummary.totalDenies can exceed total when the caller asked for a small recent window. The same summary is also surfaced best-effort on team_status, and mined by /reflect to flag over-restriction or missing affordances.
Review routing
run_code_review infers a review angle from the changed paths when focus is omitted, and surfaces it as effectiveFocus plus a raw inferredFoci tag list in the tool's JSON output and in session metadata. Explicit focus always wins. The tags are advisory — they bias the reviewer's checklist toward the concerns most likely to matter for that change:
| Tag | Trigger | Bias |
| ------------------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| public-api | src/index.ts, src/types/contracts.ts, other src/types/** | Exported surface, backwards compatibility, tool-schema/contract shape |
| state-persistence | src/state/**, src/team/**, team/transcript stores, roster, persistent-manager | On-disk schema, atomicity, crash/rollback safety |
| approval-security | tool-approval-manager, src/**/agents/**, service-factory, agent-hierarchy | Policy correctness, deny/allow semantics, trust boundaries |
| prompts | src/prompts/** | Template drift, placeholder coverage, cross-entry-point consistency |
| plugin-wiring | src/plugin/** (outside approval paths) | Tool definitions, lifecycle hooks, factory closures, service wiring |
| undo-history | Paths matching undo/wrapper-history/revert | Revert dedup, /undo propagation, history pruning correctness |
| ui-accessibility | *.tsx/*.jsx/*.vue/*.svelte, CSS, components/**/pages/**/app/** | Responsive behavior, keyboard flow, semantics, labels, contrast |
| build-config | package.json, pnpm-lock.yaml, tsconfig*.json, ESLint/Vitest configs, .github/** | Dependency surface, CI wiring, type-check and lint coverage |
| test-only | Every changed path is a test file | Coverage quality, determinism — no production change expected |
| docs-only | Every changed path is documentation | Accuracy and link integrity — no production change expected |
When ui-accessibility is inferred on a change that is NOT test-only or docs-only, the returned JSON sets browserQaFollowupSuggested: true — consider run_browser_qa as the follow-up verification.
Workflows
Investigate then implement:
Ask cto to inspect the failing billing tests, send tom to implement the smallest safe fix, then review with git_diff.Dual-engineer planning:
Ask cto to run plan_with_team to produce a two-engineer synthesized plan for adding SSO to the auth module.Browser verification:
Ask cto to send browser-qa to verify the signup flow on http://localhost:3000 and report failures.Reuse engineer context:
Ask cto to send john to add error handling to the function he just implemented.Inspect state before committing:
Ask cto to run git_diff, summarize the changes, then run git_commit with a descriptive message.Configuration
On first run the plugin creates .claude-manager/config.toml with documented defaults. Edit it to override provider, model, and effort settings.
version = 1
[defaults.opencode]
# Outer OpenCode agent defaults.
provider = "openai"
model = "gpt-5.5-mini"
effort = "medium"
[defaults.claude]
# Default model for all inner Claude Code sessions.
model = "claude-opus-4-6"
[defaults.claude.effort]
# Effort per work mode. Valid values: "low", "medium", "high", "max"
explore = "high"
implement = "high"
verify = "high"
plan = "high" # used for plan_with_team synthesis
[agents.cto.opencode]
provider = "openai"
model = "gpt-5.5"
effort = "medium"
# Per-agent overrides (all fields optional):
[agents.tom.opencode]
# provider = "inherit" # use host/session provider
# model = "gpt-5.5-mini" # outer OpenCode agent model for Tom
# effort = "medium" # outer OpenCode reasoning effort for Tom
# [agents.tom.claude]
# model = "claude-opus-4-6" # Tom's inner Claude Code session model
# effort = "high" # Tom's effort override (all modes)
[agents.browser-qa.claude]
model = "claude-sonnet-4-6"
effort = "high"Precedence
Outer OpenCode agent model:
- Host/OpenCode
config.agent[id]— always wins if already set. [agents.<id>.opencode]model fromconfig.toml.[defaults.opencode]model fromconfig.toml.- Host session default only when the resolved config value is
"inherit".
When provider is not "inherit" and the model is unqualified, the plugin composes "provider/model" (e.g. "anthropic/claude-opus-4-6"). Fully qualified model strings like "openai/gpt-5" are used as-is.
Outer OpenCode reasoning effort:
[agents.<id>.opencode].effortfor that specific agent.[defaults.opencode].effort.- Host/provider default only when the resolved config value is
"inherit".
Valid outer OpenCode effort values are "none", "minimal", "low", "medium", "high", and "xhigh".
Inner Claude worker model:
- Explicit
modelarg on theclaude/plan_with_teamtool call. [agents.<id>.claude].modelfor that specific engineer.[defaults.claude].model.- Session default only when the resolved config value is
"inherit".
Inner Claude worker effort:
[agents.<id>.claude].effortfor that specific engineer.[defaults.claude.effort].<mode>for the active work mode.- Hardcoded fallback (
"high"forimplement,"medium"otherwise).
Malformed config is silently ignored; hardcoded defaults apply.
State
Runtime state is local to the worktree and gitignored:
.claude-manager/
config.toml # Plugin config (auto-created, safe to edit)
teams/ # One JSON file per CTO session (team ID)
transcripts/ # Claude session event logs
approval-policy.json # Active policy, if customized
debug.log # NDJSON debug log from plugin hooks- State is not shared across machines or worktrees.
- Continuity is strongest within a single CTO session. Restarting the CTO session starts a new team.
- Undo at the CTO level propagates to each engineer's inner Claude Code session (sending
/undoper affected exchange) and prunes their persisted assignment history. All engineers (including BrowserQA) are direct-dispatched, so there are no OpenCode wrapper sessions to revert.
Limits and caveats
- Context usage tracking is heuristic, not exact SDK-reported truth. Actual token counts may differ.
browser-qareturnsPLAYWRIGHT_UNAVAILABLE: <reason>if the Playwright skill or command is missing.plan_with_teamruns two general engineers.browser-qais excluded from the planning pool.git_resetis destructive and immediate. Rungit_difffirst to inspect state.- Engineer context degrades if sessions are reset or if the CTO session is restarted mid-task.
Development
pnpm install
pnpm run lint
pnpm run typecheck
pnpm run test
pnpm run builddist/ is generated output. Do not edit it directly.
