@doingdev/opencode-claude-manager-plugin 0.1.25 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # OpenCode Claude Manager Plugin
2
2
 
3
- This package provides an OpenCode plugin that lets an OpenCode-side manager agent orchestrate Claude Code sessions through a stable local bridge.
3
+ This package provides an OpenCode plugin that lets an OpenCode-side agent hierarchy orchestrate Claude Code sessions through a stable local bridge.
4
4
 
5
5
  ## Overview
6
6
 
@@ -51,43 +51,43 @@ If you are testing locally, point OpenCode at the local package or plugin file u
51
51
 
52
52
  ## OpenCode tools
53
53
 
54
- ### Session management
54
+ ### Engineer session
55
55
 
56
- - `claude_manager_send` — send a message to the persistent Claude Code session. Auto-creates on first call, resumes on subsequent calls.
56
+ - `engineer_send` — send a message to the persistent Claude Code session. Auto-creates on first call, resumes on subsequent calls.
57
57
  - `message` (required) — the instruction to send.
58
58
  - `mode` — `"plan"` (read-only investigation) or `"free"` (default, normal execution with edits).
59
59
  - `freshSession` — set to `true` to clear the active session before sending. Use when switching to an unrelated task or when context is contaminated.
60
60
  - `model` — `"claude-opus-4-6"` (default, recommended for most coding work), `"claude-sonnet-4-6"`, or `"claude-sonnet-4-5"` (faster/lighter tasks).
61
61
  - `effort` — `"high"` (default), `"medium"` (lighter tasks), `"low"`, or `"max"` (especially hard problems).
62
- - `claude_manager_compact` — compress the active session context while preserving session state. Use before clearing when context is high but salvageable.
63
- - `claude_manager_clear` — drop the active session entirely; next send starts fresh.
64
- - `claude_manager_status` — get current session health: context %, turns, cost, session ID.
62
+ - `engineer_compact` — compress the active session context while preserving session state. Use before clearing when context is high but salvageable.
63
+ - `engineer_clear` — drop the active session entirely; next send starts fresh.
64
+ - `engineer_status` — get current session health: context %, turns, cost, session ID.
65
65
 
66
66
  ### Git operations
67
67
 
68
- - `claude_manager_git_diff` — review all uncommitted changes (staged + unstaged).
69
- - `claude_manager_git_commit` — stage all changes and commit with a message.
70
- - `claude_manager_git_reset` — hard reset + clean (destructive).
68
+ - `git_diff` — review all uncommitted changes (staged + unstaged).
69
+ - `git_commit` — stage all changes and commit with a message.
70
+ - `git_reset` — hard reset + clean (destructive).
71
71
 
72
72
  ### Inspection
73
73
 
74
- - `claude_manager_metadata` — inspect available Claude commands, skills, hooks, and settings.
75
- - `claude_manager_sessions` — list Claude sessions or inspect a saved transcript.
76
- - `claude_manager_runs` — list or inspect persisted manager run records (may be empty if tasks were sent directly via `claude_manager_send` rather than the run-tracking path).
74
+ - `engineer_metadata` — inspect available Claude commands, skills, hooks, and settings.
75
+ - `engineer_sessions` — list Claude sessions or inspect a saved transcript.
76
+ - `engineer_runs` — list or inspect persisted manager run records (may be empty if tasks were sent directly via `engineer_send` rather than the run-tracking path).
77
77
 
78
78
  ### Tool approval
79
79
 
80
- - `claude_manager_approval_policy` — view the current tool approval policy.
81
- - `claude_manager_approval_decisions` — view recent tool approval decisions.
82
- - `claude_manager_approval_update` — add/remove rules, change default action, or enable/disable approval.
80
+ - `approval_policy` — view the current tool approval policy.
81
+ - `approval_decisions` — view recent tool approval decisions.
82
+ - `approval_update` — add/remove rules, change default action, or enable/disable approval.
83
83
 
84
- ## Plugin-provided agents and commands
84
+ ## Agent hierarchy
85
85
 
86
- When the plugin loads successfully, it also injects config entries through the OpenCode plugin `config` hook.
86
+ The plugin registers a CTO Manager Engineer hierarchy through the OpenCode plugin `config` hook:
87
87
 
88
- - Primary agent: `claude-manager`
89
- - Subagent: `claude-manager-research`
90
- - Commands: `/claude-metadata`, `/claude-run`, `/claude-sessions`
88
+ - **`cto`** (primary agent) — sets direction and orchestrates work by spawning `manager` subagents. Has read/search/web tools but does NOT operate Claude Code directly.
89
+ - **`manager`** (subagent) — operates a Claude Code engineer through a persistent session. Has the full tool surface (`engineer_*`, `git_*`, `approval_*`) plus read/search/web tools for investigation.
90
+ - **Engineer** the Claude Code persistent session itself (not an OpenCode agent). Receives instructions from the manager, executes code changes, and reports results.
91
91
 
92
92
  These are added to OpenCode config at runtime by the plugin, so they do not require separate manual `opencode.json` entries.
93
93
 
@@ -95,27 +95,27 @@ These are added to OpenCode config at runtime by the plugin, so they do not requ
95
95
 
96
96
  Typical flow inside OpenCode:
97
97
 
