@jaybeeuu/agent-cortex 1.38.1 → 1.40.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 (88) hide show
  1. package/.agents/skills/style-versioning/SKILL.md +1 -1
  2. package/.github/workflows/ci.yml +47 -14
  3. package/AGENTS.md +19 -3
  4. package/CHANGELOG.md +42 -0
  5. package/README.md +118 -63
  6. package/agents/README.md +13 -10
  7. package/agents/ralph-plan/agent.md +1 -1
  8. package/agents/ralph-plan.agent.md +1 -1
  9. package/bin/agent-cortex.mjs +29 -8
  10. package/bin/installers/claude.mjs +569 -105
  11. package/bin/installers/copilot.mjs +22 -12
  12. package/bin/installers/pi.mjs +37 -34
  13. package/docs/claude-hooks.md +3 -3
  14. package/docs/ideas/extension-manifests.md +75 -0
  15. package/docs/ideas/record-ideas-as-beads.md +115 -0
  16. package/docs/ideas/subagent-visibility.md +72 -0
  17. package/docs/ideas/task-session-context.md +89 -0
  18. package/docs/research/skill-design-research.md +4 -4
  19. package/docs/research/skill-improvements-analysis.md +1 -1
  20. package/docs/skills/skill-anatomy.md +38 -2
  21. package/docs/technical-direction/migration-execution-labels.md +132 -0
  22. package/extensions/agent-modes/README.md +3 -2
  23. package/extensions/agent-modes/discover.test.ts +30 -7
  24. package/extensions/agent-modes/discover.ts +1 -1
  25. package/extensions/skill-stats/index.test.ts +3 -2
  26. package/lib/cli.mjs +24 -6
  27. package/package.json +4 -4
  28. package/plugin.json +1 -1
  29. package/pnpm-workspace.yaml +1 -1
  30. package/scripts/build-copilot-agents.mjs +1 -1
  31. package/scripts/check-no-sync.mjs +49 -0
  32. package/scripts/lib/compose-agent.mjs +32 -14
  33. package/skills/engineering/design-an-interface/SKILL.md +78 -58
  34. package/skills/engineering/grill-with-docs/REFERENCE.md +78 -0
  35. package/skills/engineering/grill-with-docs/SKILL.md +66 -63
  36. package/skills/engineering/improve-codebase-architecture/SKILL.md +66 -48
  37. package/skills/engineering/technical-direction/FORMAT.md +38 -0
  38. package/skills/engineering/technical-direction/SKILL.md +70 -77
  39. package/skills/planning/classify-bead/SKILL.md +59 -35
  40. package/skills/planning/create-task/REFERENCE.md +40 -0
  41. package/skills/planning/create-task/SKILL.md +70 -66
  42. package/skills/planning/create-task/scripts/create-chores.ts +6 -1
  43. package/skills/planning/create-task/scripts/node_modules/.bin/tsc +21 -0
  44. package/skills/planning/create-task/scripts/node_modules/.bin/tsserver +21 -0
  45. package/skills/planning/create-task/scripts/node_modules/.bin/tsx +21 -0
  46. package/skills/planning/prd-to-tasks/REFERENCE.md +66 -0
  47. package/skills/planning/prd-to-tasks/SKILL.md +86 -170
  48. package/skills/planning/record-idea/FORMAT.md +44 -0
  49. package/skills/planning/record-idea/SKILL.md +70 -53
  50. package/skills/planning/request-refactor-plan/FORMAT.md +45 -0
  51. package/skills/planning/request-refactor-plan/SKILL.md +57 -46
  52. package/skills/planning/write-a-prd/FORMAT.md +54 -0
  53. package/skills/planning/write-a-prd/SKILL.md +49 -48
  54. package/skills/planning/write-a-ticket/SKILL.md +68 -53
  55. package/skills/productivity/handoff/SKILL.md +12 -0
  56. package/skills/productivity/init-beads/SKILL.md +48 -40
  57. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsc +21 -0
  58. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsserver +21 -0
  59. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsx +21 -0
  60. package/skills/productivity/write-a-skill/SKILL.md +2 -1
  61. package/skills/review/maintain-agent-docs/SKILL.md +71 -51
  62. package/skills/workflow/hitl-collab/SKILL.md +86 -17
  63. package/skills/workflow/ralph/REFERENCE.md +22 -17
  64. package/skills/workflow/ralph/SKILL.md +88 -74
  65. package/skills/workflow/run-pipeline-stage/REFERENCE.md +22 -0
  66. package/skills/workflow/run-pipeline-stage/SKILL.md +91 -93
  67. package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +6 -107
  68. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsc +21 -0
  69. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsserver +21 -0
  70. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsx +21 -0
  71. package/test/claude-installer.test.mjs +308 -0
  72. package/test/cli.test.mjs +40 -30
  73. package/test/copilot-installer.test.mjs +92 -82
  74. package/test/helpers/fake-claude.mjs +152 -0
  75. package/test/installer.test.mjs +309 -57
  76. package/test/pi-installer.test.mjs +115 -99
  77. package/token-map.README.md +21 -10
  78. package/token-map.json +7 -6
  79. package/.claude-plugin/marketplace.json +0 -16
  80. package/claude/.claude-plugin/plugin.json +0 -11
  81. package/claude/agents/plan.md +0 -58
  82. package/claude/agents/ralph-plan.md +0 -121
  83. package/claude/agents/ralph.md +0 -193
  84. package/claude/agents/strategy.md +0 -111
  85. package/claude/hooks/scripts/notify.mjs +0 -54
  86. package/claude/hooks.json +0 -38
  87. /package/{claude → claude-extras}/.mcp.json +0 -0
  88. /package/{claude → claude-extras}/scripts/statusline-command.sh +0 -0
@@ -64,7 +64,7 @@ Fix status bead showing wrong priority after update
64
64
  The `release` job in `.github/workflows/ci.yml` handles everything automatically:
65
65
 
66
66
  1. **Detects new changesets** on main
67
- 2. **Creates a "Version Packages" PR** — the `version` step runs `pnpm version-packages`, which bumps `package.json`, syncs `plugin.json` (via `scripts/sync-plugin-version.sh`), updates `CHANGELOG.md`, and regenerates the committed generated output (`pnpm build:claude`, `pnpm build:copilot`) so the drift gates never fail on a version bump
67
+ 2. **Creates a "Version Packages" PR** — the `version` step runs `pnpm version-packages`, which bumps `package.json`, syncs `plugin.json` (via `scripts/sync-plugin-version.sh`), updates `CHANGELOG.md`, and regenerates the committed Copilot output (`pnpm build:copilot`; the Claude plugin is materialised at install time with the package version, so it has no committed output to regenerate) so the drift gates never fail on a version bump
68
68
  3. **When "Version Packages" is merged**:
