command-code 1.82.1 → 1.82.3

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,18 @@
1
1
  # command-code
2
2
 
3
+ ## 1.82.3
4
+
5
+ ### Patch Changes
6
+
7
+ - chore: bump deps to latest versions
8
+
9
+ ## 1.82.2
10
+
11
+ ### Patch Changes
12
+
13
+ - feat: retire ling 3.1 flash free
14
+ - feat: Add todo checklist as a built-in mod, disabled by default
15
+
3
16
  ## 1.82.1
4
17
 
5
18
  ### Patch Changes
@@ -0,0 +1,227 @@
1
+ /**
2
+ * The live half of the command-code-knowledge skill's model facts. reference/models.md is generated
3
+ * at build time, so a model the catalog launched after this release is missing from it, and the
4
+ * skill tells the model to "never invent a model id" — it then refuses to name the new model or pin
5
+ * an agent to it. On activation the skill body gains a section built from the catalog this process
6
+ * already holds (never a fetch): models the reference does not list, models the catalog has hidden
7
+ * or dropped since, and known models whose window or effort levels changed. "This build" is the
8
+ * catalog embedded in it, which the reference is generated from. No remote catalog, or a catalog
9
+ * that matches this build, adds nothing.
10
+ */
11
+
12
+ import {
13
+ getSupportedEfforts,
14
+ listSelectableModelIds,
15
+ } from '../../../config/known-models.js';
16
+ import {getInstalledModelCatalogManager} from '../../../model/catalog-manager.js';
17
+ import {
18
+ type EffectiveModelCatalog,
19
+ resolveCatalogModelStatus,
20
+ getSnapshotEffectiveCatalog,
21
+ } from '../../../model/catalog-resolution.js';
22
+ import type {CatalogModelV1} from '../../../model/model-catalog-wire.js';
23
+ import {getKnownModelContextWindow} from '../../../model/model-registry.js';
24
+ import type {Skill} from '../../skill-registry.js';
25
+
26
+ export const KNOWLEDGE_SKILL_NAME = 'command-code-knowledge';
27
+
28
+ interface ModelBuckets {
29
+ readonly added: readonly CatalogModelV1[];
30
+ // Shipped ids the catalog hides or no longer carries.
31
+ readonly hidden: readonly string[];
32
+ // Shipped ids the catalog now serves in a shape this build cannot run (an unknown profile).
33
+ readonly outdated: readonly string[];
34
+ readonly changed: readonly CatalogModelV1[];
35
+ }
36
+
37
+ // 205_000 → '205K'; 1_000_000 → '1M'; 1_050_000 → '1.05M' — the reference table's spelling.
38
+ function formatContext(tokens: number): string {
39
+ if (tokens < 1_000_000) return `${Math.round(tokens / 1000)}K`;
40
+ const millions = tokens / 1_000_000;
41
+ return `${Number.isInteger(millions) ? millions : millions.toFixed(2)}M`;
42
+ }
43
+
44
+ function formatEfforts(efforts: readonly string[] | null): string {
45
+ return efforts && efforts.length > 0 ? efforts.join(', ') : '—';
46
+ }
47
+
48
+ function sameEfforts(
49
+ left: readonly string[] | null,
50
+ right: readonly string[] | null,
51
+ ): boolean {
52
+ return formatEfforts(left) === formatEfforts(right);
53
+ }
54
+
55
+ function modelRow(model: CatalogModelV1): string {
56
+ return `| \`${model.id}\` | ${model.display.label} | ${formatContext(model.contextWindow)} | ${formatEfforts(model.reasoningEfforts)} |`;
57
+ }
58
+
59
+ function modelTable(models: readonly CatalogModelV1[]): string {
60
+ return [
61
+ '| Id (use EXACTLY this) | Name | Context | Efforts |',
62
+ '|---|---|---|---|',
63
+ ...models.map(modelRow),
64
+ ].join('\n');
65
+ }
66
+
67
+ // The catalog this build ships, which the reference was generated from.
68
+ function builtCatalog(): EffectiveModelCatalog {
69
+ return getSnapshotEffectiveCatalog({remoteDisabled: false});
70
+ }
71
+
72
+ // A known model whose served window or effort levels no longer match the embedded catalog the
73
+ // reference was generated from.
74
+ function changedSinceBuild(model: CatalogModelV1): boolean {
75
+ const built = builtCatalog();
76
+ const window = getKnownModelContextWindow(model.id, built);
77
+ if (window !== undefined && window !== model.contextWindow) return true;
78
+ return !sameEfforts(
79
+ getSupportedEfforts(model.id, built),
80
+ model.reasoningEfforts,
81
+ );
82
+ }
83
+
84
+ function bucketModels(effective: EffectiveModelCatalog): ModelBuckets {
85
+ const known = listSelectableModelIds({catalog: builtCatalog()});
86
+ const knownSet = new Set(known);
87
+ const added: CatalogModelV1[] = [];
88
+ const hidden: string[] = [];
89
+ const changed: CatalogModelV1[] = [];
90
+ for (const model of effective.catalog.models) {
91
+ const {state} = resolveCatalogModelStatus({
92
+ effective,
93
+ modelId: model.id,
94
+ });
95
+ if (state === 'hidden' && knownSet.has(model.id)) {
96
+ hidden.push(model.id);
97
+ continue;
98
+ }
99
+ if (state !== 'selectable') continue;
100
+ if (!knownSet.has(model.id)) {
101
+ added.push(model);
102
+ continue;
103
+ }
104
+ if (changedSinceBuild(model)) changed.push(model);
105
+ }
106
+ // A shipped id the catalog no longer carries at all (no row, no alias), or now marks update
107
+ // required, is refused by /model and sub-agents too.
108
+ const outdated: string[] = [];
109
+ for (const id of known) {
110
+ const {state} = resolveCatalogModelStatus({
111
+ effective,
112
+ modelId: id,
113
+ });
114
+ if (state === 'not-in-catalog') hidden.push(id);
115
+ if (state === 'client-update-required') outdated.push(id);
116
+ }
117
+ return {added, hidden, outdated, changed};
118
+ }
119
+
120
+ export interface BuildLiveModelSectionParams {
121
+ readonly catalog?: EffectiveModelCatalog;
122
+ }
123
+
124
+ /**
125
+ * The "live model catalog" section for the knowledge skill, or '' when there is no remote catalog
126
+ * or it differs from this build in nothing the reference covers. `catalog` defaults to the one this
127
+ * process's catalog manager holds.
128
+ */
129
+ export function buildLiveModelSection(
130
+ params: BuildLiveModelSectionParams = {},
131
+ ): string {
132
+ const effective =
133
+ params.catalog ?? getInstalledModelCatalogManager()?.getEffective();
134
+ if (!effective) return '';
135
+ const {added, hidden, outdated, changed} = bucketModels(effective);
136
+ if (added.length + hidden.length + outdated.length + changed.length === 0)
137
+ return '';
138
+ const parts = [
139
+ '## Live model catalog (overrides reference/models.md)',
140
+ 'The model catalog in force now differs from the one `reference/models.md` was generated from. Where they disagree, this section wins. Prices and minimum plans for models listed here are not in the reference. Point the user at /model or https://commandcode.ai/docs for those.',
141
+ ];
142
+ if (added.length > 0) {
143
+ parts.push(
144
+ `### Available models the reference does not list\nThese ids are valid for \`/model\`, \`--model\` and an agent file's \`model:\`.\n\n${modelTable(added)}`,
145
+ );
146
+ }
147
+ if (changed.length > 0) {
148
+ parts.push(
149
+ `### Context window or efforts changed since the reference\n${modelTable(changed)}`,
150
+ );
151
+ }
152
+ if (hidden.length > 0) {
153
+ parts.push(
154
+ `### No longer offered\nDo not recommend these or pin new agents to them: ${hidden
155
+ .map(id => `\`${id}\``)
156
+ .join(', ')}.`,
157
+ );
158
+ }
159
+ if (outdated.length > 0) {
160
+ parts.push(
161
+ `### Needs a newer Command Code\nThis version cannot run these. Do not recommend them or pin agents to them; tell the user to update Command Code to use them: ${outdated
162
+ .map(id => `\`${id}\``)
163
+ .join(', ')}.`,
164
+ );
165
+ }
166
+ return parts.join('\n\n');
167
+ }
168
+
169
+ /**
170
+ * The section built once per catalog `getCatalog` answers with. A session hands in its pin when the
171
+ * pin came from the live catalog, else the newest catalog — so every activation (the activate_skill
172
+ * tool, a `/command-code-knowledge` turn, an inline mention) reads the same text until a catalog
173
+ * lands or /model re-pins.
174
+ */
175
+ export function createLiveModelSectionCache(
176
+ getCatalog: () => EffectiveModelCatalog | undefined,
177
+ ): () => string {
178
+ let cached:
179
+ | {readonly catalog: EffectiveModelCatalog; readonly text: string}
180
+ | undefined;
181
+ return () => {
182
+ const catalog = getCatalog();
183
+ if (!catalog) return '';
184
+ if (cached?.catalog !== catalog) {
185
+ cached = {catalog, text: buildLiveModelSection({catalog})};
186
+ }
187
+ return cached.text;
188
+ };
189
+ }
190
+
191
+ export interface AppendLiveModelSectionParams {
192
+ readonly body: string;
193
+ readonly section: string;
194
+ }
195
+
196
+ /** A skill body plus the live model section, when there is one. */
197
+ export function appendLiveModelSection(
198
+ params: AppendLiveModelSectionParams,
199
+ ): string {
200
+ return params.section ? `${params.body}\n\n${params.section}` : params.body;
201
+ }
202
+
203
+ export interface WithLiveModelSectionParams {
204
+ readonly skill: Skill;
205
+ readonly section: () => string | Promise<string>;
206
+ }
207
+
208
+ /**
209
+ * The bundled knowledge skill with the live model section on its body, so every path that loads the
210
+ * body gets it; any other skill (a user skill of the same name included) is returned unchanged.
211
+ */
212
+ export function withLiveModelSection(
213
+ params: WithLiveModelSectionParams,
214
+ ): Skill {
215
+ const {skill} = params;
216
+ if (skill.source !== 'bundled' || skill.name !== KNOWLEDGE_SKILL_NAME) {
217
+ return skill;
218
+ }
219
+ return {
220
+ ...skill,
221
+ loadBody: async () =>
222
+ appendLiveModelSection({
223
+ body: await skill.loadBody(),
224
+ section: await params.section(),
225
+ }),
226
+ };
227
+ }
@@ -61,7 +61,7 @@ Every built-in command, grouped by area. Aliases are shown in parentheses on the
61
61
  | `/plans [name]` | Browse, review, and annotate saved plans; bare `/plans` opens the browser |
62
62
  | `/plan-review` | Open this session's latest plan in review |
63
63
  | `/goal <objective>\|clear\|status` | Set an objective for the agent to work towards autonomously |
64
- | `/todos` | Manage the session todo list - `c` completes the selected item, `x` removes it, `a` clears the list |
64
+ | `/todos` | Manage the session todo list (needs the `todos` mod: `cmd mods enable todos`) |
65
65
  | `/review [pr-number]` | Review a pull request |
66
66
  | `/pr-comments` | Fetch all PR comments for current branch |
67
67
 
@@ -151,7 +151,7 @@ Most commands are **blocked mid-turn** - mode flips, session switches, model cha
151
151
  - `/trace` - capture the live trace id of the running turn (its main purpose)
152
152
  - `/session-file` - read-only session facts
153
153
  - `/copy` - clipboard only
154
- - `/todos` (also `ctrl+x`) - edits local todo state, most useful mid-turn while a plan is being driven
154
+ - `/todos` (also `ctrl+x`) - edits local todo state, most useful mid-turn while a plan is being driven (needs the `todos` mod enabled)
155
155
  - `/exit` / `/quit` - always available
156
156
  - `/goal clear` - stops the goal loop; the current step finishes, then the loop stops. Setting a **new** goal mid-turn is refused with a busy notice.
157
157
 
@@ -100,7 +100,7 @@ cmd -p "..." --tools-all
100
100
  CMD_TOOLS_ALL_ENABLE=true cmd -p "..."
101
101
 
102
102
  # Only enable the ones you name (comma-separated, repeatable)
103
- cmd -p "..." --tools-enable ask_user_question,todo_write
103
+ cmd -p "..." --tools-enable ask_user_question
104
104
  CMD_TOOLS_ASK_USER_QUESTION_ENABLE=true cmd -p "..."
105
105
  ```
