command-code 1.79.2 → 1.80.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/CHANGELOG.md +8 -0
- package/dist/bundled/command-code-knowledge/reference/models.md +1 -0
- package/dist/bundled/command-code-knowledge/reference/product-help.md +1 -0
- package/dist/bundled/mod-builder/SKILL.md +7 -3
- package/dist/bundled/mod-builder/examples/kitchen-sink.ts +21 -2
- package/dist/bundled/mod-builder/reference/api.md +20 -2
- package/dist/bundled/mod-builder/reference/packaging.md +45 -1
- package/dist/bundled/mod-builder/reference/ui.md +6 -1
- package/dist/cli.mjs +5 -5
- package/package.json +1 -1
- package/vsix/commandcode-vscode.vsix +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -116,6 +116,7 @@ The model catalog — every id `/model`, `--model`, `model:effort` shorthand, an
|
|
|
116
116
|
| `meta/muse-spark-1.2-contributor` | Muse Spark 1.2 Contributor | 1.05M | low, medium, high, xhigh | $0.1/$0.2 · cache $0.002 | Go and above | Muse Spark 1.2 at ~95% off |
|
|
117
117
|
| `meta/muse-spark-1.3` | Muse Spark 1.3 | 1.05M | low, medium, high, xhigh, max | $1.25/$4.25 · cache $0.15 | GOAT and above | multimodal reasoning for long-horizon agentic and coding workflows |
|
|
118
118
|
| `meta/muse-spark-1.3-contributor` | Muse Spark 1.3 Contributor | 1.05M | low, medium, high, xhigh | $0.1/$0.2 · cache $0.002 | Go and above | Muse Spark 1.3 at up to 95% off |
|
|
119
|
+
| `meta/muse-wonder-1.0` | Muse Wonder | 1.05M | low, medium, high, xhigh | $4/$20 · cache $0.2 | Max | frontier coding, long-running agents and advanced computer use |
|
|
119
120
|
## xAI
|
|
120
121
|
|
|
121
122
|
| Id (use EXACTLY this) | Name | Context | Efforts | $/1M in/out · cache read | Min plan | Best for |
|
|
@@ -337,6 +337,7 @@ Valid model ids (the /model catalog — use these EXACT ids):
|
|
|
337
337
|
- meta/muse-spark-1.2-contributor
|
|
338
338
|
- meta/muse-spark-1.3
|
|
339
339
|
- meta/muse-spark-1.3-contributor
|
|
340
|
+
- meta/muse-wonder-1.0
|
|
340
341
|
- nvidia/nemotron-3-ultra-550b-a55b
|
|
341
342
|
- poolside/laguna-s-2.1-free
|
|
342
343
|
- inclusionai/ling-3.0-flash-sante:free
|
|
@@ -114,9 +114,13 @@ run `pnpm generate:knowledge` after editing the docs under `packages/docs/src/ap
|
|
|
114
114
|
## 6. Ship it (optional)
|
|
115
115
|
|
|
116
116
|
- Personal: leave it in `~/.commandcode/mods/`.
|
|
117
|
-
- A package: a `package.json` with `{"commandcode": {"mods": ["./index.ts"]}}`,
|
|
118
|
-
`cmd mods add npm:<name>` / `cmd mods add owner/repo` / `cmd mods add ./local-dir`.
|
|
119
|
-
|
|
117
|
+
- A package: a `package.json` with `{"keywords": ["cmd-mod"], "commandcode": {"mods": ["./index.ts"]}}`,
|
|
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`.
|
|
120
124
|
|
|
121
125
|
## Boundaries to state up front
|
|
122
126
|
|
|
@@ -92,13 +92,32 @@ export default function (cmd: ModApi): void {
|
|
|
92
92
|
// ── observe events (never mutate here) ──────────────────────────────────────────────
|
|
93
93
|
cmd.on('tool_errored', () => cmd.ui.notify('a tool errored', 'warning'));
|
|
94
94
|
|
|
95
|
+
// ── a keyboard shortcut (interactive TUI only; dispatched after host bindings) ──────
|
|
96
|
+
cmd.addShortcut('alt+u', {
|
|
97
|
+
description: 'Show context usage',
|
|
98
|
+
handler: () => {
|
|
99
|
+
const usage = cmd.getContextUsage();
|
|
100
|
+
if (!usage || usage.percent === null)
|
|
101
|
+
return {message: 'context window not measured yet'};
|
|
102
|
+
return {
|
|
103
|
+
message: `${cmd.getModel()} · ${usage.percent}% of ${usage.contextWindow} tokens`,
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ── skills shipped beside this mod (resolved against this file) ────────────────────
|
|
109
|
+
// cmd.addSkillsPath('./skills');
|
|
110
|
+
|
|
95
111
|
// ── live surfaces (usable any time after the harness binds) ─────────────────────────
|
|
96
|
-
// cmd.ui.notify / confirm / select / input — talk to the user.
|
|
112
|
+
// cmd.ui.notify / confirm / select / input — talk to the user; ui.setTitle — the tab.
|
|
97
113
|
// cmd.queueMessage({content, deliverAs}) — steer the running loop or queue a follow-up.
|
|
114
|
+
// cmd.sendUserMessage(text) — a real user turn (starts one when idle).
|
|
98
115
|
// cmd.session — durable custom-entry persistence (undefined until bound).
|
|
99
116
|
// cmd.sessions — compact(), tree(), leafId(), navigateTree(...), setLabel(...).
|
|
100
|
-
// cmd.setModel / setEffort / setSessionName.
|
|
117
|
+
// cmd.setModel / setEffort / setSessionName, and their get* counterparts.
|
|
118
|
+
// cmd.getContextUsage / getCommands / getToolInfo / isIdle — live reads.
|
|
101
119
|
// cmd.getAllTools / getActiveTools / setActiveTools — a mod-managed tool filter.
|
|
120
|
+
// cmd.shutdown() — exit once the turn settles.
|
|
102
121
|
//
|
|
103
122
|
// Example: on the first run, greet once via a queued steering message.
|
|
104
123
|
let greeted = false;
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
| `cmd.addFlag` | `(name, {type: 'boolean'\|'string'; default?; description?}) => Disposable` |
|
|
26
26
|
| `cmd.addProvider` | `(module: ProviderModule) => Disposable` |
|
|
27
27
|
| `cmd.addRenderer` | `(customType: string, (data) => readonly string[]) => Disposable` |
|
|
28
|
+
| `cmd.addShortcut` | `(keys: string, {description?; handler}) => Disposable` |
|
|
29
|
+
| `cmd.addSkillsPath` | `(path: string) => Disposable` |
|
|
28
30
|
| `cmd.on` | `(event: AgentEventType \| 'session_start' \| 'session_shutdown', handler) => Disposable` |
|
|
29
31
|
|
|
30
32
|
What each does:
|
|
@@ -36,6 +38,8 @@ What each does:
|
|
|
36
38
|
- `cmd.on(event, handler)` - observe any `AgentEvent` plus the host lifecycle events `session_start` / `session_shutdown` (fired when a harness binds the host and when a session switch or dispose replaces it). Handlers are isolated: a throw becomes a `mod_error {hook: 'on:<event>'}` event, never a crash.
|
|
37
39
|
- `cmd.addProvider(providerModule)` - register a model provider through the same `ProviderModule` seam the built-ins use (id, transport, auth hooks, model list). The host appends mod providers to its set - mods extend the provider set, never replace it.
|
|
38
40
|
- `cmd.addRenderer(customType, data => lines)` - a renderer for a custom entry type; returns the lines to print (style them with ansi escapes - picocolors, `@commandcode/tui` helpers, or raw codes). First registration per type wins across mods.
|
|
41
|
+
- `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.
|
|
42
|
+
- `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).
|
|
39
43
|
|
|
40
44
|
## Live methods (any time after the harness binds)
|
|
41
45
|
|
|
@@ -44,15 +48,29 @@ What each does:
|
|
|
44
48
|
| `cmd.getFlag` | `(name) => boolean \| string \| undefined` |
|
|
45
49
|
| `cmd.showEntry` | `(customType, data?) => void` |
|
|
46
50
|
| `cmd.queueMessage` | `({content, deliverAs?: 'steer' \| 'follow-up'}) => void` |
|
|
51
|
+
| `cmd.sendUserMessage` | `(content, {deliverAs?}) => void` |
|
|
47
52
|
| `cmd.exec` | `({command, args?, cwd?, signal?}) => Promise<{stdout, stderr, code}>` |
|
|
48
53
|
| `cmd.setSessionName` / `setModel` / `setEffort` | `(value) => void` (buffered pre-bind) |
|
|
54
|
+
| `cmd.getSessionName` / `getModel` / `getEffort` | `() => value \| undefined` (undefined pre-bind) |
|
|
55
|
+
| `cmd.getContextUsage` | `() => {tokens, contextWindow, percent} \| undefined` |
|
|
56
|
+
| `cmd.getCommands` | `() => readonly {name, description?, mod}[]` |
|
|
57
|
+
| `cmd.isIdle` | `() => boolean` |
|
|
58
|
+
| `cmd.shutdown` | `() => void` |
|
|
49
59
|
| `cmd.getAllTools` / `getActiveTools` | `() => readonly string[]` |
|
|
60
|
+
| `cmd.getToolInfo` | `() => readonly {name, description, readOnly, active}[]` |
|
|
50
61
|
| `cmd.setActiveTools` | `(names: readonly string[]) => void` |
|
|
51
62
|
|
|
52
63
|
Details:
|
|
53
64
|
|
|
54
|
-
- `cmd.ui` - `notify` (a `notice` feed row), `confirm` / `select` / `input` (the Interaction question modal in the TUI; deterministic defaults headless: false/undefined), `setStatus`, `widget`, `refreshWidgets`. The full dialog/status/widget contract is in [UI surface](./ui.md#ui-surface).
|
|
55
|
-
- `cmd.queueMessage({content, deliverAs})` - `steer` lands after the current tool batch (behind any queued user messages in the same poll), `follow-up` only when the run would stop (ahead of continuation nudges, behind queued user input).
|
|
65
|
+
- `cmd.ui` - `notify` (a `notice` feed row), `confirm` / `select` / `input` (the Interaction question modal in the TUI; deterministic defaults headless: false/undefined), `setStatus`, `widget`, `refreshWidgets`, `setTitle`. The full dialog/status/widget contract is in [UI surface](./ui.md#ui-surface).
|
|
66
|
+
- `cmd.queueMessage({content, deliverAs})` - `steer` lands after the current tool batch (behind any queued user messages in the same poll), `follow-up` only when the run would stop (ahead of continuation nudges, behind queued user input). Queued messages steer a run that is already going; they never START one.
|
|
67
|
+
- `cmd.sendUserMessage(content, {deliverAs})` - a REAL user message: echoed in the feed like typed input and, when the agent is idle, starting a turn right away. While a run is going, `steer` (default) queues it behind the active turn exactly as typing would, and `follow-up` holds it until the run would stop. Headless there is no submit path, so it falls back to `queueMessage` with the same `deliverAs`.
|
|
68
|
+
- `cmd.getSessionName()` / `getModel()` / `getEffort()` - the live values behind the setters; `undefined` before a session binds.
|
|
69
|
+
- `cmd.getContextUsage()` - `{tokens, contextWindow, percent}` for the bound session: `tokens` and `percent` are `null` until the first model call has measured the window (never a misleading 0%).
|
|
70
|
+
- `cmd.getCommands()` - every slash command mods registered on this host (`{name, description, mod}`), so a mod can discover siblings or avoid a taken name. Built-in commands are host-owned and not listed.
|
|
71
|
+
- `cmd.isIdle()` - `false` while an agent run is in flight on the bound harness (`run_start` … `run_end`), `true` otherwise and pre-bind.
|
|
72
|
+
- `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.
|
|
73
|
+
- `cmd.getToolInfo()` - the registered tools with `description`, `readOnly`, and `active` (per the mod-managed filter) - the descriptive counterpart of `getAllTools()`'s bare names.
|
|
56
74
|
- `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).
|
|
57
75
|
- `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.
|
|
58
76
|
- `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.
|
|
@@ -44,12 +44,56 @@ A package declares what it ships via `package.json` - exact paths, directories,
|
|
|
44
44
|
```json
|
|
45
45
|
{
|
|
46
46
|
"name": "@team/review-mod",
|
|
47
|
-
"
|
|
47
|
+
"description": "Blocks risky diffs and adds a /review command.",
|
|
48
|
+
"keywords": ["cmd-mod", "cmd-mod-tool", "cmd-mod-command"],
|
|
49
|
+
"repository": "https://github.com/team/review-mod",
|
|
50
|
+
"commandcode": {
|
|
51
|
+
"mods": ["./src/review.ts", "src/checks/*.ts"],
|
|
52
|
+
"skills": ["./skills"]
|
|
53
|
+
}
|
|
48
54
|
}
|
|
49
55
|
```
|
|
50
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.
|
|
63
|
+
|
|
51
64
|
No manifest → the `mods/` convention directory → a root `index.ts`, in that order.
|
|
52
65
|
|
|
66
|
+
`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
|
+
|
|
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.
|
|
69
|
+
|
|
70
|
+
## Listing a git-only mod (the curated registry)
|
|
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.
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"version": 1,
|
|
77
|
+
"hidden": [],
|
|
78
|
+
"mods": [
|
|
79
|
+
{
|
|
80
|
+
"name": "review-guard",
|
|
81
|
+
"source": "owner/review-guard",
|
|
82
|
+
"description": "Blocks risky diffs and adds a /review command.",
|
|
83
|
+
"author": {"name": "Ada", "github": "ada"},
|
|
84
|
+
"repo": "https://github.com/owner/review-guard",
|
|
85
|
+
"kinds": ["tool", "command"],
|
|
86
|
+
"tags": ["safety", "review"],
|
|
87
|
+
"official": false
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
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.
|
|
94
|
+
|
|
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.
|
|
96
|
+
|
|
53
97
|
## Filtering a source's mods
|
|
54
98
|
|
|
55
99
|
A `mods.sources` entry can be the object form to load only part of a package:
|
|
@@ -6,8 +6,9 @@ Everything a mod can put on screen rides `cmd.ui`, `cmd.addRenderer`, and `cmd.s
|
|
|
6
6
|
|
|
7
7
|
## Notifications and dialogs
|
|
8
8
|
|
|
9
|
-
- `cmd.ui.notify(message)` - a `notice` feed row.
|
|
9
|
+
- `cmd.ui.notify(message, level?)` - a `notice` feed row, styled by `level`: `'info'` (default) is a dim bullet, `'warning'` an amber ⚠, `'error'` a red ⚠. Rendered during a turn (the per-turn feed projector); a notice raised at factory time flushes once the session binds.
|
|
10
10
|
- `cmd.ui.confirm({title, message?})` / `cmd.ui.select({title, options})` / `cmd.ui.input({title, placeholder?})` - the Interaction question modal in the TUI. Headless, each resolves its deterministic default: confirm → `false`, select/input → `undefined` - never auto-approved.
|
|
11
|
+
- `cmd.ui.setTitle(text | null)` - the terminal tab title. The text replaces the session title on the tab (and survives the host's own title re-assertions) until `null` hands the tab back. Headless: no-op.
|
|
11
12
|
|
|
12
13
|
## Footer status segments and editor widgets
|
|
13
14
|
|
|
@@ -59,4 +60,8 @@ Rendering is deliberately **line-based, not component-based**: mods return style
|
|
|
59
60
|
| `select` / `input` | modal | resolves `undefined` |
|
|
60
61
|
| `setStatus` | footer segment under the input | stored, rendered nowhere |
|
|
61
62
|
| `widget` | no-op (wire-up pending) | no-op |
|
|
63
|
+
| `setTitle` | terminal tab title | no-op |
|
|
62
64
|
| `showEntry` | rendered feed row | dropped |
|
|
65
|
+
| `addShortcut` | dispatched after host bindings | never fires |
|
|
66
|
+
| `sendUserMessage` | real user turn (queued while busy) | falls back to `queueMessage` |
|
|
67
|
+
| `shutdown` | exits after the turn settles | no-op |
|