69
69
  - Creates a git tag
70
70
  - Publishes to npm — `pnpm publish-package` packs with `pnpm pack` and publishes with `npm publish --provenance --access public`. Authenticates via npm Trusted Publishing (OIDC): the release job's `id-token` permission lets npm exchange a GitHub OIDC token for a short-lived npm token at publish time, so no `NPM_TOKEN` secret or `.npmrc` auth config is required — only the one-time npm-side Trusted Publishing setup on npmjs.com (package → Access → Trusted Publishing → GitHub repo `jaybeeuu/agent-cortex` + workflow `.github/workflows/ci.yml`)
@@ -146,7 +146,7 @@ jobs:
146
146
  run: pnpm test
147
147
 
148
148
  claude-plugin-check:
149
- name: Claude plugin check
149
+ name: Claude plugin materialiser check
150
150
  needs: setup
151
151
  runs-on: ubuntu-latest
152
152
  steps:
@@ -175,16 +175,48 @@ jobs:
175
175
  - name: Install dependencies
176
176
  run: pnpm install --frozen-lockfile
177
177
 
178
- # `pnpm build:claude` is an alias of `agent-cortex install claude` (both run
179
- # bin/installers/claude.mjs), so this drift check proves the committed subtree
180
- # equals the installer's output — stale output or hand-edits to generated
181
- # files fail the build. The subtree stays committed because the marketplace
182
- # install flow reads it straight from the working tree (fresh clone installs
183
- # as-is).
184
- - name: Check generated Claude plugin is up to date
178
+ # The claude/ subtree is retired — the installer is the only generator
179
+ # (plain `agent-cortex install claude` materialises ~/.agent-cortex/claude;
180
+ # `--output <dir>` is generate-only for tests). There is no committed
181
+ # output to diff, so this job validates the materialiser itself: it must
182
+ # produce a complete, structural plugin (generated + hand-authored pieces),
183
+ # no symlinks, no literal {{TOOL:/{{PATH:/{{SECTION: tokens, and a
184
+ # plugin.json version tracking the package — exactly what a real install
185
+ # would ship.
186
+ - name: Materialise the Claude plugin and run structural checks
185
187
  run: |
186
- pnpm build:claude
187
- git diff --exit-code claude/agents/ claude/skills/ claude/.claude-plugin/plugin.json claude/hooks.json claude/hooks/
188
+ set -euo pipefail
189
+ OUT="$RUNNER_TEMP/claude-plugin-check"
190
+ node bin/agent-cortex.mjs install claude --output "$OUT"
191
+
192
+ # structure: generated + hand-authored pieces all present
193
+ test -f "$OUT/.claude-plugin/plugin.json"
194
+ test -f "$OUT/agents/plan.md"
195
+ test -f "$OUT/agents/ralph.md"
196
+ test -f "$OUT/skills/tdd/SKILL.md"
197
+ test -f "$OUT/hooks.json"
198
+ test -f "$OUT/hooks/scripts/notify.mjs"
199
+ test -f "$OUT/.mcp.json"
200
+ test -f "$OUT/scripts/statusline-command.sh"
201
+
202
+ # flat-copy guarantee: no symlinks in the materialised tree
203
+ if [ -n "$(find "$OUT" -type l)" ]; then
204
+ echo "::error::symlinks found in materialised Claude plugin"
205
+ exit 1
206
+ fi
207
+
208
+ # token substitution: no literal tokens survive materialisation
209
+ TOKENS=$(grep -rlE '\{\{(TOOL|PATH|SECTION):' "$OUT" || true)
210
+ if [ -n "$TOKENS" ]; then
211
+ echo "::error::literal substitution tokens in materialised Claude plugin:"
212
+ echo "$TOKENS"
213
+ exit 1
214
+ fi
215
+
216
+ # plugin version tracks the package (never stale)
217
+ PKG_VERSION=$(node -p "require('./package.json').version")
218
+ PLUGIN_VERSION=$(node -p "require('$OUT/.claude-plugin/plugin.json').version")
219
+ test "$PKG_VERSION" = "$PLUGIN_VERSION"
188
220
 
189
221
  - name: Check generated Copilot agent files are up to date
190
222
  run: |
@@ -239,10 +271,11 @@ jobs:
239
271
  # the string is split by argStringToArray on whitespace (single quotes
240
272
  # survive literally), so each must be a single unquoted command token
241
273
  # that runs a pnpm script. version-packages bumps versions, syncs
242
- # plugin.json, THEN regenerates the committed generated output
243
- # (build:claude writes claude/.claude-plugin/plugin.json with the NEW
244
- # version, build:copilot re-derives agents/*.agent.md) before the action
245
- # commits, so the Version Packages PR always passes the drift gates.
274
+ # plugin.json, THEN regenerates the committed Copilot output
275
+ # (build:copilot re-derives agents/*.agent.md; the Claude plugin is
276
+ # materialised at install time with the package version, so nothing
277
+ # committed needs regenerating) before the action commits, so the
278
+ # Version Packages PR always passes the drift gates.
246
279
  version: pnpm version-packages
247
280
  publish: pnpm publish-package
248
281
  commit: "chore: version packages"
package/AGENTS.md CHANGED
@@ -33,7 +33,10 @@ agent-cortex/
33
33
  │ ├── README.md # Installation & usage
34
34
  │ └── index.ts # Extension entrypoint
35
35
  ├── hooks/ # Canonical Claude Code hooks (hooks.json + scripts — see docs/claude-hooks.md)
36
- │ └── claude/ # generated into claude/hooks.json + claude/hooks/ by bin/installers/claude.mjs
36
+ │ └── claude/ # generated into the plugin's hooks.json + hooks/ by bin/installers/claude.mjs
37
+ ├── claude-extras/ # Hand-authored Claude plugin extras (no committed claude/ output)
38
+ │ ├── .mcp.json # MCP servers (context7, github) — copied into installs
39
+ │ └── scripts/ # statusline-command.sh — copied into installs (executable)
37
40
  └── package.json # PI package manifest (pi: { extensions, skills })