106
106
 
@@ -35,6 +35,7 @@ The model catalog — every id `/model`, `--model`, `model:effort` shorthand, an
35
35
  | `xiaomi/mimo-v2.5-pro` | MiMo V2.5 Pro | 1M | — | $0.435/$0.87 · cache $0.0036 | Go and above | high-capability long-context agentic coding |
36
36
  | `xiaomi/mimo-v2.5` | MiMo V2.5 | 1M | — | $0.14/$0.28 · cache $0.0028 | Go and above | efficient long-context agentic coding |
37
37
  | `Qwen/Qwen3.8-Omni-Flash` | Qwen 3.8 Omni Flash | 1M | low, medium, xhigh | $0.15/$0.47 · cache $0.016 | Go and above | omni-modal understanding & multimedia agentic work |
38
+ | `Qwen/Qwen3.8-Max-Prime` | Qwen 3.8 Max Prime | 1M | low, medium, xhigh | $4/$12 · cache $0.5 (write $5) | GOAT and above | high-speed Qwen 3.8 Max: 1.5–2× faster output |
38
39
  | `Qwen/Qwen3.8-Max-0902` | Qwen 3.8 Max 0902 | 1M | low, medium, xhigh | $2/$6 · cache $0.25 | Go and above | upgraded Qwen 3.8 Max: stronger coding & agentic tool use |
