@jaybeeuu/agent-cortex 1.39.0 → 1.41.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.
- package/.agents/skills/style-versioning/SKILL.md +1 -1
- package/.github/workflows/ci.yml +47 -14
- package/AGENTS.md +35 -8
- package/CHANGELOG.md +60 -0
- package/README.md +174 -97
- package/agents/README.md +14 -11
- package/bin/agent-cortex.mjs +55 -10
- package/bin/installers/claude.mjs +674 -174
- package/bin/installers/copilot.mjs +13 -18
- package/bin/installers/pi.mjs +293 -51
- package/claude/settings.json +4 -0
- package/{claude → claude-extras}/scripts/statusline-command.sh +32 -4
- package/docs/claude-hooks.md +15 -3
- package/docs/ideas/ban-content-assertion-tests.md +73 -0
- package/docs/ideas/bead-progress-notes-for-session-resumption.md +75 -0
- package/docs/ideas/classify-beads-via-deterministic-script-with-agent-fallback.md +70 -0
- package/docs/ideas/ctx-alias-version-and-update-commands.md +65 -0
- package/docs/ideas/ctx-feedback-command-for-capturing-ideas-from-any-machine.md +67 -0
- package/docs/ideas/deployment-beads-for-post-merge-pipelines.md +36 -0
- package/docs/ideas/design-and-delivery-as-separate-bead-trees/design-and-delivery-as-separate-bead-trees.md +99 -0
- package/docs/ideas/enable-signed-commit-enforcement-changesets-bot-commits-must-be-signed.md +33 -0
- package/docs/ideas/extension-manifests.md +55 -14
- package/docs/ideas/improve-pi-system-prompt.md +5 -2
- package/docs/ideas/map-every-cortex-tool-to-a-real-pi-equivalent.md +95 -0
- package/docs/ideas/record-idea-implementation-questions.md +68 -0
- package/docs/ideas/self-flushing-session.md +72 -0
- package/docs/ideas/state-in-beads-not-md.md +69 -0
- package/docs/ideas/task-session-context.local.md +95 -0
- package/docs/ideas/test-data-creation-helpers.md +92 -0
- package/docs/ideas/test-planning-stage-bead-in-feature-planning.md +68 -0
- package/docs/ideas/worktree-housekeeping-for-closed-beads.md +39 -0
- package/docs/technical-direction/harness-config.md +161 -0
- package/docs/technical-direction/migration-execution-labels.md +60 -23
- package/extensions/agent-guardrails/README.md +45 -0
- package/extensions/agent-guardrails/guardrails.test.ts +42 -0
- package/extensions/agent-guardrails/guardrails.ts +66 -0
- package/extensions/agent-guardrails/index.ts +22 -0
- package/extensions/agent-guardrails/node_modules/.bin/pi +21 -0
- package/extensions/agent-guardrails/node_modules/.bin/tsc +21 -0
- package/extensions/agent-guardrails/node_modules/.bin/tsserver +21 -0
- package/extensions/agent-guardrails/node_modules/.bin/tsx +21 -0
- package/extensions/agent-guardrails/package.json +19 -0
- package/extensions/agent-guardrails/tsconfig.json +12 -0
- package/extensions/agent-modes/README.md +12 -5
- package/extensions/agent-modes/discover.test.ts +30 -7
- package/extensions/agent-modes/discover.ts +1 -1
- package/extensions/agent-modes/index.test.ts +208 -0
- package/extensions/agent-modes/index.ts +23 -6
- package/extensions/agent-modes/package.json +1 -1
- package/extensions/skill-stats/index.test.ts +3 -2
- package/lib/cli.mjs +30 -12
- package/lib/pi-packages.mjs +169 -0
- package/package.json +8 -4
- package/pi/settings.json +23 -12
- package/plugin.json +1 -1
- package/scripts/build-copilot-agents.mjs +1 -1
- package/scripts/check-no-sync.mjs +49 -0
- package/scripts/lib/compose-agent.mjs +32 -14
- package/scripts/lib/fs.mjs +31 -0
- package/skills/engineering/grill-with-docs/SKILL.md +1 -1
- package/skills/planning/classify-bead/REFERENCE.md +85 -0
- package/skills/planning/classify-bead/SKILL.md +32 -36
- package/skills/planning/classify-bead/scripts/classify-bead.mjs +292 -0
- package/skills/planning/create-task/SKILL.md +19 -10
- package/skills/planning/write-a-prd/SKILL.md +2 -2
- package/skills/style/style-code/REFERENCE.md +32 -2
- package/skills/style/style-code/SKILL.md +5 -21
- package/skills/style/style-tests/SKILL.md +69 -17
- package/skills/workflow/hitl-collab/SKILL.md +1 -1
- package/skills/workflow/run-pipeline-stage/SKILL.md +13 -1
- package/skills/workflow/run-pipeline-stage/prompts/stage-runner.md +12 -0
- package/test/classify-bead.test.mjs +277 -0
- package/test/claude-installer.test.mjs +199 -139
- package/test/cli.test.mjs +95 -41
- package/test/copilot-installer.test.mjs +92 -82
- package/test/fs.test.mjs +76 -0
- package/test/helpers/fake-claude.mjs +152 -0
- package/test/installer.test.mjs +542 -57
- package/test/pi-installer.test.mjs +457 -102
- package/test/pi-packages.test.mjs +295 -0
- package/token-map.README.md +23 -12
- package/token-map.json +8 -7
- package/.claude-plugin/marketplace.json +0 -16
- package/claude/.claude-plugin/plugin.json +0 -11
- package/claude/agents/plan.md +0 -58
- package/claude/agents/ralph-plan.md +0 -121
- package/claude/agents/ralph.md +0 -193
- package/claude/agents/strategy.md +0 -111
- package/claude/hooks/scripts/notify.mjs +0 -54
- package/claude/hooks.json +0 -38
- /package/{claude → claude-extras}/.mcp.json +0 -0
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/)
|
|
@@ -27,28 +25,26 @@ agent-cortex/
|
|
|
27
25
|
│ ├── style/ # style-code, style-tests, style-comms, style-documentation
|
|
28
26
|
│ └── workflow/ # ralph, run-pipeline-stage, create-task, …
|
|
29
27
|
├── extensions/ # pi extensions (pi only)
|
|
28
|
+
│ ├── agent-guardrails/ # behavioural circuit-breakers in the system prompt
|
|
30
29
|
│ ├── agent-modes/ # switchable agent modes (reads composable agents/)
|
|
31
30
|
│ ├── skill-stats/
|
|
32
31
|
│ └── notify/
|
|
33
|
-
├── pi/ #
|
|
34
|
-
│
|
|
32
|
+
├── pi/ # Committed pi config templates (see below)
|
|
33
|
+
│ ├── settings.json
|
|
34
|
+
│ └── keybindings.json
|
|
35
35
|
├── token-map.json # canonical tool/path/agent names per harness (install-time token substitution)
|
|
36
36
|
├── token-map.README.md # design decisions behind token-map.json
|
|
37
37
|
├── bin/
|
|
38
38
|
│ ├── agent-cortex.mjs # CLI entrypoint
|
|
39
39
|
│ └── installers/
|
|
40
40
|
│ ├── copilot.mjs # shared generator: agent-cortex install copilot + scripts/build-copilot-agents.mjs
|
|
41
|
-
│ └── claude.mjs #
|
|
41
|
+
│ └── claude.mjs # materialises ~/.agent-cortex/claude + ~/.claude/settings.json, registers with Claude Code (--output <dir> = generate-only)
|
|
42
42
|
├── scripts/
|
|
43
43
|
│ └── build-copilot-agents.mjs # thin wrapper over bin/installers/copilot.mjs (regenerates agents/*.agent.md)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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)
|
|
44
|
+
├── claude/ # Committed Claude user-settings template (settings.json) — merged into ~/.claude/settings.json
|
|
45
|
+
└── claude-extras/ # Hand-authored Claude plugin extras
|
|
46
|
+
├── .mcp.json # MCP servers (context7, github) — copied into installs
|
|
47
|
+
└── scripts/ # statusline-command.sh — copied into installs (executable)
|
|
52
48
|
```
|
|
53
49
|
|
|
54
50
|
The same `agents/` and `skills/` power three harnesses (Copilot, pi, Claude Code).
|
|
@@ -61,36 +57,45 @@ install-time and build-time output can never diverge) and committed so Copilot C
|
|
|
61
57
|
The `{{TOOL:...}}` / `{{PATH:...}}` tokens written in agent and skill files are resolved
|
|
62
58
|
per harness at install time from `token-map.json`, the single source of truth for
|
|
63
59
|
canonical tool/path/agent names (see `token-map.README.md` and the `contract` section).
|
|
64
|
-
The
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
60
|
+
The Claude plugin is **materialised** at install time by `bin/installers/claude.mjs`. A
|
|
61
|
+
plain `agent-cortex install claude` copies the plugin into the home install root
|
|
62
|
+
(`~/.agent-cortex/claude`), writes a marketplace manifest at
|
|
63
|
+
`~/.agent-cortex/.claude-plugin/marketplace.json` exposing it, and registers it with
|
|
64
|
+
Claude Code by driving the `claude plugin` CLI — state-checked and idempotent (a fresh
|
|
65
|
+
install adds the marketplace + installs the plugin; a re-run updates what state says is
|
|
66
|
+
out of date; a repeat install at the same version is a no-op; a missing or pre-v2 CLI
|
|
67
|
+
warns and prints the manual registration commands instead of failing). The generated
|
|
68
|
+
`claude/` plugin subtree is never committed (only the `claude/settings.json` template and
|
|
69
|
+
the hand-authored `claude-extras/` are), so CI validates the materialiser itself — a
|
|
70
|
+
temp-dir install plus structural checks:
|
|
71
|
+
|
|
72
|
+
- **Skills** stay single-source — the installer copies each `skills/<group>/<name>/` dir
|
|
73
|
+
flat into `skills/<name>/` (Claude discovers skills only one level deep) with
|
|
74
|
+
`{{TOOL:...}}` / `{{PATH:...}}` tokens substituted against token-map.json's claude
|
|
75
|
+
column — no symlinks, so literal tokens never reach Claude.
|
|
76
|
+
- **Agents** can't be shared files (the frontmatter formats differ), so the materialised
|
|
77
|
+
plugin's `agents/*.md` are composed from the canonical `agents/<name>/` directories' `claude/`
|
|
78
|
+
harness dirs
|
|
77
79
|
(frontmatter.json + section files), exactly like the Copilot flats are composed from their
|
|
78
80
|
`copilot/` dirs. Claude only loads agents from a plugin's default `agents/` dir, so the plugin
|
|
79
|
-
root
|
|
81
|
+
ships them at its own root (default `~/.agent-cortex/claude/agents/`) — isolating them from the
|
|
82
|
+
Copilot `.agent.md` files.
|
|
80
83
|
- **Claude-native agents** that have no Copilot equivalent live in `agents-native/*.md` and are
|
|
81
|
-
copied verbatim into `
|
|
84
|
+
copied verbatim into the materialised plugin's `agents/`. `ralph` is one: it is reimplemented
|
|
85
|
+
for Claude around
|
|
82
86
|
background workers + an independent review gate (the Copilot Ralph's `task`/`read_agent`
|
|
83
87
|
poll loop has no Claude equivalent), so it can't be mechanically converted.
|
|
84
|
-
- **Manifests** are generated too:
|
|
85
|
-
`package.json`, so it never goes stale) and `
|
|
88
|
+
- **Manifests** are generated too: the plugin's `.claude-plugin/plugin.json` (its `version`
|
|
89
|
+
tracks `package.json`, so it never goes stale) and `hooks.json` (copied from the canonical
|
|
86
90
|
`hooks/claude/hooks.json` source), plus any support files under `hooks/claude/` bundled into
|
|
87
|
-
`
|
|
88
|
-
and `
|
|
89
|
-
|
|
91
|
+
the plugin's `hooks/` so hook commands can reach them via `$CLAUDE_PLUGIN_ROOT`. Hand-authored
|
|
92
|
+
extras — `.mcp.json` and `scripts/` — are copied into every install from the `claude-extras/`
|
|
93
|
+
dir, which is their canonical store. See `docs/claude-hooks.md` for the
|
|
94
|
+
extension→hook mapping and the rejections (auto-name, agent-guardrails, skill-stats, subagent, agent-modes).
|
|
90
95
|
|
|
91
96
|
Edit the sources (`agents/<name>/` composable dirs, `agents-native/*.md`, `skills/**`,
|
|
92
|
-
`hooks/claude/`, `package.json`), never
|
|
93
|
-
`agents/*.agent.md` files
|
|
97
|
+
`hooks/claude/`, `claude-extras/`, `package.json`), never the generated
|
|
98
|
+
`agents/*.agent.md` files or anything under the materialised `~/.agent-cortex/claude`.
|
|
94
99
|
|
|
95
100
|
## CI
|
|
96
101
|
|
|
@@ -100,6 +105,15 @@ does its own checkout and `pnpm install` rather than sharing build artifacts fro
|
|
|
100
105
|
the `setup` job — pnpm workspace symlinks don't survive artifact upload/download,
|
|
101
106
|
so artifact sharing would break the workspace resolution that the build depends on.
|
|
102
107
|
|
|
108
|
+
The repo commits no generated `claude/` plugin output, so the `claude-plugin-check` job
|
|
109
|
+
validates the Claude plugin **materialiser** instead of diffing a committed mirror:
|
|
110
|
+
it runs `node bin/agent-cortex.mjs install claude --output <tmp dir>` and checks the
|
|
111
|
+
result structurally — `plugin.json` version tracks `package.json`, every generated and
|
|
112
|
+
hand-authored piece is present, no literal `{{TOOL:...}}`/`{{PATH:...}}` tokens survive,
|
|
113
|
+
and no symlinks leak into the copied tree. The Copilot drift check
|
|
114
|
+
(`pnpm build:copilot` + `git diff --exit-code -- 'agents/*.agent.md'`) still guards the
|
|
115
|
+
committed flat agent files.
|
|
116
|
+
|
|
103
117
|
A separate `changeset-check` job runs only on pull requests and fails any PR that
|
|
104
118
|
touches a versioned path (`extensions/`, `skills/`, `agents/`, `package.json`, or
|
|
105
119
|
`plugin.json`) without a changeset in `.changeset/`. Add one with `pnpm changeset` —
|
|
@@ -109,7 +123,9 @@ On pushes to `main`, a `release` job (gated on `lint`, `test`, and
|
|
|
109
123
|
`claude-plugin-check`) runs changesets to open a `chore: version packages` PR when
|
|
110
124
|
changesets are pending, then publishes to npm once it lands. The version step runs
|
|
111
125
|
`pnpm version-packages` — bumping `package.json`, syncing `plugin.json`, and
|
|
112
|
-
regenerating the committed
|
|
126
|
+
regenerating the committed Copilot agent files (the Claude plugin is materialised at
|
|
127
|
+
install time with the package version, so it has no committed output to regenerate)
|
|
128
|
+
so the drift gates stay green; the
|
|
113
129
|
publish step runs `pnpm publish-package` (pack + provenance publish). Publish
|
|
114
130
|
authenticates via npm Trusted Publishing (OIDC) — no npm token or GitHub
|
|
115
131
|
secret is needed, only the one-time npm-side setup on npmjs.com (package →
|
|
@@ -118,30 +134,51 @@ are sourced entirely from `main`.
|
|
|
118
134
|
|
|
119
135
|
## Installation
|
|
120
136
|
|
|
121
|
-
###
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
### Pi config files (`settings.json` + `keybindings.json`)
|
|
138
|
+
|
|
139
|
+
`agent-cortex install pi` materialises `~/.pi/agent/settings.json` and
|
|
140
|
+
`~/.pi/agent/keybindings.json` as real CLI-managed files — the legacy symlinks
|
|
141
|
+
into this repo's `pi/` directory are gone. `pi/settings.json` and
|
|
142
|
+
`pi/keybindings.json` are the committed **templates**; the live files exist only
|
|
143
|
+
on the machine, so re-run the installer after pulling changes.
|
|
144
|
+
|
|
145
|
+
`settings.json` is merged. The template supplies defaults for keys the live file
|
|
146
|
+
lacks, every value already present in the live file wins, and keys the template
|
|
147
|
+
does not know about are preserved — so personal config (and anything pi itself
|
|
148
|
+
wrote) survives re-install. The one key the CLI owns outright is `packages`: it
|
|
149
|
+
is rebuilt from the template with the repo path entry resolved against the live
|
|
150
|
+
settings file.
|
|
151
|
+
|
|
152
|
+
Two consequences follow from that precedence:
|
|
153
|
+
|
|
154
|
+
- **Template changes to non-`packages` keys never reach an existing install.**
|
|
155
|
+
Because the live value always wins, editing a default in `pi/settings.json`
|
|
156
|
+
only affects a fresh install (or a manually deleted live file) — edit the live
|
|
157
|
+
file to adopt a new default.
|
|
158
|
+
- **`pi install npm:<pkg>` entries do not survive re-install.** `packages` is
|
|
159
|
+
rebuilt from the template, so any `npm:` package pi added to the live file is
|
|
160
|
+
dropped on the next `agent-cortex install pi`. Declare long-lived packages in
|
|
161
|
+
the repo template instead.
|
|
162
|
+
|
|
163
|
+
An unparseable live `settings.json` is warned about and overwritten.
|
|
164
|
+
`keybindings.json` follows a checksum rule: written from the template, refreshed
|
|
165
|
+
when the template changes, and left untouched once you edit it by hand (delete
|
|
166
|
+
it to re-adopt the template).
|
|
137
167
|
|
|
138
168
|
### Pi package dependencies
|
|
139
169
|
|
|
140
|
-
These packages are declared in `
|
|
170
|
+
These packages are declared in the package manifest (`package.json` → `pi.packages`) and
|
|
171
|
+
provisioned by `agent-cortex install pi`, so a clean `~/.pi` gets the tools they provide
|
|
172
|
+
without a manual `pi install`. They are also declared in the template `pi/settings.json`,
|
|
173
|
+
so the materialised `settings.json` registers them with pi.
|
|
141
174
|
|
|
142
175
|
| Package | Version | Purpose |
|
|
143
176
|
|---|---|---|
|
|
144
|
-
| [`pi-web-access`](https://www.npmjs.com/package/pi-web-access) | 0.10.7 | Web search, URL fetching, GitHub repo access, PDF/YouTube/video analysis |
|
|
177
|
+
| [`pi-web-access`](https://www.npmjs.com/package/pi-web-access) | 0.10.7 | Web search, URL fetching, GitHub repo access, PDF/YouTube/video analysis (`fetch_content`) |
|
|
178
|
+
| [`pi-questions`](https://www.npmjs.com/package/pi-questions) | latest | Structured interactive questions (`ask_questions`) |
|
|
179
|
+
|
|
180
|
+
Pass `--no-provision` to skip the package install step (e.g. offline machines); a
|
|
181
|
+
missing `pi` CLI or failed install warns and leaves the rest of the install intact.
|
|
145
182
|
|
|
146
183
|
Desktop notifications are handled by the local `extensions/notify/` extension
|
|
147
184
|
(replaces the former `pi-notify` dependency). It sends an OSC desktop
|
|
@@ -159,6 +196,7 @@ composed agents and token-substituted skills into pi's user scope:
|
|
|
159
196
|
agent-cortex install pi
|
|
160
197
|
# → ~/.pi/agent/agents/<name>.agent.md (ralph, plan, ralph-plan, strategy)
|
|
161
198
|
# → ~/.pi/agent/skills/ (token-substituted skill tree)
|
|
199
|
+
# → ~/.pi/agent/settings.json + keybindings.json (merged from the repo templates)
|
|
162
200
|
```
|
|
163
201
|
|
|
164
202
|
Flags:
|
|
@@ -166,8 +204,9 @@ Flags:
|
|
|
166
204
|
| Flag | Meaning |
|
|
167
205
|
| --- | --- |
|
|
168
206
|
| `--dry-run` | Show what would be installed without writing anything |
|
|
169
|
-
| `--output <dir>` | Install into `<dir>/agents
|
|
207
|
+
| `--output <dir>` | Install into `<dir>/agents`, `<dir>/skills` and the config files (default `~/.pi/agent`) |
|
|
170
208
|
| `--plugin-root <dir>` | Override the plugin root used for `{{PATH:...}}` tokens (default: token-map.json's pi value — use it for checkout or symlinked installs) |
|
|
209
|
+
| `--no-provision` | Skip provisioning the third-party pi packages declared in `package.json` `pi.packages` (default: install them via the `pi` CLI) |
|
|
171
210
|
|
|
172
211
|
Re-run whenever you pull changes (`git pull` + reinstall, or after `pnpm build:copilot`).
|
|
173
212
|
|
|
@@ -185,32 +224,43 @@ copilot plugin install ./agent-cortex
|
|
|
185
224
|
|
|
186
225
|
### Claude Code plugin (separate)
|
|
187
226
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
227
|
+
A plain `agent-cortex install claude` **materialises** the plugin into the home install
|
|
228
|
+
root `~/.agent-cortex/claude` — **4 agents** (`strategy`, `plan`, `ralph-plan`, `ralph`),
|
|
229
|
+
**29 skills** (copied flat per skill, `{{TOOL:...}}` / `{{PATH:...}}` token-substituted — no
|
|
230
|
+
symlinks), `SessionStart` + `Notification` hooks, and 2 MCP servers — writes a marketplace
|
|
231
|
+
manifest at `~/.agent-cortex/.claude-plugin/marketplace.json` exposing `./claude`, and
|
|
232
|
+
registers it with Claude Code, and merges the committed `claude/settings.json` template into
|
|
233
|
+
`~/.claude/settings.json`: the template supplies defaults, personal values win, and the
|
|
234
|
+
installer owns exactly `enabledPlugins` + `extraKnownMarketplaces` — every other key
|
|
235
|
+
(`permissions`, `hooks`, `env`, `statusLine`, unknown keys) is preserved. The only committed
|
|
236
|
+
Claude config is that template plus the hand-authored extras in `claude-extras/`
|
|
237
|
+
(`.mcp.json`, `scripts/`); the plugin subtree is generated at install time — there is nothing
|
|
238
|
+
to drift.
|
|
239
|
+
|
|
240
|
+
The generate-only `--output <dir>` form is for previewing and CI validation; the
|
|
241
|
+
documented path is the plain install to `~/.agent-cortex/claude`:
|
|
195
242
|
|
|
196
243
|
```sh
|
|
197
244
|
pnpm build:copilot # or: node scripts/build-copilot-agents.mjs (regenerates agents/*.agent.md)
|
|
198
|
-
pnpm build:claude # or: node bin/agent-cortex.mjs install claude --output claude (generate-only)
|
|
199
|
-
# or the install-time entry (same generator, less typing):
|
|
200
245
|
node bin/agent-cortex.mjs install copilot # regenerates agents/*.agent.md in place
|
|
201
246
|
node bin/agent-cortex.mjs install copilot --dry-run # plan only, no writes
|
|
202
247
|
node bin/agent-cortex.mjs install copilot --output /tmp/x # preview the flat files elsewhere
|
|
203
|
-
node bin/agent-cortex.mjs install claude #
|
|
248
|
+
node bin/agent-cortex.mjs install claude # materialises ~/.agent-cortex/claude + marketplace manifest AND registers it with Claude Code (user scope, idempotent)
|
|
204
249
|
node bin/agent-cortex.mjs install claude --dry-run # plan generation + registration, no writes/spawns
|
|
205
|
-
node bin/agent-cortex.mjs install claude --
|
|
250
|
+
node bin/agent-cortex.mjs install claude --require-register # fail (non-zero exit) when the claude CLI can't drive registration
|
|
251
|
+
node bin/agent-cortex.mjs install claude --output /tmp/x # generate only (preview/CI) — no marketplace manifest, no registration
|
|
206
252
|
```
|
|
207
253
|
|
|
208
254
|
#### Try it for one session
|
|
209
255
|
|
|
256
|
+
Generate a throwaway plugin and point Claude Code at it — no install or registration
|
|
257
|
+
needed:
|
|
258
|
+
|
|
210
259
|
```sh
|
|
211
|
-
claude --
|
|
260
|
+
node bin/agent-cortex.mjs install claude --output /tmp/agent-cortex-claude
|
|
261
|
+
claude --plugin-dir /tmp/agent-cortex-claude
|
|
212
262
|
# verify what loaded:
|
|
213
|
-
claude --plugin-dir /
|
|
263
|
+
claude --plugin-dir /tmp/agent-cortex-claude plugin details agent-cortex
|
|
214
264
|
```
|
|
215
265
|
|
|
216
266
|
`SKILL.md` edits are picked up live in that session; agent, hook, and MCP changes need
|
|
@@ -218,24 +268,42 @@ claude --plugin-dir /path/to/agent-cortex/claude plugin details agent-cortex
|
|
|
218
268
|
|
|
219
269
|
#### Install persistently (recommended)
|
|
220
270
|
|
|
221
|
-
The
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
271
|
+
The plain install does both halves in one step: it materialises the plugin into
|
|
272
|
+
`~/.agent-cortex/claude`, writes `~/.agent-cortex/.claude-plugin/marketplace.json` (the
|
|
273
|
+
home install root doubles as the marketplace root — the manifest exposes `./claude`), and
|
|
274
|
+
registers it with Claude Code by driving the `claude plugin` CLI against that root at
|
|
275
|
+
**user scope** (the `claude plugin install` default, so the plugin is available in every
|
|
276
|
+
session — the recommended persistent flow). Registration is idempotent by state, not by
|
|
277
|
+
exit code: `claude plugin marketplace list --json` picks add-vs-update and
|
|
278
|
+
`claude plugin list --json` picks install-vs-update against the materialised version. A
|
|
279
|
+
fresh install adds the marketplace and installs the plugin; a re-run is the update path
|
|
280
|
+
(`marketplace update`, plus `plugin update` only when a newer version is materialised); a
|
|
281
|
+
repeat install at the same version is a true no-op. It requires the `claude` plugin CLI
|
|
282
|
+
(Claude Code v2+): with a missing or pre-v2 CLI the installer warns and prints the manual
|
|
283
|
+
commands below, exiting 0 — `--require-register` makes registration mandatory and fails
|
|
284
|
+
non-zero when it can't run:
|
|
226
285
|
|
|
227
286
|
```sh
|
|
228
|
-
|
|
229
|
-
agent-cortex install claude
|
|
287
|
+
agent-cortex install claude # materialise + register (user scope, idempotent)
|
|
288
|
+
agent-cortex install claude --require-register # register or fail the install
|
|
230
289
|
```
|
|
231
290
|
|
|
232
291
|
`--dry-run` prints the full plan without spawning the claude CLI or writing anything;
|
|
233
|
-
`--output <dir>`
|
|
234
|
-
|
|
235
|
-
|
|
292
|
+
`--output <dir>` generates only, with no marketplace manifest and no registration.
|
|
293
|
+
|
|
294
|
+
The install also merges the committed `claude/settings.json` template into
|
|
295
|
+
`~/.claude/settings.json` (the settings file Claude Code reads at user scope). The template
|
|
296
|
+
supplies defaults and personal values win; the installer owns exactly `enabledPlugins` +
|
|
297
|
+
`extraKnownMarketplaces`, so `permissions`, `hooks`, `env`, `statusLine` and unknown keys are
|
|
298
|
+
never touched. A legacy symlinked `settings.json` is replaced with a real file rather than
|
|
299
|
+
written through, and `--output` leaves the user's Claude config alone.
|
|
300
|
+
|
|
301
|
+
The equivalent manual registration adds a marketplace root by **absolute path** (a bare `.` is
|
|
302
|
+
rejected) — the home install root (`~/.agent-cortex`) is the marketplace root written by
|
|
303
|
+
the plain install; the repo checkout ships no manifest:
|
|
236
304
|
|
|
237
305
|
```sh
|
|
238
|
-
claude plugin marketplace add
|
|
306
|
+
claude plugin marketplace add ~/.agent-cortex # after a plain install
|
|
239
307
|
claude plugin install agent-cortex@jaybeeuu # every session (user scope)
|
|
240
308
|
# or, for this project only:
|
|
241
309
|
claude plugin install agent-cortex@jaybeeuu --scope local
|
|
@@ -246,17 +314,23 @@ flag, and Ralph is just `claude --agent agent-cortex:ralph`.
|
|
|
246
314
|
|
|
247
315
|
#### Update
|
|
248
316
|
|
|
249
|
-
The
|
|
250
|
-
it
|
|
251
|
-
plugin update
|
|
317
|
+
The plain install re-materialises from the current sources, so after pulling changes
|
|
318
|
+
re-run it — it refreshes the materialised plugin and re-registers whatever the installed
|
|
319
|
+
state says is out of date (`marketplace update`, plus `plugin update` only when a newer
|
|
320
|
+
version is materialised; a repeat install at the same version is a no-op) in one step:
|
|
252
321
|
|
|
253
322
|
```sh
|
|
254
323
|
git pull
|
|
255
|
-
agent-cortex install claude #
|
|
324
|
+
agent-cortex install claude # re-materialise + refresh (restart Claude Code to apply)
|
|
256
325
|
```
|
|
257
326
|
|
|
258
|
-
|
|
259
|
-
|
|
327
|
+
Registration matches the marketplace by **name**, not path: a marketplace previously added
|
|
328
|
+
from a different root is refreshed in place rather than re-pointed at the fresh home
|
|
329
|
+
install. Re-point it with
|
|
330
|
+
`claude plugin marketplace remove jaybeeuu` and re-run the install.
|
|
331
|
+
|
|
332
|
+
The plain install IS the update — there is no separate build step. (`--output <dir>` only
|
|
333
|
+
generates a preview and never refreshes an installed plugin.)
|
|
260
334
|
|
|
261
335
|
#### Uninstall
|
|
262
336
|
|
|
@@ -281,7 +355,7 @@ The lean **Ralph** runs as the interactive main agent (not delegated — it must
|
|
|
281
355
|
receive its workers' completions):
|
|
282
356
|
|
|
283
357
|
```sh
|
|
284
|
-
claude --agent agent-cortex:ralph # (
|
|
358
|
+
claude --agent agent-cortex:ralph # (omitted once installed via agent-cortex install claude; else --plugin-dir ~/.agent-cortex/claude)
|
|
285
359
|
```
|
|
286
360
|
|
|
287
361
|
It finds ready beads, spawns parallel background workers (implement → independent review →
|
|
@@ -302,7 +376,7 @@ extension→hook audit.
|
|
|
302
376
|
#### Not ported / follow-ups
|
|
303
377
|
|
|
304
378
|
- Only `session-start` and `notify` had Claude equivalents (both ported to hooks); the other
|
|
305
|
-
pi `extensions/` (auto-name, skill-stats, subagent, agent-modes) have none — the audit and
|
|
379
|
+
pi `extensions/` (auto-name, agent-guardrails, skill-stats, subagent, agent-modes) have none — the audit and
|
|
306
380
|
rejection rationale live in `docs/claude-hooks.md`.
|
|
307
381
|
- Ralph follow-ups: multi-feature epic branches, and a GitHub-trigger routine to auto-resume
|
|
308
382
|
after a PR merge (instead of manual re-invocation).
|
|
@@ -313,14 +387,17 @@ extension→hook audit.
|
|
|
313
387
|
|
|
314
388
|
Edit the **sources** — the composable `agents/<name>/` directories (shared `agent.md` +
|
|
315
389
|
per-harness frontmatter/sections, auto-composed by `scripts/build-copilot-agents.mjs` and
|
|
316
|
-
|
|
390
|
+
`bin/installers/claude.mjs`), `agents-native/*.md` (Claude-only
|
|
317
391
|
agents like `ralph` — the canonical bodies the installer copies verbatim), `skills/**`,
|
|
318
|
-
`hooks/claude/hooks.json` (hook config),
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
`claude
|
|
325
|
-
|
|
326
|
-
|
|
392
|
+
`hooks/claude/hooks.json` (hook config), `claude/settings.json` (the user-settings template
|
|
393
|
+
merged into `~/.claude/settings.json`), `claude-extras/` (hand-authored `.mcp.json` and
|
|
394
|
+
`scripts/`), and `package.json` (plugin
|
|
395
|
+
version — picked up at install time) — then run
|
|
396
|
+
`agent-cortex install claude` (re-materialises the home plugin, merges settings, and
|
|
397
|
+
re-registers it; `--output <dir>` generates a preview only). The only committed file under
|
|
398
|
+
`claude/` is the settings template; `~/.agent-cortex/claude` is generated in full
|
|
399
|
+
(`.claude-plugin/plugin.json`, `agents/`, `skills/`, `hooks.json`, `.mcp.json`, `scripts/`)
|
|
400
|
+
so never edit anything under it. The generated `agents/*.agent.md` files are still
|
|
401
|
+
drift-checked by CI (`git diff --exit-code -- 'agents/*.agent.md'`), and CI validates the
|
|
402
|
+
Claude materialiser (structural checks on a temp-dir install) so sources and installer can
|
|
403
|
+
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`
|
|
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,21 +209,24 @@ 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` (plain `agent-cortex install claude`
|
|
213
|
-
with Claude Code;
|
|
214
|
-
|
|
215
|
-
`
|
|
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).
|
|
216
217
|
- The pi harness delivers two ways: the `agent-modes` extension composes `agent.md` +
|
|
217
218
|
`pi/frontmatter.json` at runtime against `token-map.json`, and `agent-cortex install pi`
|
|
218
219
|
materialises composed agents + token-substituted skills into `~/.pi/agent` at install
|
|
219
220
|
time (see README "Pi harness agents & skills").
|
|
220
221
|
|
|
221
|
-
Never edit the generated flat
|
|
222
|
-
|
|
222
|
+
Never edit the generated flat materialised files by hand — edit the composable directory.
|
|
223
|
+
Generation is install-time: `claude` ships
|
|
223
224
|
via `bin/installers/claude.mjs`, the generator behind plain `agent-cortex install claude`
|
|
224
|
-
(which
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
(which materialises into `~/.agent-cortex/claude`, merges the committed
|
|
226
|
+
`claude/settings.json` into `~/.claude/settings.json`, and registers the plugin with Claude
|
|
227
|
+
Code); the only committed `claude/` file is that settings template (hand-authored extras live
|
|
228
|
+
in `claude-extras/`), and CI validates the materialiser with structural checks on a temp-dir
|
|
229
|
+
install; `copilot` ships via
|
|
227
230
|
`bin/installers/copilot.mjs`, the shared code path behind both `agent-cortex install
|
|
228
231
|
copilot` and `scripts/build-copilot-agents.mjs`; `pi` ships via
|
|
229
232
|
`bin/installers/pi.mjs`, which materialises composed agents + token-substituted skills
|
package/bin/agent-cortex.mjs
CHANGED
|
@@ -30,8 +30,12 @@ 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
|
+
// Third-party pi packages are only provisioned for a real install:
|
|
36
|
+
// --output is the generate-only form, --no-provision opts an offline
|
|
37
|
+
// machine out explicitly.
|
|
38
|
+
provisionPackages: parsed.output === undefined && !parsed.noProvision,
|
|
35
39
|
warn: () => {}, // warnings surface once in the printed summary
|
|
36
40
|
...(parsed.output ? { output: parsed.output } : {}),
|
|
37
41
|
...(parsed.pluginRoot ? { pluginRoot: parsed.pluginRoot } : {}),
|
|
@@ -47,21 +51,36 @@ if (parsed.command === "install") {
|
|
|
47
51
|
process.stdout.write(`Installing agent-cortex for "${parsed.harness}" harness…\n`);
|
|
48
52
|
|
|
49
53
|
// claude is the first wired harness: a plain `agent-cortex install claude`
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
54
|
+
// materialises the plugin into the home install root (~/.agent-cortex/claude)
|
|
55
|
+
// with copied, token-substituted skills, writes the marketplace manifest at
|
|
56
|
+
// ~/.agent-cortex/.claude-plugin/marketplace.json, merges the committed
|
|
57
|
+
// claude/settings.json template into ~/.claude/settings.json (owning only
|
|
58
|
+
// enabledPlugins + extraKnownMarketplaces), and registers it with Claude Code
|
|
59
|
+
// (marketplace add → install → update); `--output <dir>` is the generate-only
|
|
60
|
+
// form (tests/CI validation), and the generated claude/ plugin subtree is
|
|
61
|
+
// never committed — only the settings template is.
|
|
56
62
|
if (parsed.harness === "claude") {
|
|
57
63
|
// Avoid loading the installer on the help/summary paths and for other harnesses.
|
|
58
64
|
const { installClaude, registerClaude } = await import("./installers/claude.mjs");
|
|
59
65
|
try {
|
|
60
|
-
|
|
66
|
+
const result = await installClaude({
|
|
67
|
+
dryRun: parsed.dryRun ?? false,
|
|
68
|
+
warn: () => {}, // warnings surface once via result.warnings
|
|
69
|
+
...(parsed.output ? { output: parsed.output } : {}),
|
|
70
|
+
});
|
|
71
|
+
for (const warning of result.warnings) {
|
|
72
|
+
process.stdout.write(` ⚠ ${warning}\n`);
|
|
73
|
+
}
|
|
61
74
|
// Runtime registration happens only for the plain install — `--output`
|
|
62
75
|
// keeps generating only (documented in --help).
|
|
63
76
|
if (parsed.output === undefined) {
|
|
64
|
-
registerClaude({
|
|
77
|
+
await registerClaude({
|
|
78
|
+
root: result.marketplaceRoot,
|
|
79
|
+
manifest: result.marketplaceManifest,
|
|
80
|
+
pluginVersion: result.pluginVersion,
|
|
81
|
+
dryRun: parsed.dryRun ?? false,
|
|
82
|
+
requireRegister: parsed.requireRegister ?? false,
|
|
83
|
+
});
|
|
65
84
|
}
|
|
66
85
|
process.exit(0);
|
|
67
86
|
} catch (err) {
|
|
@@ -76,7 +95,7 @@ if (parsed.command === "install") {
|
|
|
76
95
|
if (parsed.harness === "copilot") {
|
|
77
96
|
const { installCopilot } = await import("./installers/copilot.mjs");
|
|
78
97
|
try {
|
|
79
|
-
installCopilot({ output: parsed.output, dryRun: parsed.dryRun });
|
|
98
|
+
await installCopilot({ output: parsed.output, dryRun: parsed.dryRun });
|
|
80
99
|
process.exit(0);
|
|
81
100
|
} catch (err) {
|
|
82
101
|
process.stderr.write(`Install failed: ${err.message}\n`);
|
|
@@ -93,10 +112,36 @@ function printPiInstall(result) {
|
|
|
93
112
|
process.stdout.write(` ✓ ${agent.name}.agent.md → ${agent.filePath}\n`);
|
|
94
113
|
}
|
|
95
114
|
process.stdout.write(` ✓ Substituted ${result.skills.md} markdown file(s) across ${result.skills.skills} skill(s) → ${result.skills.dir}\n`);
|
|
115
|
+
printManagedConfig("settings.json", result.settings);
|
|
116
|
+
printManagedConfig("keybindings.json", result.keybindings);
|
|
117
|
+
// A dry run installs nothing, so report the plan — otherwise the documented
|
|
118
|
+
// "show what would be installed" contract prints no packages at all.
|
|
119
|
+
const packages = result.packages ?? { planned: [], installed: [] };
|
|
120
|
+
for (const source of result.dryRun ? packages.planned : packages.installed) {
|
|
121
|
+
process.stdout.write(` ✓ ${result.dryRun ? "Would install" : "Installed"} pi package ${source}\n`);
|
|
122
|
+
}
|
|
96
123
|
for (const warning of result.warnings) {
|
|
97
124
|
process.stdout.write(` ⚠ ${warning}\n`);
|
|
98
125
|
}
|
|
99
126
|
if (result.dryRun) {
|
|
100
127
|
process.stdout.write("(dry-run — nothing written)\n");
|
|
101
128
|
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Report one managed pi config file (settings.json / keybindings.json). */
|
|
132
|
+
function printManagedConfig(label, info) {
|
|
133
|
+
if (!info) return;
|
|
134
|
+
if (info.action === "would-remove-symlink") {
|
|
135
|
+
process.stdout.write(` → would remove symlink ${info.path} and write ${label}\n`);
|
|
136
|
+
} else if (info.action === "would-write") {
|
|
137
|
+
process.stdout.write(` → would write ${label} → ${info.path}\n`);
|
|
138
|
+
} else if (info.action === "unchanged") {
|
|
139
|
+
process.stdout.write(` · ${label} → ${info.path} (unchanged)\n`);
|
|
140
|
+
} else if (info.action === "skipped") {
|
|
141
|
+
process.stdout.write(` ⚠ ${label} modified after install — left untouched → ${info.path}\n`);
|
|
142
|
+
} else if (info.action === "removed-symlink") {
|
|
143
|
+
process.stdout.write(` ✓ ${label} → ${info.path} (removed legacy symlink)\n`);
|
|
144
|
+
} else {
|
|
145
|
+
process.stdout.write(` ✓ ${label} → ${info.path}\n`);
|
|
146
|
+
}
|
|
102
147
|
}
|