@anyi61/codex-claude-delegate-mcp 0.1.0

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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +262 -0
  3. package/dist/claude-cli.d.ts +84 -0
  4. package/dist/claude-cli.js +3123 -0
  5. package/dist/claude-cli.js.map +1 -0
  6. package/dist/cli.d.ts +61 -0
  7. package/dist/cli.js +334 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/codex-config.d.ts +104 -0
  10. package/dist/codex-config.js +446 -0
  11. package/dist/codex-config.js.map +1 -0
  12. package/dist/guard.d.ts +27 -0
  13. package/dist/guard.js +229 -0
  14. package/dist/guard.js.map +1 -0
  15. package/dist/job-runner.d.ts +13 -0
  16. package/dist/job-runner.js +75 -0
  17. package/dist/job-runner.js.map +1 -0
  18. package/dist/jobs.d.ts +46 -0
  19. package/dist/jobs.js +175 -0
  20. package/dist/jobs.js.map +1 -0
  21. package/dist/package-info.d.ts +4 -0
  22. package/dist/package-info.js +14 -0
  23. package/dist/package-info.js.map +1 -0
  24. package/dist/schema.d.ts +779 -0
  25. package/dist/schema.js +325 -0
  26. package/dist/schema.js.map +1 -0
  27. package/dist/server.d.ts +1142 -0
  28. package/dist/server.js +693 -0
  29. package/dist/server.js.map +1 -0
  30. package/dist/session.d.ts +35 -0
  31. package/dist/session.js +109 -0
  32. package/dist/session.js.map +1 -0
  33. package/package.json +49 -0
  34. package/plugins/codex-claude-delegate/.codex-plugin/plugin.json +36 -0
  35. package/plugins/codex-claude-delegate/.mcp.json +9 -0
  36. package/plugins/codex-claude-delegate/hooks/hooks.json +16 -0
  37. package/plugins/codex-claude-delegate/hooks/review-gate-stop.mjs +66 -0
  38. package/plugins/codex-claude-delegate/server/job-runner.js +16999 -0
  39. package/plugins/codex-claude-delegate/server/server.js +28048 -0
  40. package/plugins/codex-claude-delegate/skills/claude-delegate.md +30 -0
  41. package/plugins/codex-claude-delegate/skills/claude-rescue.md +52 -0
  42. package/plugins/codex-claude-delegate/skills/claude-review.md +25 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 anyi61
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,262 @@
1
+ # codex-claude-delegate-mcp
2
+
3
+ Let Codex delegate read/review/write tasks to Claude Code through a local MCP server.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npm install -g @anyi61/codex-claude-delegate-mcp
9
+ codex-claude setup --write
10
+ codex-claude doctor
11
+ ```
12
+
13
+ Restart Codex, then ask:
14
+
15
+ ```text
16
+ Use claude_setup to check this repository.
17
+ ```
18
+
19
+ ### 60-Second Demo
20
+
21
+ ```text
22
+ 1. claude_setup → checks workspace readiness
23
+ 2. claude_task(mode="read", ...) → delegate a read analysis
24
+ 3. claude_task(mode="write", ...) → delegate a write task with instruction_files
25
+ 4. claude_job_wait(...) → poll until the job completes
26
+ 5. claude_result(...) → inspect results and changed files
27
+ 6. claude_apply(preview=true, ...) → preview the diff
28
+ 7. user approval → user confirms
29
+ 8. claude_apply(cleanup=true, ...) → apply changes and clean up worktree
30
+ 9. claude_cleanup(dry_run=true, ...) → confirm no stale worktrees remain
31
+ ```
32
+
33
+ ## Features
34
+
35
+ - **Delegate read/review/write tasks** — from Codex to Claude Code
36
+ - **Isolated git worktree execution** — write tasks run in a separate worktree, leaving your main workspace untouched
37
+ - **Background job polling** — all delegations are queued as background jobs with progress tracking
38
+ - **Preview before apply** — review worktree diffs before landing changes in your main workspace
39
+ - **Review gate** — optional stop-hook that prompts review before terminal state transitions
40
+
41
+ ## Install
42
+
43
+ ### Prerequisites
44
+
45
+ - Codex CLI installed and authenticated
46
+ - `node` >= 20 available in PATH
47
+ - Claude Code CLI `claude` available in PATH (or set `CLAUDE_BIN`)
48
+ - Git (write mode requires worktree support)
49
+
50
+ ### Global install (recommended)
51
+
52
+ ```bash
53
+ npm install -g @anyi61/codex-claude-delegate-mcp
54
+ ```
55
+
56
+ Verify installation:
57
+
58
+ ```bash
59
+ codex-claude --version
60
+ ```
61
+
62
+ ### Setup
63
+
64
+ Write the MCP server configuration to Codex config:
65
+
66
+ ```bash
67
+ codex-claude setup --write
68
+ ```
69
+
70
+ This adds `command = "codex-claude"` with the default 6 tools to `~/.codex/config.toml`.
71
+
72
+ Options:
73
+
74
+ | Flag | Description |
75
+ |------|-------------|
76
+ | `--force` | Overwrite existing claude_delegate config (creates timestamped backup) |
77
+ | `--allow-root <path>` | Add a repository to `CODEX_CLAUDE_ALLOW_ROOTS` |
78
+ | `--project` | Write to `./.codex/config.toml` instead of global config |
79
+ | `--print` | Preview the config that would be written |
80
+
81
+ ### Doctor
82
+
83
+ Verify your installation:
84
+
85
+ ```bash
86
+ codex-claude doctor
87
+ ```
88
+
89
+ Checks Node.js ≥ 20, package version, Claude CLI path/version, Git, worktree support, Codex config, default tools, and allow roots.
90
+
91
+ ```bash
92
+ codex-claude doctor --json
93
+ ```
94
+
95
+ ### Print config
96
+
97
+ See the MCP server TOML config without writing:
98
+
99
+ ```bash
100
+ codex-claude print-config
101
+ codex-claude print-config --source /path/to/repo
102
+ codex-claude print-config --project
103
+ ```
104
+
105
+ ## Default tool set
106
+
107
+ `setup --write` and `print-config` enable exactly 6 tools:
108
+
109
+ | Tool | Usage |
110
+ |------|-------|
111
+ | `claude_setup` | First-use / check workspace readiness |
112
+ | `claude_task` | **Recommended entry point**, auto-routes to read/review/write |
113
+ | `claude_job_wait` | Poll background job until terminal state |
114
+ | `claude_result` | Get the most relevant completed result + next_actions |
115
+ | `claude_apply` | Preview or land worktree changes into main workspace |
116
+ | `claude_cleanup` | Remove stale delegated worktrees (defaults to dry-run) |
117
+
118
+ ## Usage flow
119
+
120
+ ### Read-only analysis
121
+
122
+ ```text
123
+ claude_task(mode="read", cwd="/path/to/repo", task="Explain how auth works")
124
+ → claude_job_wait(cwd="...", job_id="job-xxx")
125
+ → claude_result(cwd="...", prefer="latest-job")
126
+ ```
127
+
128
+ ### Review / audit
129
+
130
+ ```text
131
+ claude_task(mode="review", cwd="/path/to/repo", task="Check for security issues")
132
+ → claude_job_wait → claude_result
133
+ ```
134
+
135
+ ### Write / apply / cleanup
136
+
137
+ ```text
138
+ claude_task(mode="write", cwd="/path/to/repo", task="Implement feature X")
139
+ → claude_job_wait(cwd="...", job_id="...")
140
+ → claude_result(cwd="...")
141
+ → claude_apply(cwd="...", worktree_path=".claude/worktrees/...", preview=true)
142
+ → user confirms → claude_apply(cwd="...", worktree_path="...", cleanup=true, confirmed_by_user=true)
143
+ → claude_cleanup(cwd="...", dry_run=true)
144
+ ```
145
+
146
+ ## Advanced / Debug tools
147
+
148
+ These tools are NOT in the default config. Enable them explicitly in `~/.codex/config.toml`:
149
+
150
+ ```toml
151
+ [mcp_servers.claude_delegate]
152
+ enabled_tools = ["claude_status", "claude_runs", "claude_run_inspect", "claude_workspace_status", "claude_review_gate", "claude_query", "claude_review", "claude_implement", "claude_jobs", "claude_job_result", "claude_job_cancel", "claude_job_cleanup"]
153
+ ```
154
+
155
+ | Tool | Purpose |
156
+ |------|---------|
157
+ | `claude_status` | Check Claude/Git/worktree/auth status |
158
+ | `claude_runs` | List historical run logs |
159
+ | `claude_run_inspect` | View single run details by run_id |
160
+ | `claude_workspace_status` | Aggregated view: jobs / runs / sessions / worktrees |
161
+ | `claude_review_gate` | Enable/disable/status review gate |
162
+ | `claude_query` | Read-only Q&A (low-level entry) |
163
+ | `claude_review` | Read-only review (low-level entry) |
164
+ | `claude_implement` | Isolated worktree implementation (low-level entry) |
165
+ | `claude_jobs` | List background jobs |
166
+ | `claude_job_result` | Read job by job_id |
167
+ | `claude_job_cancel` | Cancel a running job |
168
+ | `claude_job_cleanup` | Clean old terminal job records |
169
+
170
+ ## Important notes
171
+
172
+ - **`claude_task.files` is deprecated.** Use `instruction_files` instead. `claude_task.files` is treated as context only, not apply scope.
173
+ - **`claude_implement.files`** is a strict scope control for cases where precise file constraints are needed.
174
+ - **Uncommitted workspace changes:** Default returns `needs_user`. Pass `dirty_policy=committed` to ignore local changes, or `dirty_policy=snapshot` to copy dirty files into the worktree.
175
+ - **Polling behavior:** `claude_job_wait` does not long-block. When `poll_too_soon=true`, wait until `next_allowed_poll_at`. When `waiting=true`, do not start a duplicate job.
176
+ - **Turn caps:** `claude_task` does not accept `max_turns`. Use Advanced tools (`claude_query` / `claude_review` / `claude_implement`) when explicit turn limits are needed.
177
+ - **Apply safety:** `preview=true` does not modify the main workspace. Non-preview `claude_apply` requires `confirmed_by_user=true` after user approval.
178
+ - **Invalid combination:** `preview=true` + `cleanup=true` is rejected — preview should not delete the worktree.
179
+ - **Next actions:** `claude_result` and `claude_job_wait` only suggest preview operations (`preview=true`), never direct non-preview apply.
180
+
181
+ ## Configuration
182
+
183
+ ### Allow roots
184
+
185
+ Default allowed roots are `~/projects`, `~/work`, `~/codex-claude`. Extend via:
186
+
187
+ ```toml
188
+ # ~/.codex/config.toml
189
+ [shell_environment_policy.set]
190
+ CODEX_CLAUDE_ALLOW_ROOTS = "/Users/you/projects:/Users/you/work:/Users/you/my-repo"
191
+ ```
192
+
193
+ Or use the CLI:
194
+
195
+ ```bash
196
+ codex-claude setup --write --allow-root "$(pwd)"
197
+ ```
198
+
199
+ ### Development / maintenance
200
+
201
+ If you are a maintainer building from source:
202
+
203
+ ```bash
204
+ git clone https://github.com/anyi61/codex-claude.git
205
+ cd codex-claude
206
+ npm install
207
+ npm run build:plugin
208
+ npm run check:plugin
209
+ ```
210
+
211
+ The plugin directory (`plugins/`) remains as internal packaging. For development, use `npm run dev` or `npm run build`.
212
+
213
+ ## Troubleshooting
214
+
215
+ | Problem | Fix |
216
+ |---------|-----|
217
+ | `claude` command not found | Install Claude Code CLI or set `CLAUDE_BIN` |
218
+ | cwd outside allowed roots | `codex-claude setup --write --allow-root "$(pwd)"` |
219
+ | Dangerous allow root | Use a specific repo path, not `/`, `/tmp`, `/etc`, or `$HOME` |
220
+ | `poll_too_soon=true` | Wait until `next_allowed_poll_at`, do not start a new task |
221
+ | `waiting=true` | Continue polling the same `job_id`, do not re-delegate |
222
+ | Stale job | Use claude_result to inspect; with Advanced tools, claude_job_cancel may help |
223
+ | Apply refused: dirty workspace | Commit/stash changes, or use `dirty_policy=committed` |
224
+ | Missing `confirmed_by_user` | Show the preview and get explicit user approval before applying |
225
+ | `preview=true` + `cleanup=true` | Split into preview and confirmed apply+cleanup |
226
+ | Leftover worktrees | `claude_cleanup(cwd="...", dry_run=true)` then `dry_run=false` |
227
+
228
+ ## Uninstall
229
+
230
+ ```bash
231
+ npm uninstall -g @anyi61/codex-claude-delegate-mcp
232
+ ```
233
+
234
+ To also remove the MCP server configuration from Codex, delete the `[mcp_servers.claude_delegate]` section from `~/.codex/config.toml` manually.
235
+
236
+ ## Security
237
+
238
+ - `spawn("claude", args[])` — no shell injection
239
+ - `--tools` / `--allowedTools` / `--disallowedTools` — three-layer tool control
240
+ - `--permission-mode dontAsk` — non-interactive safe mode
241
+ - `sanitizeEnv()` — minimal environment (strips API keys, tokens, SSH agent)
242
+ - `BRIDGE_DEPTH` — recursion protection (≥2 refused)
243
+ - `validateCwd()` — realpath + allow roots whitelist
244
+ - `dangerousRoot()` — rejects `/`, `/tmp`, `/etc`, `$HOME`
245
+
246
+ ## Known limitations
247
+
248
+ - No real-time bidirectional communication (Codex → Claude one-shot delegation)
249
+ - ~2-5s cold start per Claude invocation
250
+ - No automatic worktree cleanup (use `claude_cleanup`)
251
+ - Old job records lack fingerprint/heartbeat; stale classification falls back to updated_at
252
+ - Stale detection is advisory only, does not auto-kill processes
253
+
254
+ ## Maintainer release checklist
255
+
256
+ ```bash
257
+ npm run typecheck
258
+ npm test
259
+ npm run build:plugin
260
+ npm run check:plugin
261
+ npm pack --dry-run
262
+ ```
@@ -0,0 +1,84 @@
1
+ import type { BackgroundJobEnqueueResult, BackgroundJobSummary, BackgroundJobType, ClaudeApplyInput, ClaudeApplyResult, ClaudeCleanupInput, ClaudeCleanupResult, ClaudeImplementInput, ClaudeJobCancelInput, ClaudeJobCleanupInput, ClaudeJobCleanupResult, ClaudeJobResultInput, ClaudeResultInput, ClaudeResultResult, ClaudeJobWaitInput, ClaudeJobWaitResult, ClaudeJobsInput, ClaudeJobsResult, ClaudeQueryInput, ClaudeReviewInput, ClaudeResult, ClaudeRunInspectInput, ClaudeRunInspectResult, ClaudeRunsInput, ClaudeRunsResult, ClaudeStatusResult, ClaudeSetupInput, ClaudeSetupResult, ClaudeTaskInput, ClaudeTaskResult, ClaudeWorkspaceStatusInput, ClaudeWorkspaceStatusResult, RunLogEntrySummary, ToolEnvelope, ClaudeReviewGateInput, ClaudeReviewGateResult } from "./schema.js";
2
+ export declare function createTaskFingerprint(input: {
3
+ cwd: string;
4
+ type: BackgroundJobType;
5
+ payload: Record<string, unknown>;
6
+ }): string;
7
+ export declare function listRunLogs(input: ClaudeRunsInput): Promise<ClaudeRunsResult>;
8
+ export declare function getRecentRunsSummary(cwd: string, limit?: number): Promise<{
9
+ entries: RunLogEntrySummary[];
10
+ lifecycle_counts: Record<string, number>;
11
+ }>;
12
+ export declare function getRunLogById(input: ClaudeRunInspectInput): Promise<ClaudeRunInspectResult | null>;
13
+ export declare function getClaudeResult(input: ClaudeResultInput): Promise<ClaudeResultResult>;
14
+ export declare function getWorkspaceStatus(input: ClaudeWorkspaceStatusInput): Promise<ClaudeWorkspaceStatusResult>;
15
+ export declare function runClaudeSetup(input: ClaudeSetupInput): Promise<ClaudeSetupResult>;
16
+ export declare function manageClaudeReviewGate(input: ClaudeReviewGateInput): Promise<ClaudeReviewGateResult>;
17
+ export declare function runClaudeTask(input: ClaudeTaskInput, _runId: string): Promise<ClaudeTaskResult>;
18
+ export declare function enqueueBackgroundJob(input: {
19
+ cwd: string;
20
+ type: BackgroundJobType;
21
+ payload: Record<string, unknown>;
22
+ dedupe?: boolean;
23
+ }): Promise<BackgroundJobEnqueueResult>;
24
+ export declare function startBackgroundReview(input: ClaudeReviewInput): Promise<BackgroundJobEnqueueResult>;
25
+ export declare function startBackgroundQuery(input: ClaudeQueryInput): Promise<BackgroundJobEnqueueResult>;
26
+ export declare function startBackgroundImplement(input: ClaudeImplementInput): Promise<BackgroundJobEnqueueResult | ClaudeResult>;
27
+ export declare function startBackgroundApply(input: ClaudeApplyInput): Promise<BackgroundJobEnqueueResult>;
28
+ export declare function startBackgroundCleanup(input: ClaudeCleanupInput): Promise<BackgroundJobEnqueueResult>;
29
+ export declare function listBackgroundJobs(input: ClaudeJobsInput): Promise<ClaudeJobsResult>;
30
+ export declare function getBackgroundJobResult(input: ClaudeJobResultInput): Promise<{
31
+ job: BackgroundJobSummary;
32
+ result?: Record<string, unknown>;
33
+ } | null>;
34
+ export declare function waitForBackgroundJob(input: ClaudeJobWaitInput): Promise<ClaudeJobWaitResult>;
35
+ export declare function cancelBackgroundJob(input: ClaudeJobCancelInput): Promise<{
36
+ cancelled: boolean;
37
+ job?: BackgroundJobSummary;
38
+ error?: string;
39
+ }>;
40
+ export declare function cleanupBackgroundJobs(input: ClaudeJobCleanupInput): Promise<ClaudeJobCleanupResult>;
41
+ export declare function resolveLatestImplementSession(input: {
42
+ cwd: string;
43
+ }): Promise<{
44
+ run_id: string;
45
+ session_id: string;
46
+ } | null>;
47
+ export declare function parseStatusPorcelainZ(output: string): Array<{
48
+ status: string;
49
+ file: string;
50
+ }>;
51
+ export declare function parseNameStatusPorcelainZ(output: string): Array<{
52
+ status: string;
53
+ file: string;
54
+ }>;
55
+ export interface ClaudeRunOptions {
56
+ prompt: string;
57
+ cwd: string;
58
+ worktree?: string;
59
+ tools: string;
60
+ allowedTools: string[];
61
+ disallowedTools: string[];
62
+ maxTurns?: number;
63
+ timeoutSec: number;
64
+ jsonSchema: object;
65
+ maxBudgetUsd?: number;
66
+ resumeSessionId?: string;
67
+ forkSession?: boolean;
68
+ noSessionPersistence?: boolean;
69
+ }
70
+ export declare const DANGEROUS_DISALLOWED_TOOLS: string[];
71
+ export declare function truncateTail(input: string, maxChars?: number): string;
72
+ export declare function buildSafeEnv(): Record<string, string>;
73
+ export declare function abortActiveClaudeRun(signal?: NodeJS.Signals): boolean;
74
+ export declare function buildClaudeArgs(opts: ClaudeRunOptions): string[];
75
+ export declare function buildQueryArgs(input: ClaudeQueryInput): string[];
76
+ export declare function buildReviewArgs(input: ClaudeReviewInput): string[];
77
+ export declare function buildImplementArgs(input: ClaudeImplementInput): string[];
78
+ export declare function checkClaudeStatus(cwd: string): Promise<ClaudeStatusResult>;
79
+ export declare function runClaudeQuery(input: ClaudeQueryInput, runId: string): Promise<ToolEnvelope<Record<string, unknown>>>;
80
+ export declare function executeBackgroundJob(jobId: string): Promise<void>;
81
+ export declare function runClaudeReview(input: ClaudeReviewInput, runId: string): Promise<ToolEnvelope<Record<string, unknown>>>;
82
+ export declare function runClaudeImplement(input: ClaudeImplementInput, runId: string): Promise<ClaudeResult>;
83
+ export declare function runClaudeApply(input: ClaudeApplyInput, runId: string): Promise<ClaudeApplyResult>;
84
+ export declare function runClaudeCleanup(input: ClaudeCleanupInput, runId: string): Promise<ClaudeCleanupResult>;