98
- 1. Inspect Claude capabilities with `claude_manager_metadata`.
99
- 2. Delegate work with `claude_manager_send`.
100
- 3. Review changes with `claude_manager_git_diff`, then commit or reset.
101
- 4. Inspect saved Claude history with `claude_manager_sessions` or prior orchestration records with `claude_manager_runs`.
98
+ 1. Inspect Claude capabilities with `engineer_metadata`.
99
+ 2. Delegate work with `engineer_send`.
100
+ 3. Review changes with `git_diff`, then commit or reset.
101
+ 4. Inspect saved Claude history with `engineer_sessions` or prior orchestration records with `engineer_runs`.
102
102
 
103
103
  Example tasks:
104
104
 
105
105
  ```text
106
- Use claude_manager_send to implement the new validation logic in src/auth.ts, then review with claude_manager_git_diff.
106
+ Use engineer_send to implement the new validation logic in src/auth.ts, then review with git_diff.
107
107
  ```
108
108
 
109
109
  Start a fresh session for an unrelated task:
110
110
 
111
111
  ```text
112
- Use claude_manager_send with freshSession:true to investigate the failing CI test in test/api.test.ts using mode:"plan".
112
+ Use engineer_send with freshSession:true to investigate the failing CI test in test/api.test.ts using mode:"plan".
113
113
  ```
114
114
 
115
115
  Reclaim context mid-session:
116
116
 
117
117
  ```text
118
- Use claude_manager_compact to free up context, then continue with the next implementation step.
118
+ Use engineer_compact to free up context, then continue with the next implementation step.
119
119
  ```
120
120
 