39
40
  | `Qwen/Qwen3.8-Max` | Qwen 3.8 Max | 1M | low, medium, xhigh | $2/$6 · cache $0.25 (write $2.5) | Go and above | autonomous long-horizon coding & professional work |
40
41
  | `Qwen/Qwen3.8-27B` | Qwen 3.8 27B | 262K | low, medium, xhigh | $0.4/$3 · cache $0.04 | Go and above | compact vision-language coding & agentic work |
@@ -55,7 +56,7 @@ The model catalog — every id `/model`, `--model`, `model:effort` shorthand, an
55
56
  | `thinkingmachines/inkling-small` | Inkling Small | 1M | — | $0.5/$1.2 · cache $0.1 | Go and above | lightweight MoE reasoning at lower cost and latency |
56
57
  | `poolside/laguna-s-2.1-free` | Laguna S 2.1 | 256K | — | $0/$0 · cache $0 | Go and above | open-weight agentic coding and long-horizon work |
57
58
  | `inclusionai/ling-3.0-flash-sante:free` | Ling 3.0 Flash Sante | 262K | — | $0/$0 · cache $0 | Go and above | health & medicine tuned lightweight-MoE, still strong on code |
58
- | `inclusionai/ling-3.1-flash:free` | Ling 3.1 Flash | 262K | low, medium, high | $0/$0 · cache $0 | Go and above | hybrid-reasoning MoE for coding & tool-using agents |
59
+ | `inclusionai/ling-3.1-flash` | Ling 3.1 Flash | 262K | low, medium, high | $0.3/$0.9 · cache $0.06 | Go and above | hybrid-reasoning MoE for coding & tool-using agents |
59
60
  | `mistral/mistral-large-4` | Mistral Large 4 | 524K | low, medium, high | $1.36/$4.18 · cache $0.14 | Go and above | frontier open-weight multimodal model for coding & analysis |
