command-code 1.87.0 → 1.87.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # command-code
2
2
 
3
+ ## 1.87.2
4
+
5
+ ### Patch Changes
6
+
7
+ - fix: cmd acp can load --mod and mod options
8
+ - fix: invalid reasoning effort no longer fails every request.
9
+ - fix: stop re-setting the process name every 5 seconds, which on macOS made each open session trigger a LaunchServices check-in every 5s and drove `launchservicesd` CPU up with many sessions open
10
+ - fix: show the provider's real error message (e.g. "Overloaded") when a stream fails mid-flight instead of "Stream failed: [object Object]" / "Connection error"
11
+
12
+ ## 1.87.1
13
+
14
+ ### Patch Changes
15
+
16
+ - fix: warn and exit instead of crashing when the disk is full
17
+ - fix: sub agent token count display in feed
18
+
3
19
  ## 1.87.0
4
20
 
5
21
  ### Minor Changes
@@ -30,6 +30,44 @@ Always wrap your query in quotes. Unquoted multi-word queries cause argument par
30
30
 
31
31
  ---
32
32
 
33
+ ## Authentication
34
+
35
+ On your own machine, `cmd login` once and headless runs reuse that login. For non-interactive environments (CI pipelines, Docker images, scheduled jobs, SSH boxes without a browser), [create an API key](https://commandcode.ai/docs/studio#api-keys) and export it as the `COMMAND_CODE_API_KEY` environment variable. The CLI reads the env var at startup and uses it as the auth token. No need to run `cmd login` or pre-write an `auth.json` file.
36
+
37
+ **Set the API key**
38
+
39
+ ```bash {{ title: 'macOS / Linux' }}
40
+ export COMMAND_CODE_API_KEY="" # add your API key here
41
+ cmd -p "Run my workflow" # already logged in
42
+ ```
43
+
44
+ ```bash {{ title: 'Windows' }}
45
+ $env:COMMAND_CODE_API_KEY = "" # PowerShell: add your API key here
46
+ cmdc -p "Run my workflow" # already logged in
47
+ ```
48
+
49
+ The env var takes precedence over `~/.commandcode/auth.json`. It overrides any local authentication method.
50
+
51
+ Run `cmd status` to confirm. The output shows `Source: $COMMAND_CODE_API_KEY` when the env var is the active credential.
52
+
53
+ ### GitHub Actions
54
+
55
+ Store the key as a repository secret and pass it through `env`:
56
+
57
+ ```yaml
58
+ - name: Install Command Code
59
+ run: npm i -g command-code@latest
60
+
61
+ - name: Run Command Code
62
+ run: cmd -p "review the changes in this PR"
63
+ env:
64
+ COMMAND_CODE_API_KEY: ${{ secrets.COMMAND_CODE_API_KEY }}
65
+ ```
66
+
67
+ Treat the key as a secret: use your CI provider's encrypted-secrets store (GitHub Actions secrets, GitLab CI variables, etc.) rather than committing it to the repo.
68
+
69
+ ---
70
+
33
71
  ## Input methods
34
72
 
35
73
  ### Direct argument
@@ -66,7 +104,7 @@ To enable all tools, pass `--yolo`:
66
104
  cmd -p "fix the lint errors" --yolo
67
105
  ```
68
106
 
69
- > `--dangerously-skip-permissions` is also accepted as an alias.
107
+ > `--dangerously-skip-permissions` is also accepted as an alias. `--permission-mode yolo` does not lift the block in headless mode. Pass `--yolo`.
70
108
 
71
109
  | **Tool** | **Default (no flag)** | **With `--yolo`** |
72
110
  | -------- | --------------------- | ----------------------------------------- |
@@ -27,12 +27,10 @@ The model catalog — every id `/model`, `--model`, `model:effort` shorthand, an
27
27
  | `zai-org/GLM-5.1` | GLM-5.1 | — | — | $1.4/$4.4 · cache $0.26 | Go and above | long-horizon autonomous coding agent |
28
28
  | `zai-org/GLM-5` | GLM-5 | 200K | — | $1/$3.2 · cache $0.2 | Go and above | multi-mode thinking & long-range planning |
29
29
  | `minimax/minimax-m3.1-flash` | MiniMax M3.1 Flash | 1M | low, medium, high, xhigh, max | $0.15/$0.6 · cache $0.015 | Go and above | multimodal coding with tunable thinking depth |
30
- | `minimax/minimax-m3.1-flash:free` | MiniMax M3.1 Flash | 1M | low, medium, high, xhigh, max | $0/$0 · cache $0 | Go and above | multimodal coding with tunable thinking depth |
31
30
  | `MiniMaxAI/MiniMax-M3` | MiniMax M3 | 1M | low, medium, high | $0.3/$1.2 · cache $0.06 | Go and above | frontier coding, agents & native multimodality |
32
31
  | `MiniMaxAI/MiniMax-M2.7` | MiniMax M2.7 | — | — | $0.3/$1.2 · cache $0.06 | Go and above | end-to-end software engineering agent |
33
32
  | `MiniMaxAI/MiniMax-M2.5` | MiniMax M2.5 | 200K | — | $0.3/$1.2 · cache $0.03 | Go and above | cross-platform full-stack agentic dev |
34
33
  | `ornith/ornith-1.5-122b` | Ornith 1.5 122B | 262K | — | $0.16/$0.64 · cache $0.02 | Go and above | open-weight MoE for fast agentic coding |
35
- | `ornith/ornith-1.5-122b:free` | Ornith 1.5 122B | 262K | — | $0/$0 · cache $0 | Go and above | open-weight MoE for fast agentic coding |
36
34
  | `xiaomi/mimo-v2.6-pro` | MiMo V2.6 Pro | 1.05M | — | $0.435/$0.87 · cache $0.0036 | Go and above | flagship multimodal agentic coding with 1M context |
37
35
  | `xiaomi/mimo-v2.6-pro-ultraspeed` | MiMo V2.6 Pro UltraSpeed | 1.05M | — | $4.35/$8.7 · cache $0.036 | GOAT and above | low-latency serving tier of MiMo V2.6 Pro |
38
36
  | `xiaomi/mimo-v2.6-flash` | MiMo V2.6 Flash | 1.05M | — | $0.14/$0.28 · cache $0.0028 | Go and above | efficient multimodal agentic coding with 1M context |
@@ -140,7 +140,9 @@ cmd --plan # start in plan mode
140
140
  cmd --yolo # yolo (permission bypass) - alias for --dangerously-skip-permissions; use with care
141
141
  ```
142
142
 
143
- `--permission-mode` wins over `--plan`. `--permission-mode yolo` starts in permission bypass, same as `--yolo` / `--dangerously-skip-permissions`; the `disableBypass` kill switch covers all three.
143
+ `--permission-mode` wins over `--plan`. In an interactive session, `--permission-mode yolo` starts in permission bypass, same as `--yolo` / `--dangerously-skip-permissions`; the `disableBypass` kill switch covers all three.
144
+
145
+ Print mode (`-p`) is different. It blocks file writes, file edits, and shell commands unless you pass `--yolo` or `--dangerously-skip-permissions`. `--permission-mode yolo` sets the mode but does not lift that block, so a headless run that needs to change files takes `--yolo`. See [headless permissions](./headless.md#permissions).
144
146
 
145
147
  A mode switch also answers a prompt already on screen: `accept-edits` or `yolo` **approves** it (you said "stop asking"); `plan` **denies** it. A safety-forced prompt - destructive command, sensitive file, explicit `ask` rule - is never answered this way; it stays put for an explicit yes/no.
146
148
 
@@ -367,7 +367,7 @@ A client-side URL guard rejects credentials-in-URL, private/loopback/link-local
367
367
 
368
368
  ## Artifacts
369
369
 
370
- `artifact_publish` and `artifact_manage` publish an HTML page as a link to open and share. Their parameters are on [Artifact tools](https://commandcode.ai/docs/artifacts/tools).
370
+ `artifact_publish` and `artifact_manage` publish an HTML page as a link to open and share. Their parameters are on [Artifacts](https://commandcode.ai/docs/artifacts#tools).
371
371
 
372
372
  ---
373
373
 
@@ -23,7 +23,7 @@ Two resources ship next to this file — use them instead of searching the codeb
23
23
  - `reference/api.md` — ModApi reference
24
24
  - `reference/hooks-and-events.md` — Hooks and events
25
25
  - `reference/ui.md` — UI surface
26
- - `reference/packaging.md` — Packaging and install
26
+ - `reference/packaging.md` — Install and share mods
27
27
  - `reference/verify.md` — Verify a mod
28
28
  <!-- generated:reference-index:end -->
29
29
 
@@ -22,7 +22,9 @@
22
22
  | `cmd.process` | `ModProcessApi` | `spawn` - run a process and stream its output as it arrives |
23
23
  | `cmd.audio` | `ModAudioApi` | `play` / `bell` - sound files shipped with the mod, and the terminal bell |
24
24
 
25
- ## Registration (factory-time; each returns `Disposable`)
25
+ ## Registration methods
26
+
27
+ Call these while the mod's factory runs. Each one returns a `Disposable`.
26
28
 
27
29
  | Method | Signature |
28
30
  |---|---|
@@ -50,9 +52,11 @@ What each does:
50
52
  - `cmd.addAgent(definition)` - a sub-agent type the model can delegate to through the `task` tool, next to the bundled and on-disk agents. `tools` defaults to `'*'`. An agent name that already exists (bundled, project, user, or another mod's) is skipped with a warning. Read live, so a reload's agents show up on the next turn.
51
53
  - `cmd.expose(name, fn)` / `cmd.use(mod, name)` - share a function with other mods and call one another mod shared. `use` answers `undefined` until that mod has loaded and exposed the name, so call it from a hook or command, not only at factory time.
52
54
  - `cmd.addShortcut(keys, {description, handler})` - a keyboard shortcut in the interactive TUI. `keys` is a `modifier+key` chord that **must include Ctrl or Alt** (`alt+r`, `ctrl+r`); a modifier-less or Shift-only chord (`p`, `enter`, `shift+p`) is rejected with a warning, because it would also type into the prompt, and so is a `Ctrl+Shift` chord whose key reaches the terminal as a bare control byte — letters, digits, Enter, Tab, Backspace (`ctrl+shift+p`, `ctrl+shift+enter`) — where the Shift never arrives (arrow / navigation keys keep their modifiers, so `ctrl+shift+up` is fine). `ctrl+m`, `ctrl+i`, `ctrl+h` and `ctrl+[` are rejected too: terminals send them as Enter, Tab, Backspace and Escape. A chord a built-in already owns (`ctrl+c`, `ctrl+o`, an editor key like `ctrl+k`) is rejected the same way — the host's own bindings run first, so it would never fire — and so are the keys the prompt handles itself (`alt+w`, `ctrl+z`, `ctrl+g`, `ctrl+s`, `ctrl+v`, `alt+v`), which stay taken even when rebound. The handler gets the same `{args, ui, cwd, exec}` context a command handler does and may return the same `{message}` / `{prompt}` result. The host dispatches mod shortcuts AFTER its own bindings, so a mod can add keys but never shadow interrupt, exit, mode cycling, or the transcript toggles; `Esc` stays host-owned. First registration per chord wins across mods; `/hotkeys` lists them under **Mods**. Headless hosts never fire shortcuts.
53
- - `cmd.addSkillsPath(path)` - an extra skills location (one skill directory, or a directory of skills) for this session's skill discovery. Relative paths resolve against the mod's own file, so a package can point at the `./skills` it ships. Collected at factory time. A package can declare the same thing without code through its manifest - see [What a package ships](./packaging.md#what-a-package-ships).
55
+ - `cmd.addSkillsPath(path)` - an extra skills location (one skill directory, or a directory of skills) for this session's skill discovery. Relative paths resolve against the mod's own file, so a package can point at the `./skills` it ships. Collected at factory time. A package can declare the same thing without code through its manifest - see [Turn a mod into a package](./packaging.md#turn-a-mod-into-a-package).
56
+
57
+ ## Live methods
54
58
 
55
- ## Live methods (any time after the harness binds)
59
+ These work any time after the harness binds to the mod host.
56
60
 
57
61
  | Method | Signature |
58
62
  |---|---|
@@ -92,7 +96,7 @@ Details:
92
96
  - `cmd.isIdle()` - `false` while an agent run is in flight on the bound harness (`run_start` … `run_end`), `true` otherwise and pre-bind.
93
97
  - `cmd.shutdown()` - asks the interactive host to exit once the current turn settles (the same path as `/exit`). Headless: no-op - the print run ends on its own.
94
98
  - `cmd.getToolInfo()` - the registered tools with `description`, `readOnly`, and `active` (per the mod-managed filter) - the descriptive counterpart of `getAllTools()`'s bare names.
95
- - `cmd.session` - the `ModSessionApi` persistence seam (appendCustomEntry / appendCustomMessageEntry / getCustomEntries), undefined until bound. See [ModContext.session - the mods' persistence surface](./hooks-and-events.md#mod-context-session-the-mods-persistence-surface).
99
+ - `cmd.session` - the `ModSessionApi` persistence seam (appendCustomEntry / appendCustomMessageEntry / getCustomEntries), undefined until bound. See [ModContext.session - the mods' persistence surface](./hooks-and-events.md#mod-context-session-saved-mod-data).
96
100
  - `cmd.showEntry(customType, data)` - render a custom entry into the live feed through the renderer registered for that type (unrendered types pretty-print as JSON). The TUI wires the sink; headless runs drop entries. Pair with `cmd.session.appendCustomEntry` when the data should also persist.
97
101
  - `cmd.sessions` - live session controls: `compact()`, `tree()` (the session branch tree as stable `{id, label, children}` nodes), `leafId()`, `navigateTree({targetId, summarize?, customInstructions?})`, and `setLabel({targetId, label})`. These read live harness state, so unlike the buffered setters they throw with a clear message when no session is bound yet.
98
102
  - `cmd.exec({command, args})` - run a process through the harness Runtime (args are shell-quoted).
@@ -107,7 +111,9 @@ Details:
107
111
  - `cmd.ui.copy(text)` - write text to the system clipboard with the same helper `/copy` uses. See [Clipboard and sound](./ui.md#clipboard-and-sound).
108
112
  - `cmd.audio.play({file})` / `cmd.audio.bell()` - play a sound file shipped with the mod, or ring the terminal bell. See [Clipboard and sound](./ui.md#clipboard-and-sound).
109
113
 
110
- ## `ModHooks` (the mutating lifecycle - all optional, all composable)
114
+ ## `ModHooks`: hooks that change behavior
115
+
116
+ Every hook is optional, and hooks from several `cmd.hooks()` calls compose.
111
117
 
112
118
  `transformContext`, `appendSystemPrompt`, `transformSystemPrompt`, `transformMessage`, `transformTextDelta`, `beforeModelRequest`, `beforeToolCall`, `afterToolCall`, `onTurnStart`, `onTurnEnd`, `shouldStopAfterTurn`, `prepareNextTurn`, `onRunEnd`, `onStop`, plus the host-level `transformInput`, `onPermissionRequest`, `onSessionStart`, and `onSessionEnd`.
113
119
 
@@ -6,7 +6,7 @@ The harness's extension seam. A **mod** is a plain object of lifecycle hooks tha
6
6
 
7
7
  A mod may also contribute **tools**, and every hook receives a **`ModContext`** (`{emit, signal, cwd, session?}`) as an extra last argument, so a mod can raise its own events and persist durable state without extra plumbing.
8
8
 
9
- ## Lifecycle - where each hook fires
9
+ ## Where each hook fires
10
10
 
11
11
  One `run()` = one user turn → many model turns ("rounds"). The loop below is the agent loop, verbatim in ordering; mod hooks are marked `◆`, events `→`.
12
12
 
@@ -199,7 +199,7 @@ const persistUntilTestsPass = {
199
199
  };
200
200
  ```
201
201
 
202
- ## `ModContext.session` - the mods' persistence surface
202
+ ## `ModContext.session`: saved mod data
203
203
 
204
204
  The harness's tree-format session store gives mods a durable, per-entry seam onto the SAME append-only file the transcript lives in. Available in a loadable mod as `cmd.session` and inside hooks as `ctx.session`. Two entry kinds:
205
205
 
@@ -276,7 +276,7 @@ One sync sink, fan out with `createEventBus`. Payloads are snapshots - never liv
276
276
  | `interrupted` | abort observed | - |
277
277
  | `run_error` | non-retryable failure | the raw `Error` |
278
278
 
279
- ## Worked example - a write-quota mod
279
+ ## Example: a write quota mod
280
280
 
281
281
  Blocks writes outside an allowlist, counts tool activity durably in modState, and reports at run end. Exercises the block channel, the closure-vs-modState split, and `onRunEnd`.
282
282
 
@@ -164,7 +164,7 @@ It loads on the next session (or `cmd --mod ./review-guard.ts` to try it without
164
164
  | `~/.commandcode/mods/<dir>/` | user | `package.json` manifest → `mods/` dir → `index.ts` |
165
165
  | `<project>/.commandcode/mods/…` | project | same layout; loads only once the workspace is trusted |
166
166
  | settings `mods.paths` | user/project | explicit files/dirs, relative to the settings scope |
167
- | settings `mods.sources` | user/project | installed packages (see [Packaging and install](./packaging.md#packaging-and-install)) |
167
+ | settings `mods.sources` | user/project | installed packages (see [Install and share mods](./packaging.md#install-and-share-mods)) |
168
168
  | `--mod <path>` | session | repeatable; loads ahead of installed, wins name collisions |
169
169
 
170
170
  Dot-entries and `node_modules` are never scanned (the package registry lives under `mods/.registry/` precisely so discovery skips it). Duplicate mod names keep the first and warn. Disable without deleting via settings:
@@ -200,7 +200,7 @@ Some built-ins are **opt-in** and are disabled by default; `cmd mods list --buil
200
200
  {"mods": {"enabled": ["todos"]}}
201
201
  ```
202
202
 
203
- `cmd mods disable <name>` disables the mod. A disable in any settings file wins and keeps the mod disabled. The change takes effect on the next session or `/reload`; see [Enable/Disable a mod](https://commandcode.ai/docs/mods#enabledisable-a-mod).
203
+ `cmd mods disable <name>` disables the mod. A disable in any settings file wins and keeps the mod disabled. The change takes effect on the next session or `/reload`; see [Turn a mod on or off](./packaging.md#turn-a-mod-on-or-off).
204
204
 
205
205
  Built-in mods always win a name collision against a discovered mod of the same name (the loader shadows the file with a warning), and they are compiled in - never jiti-loaded from a writable path, so they are not supply-chain surface. Structural harness mods (workspace, compaction, checkpoints) are load-bearing for correctness and stay unconditional; only the observer-style built-ins above are disable-able.
206
206
 
@@ -239,7 +239,9 @@ Ask for any of these by name or by what you want:
239
239
 
240
240
  ---
241
241
 
242
- ## Boundaries (deliberate)
242
+ ## What mods cannot do
243
+
244
+ These limits are deliberate.
243
245
 
244
246
  - **Hooks mutate, `on` observes.** Event handlers cannot block tools or rewrite context; that is what `cmd.hooks` is for.
245
247
  - **Project mods are trust-gated** like project skills: they load only after the workspace trust prompt, because a mod is arbitrary code. User-scope and `--mod` mods always load. There is no sandbox - install packages you trust. Package installs run npm with `--ignore-scripts` (mods are jiti-loaded TypeScript; they need no build step, so lifecycle scripts are pure attack surface).
@@ -255,12 +257,13 @@ Embedders wire the same machinery directly: `createModHost` + `loadMods` + `crea
255
257
 
256
258
  ---
257
259
 
258
- ## The reference sections
260
+ ## Reference overview
259
261
 
260
262
  The rest of this page is the complete reference, in order:
261
263
 
262
264
  - [ModApi reference](./api.md#mod-api-reference): every field, registration verb, and live method.
263
265
  - [Hooks and events](./hooks-and-events.md#hooks-and-events): the mutating lifecycle, the `AgentEvent` catalog.
264
266
  - [UI surface](./ui.md#ui-surface): dialogs, footer status, editor widgets, custom feed rendering.
265
- - [Packaging and install](./packaging.md#packaging-and-install): `cmd mods add`, manifests, filtering, scopes.
267
+ - [Install and share mods](./packaging.md#install-and-share-mods): `cmd mods add`, packages, filtering, turning mods on and off.
268
+ - [Listing a mod on the mods hub](./packaging.md#listing-a-mod-on-the-mods-hub): get your mod on the Command Code mods hub.
266
269
  - [Verify a mod](./verify.md#verify-a-mod): load it, list it, test it, ship it.
@@ -1,28 +1,28 @@
1
1
  <!-- Generated from the Command Code docs: https://commandcode.ai/docs -->
2
2
 
3
- # Packaging and install
3
+ # Install and share mods
4
4
 
5
- A mod starts life as a loose file in `~/.commandcode/mods/`. When it should be shared - with a team, or the world - it becomes a **package**: an npm package, a git repo, or a local directory that `cmd mods add` installs and Command Code loads on every session.
5
+ A mod starts as a single file in `~/.commandcode/mods/`. To share it with your team or anyone else, turn it into a **package**: an npm package, a git repo, or a local folder. `cmd mods add` installs a package, and Command Code loads it in every session after that.
6
6
 
7
- ## Install, remove, list, update, open
7
+ ## Manage mods from the CLI
8
8
 
9
9
  ```bash
10
- cmd mods add cmd-mod-hi # bare name = npm package
11
- cmd mods add @team/review-mod@1.2.0 # scoped npm name, pinned (npm: prefix optional)
12
- cmd mods add owner/repo@v1 # GitHub shorthand (any git host via git:<host>/…)
13
- cmd mods add ./tools/local-mod # local path, referenced in place
14
- cmd mods add -g owner/repo # user scope instead of project
15
- cmd mods list # alias: cmd mods ls
16
- cmd mods update # reinstall missing, reconcile pinned refs (alias: up)
17
- cmd mods remove owner/repo # alias: cmd mods rm
18
- cmd mods remove fun-stuff # by the name `mods list` prints
19
- cmd mods enable <name> # enable a mod; -g for user level
20
- cmd mods disable <name> # disable a mod; -g for user level
21
- cmd mods open # open the mods dir (project); --user for ~
22
- cmd mods inspect ./some-mod # what it hooks, registers, and reaches (never runs it)
10
+ cmd mods add cmd-mod-hi # npm package (a bare name means npm)
11
+ cmd mods add @team/review-mod@1.2.0 # scoped npm package, pinned to a version
12
+ cmd mods add owner/repo@v1 # GitHub repo (other hosts: git:<host>/…)
13
+ cmd mods add ./tools/local-mod # local folder, used where it is
14
+ cmd mods add -g owner/repo # install for your user instead of this project
15
+ cmd mods list # list installed mods (alias: ls)
16
+ cmd mods update # install anything missing, refresh pinned refs (alias: up)
17
+ cmd mods remove owner/repo # remove by source (alias: rm)
18
+ cmd mods remove fun-stuff # or by the name `mods list` prints
19
+ cmd mods enable <name> # turn a mod on; -g for your user
20
+ cmd mods disable <name> # turn a mod off; -g for your user
21
+ cmd mods open # open this project's mods folder; --user for yours
22
+ cmd mods inspect ./some-mod # show what a mod hooks and reaches, without running it
23
23
  ```
24
24
 
25
- `cmd mods list` prints one line per mod - name, scope, origin - project mods first, then user, then package-provided:
25
+ `cmd mods list` prints one line per mod: its name, its scope, and where it comes from. Project mods come first, then user mods, then mods from packages.
26
26
 
27
27
  ```
28
28
  Mods (2)
@@ -30,17 +30,28 @@ Mods (2)
30
30
  cmd-mod-hi · user · from npm:cmd-mod-hi
31
31
  ```
32
32
 
33
- The origin is the file for a drop-in mod and `from <source>` for a package mod (whose file lives under `.registry/`, which you never edit by hand). Built-in mods are Command Code's own internals and are never listed. Configured package sources stay out of the output entirely unless one needs attention - not installed, or installed but contributing no mods.
33
+ A mod you dropped in shows its file. A mod from a package shows `from <source>`; its files live under `.registry/`, which you never edit by hand. Built-in mods are not listed. A package source only appears when it needs attention: it is not installed yet, or it installed but added no mods.
34
34
 
35
- `remove` (`rm`) takes **either** a source or the mod NAME `cmd mods list` prints, and removes whatever backs that name: a drop-in file or directory is deleted from the mods dir, a package-provided mod removes its source (and says which sibling mods went with it), a `mods.paths` mod drops its settings entry. Scope follows where the mod actually lives, so a user-scope mod does not need `-g`; a source that is configured in neither scope reports that instead of a silent success.
35
+ **Removing.** `cmd mods remove` takes either a source or a mod name from `cmd mods list`, and removes whatever provides it:
36
36
 
37
- `cmd mods open` opens the drop-in mods directory - `<project>/.commandcode/mods` by default, `~/.commandcode/mods` with `--user` (`-g`) - creating it if it does not exist yet. `--path` prints the directory instead of opening it.
37
+ - a dropped-in file or folder is deleted from the mods folder;
38
+ - a mod from a package removes that package, and tells you which other mods went with it;
39
+ - a `mods.paths` mod has its settings entry removed.
38
40
 
39
- A source with no slash is an npm package name, and so is a `@scope/name` - git shorthand always carries an `owner/repo` slash, so `npm:` is optional (an explicit `git:` prefix always wins). Sources persist in the `mods.sources` settings key (project scope writes `.commandcode/settings.json`, `-g` writes `~/.commandcode/settings.json`). Identity is version/ref-agnostic - `owner/repo@v1` and `https://github.com/owner/repo` are the same package, and a project entry shadows the same identity at user scope. Installs land in `<scope>/.commandcode/mods/.registry/{npm,git}/…`; startup never runs npm/git on its own - a configured-but-missing package is a warning pointing at `cmd mods update`.
41
+ It finds the right scope on its own, so a user mod does not need `-g`. If the source is not installed in either scope, it tells you so.
40
42
 
41
- ## What a package ships
43
+ **Opening the folder.** `cmd mods open` opens `<project>/.commandcode/mods`, or `~/.commandcode/mods` with `--user` (`-g`), and creates it if needed. `--path` prints the folder instead of opening it.
42
44
 
43
- A package declares what it ships via `package.json` - exact paths, directories, or globs (expanded against the package root; entries escaping the root are dropped):
45
+ **How sources are read and saved.**
46
+
47
+ - A source without a slash, or a `@scope/name`, is an npm package, so the `npm:` prefix is optional. A `git:` prefix always means git.
48
+ - Sources are saved in the `mods.sources` settings key: `.commandcode/settings.json` for the project, `~/.commandcode/settings.json` with `-g`.
49
+ - Versions and refs do not change what a source is: `owner/repo@v1` and `https://github.com/owner/repo` are the same package. A project entry takes priority over the same package at the user level.
50
+ - Packages install into `<scope>/.commandcode/mods/.registry/{npm,git}/…`. Startup never runs npm or git by itself. A package that is configured but not installed shows a warning that points at `cmd mods update`.
51
+
52
+ ## Turn a mod into a package
53
+
54
+ List what the package contains in `package.json`. Entries can be exact paths, folders, or globs, relative to the package root. Entries that point outside the root are ignored.
44
55
 
45
56
  ```json
46
57
  {
@@ -55,55 +66,15 @@ A package declares what it ships via `package.json` - exact paths, directories,
55
66
  }
56
67
  ```
57
68
 
58
- Include the `cmd-mod` keyword so maintainers can find the package during review.
59
- Kind keywords such as `cmd-mod-tool` and `cmd-mod-hook` help describe it, but the
60
- hub's categories and summary come from its reviewed registry entry. Publishing
61
- to npm does not list a package on the [mods hub](https://commandcode.ai/mods).
62
-
63
- No manifest → the `mods/` convention directory → a root `index.ts`, in that order.
64
-
65
- `commandcode.skills` lists skill directories the package ships beside its mods (each entry is one skill directory or a directory of skills, relative to the package root; entries escaping the root are dropped). They join skill discovery for every session the package loads in, so one `cmd mods add` brings the mods and the skills that go with them. A mod can contribute the same thing from code with `cmd.addSkillsPath`.
66
-
67
- After publishing, submit an entry to the public registry for review. Listed npm
68
- packages get live monthly downloads, latest version, and publish date from npm.
69
- A GitHub `repo` in the registry entry adds its star count.
70
-
71
- ## Listing a mod on the hub
72
-
73
- The [hub](https://commandcode.ai/mods) lists the reviewed entries in
74
- `mods/registry.json` in the public
75
- [`CommandCodeAI/command-code`](https://github.com/CommandCodeAI/command-code) repo.
76
- Open a PR against that file for either an npm or a GitHub mod. Maintainers review
77
- npm candidates before adding them to the list. The hub automatically fetches
78
- GitHub entries and approved npm entries from this file within about 15 minutes
79
- of a merge, without a website deployment.
80
-
81
- ```json
82
- {
83
- "version": 1,
84
- "hidden": [],
85
- "mods": [
86
- {
87
- "name": "review-guard",
88
- "source": "owner/review-guard",
89
- "description": "Blocks risky diffs and adds a /review command.",
90
- "author": {"name": "Ada", "github": "ada"},
91
- "repo": "https://github.com/owner/review-guard",
92
- "kinds": ["tool", "command"],
93
- "tags": ["safety", "review"],
94
- "official": false
95
- }
96
- ]
97
- }
98
- ```
69
+ Without `commandcode.mods`, Command Code looks for a `mods/` folder, then a root `index.ts`.
99
70
 
100
- `name`, `source` (what `cmd mods add <source>` takes), `description` (≤240 chars), `author.name`, and at least one `kinds` value (`tool`/`command`/`hook`/`provider`/`renderer`/`flag`) are required; `repo`, `npm`, `tags`, `official`, and `addedAt` are optional. A GitHub `repo` adds a live star count, `npm` names the published package for live metadata and download counts, `official` marks a team-maintained mod, and a `hidden` name (a mod or an npm package) keeps spam or impersonation off the hub. The public schema is `mods/registry.schema.json`.
71
+ `commandcode.skills` lists skill folders the package ships next to its mods. Each entry is one skill folder or a folder of skills, relative to the package root. They load in every session the package loads in, so one `cmd mods add` brings both the mods and their skills. A mod can add skills from code too, with `cmd.addSkillsPath`.
101
72
 
102
- The reviewed list, with live npm metadata and GitHub star counts, is served at [`commandcode.ai/mods.json`](https://commandcode.ai/mods.json), CORS-open, so the CLI or any script can read the same list the hub renders.
73
+ Add the `cmd-mod` keyword so maintainers can find your package. Kind keywords such as `cmd-mod-tool` and `cmd-mod-hook` describe it further. Publishing to npm does not put your mod on the Command Code mods hub by itself. To list it, see [Listing a mod on the mods hub](#listing-a-mod-on-the-mods-hub).
103
74
 
104
- ## Filtering a source's mods
75
+ ## Load only some mods from a package
105
76
 
106
- A `mods.sources` entry can be the object form to load only part of a package:
77
+ To load part of a package, use the object form of a `mods.sources` entry:
107
78
 
108
79
  ```json
109
80
  {
@@ -115,24 +86,31 @@ A `mods.sources` entry can be the object form to load only part of a package:
115
86
  }
116
87
  ```
117
88
 
118
- Four pattern kinds, applied in precedence order: `-path` force-exclude (exact, beats everything) → `+path` force-include (exact, restores what globs dropped) → `!glob` exclude → plain-glob include (when any includes exist, an entry must match one). Patterns match the entry's package-relative path or its mod name. `cmd mods add` / `remove` preserve hand-written object entries - they never flatten your filters.
89
+ Patterns match a file's path inside the package, or its mod name. There are four kinds, applied in this order:
119
90
 
120
- ## Enable/Disable a mod
91
+ 1. `-path` always excludes that exact path, and beats everything else.
92
+ 2. `+path` always includes that exact path, even if a glob dropped it.
93
+ 3. `!glob` excludes matches.
94
+ 4. A plain glob includes matches. When any includes exist, a mod must match one of them.
121
95
 
122
- `cmd mods disable <name>` disables a mod without removing it, and `cmd mods enable <name>` enables it again. Both write the project level (`.commandcode/settings.json`) by default, or the user level (`~/.commandcode/settings.json`) with `-g` flag, and take effect on the next session or `/reload`:
96
+ `cmd mods add` and `cmd mods remove` keep entries you wrote by hand, filters included.
97
+
98
+ ## Turn a mod on or off
99
+
100
+ `cmd mods disable <name>` turns a mod off without removing it, and `cmd mods enable <name>` turns it back on. Both write to the project settings (`.commandcode/settings.json`) by default, or to your user settings (`~/.commandcode/settings.json`) with `-g`. The change applies on the next session or after `/reload`.
123
101
 
124
102
  ```bash
125
- cmd mods disable review-guard # disable in this project
126
- cmd mods enable review-guard -g # enable at the user level
103
+ cmd mods disable review-guard # off in this project
104
+ cmd mods enable review-guard -g # on for your user
127
105
  ```
128
106
 
129
- They work for discovered files, installed packages, and the disable-able built-ins (`provider-copilot`, `update-notice`, `titling`, `learning` etc). The `cmd mods disable` command adds the name to `mods.disabled`; `cmd mods enable` removes it from there and, for an opt-in built-in such as `todos`, adds it to `mods.enabled`:
107
+ They work for dropped-in files, installed packages, and the built-ins that can be turned off (`provider-copilot`, `update-notice`, `titling`, `learning`, and others). `disable` adds the name to `mods.disabled`. `enable` removes it from there, and for an opt-in built-in such as `todos` it also adds the name to `mods.enabled`:
130
108
 
131
109
  ```json
132
110
  {"mods": {"disabled": ["review-guard"], "enabled": ["todos"]}}
133
111
  ```
134
112
 
135
- Disabling a mod anywhere will keep a mod disabled. Command Code reads the user, project, and project-local (`.commandcode/settings.local.json`) settings file, and a `mods.disabled` entry in any of them keeps the mod off, even when another file enables it. So when another settings file still disables the mod you enable, the command does not report success: it names that file, gives the one fix, and exits 1 so a script's `&&` chain stops:
113
+ A disable in any settings file wins. Command Code reads the user, project, and project local (`.commandcode/settings.local.json`) settings, and a `mods.disabled` entry in any of them keeps the mod off, even if another file turns it on. So if another file still disables the mod you enable, the command does not report success. It names that file, gives the fix, and exits with code 1 so a script's `&&` chain stops:
136
114
 
137
115
  ```bash
138
116
  $ cmd mods enable review-guard
@@ -141,14 +119,14 @@ $ cmd mods enable review-guard
141
119
  To enable it at the user level, run: cmd mods enable review-guard -g
142
120
  ```
143
121
 
144
- A disable in `settings.local.json` has to be removed by hand; no command writes to that file.
122
+ No command writes to `settings.local.json`, so a disable there has to be removed by hand.
145
123
 
146
- **A project you have not used yet:** Project settings are read only once Command Code has run in that project, the same gate project mods follow. Enabling or disabling there still saves the setting, which applies once you start Command Code in the project; use `-g` to apply it at the user level right away. `cmd mods list --builtin` marks a built-in whose state changes then, for example `enabled · disabled once you start Command Code here`.
124
+ **In a project you have not opened yet.** Command Code reads project settings only after it has run in that project, the same rule project mods follow. Enabling or disabling there still saves the setting, and it applies once you start Command Code in the project. Use `-g` to apply it at the user level right away. `cmd mods list --builtin` shows when a built-in will change state, for example `enabled · disabled once you start Command Code here`.
147
125
 
148
126
  ## Trust and safety
149
127
 
150
- - **There is no sandbox** - a mod is arbitrary code that runs with your permissions; install packages you trust.
151
- - **Inspect before you trust** - `cmd mods inspect <path>` reads a mod's source (it never imports it) and lists the hooks it registers, what it adds, and what it can reach: processes, the network, the filesystem, the environment, permission answers, transcript rewrites. It is a lexical scan, so code a mod imports or names it builds at runtime can reach further, and the report says so.
128
+ - **There is no sandbox.** A mod is code that runs with your permissions, so only install packages you trust.
129
+ - **Inspect before you trust.** `cmd mods inspect <path>` reads a mod's source without importing it, and lists the hooks it registers, what it adds, and what it can reach: processes, the network, the filesystem, the environment, permission answers, and transcript rewrites. It only reads the text, so code the mod imports or builds at runtime can reach further, and the report says so.
152
130
 
153
131
  ```bash
154
132
  $ cmd mods inspect ./permission-policy.ts
@@ -159,7 +137,51 @@ reaches: answers permission prompts (onPermissionRequest)
159
137
  imports: none
160
138
  ```
161
139
 
162
- - **Kill switches** - `cmd --safe-mode` loads built-in mods only for one session (no installed mods, no `--mod`); `{"mods": {"disableAll": true}}` in any settings file does the same for every session until removed.
163
- - **Project mods are trust-gated** like project skills: they load only after the workspace trust prompt. User-scope and `--mod` mods always load.
164
- - **Package installs run npm with `--ignore-scripts`** - mods are jiti-loaded TypeScript; they need no build step, so lifecycle scripts are pure attack surface.
165
- - **Print mode loads user-scope and `--mod` mods only.** Project mods stay out of headless runs because print never shows a trust prompt; pass `--dangerously-skip-permissions` to opt a repo's own mods into a headless run (CI).
140
+ - **Kill switches.** `cmd --safe-mode` loads only built-in mods for one session (no installed mods, no `--mod`). `{"mods": {"disableAll": true}}` in any settings file does the same for every session until you remove it.
141
+ - **Project mods need workspace trust**, like project skills. They load only after you accept the workspace trust prompt. User mods and `--mod` mods always load.
142
+ - **Packages install with `npm --ignore-scripts`.** Mods are TypeScript loaded directly, so they need no build step, and install scripts would only add risk.
143
+ - **Print mode loads only user mods and `--mod` mods.** Print mode never shows a trust prompt, so project mods stay out of headless runs. Pass `--dangerously-skip-permissions` to include a repo's own mods in a headless run, for example in CI.
144
+
145
+ # Listing a mod on the mods hub
146
+
147
+ The [Command Code mods hub](https://commandcode.ai/mods) lists the reviewed entries in `mods/registry.json` in the public [`CommandCodeAI/command-code`](https://github.com/CommandCodeAI/command-code) repo. Every mod on the mods hub needs an entry there, whether it is published to npm or lives on GitHub. Publishing a package or adding a keyword does not list it.
148
+
149
+ To list your mod:
150
+
151
+ 1. Publish it to npm or push it to a public GitHub repo. Check that `package.json` has the right mod entry points, description, and repository.
152
+ 2. Open a PR that adds one entry to [`mods/registry.json`](https://github.com/CommandCodeAI/command-code/blob/main/mods/registry.json). For an npm mod, set both `source` and `npm` to the full package name, including its scope.
153
+ 3. Maintainers review the published code. Once the PR is merged, the mods hub picks up the change within about 15 minutes, with no website deploy.
154
+
155
+ ```json
156
+ {
157
+ "version": 1,
158
+ "hidden": [],
159
+ "mods": [
160
+ {
161
+ "name": "review-guard",
162
+ "source": "owner/review-guard",
163
+ "description": "Blocks risky diffs and adds a /review command.",
164
+ "author": {"name": "Ada", "github": "ada"},
165
+ "repo": "https://github.com/owner/review-guard",
166
+ "kinds": ["tool", "command"],
167
+ "tags": ["safety", "review"]
168
+ }
169
+ ]
170
+ }
171
+ ```
172
+
173
+ | Field | Required | What it does |
174
+ |---|:---:|---|
175
+ | `name` | yes | Unique lowercase name the mods hub shows |
176
+ | `source` | yes | What `cmd mods add <source>` installs: an npm name or `owner/repo` |
177
+ | `description` | yes | The summary on the mods hub card, up to 240 characters |
178
+ | `author.name` | yes | Who made it. Add `author.github` to link your profile |
179
+ | `kinds` | yes | At least one of `tool`, `command`, `hook`, `provider`, `renderer`, `flag` |
180
+ | `repo` | no | A GitHub URL. Adds a live star count |
181
+ | `npm` | no | The published npm package. Adds the latest version, publish date, and monthly downloads |
182
+ | `tags` | no | Lowercase search tags |
183
+ | `addedAt` | no | `YYYY-MM-DD`, used to sort by newest |
184
+
185
+ `official` marks a mod the Command Code team maintains, and the top level `hidden` list keeps spam or impersonation off the mods hub. Both are set by maintainers only. The full schema is `mods/registry.schema.json`.
186
+
187
+ The mods hub's list, with live npm data and GitHub star counts, is also served at [`commandcode.ai/mods.json`](https://commandcode.ai/mods.json). It allows requests from any origin, so the CLI or any script can read the same list the mods hub shows.
@@ -58,14 +58,9 @@ cmd -p "exercise the mod" --mod ./your-mod.ts
58
58
 
59
59
  Print mode loads user-scope and `--mod` mods with the UI bridge degraded to deterministic defaults (confirm → false, select/input → undefined). A mod that must work in CI should behave sensibly under those defaults.
60
60
 
61
- ## 6. Submit the published mod for review
62
-
63
- Include `cmd-mod` in your package's keywords so maintainers can discover it.
64
- Before publishing, check `package.json` for the correct mod entrypoints,
65
- description, and repository. Publish with `pnpm publish`, then open a PR adding
66
- an entry to the public [`mods/registry.json`](https://github.com/CommandCodeAI/command-code/blob/main/mods/registry.json).
67
- Set `source` and `npm` to the full package name for an npm mod. Publishing or
68
- adding a keyword alone does not list it on the hub.
61
+ ## 6. List it on the mods hub
62
+
63
+ Publish the mod, then add it to the Command Code mods hub with a PR to the public registry. See [Listing a mod on the mods hub](./packaging.md#listing-a-mod-on-the-mods-hub) for the steps and fields.
69
64
 
70
65
  ## Working from the bundled examples
71
66