codetrap 0.1.8 → 0.1.9
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 +29 -94
- package/docs/installation.md +13 -99
- package/package.json +1 -1
- package/plugins/codetrap-agent/.codex-plugin/plugin.json +1 -1
- package/plugins/codetrap-agent/templates/AGENTS.codetrap-maintainer.md +15 -0
- package/plugins/codetrap-agent/templates/AGENTS.codetrap.md +0 -15
- package/scripts/release-preflight.ts +15 -0
- package/src/commands/workflow.ts +29 -1
- package/src/index.ts +6 -1
- package/src/lib/codex-setup.ts +247 -0
package/README.md
CHANGED
|
@@ -64,50 +64,21 @@ npm install -g codetrap
|
|
|
64
64
|
|
|
65
65
|
# Initialize pitfall memory in the target project
|
|
66
66
|
cd /path/to/project
|
|
67
|
-
codetrap
|
|
67
|
+
codetrap setup codex
|
|
68
68
|
codetrap doctor
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
cat "$(npm root -g)/codetrap/plugins/codetrap-agent/templates/AGENTS.codetrap.md" >> AGENTS.md
|
|
75
|
-
# or:
|
|
76
|
-
cat "$(npm root -g)/codetrap/plugins/codetrap-agent/templates/AGENTS.codetrap.md" >> CLAUDE.md
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Then have the agent run this before non-trivial edits:
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
codetrap search "<task keywords>" --mode hybrid --json
|
|
83
|
-
```
|
|
71
|
+
`codetrap setup codex` installs the bundled Codex skills into `~/.codex/skills`, initializes `.codetrap/` when needed, and writes `AGENTS.md`. It does not configure MCP by default.
|
|
84
72
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
After a user correction, repeated test failure, or review finding, have the agent draft a candidate instead of writing confirmed memory:
|
|
73
|
+
To also configure Codex MCP, opt in explicitly:
|
|
88
74
|
|
|
89
75
|
```bash
|
|
90
|
-
|
|
91
|
-
Title: <durable pitfall>
|
|
92
|
-
Context: <when it triggers>
|
|
93
|
-
Mistake: <what the agent did wrong>
|
|
94
|
-
Fix: <what to do instead>
|
|
95
|
-
EOF
|
|
76
|
+
codetrap setup codex --mcp
|
|
96
77
|
```
|
|
97
78
|
|
|
98
|
-
|
|
79
|
+
The packaged template is the source of truth for exact agent behavior. It tells agents to run CLI JSON checks before non-trivial edits, inspect only relevant action cards, keep post-flight lessons in the session candidate inbox, and require explicit human approval before accepting a candidate into `traps.db`.
|
|
99
80
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
codetrap session candidate <candidate-id> --session <session-id> --json
|
|
104
|
-
|
|
105
|
-
# Only after explicit human approval:
|
|
106
|
-
codetrap session accept <candidate-id> --session <session-id>
|
|
107
|
-
|
|
108
|
-
# Or reject instead:
|
|
109
|
-
codetrap session reject <candidate-id> --session <session-id> --reason "<reason>"
|
|
110
|
-
```
|
|
81
|
+
For a quick manual check, agents can run `codetrap search "<task keywords>" --mode hybrid --json` from the project cwd.
|
|
111
82
|
|
|
112
83
|
## Features
|
|
113
84
|
|
|
@@ -227,6 +198,7 @@ codetrap/
|
|
|
227
198
|
| `import` | Import traps from JSON (--json) |
|
|
228
199
|
| `stats` | Show database statistics (--json includes embedding health) |
|
|
229
200
|
| `doctor` | Diagnose cwd, scope, database paths, trap counts, and embedding health (--json) |
|
|
201
|
+
| `setup codex` | Install Codex skills and project guidance; MCP is opt-in with `--mcp` |
|
|
230
202
|
| `repair-scope` | Move legacy mis-scoped project traps into the current project (dry-run by default, `--apply` to mutate, `--json`) |
|
|
231
203
|
| `migrate-project` | Move project traps between initialized projects (`--from-project-path`, `--to-project-path`, dry-run by default, `--apply`, `--json`) |
|
|
232
204
|
| `embed` | Generate embeddings (requires configured Ollama or Jina provider) |
|
|
@@ -282,14 +254,28 @@ For AI coding agents, use the CLI as the default integration path:
|
|
|
282
254
|
|
|
283
255
|
CLI and project guidance are the main path. MCP should stay thin and share the same store/search behavior.
|
|
284
256
|
|
|
285
|
-
###
|
|
257
|
+
### Codex Setup
|
|
286
258
|
|
|
287
|
-
|
|
259
|
+
Default setup installs skills and project guidance without MCP:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
codetrap setup codex
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
MCP is optional. To configure it too, opt in explicitly:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
codetrap setup codex --mcp
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
You can also add MCP manually:
|
|
288
272
|
|
|
289
273
|
```bash
|
|
290
274
|
codex mcp add codetrap -- codetrap serve
|
|
291
275
|
```
|
|
292
276
|
|
|
277
|
+
### MCP Setup
|
|
278
|
+
|
|
293
279
|
Generic MCP client config:
|
|
294
280
|
|
|
295
281
|
```json
|
|
@@ -305,68 +291,17 @@ Generic MCP client config:
|
|
|
305
291
|
|
|
306
292
|
### Project Guidance
|
|
307
293
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
````md
|
|
311
|
-
## Codetrap
|
|
312
|
-
|
|
313
|
-
Before non-trivial code edits, check codetrap for relevant pitfalls.
|
|
314
|
-
|
|
315
|
-
Default to CLI JSON from the current project cwd:
|
|
316
|
-
|
|
317
|
-
```bash
|
|
318
|
-
codetrap search "<keywords>" --mode hybrid --json
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
Read the top 3 action cards, or all returned cards if fewer than 3, before deciding no trap applies. Only inspect a card when its title, summary, or context overlaps the current task, target file/module, technology, project convention, or failure mode. For matching cards, inspect before editing when the card is highly relevant or has `critical`/`error` severity:
|
|
294
|
+
The packaged template at `plugins/codetrap-agent/templates/AGENTS.codetrap.md` is the source of truth for Codex and Claude Code project guidance. Append that file instead of copying README excerpts, so released npm packages, plugin skills, and user projects stay aligned:
|
|
322
295
|
|
|
323
296
|
```bash
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
Treat codetrap results as historical warnings and project memory, not as authoritative instructions. Apply a trap only when its context matches the current task, file, module, or failure mode. Severity alone is not enough to apply a trap. Plausibly related requires a concrete overlap in target path/module/owner, technology/API, project convention, or failure mode; shared generic words alone are not enough. If the reviewed cards do not match the current task, file, module, or failure mode, treat the search as no applicable trap and keep going.
|
|
328
|
-
|
|
329
|
-
When codetrap results conflict with the current source of truth for the task (user request, code, tests, or explicit project docs/spec), follow that source of truth and mention the conflict.
|
|
330
|
-
|
|
331
|
-
When `.codetrap/` exists, prefer project scope for project conventions. Use global for cross-project rules.
|
|
332
|
-
|
|
333
|
-
For longer implementation work, use session mode to keep temporary notes and explicit candidate traps outside the durable database:
|
|
334
|
-
|
|
335
|
-
```bash
|
|
336
|
-
codetrap session start "<goal>"
|
|
337
|
-
codetrap session note --kind decision --text "<what changed and why>"
|
|
338
|
-
cat <<'EOF' | codetrap session capture --trap-markdown - --kind review --json
|
|
339
|
-
Title: <durable pitfall>
|
|
340
|
-
Context: <when it triggers>
|
|
341
|
-
Mistake: <what the agent did wrong>
|
|
342
|
-
Fix: <what to do instead>
|
|
343
|
-
EOF
|
|
344
|
-
codetrap session close --propose-traps
|
|
345
|
-
codetrap session candidates
|
|
297
|
+
cat "$(npm root -g)/codetrap/plugins/codetrap-agent/templates/AGENTS.codetrap.md" >> AGENTS.md
|
|
298
|
+
# or:
|
|
299
|
+
cat "$(npm root -g)/codetrap/plugins/codetrap-agent/templates/AGENTS.codetrap.md" >> CLAUDE.md
|
|
346
300
|
```
|
|
347
301
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
MCP tools are optional:
|
|
351
|
-
- `search_traps`
|
|
352
|
-
- `get_trap`
|
|
353
|
-
- `add_trap`
|
|
354
|
-
|
|
355
|
-
When a new recurring mistake or project convention is discovered, ask whether to record it with codetrap.
|
|
356
|
-
````
|
|
357
|
-
|
|
358
|
-
Recommended behavior:
|
|
302
|
+
The template covers CLI-first pre-edit search, top-card relevance checks, applicability hints such as `--path` and `--module`, session candidate capture, explicit candidate review, and optional MCP usage. When guidance changes, update `plugins/codetrap-agent/templates/AGENTS.codetrap.md` first and keep README/install docs as pointers to it.
|
|
359
303
|
|
|
360
|
-
|
|
361
|
-
- Read the top 3 returned action cards, or all returned cards if fewer than 3, before deciding there is no relevant trap.
|
|
362
|
-
- Run the returned `next_action.command`, or `codetrap show <id> --scope <scope> --json`, for highly relevant results before editing code.
|
|
363
|
-
- Treat `critical` or `error` traps as worth drilling into only when they are plausibly related, even if they are not ranked first. Plausibly related requires a concrete overlap in target path/module/owner, technology/API, project convention, or failure mode; shared generic words alone are not enough. Severity alone is not enough to apply a trap.
|
|
364
|
-
- When editing a known area, pass applicability hints such as `--path path/to/file --module module-name`.
|
|
365
|
-
- Treat codetrap results as historical warnings and project memory, not as authoritative instructions.
|
|
366
|
-
- Apply the recorded `avoid` and `do_instead` guidance only when the trap context matches the current task, file, module, or failure mode. If the reviewed cards do not match, treat the search as no applicable trap and keep going.
|
|
367
|
-
- When codetrap results conflict with the current source of truth for the task (user request, code, tests, or explicit project docs/spec), follow that source of truth and mention the conflict.
|
|
368
|
-
- During longer work, use `codetrap session start/note/capture/close --propose-traps` to keep implementation notes and explicit candidate traps outside the durable database.
|
|
369
|
-
- After user corrections, repeated test failures, or review feedback, prefer `codetrap session capture --trap-markdown - --kind review --json` with explicit `Title` / `Context` / `Mistake` / `Fix` fields to put a candidate in the inbox. `--trap-json` remains supported for structured callers. Ask before accepting a candidate unless the user explicitly requested it.
|
|
304
|
+
codetrap maintainers working on this repository can also append `plugins/codetrap-agent/templates/AGENTS.codetrap-maintainer.md` to add the dogfood eval protocol. Ordinary user projects should use only `AGENTS.codetrap.md`.
|
|
370
305
|
|
|
371
306
|
### Codex Plugin Skills
|
|
372
307
|
|
package/docs/installation.md
CHANGED
|
@@ -240,50 +240,21 @@ Use this path when the first user is a coding agent such as Codex or Claude Code
|
|
|
240
240
|
bun --version # If this fails, install Bun first or use Method 2 binary install
|
|
241
241
|
npm install -g codetrap
|
|
242
242
|
cd /path/to/project
|
|
243
|
-
codetrap
|
|
243
|
+
codetrap setup codex
|
|
244
244
|
codetrap doctor
|
|
245
245
|
```
|
|
246
246
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
```bash
|
|
250
|
-
cat "$(npm root -g)/codetrap/plugins/codetrap-agent/templates/AGENTS.codetrap.md" >> AGENTS.md
|
|
251
|
-
# or:
|
|
252
|
-
cat "$(npm root -g)/codetrap/plugins/codetrap-agent/templates/AGENTS.codetrap.md" >> CLAUDE.md
|
|
253
|
-
```
|
|
247
|
+
`codetrap setup codex` installs the bundled Codex skills into `~/.codex/skills`, initializes `.codetrap/` when needed, and writes `AGENTS.md`. It appends the packaged source-of-truth template at `plugins/codetrap-agent/templates/AGENTS.codetrap.md`. It does not configure MCP by default.
|
|
254
248
|
|
|
255
|
-
|
|
249
|
+
To also configure Codex MCP, opt in explicitly:
|
|
256
250
|
|
|
257
251
|
```bash
|
|
258
|
-
codetrap
|
|
252
|
+
codetrap setup codex --mcp
|
|
259
253
|
```
|
|
260
254
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
After user corrections, repeated test failures, or review feedback, have the agent write a candidate into the review inbox:
|
|
264
|
-
|
|
265
|
-
```bash
|
|
266
|
-
cat <<'EOF' | codetrap session capture --trap-markdown - --kind review --json
|
|
267
|
-
Title: <durable pitfall>
|
|
268
|
-
Context: <when it triggers>
|
|
269
|
-
Mistake: <what the agent did wrong>
|
|
270
|
-
Fix: <what to do instead>
|
|
271
|
-
EOF
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Use `codetrap session status`, `codetrap session list`, `codetrap doctor`, or `codetrap web` to review pending candidates. Do not accept candidates automatically.
|
|
275
|
-
|
|
276
|
-
Use the returned `candidate_id` and `session_id` to inspect and resolve the candidate:
|
|
277
|
-
|
|
278
|
-
```bash
|
|
279
|
-
codetrap session candidate <candidate-id> --session <session-id> --json
|
|
280
|
-
|
|
281
|
-
# Only after explicit human approval:
|
|
282
|
-
codetrap session accept <candidate-id> --session <session-id>
|
|
255
|
+
The packaged template is the source of truth for exact agent behavior. It tells agents to run CLI JSON checks before non-trivial edits, inspect only relevant action cards, keep post-flight lessons in the session candidate inbox, and require explicit human approval before accepting a candidate into `traps.db`.
|
|
283
256
|
|
|
284
|
-
|
|
285
|
-
codetrap session reject <candidate-id> --session <session-id> --reason "<reason>"
|
|
286
|
-
```
|
|
257
|
+
For a quick manual check, agents can run `codetrap search "<task keywords>" --mode hybrid --json` from the project cwd.
|
|
287
258
|
|
|
288
259
|
## Optional: Local Ollama Embeddings
|
|
289
260
|
|
|
@@ -342,79 +313,22 @@ If no embedding provider is configured:
|
|
|
342
313
|
|
|
343
314
|
## Optional: Codex MCP
|
|
344
315
|
|
|
345
|
-
|
|
316
|
+
MCP is optional. `codetrap setup codex` does not configure MCP unless you pass `--mcp`:
|
|
346
317
|
|
|
347
318
|
```bash
|
|
348
|
-
|
|
319
|
+
codetrap setup codex --mcp
|
|
349
320
|
```
|
|
350
321
|
|
|
351
|
-
|
|
322
|
+
You can also add MCP manually if the `codetrap` command is on your `PATH`:
|
|
352
323
|
|
|
353
324
|
```bash
|
|
354
|
-
codex mcp add codetrap --
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
Agents can also use the CLI directly from `AGENTS.md`:
|
|
358
|
-
|
|
359
|
-
````md
|
|
360
|
-
Before non-trivial code edits, check codetrap from the current project cwd:
|
|
361
|
-
|
|
362
|
-
codetrap search "<keywords>" --mode hybrid --json
|
|
363
|
-
|
|
364
|
-
Review the top 3 action cards, or all returned cards if fewer than 3, before deciding no trap applies. Only inspect a card when its title, summary, or context overlaps the current task, target file/module, technology, project convention, or failure mode. For matching critical/error results, inspect before editing:
|
|
365
|
-
|
|
366
|
-
codetrap show <id> --scope <project|global> --json
|
|
367
|
-
|
|
368
|
-
Apply a trap only when its context matches the current task, file, module, or failure mode. Severity alone is not enough to apply a trap. Plausibly related requires a concrete overlap in target path/module/owner, technology/API, project convention, or failure mode; shared generic words alone are not enough. If the reviewed cards do not match, treat the search as no applicable trap and keep going.
|
|
369
|
-
|
|
370
|
-
When editing a known area, pass applicability hints:
|
|
371
|
-
|
|
372
|
-
codetrap search "<keywords>" --path path/to/file --module module-name --json
|
|
373
|
-
|
|
374
|
-
To capture a post-flight lesson from agent work:
|
|
375
|
-
|
|
376
|
-
```bash
|
|
377
|
-
cat <<'EOF' | codetrap session capture --trap-markdown - --kind review --json
|
|
378
|
-
Title: <durable pitfall>
|
|
379
|
-
Context: <when it triggers>
|
|
380
|
-
Mistake: <what the agent did wrong>
|
|
381
|
-
Fix: <what to do instead>
|
|
382
|
-
EOF
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
`--trap-json` remains available for callers that already have a structured object:
|
|
386
|
-
|
|
387
|
-
```bash
|
|
388
|
-
codetrap session capture --trap-json '{...}' --kind review --json
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
For longer implementation work, keep temporary notes and explicit candidate traps in session files first:
|
|
392
|
-
|
|
393
|
-
```bash
|
|
394
|
-
codetrap session start "<goal>"
|
|
395
|
-
codetrap session note --kind decision --text "<what changed and why>"
|
|
396
|
-
cat <<'EOF' | codetrap session capture --trap-markdown - --kind review --json
|
|
397
|
-
Title: <durable pitfall>
|
|
398
|
-
Context: <when it triggers>
|
|
399
|
-
Mistake: <what the agent did wrong>
|
|
400
|
-
Fix: <what to do instead>
|
|
401
|
-
EOF
|
|
402
|
-
codetrap session close --propose-traps
|
|
403
|
-
codetrap session candidates
|
|
325
|
+
codex mcp add codetrap -- codetrap serve
|
|
404
326
|
```
|
|
405
327
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
Only accepted candidates are written to `traps.db`:
|
|
328
|
+
If your MCP client does not inherit your shell `PATH`, use the absolute path:
|
|
409
329
|
|
|
410
330
|
```bash
|
|
411
|
-
|
|
412
|
-
codetrap session accept <candidate-id>
|
|
331
|
+
codex mcp add codetrap -- "$(bun pm bin -g)/codetrap" serve
|
|
413
332
|
```
|
|
414
333
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
To save a lesson from an external article or reference, let the agent read the source and attach the URL as evidence after the user confirms the trap:
|
|
418
|
-
|
|
419
|
-
codetrap add_trap_evidence <id> --scope global --source_type article --source_ref "https://example.com/post" --output-json
|
|
420
|
-
````
|
|
334
|
+
Agents can also use the CLI directly when the project guidance tells them when to call it. `codetrap setup codex` installs that guidance in `AGENTS.md`.
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## Codetrap Dogfood Eval
|
|
2
|
+
|
|
3
|
+
Use this add-on only for codetrap maintainers working on codetrap itself. For ordinary external projects, use `AGENTS.codetrap.md` without this dogfood section.
|
|
4
|
+
|
|
5
|
+
After each pre-edit codetrap search, record whether the search was:
|
|
6
|
+
- useful_hit
|
|
7
|
+
- miss
|
|
8
|
+
- noisy_hit
|
|
9
|
+
- no_relevant_trap
|
|
10
|
+
|
|
11
|
+
Record the observation in `dogfood-log.md` with the task, query, mode, top results, judgment, whether the result changed the next action, and the promotion lane.
|
|
12
|
+
|
|
13
|
+
When a real query should reliably find an existing trap, save it as a live eval case with query, mode, scope, and gold target.
|
|
14
|
+
|
|
15
|
+
Do not promote every observation. Only promote representative cases that protect search quality.
|
|
@@ -38,18 +38,3 @@ Use `--trap-json` only when the caller already has a structured object.
|
|
|
38
38
|
Review the candidate with `codetrap session candidate <candidate-id> --session <session-id> --json`, then accept, edit, reject, or supersede it explicitly.
|
|
39
39
|
|
|
40
40
|
Use `codetrap session status`, `codetrap session list`, `codetrap doctor`, or `codetrap web` to find pending candidates that still need review.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
## Codetrap Dogfood Eval
|
|
44
|
-
|
|
45
|
-
After each pre-edit codetrap search, record whether the search was:
|
|
46
|
-
- useful_hit
|
|
47
|
-
- miss
|
|
48
|
-
- noisy_hit
|
|
49
|
-
- no_relevant_trap
|
|
50
|
-
|
|
51
|
-
Record the observation in `dogfood-log.md` with the task, query, mode, top results, judgment, whether the result changed the next action, and the promotion lane.
|
|
52
|
-
|
|
53
|
-
When a real query should reliably find an existing trap, save it as a live eval case with query, mode, scope, and gold target.
|
|
54
|
-
|
|
55
|
-
Do not promote every observation. Only promote representative cases that protect search quality.
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
3
6
|
const tag = process.argv[2] ?? process.env.RELEASE_TAG;
|
|
4
7
|
const packageJson = await Bun.file("package.json").json() as { name?: string; version?: string };
|
|
5
8
|
const published = await packageVersionExists(packageJson.name, packageJson.version);
|
|
@@ -10,6 +13,18 @@ const commands: { name: string; cmd: string[]; optional?: boolean }[] = [
|
|
|
10
13
|
{ name: "build", cmd: ["bun", "run", "build"] },
|
|
11
14
|
{ name: "build release assets", cmd: ["bun", "run", "build:release"] },
|
|
12
15
|
{ name: "smoke test release binary", cmd: [hostBinaryPath(), "--help"] },
|
|
16
|
+
{
|
|
17
|
+
name: "smoke test release binary Codex setup",
|
|
18
|
+
cmd: [
|
|
19
|
+
hostBinaryPath(),
|
|
20
|
+
"setup",
|
|
21
|
+
"codex",
|
|
22
|
+
"--dry-run",
|
|
23
|
+
"--json",
|
|
24
|
+
"--codex-home",
|
|
25
|
+
join(tmpdir(), "codetrap-release-preflight-codex-home"),
|
|
26
|
+
],
|
|
27
|
+
},
|
|
13
28
|
{ name: "npm pack dry-run", cmd: ["npm", "pack", "--dry-run"] },
|
|
14
29
|
...(!published ? [{ name: "npm publish dry-run", cmd: ["npm", "publish", "--dry-run", "--access", "public"] }] : []),
|
|
15
30
|
];
|
package/src/commands/workflow.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
type EmbeddingsUseResult,
|
|
18
18
|
} from "../lib/embedding-management";
|
|
19
19
|
import { searchDefaultsFromConfig } from "../lib/config";
|
|
20
|
+
import { formatCodexSetupText, runCodexSetup } from "../lib/codex-setup";
|
|
20
21
|
import { SessionStore } from "../lib/session-store";
|
|
21
22
|
import { SessionOperations, type SessionConflictResult } from "../lib/session-operations";
|
|
22
23
|
import {
|
|
@@ -110,6 +111,8 @@ export async function executeCommand(strip: string[], store: TrapStore): Promise
|
|
|
110
111
|
return cmdStats(args, operations);
|
|
111
112
|
case "doctor":
|
|
112
113
|
return cmdDoctor(args, store, operations);
|
|
114
|
+
case "setup":
|
|
115
|
+
return cmdSetup(args);
|
|
113
116
|
case "repair-scope":
|
|
114
117
|
return cmdScopeMigration("repair-scope", args, operations);
|
|
115
118
|
case "migrate-project":
|
|
@@ -123,7 +126,7 @@ export async function executeCommand(strip: string[], store: TrapStore): Promise
|
|
|
123
126
|
default:
|
|
124
127
|
return errorResult([
|
|
125
128
|
`Unknown command: ${sub}`,
|
|
126
|
-
"Commands: init, add, search, list, show, edit, delete, add_trap_evidence, archive_trap, supersede_trap, export, import, stats, doctor, repair-scope, migrate-project, embed, embeddings, session",
|
|
129
|
+
"Commands: init, add, search, list, show, edit, delete, add_trap_evidence, archive_trap, supersede_trap, export, import, stats, doctor, setup, repair-scope, migrate-project, embed, embeddings, session",
|
|
127
130
|
].join("\n"));
|
|
128
131
|
}
|
|
129
132
|
}
|
|
@@ -370,6 +373,31 @@ async function cmdDoctor(args: string[], store: TrapStore, operations: TrapOpera
|
|
|
370
373
|
: textResult(formatDoctorText(report));
|
|
371
374
|
}
|
|
372
375
|
|
|
376
|
+
function cmdSetup(args: string[]): CommandResult {
|
|
377
|
+
const sub = args[0];
|
|
378
|
+
const rest = args.slice(1);
|
|
379
|
+
if (sub !== "codex") {
|
|
380
|
+
return errorResult("Usage: codetrap setup codex [--mcp] [--no-agents] [--agents-file AGENTS.md] [--codex-home <path>] [--dry-run] [--json]");
|
|
381
|
+
}
|
|
382
|
+
const { opts } = parseArgs(rest);
|
|
383
|
+
try {
|
|
384
|
+
const result = runCodexSetup({
|
|
385
|
+
cwd: process.cwd(),
|
|
386
|
+
codexHome: opts["codex-home"],
|
|
387
|
+
agentsFile: opts["agents-file"],
|
|
388
|
+
installMcp: opts.mcp !== undefined,
|
|
389
|
+
skipAgents: opts["no-agents"] !== undefined,
|
|
390
|
+
dryRun: opts["dry-run"] !== undefined,
|
|
391
|
+
});
|
|
392
|
+
if (opts.json !== undefined) return jsonResult(result, result.success ? 0 : 1);
|
|
393
|
+
return result.success
|
|
394
|
+
? textResult(formatCodexSetupText(result))
|
|
395
|
+
: errorResult(formatCodexSetupText(result));
|
|
396
|
+
} catch (error) {
|
|
397
|
+
return errorFrom(error);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
373
401
|
function cmdScopeMigration(
|
|
374
402
|
command: ScopeMigrationCommand,
|
|
375
403
|
args: string[],
|
package/src/index.ts
CHANGED
|
@@ -61,6 +61,7 @@ function showHelp(): void {
|
|
|
61
61
|
console.log(" import <file.json> Import traps from JSON");
|
|
62
62
|
console.log(" stats Show statistics");
|
|
63
63
|
console.log(" doctor Diagnose scope, database, and embedding health");
|
|
64
|
+
console.log(" setup codex Install Codex skills and project guidance (MCP opt-in)");
|
|
64
65
|
console.log(" repair-scope Move mis-scoped project traps into the current project");
|
|
65
66
|
console.log(" migrate-project Move project traps between initialized projects");
|
|
66
67
|
console.log(" serve Start MCP server (for Claude Code)");
|
|
@@ -84,7 +85,11 @@ function showHelp(): void {
|
|
|
84
85
|
console.log(" --output-json JSON output for add/edit when --json is used as input");
|
|
85
86
|
console.log(" --from-project-path <path> Source project path for scope repair/migration");
|
|
86
87
|
console.log(" --to-project-path <path> Destination project path for scope repair/migration");
|
|
87
|
-
console.log(" --dry-run|--apply Preview or apply scope
|
|
88
|
+
console.log(" --dry-run|--apply Preview setup/scope migration, or apply scope migration");
|
|
89
|
+
console.log(" --mcp With setup codex, also run: codex mcp add codetrap -- codetrap serve");
|
|
90
|
+
console.log(" --codex-home <path> With setup codex, override CODEX_HOME/default ~/.codex");
|
|
91
|
+
console.log(" --agents-file <path> With setup codex, choose AGENTS.md target");
|
|
92
|
+
console.log(" --no-agents With setup codex, install skills without editing AGENTS.md");
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
function showWebHelp(): void {
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendFileSync,
|
|
3
|
+
cpSync,
|
|
4
|
+
existsSync,
|
|
5
|
+
mkdirSync,
|
|
6
|
+
readdirSync,
|
|
7
|
+
readFileSync,
|
|
8
|
+
writeFileSync,
|
|
9
|
+
} from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
import { dirname, join, resolve } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { findProjectRoot } from "./scope";
|
|
14
|
+
import agentsTemplateAsset from "../../plugins/codetrap-agent/templates/AGENTS.codetrap.md" with { type: "text" };
|
|
15
|
+
import codetrapAddSkill from "../../plugins/codetrap-agent/skills/codetrap-add/SKILL.md" with { type: "text" };
|
|
16
|
+
import codetrapCaptureSkill from "../../plugins/codetrap-agent/skills/codetrap-capture/SKILL.md" with { type: "text" };
|
|
17
|
+
import codetrapCaptureExternalSkill from "../../plugins/codetrap-agent/skills/codetrap-capture-external/SKILL.md" with { type: "text" };
|
|
18
|
+
import codetrapCheckSkill from "../../plugins/codetrap-agent/skills/codetrap-check/SKILL.md" with { type: "text" };
|
|
19
|
+
import codetrapSearchSkill from "../../plugins/codetrap-agent/skills/codetrap-search/SKILL.md" with { type: "text" };
|
|
20
|
+
|
|
21
|
+
export type CodexSetupOptions = {
|
|
22
|
+
cwd: string;
|
|
23
|
+
codexHome?: string;
|
|
24
|
+
agentsFile?: string;
|
|
25
|
+
installMcp?: boolean;
|
|
26
|
+
skipAgents?: boolean;
|
|
27
|
+
dryRun?: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type CodexSetupStatus =
|
|
31
|
+
| "already_present"
|
|
32
|
+
| "created"
|
|
33
|
+
| "appended"
|
|
34
|
+
| "installed"
|
|
35
|
+
| "updated"
|
|
36
|
+
| "unchanged"
|
|
37
|
+
| "skipped"
|
|
38
|
+
| "would_create"
|
|
39
|
+
| "would_append"
|
|
40
|
+
| "would_install"
|
|
41
|
+
| "would_update"
|
|
42
|
+
| "would_run"
|
|
43
|
+
| "failed";
|
|
44
|
+
|
|
45
|
+
export type CodexSetupResult = {
|
|
46
|
+
success: boolean;
|
|
47
|
+
project_root: string;
|
|
48
|
+
codex_home: string;
|
|
49
|
+
plugin_root: string;
|
|
50
|
+
dry_run: boolean;
|
|
51
|
+
project: {
|
|
52
|
+
codetrap_dir: string;
|
|
53
|
+
status: CodexSetupStatus;
|
|
54
|
+
};
|
|
55
|
+
skills: Array<{
|
|
56
|
+
name: string;
|
|
57
|
+
source: string;
|
|
58
|
+
destination: string;
|
|
59
|
+
status: CodexSetupStatus;
|
|
60
|
+
}>;
|
|
61
|
+
agents: {
|
|
62
|
+
path: string | null;
|
|
63
|
+
status: CodexSetupStatus;
|
|
64
|
+
};
|
|
65
|
+
mcp: {
|
|
66
|
+
requested: boolean;
|
|
67
|
+
command: string;
|
|
68
|
+
status: CodexSetupStatus;
|
|
69
|
+
exit_code?: number | null;
|
|
70
|
+
error?: string;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const AGENTS_TEMPLATE_PATH = "templates/AGENTS.codetrap.md";
|
|
75
|
+
const CODEX_MARKER = "codetrap search \"<keywords>\" --mode hybrid --json";
|
|
76
|
+
const MCP_COMMAND = ["codex", "mcp", "add", "codetrap", "--", "codetrap", "serve"];
|
|
77
|
+
const EMBEDDED_PLUGIN_ROOT = "embedded://plugins/codetrap-agent";
|
|
78
|
+
const EMBEDDED_SKILLS = [
|
|
79
|
+
{ name: "codetrap-add", skill: codetrapAddSkill },
|
|
80
|
+
{ name: "codetrap-capture", skill: codetrapCaptureSkill },
|
|
81
|
+
{ name: "codetrap-capture-external", skill: codetrapCaptureExternalSkill },
|
|
82
|
+
{ name: "codetrap-check", skill: codetrapCheckSkill },
|
|
83
|
+
{ name: "codetrap-search", skill: codetrapSearchSkill },
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
export function runCodexSetup(options: CodexSetupOptions): CodexSetupResult {
|
|
87
|
+
const cwd = resolve(options.cwd);
|
|
88
|
+
const projectRoot = findProjectRoot(cwd) ?? cwd;
|
|
89
|
+
const codexHome = resolveCodexHome(options.codexHome);
|
|
90
|
+
const pluginRoot = bundledPluginRoot();
|
|
91
|
+
const useEmbeddedAssets = !existsSync(pluginRoot);
|
|
92
|
+
|
|
93
|
+
const dryRun = options.dryRun === true;
|
|
94
|
+
const project = ensureProjectCodetrap(projectRoot, dryRun);
|
|
95
|
+
const skills = useEmbeddedAssets
|
|
96
|
+
? installEmbeddedSkills(codexHome, dryRun)
|
|
97
|
+
: installSkills(pluginRoot, codexHome, dryRun);
|
|
98
|
+
const agents = options.skipAgents
|
|
99
|
+
? { path: null, status: "skipped" as const }
|
|
100
|
+
: installAgentsTemplate(projectRoot, useEmbeddedAssets ? null : pluginRoot, options.agentsFile ?? "AGENTS.md", dryRun);
|
|
101
|
+
const mcp = setupMcp(options.installMcp === true, dryRun);
|
|
102
|
+
const success = mcp.status !== "failed";
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
success,
|
|
106
|
+
project_root: projectRoot,
|
|
107
|
+
codex_home: codexHome,
|
|
108
|
+
plugin_root: useEmbeddedAssets ? EMBEDDED_PLUGIN_ROOT : pluginRoot,
|
|
109
|
+
dry_run: dryRun,
|
|
110
|
+
project,
|
|
111
|
+
skills,
|
|
112
|
+
agents,
|
|
113
|
+
mcp,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function formatCodexSetupText(result: CodexSetupResult): string {
|
|
118
|
+
const installed = result.skills.filter((skill) =>
|
|
119
|
+
["installed", "updated", "would_install", "would_update"].includes(skill.status)
|
|
120
|
+
).length;
|
|
121
|
+
const unchanged = result.skills.filter((skill) => skill.status === "unchanged").length;
|
|
122
|
+
const lines = [
|
|
123
|
+
result.success ? "Codex setup complete." : "Codex setup completed with errors.",
|
|
124
|
+
`Project: ${result.project.status} (${result.project.codetrap_dir})`,
|
|
125
|
+
`Skills: ${installed} changed, ${unchanged} unchanged (${join(result.codex_home, "skills")})`,
|
|
126
|
+
`AGENTS: ${result.agents.status}${result.agents.path ? ` (${result.agents.path})` : ""}`,
|
|
127
|
+
];
|
|
128
|
+
if (result.mcp.requested) {
|
|
129
|
+
lines.push(`MCP: ${result.mcp.status} (${result.mcp.command})`);
|
|
130
|
+
if (result.mcp.error) lines.push(`MCP error: ${result.mcp.error}`);
|
|
131
|
+
} else {
|
|
132
|
+
lines.push(`MCP: skipped; pass --mcp to run '${result.mcp.command}'.`);
|
|
133
|
+
}
|
|
134
|
+
if (result.dry_run) lines.unshift("Dry run; no files or Codex config were changed.");
|
|
135
|
+
return lines.join("\n");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function ensureProjectCodetrap(projectRoot: string, dryRun: boolean): CodexSetupResult["project"] {
|
|
139
|
+
const codetrapDir = join(projectRoot, ".codetrap");
|
|
140
|
+
if (existsSync(codetrapDir)) {
|
|
141
|
+
return { codetrap_dir: codetrapDir, status: "already_present" };
|
|
142
|
+
}
|
|
143
|
+
if (!dryRun) mkdirSync(codetrapDir, { recursive: true });
|
|
144
|
+
return { codetrap_dir: codetrapDir, status: dryRun ? "would_create" : "created" };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function installSkills(pluginRoot: string, codexHome: string, dryRun: boolean): CodexSetupResult["skills"] {
|
|
148
|
+
const sourceSkillsDir = join(pluginRoot, "skills");
|
|
149
|
+
const targetSkillsDir = join(codexHome, "skills");
|
|
150
|
+
if (!dryRun) mkdirSync(targetSkillsDir, { recursive: true });
|
|
151
|
+
|
|
152
|
+
return readdirSync(sourceSkillsDir, { withFileTypes: true })
|
|
153
|
+
.filter((entry) => entry.isDirectory())
|
|
154
|
+
.sort((left, right) => left.name.localeCompare(right.name))
|
|
155
|
+
.map((entry) => {
|
|
156
|
+
const source = join(sourceSkillsDir, entry.name);
|
|
157
|
+
const destination = join(targetSkillsDir, entry.name);
|
|
158
|
+
const sourceSkill = readFileSync(join(source, "SKILL.md"), "utf-8");
|
|
159
|
+
const destinationSkillPath = join(destination, "SKILL.md");
|
|
160
|
+
const exists = existsSync(destinationSkillPath);
|
|
161
|
+
const unchanged = exists && readFileSync(destinationSkillPath, "utf-8") === sourceSkill;
|
|
162
|
+
let status: CodexSetupStatus = unchanged ? "unchanged" : exists ? "updated" : "installed";
|
|
163
|
+
if (dryRun && status === "installed") status = "would_install";
|
|
164
|
+
if (dryRun && status === "updated") status = "would_update";
|
|
165
|
+
if (!dryRun && !unchanged) cpSync(source, destination, { recursive: true, force: true });
|
|
166
|
+
return { name: entry.name, source, destination, status };
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function installEmbeddedSkills(codexHome: string, dryRun: boolean): CodexSetupResult["skills"] {
|
|
171
|
+
const targetSkillsDir = join(codexHome, "skills");
|
|
172
|
+
if (!dryRun) mkdirSync(targetSkillsDir, { recursive: true });
|
|
173
|
+
|
|
174
|
+
return EMBEDDED_SKILLS.map((entry) => {
|
|
175
|
+
const destination = join(targetSkillsDir, entry.name);
|
|
176
|
+
const destinationSkillPath = join(destination, "SKILL.md");
|
|
177
|
+
const exists = existsSync(destinationSkillPath);
|
|
178
|
+
const unchanged = exists && readFileSync(destinationSkillPath, "utf-8") === entry.skill;
|
|
179
|
+
let status: CodexSetupStatus = unchanged ? "unchanged" : exists ? "updated" : "installed";
|
|
180
|
+
if (dryRun && status === "installed") status = "would_install";
|
|
181
|
+
if (dryRun && status === "updated") status = "would_update";
|
|
182
|
+
if (!dryRun && !unchanged) {
|
|
183
|
+
mkdirSync(destination, { recursive: true });
|
|
184
|
+
writeFileSync(destinationSkillPath, entry.skill);
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
name: entry.name,
|
|
188
|
+
source: `${EMBEDDED_PLUGIN_ROOT}/skills/${entry.name}`,
|
|
189
|
+
destination,
|
|
190
|
+
status,
|
|
191
|
+
};
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function installAgentsTemplate(
|
|
196
|
+
projectRoot: string,
|
|
197
|
+
pluginRoot: string | null,
|
|
198
|
+
agentsFile: string,
|
|
199
|
+
dryRun: boolean
|
|
200
|
+
): CodexSetupResult["agents"] {
|
|
201
|
+
const target = resolve(projectRoot, agentsFile);
|
|
202
|
+
const template = (pluginRoot
|
|
203
|
+
? readFileSync(join(pluginRoot, AGENTS_TEMPLATE_PATH), "utf-8")
|
|
204
|
+
: agentsTemplateAsset
|
|
205
|
+
).trimEnd();
|
|
206
|
+
if (existsSync(target)) {
|
|
207
|
+
const current = readFileSync(target, "utf-8");
|
|
208
|
+
if (current.includes(CODEX_MARKER)) {
|
|
209
|
+
return { path: target, status: "already_present" };
|
|
210
|
+
}
|
|
211
|
+
if (!dryRun) appendFileSync(target, `${current.endsWith("\n") ? "\n" : "\n\n"}${template}\n`);
|
|
212
|
+
return { path: target, status: dryRun ? "would_append" : "appended" };
|
|
213
|
+
}
|
|
214
|
+
if (!dryRun) writeFileSync(target, `${template}\n`);
|
|
215
|
+
return { path: target, status: dryRun ? "would_create" : "created" };
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function setupMcp(requested: boolean, dryRun: boolean): CodexSetupResult["mcp"] {
|
|
219
|
+
const command = MCP_COMMAND.join(" ");
|
|
220
|
+
if (!requested) return { requested, command, status: "skipped" };
|
|
221
|
+
if (dryRun) return { requested, command, status: "would_run" };
|
|
222
|
+
|
|
223
|
+
const result = Bun.spawnSync({
|
|
224
|
+
cmd: MCP_COMMAND,
|
|
225
|
+
stdout: "pipe",
|
|
226
|
+
stderr: "pipe",
|
|
227
|
+
});
|
|
228
|
+
if (result.success) return { requested, command, status: "installed", exit_code: result.exitCode };
|
|
229
|
+
|
|
230
|
+
const stderr = new TextDecoder().decode(result.stderr).trim();
|
|
231
|
+
const stdout = new TextDecoder().decode(result.stdout).trim();
|
|
232
|
+
return {
|
|
233
|
+
requested,
|
|
234
|
+
command,
|
|
235
|
+
status: "failed",
|
|
236
|
+
exit_code: result.exitCode,
|
|
237
|
+
error: stderr || stdout || "codex mcp add failed",
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function resolveCodexHome(codexHome?: string): string {
|
|
242
|
+
return resolve(codexHome ?? process.env.CODEX_HOME ?? join(process.env.HOME ?? process.env.USERPROFILE ?? homedir(), ".codex"));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function bundledPluginRoot(): string {
|
|
246
|
+
return join(dirname(dirname(dirname(fileURLToPath(import.meta.url)))), "plugins", "codetrap-agent");
|
|
247
|
+
}
|