skill-codex 0.2.0 → 0.7.1

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,7 +1,11 @@
1
1
  # skill-codex
2
2
 
3
- ![npm](https://img.shields.io/npm/v/skill-codex)
3
+ [![npm version](https://img.shields.io/npm/v/skill-codex)](https://www.npmjs.com/package/skill-codex)
4
+ [![npm downloads](https://img.shields.io/npm/dm/skill-codex)](https://www.npmjs.com/package/skill-codex)
4
5
  ![CI](https://github.com/Arystos/skill-codex/actions/workflows/ci.yml/badge.svg)
6
+ <!-- After enabling the repo on codecov.io (see DISTRIBUTION.md), uncomment:
7
+ [![codecov](https://codecov.io/gh/Arystos/skill-codex/graph/badge.svg)](https://codecov.io/gh/Arystos/skill-codex) -->
8
+ ![Coverage](https://img.shields.io/badge/coverage-80%25%2B%20enforced-brightgreen)
5
9
  ![Windows](https://img.shields.io/badge/Windows-0078D4?style=flat&logo=windows&logoColor=white)
6
10
  ![macOS](https://img.shields.io/badge/macOS-000000?style=flat&logo=apple&logoColor=white)
7
11
  ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat&logo=linux&logoColor=black)
@@ -11,6 +15,12 @@
11
15
 
12
16
  A cross-platform [Claude Code](https://code.claude.com) skill that integrates [OpenAI Codex CLI](https://github.com/openai/codex) for code review, task delegation, and consultation. Uses your existing Codex subscription -- no API key required.
13
17
 
18
+ > **Two models rarely make the same mistake.** skill-codex lets Claude and Codex check each other's work -- Claude plans and builds fast, Codex reviews with fresh eyes -- from a single terminal, using the Codex subscription you already pay for. No API key, no second window, no copy-paste.
19
+
20
+ <!-- Demo GIF: record a ~20s clip of `/codex-review` catching a real bug, save it to docs/demo.gif, then uncomment the next line:
21
+ ![skill-codex demo](docs/demo.gif)
22
+ -->
23
+
14
24
  ## Why?
15
25
 
16
26
  Claude Code and Codex CLI have different strengths. Claude excels at reasoning, architecture, and complex refactors. Codex is fast, thorough, and great at focused execution and review. **skill-codex** lets them work together from a single terminal -- no second window, no copy-paste, no context loss.
@@ -18,10 +28,30 @@ Claude Code and Codex CLI have different strengths. Claude excels at reasoning,
18
28
  * **`/codex-review`** -- Have Codex review your current changes as a second reviewer
19
29
  * **`/codex-do`** -- Delegate well-scoped implementation tasks to Codex
20
30
  * **`/codex-consult`** -- Get a second opinion on architecture or design decisions
31
+ * **`codex-bridge` agent skill** -- Auto-triggers on implementation/review/consult requests so Claude reaches for Codex without an explicit slash command
21
32
  * **Auto-review hook** -- Smart PostToolUse hook suggests review after significant changes
33
+ * **Live progress** -- Streams Codex's activity (running commands, file edits, elapsed time) as MCP progress so long runs never look frozen; also mirrored to a tail-able log file (under the OS temp dir, path printed at run start -- never pollutes your repo)
22
34
  * **Subscription-first** -- Works with `codex login`, no `OPENAI_API_KEY` needed
23
35
  * **Edge case handling** -- Retry logic, timeout, anti-recursion, lock files, pre-flight checks
24
36
 
37
+ ### Why not just use Claude's own subagents?
38
+
39
+ Because a subagent is the **same model**. When Claude reviews Claude, you inherit the same blind spots -- it's grading its own homework. A *different* model family was trained differently, so its mistakes don't correlate with Claude's: it catches what Claude is confidently wrong about, and Claude catches what Codex gets wrong. That uncorrelated, cross-model check is the entire point -- and skill-codex keeps Claude as the final judge, never blindly forwarding Codex's verdict.
40
+
41
+ ### How it compares
42
+
43
+ | | skill-codex | Most Codex MCP bridges |
44
+ |---|---|---|
45
+ | Codex **subscription** auth (no `OPENAI_API_KEY`) | ✅ | ⚠️ often require an API key |
46
+ | **Windows** verified in CI (not just "should work") | ✅ 9-way matrix (Windows/macOS/Linux × Node 18/20/22) | ❌ usually Linux-only CI |
47
+ | **Live progress** so long runs never look frozen | ✅ MCP progress + tail-able log | ⚠️ varies |
48
+ | **Slash commands** (`/codex-review`, `/codex-do`, `/codex-consult`) | ✅ | ⚠️ some |
49
+ | **Auto-review hook** (PostToolUse) | ✅ | ❌ |
50
+ | **Agent skill** (auto-triggers, no command needed) | ✅ | ❌ |
51
+ | **Guardrails**: retry, timeout, anti-recursion, lock files | ✅ | ⚠️ partial |
52
+
53
+ *A snapshot, not a leaderboard -- the Codex MCP space moves fast, so check each tool's current state. The point isn't "skill-codex wins everything"; it's that the operational details (subscription auth, real Windows support, never-frozen runs, guardrails) are where it focuses.*
54
+
25
55
  ## Prerequisites
26
56
 
27
57
  * [Node.js](https://nodejs.org) >= 18
@@ -31,12 +61,14 @@ Claude Code and Codex CLI have different strengths. Claude excels at reasoning,
31
61
  ## Quick Start
32
62
 
33
63
  ```shell
34
- # 1. Install and configure everything in one command
64
+ # Option A: Run directly (no global install)
35
65
  npx skill-codex setup
36
66
 
37
- # 2. Restart Claude Code to load the MCP server
67
+ # Option B: Install globally, then setup
68
+ npm i -g skill-codex
69
+ skill-codex setup
38
70
 
39
- # 3. Use the commands in any project
71
+ # Restart Claude Code to load the MCP server, then use:
40
72
  /codex-review # Review uncommitted changes
41
73
  /codex-do "write tests" # Delegate a task to Codex
42
74
  /codex-consult "approach?" # Get a second opinion
@@ -46,7 +78,8 @@ The setup command:
46
78
  1. Registers the MCP server in your Claude Code config (`~/.claude.json`)
47
79
  2. Installs slash commands globally (`~/.claude/commands/`)
48
80
  3. Configures the auto-review PostToolUse hook
49
- 4. Verifies everything works
81
+ 4. Installs the `codex-bridge` agent skill (`~/.claude/skills/`)
82
+ 5. Verifies everything works
50
83
 
51
84
  > **Tip:** Add `.skill-codex.lock` to your `.gitignore`
52
85
 
@@ -55,46 +88,59 @@ The setup command:
55
88
  ```
56
89
  You in Claude Code
57
90
  |
58
- |-- /codex-review --> MCP tool --> codex exec (read-only) --> review findings
59
- |-- /codex-do "task" --> MCP tool --> codex exec --full-auto --> reviewed output
60
- +-- /codex-consult "q" --> MCP tool --> codex exec (read-only) --> synthesized opinion
91
+ |-- /codex-review --> MCP tool --> codex exec --sandbox read-only --> review findings
92
+ |-- /codex-do "task" --> MCP tool --> codex exec --sandbox workspace-write --> reviewed output
93
+ +-- /codex-consult "q" --> MCP tool --> codex exec --sandbox read-only --> synthesized opinion
61
94
  ```
62
95
 
63
96
  The MCP server spawns `codex exec` as a subprocess, using your logged-in Codex session. Claude sees the output and critically evaluates it -- **Codex is treated as a peer, not an authority**.
64
97
 
98
+ ### Advanced: sandbox, sessions, model & review
99
+
100
+ These `codex_exec` parameters are all optional -- omit them and Codex uses its defaults:
101
+
102
+ * **`sandbox`** -- the explicit Codex sandbox policy (`read-only`, `workspace-write`, or `danger-full-access`), overriding the `mode` default. Use `danger-full-access` only when you understand the risk.
103
+ * **`sessionId`** -- resume a previous Codex session for multi-round memory. Each response includes the session's thread id; pass it back so Codex retains context -- e.g. a follow-up review that checks whether *previously flagged* issues were fixed, instead of re-discovering them.
104
+ * **`model`** -- pick the Codex model (e.g. `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`). Route cheap tasks to a smaller model and escalate hard ones; omit to use your configured default.
105
+ * **`reasoningEffort`** -- how hard Codex thinks: `minimal` | `low` | `medium` | `high` | `xhigh`. Omit for the model's default.
106
+ * **`review`** -- run Codex's native diff-scoped reviewer (`codex exec review`) instead of a freeform prompt, optionally targeting a branch (`reviewBase`) or commit (`reviewCommit`). The prompt becomes optional focus instructions.
107
+
65
108
  ### Auto-review
66
109
 
67
110
  After significant code changes (3+ files, 100+ lines, security-related paths), the PostToolUse hook suggests running `/codex-review`. Trivial changes (docs-only, < 5 lines, whitespace) are skipped to preserve your Codex quota.
68
111
 
69
- ### Example: `/codex-review`
112
+ ### Agent skill (auto-trigger)
70
113
 
71
- ```
72
- > /codex-review
114
+ The slash commands are explicit, on-demand entry points. The `codex-bridge` agent skill is the implicit one: it installs to `~/.claude/skills/` and Claude loads it automatically when your request matches a delegation, review, or consult pattern (e.g. "implement X", "generate tests for", "review this diff", "second opinion on this approach"). It maps the same three workflows -- delegate, review, consult -- onto the `codex_exec` tool, so you get Codex collaboration without remembering a command. Trivial tasks (< 50 lines, faster done directly) are explicitly out of scope.
115
+
116
+ ### Example Output
73
117
 
74
- Reviewing uncommitted changes (3 files, ~85 lines)...
118
+ When Codex runs, the MCP tool returns a structured plain-text response:
75
119
 
76
- Codex found 2 issues:
120
+ ```
121
+ [read-only │ D:\myproject │ 21538 tok in (15744 cached) → 129 out]
122
+ ✔ exec: powershell -Command 'git diff --cached' (ok)
77
123
 
78
124
  CRITICAL — src/auth/login.ts:42
79
125
  Password comparison uses == instead of timing-safe comparison.
80
- Claude's assessment: Agree. Use crypto.timingSafeEqual() instead.
81
126
 
82
127
  MEDIUM — src/api/routes.ts:18
83
128
  Missing rate limiting on login endpoint.
84
- Claude's assessment: Agree. Add rate limiter middleware.
85
-
86
- Shall I fix these issues?
87
129
  ```
88
130
 
131
+ The first line shows mode, working directory, and token usage. Activity lines show commands Codex executed (with status icons: ✔ ok, ✘ blocked/failed). The response content follows after a blank line.
132
+
89
133
  ## Configuration
90
134
 
91
135
  Environment variables (all optional):
92
136
 
93
137
  | Variable | Default | Description |
94
138
  |----------|---------|-------------|
95
- | `SKILL_CODEX_TIMEOUT_MS` | `600000` (10 min) | Subprocess timeout |
139
+ | `SKILL_CODEX_TIMEOUT_MS` | `300000` (5 min) | Subprocess timeout |
96
140
  | `SKILL_CODEX_MAX_RETRIES` | `3` | Retry count for transient errors |
141
+ | `SKILL_CODEX_LOG` | `<os-temp>/skill-codex/<workspace>.log` | Absolute path override for the live, tail-able per-run log |
97
142
  | `SKILL_CODEX_DEBUG` | -- | Enable debug logging to stderr |
143
+ | `SKILL_CODEX_WINDOWS_SANDBOX` | `unelevated` | Windows only — Codex `windows.sandbox` mode (`unelevated`/`elevated`) |
98
144
 
99
145
  ### Smart Filter Thresholds
100
146
 
@@ -115,7 +161,7 @@ Environment variables (all optional):
115
161
  | Auth expired | Advises `codex login`, no retry |
116
162
  | Network down | Retries 3x with exponential backoff |
117
163
  | Rate limited (429) | Retries with backoff + jitter |
118
- | Codex hangs | Killed after timeout (SIGTERM then SIGKILL) |
164
+ | Codex hangs | Killed after timeout (SIGTERM+SIGKILL on Unix, immediate kill on Windows) |
119
165
  | Concurrent runs | Lock file prevents conflicts (stale after 15min) |
120
166
  | Recursive calls | `SKILL_CODEX_DEPTH` limit prevents infinite loops |
121
167
  | Trivial changes | Smart filter skips auto-review |
@@ -143,6 +189,8 @@ skill-codex/
143
189
  |-- hooks/
144
190
  | |-- post-tool-use-review.sh # Auto-review hook (macOS/Linux)
145
191
  | +-- post-tool-use-review.ps1 # Auto-review hook (Windows)
192
+ |-- skills/
193
+ | +-- codex-bridge/SKILL.md # Agent skill (auto-triggers delegation/review/consult)
146
194
  |-- setup/ # npx skill-codex setup installer
147
195
  |-- bin/ # CLI entry point
148
196
  +-- __tests__/ # vitest test suite
@@ -162,6 +210,7 @@ cd skill-codex
162
210
  npm install
163
211
  npm run build
164
212
  npm test
213
+ npm run test:coverage # enforces the same 80%+ gate as CI
165
214
  ```
166
215
 
167
216
  ## Troubleshooting
@@ -176,11 +225,14 @@ Restart Claude Code after running setup. The MCP server only loads on startup.
176
225
  Increase the timeout: `export SKILL_CODEX_TIMEOUT_MS=1200000` (20 min). Large codebases can take longer.
177
226
 
178
227
  **"Auth expired" but Codex works in another terminal**
179
- The MCP server runs in its own process. Run `codex login` and restart Claude Code.
228
+ The MCP server runs in its own process. Run `codex login` and restart Claude Code. On Windows, the auth pre-check is skipped automatically (PowerShell profile errors can cause false negatives); auth is still verified when Codex actually runs.
180
229
 
181
230
  **Lock file blocking runs**
182
231
  If a previous run crashed, a stale `.skill-codex.lock` may remain. It auto-cleans after 15 minutes, or delete it manually.
183
232
 
233
+ **Windows: "windows sandbox failed: spawn setup refresh" / Codex commands all blocked**
234
+ Codex's default *elevated* Windows sandbox fails to spawn shells on many setups ([openai/codex#24098](https://github.com/openai/codex/issues/24098), [#24259](https://github.com/openai/codex/issues/24259)). skill-codex works around this by pinning `windows.sandbox=unelevated`, which spawns reliably. If your machine needs the elevated sandbox instead, set `SKILL_CODEX_WINDOWS_SANDBOX=elevated`.
235
+
184
236
  ## Inspired By
185
237
 
186
238
  * [Dunqing/claude-codex-bridge](https://github.com/Dunqing/claude-codex-bridge) -- retry logic, anti-recursion, output parsing
@@ -10,7 +10,7 @@ You are delegating an implementation task to Codex. Follow these steps:
10
10
 
11
11
  2. **Evaluate if the task is suitable for delegation**:
12
12
  - **Good for Codex**: repetitive bulk changes, boilerplate generation, test writing for existing code, migration scripts, file format conversions, well-defined single-file edits
13
- - **Keep for yourself**: architectural decisions, cross-module refactoring, tasks requiring deep conversation context, ambiguous requirements, tasks under 50 lines
13
+ - **Keep for yourself**: architectural decisions, cross-module refactoring, tasks requiring deep conversation context, ambiguous requirements, and trivial edits you'd finish faster yourself than you can write a spec for
14
14
  - If the task is poorly scoped, explain why and suggest how to break it down.
15
15
 
16
16
  3. **Prepare a precise, self-contained prompt** for Codex. Include:
@@ -25,7 +25,8 @@ You are delegating an implementation task to Codex. Follow these steps:
25
25
  - `requireGit`: true
26
26
 
27
27
  5. **Review Codex's output critically**:
28
- - Run `git diff` to see exactly what Codex changed
28
+ - Run `git status --short` **first** to see ALL changes, including **newly-created files** (lines starting with `??`). Codex in full-auto mode often creates new files, and `git diff` alone is blind to untracked files.
29
+ - Run `git diff` for modifications to tracked files, and **read any new untracked files directly** to review their contents.
29
30
  - Check for introduced bugs, regressions, or style violations
30
31
  - Verify it matches the requested changes
31
32
  - Verify it doesn't modify files outside the requested scope
@@ -39,6 +40,6 @@ You are delegating an implementation task to Codex. Follow these steps:
39
40
  ## Important
40
41
 
41
42
  - Codex runs in **full-auto mode** — it CAN modify files in the workspace
42
- - Always `git diff` after Codex runs to verify what changed
43
+ - Always run `git status --short` **and** `git diff` after Codex runs `git status` catches new files that `git diff` misses
43
44
  - Codex is a **peer, not an authority** — review all output before accepting
44
45
  - For complex multi-file tasks, consider doing it yourself instead
@@ -7,7 +7,7 @@ Review the current changes using Codex as a second reviewer.
7
7
  You are invoking Codex for a second-opinion code review. Follow these steps:
8
8
 
9
9
  1. **Determine what to review** based on `$ARGUMENTS`:
10
- - If empty or "uncommitted": get unstaged changes via `git diff`. If empty, try staged changes via `git diff --cached`. If both empty, inform the user there are no changes to review.
10
+ - If empty or "uncommitted": first run `git status --short` to see ALL changes, including **new untracked files** (lines starting with `??`). Collect tracked modifications via `git diff` and staged changes via `git diff --cached`, **and** include the full contents of any new untracked files — read them directly, or use `git diff --no-index -- /dev/null <file>`. Plain `git diff` is blind to untracked files, so a review that skips this step will miss brand-new files entirely. If there are no changes at all, inform the user and stop.
11
11
  - If it looks like a branch name: get changes via `git diff <branch>...HEAD`
12
12
  - If it looks like a commit SHA: get changes via `git show <sha>`
13
13
 
@@ -20,16 +20,27 @@ You are invoking Codex for a second-opinion code review. Follow these steps:
20
20
  - `mode`: "exec"
21
21
  - `requireGit`: true
22
22
 
23
- 4. **Present findings** to the user:
23
+ **Option B (native Codex review):** Default to the Claude-assembled diff above, since the user prefers Claude-led review. You may instead call `codex_exec` with `review: true` to use `codex exec review`; add `reviewBase` for a branch or `reviewCommit` for a SHA. The prompt is optional focus instructions.
24
+
25
+ 4. **Assign an overall verdict** from the findings (you are the final judge — weigh Codex's findings, don't just echo them):
26
+ - **BLOCKED** — one or more CRITICAL/HIGH issues that should be fixed before merge
27
+ - **WARNING** — only MEDIUM/LOW issues; safe to proceed with awareness
28
+ - **APPROVED** — no substantive issues
29
+ State it explicitly, e.g. `Verdict: BLOCKED — 2 CRITICAL, 1 MEDIUM`.
30
+
31
+ 5. **Present findings** to the user:
24
32
  - Group by severity (CRITICAL first)
25
- - For each finding, add your own assessment: agree, disagree, or nuance
33
+ - For each finding, add your own assessment: agree, disagree (with reasoning), or add nuance
26
34
  - Note anything Codex missed that you think is important
27
35
  - Summarize actionable items at the end
28
36
 
29
- 5. **If Codex found issues**, offer to fix them.
37
+ 6. **If BLOCKED or WARNING, offer a bounded fix loop** (only with the user's go-ahead for automated fixing):
38
+ - Fix the issues you agree are genuine. If you disagree with a finding, explain why instead of "fixing" it just to satisfy Codex.
39
+ - Re-run the review (call `codex_exec` again on the updated diff) so Codex confirms the fixes and checks for regressions.
40
+ - Repeat until the verdict is APPROVED or you have done **3 rounds**, then stop and summarize what remains. The hard cap keeps the loop from quietly burning your Codex quota.
30
41
 
31
42
  ## Important
32
43
 
33
44
  - Codex runs in **read-only mode** — it cannot modify files
34
- - Codex is a **peer, not an authority** — evaluate each finding critically
35
- - If the MCP tool returns an error, explain what happened and suggest remediation
45
+ - Codex is a **peer, not an authority** — evaluate each finding critically and keep the final call yourself
46
+ - **Fail soft:** if `codex_exec` errors (Codex not installed, auth expired, offline), say so and fall back to your own review — a missing Codex should degrade to Claude-only review, never block the user
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // bin/skill-codex.ts
4
- import fs7 from "fs";
5
- import path8 from "path";
4
+ import fs8 from "fs";
5
+ import path10 from "path";
6
6
  import { fileURLToPath } from "url";
7
7
 
8
8
  // setup/setup.ts
9
- import fs6 from "fs";
10
- import path7 from "path";
9
+ import fs7 from "fs";
10
+ import path9 from "path";
11
11
 
12
12
  // setup/install-mcp.ts
13
13
  import fs2 from "fs";
@@ -44,6 +44,9 @@ function getGlobalMcpConfigPath() {
44
44
  function getGlobalCommandsDir() {
45
45
  return path2.join(getClaudeDir(), "commands");
46
46
  }
47
+ function getGlobalSkillsDir() {
48
+ return path2.join(getClaudeDir(), "skills");
49
+ }
47
50
 
48
51
  // src/config/package-root.ts
49
52
  import fs from "fs";
@@ -243,8 +246,79 @@ function installHook() {
243
246
  };
244
247
  }
245
248
 
246
- // setup/verify.ts
249
+ // setup/install-skill.ts
247
250
  import fs5 from "fs";
251
+ import path7 from "path";
252
+ var SKILL_NAME = "codex-bridge";
253
+ function getSkillSourceDir() {
254
+ return path7.join(getPackageRoot(), "skills", SKILL_NAME);
255
+ }
256
+ function copyDirRecursive(source, target) {
257
+ const copied = [];
258
+ if (!fs5.existsSync(target)) {
259
+ fs5.mkdirSync(target, { recursive: true });
260
+ }
261
+ const entries = fs5.readdirSync(source, { withFileTypes: true });
262
+ for (const entry of entries) {
263
+ const sourcePath = path7.join(source, entry.name);
264
+ const targetPath = path7.join(target, entry.name);
265
+ if (entry.isDirectory()) {
266
+ copied.push(...copyDirRecursive(sourcePath, targetPath));
267
+ } else if (entry.isFile()) {
268
+ const sourceContent = fs5.readFileSync(sourcePath);
269
+ let shouldWrite = true;
270
+ if (fs5.existsSync(targetPath)) {
271
+ const existing = fs5.readFileSync(targetPath);
272
+ shouldWrite = !existing.equals(sourceContent);
273
+ }
274
+ if (shouldWrite) {
275
+ fs5.writeFileSync(targetPath, sourceContent);
276
+ copied.push(entry.name);
277
+ }
278
+ }
279
+ }
280
+ return copied;
281
+ }
282
+ function installSkill() {
283
+ const sourceDir = getSkillSourceDir();
284
+ const targetDir = path7.join(getGlobalSkillsDir(), SKILL_NAME);
285
+ if (!fs5.existsSync(sourceDir)) {
286
+ return {
287
+ installed: false,
288
+ targetDir,
289
+ copiedFiles: [],
290
+ message: `Skill source not found at ${sourceDir}`
291
+ };
292
+ }
293
+ const skillFile = path7.join(sourceDir, "SKILL.md");
294
+ if (!fs5.existsSync(skillFile)) {
295
+ return {
296
+ installed: false,
297
+ targetDir,
298
+ copiedFiles: [],
299
+ message: `SKILL.md missing in ${sourceDir}`
300
+ };
301
+ }
302
+ const copied = copyDirRecursive(sourceDir, targetDir);
303
+ return {
304
+ installed: true,
305
+ targetDir,
306
+ copiedFiles: copied,
307
+ message: copied.length > 0 ? `Installed skill '${SKILL_NAME}' to ${targetDir} (${copied.length} file(s))` : `Skill '${SKILL_NAME}' already up to date`
308
+ };
309
+ }
310
+ function uninstallSkill() {
311
+ const targetDir = path7.join(getGlobalSkillsDir(), SKILL_NAME);
312
+ if (!fs5.existsSync(targetDir)) {
313
+ return { removed: false, targetDir };
314
+ }
315
+ fs5.rmSync(targetDir, { recursive: true, force: true });
316
+ return { removed: true, targetDir };
317
+ }
318
+
319
+ // setup/verify.ts
320
+ import fs6 from "fs";
321
+ import path8 from "path";
248
322
  import which from "which";
249
323
  async function runVerification() {
250
324
  const results = [];
@@ -264,9 +338,9 @@ async function runVerification() {
264
338
  }
265
339
  const mcpPath = getGlobalMcpConfigPath();
266
340
  let mcpRegistered = false;
267
- if (fs5.existsSync(mcpPath)) {
341
+ if (fs6.existsSync(mcpPath)) {
268
342
  try {
269
- const raw = fs5.readFileSync(mcpPath, "utf-8");
343
+ const raw = fs6.readFileSync(mcpPath, "utf-8");
270
344
  const config = JSON.parse(raw);
271
345
  mcpRegistered = "skill-codex" in (config.mcpServers ?? {});
272
346
  } catch {
@@ -280,13 +354,20 @@ async function runVerification() {
280
354
  const commandsDir = getGlobalCommandsDir();
281
355
  const expectedCommands = ["codex-review.md", "codex-do.md", "codex-consult.md"];
282
356
  const missingCommands = expectedCommands.filter(
283
- (cmd) => !fs5.existsSync(`${commandsDir}/${cmd}`)
357
+ (cmd) => !fs6.existsSync(`${commandsDir}/${cmd}`)
284
358
  );
285
359
  results.push({
286
360
  name: "Slash commands installed",
287
361
  pass: missingCommands.length === 0,
288
362
  detail: missingCommands.length === 0 ? `All 3 commands in ${commandsDir}` : `Missing: ${missingCommands.join(", ")}`
289
363
  });
364
+ const skillFile = path8.join(getGlobalSkillsDir(), "codex-bridge", "SKILL.md");
365
+ const skillInstalled = fs6.existsSync(skillFile);
366
+ results.push({
367
+ name: "Agent skill installed",
368
+ pass: skillInstalled,
369
+ detail: skillInstalled ? skillFile : `Not found at ${skillFile}`
370
+ });
290
371
  return {
291
372
  results,
292
373
  allPassed: results.every((r) => r.pass)
@@ -309,6 +390,9 @@ async function runSetup(options = {}) {
309
390
  log(" ", "Registering auto-review hook...");
310
391
  const hookResult = installHook();
311
392
  log(hookResult.installed ? "[ok]" : "[--]", hookResult.message);
393
+ log(" ", "Installing agent skill...");
394
+ const skillResult = installSkill();
395
+ log(skillResult.installed ? "[ok]" : "[--]", skillResult.message);
312
396
  log("\n ", "Verifying installation...\n");
313
397
  const verification = await runVerification();
314
398
  for (const check of verification.results) {
@@ -323,6 +407,8 @@ async function runSetup(options = {}) {
323
407
  log(" ", " /codex-do - Delegate a task to Codex");
324
408
  log(" ", " /codex-consult - Get a second opinion from Codex");
325
409
  log("", "");
410
+ log(" ", "Agent skill installed: codex-bridge (auto-triggers on implementation/review requests)");
411
+ log("", "");
326
412
  log(" ", "Tip: Add .skill-codex.lock to your .gitignore");
327
413
  } else {
328
414
  log("[!!]", "Setup completed with warnings. Fix the issues above and run: npx skill-codex verify\n");
@@ -333,12 +419,12 @@ async function runUninstall() {
333
419
  log(">>", "skill-codex uninstall\n");
334
420
  const mcpConfigPath = getGlobalMcpConfigPath();
335
421
  try {
336
- const raw = fs6.readFileSync(mcpConfigPath, "utf-8");
422
+ const raw = fs7.readFileSync(mcpConfigPath, "utf-8");
337
423
  const config = JSON.parse(raw);
338
424
  const mcpServers = config.mcpServers;
339
425
  if (mcpServers && "skill-codex" in mcpServers) {
340
426
  delete mcpServers["skill-codex"];
341
- fs6.writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
427
+ fs7.writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
342
428
  log("[ok]", "Removed MCP server");
343
429
  } else {
344
430
  log("[--]", "MCP server not found");
@@ -349,17 +435,23 @@ async function runUninstall() {
349
435
  const commandsDir = getGlobalCommandsDir();
350
436
  const commandFiles = ["codex-review.md", "codex-do.md", "codex-consult.md"];
351
437
  for (const file of commandFiles) {
352
- const filePath = path7.join(commandsDir, file);
438
+ const filePath = path9.join(commandsDir, file);
353
439
  try {
354
- fs6.unlinkSync(filePath);
440
+ fs7.unlinkSync(filePath);
355
441
  log("[ok]", `Removed ${file}`);
356
442
  } catch {
357
443
  log("[--]", `${file} not found`);
358
444
  }
359
445
  }
446
+ const skillUninstall = uninstallSkill();
447
+ if (skillUninstall.removed) {
448
+ log("[ok]", `Removed skill: ${skillUninstall.targetDir}`);
449
+ } else {
450
+ log("[--]", "Agent skill not found");
451
+ }
360
452
  const settingsPath = getClaudeSettingsPath();
361
453
  try {
362
- const raw = fs6.readFileSync(settingsPath, "utf-8");
454
+ const raw = fs7.readFileSync(settingsPath, "utf-8");
363
455
  const settings = JSON.parse(raw);
364
456
  const hooks = settings.hooks;
365
457
  if (hooks) {
@@ -372,7 +464,7 @@ async function runUninstall() {
372
464
  if (hooks[eventType].length < before) removed = true;
373
465
  }
374
466
  if (removed) {
375
- fs6.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
467
+ fs7.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
376
468
  log("[ok]", "Removed PostToolUse hook");
377
469
  } else {
378
470
  log("[--]", "PostToolUse hook not found");
@@ -391,10 +483,10 @@ async function runUninstall() {
391
483
  var args = process.argv.slice(2);
392
484
  var command = args[0];
393
485
  function getVersion() {
394
- const __dirname = path8.dirname(fileURLToPath(import.meta.url));
395
- const pkgPath = path8.resolve(__dirname, "..", "package.json");
486
+ const __dirname = path10.dirname(fileURLToPath(import.meta.url));
487
+ const pkgPath = path10.resolve(__dirname, "..", "package.json");
396
488
  try {
397
- const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
489
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
398
490
  return pkg.version ?? "0.0.0";
399
491
  } catch {
400
492
  return "0.0.0";