60
61
  ## Stealth
61
62
 
@@ -54,7 +54,7 @@
54
54
  - /export [path]: Export session — /export [html|jsonl|md] or a file path
55
55
  - /changelog: See what's new in Command Code
56
56
  - /hotkeys: Show all keyboard shortcuts
57
- - /todos: Manage the session todo list — x to remove an item, c to clear
57
+ - /todos: Manage the session todo list — c completes an item, x removes it, a completes all (needs the `todos` mod: `cmd mods enable todos`)
58
58
  - /loop [interval] [task]: Re-run a task on fixed intervals, or let the agent pace itself
59
59
  - /rc: Remote-control this session from Telegram or Discord
60
60
  - /plan [task]: Enter plan mode; `/plan <task>` plans that task
@@ -277,22 +277,20 @@ Valid model ids (the /model catalog — use these EXACT ids):
277
277
  - gpt-5.4
278
278
  - gpt-5.3-codex
279
279
  - gpt-5.4-mini
280
- - moonshotai/Kimi-K3
281
- - thinkingmachines/inkling
282
- - thinkingmachines/inkling-small
283
280
  - deepseek/deepseek-v4-pro
284
281
  - deepseek/deepseek-v4-flash
285
282
  - deepseek/deepseek-v4-flash-vision-exp