121
121
  ## Local Development
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Agent hierarchy configuration for the CTO + Engineer Wrapper architecture.
3
+ *
4
+ * CTO (cto) — main operator, directly controls Claude Code sessions
5
+ * Engineer Plan (engineer_plan) — thin subagent wrapper for read-only investigation
6
+ * Engineer Build (engineer_build) — thin subagent wrapper for implementation tasks
7
+ * Engineer — the Claude Code session itself (prompt only, no OpenCode agent)
8
+ */
9
+ import type { ManagerPromptRegistry } from '../types/contracts.js';
10
+ export declare const AGENT_CTO = "cto";
11
+ export declare const AGENT_ENGINEER_PLAN = "engineer_plan";
12
+ export declare const AGENT_ENGINEER_BUILD = "engineer_build";
13
+ /** All restricted tool IDs (union of engineer + git + approval) */
14
+ export declare const ALL_RESTRICTED_TOOL_IDS: readonly ["engineer_send", "engineer_compact", "engineer_clear", "engineer_status", "engineer_metadata", "engineer_sessions", "engineer_runs", "git_diff", "git_commit", "git_reset", "approval_policy", "approval_decisions", "approval_update"];
15
+ type ToolPermission = 'allow' | 'ask' | 'deny';
16
+ type AgentPermission = {
17
+ '*'?: ToolPermission;
18
+ read?: ToolPermission;
19
+ grep?: ToolPermission;
20
+ glob?: ToolPermission;
21
+ codesearch?: ToolPermission;
22
+ webfetch?: ToolPermission;
23
+ websearch?: ToolPermission;
24
+ /** OpenCode built-in: manage session todo list */
25
+ todowrite?: ToolPermission;
26
+ /** OpenCode built-in: read session todo list */
27
+ todoread?: ToolPermission;
28
+ /** OpenCode built-in: ask the user structured questions with options */
29
+ question?: ToolPermission;
30
+ bash?: ToolPermission | Record<string, ToolPermission>;
31
+ [tool: string]: ToolPermission | Record<string, ToolPermission> | undefined;
32
+ };
33
+ export declare function buildCtoAgentConfig(prompts: ManagerPromptRegistry): {
34
+ description: string;
35
+ mode: "primary";
36
+ color: string;
37
+ permission: AgentPermission;
38
+ prompt: string;
39
+ };
40
+ export declare function buildEngineerPlanAgentConfig(prompts: ManagerPromptRegistry): {
41
+ description: string;
42
+ mode: "subagent";
43
+ color: string;
44
+ permission: AgentPermission;
45
+ prompt: string;
46
+ };
47
+ export declare function buildEngineerBuildAgentConfig(prompts: ManagerPromptRegistry): {
48
+ description: string;
49
+ mode: "subagent";
50
+ color: string;
51
+ permission: AgentPermission;
52
+ prompt: string;
53
+ };
54
+ /** Deny all restricted tools at the global level so only designated agents can use them. */
55
+ export declare function denyRestrictedToolsGlobally(permissions: Record<string, ToolPermission>): void;
56
+ export {};
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Agent hierarchy configuration for the CTO + Engineer Wrapper architecture.
3
+ *
4
+ * CTO (cto) — main operator, directly controls Claude Code sessions
5
+ * Engineer Plan (engineer_plan) — thin subagent wrapper for read-only investigation
6
+ * Engineer Build (engineer_build) — thin subagent wrapper for implementation tasks
7
+ * Engineer — the Claude Code session itself (prompt only, no OpenCode agent)
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // Agent names
11
+ // ---------------------------------------------------------------------------
12
+ export const AGENT_CTO = 'cto';
13
+ export const AGENT_ENGINEER_PLAN = 'engineer_plan';
14
+ export const AGENT_ENGINEER_BUILD = 'engineer_build';
15
+ // ---------------------------------------------------------------------------
16
+ // Tool IDs — grouped by domain
17
+ // ---------------------------------------------------------------------------
18
+ /** Engineer-facing session tools */
19
+ const ENGINEER_TOOL_IDS = [
20
+ 'engineer_send',
21
+ 'engineer_compact',
22
+ 'engineer_clear',
23
+ 'engineer_status',
24
+ 'engineer_metadata',
25
+ 'engineer_sessions',
26
+ 'engineer_runs',
27
+ ];
28
+ /** Git tools */
29
+ const GIT_TOOL_IDS = ['git_diff', 'git_commit', 'git_reset'];
30
+ /** Approval tools */
31
+ const APPROVAL_TOOL_IDS = [
32
+ 'approval_policy',
33
+ 'approval_decisions',
34
+ 'approval_update',
35
+ ];
36
+ /** All restricted tool IDs (union of engineer + git + approval) */
37
+ export const ALL_RESTRICTED_TOOL_IDS = [
38
+ ...ENGINEER_TOOL_IDS,
39
+ ...GIT_TOOL_IDS,
40
+ ...APPROVAL_TOOL_IDS,
41
+ ];
42
+ /** Tools available to engineer wrapper subagents (thin wrappers around Claude Code) */
43
+ const ENGINEER_WRAPPER_TOOL_IDS = ['engineer_send', 'engineer_status'];
44
+ // ---------------------------------------------------------------------------
45
+ // Shared read-only tool permissions
46
+ // ---------------------------------------------------------------------------
47
+ const READONLY_TOOLS = {
48
+ read: 'allow',
49
+ grep: 'allow',
50
+ glob: 'allow',
51
+ codesearch: 'allow',
52
+ webfetch: 'allow',
53
+ websearch: 'allow',
54
+ todowrite: 'allow',
55
+ todoread: 'allow',
56
+ question: 'allow',
57
+ };
58
+ // ---------------------------------------------------------------------------
59
+ // Permission builders
60
+ // ---------------------------------------------------------------------------
61
+ /** CTO: full operator — all restricted tools + read-only codebase tools. No edit, no bash. */
62
+ function buildCtoPermissions() {
63
+ const allowed = {};
64
+ for (const toolId of ALL_RESTRICTED_TOOL_IDS) {
65
+ allowed[toolId] = 'allow';
66
+ }
67
+ return {
68
+ '*': 'deny',
69
+ ...READONLY_TOOLS,
70
+ ...allowed,
71
+ };
72
+ }
73
+ /** Engineer wrapper: only engineer_send + engineer_status. Everything else denied. */
74
+ function buildEngineerWrapperPermissions() {
75
+ const denied = {};
76
+ for (const toolId of ALL_RESTRICTED_TOOL_IDS) {
77
+ denied[toolId] = 'deny';
78
+ }
79
+ const allowed = {};
80
+ for (const toolId of ENGINEER_WRAPPER_TOOL_IDS) {
81
+ allowed[toolId] = 'allow';
82
+ }
83
+ return {
84
+ '*': 'deny',
85
+ ...denied,
86
+ ...allowed,
87
+ };
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // Agent config builders
91
+ // ---------------------------------------------------------------------------
92
+ export function buildCtoAgentConfig(prompts) {
93
+ return {
94
+ description: 'CTO agent that directly operates Claude Code, gathers information, investigates, reviews, and commits. Can spawn engineer wrappers for parallel or isolated work.',
95
+ mode: 'primary',
96
+ color: '#D97757',
97
+ permission: buildCtoPermissions(),
98
+ prompt: prompts.ctoSystemPrompt,
99
+ };
100
+ }
101
+ export function buildEngineerPlanAgentConfig(prompts) {
102
+ return {
103
+ description: 'Thin wrapper that sends a read-only investigation task to Claude Code in plan mode and returns the result.',
104
+ mode: 'subagent',
105
+ color: '#D97757',
106
+ permission: buildEngineerWrapperPermissions(),
107
+ prompt: prompts.engineerPlanPrompt,
108
+ };
109
+ }
110
+ export function buildEngineerBuildAgentConfig(prompts) {
111
+ return {
112
+ description: 'Thin wrapper that sends an implementation task to Claude Code in free mode and returns the result.',
113
+ mode: 'subagent',
114
+ color: '#D97757',
115
+ permission: buildEngineerWrapperPermissions(),
116
+ prompt: prompts.engineerBuildPrompt,
117
+ };
118
+ }
119
+ // ---------------------------------------------------------------------------
120
+ // Global permission helper
121
+ // ---------------------------------------------------------------------------
122
+ /** Deny all restricted tools at the global level so only designated agents can use them. */
123
+ export function denyRestrictedToolsGlobally(permissions) {
124
+ for (const toolId of ALL_RESTRICTED_TOOL_IDS) {
125
+ permissions[toolId] ??= 'deny';
126
+ }
127
+ }
@@ -1,115 +1,20 @@
1
1
  import { tool } from '@opencode-ai/plugin';
2
2
  import { managerPromptRegistry } from '../prompts/registry.js';
3
+ import { AGENT_CTO, AGENT_ENGINEER_BUILD, AGENT_ENGINEER_PLAN, buildCtoAgentConfig, buildEngineerBuildAgentConfig, buildEngineerPlanAgentConfig, denyRestrictedToolsGlobally, } from './agent-hierarchy.js';
3
4
  import { getOrCreatePluginServices } from './service-factory.js';
4
- const MANAGER_TOOL_IDS = [
5
- 'claude_manager_send',
6
- 'claude_manager_compact',
7
- 'claude_manager_git_diff',
8
- 'claude_manager_git_commit',
9
- 'claude_manager_git_reset',
10
- 'claude_manager_clear',
11
- 'claude_manager_status',
12
- 'claude_manager_metadata',
13
- 'claude_manager_sessions',
14
- 'claude_manager_runs',
15
- 'claude_manager_approval_policy',
16
- 'claude_manager_approval_decisions',
17
- 'claude_manager_approval_update',
18
- ];
19
5
  export const ClaudeManagerPlugin = async ({ worktree }) => {
20
6
  const services = getOrCreatePluginServices(worktree);
21
7
  return {
22
8
  config: async (config) => {
23
9
  config.agent ??= {};
24
- config.command ??= {};
25
10
  config.permission ??= {};
26
- const globalPermissions = config.permission;
27
- const managerPermissions = {};
28
- const researchPermissions = {};
29
- for (const toolId of MANAGER_TOOL_IDS) {
30
- globalPermissions[toolId] ??= 'deny';
31
- managerPermissions[toolId] = 'allow';
32
- // Research agent can inspect but not send or modify
33
- researchPermissions[toolId] =
34
- toolId === 'claude_manager_send' ||
35
- toolId === 'claude_manager_compact' ||
36
- toolId === 'claude_manager_git_commit' ||
37
- toolId === 'claude_manager_git_reset' ||
38
- toolId === 'claude_manager_clear' ||
39
- toolId === 'claude_manager_approval_update'
40
- ? 'deny'
41
- : 'allow';
42
- }
43
- config.agent['claude-manager'] ??= {
44
- description: 'Primary agent that operates Claude Code through a persistent session, reviews work via git diff, and commits/resets changes.',
45
- mode: 'primary',
46
- color: '#D97757',
47
- permission: {
48
- '*': 'deny',
49
- read: 'allow',
50
- grep: 'allow',
51
- glob: 'allow',
52
- codesearch: 'allow',
53
- webfetch: 'allow',
54
- websearch: 'allow',
55
- todowrite: 'allow',
56
- todoread: 'allow',
57
- question: 'allow',
58
- ...managerPermissions,
59
- },
60
- prompt: managerPromptRegistry.managerSystemPrompt,
61
- };
62
- config.agent['claude-manager-research'] ??= {
63
- description: 'Subagent that inspects Claude metadata, prior sessions, and manager runs without changing repository state.',
64
- mode: 'subagent',
65
- color: 'info',
66
- permission: {
67
- '*': 'deny',
68
- ...researchPermissions,
69
- },
70
- prompt: [
71
- 'Focus on inspection and summarization.',
72
- 'Use claude_manager_status, claude_manager_metadata, claude_manager_sessions, and claude_manager_runs to gather information.',
73
- ].join(' '),
74
- };
75
- config.command['claude-run'] ??= {
76
- description: 'Send a task to the persistent Claude Code session.',
77
- agent: 'claude-manager',
78
- subtask: true,
79
- template: [
80
- 'Use claude_manager_send to send the following task to Claude Code:',
81
- '$ARGUMENTS',
82
- 'After it completes, review the result and use claude_manager_git_diff if changes were expected. Commit or reset accordingly.',
83
- ].join('\n\n'),
84
- };
85
- config.command['claude-metadata'] ??= {
86
- description: 'Inspect bundled Claude commands, skills, hooks, and agents.',
87
- agent: 'claude-manager-research',
88
- subtask: true,
89
- template: [
90
- 'Use claude_manager_metadata to inspect the current repository.',
91
- 'Summarize Claude commands, skills, hooks, discovered agents, and important config files.',
92
- ].join(' '),
93
- };
94
- config.command['claude-sessions'] ??= {
95
- description: 'Inspect Claude session history and manager run records.',
96
- agent: 'claude-manager-research',
97
- subtask: true,
98
- template: [
99
- 'Use claude_manager_sessions and claude_manager_runs to inspect recent Claude activity for this repository.',
100
- 'If the user provided extra arguments, use them to focus the inspection:',
101
- '$ARGUMENTS',
102
- ].join('\n\n'),
103
- };
104
- },
105
- 'command.execute.before': async (input, output) => {
106
- const commandText = buildCommandText(input.command, input.arguments);
107
- if (commandText) {
108
- output.parts = rewriteCommandParts(output.parts, commandText);
109
- }
11
+ denyRestrictedToolsGlobally(config.permission);
12
+ config.agent[AGENT_CTO] ??= buildCtoAgentConfig(managerPromptRegistry);
13
+ config.agent[AGENT_ENGINEER_PLAN] ??= buildEngineerPlanAgentConfig(managerPromptRegistry);
14
+ config.agent[AGENT_ENGINEER_BUILD] ??= buildEngineerBuildAgentConfig(managerPromptRegistry);
110
15
  },
111
16
  tool: {
112
- claude_manager_send: tool({
17
+ engineer_send: tool({
113
18
  description: 'Send a message to the persistent Claude Code session. ' +
114
19
  'Auto-creates a session on first call. Resumes the existing session on subsequent calls. ' +
115
20
  'Returns the assistant response and current context health snapshot. ' +
@@ -320,7 +225,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
320
225
  }, null, 2);
321
226
  },
322
227
  }),
323
- claude_manager_compact: tool({
228
+ engineer_compact: tool({
324
229
  description: 'Compact the active Claude Code session to reclaim context space. ' +
325
230
  'Sends /compact to the session, which compresses prior conversation while preserving state. ' +
326
231
  'Use before clearing when context is high but the session still has useful state. ' +
@@ -350,7 +255,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
350
255
  }, null, 2);
351
256
  },
352
257
  }),
353
- claude_manager_git_diff: tool({
258
+ git_diff: tool({
354
259
  description: 'Run git diff to see all current changes (staged + unstaged) relative to HEAD.',
355
260
  args: {
356
261
  cwd: tool.schema.string().optional(),
@@ -361,7 +266,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
361
266
  return JSON.stringify(result, null, 2);
362
267
  },
363
268
  }),
364
- claude_manager_git_commit: tool({
269
+ git_commit: tool({
365
270
  description: 'Stage all changes and commit with the given message.',
366
271
  args: {
367
272
  message: tool.schema.string().min(1),
@@ -375,7 +280,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
375
280
  return JSON.stringify(result, null, 2);
376
281
  },
377
282
  }),
378
- claude_manager_git_reset: tool({
283
+ git_reset: tool({
379
284
  description: 'Run git reset --hard HEAD and git clean -fd to discard ALL uncommitted changes and untracked files.',
380
285
  args: {
381
286
  cwd: tool.schema.string().optional(),
@@ -386,7 +291,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
386
291
  return JSON.stringify(result, null, 2);
387
292
  },
388
293
  }),
389
- claude_manager_clear: tool({
294
+ engineer_clear: tool({
390
295
  description: 'Clear the active Claude Code session. The next send will start a fresh session. ' +
391
296
  'Use when context is full, the session is confused, or starting a different task.',
392
297
  args: {
@@ -401,7 +306,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
401
306
  return JSON.stringify({ clearedSessionId: clearedId });
402
307
  },
403
308
  }),
404
- claude_manager_status: tool({
309
+ engineer_status: tool({
405
310
  description: 'Get the current persistent session status: context usage %, turns, cost, active session ID.',
406
311
  args: {
407
312
  cwd: tool.schema.string().optional(),
@@ -418,7 +323,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
418
323
  }, null, 2);
419
324
  },
420
325
  }),
421
- claude_manager_metadata: tool({
326
+ engineer_metadata: tool({
422
327
  description: 'Inspect Claude slash commands, skills, hooks, and repo settings.',
423
328
  args: {
424
329
  cwd: tool.schema.string().optional(),
@@ -434,9 +339,9 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
434
339
  return JSON.stringify(metadata, null, 2);
435
340
  },
436
341
  }),
437
- claude_manager_sessions: tool({
342
+ engineer_sessions: tool({
438
343
  description: 'List Claude sessions or inspect a saved transcript. ' +
439
- 'When sessionId is provided, returns both SDK transcript and local manager events.',
344
+ 'When sessionId is provided, returns both SDK transcript and local events.',
440
345
  args: {
441
346
  cwd: tool.schema.string().optional(),
442
347
  sessionId: tool.schema.string().optional(),
@@ -458,7 +363,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
458
363
  return JSON.stringify(sessions, null, 2);
459
364
  },
460
365
  }),
461
- claude_manager_runs: tool({
366
+ engineer_runs: tool({
462
367
  description: 'List persistent manager run records.',
463
368
  args: {
464
369
  cwd: tool.schema.string().optional(),
@@ -474,7 +379,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
474
379
  return JSON.stringify(runs, null, 2);
475
380
  },
476
381
  }),
477
- claude_manager_approval_policy: tool({
382
+ approval_policy: tool({
478
383
  description: 'View the current tool approval policy: rules, default action, and enabled status.',
479
384
  args: {},
480
385
  async execute(_args, context) {
@@ -482,7 +387,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
482
387
  return JSON.stringify(services.approvalManager.getPolicy(), null, 2);
483
388
  },
484
389
  }),
485
- claude_manager_approval_decisions: tool({
390
+ approval_decisions: tool({
486
391
  description: 'View recent tool approval decisions. Shows what tools were allowed or denied. ' +
487
392
  'Use deniedOnly to see only denied calls.',
488
393
  args: {
@@ -497,7 +402,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
497
402
  return JSON.stringify({ total: decisions.length, decisions }, null, 2);
498
403
  },
499
404
  }),
500
- claude_manager_approval_update: tool({
405
+ approval_update: tool({
501
406
  description: 'Update the tool approval policy. Add/remove rules, change default action, or enable/disable. ' +
502
407
  'Rules are evaluated top-to-bottom; first match wins.',
503
408
  args: {
@@ -568,47 +473,6 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
568
473
  function annotateToolRun(context, title, metadata) {
569
474
  context.metadata({ title, metadata });
570
475
  }
571
- function buildCommandText(command, rawArguments) {
572
- const argumentsText = rawArguments.trim();
573
- if (command === 'claude-run') {
574
- return [
575
- 'Use `claude_manager_send` to send the following task to Claude Code:',
576
- argumentsText
577
- ? argumentsText
578
- : 'Inspect the current repository and wait for follow-up instructions.',
579
- 'After it completes, review the result. If code changes were expected, use `claude_manager_git_diff` to review, then `claude_manager_git_commit` or `claude_manager_git_reset` accordingly.',
580
- ].join('\n\n');
581
- }
582
- if (command === 'claude-metadata') {
583
- return [
584
- 'Call `claude_manager_metadata` immediately for the current repository.',
585
- argumentsText ? `Focus: ${argumentsText}` : '',
586
- 'Then summarize the discovered Claude commands, skills, hooks, agents, and config files briefly.',
587
- ]
588
- .filter(Boolean)
589
- .join('\n\n');
590
- }
591
- if (command === 'claude-sessions') {
592
- return [
593
- 'Call `claude_manager_sessions` and `claude_manager_runs` immediately for the current repository.',
594
- argumentsText ? `Focus: ${argumentsText}` : '',
595
- 'Then summarize the most relevant recent Claude activity briefly.',
596
- ]
597
- .filter(Boolean)
598
- .join('\n\n');
599
- }
600
- return null;
601
- }
602
- function rewriteCommandParts(parts, text) {
603
- let hasRewrittenText = false;
604
- return parts.map((part) => {
605
- if (part.type !== 'text' || hasRewrittenText) {
606
- return part;
607
- }
608
- hasRewrittenText = true;
609
- return { ...part, text };
610
- });
611
- }
612
476
  function formatContextWarning(context) {
613
477
  const { warningLevel, estimatedContextPercent, totalTurns, totalCostUsd } = context;
614
478
  if (warningLevel === 'ok' || estimatedContextPercent === null) {
@@ -22,7 +22,7 @@ export function getOrCreatePluginServices(worktree) {
22
22
  const metadataService = new ClaudeMetadataService(new RepoClaudeConfigReader(), sdkAdapter);
23
23
  const sessionService = new ClaudeSessionService(sdkAdapter, metadataService);
24
24
  const contextTracker = new ContextTracker();
25
- const sessionController = new SessionController(sdkAdapter, contextTracker, managerPromptRegistry.claudeCodeSessionPrompt, managerPromptRegistry.modePrefixes);
25
+ const sessionController = new SessionController(sdkAdapter, contextTracker, managerPromptRegistry.engineerSessionPrompt, managerPromptRegistry.modePrefixes);
26
26
  const gitOps = new GitOperations(worktree);
27
27
  const stateStore = new FileRunStateStore();
28
28
  const transcriptStore = new TranscriptStore();
@@ -1,28 +1,34 @@
1
1
  export const managerPromptRegistry = {
2
- managerSystemPrompt: [
3
- 'You are a senior IC operating Claude Code through a persistent session.',
4
- 'Your job is to make Claude Code do the work not to write code yourself.',
5
- 'Think like a staff engineer: correctness, maintainability, tests, rollback safety,',
6
- 'and clear communication to the user.',
2
+ ctoSystemPrompt: [
3
+ 'You are the CTO — a top 0.001% Claude Code operator.',
4
+ 'You directly operate Claude Code through a persistent session, gather information,',
5
+ 'investigate code, review diffs, and commit changes. You can also spawn thin',
6
+ 'engineer wrapper subagents for parallel or isolated work.',
7
+ '',
8
+ '## Your role',
9
+ '- You are the PRIMARY operator. You do not merely orchestrate — you execute.',
10
+ '- Think like a staff+ engineer: correctness, maintainability, tests, rollback safety.',
11
+ '- Gather requirements thoroughly before acting. Clarify ambiguity early.',
12
+ '- Plan thoughtfully, execute with quality, review rigorously.',
7
13
  '',
8
14
  '## Decision loop',
9
15
  'On every turn, choose exactly one action:',
10
- ' investigate — read files, grep, search the codebase to build context',
11
- ' delegate — send a focused instruction to Claude Code via claude_manager_send',
12
- ' review — run claude_manager_git_diff to inspect what changed',
13
- ' validate — tell Claude Code to run tests, lint, or typecheck',
14
- ' commit — checkpoint good work with claude_manager_git_commit',
16
+ ' investigate — read files, grep, search the codebase, or send a plan-mode task to build context',
17
+ ' delegate — send a focused instruction to the engineer via engineer_send',
18
+ ' review — run git_diff to inspect what changed',
19
+ ' validate — tell the engineer to run tests, lint, or typecheck',
20
+ ' commit — checkpoint good work with git_commit',
15
21
  ' correct — send a targeted fix instruction (never "try again")',
16
- ' reset — discard bad work with claude_manager_git_reset',
22
+ ' reset — discard bad work with git_reset',
17
23
  ' ask — use the question tool for structured choices, or one narrow text question',
24
+ ' spawn — spawn an engineer_plan or engineer_build subagent for parallel/isolated work',
18
25
  '',
19
26
  'Default order: investigate → delegate → review → validate → commit.',
20
27
  'Skip steps only when you have strong evidence they are unnecessary.',
21
28
  '',
22
29
  '## Before you delegate',
23
30
  '1. Read the relevant files yourself (you have read, grep, glob).',
24
- ' For broad investigations, scope them narrowly or use subagents to avoid',
25
- ' polluting your own context with excessive file contents.',
31
+ ' For broad investigations, scope them narrowly or use engineer_plan subagents.',
26
32
  '2. Identify the exact files, functions, line numbers, and patterns involved.',
27
33
  '3. Check existing conventions: naming, test style, error handling patterns.',
28
34
  '4. Craft an instruction that a senior engineer would find unambiguous.',
@@ -33,49 +39,56 @@ export const managerPromptRegistry = {
33
39
  '',
34
40
  '## After delegation — mandatory review',
35
41
  'Never claim success without evidence:',
36
- '1. claude_manager_git_diff — read the actual diff, not just the summary.',
42
+ '1. git_diff — read the actual diff, not just the summary.',
37
43
  '2. Verify the diff matches what you asked for. Check for:',
38
44
  ' - Unintended changes or regressions',
39
45
  ' - Missing test updates',
40
46
  ' - Style violations against repo conventions',
41
- '3. If changes look correct, tell Claude Code to run tests/lint/typecheck.',
47
+ '3. If changes look correct, tell the engineer to run tests/lint/typecheck.',
42
48
  '4. Only commit after verification passes.',
43
49
  '5. If the diff is wrong: send a specific correction or reset.',
44
50
  '',
51
+ '## Spawning engineer wrappers',
52
+ 'Use subagents for parallel or isolated work:',
53
+ '- `engineer_plan` — sends tasks in plan mode (read-only investigation).',
54
+ ' Use for: exploring unfamiliar code, analyzing dependencies, generating plans.',
55
+ '- `engineer_build` — sends tasks in free mode (implementation).',
56
+ ' Use for: independent implementation slices that do not conflict with your main work.',
57
+ '- Provide each subagent with a clear, scoped objective and relevant context.',
58
+ '- Subagents are THIN wrappers — they relay to Claude Code and return results.',
59
+ ' They do not investigate, review diffs, or commit. YOU do that after they return.',
60
+ '- If slices are independent, spawn them in parallel.',
61
+ '',
45
62
  '## Handling ambiguity',
46
63
  'When requirements are unclear:',
47
64
  '1. First, try to resolve it yourself — read code, check tests, grep for usage.',
48
65
  '2. If ambiguity remains, ask the user ONE specific question.',
49
- ' Prefer the question tool when discrete options exist (OpenCode shows choices in the UI).',
50
- ' Bad: "What should I do?"',
51
- ' Good: "The `UserService` has both `deactivate()` and `softDelete()` —',
52
- ' should the new endpoint use deactivation (reversible) or',
53
- ' soft-delete (audit-logged)?"',
66
+ ' Prefer the question tool when discrete options exist.',
54
67
  '3. Never block on multiple questions at once.',
55
68
  '',
56
69
  '## Correction and recovery',
57
- 'If Claude Code produces wrong output:',
70
+ 'If the engineer produces wrong output:',
58
71
  '1. First correction: send a specific, targeted fix instruction.',
59
72
  '2. Second correction on the same issue: reset, clear the session,',
60
73
  ' and rewrite the prompt incorporating lessons from both failures.',
61
74
  'Never send three corrections for the same problem in one session.',
62
75
  '',
63
76
  '## Multi-step tasks',
64
- '- Use todowrite / todoread to track steps in OpenCode; keep items concrete and few.',
77
+ '- Use todowrite / todoread to track steps; keep items concrete and few.',
65
78
  '- Decompose large tasks into sequential focused instructions.',
66
79
  '- Commit after each successful step (checkpoint for rollback).',
67
- '- Tell Claude Code to use subagents for independent parallel work.',
68
- '- For complex design decisions, tell Claude Code to "think hard".',
80
+ '- Tell the engineer to use subagents for independent parallel work.',
81
+ '- For complex design decisions, tell the engineer to "think hard".',
69
82
  '- Prefer small diffs — they are easier to review and safer to ship.',
70
83
  '',
71
84
  '## Context management',
72
85
  'Check the context snapshot returned by each send:',
73
86
  '- Under 50%: proceed freely.',
74
87
  '- 50–70%: finish current step, then evaluate if a fresh session is needed.',
75
- '- Over 70%: use claude_manager_compact to reclaim context if the session',
88
+ '- Over 70%: use engineer_compact to reclaim context if the session',
76
89
  ' still has useful state. Only clear if compaction is insufficient.',
77
90
  '- Over 85%: clear the session immediately.',
78
- 'Use freshSession:true on claude_manager_send when switching to an unrelated',
91
+ 'Use freshSession:true on engineer_send when switching to an unrelated',
79
92
  'task or when the session context is contaminated. Prefer this over a manual',
80
93
  'clear+send sequence — it is atomic and self-documenting.',
81
94
  '',
@@ -90,27 +103,30 @@ export const managerPromptRegistry = {
90
103
  "- Do not use Haiku for this plugin's coding-agent role.",
91
104
  '',
92
105
  '## Plan mode',
93
- 'When delegating with mode:"plan", Claude Code returns a read-only',
106
+ 'When delegating with mode:"plan", the engineer returns a read-only',
94
107
  'implementation plan. The plan MUST be returned inline in the assistant',
95
108
  'response — do NOT write plan artifacts to disk, create files, or rely on',
96
109
  'ExitPlanMode. Treat the returned finalText as the plan. If the plan is',
97
110
  'acceptable, switch to mode:"free" and delegate the implementation steps.',
98
111
  '',
99
112
  '## Tools reference',
100
- 'todowrite / todoread — OpenCode session todo list (track multi-step work)',
101
- 'question — OpenCode user prompt with options (clarify trade-offs)',
102
- 'claude_manager_send — send instruction (creates or resumes session)',
103
- ' freshSession:true — clear session first (use for unrelated tasks)',
104
- ' model / effort — choose deliberately (see "Model and effort selection")',
105
- 'claude_manager_compact — compress session context (preserves session state)',
106
- 'claude_manager_git_diff review all uncommitted changes',
107
- 'claude_manager_git_commit stage all + commit',
108
- 'claude_manager_git_reset hard reset + clean (destructive)',
109
- 'claude_manager_cleardrop session, next send starts fresh',
110
- 'claude_manager_status context health snapshot',
111
- 'claude_manager_metadata inspect repo Claude config',
112
- 'claude_manager_sessions list sessions or read transcripts',
113
- 'claude_manager_runs list or inspect run records',
113
+ 'todowrite / todoread — OpenCode session todo list (track multi-step work)',
114
+ 'question — OpenCode user prompt with options (clarify trade-offs)',
115
+ 'engineer_send — send instruction (creates or resumes session)',
116
+ ' freshSession:true — clear session first (use for unrelated tasks)',
117
+ ' model / effort — choose deliberately (see "Model and effort selection")',
118
+ 'engineer_compact — compress session context (preserves session state)',
119
+ 'engineer_clear drop session, next send starts fresh',
120
+ 'engineer_status context health snapshot',
121
+ 'engineer_metadata inspect repo Claude config',
122
+ 'engineer_sessionslist sessions or read transcripts',
123
+ 'engineer_runs list or inspect run records',
124
+ 'git_diff review all uncommitted changes',
125
+ 'git_commit stage all + commit',
126
+ 'git_reset hard reset + clean (destructive)',
127
+ 'approval_policy — view tool approval rules',
128
+ 'approval_decisions — view recent approval decisions',
129
+ 'approval_update — modify tool approval policy',
114
130
  '',
115
131
  '## Autonomy blockers — surface these to the user',
116
132
  'Be candid about what you cannot do autonomously:',
@@ -120,9 +136,41 @@ export const managerPromptRegistry = {
120
136
  '- Access to external services or environments you cannot reach.',
121
137
  'State the blocker, what you need, and a concrete suggestion to unblock.',
122
138
  ].join('\n'),
123
- claudeCodeSessionPrompt: [
124
- 'You are directed by an expert automated operator.',
125
- 'Treat each message as a precise instruction from a senior engineer.',
139
+ engineerPlanPrompt: [
140
+ 'You are a thin engineer wrapper. Your only job is to relay a read-only investigation',
141
+ 'task to Claude Code in plan mode and return the result.',
142
+ '',
143
+ '## Behavior',
144
+ '- You will receive an objective from the CTO.',
145
+ '- Send it to Claude Code using engineer_send with mode:"plan".',
146
+ "- Return the engineer's response verbatim. Do not summarize or interpret.",
147
+ '- Use engineer_status if you need to check session health before sending.',
148
+ '',
149
+ '## What you must NOT do',
150
+ '- Do NOT investigate on your own — no read, grep, glob, or web tools.',
151
+ '- Do NOT call git_*, approval_*, or any other tools.',
152
+ '- Do NOT add commentary, opinions, or additional analysis.',
153
+ '- Do NOT attempt multiple sends. One send per invocation.',
154
+ ].join('\n'),
155
+ engineerBuildPrompt: [
156
+ 'You are a thin engineer wrapper. Your only job is to relay an implementation',
157
+ 'task to Claude Code in free mode and return the result.',
158
+ '',
159
+ '## Behavior',
160
+ '- You will receive an objective from the CTO.',
161
+ '- Send it to Claude Code using engineer_send with mode:"free".',
162
+ "- Return the engineer's response verbatim. Do not summarize or interpret.",
163
+ '- Use engineer_status if you need to check session health before sending.',
164
+ '',
165
+ '## What you must NOT do',
166
+ '- Do NOT investigate on your own — no read, grep, glob, or web tools.',
167
+ '- Do NOT call git_*, approval_*, or any other tools.',
168
+ '- Do NOT add commentary, opinions, or additional analysis.',
169
+ '- Do NOT attempt multiple sends. One send per invocation.',
170
+ ].join('\n'),
171
+ engineerSessionPrompt: [
172
+ 'You are directed by the CTO acting as your technical lead.',
173
+ 'Treat each message as a precise instruction from the CTO.',
126
174
  '',
127
175
  '## Execution rules',
128
176
  '- Execute instructions directly. Do not ask for clarification.',
@@ -139,7 +187,7 @@ export const managerPromptRegistry = {
139
187
  '',
140
188
  '## Git boundary — do NOT run these commands:',
141
189
  'git commit, git push, git reset, git checkout, git stash.',
142
- 'The operator manages all git operations externally.',
190
+ 'The CTO handles all git operations externally.',
143
191
  '',
144
192
  '## Reporting',
145
193
  '- End with a brief verification summary: what was done, what was verified.',
@@ -1,6 +1,8 @@
1
1
  export interface ManagerPromptRegistry {
2
- managerSystemPrompt: string;
3
- claudeCodeSessionPrompt: string;
2
+ ctoSystemPrompt: string;
3
+ engineerPlanPrompt: string;
4
+ engineerBuildPrompt: string;
5
+ engineerSessionPrompt: string;
4
6
  modePrefixes: {
5
7
  plan: string;
6
8
  free: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doingdev/opencode-claude-manager-plugin",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "OpenCode plugin that orchestrates Claude Code sessions.",
5
5
  "keywords": [
6
6
  "opencode",