38
41
  ```
39
42
 
@@ -47,6 +50,13 @@ See the `style-versioning` skill for the full workflow.
47
50
 
48
51
  Generated automatically by changesets. Do not edit `CHANGELOG.md` manually.
49
52
 
53
+ ## Coding Conventions
54
+
55
+ - **Never block the main thread**: no `*Sync` functions (`readFileSync`, `spawnSync`, …).
56
+ Tooling code in `bin/`, `scripts/`, `lib/`, `hooks/`, and `test/` must be async —
57
+ enforced by `scripts/check-no-sync.mjs` (runs via `pnpm lint`). Skill-owned
58
+ scripts (`skills/*/scripts`) and `extensions/` are the remaining sync surfaces.
59
+
50
60
  ## Skill Conventions
51
61
 
52
62
  - `SKILL.md` must include a YAML front-matter block with `name` and `description`.
@@ -66,8 +76,14 @@ Generated automatically by changesets. Do not edit `CHANGELOG.md` manually.
66
76
  from the canonical directories by the shared `bin/installers/copilot.mjs` code path behind both
67
77
  `agent-cortex install copilot` and `scripts/build-copilot-agents.mjs` (thin wrapper), and
68
78
  committed for Copilot CLI (plugin.json `agents: "agents/"` scans for `*.agent.md`); never edit
69
- them by hand. The `claude/` subtree is generated by the install-time generator
70
- `bin/installers/claude.mjs` (`pnpm build:claude` aliases `agent-cortex install claude`; `ralph`
79
+ them by hand. The Claude plugin is materialised by the install-time generator
80
+ `bin/installers/claude.mjs`: a plain `agent-cortex install claude` copies it into
81
+ `~/.agent-cortex/claude` (skills copied flat with `{{TOOL:...}}`/`{{PATH:...}}` substituted,
82
+ never symlinked), writes the marketplace manifest at
83
+ `~/.agent-cortex/.claude-plugin/marketplace.json`, and registers it with Claude Code via the
84
+ `claude plugin` CLI; the repo commits no `claude/` output — hand-authored plugin
85
+ extras live in `claude-extras/` (`.mcp.json`, `scripts/`), and `--output <dir>` is the
86
+ generate-only form (tests/CI materialiser checks); `ralph`
71
87
  is authored natively in `agents-native/` and copied verbatim; the other agents compose from their
72
88
  `claude/` harness dirs).
73
89
  - Keep orchestration logic in the agent file; extract shared per-task workflow into a skill
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.40.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1b6b8b8: `agent-cortex install claude` now materialises the plugin: home-scoped install into `~/.agent-cortex/claude`, copied (token-substituted, no symlinks) skills, marketplace manifest, and automatic registration with Claude Code. Installer toolchain is fully async (no `*Sync` — never block the main thread), enforced by a `check-no-sync` lint scanner.
8
+ - 65119b8: Map `ask_user` → `ask_questions` (pi-questions package) and `skill` → `read` in the pi column of token-map.json: pi agent modes regain interactive questioning (`ask_questions`) instead of dropping the tool with a startup warning, and skill references resolve to reading their SKILL.md. Notes and docs updated to record that `ask_questions` is provided by the pi-questions package.
9
+ - 1b6b8b8: Retire the committed `claude/` plugin subtree: `agent-cortex install claude` into `~/.agent-cortex/claude` (with automatic marketplace registration) is now the only way to build the Claude Code plugin. Hand-authored extras moved to `claude-extras/`, the `build:claude` script is removed, and CI validates the installer instead of diffing committed output.
10
+
11
+ ### Patch Changes
12
+
13
+ - fcb16d7: Fix grill-with-docs failing to load: quote the front-matter description so skill parsers accept it.
14
+
15
+ ## 1.39.0
16
+
17
+ ### Minor Changes
18
+
19
+ - 5d4159f: Handoff documents now end with a `## Starter prompt` section: a ready-to-paste first-message prompt pointing the next session at the handoff doc by absolute path and the artifacts it references, telling it to read those before acting, asking it to clean up any provisional artifacts unless the handoff says otherwise, and staying under ~150 words.
20
+ - 5351ae9: agent-cortex install claude now fully installs agent-cortex into Claude Code: it regenerates the claude/ subtree and registers it with the Claude Code runtime via the claude plugin CLI (--dry-run prints the plan without writing; --output <dir> generates only).
21
+
22
+ ### Patch Changes
23
+
24
+ - adb5f84: Add optional ASCII workflow diagram guidance (inclusion rules, style guide, template example) to the skill anatomy and reference it from write-a-skill
25
+ - 5d4159f: Fix create-chores to resolve `bd` via PATH by default instead of a machine-specific hardcoded path. The BD_PATH env override is retained for machines where bd is not on PATH.
26
+ - 3e8b6e7: Refactor the `hitl-collab` skill to the canonical anatomy template: added When to use / When NOT to use boundaries, Red Flags, Common Rationalizations, a worked handoff-doc example, and a verification checklist; switched bead updates to `--append-notes` so existing notes are preserved.
27
+ - b33d9ef: Refactor the improve-codebase-architecture skill to the anatomy template: add when-to-use / when-not-to-use boundaries, red flags, common rationalizations, philosophy, phase-gate checklists, cross-skill references, a worked example, and a verification checklist.
28
+ - da1e3dd: Add `bd dep add` line to the init-beads skill's embedded AGENTS.md quick-reference template so it matches the repo template and stops re-propagating the drift
29
+ - 358509f: Prune stale doc-contract prose assertions from the run-pipeline-stage progress test; re-enable the skills-script test suites in the pnpm workspace so they actually run in CI.
30
+ - 32b33ac: Refactor the record-idea skill to the anatomy template: add when-to-use boundaries, red flags, rationale, and a verification checklist; move the idea-record scaffold to FORMAT.md to match the generator script.
31
+ - 662cea5: Refactor the `classify-bead` skill to the anatomy template: adds when-not-to-use boundaries, red flags, common rationalizations, philosophy, and a verification checklist.
32
+ - bb01fd6: Refactor create-task skill to the anatomy template: adds When to use / When NOT to use, Red Flags, Common Rationalizations, verification checklist, and moves the bead-property contract detail to REFERENCE.md. No behavioural change — the create-chores script invocation contract is preserved exactly.
33
+ - 876e5cc: Refactor design-an-interface skill to the anatomy template: adds When to use, When NOT to use, verification checklist, phase gates, and rationalization sections while keeping the parallel sub-agent design workflow intact
34
+ - 00c4238: Refactor grill-with-docs to the anatomy template: add when-to-use boundaries, numbered workflow, red flags, common rationalizations, examples, and a verification checklist; consolidate the previously-dangling CONTEXT.md/ADR format links into REFERENCE.md.
35
+ - fd5f787: Refactor init-beads skill to the anatomy template: adds When to use / When NOT to use, Red Flags, Common Rationalizations, Cross-skill references, Examples, and a verification checklist. No behavioural change — the `bd init --quiet --stealth` invocation, install-method preference order, and AGENTS.md quick-reference block are preserved exactly.
36
+ - 608fb58: Refactor maintain-agent-docs skill to the canonical anatomy template: added When NOT to use, Philosophy, Red Flags, Common Rationalizations, Phase-gate checklist, Cross-skill references, Examples, and a concrete Verification checklist; tightened the description to the two-sentence format with quoted trigger phrases.
37
+ - 027431c: Refactor the `prd-to-tasks` skill to the canonical anatomy template: condensed the 5-phase workflow, moved the epic/task body templates into `REFERENCE.md`, added Examples and Phase-gate checklists, and aligned section ordering and voice with `docs/skills/skill-anatomy.md`.
38
+ - e80246a: Refactor the ralph skill to the canonical skill anatomy: add When to use / When NOT to use, Red Flags, Common Rationalizations, Philosophy, phase-gate checklists, cross-skill references, and a verification checklist; align the skill docs with the ralph agent definition (state.json for poll-timer and agent-ID→bead bookkeeping, parent-keyed stage log files, stage runners self-serving `bd prime`, and the single-feature-epic one-hop branching shortcut).
39
+ - d917afb: Refactor request-refactor-plan SKILL.md to the anatomy template; move the refactor plan template into FORMAT.md.
40
+ - d6d33ec: Refactor technical-direction skill to the canonical anatomy template, adding when-to-use/not-to-use boundaries, red flags, common rationalizations, cross-skill references, an examples section, and a verification checklist. The decision-memo template moves to FORMAT.md.
41
+ - 67a668f: Refactor the write-a-prd skill to the anatomy template: adds when-to-use/when-not-to-use boundaries, red flags, common rationalizations, phase gates, cross-skill references, an example, and a verification checklist; the PRD template moves to FORMAT.md.
42
+ - bedd373: Refactor the write-a-ticket skill to the canonical anatomy template: added when-to-use and when-not-to-use boundaries, red flags, common rationalizations, philosophy, cross-skill references, worked examples, and a verification checklist. The ticket template and per-section guidance are preserved.
43
+ - fd95ffe: Refactor run-pipeline-stage SKILL.md to the canonical anatomy template: add `When to use`, `When NOT to use`, `Workflow`, `Red Flags`, `Common Rationalizations`, `Cross-skill references`, `Examples`, `Philosophy / rationale`, and a `Verification checklist`; add quoted trigger phrases to the description; tokenize subagent dispatch as {{TOOL:task}}. No behavioural change to the stage pipeline — all playbooks, prompts, dispatch rules, and path references are preserved.
44
+
3
45
  ## 1.38.1
4
46
 
5
47
  ### Patch Changes
package/README.md CHANGED
@@ -9,8 +9,6 @@ pi, and [Claude Code](https://code.claude.com/docs) (as a plugin).
9
9
  ```
10
10
  agent-cortex/
11
11
  ├── plugin.json # Copilot plugin manifest
12
- ├── .claude-plugin/
13
- │ └── marketplace.json # Claude marketplace (exposes ./claude as the "jaybeeuu" market)
14
12
  ├── agents/ # Canonical agents — composable <name>/ dirs (see agents/README.md)
15
13
  │ ├── *.agent.md # ralph, ralph-plan, plan, strategy — GENERATED from <name>/ by scripts/build-copilot-agents.mjs
16
14
  │ ├── ralph/ # composable form (shared agent.md + per-harness pi/, copilot/, claude/)
@@ -38,17 +36,12 @@ agent-cortex/
38
36
  │ ├── agent-cortex.mjs # CLI entrypoint
39
37
  │ └── installers/
40
38
  │ ├── copilot.mjs # shared generator: agent-cortex install copilot + scripts/build-copilot-agents.mjs
41
- │ └── claude.mjs # install-time generator — agent-cortex install claude (pnpm build:claude aliases it)
39
+ │ └── claude.mjs # materialises ~/.agent-cortex/claude + registers with Claude Code (--output <dir> = generate-only form)
42
40
  ├── scripts/
43
41
  │ └── build-copilot-agents.mjs # thin wrapper over bin/installers/copilot.mjs (regenerates agents/*.agent.md)
44
- └── claude/ # Self-contained Claude Code plugin (GENERATED — do not hand-edit)
45
- ├── .claude-plugin/
46
- │ └── plugin.json
47
- ├── .mcp.json # MCP servers (context7, github) — hand-authored
48
- ├── hooks.json # SessionStart + Notification hooks — generated from hooks/claude/
49
- ├── hooks/ # hook scripts (e.g. scripts/notify.mjs) — generated from hooks/claude/
50
- ├── agents/ # composed from agents/<name>/claude/ + copied from agents-native/
51
- └── skills/ # symlinks to the grouped skills/ dirs (29 skills)
42
+ └── claude-extras/ # Hand-authored Claude plugin extras (no committed claude/ output)
43
+ ├── .mcp.json # MCP servers (context7, github) — copied into installs
44
+ └── scripts/ # statusline-command.sh — copied into installs (executable)
52
45
  ```
53
46
 
54
47
  The same `agents/` and `skills/` power three harnesses (Copilot, pi, Claude Code).
@@ -61,34 +54,44 @@ install-time and build-time output can never diverge) and committed so Copilot C
61
54
  The `{{TOOL:...}}` / `{{PATH:...}}` tokens written in agent and skill files are resolved
62
55
  per harness at install time from `token-map.json`, the single source of truth for
63
56
  canonical tool/path/agent names (see `token-map.README.md` and the `contract` section).
64
- The `claude/` subtree is **generated** by the install-time generator
65
- (`bin/installers/claude.mjs`) — `pnpm build:claude` is a pure alias of
66
- `agent-cortex install claude`, so there is no separate build-time code path, and the
67
- committed subtree can never diverge from a real install. CI regenerates it and checks
68
- it is never stale:
69
-
70
- - **Skills** stay single-source — `claude/skills/<name>` are symlinks into the grouped
71
- `skills/<group>/<name>` dirs (Claude discovers skills only one level deep, so the
72
- grouping is flattened via links, not copies).
73
- - **Agents** can't be shared files (the frontmatter formats differ), so `claude/agents/*.md`
74
- are composed from the canonical `agents/<name>/` directories' `claude/` harness dirs
57
+ The Claude plugin is **materialised** at install time by `bin/installers/claude.mjs`. A
58
+ plain `agent-cortex install claude` copies the plugin into the home install root
59
+ (`~/.agent-cortex/claude`), writes a marketplace manifest at
60
+ `~/.agent-cortex/.claude-plugin/marketplace.json` exposing it, and registers it with
61
+ Claude Code by driving the `claude plugin` CLI — state-checked and idempotent (a fresh
62
+ install adds the marketplace + installs the plugin; a re-run updates what state says is
63
+ out of date; a repeat install at the same version is a no-op; a missing or pre-v2 CLI
64
+ warns and prints the manual registration commands instead of failing). The repo commits
65
+ no `claude/` output (hand-authored extras live in `claude-extras/`), so CI validates the
66
+ materialiser itself — a temp-dir install plus structural checks:
67
+
68
+ - **Skills** stay single-source — the installer copies each `skills/<group>/<name>/` dir
69
+ flat into `skills/<name>/` (Claude discovers skills only one level deep) with
70
+ `{{TOOL:...}}` / `{{PATH:...}}` tokens substituted against token-map.json's claude
71
+ column — no symlinks, so literal tokens never reach Claude.
72
+ - **Agents** can't be shared files (the frontmatter formats differ), so the materialised
73
+ plugin's `agents/*.md` are composed from the canonical `agents/<name>/` directories' `claude/`
74
+ harness dirs
75
75
  (frontmatter.json + section files), exactly like the Copilot flats are composed from their
76
76
  `copilot/` dirs. Claude only loads agents from a plugin's default `agents/` dir, so the plugin
77
- root is `claude/` — isolating it from the Copilot `.agent.md` files.
77
+ ships them at its own root (default `~/.agent-cortex/claude/agents/`) — isolating them from the
78
+ Copilot `.agent.md` files.
78
79
  - **Claude-native agents** that have no Copilot equivalent live in `agents-native/*.md` and are
79
- copied verbatim into `claude/agents/`. `ralph` is one: it is reimplemented for Claude around
80
+ copied verbatim into the materialised plugin's `agents/`. `ralph` is one: it is reimplemented
81
+ for Claude around
80
82
  background workers + an independent review gate (the Copilot Ralph's `task`/`read_agent`
81
83
  poll loop has no Claude equivalent), so it can't be mechanically converted.
82
- - **Manifests** are generated too: `claude/.claude-plugin/plugin.json` (its `version` tracks
83
- `package.json`, so it never goes stale) and `claude/hooks.json` (copied from the canonical
84
+ - **Manifests** are generated too: the plugin's `.claude-plugin/plugin.json` (its `version`
85
+ tracks `package.json`, so it never goes stale) and `hooks.json` (copied from the canonical
84
86
  `hooks/claude/hooks.json` source), plus any support files under `hooks/claude/` bundled into
85
- `claude/hooks/` so hook commands can reach them via `$CLAUDE_PLUGIN_ROOT`. `claude/.mcp.json`
86
- and `claude/scripts/` stay hand-authored. See `docs/claude-hooks.md` for the extension→hook
87
- mapping and the rejections (auto-name, skill-stats, subagent, agent-modes).
87
+ the plugin's `hooks/` so hook commands can reach them via `$CLAUDE_PLUGIN_ROOT`. Hand-authored
88
+ extras — `.mcp.json` and `scripts/` — are copied into every install from the `claude-extras/`
89
+ dir, which is their canonical store. See `docs/claude-hooks.md` for the
90
+ extension→hook mapping and the rejections (auto-name, skill-stats, subagent, agent-modes).
88
91
 
89
92
  Edit the sources (`agents/<name>/` composable dirs, `agents-native/*.md`, `skills/**`,
90
- `hooks/claude/`, `package.json`), never anything under `claude/` or the generated
91
- `agents/*.agent.md` files.
93
+ `hooks/claude/`, `claude-extras/`, `package.json`), never the generated
94
+ `agents/*.agent.md` files or anything under the materialised `~/.agent-cortex/claude`.
92
95
 
93
96
  ## CI
94
97
 
@@ -98,6 +101,15 @@ does its own checkout and `pnpm install` rather than sharing build artifacts fro
98
101
  the `setup` job — pnpm workspace symlinks don't survive artifact upload/download,
99
102
  so artifact sharing would break the workspace resolution that the build depends on.
100
103
 
104
+ The repo commits no generated `claude/` output, so the `claude-plugin-check` job
105
+ validates the Claude plugin **materialiser** instead of diffing a committed mirror:
106
+ it runs `node bin/agent-cortex.mjs install claude --output <tmp dir>` and checks the
107
+ result structurally — `plugin.json` version tracks `package.json`, every generated and
108
+ hand-authored piece is present, no literal `{{TOOL:...}}`/`{{PATH:...}}` tokens survive,
109
+ and no symlinks leak into the copied tree. The Copilot drift check
110
+ (`pnpm build:copilot` + `git diff --exit-code -- 'agents/*.agent.md'`) still guards the
111
+ committed flat agent files.
112
+
101
113
  A separate `changeset-check` job runs only on pull requests and fails any PR that
102
114
  touches a versioned path (`extensions/`, `skills/`, `agents/`, `package.json`, or
103
115
  `plugin.json`) without a changeset in `.changeset/`. Add one with `pnpm changeset` —
@@ -107,7 +119,9 @@ On pushes to `main`, a `release` job (gated on `lint`, `test`, and
107
119
  `claude-plugin-check`) runs changesets to open a `chore: version packages` PR when
108
120
  changesets are pending, then publishes to npm once it lands. The version step runs
109
121
  `pnpm version-packages` — bumping `package.json`, syncing `plugin.json`, and
110
- regenerating the committed generated output so the drift gates stay green; the
122
+ regenerating the committed Copilot agent files (the Claude plugin is materialised at
123
+ install time with the package version, so it has no committed output to regenerate)
124
+ so the drift gates stay green; the
111
125
  publish step runs `pnpm publish-package` (pack + provenance publish). Publish
112
126
  authenticates via npm Trusted Publishing (OIDC) — no npm token or GitHub
113
127
  secret is needed, only the one-time npm-side setup on npmjs.com (package →
@@ -183,32 +197,39 @@ copilot plugin install ./agent-cortex
183
197
 
184
198
  ### Claude Code plugin (separate)
185
199
 
186
- The Claude plugin is the self-contained `claude/` subtree (manifest at
187
- `claude/.claude-plugin/plugin.json`), containing **4 agents** (`strategy`, `plan`,
188
- `ralph-plan`, `ralph`), **29 skills**, `SessionStart` + `Notification` hooks, and 2 MCP servers.
200
+ A plain `agent-cortex install claude` **materialises** the plugin into the home install
201
+ root `~/.agent-cortex/claude` — **4 agents** (`strategy`, `plan`, `ralph-plan`, `ralph`),
202
+ **29 skills** (copied flat per skill, `{{TOOL:...}}` / `{{PATH:...}}` token-substituted — no
203
+ symlinks), `SessionStart` + `Notification` hooks, and 2 MCP servers — writes a marketplace
204
+ manifest at `~/.agent-cortex/.claude-plugin/marketplace.json` exposing `./claude`, and
205
+ registers it with Claude Code. The repo commits no `claude/` output: hand-authored extras
206
+ (`.mcp.json`, `scripts/`) are served from `claude-extras/`, and everything else is generated
207
+ at install time — there is nothing to drift.
189
208
 
190
- `claude/` is committed (the marketplace install flow reads it straight from the working
191
- tree, so a fresh clone installs as-is), and rebuilt via the install-time generator if you
192
- change the sources:
209
+ The generate-only `--output <dir>` form is for previewing and CI validation; the
210
+ documented path is the plain install to `~/.agent-cortex/claude`:
193
211
 
194
212
  ```sh
195
213
  pnpm build:copilot # or: node scripts/build-copilot-agents.mjs (regenerates agents/*.agent.md)
196
- pnpm build:claude # or: node bin/agent-cortex.mjs install claude (same generator)
197
- # or the install-time entry (same generator, less typing):
198
214
  node bin/agent-cortex.mjs install copilot # regenerates agents/*.agent.md in place
199
215
  node bin/agent-cortex.mjs install copilot --dry-run # plan only, no writes
200
216
  node bin/agent-cortex.mjs install copilot --output /tmp/x # preview the flat files elsewhere
201
- node bin/agent-cortex.mjs install claude # regenerates ./claude in place
202
- node bin/agent-cortex.mjs install claude --dry-run # plan only, no writes
203
- node bin/agent-cortex.mjs install claude --output /tmp/x # write the subtree elsewhere
217
+ node bin/agent-cortex.mjs install claude # materialises ~/.agent-cortex/claude + marketplace manifest AND registers it with Claude Code (user scope, idempotent)
218
+ node bin/agent-cortex.mjs install claude --dry-run # plan generation + registration, no writes/spawns
219
+ node bin/agent-cortex.mjs install claude --require-register # fail (non-zero exit) when the claude CLI can't drive registration
220
+ node bin/agent-cortex.mjs install claude --output /tmp/x # generate only (preview/CI) — no marketplace manifest, no registration
204
221
  ```
205
222
 
206
223
  #### Try it for one session
207
224
 
225
+ Generate a throwaway plugin and point Claude Code at it — no install or registration
226
+ needed:
227
+
208
228
  ```sh
209
- claude --plugin-dir /path/to/agent-cortex/claude
229
+ node bin/agent-cortex.mjs install claude --output /tmp/agent-cortex-claude
230
+ claude --plugin-dir /tmp/agent-cortex-claude
210
231
  # verify what loaded:
211
- claude --plugin-dir /path/to/agent-cortex/claude plugin details agent-cortex
232
+ claude --plugin-dir /tmp/agent-cortex-claude plugin details agent-cortex
212
233
  ```
213
234
 
214
235
  `SKILL.md` edits are picked up live in that session; agent, hook, and MCP changes need
@@ -216,12 +237,34 @@ claude --plugin-dir /path/to/agent-cortex/claude plugin details agent-cortex
216
237
 
217
238
  #### Install persistently (recommended)
218
239
 
219
- The repo ships a marketplace manifest (`.claude-plugin/marketplace.json`) that exposes the
220
- `claude/` subtree. Register it by **absolute path** (a bare `.` is rejected — use an absolute
221
- path or a `./`-prefixed one), then install:
240
+ The plain install does both halves in one step: it materialises the plugin into
241
+ `~/.agent-cortex/claude`, writes `~/.agent-cortex/.claude-plugin/marketplace.json` (the
242
+ home install root doubles as the marketplace root — the manifest exposes `./claude`), and
243
+ registers it with Claude Code by driving the `claude plugin` CLI against that root at
244
+ **user scope** (the `claude plugin install` default, so the plugin is available in every
245
+ session — the recommended persistent flow). Registration is idempotent by state, not by
246
+ exit code: `claude plugin marketplace list --json` picks add-vs-update and
247
+ `claude plugin list --json` picks install-vs-update against the materialised version. A
248
+ fresh install adds the marketplace and installs the plugin; a re-run is the update path
249
+ (`marketplace update`, plus `plugin update` only when a newer version is materialised); a
250
+ repeat install at the same version is a true no-op. It requires the `claude` plugin CLI
251
+ (Claude Code v2+): with a missing or pre-v2 CLI the installer warns and prints the manual
252
+ commands below, exiting 0 — `--require-register` makes registration mandatory and fails
253
+ non-zero when it can't run:
254
+
255
+ ```sh
256
+ agent-cortex install claude # materialise + register (user scope, idempotent)
257
+ agent-cortex install claude --require-register # register or fail the install
258
+ ```
259
+
260
+ `--dry-run` prints the full plan without spawning the claude CLI or writing anything;
261
+ `--output <dir>` generates only, with no marketplace manifest and no registration. The
262
+ equivalent manual registration adds a marketplace root by **absolute path** (a bare `.` is
263
+ rejected) — the home install root (`~/.agent-cortex`) is the marketplace root written by
264
+ the plain install; the repo checkout ships no manifest:
222
265
 
223
266
  ```sh
224
- claude plugin marketplace add /path/to/agent-cortex
267
+ claude plugin marketplace add ~/.agent-cortex # after a plain install
225
268
  claude plugin install agent-cortex@jaybeeuu # every session (user scope)
226
269
  # or, for this project only:
227
270
  claude plugin install agent-cortex@jaybeeuu --scope local
@@ -232,16 +275,24 @@ flag, and Ralph is just `claude --agent agent-cortex:ralph`.
232
275
 
233
276
  #### Update
234
277
 
235
- The marketplace source is your local checkout, so after pulling changes you must rebuild the
236
- `claude/` subtree and refresh the plugin:
278
+ The plain install re-materialises from the current sources, so after pulling changes
279
+ re-run it — it refreshes the materialised plugin and re-registers whatever the installed
280
+ state says is out of date (`marketplace update`, plus `plugin update` only when a newer
281
+ version is materialised; a repeat install at the same version is a no-op) in one step:
237
282
 
238
283
  ```sh
239
284
  git pull
240
- pnpm build:claude # alias of agent-cortex install claude
241
- claude plugin marketplace update jaybeeuu
242
- claude plugin update agent-cortex # restart Claude Code to apply
285
+ agent-cortex install claude # re-materialise + refresh (restart Claude Code to apply)
243
286
  ```
244
287
 
288
+ Registration matches the marketplace by **name**, not path: a marketplace previously added
289
+ from a different root is refreshed in place rather than re-pointed at the fresh home
290
+ install. Re-point it with
291
+ `claude plugin marketplace remove jaybeeuu` and re-run the install.
292
+
293
+ The plain install IS the update — there is no separate build step. (`--output <dir>` only
294
+ generates a preview and never refreshes an installed plugin.)
295
+
245
296
  #### Uninstall
246
297
 
247
298
  ```sh
@@ -265,7 +316,7 @@ The lean **Ralph** runs as the interactive main agent (not delegated — it must
265
316
  receive its workers' completions):
266
317
 
267
318
  ```sh
268
- claude --agent agent-cortex:ralph # (add --plugin-dir .../claude if not installed)
319
+ claude --agent agent-cortex:ralph # (omitted once installed via agent-cortex install claude; else --plugin-dir ~/.agent-cortex/claude)
269
320
  ```
270
321
 
271
322
  It finds ready beads, spawns parallel background workers (implement → independent review →
@@ -297,12 +348,16 @@ extension→hook audit.
297
348
 
298
349
  Edit the **sources** — the composable `agents/<name>/` directories (shared `agent.md` +
299
350
  per-harness frontmatter/sections, auto-composed by `scripts/build-copilot-agents.mjs` and
300
- the install-time generator `bin/installers/claude.mjs`), `agents-native/*.md` (Claude-only
351
+ `bin/installers/claude.mjs`), `agents-native/*.md` (Claude-only
301
352
  agents like `ralph` — the canonical bodies the installer copies verbatim), `skills/**`,
302
- `hooks/claude/hooks.json` (hook config), and `package.json` (plugin
303
- version) — then run `pnpm build:claude` (an alias of `agent-cortex install claude`). Never hand-edit
304
- anything under `claude/` except the hand-authored `claude/.mcp.json` and `claude/scripts/`
305
- files, or the generated `agents/*.agent.md` files, `claude/agents/`, `claude/skills/`,
306
- `claude/.claude-plugin/plugin.json`, and `claude/hooks.json`. CI runs
307
- `git diff --exit-code claude/agents/ claude/skills/ claude/.claude-plugin/plugin.json claude/hooks.json`
308
- and `git diff --exit-code -- 'agents/*.agent.md'` so the generated outputs can never drift.
353
+ `hooks/claude/hooks.json` (hook config), `claude-extras/` (hand-authored `.mcp.json` and
354
+ `scripts/`), and `package.json` (plugin
355
+ version — picked up at install time) — then run
356
+ `agent-cortex install claude` (re-materialises the home plugin and re-registers it;
357
+ `--output <dir>` generates a preview only). There is no committed
358
+ `claude/` output to hand-edit or regenerate: `~/.agent-cortex/claude` is generated in full
359
+ (`.claude-plugin/plugin.json`, `agents/`, `skills/`, `hooks.json`, `.mcp.json`, `scripts/`)
360
+ so never edit anything under it. The generated `agents/*.agent.md` files are still
361
+ drift-checked by CI (`git diff --exit-code -- 'agents/*.agent.md'`), and CI validates the
362
+ Claude materialiser (structural checks on a temp-dir install) so sources and installer can
363
+ never silently diverge.
package/agents/README.md CHANGED
@@ -143,8 +143,8 @@ When composing the final agent file for a specific harness:
143
143
  2. Replace `{{SECTION:name}}` with content from `<harness>/<name>.md`
144
144
  3. `{{TOOL:name}}` and `{{PATH:name}}` are resolved against `token-map.json` — the
145
145
  canonical tool/path/agent names per harness. `scripts/lib/compose-agent.mjs` (used by
146
- `build:copilot` / `build:claude` and by `bin/installers/pi.mjs`) resolves them when
147
- generating the flat files / installing for pi; pi's `agent-modes` extension does the
146
+ `build:copilot` and by `bin/installers/claude.mjs` / `bin/installers/pi.mjs`) resolves them when
147
+ generating the flat files / installing for claude and pi; pi's `agent-modes` extension does the
148
148
  same at runtime. See the `contract` section of `token-map.json` and
149
149
  `token-map.README.md` for the rules.
150
150
 
@@ -209,19 +209,22 @@ flat `agents/*.agent.md` files are built from them:
209
209
  - `scripts/build-copilot-agents.mjs` (`pnpm build:copilot`) composes `agents/*.agent.md` from
210
210
  each agent's `copilot/` harness dir — committed for Copilot CLI, which loads `*.agent.md`
211
211
  from `plugin.json`'s `agents: "agents/"` path.
212
- - `bin/installers/claude.mjs` (`agent-cortex install claude`; `pnpm build:claude` is a pure
213
- alias) composes `claude/agents/*.md` from each agent's `claude/` harness dir (except
214
- `ralph`, which ships natively from `agents-native/ralph.md`, copied verbatim).
212
+ - `bin/installers/claude.mjs` (plain `agent-cortex install claude` materialises the plugin
213
+ into `~/.agent-cortex/claude` and registers it with Claude Code; `--output <dir>` is its
214
+ generate-only form, used by tests/CI) composes the plugin's
215
+ `agents/*.md` from each agent's `claude/` harness dir (except `ralph`, which ships natively
216
+ from `agents-native/ralph.md`, copied verbatim).
215
217
  - The pi harness delivers two ways: the `agent-modes` extension composes `agent.md` +
216
218
  `pi/frontmatter.json` at runtime against `token-map.json`, and `agent-cortex install pi`
217
219
  materialises composed agents + token-substituted skills into `~/.pi/agent` at install
218
220
  time (see README "Pi harness agents & skills").
219
221
 
220
- Never edit the generated flat/claude files by hand — edit the composable directory. CI
221
- regenerates both outputs and fails on drift. Generation is install-time: `claude` ships
222
- via `bin/installers/claude.mjs`, the single generator behind both `agent-cortex install
223
- claude` and the `pnpm build:claude` alias (the committed `claude/` subtree is regenerated
224
- by it and drift-checked, so it can never be stale); `copilot` ships via
222
+ Never edit the generated flat materialised files by hand — edit the composable directory.
223
+ Generation is install-time: `claude` ships
224
+ via `bin/installers/claude.mjs`, the generator behind plain `agent-cortex install claude`
225
+ (which materialises into `~/.agent-cortex/claude` and registers the plugin with Claude
226
+ Code); the repo commits no `claude/` output (hand-authored extras live in `claude-extras/`),
227
+ and CI validates the materialiser with structural checks on a temp-dir install; `copilot` ships via
225
228
  `bin/installers/copilot.mjs`, the shared code path behind both `agent-cortex install
226
229
  copilot` and `scripts/build-copilot-agents.mjs`; `pi` ships via
227
230
  `bin/installers/pi.mjs`, which materialises composed agents + token-substituted skills
@@ -63,7 +63,7 @@ bd dep add <feature-or-task-id> <planning-gate-id> # feature/task depends on p
63
63
 
64
64
  Do not close planning gates in bulk. Only close a gate after the user explicitly confirms that exact feature/task is ready to implement; leave all unconfirmed gates open and blocking.
65
65
 
66
- After creating each bead, invoke **classify-bead** to ensure it has an `implementation-type` label before handing off.
66
+ Before handing off, ensure every bead created in this step carries an `implementation-type` label — check `bd label list <id>` yourself. Do not spawn `classify-bead` here: planning gates were tagged inline above and `create-task` classifies its beads internally. Only invoke it for a bead that genuinely lacks both the label and a `## Type` field.
67
67
 
68
68
  Tag every bead created in this step with `workflow:ralph`:
69
69
 
@@ -71,7 +71,7 @@ bd dep add <feature-or-task-id> <planning-gate-id> # feature/task depends on p
71
71
 
72
72
  Do not close planning gates in bulk. Only close a gate after the user explicitly confirms that exact feature/task is ready to implement; leave all unconfirmed gates open and blocking.
73
73
 
74
- After creating each bead, invoke **classify-bead** to ensure it has an `implementation-type` label before handing off.
74
+ Before handing off, ensure every bead created in this step carries an `implementation-type` label — check `bd label list <id>` yourself. Do not spawn `classify-bead` here: planning gates were tagged inline above and `create-task` classifies its beads internally. Only invoke it for a bead that genuinely lacks both the label and a `## Type` field.
75
75
 
76
76
  Tag every bead created in this step with `workflow:ralph`:
77
77
 
@@ -30,7 +30,7 @@ if (parsed.command === "install") {
30
30
 
31
31
  if (parsed.harness === "pi") {
32
32
  try {
33
- const result = installPi({
33
+ const result = await installPi({
34
34
  dryRun: parsed.dryRun ?? false,
35
35
  warn: () => {}, // warnings surface once in the printed summary
36
36
  ...(parsed.output ? { output: parsed.output } : {}),
@@ -46,15 +46,36 @@ if (parsed.command === "install") {
46
46
 
47
47
  process.stdout.write(`Installing agent-cortex for "${parsed.harness}" harness…\n`);
48
48
 
49
- // claude is the first wired harness: generates the plugin subtree from the
50
- // canonical sources (agents/, agents-native/, skills/, hooks/claude/) via the
51
- // shared installClaude generator — `pnpm build:claude` is an alias of this
52
- // invocation, so there is no separate build-time code path.
49
+ // claude is the first wired harness: a plain `agent-cortex install claude`
50
+ // materialises the plugin into the home install root (~/.agent-cortex/claude)
51
+ // with copied, token-substituted skills, writes the marketplace manifest at
52
+ // ~/.agent-cortex/.claude-plugin/marketplace.json, and registers it with
53
+ // Claude Code (marketplace add → install → update); `--output <dir>` is the
54
+ // generate-only form (tests/CI validation), and there is no committed claude/
55
+ // subtree in the repo anymore.
53
56
  if (parsed.harness === "claude") {
54
57
  // Avoid loading the installer on the help/summary paths and for other harnesses.
55
- const { installClaude } = await import("./installers/claude.mjs");
58
+ const { installClaude, registerClaude } = await import("./installers/claude.mjs");
56
59
  try {
57
- installClaude({ output: parsed.output, dryRun: parsed.dryRun });
60
+ const result = await installClaude({
61
+ dryRun: parsed.dryRun ?? false,
62
+ warn: () => {}, // warnings surface once via result.warnings
63
+ ...(parsed.output ? { output: parsed.output } : {}),
64
+ });
65
+ for (const warning of result.warnings) {
66
+ process.stdout.write(` ⚠ ${warning}\n`);
67
+ }
68
+ // Runtime registration happens only for the plain install — `--output`
69
+ // keeps generating only (documented in --help).
70
+ if (parsed.output === undefined) {
71
+ await registerClaude({
72
+ root: result.marketplaceRoot,
73
+ manifest: result.marketplaceManifest,
74
+ pluginVersion: result.pluginVersion,
75
+ dryRun: parsed.dryRun ?? false,
76
+ requireRegister: parsed.requireRegister ?? false,
77
+ });
78
+ }
58
79
  process.exit(0);
59
80
  } catch (err) {
60
81
  process.stderr.write(`Install failed: ${err.message}\n`);
@@ -68,7 +89,7 @@ if (parsed.command === "install") {
68
89
  if (parsed.harness === "copilot") {
69
90
  const { installCopilot } = await import("./installers/copilot.mjs");
70
91
  try {
71
- installCopilot({ output: parsed.output, dryRun: parsed.dryRun });
92
+ await installCopilot({ output: parsed.output, dryRun: parsed.dryRun });
72
93
  process.exit(0);
73
94
  } catch (err) {
74
95
  process.stderr.write(`Install failed: ${err.message}\n`);