286
283
  - deepseek/deepseek-v4-flash-fast
287
284
  - deepseek/deepseek-v4.1-flash
288
285
  - deepseek/deepseek-v4.1-flash-fast
286
+ - moonshotai/Kimi-K3
289
287
  - moonshotai/Kimi-K2.7-Code
290
288
  - moonshotai/Kimi-K2.7-Code-Highspeed
291
289
  - moonshotai/Kimi-K2.6
292
290
  - moonshotai/Kimi-K2.5
293
- - zai-org/GLM-5.3
294
291
  - z-ai/glm-5.3-flash
295
292
  - z-ai/glm-5.3-flashx
293
+ - zai-org/GLM-5.3
296
294
  - zai-org/GLM-5.2
297
295
  - zai-org/GLM-5.2-Fast
298
296
  - zai-org/GLM-5.1
@@ -305,22 +303,23 @@ Valid model ids (the /model catalog — use these EXACT ids):
305
303
  - xiaomi/mimo-v2.6-flash
306
304
  - xiaomi/mimo-v2.5-pro
307
305
  - xiaomi/mimo-v2.5
308
- - Qwen/Qwen3.6-Max-Preview
309
- - Qwen/Qwen3.6-Plus
310
- - Qwen/Qwen3.7-Max
311
- - Qwen/Qwen3.7-Plus
312
306
  - Qwen/Qwen3.8-Omni-Flash
307
+ - Qwen/Qwen3.8-Max-Prime
313
308
  - Qwen/Qwen3.8-Max-0902
314
309
  - Qwen/Qwen3.8-Max
315
310
  - Qwen/Qwen3.8-27B
316
311
  - Qwen/Qwen3.8-Flash
312
+ - Qwen/Qwen3.7-Max
313
+ - Qwen/Qwen3.7-Plus
317
314
  - Qwen/Qwen3.7-Flash
315
+ - Qwen/Qwen3.6-Max-Preview
316
+ - Qwen/Qwen3.6-Plus
318
317
  - meituan/LongCat-2.0
319
318
  - stepfun/Step-5-Preview
320
319
  - stepfun/Step-3.7-Flash
321
320
  - stepfun/Step-3.5-Flash
322
- - tencent/hy4-preview
323
321
  - tencent/hy3-paid
322
+ - tencent/hy4-preview
324
323
  - google/gemini-4-argon
325
324
  - google/gemini-3.8-flash
326
325
  - google/gemini-3.7-flash
@@ -329,21 +328,23 @@ Valid model ids (the /model catalog — use these EXACT ids):
329
328
  - google/gemini-3.5-flash-lite
330
329
  - google/gemini-3.1-flash-lite
331
330
  - sakana/fugu-ultra
332
- - xai/grok-4.5
333
- - xai/grok-4.6
334
- - xai/grok-4.7
335
- - mistral/mistral-large-4
331
+ - nvidia/nemotron-3-ultra-550b-a55b
332
+ - thinkingmachines/inkling
333
+ - thinkingmachines/inkling-small
334
+ - stealth/glyph-cluster:free
335
+ - poolside/laguna-s-2.1-free
336
+ - inclusionai/ling-3.0-flash-sante:free
337
+ - inclusionai/ling-3.1-flash
336
338
  - meta/muse-spark-1.1
337
339
  - meta/muse-spark-1.2
338
340
  - meta/muse-spark-1.2-contributor
339
341
  - meta/muse-spark-1.3
340
342
  - meta/muse-spark-1.3-contributor
341
343
  - meta/muse-wonder-1.0
