@namzu/cli 12.0.2 → 12.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +41 -374
  2. package/package.json +8 -8
package/README.md CHANGED
@@ -2,11 +2,10 @@
2
2
  type: Reference
3
3
  title: "@namzu/cli"
4
4
  description: >-
5
- The terminal agent for @namzu/sdk and the operator commands around it. Bare
6
- namzu opens an interactive session; the same binary runs one prompt headlessly,
7
- streams events for a host UI, drains parked runs and diagnoses the machine.
8
- Separate from the kernel because none of this is something a library should own.
9
- tags: [readme, package, cli, terminal-agent, operator]
5
+ A terminal coding agent built on the Namzu kernel, from the same public API
6
+ you get. Interactive sessions, headless runs that stream structured events,
7
+ and a doctor that reports what the host can actually do.
8
+ tags: [readme, package, cli, agent]
10
9
  timestamp: 2026-08-17T00:00:00Z
11
10
  status: active
12
11
  diataxis: reference
@@ -16,45 +15,36 @@ diataxis: reference
16
15
 
17
16
  <h1>@namzu/cli</h1>
18
17
 
19
- **A terminal coding agent built on [`@namzu/sdk`](https://www.npmjs.com/package/@namzu/sdk), from the same public API you get.**
18
+ **A terminal coding agent, built on [`@namzu/sdk`](https://www.npmjs.com/package/@namzu/sdk).**
20
19
 
21
- ![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)
22
- [![npm](https://img.shields.io/npm/v/@namzu/cli.svg?label=%40namzu%2Fcli)](https://www.npmjs.com/package/@namzu/cli)
20
+ [![npm](https://img.shields.io/npm/v/@namzu/cli.svg)](https://www.npmjs.com/package/@namzu/cli)
21
+ [![build](https://github.com/cogitave/namzu/actions/workflows/ci.yml/badge.svg)](https://github.com/cogitave/namzu/actions/workflows/ci.yml)
22
+ [![license](https://img.shields.io/badge/license-FSL--1.1--MIT-blue.svg)](https://github.com/cogitave/namzu/blob/main/LICENSE.md)
23
23
 
24
- [Install](#install) · [Commands](#commands) · [Headless runs](#headless-runs) · [Configuration](#configuration) · [Doctor](#namzu-doctor) · [Library](#as-a-library)
24
+ [Install](#install) · [Usage](#usage) · [Headless](#headless-runs) · [Documentation](#documentation)
25
25
 
26
26
  </div>
27
27
 
28
28
  ---
29
29
 
30
- ## What this is
31
-
32
- Bare `namzu` opens an interactive terminal agent. The same binary is scriptable:
33
- one prompt and a printed reply, one prompt and a stream of newline-delimited
34
- events for a host UI, a session's history as JSON, a health report, a pass over
35
- runs some other process left parked.
36
-
37
- It is built entirely on `@namzu/sdk`, in the same repository, out of the public
38
- API — it exists as much to prove the kernel as to be used. The kernel renders no
39
- UI, reads no config file and owns no terminal; everything in that sentence is
40
- this package's job.
41
-
42
- It is also a library. `runCli` is the whole shell as one call, and the doctor
43
- registry, the config cascade, the output formatter and the capability probe are
44
- exported on their own, for a host that wants the operator surface inside its own
45
- process rather than behind a subprocess boundary.
30
+ A terminal coding agent built entirely on the Namzu kernel, in the same
31
+ repository, from the same public API you get. It exists as much to prove the
32
+ kernel as to be used: every gap in the SDK showed up first as something the CLI
33
+ had to work around.
46
34
 
47
35
  ## Install
48
36
 
49
37
  ```bash
50
38
  npm install -g @namzu/cli # the binary
51
- npx @namzu/cli # run it once without installing
39
+ npx @namzu/cli # or run it once without installing
52
40
  ```
53
41
 
54
- There is also an installer, which checks for Node 20+, installs the package and
55
- then verifies the binary answers before claiming success. If the global prefix is
56
- not writable it retries into `~/.namzu` and names the one line to add to your
57
- profile; it never re-runs itself with elevated privileges.
42
+ Requires Node.js 20+.
43
+
44
+ There is also an installer, which checks the Node version, installs the package
45
+ and then verifies the binary answers before claiming success. If the global
46
+ prefix is not writable it retries into `~/.namzu` and names the one line to add
47
+ to your profile; it never re-runs itself with elevated privileges.
58
48
 
59
49
  ```bash
60
50
  curl -fsSL https://raw.githubusercontent.com/cogitave/namzu/main/install.sh | sh
@@ -62,362 +52,39 @@ curl -fsSL https://raw.githubusercontent.com/cogitave/namzu/main/install.sh | sh
62
52
  irm https://raw.githubusercontent.com/cogitave/namzu/main/install.ps1 | iex
63
53
  ```
64
54
 
65
- Node 20 or newer, either way.
55
+ Installing brings the kernel and four model drivers — Anthropic, OpenAI,
56
+ OpenRouter and Ollama — plus `@namzu/files`, as ordinary dependencies rather
57
+ than peers. So a fresh install can already reach any of those services, given a
58
+ credential. `@namzu/telemetry`, `@namzu/sandbox` and `@namzu/computer-use` are
59
+ **not** installed with it; they are the optional capabilities `namzu doctor`
60
+ probes for.
66
61
 
67
- Installing it brings the kernel and four model drivers — `@namzu/anthropic`,
68
- `@namzu/openai`, `@namzu/openrouter`, `@namzu/ollama` — plus `@namzu/files`.
69
- These are ordinary dependencies rather than peers, so a fresh install can already
70
- reach any of those four services, given a credential where the service wants one.
71
- `@namzu/telemetry`, `@namzu/sandbox` and `@namzu/computer-use` are **not**
72
- installed with it; they are the optional capabilities `namzu doctor` probes for.
73
-
74
- To embed it instead of installing the binary:
62
+ ## Usage
75
63
 
76
64
  ```bash
77
- pnpm add @namzu/cli
65
+ namzu # interactive session in the current directory
66
+ namzu doctor # what this host can actually do, and what is missing
67
+ namzu login # store a credential in the vault
78
68
  ```
79
69
 
80
- ## The interactive session
81
-
82
- With a terminal attached, bare `namzu` launches the terminal UI. Without one — a
83
- pipe, a CI step — it prints a single line saying an interactive session needs a
84
- terminal and exits `0`, so a script that reaches the bare binary by accident does
85
- not hang against a renderer with nothing to render into.
86
-
87
- Three things happen on the way in, and they are the difference between a toy and
88
- something you point at a real repository:
89
-
90
- - **A folder nobody has trusted is not one it works in.** Launching in an
91
- unfamiliar working directory stops and asks, because reading files, running
92
- commands and editing code there is what it is about to be able to do. Accepting
93
- the prompt trusts the folder permanently; `--trust` accepts it for one run and
94
- deliberately does not remember.
95
- - **The repository gets to state how it wants work done.** `AGENTS.md` is read
96
- from the working directory upward to the repository root, outermost first, so
97
- the file nearest the work has the final word. The files that were loaded are
98
- named on stderr, and one that was skipped is named with its reason — a refusal
99
- that says nothing is indistinguishable from a project that declared nothing.
100
- - **It connects the tool servers you declare.** Each server's tools arrive
101
- prefixed with its name (`mcp_tickets_create`), so two servers offering `search`
102
- do not collide. A server that fails to start is named with its reason: the
103
- interactive session reports and carries on, because a person can read the line
104
- and decide, and a headless run refuses, because nobody is watching.
105
-
106
- Inside the session: `/help`, `/tools`, `/skills`, `/skill`, `/resume`,
107
- `/provider`, `/model`, `/permissions`, `/cost`, `/memory`, `/remember`,
108
- `/expand`, `/init`, `/login`, `/logout`, `/clear`, `/feedback`, `/quit`,
109
- `/exit`. Commands the kernel's own registry contributes are merged in beside
110
- them; a name claimed by both raises an error rather than letting one silently
111
- shadow the other.
112
-
113
- ## Commands
114
-
115
- | Command | What it does |
116
- |---|---|
117
- | `namzu` | The interactive terminal agent |
118
- | `namzu run <prompt…>` | One prompt, headless. The reply goes to stdout, status lines to stderr |
119
- | `namzu run-stream <prompt…>` | The same run, one JSON event per line, for a host UI that renders progress |
120
- | `namzu history --session <id>` | That session's persisted messages, as JSON |
121
- | `namzu skills-json` | The skills discovered for a working directory, as JSON |
122
- | `namzu providers-json` | Providers and their per-provider models, as JSON |
123
- | `namzu doctor` | Health checks against this machine |
124
- | `namzu login` / `namzu logout` | Store, or remove, a provider subscription credential |
125
- | `namzu drain` | Continue runs another process left behind — one pass, then exit |
126
- | `namzu eval` | Run eval suites and set an exit code |
127
- | `namzu acp` | Speak the agent-client protocol over this process's stdio |
128
- | `namzu serve` | Answers that there is no daemon: a run is an ordinary process |
129
- | `namzu skills` | **Not implemented.** Prints a marker naming the milestone that will implement it, rather than answering "unknown command" |
130
-
131
- Options that belong to the program rather than to a command go **before** the
132
- subcommand: `-f, --format text|json|yaml`, `-q, --quiet`, `-v, --verbose`,
133
- `--log-format pretty|json`, `--dangerously-skip-permissions` (alias `--yolo`),
134
- `-V, --version`. `namzu run "…" --verbose` is the order a person types and it is
135
- refused, but the refusal names the option as positional — "try `namzu --verbose
136
- <command> …`" — rather than handing back the generic advice about prompts that
137
- begin with a dash, which is about the wrong half of that command line.
138
-
139
- `namzu drain` deserves one sentence, because its shape is a decision rather than
140
- a limitation: namzu has no daemon, so continuing parked runs is a command your
141
- scheduler invokes, not a service that sits there. It takes every run under a
142
- `--tenant`/`--project`/`--session` scope that no worker currently holds,
143
- continues it from its last checkpoint, releases it, and exits. A run parked on a
144
- human decision is reported, never resumed past — the answer belongs to a person,
145
- and a drainer that continued without it would discard the question the run
146
- stopped to ask.
147
-
148
70
  ## Headless runs
149
71
 
150
- `namzu run` and `namzu run-stream` are the same one-shot differing only in how
151
- they print, and they share one argument parser, so an option honoured by one is
152
- honoured by the other.
153
-
154
72
  ```bash
155
- namzu run "what does this repository build?"
156
- echo "summarise this" | namzu run
157
- cat notes.txt | namzu run "summarise this"
158
- namzu run --cwd ../service --gate 'pnpm typecheck' --gate 'pnpm test' "fix the failing test"
73
+ namzu run "fix the failing test" --format json
74
+ namzu run-stream "refactor the parser" | jq -c 'select(.type == "tool_call")'
159
75
  ```
160
76
 
161
- Piped input is used rather than discarded. With no prompt argument it *is* the
162
- prompt; alongside one it is appended as material the question is about, fenced in
163
- a `<stdin>` tag so the last line of a file cannot run into the request. `namzu
164
- run -` reads the prompt from stdin explicitly. Everything that is not an option
165
- is the prompt — and an option this parser does not recognise is refused rather
166
- than read aloud to the model, which is the worst available response to a typo.
167
-
168
- | Option | What it does |
169
- |---|---|
170
- | `--cwd <path>` | Directory the agent works in. A path that is missing or is not a directory is refused, never silently ignored |
171
- | `--provider <id>` | Replaces the provider chain with this provider alone |
172
- | `--model <id>` | Re-models the existing primary and leaves the rest of the chain intact |
173
- | `--skills <a,b,c>` | Load these skills as context for the turn, resolved under `--cwd` |
174
- | `--session <id>` | Bind `run-stream` (and `history`) to a session |
175
- | `--continue`, `-c` | Resume the most recent conversation here (`run`) |
176
- | `--resume <id>` | Resume that conversation and no other (`run`) |
177
- | `--gate <command>` | Must exit `0` before the run may settle. Repeatable; they run in order and stop at the first failure |
178
- | `--gate-retries <n>` | Fix attempts a failing gate allows. Default `3` |
179
- | `--permission-mode <m>` | `prompt`, `auto` or `strict` — what happens to a call no rule decided. `auto` when there is nobody to ask |
180
- | `--trust` | Accept this working directory for this run only |
181
- | `--yolo` | Alias of `--dangerously-skip-permissions`: resolves undecided calls to `auto`. It does **not** imply `--trust` |
182
- | `--` | End of options; everything after it is the prompt verbatim |
183
-
184
- `--continue` and `--resume` are `run` options and are refused by `run-stream`
185
- rather than ignored. Neither ever falls back to starting a fresh conversation:
186
- somebody who asked for a specific one and got a new one that looks the same finds
187
- out several turns later, having already acted on it.
188
-
189
- **`--gate` is the unattended-operator flag.** The run is not allowed to settle
190
- until every gate command exits `0`. A failure comes back to the model as the next
191
- turn, naming the command, the exit code and the output; a gate is not re-run when
192
- the answer changed nothing on disk, because "the workspace is unchanged" is a
193
- different instruction from repeating a failure the model has already been shown.
194
- When the attempts run out the run stops with `answer_rejected` and a non-zero
195
- exit — never a green run over a red build.
196
-
197
- The two commands report failure differently, on purpose, because their callers
198
- listen for different things. `run` answers a shell: `0` on a reply, `1` on a
199
- failed or unfinished run (including one stopped by a budget, a timeout, an
200
- iteration cap or a blocking guardrail, where the partial text still prints), `2`
201
- when no prompt was supplied, `64` when an argument is wrong, `77` when the folder
202
- has not been trusted and nothing ran. `run-stream` answers a line-scanning host,
203
- so every failure is an `error` event on stdout and the exit code says only
204
- whether the caller could reach the run by sending something else: `0` when they
205
- could, `1` when they could not, `77` for the untrusted folder that only a person
206
- can change.
207
-
208
- ## Configuration
209
-
210
- Highest precedence first:
211
-
212
- 1. Command-line flags
213
- 2. `NAMZU_*` environment variables
214
- 3. `./namzu.config.json` — the project's
215
- 4. `~/.namzu/config.yaml` — the user's
216
- 5. Built-in defaults (`format: 'text'`, `quiet: false`)
217
-
218
- A file that is not there contributes nothing, and that is a default. A file that
219
- **is** there and cannot be established — invalid YAML or JSON, a permission
220
- error, a top level that is not a mapping — stops the CLI with exit `78` instead
221
- of continuing on settings it failed to read. That refusal is load-bearing:
222
- `permissions` is read from these files, so an unreadable config degrading to `{}`
223
- would turn an operator's deny list into approval of the same calls, on the one
224
- path where nobody is watching.
225
-
226
- | Key | Shape | Notes |
227
- |---|---|---|
228
- | `format` | `'text' \| 'json' \| 'yaml'` | Default `text`. Also `NAMZU_FORMAT` |
229
- | `quiet` | `boolean` | Default `false`. Also `NAMZU_QUIET` (`1`/`true`/`0`/`false`) |
230
- | `permissions` | tool → effect, or tool → { pattern → effect } | Effects are `allow`, `ask`, `deny`. Absent means every mutating tool prompts |
231
- | `mcpServers` | name → `{ command, args }` or `{ url }` | Tools arrive prefixed with the server's name |
232
- | `sandbox` | `{ enabled?, requireIsolation? }` | `enabled` defaults to **on**. `requireIsolation` lists the controls (`filesystem`, `network`, `process`) this machine must actually enforce, or the run refuses to start |
233
- | `telemetry` | `{ sessionExport?: { destination, eventTypes?, redactors? } }` | Writes run events to a JSONL file. `redactors: []` means no redaction and has to be written to mean it |
234
-
235
- Only `format` and `quiet` are settable from the environment. `telemetry` is
236
- deliberately not: a variable in a shell profile could otherwise start exporting
237
- conversation content with nothing in the config file to show for it. Separately,
238
- `NAMZU_LOG_LEVEL` and `NAMZU_LOG_FORMAT` govern the log records on stderr rather
239
- than this config, and `--verbose` / `--quiet` on the command line beat them.
240
-
241
- ```json
242
- {
243
- "permissions": {
244
- "bash": { "git status*": "allow", "git push*": "deny", "*": "ask" },
245
- "write": "ask"
246
- },
247
- "mcpServers": {
248
- "tickets": { "command": "node", "args": ["./tickets-server.js"] }
249
- },
250
- "sandbox": { "requireIsolation": ["filesystem", "network"] }
251
- }
252
- ```
253
-
254
- A pattern ending in `<space>*` also matches the bare command, so `git push *`
255
- covers `git push`. A line that cannot be compiled is reported by name and the
256
- rest still load — a permission somebody believes is in force and which was
257
- silently dropped is the worst outcome available here.
258
-
259
- **A permission mode only decides the calls no rule decided.** A rule that denied
260
- a call already stopped it and a rule that allowed one never asked, so neither
261
- reaches the mode: `--permission-mode` can never reopen a `deny`. The
262
- dangerous-pattern floor sits above both, and no mode reaches that either — which
263
- is why `--yolo` promises more than it delivers, on purpose.
264
-
265
- ## `namzu doctor`
266
-
267
- ```bash
268
- namzu doctor # human-readable, every category
269
- namzu doctor --json # machine-readable report
270
- namzu doctor --category sandbox,runtime # sandbox, providers, vault, telemetry, runtime, plugins, custom
271
- namzu doctor --per-check-timeout 8000 # default 5000
272
- namzu doctor --wall-clock-timeout 20000 # default 10000
273
- namzu doctor --verbose # repeat the failures, with their messages
274
- ```
275
-
276
- The built-in checks, in the order they are reported:
277
-
278
- | Check | Category | What it establishes |
279
- |---|---|---|
280
- | `sandbox.platform` | `sandbox` | What this host will actually confine — asked of the local sandbox provider, not answered from a table keyed on the OS name |
281
- | `runtime.cwd-writable` | `runtime` | `W_OK` on the working directory |
282
- | `runtime.tmpdir-writable` | `runtime` | `W_OK` on the temp directory |
283
- | `providers.registered` | `providers` | Skipped: there is no provider auto-discovery, so a host registers its own check |
284
- | `providers.credentials` | `providers` | Which credential sources were scanned, and what each yielded |
285
- | `providers.chain` | `providers` | Which of the credentials found are actually wired into the chain, member by member |
286
- | `vault.registered` | `vault` | Each registered credential provider's refs — *described*, never resolved, because this output gets pasted into issues |
287
- | `sandbox.installed` | `sandbox` | `@namzu/sandbox`: absent, present, or installed and failing to load |
288
- | `files.installed` | `custom` | `@namzu/files`, same three states |
289
- | `computer-use.installed` | `custom` | `@namzu/computer-use`, same three states |
290
- | `telemetry.installed` | `telemetry` | `@namzu/telemetry`, same three states |
291
- | `logging.pipeline` | `custom` | What the log pipeline did to the records every check above just produced — dropped, redacted, truncated |
292
- | `runtime.invariants` | `runtime` | Every registered invariant, folded with its violation counter |
293
- | `telemetry.session-export` | `telemetry` | What this invocation's configuration would send off the machine, in a sentence |
294
-
295
- Those four `*.installed` rows are the tri-state capability probe, not a
296
- `try { await import() } catch`. Resolving and loading are asked separately so
297
- that "not installed" and "installed and broken" cannot collapse into one answer:
298
- the first is an optional package legitimately absent, the second is a machine
299
- running degraded, and telling somebody who already has the package to install it
300
- is useless advice.
301
-
302
- Exit codes:
303
-
304
- | Code | Meaning |
305
- |---|---|
306
- | `0` | Every check answered, and none of them failed |
307
- | `1` | One or more checks reported `fail` |
308
- | `2` | No checks registered — namzu is not configured here |
309
- | `64` | An argument to `doctor` is wrong. Distinct from `70`: `70` says this CLI is broken and is worth a bug report, `64` says the invocation is |
310
- | `69` | A check could not answer — it timed out, was aborted, or what it reads threw. Separate from `0` because a report that did not manage to look tells you nothing about the part it did look at, and separate from `1` because nothing was established to have failed |
311
- | `70` | Internal CLI error |
312
-
313
- A `skipped` check never moves the code off `0`. An optional package absent or a
314
- registry with nothing to discover is an ordinary state of a healthy machine, and
315
- a diagnostic that went non-zero on every healthy machine would be switched off
316
- within a week.
317
-
318
- The full page, including what each status word means, is
319
- [`docs/cli/doctor.md`](../../docs/cli/doctor.md).
320
-
321
- ## As a library
322
-
323
- The whole shell, as one call:
324
-
325
- ```ts
326
- import { runCli } from '@namzu/cli'
327
-
328
- process.exit(await runCli({ argv: process.argv }))
329
- ```
330
-
331
- The reason to run the doctor in-process rather than shelling out to the binary is
332
- visibility: `registerDoctorCheck` writes to a process-wide registry, so a check
333
- your application registers is only seen by a `runDoctor()` in the same process.
334
-
335
- ```ts
336
- import { registerDoctorCheck, runDoctor } from '@namzu/cli'
337
-
338
- registerDoctorCheck({
339
- id: 'app.queue.reachable',
340
- category: 'custom',
341
- run: async () => {
342
- const url = process.env.QUEUE_URL
343
- if (!url) return { status: 'skipped', message: 'QUEUE_URL is not set' }
344
- const response = await fetch(`${url}/health`)
345
- return response.ok
346
- ? { status: 'pass', message: `queue answered ${response.status}` }
347
- : {
348
- status: 'fail',
349
- message: `queue answered ${response.status}`,
350
- remediation: 'Check QUEUE_URL and the broker credentials.',
351
- }
352
- },
353
- })
354
-
355
- const report = await runDoctor()
356
- process.exit(report.exit)
357
- ```
358
-
359
- `createDoctorRegistry()` returns an isolated registry for a test, and
360
- `runDoctor({ registry })` runs against it instead of the singleton.
361
- `builtInDoctorChecks` is the array the binary registers, exported so an embedder
362
- can start from the same set. The individual checks are exported too —
363
- `sandboxPlatformCheck`, `cwdWritableCheck`, `tmpdirWritableCheck`,
364
- `providersRegisteredCheck`, `credentialSourcesCheck`, `providerChainCheck`,
365
- `vaultRegisteredCheck`, `sandboxInstalledCheck`, `filesInstalledCheck`,
366
- `computerUseInstalledCheck`, `telemetryInstalledCheck` — for registering a subset.
367
-
368
- **Why the split runs where it does.** The doctor's protocol types
369
- (`DoctorCheck`, `DoctorCheckResult`, `DoctorReport`, `DoctorStatus`) live in
370
- `@namzu/sdk`, so a provider, a vault or a sandbox can implement a
371
- `doctorCheck?()` hook against them without depending on an operator application.
372
- The registry, the runner, the formatting and the exit codes live here, because
373
- those are operator-facing concerns. The kernel owns the contract; this package
374
- owns the presentation.
375
-
376
- Also exported, and each of them is what the binary itself uses rather than a
377
- parallel implementation:
378
-
379
- ```ts
380
- import {
381
- createFormatter,
382
- loadConfigWithProvenance,
383
- NAMZU_OPTIONAL_CAPABILITIES,
384
- probeCapabilities,
385
- } from '@namzu/cli'
386
-
387
- const { config, provenance } = loadConfigWithProvenance()
388
- console.log(config.format, provenance.format) // e.g. 'json' { kind: 'env', variable: 'NAMZU_FORMAT' }
389
-
390
- const out = createFormatter('json', { quiet: false })
391
- out.print({ ready: true })
392
-
393
- console.log(NAMZU_OPTIONAL_CAPABILITIES)
394
- // ['@namzu/sandbox', '@namzu/files', '@namzu/computer-use', '@namzu/telemetry']
395
-
396
- for (const probe of await probeCapabilities()) {
397
- console.log(probe.specifier, probe.state) // 'present' | 'absent' | 'broken'
398
- }
399
- ```
400
-
401
- `ConfigProvenance` names which cascade layer won each key, down to *which*
402
- `NAMZU_*` variable it was — "env" alone would not tell an operator what to
403
- change. `loadConfig()` is the same cascade without the provenance.
404
- `probeOptionalPackage(specifier)` probes one package instead of all four.
405
- `registerCommand` / `registerAll` add a `CommandDef` to a Commander program, and
406
- `DEFAULT_CONFIG`, `ConfigLoadError`, `isFormatName` and `runDoctorCommand` round
407
- out the surface.
408
-
409
- ## Status
77
+ `run` prints a result; `run-stream` emits one structured event per line as the
78
+ run happens, so a script can act on a tool call before the run is over. Both
79
+ take `--verbose`/`--quiet`, and both write logs to stderr so stdout stays a
80
+ clean protocol stream.
410
81
 
411
- Published — the badge above is live, so it cannot go stale here — and dogfooded
412
- in this repository, whose own `.namzu/` runtime state is written by this binary.
82
+ ## Documentation
413
83
 
414
- **Majors move quickly.** *Any* backward-incompatible change to a public API is
415
- treated as a major however small the diff, so the version number tracks the
416
- surface rather than the size of the work, and it climbs faster than you may
417
- expect. Pin your dependency and read the changelog. The library surface listed
418
- above is held by a baseline check in CI, so a symbol cannot quietly leave the
419
- barrel between releases — but it can leave loudly, in a major.
84
+ - [The operator application](https://github.com/cogitave/namzu/blob/main/docs/cli/reference.md) — every command, the configuration surface, headless event shapes
85
+ - [`namzu doctor`](https://github.com/cogitave/namzu/blob/main/docs/cli/doctor.md)
86
+ - [All docs](https://github.com/cogitave/namzu/tree/main/docs)
420
87
 
421
88
  ## License
422
89
 
423
- MIT.
90
+ FSL-1.1-MIT, converting to MIT two years after each release.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/cli",
3
- "version": "12.0.2",
3
+ "version": "12.0.4",
4
4
  "description": "Operator CLI for the Namzu agent platform — namzu doctor + future commands. Dual-purpose: standalone bin (`namzu doctor`) and library (`import { runDoctor } from '@namzu/cli'`).",
5
5
  "keywords": [
6
6
  "namzu",
@@ -44,12 +44,12 @@
44
44
  "ink": "^7.0.3",
45
45
  "react": "^19.2.6",
46
46
  "yaml": "^2.9.0",
47
- "@namzu/anthropic": "3.3.1",
48
- "@namzu/files": "1.0.0",
49
- "@namzu/ollama": "2.1.0",
50
- "@namzu/openai": "1.2.1",
51
- "@namzu/openrouter": "2.2.0",
52
- "@namzu/sdk": "^30.0.0"
47
+ "@namzu/anthropic": "3.4.0",
48
+ "@namzu/files": "1.1.0",
49
+ "@namzu/ollama": "2.2.0",
50
+ "@namzu/openai": "1.3.0",
51
+ "@namzu/openrouter": "2.3.0",
52
+ "@namzu/sdk": "^30.1.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@biomejs/biome": "^1.9.4",
@@ -58,7 +58,7 @@
58
58
  "ink-testing-library": "^4.0.0",
59
59
  "typescript": "^5.5.0",
60
60
  "vitest": "^3.2.6",
61
- "@namzu/telemetry": "2.1.0"
61
+ "@namzu/telemetry": "2.2.0"
62
62
  },
63
63
  "engines": {
64
64
  "node": ">=20.0.0"