342
- - nvidia/nemotron-3-ultra-550b-a55b
343
- - poolside/laguna-s-2.1-free
344
- - inclusionai/ling-3.0-flash-sante:free
345
- - inclusionai/ling-3.1-flash:free
346
- - stealth/glyph-cluster:free
344
+ - xai/grok-4.5
345
+ - xai/grok-4.6
346
+ - xai/grok-4.7
347
+ - mistral/mistral-large-4
347
348
  A BYO-provider id (from a configured custom provider) also works and is passed through as-is.
348
349
 
349
350
  WHEN THE USER ASKS YOU TO CREATE AN AGENT (e.g. "make a changelog agent with a cheap model"):
@@ -228,8 +228,29 @@ Resolves ports to pids via `lsof` (or `Get-NetTCPConnection` on Windows), reconc
228
228
 
229
229
  ## Work state & task management
230
230
 
231
+ ### `task_create` / `task_update` / `task_list` / `task_get`
232
+
233
+ A durable, dependency-aware task ledger for coordination-heavy work - tasks persist across restarts with stable ids, three states, owners, metadata, and `blockedBy`/`blocks` edges.
234
+
235
+ - **`task_create`** - `subject` (required), `description` (required), `activeForm`, `blockedBy`, `blocks`, `metadata`.
236
+ - **`task_update`** - `taskId` (required), `status` (`pending` | `in_progress` | `completed` | `deleted`), `subject`, `description`, `activeForm`, `owner`, `metadata` (merge; null deletes a key), `addBlockedBy` / `addBlocks` / `removeBlockedBy` / `removeBlocks`. Completing a task reports which tasks it unblocked.
237
+ - **`task_list`** - optional `status` filter; shows unresolved blockers and a tally.
238
+ - **`task_get`** - `taskId` (required); full detail.
239
+
240
+ All four are plan-safe - capturing a plan as tasks *is* planning.
241
+
242
+ ### `task_output` (alias)
243
+
244
+ Retired into `shell_output`. Calls to this name still work: they run as `shell_output` with `wait: "exit"` carried, so "block until the task settles" keeps its meaning. Use `shell_output` directly in new work.
245
+
246
+ ### `task_stop`
247
+
248
+ Stop a tracked background task by `taskId`. Signals the whole process group, flips the registry state, and distinguishes "unknown id" from "already finished."
249
+
231
250
  ### `todo_write`
232
251
 
252
+ Provided by the opt-in `todos` built-in mod, which is **disabled by default** - enable it with `cmd mods enable todos` (`-g` for user scope) and it appears on the next session or `/reload`. While the mod is disabled the model never sees this tool.
253
+
233
254
  The session checklist - the same list you manage with `/todos` and see in the TODOS panel.
234
255
 
235
256
  | Parameter | Type | Required | Description |
@@ -286,25 +307,6 @@ A single edit in a single place. The agent makes it.
286
307
 
287
308
  One command, immediate result. A checklist around it adds a panel and no information.
288
309
 
289
- ### `task_create` / `task_update` / `task_list` / `task_get`
290
-
291
- A durable, dependency-aware task ledger for coordination-heavy work - tasks persist across restarts with stable ids, three states, owners, metadata, and `blockedBy`/`blocks` edges.
292
-
293
- - **`task_create`** - `subject` (required), `description` (required), `activeForm`, `blockedBy`, `blocks`, `metadata`.
294
- - **`task_update`** - `taskId` (required), `status` (`pending` | `in_progress` | `completed` | `deleted`), `subject`, `description`, `activeForm`, `owner`, `metadata` (merge; null deletes a key), `addBlockedBy` / `addBlocks` / `removeBlockedBy` / `removeBlocks`. Completing a task reports which tasks it unblocked.
295
- - **`task_list`** - optional `status` filter; shows unresolved blockers and a tally.
296
- - **`task_get`** - `taskId` (required); full detail.
297
-
298
- All four are plan-safe - capturing a plan as tasks *is* planning.
299
-
300
- ### `task_output` (alias)
301
-
302
- Retired into `shell_output`. Calls to this name still work: they run as `shell_output` with `wait: "exit"` carried, so "block until the task settles" keeps its meaning. Use `shell_output` directly in new work.
303
-
304
- ### `task_stop`
305
-
306
- Stop a tracked background task by `taskId`. Signals the whole process group, flips the registry state, and distinguishes "unknown id" from "already finished."
307
-
308
310
  ---
309
311
 
310
312
  ## Scheduling & waiting
@@ -116,11 +116,13 @@ run `pnpm generate:knowledge` after editing the docs under `packages/docs/src/ap
116
116
  - Personal: leave it in `~/.commandcode/mods/`.
117
117
  - A package: a `package.json` with `{"keywords": ["cmd-mod"], "commandcode": {"mods": ["./index.ts"]}}`,
118
118
  installed via `cmd mods add npm:<name>` / `cmd mods add owner/repo` / `cmd mods add ./local-dir`.
119
- **Always include the `cmd-mod` keyword** — it is what lists the package on the
120
- [mods hub](https://commandcode.ai/mods) once it is published to npm; without it the mod is
121
- invisible there. Add a kind keyword too (`cmd-mod-tool`, `cmd-mod-command`, …) and a
122
- `repository` field so the hub row shows the right category and a star count. Full
123
- packaging/filtering detail: `reference/packaging.md`.
119
+ Include the exact `cmd-mod` keyword so maintainers can discover it for review.
120
+ After publishing with `pnpm publish`, submit an entry to `mods/registry.json`
121
+ in the public `CommandCodeAI/command-code` repo. Publishing alone does not list
122
+ a mod on the [mods hub](https://commandcode.ai/mods). The reviewed entry supplies
123
+ its description and categories; `npm` enables live package metadata and monthly
124
+ downloads, and a GitHub `repo` enables stars. Full packaging and submission
125
+ detail: `reference/packaging.md`.
124
126
 
125
127
  ## Boundaries to state up front
126
128
 
@@ -188,10 +188,10 @@ Command Code's own features ride this exact API. First-party providers (`provide
188
188
  {"mods": {"disabled": ["provider-copilot", "update-notice", "titling", "learning"]}}
189
189
  ```
190
190
 
191
- A built-in can also ship **opt-in** - off by default; `cmd mods list --builtin` marks it `off by default`. Enable mods with `cmd mods enable <name>` (project level; `-g` for the user level), which adds it to the `enabled` key in the settings file:
191
+ Some built-ins are **opt-in** and are disabled by default; `cmd mods list --builtin` marks them `disabled by default`. The session todo checklist (`todo_write`, the TODOS panel, `/todos`, `ctrl+x`) is the `todos` mod: enable it with `cmd mods enable todos` (project level; `-g` for the user level), which adds it to the `enabled` key in the settings file:
192
192
 
193
193
  ```json
194
- {"mods": {"enabled": ["<name>"]}}
194
+ {"mods": {"enabled": ["todos"]}}
195
195
  ```
196
196
 
197
197
  `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).
@@ -54,22 +54,28 @@ A package declares what it ships via `package.json` - exact paths, directories,
54
54
  }
55
55
  ```
56
56
 
57
- The `cmd-mod` keyword is **required** — it is the only thing that lists your package on the
58
- [mods hub](https://commandcode.ai/mods). Everything else shapes the hub row: a `description`
59
- becomes the summary, a kind keyword (`cmd-mod-tool`, `cmd-mod-command`, `cmd-mod-hook`,
60
- `cmd-mod-provider`, `cmd-mod-renderer`, `cmd-mod-flag`) sets the category badge, and a
61
- `repository` pointing at GitHub adds the star count. Ship these from the start so the hub
62
- lists the mod well the moment you publish, with nothing to submit.
57
+ Include the `cmd-mod` keyword so maintainers can find the package during review.
58
+ Kind keywords such as `cmd-mod-tool` and `cmd-mod-hook` help describe it, but the
59
+ hub's categories and summary come from its reviewed registry entry. Publishing
60
+ to npm does not list a package on the [mods hub](https://commandcode.ai/mods).
63
61
 
64
62
  No manifest → the `mods/` convention directory → a root `index.ts`, in that order.
65
63
 
66
64
  `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`.
67
65
 
68
- Publish to npm with the `cmd-mod` keyword and the package is listed on the [mods hub](https://commandcode.ai/mods) automatically - the hub reads the npm registry for that keyword, so there is nothing to submit. Monthly downloads come straight from npm; a GitHub `repository` field adds the star count.
66
+ After publishing, submit an entry to the public registry for review. Listed npm
67
+ packages get live monthly downloads, latest version, and publish date from npm.
68
+ A GitHub `repo` in the registry entry adds its star count.
69
69
 
70
- ## Listing a git-only mod (the curated registry)
70
+ ## Listing a mod on the hub
71
71
 
72
- Two things feed [the hub](https://commandcode.ai/mods). Any npm package with the `cmd-mod` keyword lists automatically (above). A **curated registry** - `mods/registry.json` in the public [`CommandCodeAI/command-code`](https://github.com/CommandCodeAI/command-code) repo - adds what npm can't: mods that live only in a git repo and never hit npm, richer metadata layered over an npm entry (matched by `npm`), an `official` badge, and a `hidden` list for moderation. Open a PR against that file to get a git-only mod listed - nothing else to submit.
72
+ The [hub](https://commandcode.ai/mods) lists the reviewed entries in
73
+ `mods/registry.json` in the public
74
+ [`CommandCodeAI/command-code`](https://github.com/CommandCodeAI/command-code) repo.
75
+ Open a PR against that file for either an npm or a GitHub mod. Maintainers review
76
+ npm candidates before adding them to the list. The hub automatically fetches
77
+ GitHub entries and approved npm entries from this file within about 15 minutes
78
+ of a merge, without a website deployment.
73
79
 
74
80
  ```json
75
81
  {
@@ -90,9 +96,9 @@ Two things feed [the hub](https://commandcode.ai/mods). Any npm package with the
90
96
  }
91
97
  ```
92
98
 
93
- `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` merges the entry with its npm package for the download count, `official` marks a team-maintained mod, and a `hidden` name (a mod or an npm package) keeps spam or impersonation off the hub. The schema is `mods.schema.json` beside the file.
99
+ `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`.
94
100
 
95
- The resolved list - npm discovery merged with the curated file, live numbers included - 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.
101
+ 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.
96
102
 
97
103
  ## Filtering a source's mods
98
104
 
@@ -119,10 +125,10 @@ cmd mods disable review-guard # disable in this project
119
125
  cmd mods enable review-guard -g # enable at the user level
120
126
  ```
121
127
 
122
- 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, adds it to `mods.enabled`:
128
+ 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`:
123
129
 
124
130
  ```json
125
- {"mods": {"disabled": ["review-guard"], "enabled": ["<opt-in-built-in>"]}}
131
+ {"mods": {"disabled": ["review-guard"], "enabled": ["todos"]}}
126
132
  ```
127
133
 
128
134
  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:
@@ -136,7 +142,7 @@ $ cmd mods enable review-guard
136
142
 
137
143
  A disable in `settings.local.json` has to be removed by hand; no command writes to that file.
138
144
 
139
- **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.
145
+ **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`.
140
146
 
141
147
  ## Trust and safety
142
148
 
@@ -54,6 +54,15 @@ cmd -p "exercise the mod" --mod ./your-mod.ts
54
54
 
55
55
  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.
56
56
 
57
+ ## 6. Submit the published mod for review
58
+
59
+ Include `cmd-mod` in your package's keywords so maintainers can discover it.
60
+ Before publishing, check `package.json` for the correct mod entrypoints,
61
+ description, and repository. Publish with `pnpm publish`, then open a PR adding
62
+ an entry to the public [`mods/registry.json`](https://github.com/CommandCodeAI/command-code/blob/main/mods/registry.json).
63
+ Set `source` and `npm` to the full package name for an npm mod. Publishing or
64
+ adding a keyword alone does not list it on the hub.
65
+
57
66
  ## Working from the bundled examples
58
67
 
59
68
  Ask Command Code to build the mod you want and it starts from a bundled example rather than a blank file - see [Runnable examples](./overview.md#runnable-examples) for the list. Each one loads through the real mod loader in CI on every test run, so what you start from is proven to load.