@kontextmind/kxm 0.7.92 → 0.7.93
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/.claude-plugin/marketplace.json +1 -1
- package/.kxm/workflows/default.yaml +1 -1
- package/CHANGELOG.md +204 -0
- package/README.md +3 -0
- package/docs/README.md +3 -0
- package/docs/agent-skills.md +123 -60
- package/docs/architecture.md +5 -2
- package/docs/cli-reference.md +3527 -0
- package/docs/config-reference.md +1943 -0
- package/docs/configuration.md +29 -3
- package/docs/continuous-improvement.md +122 -10
- package/docs/contracts/routing.md +95 -11
- package/docs/harness-routing.md +616 -0
- package/docs/kxm-handbook.md +106 -19
- package/docs/templates/README.md +1 -1
- package/docs/test-matrix.md +12 -6
- package/docs/troubleshooting.md +2 -2
- package/examples/project/.kxm/workflows/fix.yaml +1 -1
- package/examples/project/.kxm/workflows/improve.yaml +1 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +9 -10
- package/plugins/kxm/README.md +238 -56
- package/plugins/kxm/dist/claude-hook.js +10083 -0
- package/plugins/kxm/dist/cli.js +3068 -2446
- package/plugins/kxm/dist/client.js +64 -0
- package/plugins/kxm/dist/core.js +102 -9
- package/plugins/kxm/dist/extension.js +210 -68
- package/plugins/kxm/dist/mcp-server.js +217 -40
- package/plugins/kxm/dist/runtime-supervisor.js +1628 -157
- package/plugins/kxm/dist/runtime.js +1874 -298
- package/plugins/kxm/dist/server.js +416 -82
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/hints.json +1 -1
- package/plugins/kxm/skills/kxm/SKILL.md +48 -24
- package/plugins/kxm/skills/kxm/references/protocol.md +3 -3
- package/plugins/kxm/skills/kxm-context-memory/SKILL.md +61 -21
- package/plugins/kxm/skills/kxm-definitions/SKILL.md +9 -0
- package/plugins/kxm/skills/kxm-harness-auth/SKILL.md +82 -16
- package/plugins/kxm/skills/kxm-harvest/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +55 -27
- package/plugins/kxm/skills/kxm-insights/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-mind/SKILL.md +2 -2
- package/plugins/kxm/skills/{kxm-setup → kxm-mind-setup}/SKILL.md +4 -4
- package/plugins/kxm/skills/kxm-peer/SKILL.md +68 -93
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +156 -23
- package/plugins/kxm/skills/kxm-projects/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-protocol/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-query/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-routing-improve/SKILL.md +74 -15
- package/plugins/kxm/skills/kxm-runs/SKILL.md +46 -17
- package/plugins/kxm/skills/kxm-session/SKILL.md +64 -36
- package/plugins/kxm/skills/kxm-skill-lifecycle/SKILL.md +44 -15
- package/plugins/kxm/skills/kxm-tasks/SKILL.md +16 -4
- package/plugins/kxm/skills/kxm-triage/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-work/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-workflow/SKILL.md +60 -19
- package/plugins/kxm/src/arbiter.ts +67 -22
- package/plugins/kxm/src/autocomplete.ts +1 -1
- package/plugins/kxm/src/claude-hook.ts +192 -0
- package/plugins/kxm/src/cli/project.ts +11 -5
- package/plugins/kxm/src/cli/system.ts +85 -13
- package/plugins/kxm/src/cli/types.ts +4 -1
- package/plugins/kxm/src/cli/workflows.ts +18 -16
- package/plugins/kxm/src/cli.ts +23 -13
- package/plugins/kxm/src/client.ts +15 -4
- package/plugins/kxm/src/commands.ts +19 -9
- package/plugins/kxm/src/config.ts +42 -7
- package/plugins/kxm/src/context-packet.ts +14 -2
- package/plugins/kxm/src/context.ts +16 -5
- package/plugins/kxm/src/dispatch-context.ts +286 -0
- package/plugins/kxm/src/engine-plan.ts +40 -0
- package/plugins/kxm/src/engine.ts +138 -6
- package/plugins/kxm/src/hub-env.ts +17 -1
- package/plugins/kxm/src/hub.ts +92 -29
- package/plugins/kxm/src/improve-sources.ts +228 -0
- package/plugins/kxm/src/improve.ts +325 -140
- package/plugins/kxm/src/local-snapshot.ts +101 -42
- package/plugins/kxm/src/mcp-server.ts +129 -30
- package/plugins/kxm/src/project-config.ts +25 -0
- package/plugins/kxm/src/protocol.ts +11 -0
- package/plugins/kxm/src/relevance.ts +138 -0
- package/plugins/kxm/src/retrospective.ts +16 -10
- package/plugins/kxm/src/runtime-service.ts +8 -1
- package/plugins/kxm/src/runtime-supervisor.ts +16 -2
- package/plugins/kxm/src/session-token-hint.ts +17 -0
- package/plugins/kxm/src/suggest.ts +7 -7
- package/plugins/kxm/src/workflow-manager.ts +80 -78
- package/plugins/kxm/src/workflow.ts +202 -12
- package/scripts/build-runtime.mjs +7 -1
- package/scripts/check-generated.mjs +1 -0
- package/scripts/emit-codex-artifacts.mjs +1 -1
|
@@ -0,0 +1,3527 @@
|
|
|
1
|
+
# KXM CLI reference
|
|
2
|
+
|
|
3
|
+
This page documents every command and subcommand the `kxm` operator CLI registers in KXM 0.7.1 (`@kontextmind/kxm`). For each command it states what the command does, which files and services it reads and writes, whether it needs a running hub or the KXM Runtime supervisor, what `--json` returns, and the exit codes and refusal codes you are likely to see. It supersedes the "Complete CLI guide" section of the [KXM Handbook](kxm-handbook.md). Environment variables are described in [Configuration](configuration.md); this page names them only where a command reads them directly.
|
|
4
|
+
|
|
5
|
+
Output shown under examples was captured from KXM 0.7.1 run from a source checkout, inside a throwaway Git repository, with `HOME`, `KXM_STATE_HOME`, `KXM_USER_CONFIG_DIR`, and the XDG directories pointed at a temporary directory, no harness CLIs on `PATH`, and (where a hub was needed) a disposable hub on a random loopback port. Paths are shortened to `/work/proj` (the project), `/work/kxm` (the KXM checkout), `/state` (the user state root), and `~/.config/kxm` (the user config directory); session tokens are replaced with `<token>`, the machine's host name with `host.local`, and long JSON is trimmed with `...`. Every command either plans under `--dry-run` without changing anything or refuses the flag (see [Dry runs](#dry-runs)); the dry-run examples were captured from the current source tree, with a digest of the throwaway tree taken before and after to confirm that nothing was written. An example captioned "Not run" was not executed for this reference because it starts a long-lived process, writes durable state, stores credentials, or calls an external service; its output is not shown.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Invoking the CLI](#invoking-the-cli)
|
|
10
|
+
- [Global options](#global-options)
|
|
11
|
+
- [Output conventions](#output-conventions)
|
|
12
|
+
- [Where commands read and write](#where-commands-read-and-write)
|
|
13
|
+
- [Task to command](#task-to-command)
|
|
14
|
+
- Setup: [`init`](#kxm-init), [`config`](#kxm-config), [`completion`](#kxm-completion), [`trust`](#kxm-trust)
|
|
15
|
+
- Hub and sessions: [`hub`](#hub-commands), [`session`](#kxm-session), [`dash`](#kxm-dash), [`studio`](#kxm-studio)
|
|
16
|
+
- Harnesses, models, and roles: [`harness`](#kxm-harness), [`auth`](#kxm-auth), [`update`](#kxm-update), [`models`](#kxm-models), [`routes`](#kxm-routes), [`role`](#kxm-role)
|
|
17
|
+
- Running work: [`run`](#kxm-run), [`runs`](#kxm-runs), [`runtime`](#kxm-runtime), [`agent`](#kxm-agent), [`workflow`](#kxm-workflow), [`gate`](#kxm-gate), [`peer`](#kxm-peer), [`task`](#kxm-task), [`goal`](#kxm-goal), [`suggest`](#kxm-suggest), [`explain`](#kxm-explain)
|
|
18
|
+
- Context and learning: [`context`](#kxm-context), [`memory`](#kxm-memory), [`skills`](#kxm-skills), [`improve`](#kxm-improve), [`routing`](#kxm-routing)
|
|
19
|
+
- Operations: [`backup`](#kxm-backup), [`restore`](#kxm-restore), [`tenant`](#kxm-tenant), [`ssh`](#kxm-ssh), [`help`](#kxm-help)
|
|
20
|
+
- [Known behavior gaps in 0.7.1](#known-behavior-gaps-in-071)
|
|
21
|
+
|
|
22
|
+
## Invoking the CLI
|
|
23
|
+
|
|
24
|
+
An installed CLI is on `PATH` as `kxm`. Install it from the versioned release tarball as described in the [KXM Handbook](kxm-handbook.md#install-the-kxm-operator-cli).
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
kxm --help
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
Usage: kxm [options] [command]
|
|
32
|
+
|
|
33
|
+
KXM local-first orchestration CLI
|
|
34
|
+
...
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
From a source checkout, run the wrapper script instead. It executes the committed `plugins/kxm/dist/cli.js`, so run `npm run build` after changing CLI source.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
node scripts/kxm.mjs --help
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Everywhere this page shows `kxm`, a source checkout can substitute `node scripts/kxm.mjs`.
|
|
44
|
+
|
|
45
|
+
Help is available at every level and exits 0:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
kxm workflow --help
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
kxm help workflow
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
kxm workflow help start
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Running a command group without a subcommand prints that group's help and exits 2. Five groups have a default subcommand instead: `kxm config` runs `config list`, `kxm role` runs `role list`, `kxm goal` runs `goal list`, `kxm task` runs `task list`, and `kxm improve` runs `improve report`. `kxm models` opens an interactive screen.
|
|
60
|
+
|
|
61
|
+
## Global options
|
|
62
|
+
|
|
63
|
+
| Option | Argument | Default | Description |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| `--json` | none | off | Print machine-readable JSON |
|
|
66
|
+
| `--dry-run` | none | off | Plan without making changes |
|
|
67
|
+
| `--workspace` | `<dir>` | `.kxm` (or `KXM_WORKSPACE_DIR`) | Workspace directory |
|
|
68
|
+
| `-V`, `--version` | none | none | Print the installed kxm version |
|
|
69
|
+
| `-h`, `--help` | none | none | display help for command |
|
|
70
|
+
|
|
71
|
+
- `--json`, `--dry-run`, and `--workspace` are registered on the root, on every group, and on every subcommand, so `kxm --json config list`, `kxm config --json list`, and `kxm config list --json` are equivalent.
|
|
72
|
+
- `kxm init` registers only `--json` and `--dry-run`. It, `kxm trust diff`, `kxm trust check`, `kxm run`, and `kxm task run` refuse `--workspace` (including a root-level `--workspace`) with exit 2 and error `workspace_option_unsupported`, because they discover the project from the current directory.
|
|
73
|
+
- `--workspace <dir>` resolves against `KXM_WORKDIR` (or the current directory) and derives `config/`, `logs/`, `assets/`, and `state/` under it, overriding `KXM_CONFIG_DIR`, `KXM_LOGS_DIR`, `KXM_ASSETS_DIR`, and `KXM_STATE_DIR`. Only commands that use workspace directories are affected; see [Where commands read and write](#where-commands-read-and-write).
|
|
74
|
+
- `--version` ignores `--json` and prints the bare version.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
kxm -V
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
0.7.1
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Output conventions
|
|
85
|
+
|
|
86
|
+
### JSON results
|
|
87
|
+
|
|
88
|
+
- Every JSON result carries a `schema` field. Most commands print `kxm.cli-result.v1` with `ok` and `command` fields plus command-specific keys.
|
|
89
|
+
- Gate-style commands print a `kxm.worker-result.v1` envelope, which adds `worker`, `createdAt`, `outcome` (`passed`, `warning`, or `failed`), and `summary`: `gate validate`, `gate artifacts-exist`, `gate degrade`, `gate signal`, `workflow signal`, `gate github watch`, and `agent worker --dry-run`. Outside `--dry-run`, the `gate` subcommands and `workflow signal` also append the envelope to `.kxm/logs/telemetry.jsonl`.
|
|
90
|
+
- `session brief` prints `kxm.session-brief.v1` and `tenant status` prints `kxm.tenant-status.v1`.
|
|
91
|
+
- The `command` field is not always the words you typed: `hub stop` and `session stop` report `stop`, `session token` reports `auth token`, `routes admit` and `routes disable` report `routes admitted` and `routes disabled`, `models inventory-refresh` reports `models inventory refresh`, `workflow export` reports `retrospective export`, `gate degrade` reports `workflow degrade`, `gate signal` and `workflow signal` report `signal`, `gate github watch` reports `github watch`, `agent worker` reports `worker`, and `improve report` reports `improve`.
|
|
92
|
+
- A result with `ok: false` is written to stderr in both text and JSON mode; everything else goes to stdout. `runtime status` is the exception: when the supervisor is down it prints `ok: true, running: false` on stdout and exits 1.
|
|
93
|
+
- `peer` subcommands and `workflow checkpoint|record|wait` print the hub's result object as returned, tagged with `schema` but without `ok` or `command`. Their failures print `{"ok":false,"error":"command_failed","detail":"..."}`. Text mode prints the same JSON.
|
|
94
|
+
- Several error paths ignore `--json` and print one plain line on stderr: argument checks in `agent worker`, `session start`, `workflow start`, `gate degrade`, `gate signal`, and `gate github watch`; every error from `config`, `role`, `workflow definitions|add|remove|modify` (except the three `workflow add --template` refusals, which honor `--json`), `goal`, `task`, `memory`, `skills` (other than `skills create --dry-run`), `suggest`, `studio`, and `completion`. Check the exit code before parsing stdout.
|
|
95
|
+
- Every `context` subcommand exits 1 with a Node.js stack trace and no JSON when the hub cannot be reached.
|
|
96
|
+
- Output is redacted. Values of environment variables whose names contain `TOKEN`, `SECRET`, `KEY`, or `PASSWORD` are replaced with `[redacted]`, and 64-character hex strings are replaced unless they appear in a known digest field such as `configRevision` or `sha256`. `session brief` and `auth token` print the session token itself; treat their output as a credential.
|
|
97
|
+
|
|
98
|
+
### Dry runs
|
|
99
|
+
|
|
100
|
+
`--dry-run` changes nothing: no file is written, deleted, or moved, no request that changes hub or Runtime state is sent, no process is started, and no remote command runs. A command that cannot say what it would do without doing some of it refuses the flag instead of acting.
|
|
101
|
+
|
|
102
|
+
- Plan with `planned`: `backup`, `restore`, `config set`, `role add|remove|modify|set-host|resume`, `workflow add|remove|modify`, `goal create`, `task create|run|sync`, `memory note|sync`, `skills evaluate|promote|reject`, `context promote`, `context wiki-compile --out`, `auth token`, `session token`, `session brief`, and `ssh run|file|close`. Each prints its normal result plus `dryRun: true` and `planned`, a list of `{action, target}` entries whose `action` is `write`, `delete`, `move`, `request`, or `ssh`. Text mode prints `dry run: <summary>` and one indented `would <action> <target>` line per entry (`session brief` appends `dry run: would write <file>` lines to the brief instead).
|
|
103
|
+
- Plan in their own shape (described in each section): `init`, `run`, `runs drive|cancel`, `runtime start|stop|sync-retry`, `hub start|stop|bind|unbind`, `session start|stop`, `agent worker`, `dash`, `studio serve`, `models inventory-refresh`, `routes admit|disable`, `update`, `completion install`, `workflow start|signal|export|checkpoint|record|wait`, every `peer` subcommand, `gate degrade|signal`, `skills create`, and `improve report`. `gate github watch --dry-run` still polls GitHub but does not post the signal.
|
|
104
|
+
- Read-only commands run as usual, without leaving a trace: a local SQLite store is opened without creating `-wal` or `-shm` files, and `runs status|list|receipt` only attach to a running Runtime supervisor. With no supervisor running they exit 2 with `dry_run_unsupported` instead of starting one. `context wiki-compile --dry-run` still asks the hub to compile, which is a read.
|
|
105
|
+
- Refused: `kxm models` (the interactive screen) exits 2 with `dry_run_unsupported`. The CLI keeps one list of the commands that answer `--dry-run` and refuses every other command the same way before it runs, so a command added without dry-run support fails closed.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
kxm config set user.theme light --dry-run
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
dry run: set user.theme = light in project config
|
|
113
|
+
would write /work/proj/.kxm/config.yaml
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
kxm models --dry-run --json
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```text
|
|
121
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"models","dryRun":true,"error":"dry_run_unsupported","detail":"this command cannot plan without making changes; rerun without --dry-run"}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
For this page, 63 `--dry-run` invocations (every command in the first list, the refusals, and a sample of the others) ran in a throwaway project seeded with a role, a global workflow, a task, a goal, a skill candidate with passing evaluations, a WAL-mode hub store, and a backup, with no harness CLIs on `PATH`. A digest of every file under the temporary root before and after showed nothing created, changed, or removed; no Runtime supervisor was started; and the hub saw only the wiki compile. Harness probes (`update`, `suggest`, `harness list`) run the installed harness CLIs to read their versions and login state, and those CLIs can write their own files: Codex creates `~/.codex/tmp/` whenever it runs.
|
|
125
|
+
|
|
126
|
+
### Exit codes
|
|
127
|
+
|
|
128
|
+
| Code | Meaning |
|
|
129
|
+
|---|---|
|
|
130
|
+
| 0 | Success, including `--help`, `--version`, and dry-run plans. |
|
|
131
|
+
| 1 | The command ran and failed or found a problem: an `ok: false` result, an unreachable hub for `hub view`, permission expansions for `trust check`, a stopped supervisor for `runtime status`, missing local state, or a planning-only `init`. |
|
|
132
|
+
| 2 | Usage error: unknown command or option, a missing argument or required option, a value KXM rejects before acting, `--workspace` where unsupported, conflicting flags, a group run without a subcommand, a removed command (`removed_command`), or `--dry-run` on a command that cannot plan (`dry_run_unsupported`). |
|
|
133
|
+
| 4 | `gate github watch` timed out and posted (or, under `--dry-run`, would have posted) a signed `failed` signal. |
|
|
134
|
+
| other | `hub start` and `agent worker` return the exit code of the foreground process; `ssh run` returns the remote command's exit code. |
|
|
135
|
+
|
|
136
|
+
## Where commands read and write
|
|
137
|
+
|
|
138
|
+
| Location | Contents | Used by |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| Project files under `<project>/.kxm/` (reviewed in Git) | `project.yaml`, `agents/`, `workflows/`, `gates.yaml`, `repo/`, `template-provenance.yaml`, `routes.yaml`, `models/inventory.yaml`, `roles/`, `role-hosts.yaml`, `modes.yaml`, `prices.yaml` | `init`, `trust`, `run`, `models`, `routes`, `role`, `workflow definitions\|add\|remove\|modify`, `explain`, `studio` |
|
|
141
|
+
| Local project records under `<project>/.kxm/` | `config.yaml` (project scope), `goals/`, `tasks/`, `memory/`, `skills/`, `candidates/`, `backups/`, `run/ssh-sockets/` | `config`, `goal`, `task`, `memory`, `skills`, `improve`, `backup`, `ssh` |
|
|
142
|
+
| Workspace directories (`.kxm/state`, `.kxm/logs`, `.kxm/assets`, `.kxm/config`; moved by `--workspace` or `KXM_*_DIR`) | hub SQLite store `state/kxm.db` (or `KXM_DATA_PATH`), `state/hub.pid`, `state/session-brief.json`, `logs/telemetry.jsonl`, `logs/kxm-hub.jsonl`, `assets/sessions/`, `assets/workflows/`, `assets/improvements/`, `assets/retrospectives/`, legacy `config/agents.json` and `config/gates.json` | `hub`, `session`, `dash`, `agent worker`, `workflow list\|get\|export`, `gate`, `improve`, `routing report` |
|
|
143
|
+
| User config directory (`KXM_USER_CONFIG_DIR`, default `~/.config/kxm`) | `config.yaml` (user scope), `session.token`, global `roles/` and `workflows/`, `role-hosts.yaml`, `completions/` | `config --scope user`, `auth token`, `session brief\|token`, `role`/`workflow` with `--scope global`, `studio serve`, `completion install` |
|
|
144
|
+
| User state root (`KXM_STATE_HOME`; macOS `~/Library/Application Support/KXM`; Linux `$XDG_STATE_HOME/kxm` or `~/.local/state/kxm`; Windows `%LOCALAPPDATA%\KXM`) | `hub-env.json` (persisted hub credentials), `hub-binding.json`, `runtime/` (Runtime supervisor registry and per-project run stores), `update.yaml`, repository bindings | `hub start\|bind\|unbind`, every hub client, `run`, `runs`, `runtime`, `tenant status`, `update`, `init --repository`, and (read-only, the project's run store) `improve` and `routing report` |
|
|
145
|
+
|
|
146
|
+
`init`, `trust`, `run`, `runs`, `runtime sync-retry`, `tenant status`, and `studio layout` find the project root by walking up from the current directory. `improve` and `routing report` use the current directory's Git root when it holds `.kxm/project.yaml`, to find the project's Runtime run store (and, for `improve`, its configuration and default candidate directory). `config`, `role`, `workflow definitions|add|remove|modify`, `goal`, `task`, `memory`, `skills`, `backup`, `restore`, `studio serve`, and `ssh` (socket directory) use `.kxm` in the current directory. Run those from the project root.
|
|
147
|
+
|
|
148
|
+
## Task to command
|
|
149
|
+
|
|
150
|
+
| Task | Commands |
|
|
151
|
+
|---|---|
|
|
152
|
+
| Set up a project | [`kxm init`](#kxm-init), [`kxm trust check`](#kxm-trust-check), [`kxm config set`](#kxm-config-set) |
|
|
153
|
+
| Start or bind a hub | [`kxm hub start`](#kxm-hub-start), [`kxm hub bind`](#kxm-hub-bind), [`kxm hub view`](#kxm-hub-view) |
|
|
154
|
+
| Check harness installs and authentication | [`kxm harness list`](#kxm-harness-list), [`kxm update --dry-run`](#kxm-update) |
|
|
155
|
+
| Create and drive a run | [`kxm run`](#kxm-run), [`kxm runs drive`](#kxm-runs-drive), [`kxm runtime status`](#kxm-runtime-status) |
|
|
156
|
+
| Inspect runs | [`kxm runs list`](#kxm-runs-list), [`kxm runs status`](#kxm-runs-status), [`kxm runs receipt`](#kxm-runs-receipt), [`kxm tenant status`](#kxm-tenant-status), [`kxm workflow list`](#kxm-workflow-list) |
|
|
157
|
+
| Message peers | [`kxm peer list`](#kxm-peer-list), [`kxm peer send`](#kxm-peer-send), [`kxm peer await`](#kxm-peer-await), [`kxm peer fanout`](#kxm-peer-fanout) |
|
|
158
|
+
| Operate gates and evidence | [`kxm gate validate`](#kxm-gate-validate), [`kxm gate artifacts-exist`](#kxm-gate-artifacts-exist), [`kxm gate signal`](#kxm-gate-signal), [`kxm workflow checkpoint`](#kxm-workflow-checkpoint) |
|
|
159
|
+
| Query context and memory | [`kxm context get`](#kxm-context-get), [`kxm context recall`](#kxm-context-recall), [`kxm memory brief`](#kxm-memory-brief), [`kxm memory note`](#kxm-memory-note) |
|
|
160
|
+
| Read improvement and routing reports | [`kxm improve report`](#kxm-improve-report), [`kxm routing report`](#kxm-routing-report) |
|
|
161
|
+
| Back up and restore | [`kxm backup`](#kxm-backup), [`kxm restore`](#kxm-restore) |
|
|
162
|
+
| Update KXM and harnesses | [`kxm update --check`](#kxm-update), [`kxm update --kxm`](#kxm-update) |
|
|
163
|
+
|
|
164
|
+
## `kxm init`
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
kxm init [--name <name>] [--project-id <id>] [--repository <id=absolute-path>]...
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Creates, validates, repairs, resumes, or joins a KXM project at the Git root that contains the current directory. A new project gets a minimal configuration: one coordinator agent, one implementer agent, a `test` command gate, and a `default` plan-implement-verify workflow. An existing project is validated without rewriting. Conflict-free template updates to non-authority fields are applied; authority changes, overlapping edits, and provenance-free or legacy state stay planning-only. `init` does not start a hub or the Runtime.
|
|
171
|
+
|
|
172
|
+
| Option | Argument | Default | Description |
|
|
173
|
+
|---|---|---|---|
|
|
174
|
+
| `--name` | `<name>` | Git root directory name | Project display name for a new project |
|
|
175
|
+
| `--project-id` | `<id>` | generated | Stable project ID for controlled provisioning |
|
|
176
|
+
| `--repository` | `<id=absolute-path>` | `[]` | Bind a member repository outside Git configuration |
|
|
177
|
+
|
|
178
|
+
- Global options: `--json` and `--dry-run` only; `--workspace` exits 2 with `workspace_option_unsupported`.
|
|
179
|
+
- `--project-id` must match `prj_` followed by 6 to 128 letters, digits, `_`, or `-`. `--repository` is repeatable; each value must be `<id>=<absolute path>`, and a repeated ID fails with `repository_binding_argument_duplicate`.
|
|
180
|
+
- Needs a Git repository. Does not need a hub or the Runtime.
|
|
181
|
+
- Writes `.kxm/project.yaml`, `.kxm/agents/coordinator.yaml`, `.kxm/agents/implementer.yaml`, `.kxm/gates.yaml`, `.kxm/repo/repo.yaml`, `.kxm/workflows/default.yaml`, and `.kxm/template-provenance.yaml`, using a `.kxm-init-transaction` directory at the Git root while a create or repair is in flight. Repository bindings are written under the user state root, never into Git. `--dry-run` writes nothing.
|
|
182
|
+
- On an interactive terminal without `--json` or `--dry-run`, a successful create or join offers to install shell completion (suppress with `KXM_SKIP_COMPLETION_PROMPT=1`) and to write workflow-guide agents for authenticated harnesses (suppress with `KXM_SKIP_GUIDE_SETUP_PROMPT=1`).
|
|
183
|
+
- JSON keys: `action` (`planned`, `created`, `joined`, `repaired`, `resumed`, or `validated`), `mode`, `inspectedFrom`, `projectRoot`, `changesRequired`, `legacyInputs`, `issues`, `configRevision`, `files`, `plannedOnly`, and, when relevant, `localBindingFile`, `bindingsChanged`, `repairPlan`, `resumePending`, `transactionKind`.
|
|
184
|
+
- Exit 0 for every completed action and every dry-run plan. Exit 1 when the result is planning-only (legacy state, blocked repair, partial state without provenance) or for `initialization_failed` (with `issues`) and `initialization_io_failed`. A planning-only text result prints the reason and then one `<file>: <code>: <message>` line per validation issue, for example `.kxm/workflows/first.yaml: gate_outcome_impossible: ...`.
|
|
185
|
+
|
|
186
|
+
Preview what a new project would contain:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
kxm init --dry-run --json
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"init","action":"planned","mode":"create","inspectedFrom":"/work/proj","projectRoot":"/work/proj","changesRequired":true,"legacyInputs":[],"issues":[],"files":[".kxm/agents/coordinator.yaml",".kxm/agents/implementer.yaml",".kxm/gates.yaml",".kxm/project.yaml",".kxm/repo/repo.yaml",".kxm/template-provenance.yaml",".kxm/workflows/default.yaml"],"plannedOnly":true}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Create the project:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
kxm init --name "Demo"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
```text
|
|
203
|
+
initialized KXM project at /work/proj
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Validate it again later:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
kxm init --json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"init","action":"validated","mode":"ready",...,"configRevision":"sha256:80457232cbfc...","files":[],"plannedOnly":false}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Join a cloned multi-repository project (Not run):
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
kxm init --repository api=/absolute/path/to/api
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## `kxm config`
|
|
223
|
+
|
|
224
|
+
Reads and writes personalization settings (`kxm.config.v1`). The merged view layers built-in defaults, the user file `<KXM_USER_CONFIG_DIR>/config.yaml`, and the project file `.kxm/config.yaml` in the current directory. `kxm config` with no subcommand runs `config list`. None of the subcommands needs a hub.
|
|
225
|
+
|
|
226
|
+
### `kxm config list`
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
kxm config list
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Prints the resolved configuration. Text output shows `schema`, `user`, `defaults`, `dash`, `sync`, and `loadedFrom`; the JSON `config` object also contains `hub`, `improvement`, `routing`, and `telemetry`. An empty `loadedFrom` means no file supplies values yet.
|
|
233
|
+
|
|
234
|
+
No command-specific options.
|
|
235
|
+
|
|
236
|
+
- Reads only. JSON keys: `config`.
|
|
237
|
+
- Exit 0; exit 1 with a plain `config list failed:` line when a file cannot be parsed.
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
kxm config list
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
```text
|
|
244
|
+
schema: kxm.config.v1
|
|
245
|
+
user:
|
|
246
|
+
theme: dark
|
|
247
|
+
preferredCritics:
|
|
248
|
+
- reviewer-arch
|
|
249
|
+
- reviewer-cli
|
|
250
|
+
tokenBudget: 16000
|
|
251
|
+
defaults:
|
|
252
|
+
workflow: software-engineering/feature-implementation
|
|
253
|
+
harness: pi
|
|
254
|
+
dash:
|
|
255
|
+
defaultScreen: agents
|
|
256
|
+
refreshIntervalMs: 1000
|
|
257
|
+
autoOpen: false
|
|
258
|
+
sync:
|
|
259
|
+
defaultTracker: none
|
|
260
|
+
loadedFrom: {}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
kxm config list --json
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
```text
|
|
268
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"config list","config":{"schema":"kxm.config.v1",...,"hub":{"autoStart":"background"},...,"loadedFrom":{}}}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### `kxm config get`
|
|
272
|
+
|
|
273
|
+
```text
|
|
274
|
+
kxm config get <key>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Prints one value by dotted key from the merged view.
|
|
278
|
+
|
|
279
|
+
- Arguments: `<key>`, a dotted path such as `hub.autoStart`.
|
|
280
|
+
- No command-specific options. Reads only.
|
|
281
|
+
- An unknown key prints `(undefined)` (JSON: no `value` key) and exits 0.
|
|
282
|
+
- JSON keys: `key`, `value`.
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
kxm config get hub.autoStart
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
```text
|
|
289
|
+
background
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
kxm config get defaults.harness --json
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
```text
|
|
297
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"config get","key":"defaults.harness","value":"pi"}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### `kxm config set`
|
|
301
|
+
|
|
302
|
+
```text
|
|
303
|
+
kxm config set <key> <value> [--scope user|project]
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Writes one value into exactly one scope file.
|
|
307
|
+
|
|
308
|
+
| Option | Argument | Default | Description |
|
|
309
|
+
|---|---|---|---|
|
|
310
|
+
| `--scope` | `<scope>` | `project` | Configuration scope: user or project (default: project) |
|
|
311
|
+
|
|
312
|
+
- Arguments: `<key>` (dotted path) and `<value>`. The value is parsed as JSON when it parses (`true`, `5`, `"text"`, `{"a":1}`); otherwise it is stored as a string. Keys are not validated.
|
|
313
|
+
- `--scope user` writes `<KXM_USER_CONFIG_DIR>/config.yaml`; any other value writes `.kxm/config.yaml` in the current directory.
|
|
314
|
+
- Mutates. `--dry-run` names the file it would write and writes nothing.
|
|
315
|
+
- JSON keys: `key`, `value`, `scope` (plus `dryRun` and `planned` under `--dry-run`). Exit 1 with a plain `config set failed:` line on error.
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
kxm config set user.theme light --dry-run --json
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
```text
|
|
322
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"config set","key":"user.theme","value":"light","scope":"project","dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/config.yaml"}]}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Stop harness extensions from starting a hub (Not run):
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
kxm config set hub.autoStart off --scope user
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## `kxm completion`
|
|
332
|
+
|
|
333
|
+
```text
|
|
334
|
+
kxm completion <bash|zsh|fish>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Prints a shell completion script to stdout. With no shell, prints `usage: kxm completion <bash|zsh|fish> | kxm completion install [--shell <shell>] [--no-path]` on stderr and exits 2; an unsupported shell exits 1. The script is printed as text even with `--json`. The generated command list lags the CLI in 0.7.1 (see [Known behavior gaps](#known-behavior-gaps-in-071)).
|
|
338
|
+
|
|
339
|
+
- Arguments: `[shell]`, one of `bash`, `zsh`, `fish` (or the `install` subcommand).
|
|
340
|
+
- Reads only.
|
|
341
|
+
|
|
342
|
+
Print the bash script:
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
kxm completion bash
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
```text
|
|
349
|
+
#!/usr/bin/env bash
|
|
350
|
+
# Bash completion for kxm
|
|
351
|
+
...
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Save the zsh script into a directory on your `fpath` (Not run):
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
kxm completion zsh > ~/.zfunc/_kxm
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### `kxm completion install`
|
|
361
|
+
|
|
362
|
+
```text
|
|
363
|
+
kxm completion install [--shell <shell>] [--no-path]
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Installs tab completion for the detected or given shell and, unless `--no-path` is set, adds the directory containing `kxm` to `PATH` in the shell's rc file.
|
|
367
|
+
|
|
368
|
+
| Option | Argument | Default | Description |
|
|
369
|
+
|---|---|---|---|
|
|
370
|
+
| `--shell` | `<shell>` | detected from `$SHELL` | Shell to install for (bash, zsh, fish; default: detect from $SHELL) |
|
|
371
|
+
| `--no-path` | none | off | Only install completion; do not add a PATH entry |
|
|
372
|
+
|
|
373
|
+
- Writes `<KXM_USER_CONFIG_DIR>/completions/kxm.<shell>` and a source stanza in `~/.bashrc` (or `~/.bash_profile`) or `$ZDOTDIR/.zshrc` (or `~/.zshrc`); fish writes `~/.config/fish/completions/kxm.fish` (or under `XDG_CONFIG_HOME`) and needs no rc edit. Idempotent. Honors `--dry-run`.
|
|
374
|
+
- JSON keys: `shell`, `scriptPath`, `rcFile`, `rcModified`, `alreadyInstalled`, `path`, `dryRun`. Exit 1 with `shell_not_detected` when the shell cannot be determined.
|
|
375
|
+
|
|
376
|
+
Preview the change (Not run):
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
kxm completion install --shell zsh --dry-run
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## `kxm trust`
|
|
383
|
+
|
|
384
|
+
Compares the authority-bearing fields of the project configuration against a base Git revision. The base is materialized into a temporary shadow with a sanitized environment; nothing in the project is written. Both subcommands refuse `--workspace` (exit 2) and need no hub.
|
|
385
|
+
|
|
386
|
+
### `kxm trust diff`
|
|
387
|
+
|
|
388
|
+
```text
|
|
389
|
+
kxm trust diff [--base <revision>]
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Prints the structured `kxm.permission-diff.v1` report: every authority-bearing change classified as an expansion, narrowing, or neutral change, with per-field value hashes.
|
|
393
|
+
|
|
394
|
+
| Option | Argument | Default | Description |
|
|
395
|
+
|---|---|---|---|
|
|
396
|
+
| `--base` | `<revision>` | `HEAD` | Base Git revision (default: HEAD) |
|
|
397
|
+
|
|
398
|
+
- Reads only. Exit 0 even when expansions exist.
|
|
399
|
+
- JSON keys: `baseRevision`, `candidateRevision`, `requiresReview`, `expansions`, `narrowings`, `neutralChanges` (counts), `changes` (each with `resource`, `path`, `field`, `direction`, `summary`, `baseValueSha256`, `candidateValueSha256`).
|
|
400
|
+
- Errors: `trust_diff_failed` with `issues` (for example `resource_missing` when the base revision has no `.kxm/project.yaml`), `trust_diff_io_failed`. Both exit 1.
|
|
401
|
+
|
|
402
|
+
After widening the coordinator's repository access from `read` to `write`:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
kxm trust diff
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
```text
|
|
409
|
+
permission diff: sha256:80457232cbfc… -> sha256:7428fde55ca4…
|
|
410
|
+
EXPANSION .kxm/agents/coordinator.yaml /repositories/control repository-access changed (expansion)
|
|
411
|
+
1 expansion(s) require explicit reviewed trust action
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Compare against an older commit:
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
kxm trust diff --base main --json
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Not run against `main`; a base without `.kxm/project.yaml` fails with `resource_missing`.
|
|
421
|
+
|
|
422
|
+
### `kxm trust check`
|
|
423
|
+
|
|
424
|
+
```text
|
|
425
|
+
kxm trust check [--base <revision>]
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Same comparison as `trust diff`, but exits 1 when any expansion exists so an authority-widening change cannot merge without review. Formatting and description-only changes never fail the check.
|
|
429
|
+
|
|
430
|
+
| Option | Argument | Default | Description |
|
|
431
|
+
|---|---|---|---|
|
|
432
|
+
| `--base` | `<revision>` | `HEAD` | Base Git revision (default: HEAD) |
|
|
433
|
+
|
|
434
|
+
- Reads only. JSON keys are the same as `trust diff`; `ok` is `false` when review is required.
|
|
435
|
+
- Exit 0 with no expansions, 1 with expansions or on failure.
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
kxm trust check
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
```text
|
|
442
|
+
permission diff: sha256:80457232cbfc… -> sha256:7428fde55ca4…
|
|
443
|
+
EXPANSION .kxm/agents/coordinator.yaml /repositories/control repository-access changed (expansion)
|
|
444
|
+
1 expansion(s) require explicit reviewed trust action
|
|
445
|
+
trust check failed: review every expansion above before merging
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
kxm trust check --json
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
```text
|
|
453
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"trust check",...,"requiresReview":true,"expansions":1,"narrowings":0,"neutralChanges":0,"changes":[{"resource":".kxm/agents/coordinator.yaml","path":"/repositories/control","field":"repository-access","direction":"expansion",...}]}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
<a id="hub-commands"></a>
|
|
457
|
+
|
|
458
|
+
## `kxm hub`
|
|
459
|
+
|
|
460
|
+
Starts, inspects, and stops the local KXM hub, and binds this machine to a hub. Hub clients pick their target in this order: `KXM_SERVER_URL`, the binding written by `kxm hub bind`, then `http://127.0.0.1:7331`.
|
|
461
|
+
|
|
462
|
+
### `kxm hub view`
|
|
463
|
+
|
|
464
|
+
```text
|
|
465
|
+
kxm hub view
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Calls `GET /health` and `GET /ready` on the target hub and reports whether the URL is loopback or remote.
|
|
469
|
+
|
|
470
|
+
No command-specific options.
|
|
471
|
+
|
|
472
|
+
- Needs a hub to succeed. Reads only.
|
|
473
|
+
- JSON keys: `target` (`url`, `scope`, and `source: "env"` when `KXM_SERVER_URL` overrides a binding), `health`, `ready`. An unreachable hub reports `{"error":"hub_unreachable"}` for both probes.
|
|
474
|
+
- Exit 0 when both probes succeed, 1 otherwise.
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
kxm hub view
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
```text
|
|
481
|
+
hub health=true ready=true · loopback hub
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
kxm hub view --json
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
```text
|
|
489
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"hub view","target":{"url":"http://127.0.0.1:46315","scope":"loopback"},"health":{"ok":true,"agents":0},"ready":{"ok":true,"storage":"sqlite"}}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### `kxm hub start`
|
|
493
|
+
|
|
494
|
+
```text
|
|
495
|
+
kxm hub start
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
Runs the hub in the foreground through `scripts/kxm-hub.mjs`, passing the workspace directories and `KXM_SERVER_URL` to it. The hub listens on `KXM_HOST` (default `127.0.0.1`) and `KXM_PORT` (default `7331`) and refuses a non-loopback bind without `KXM_AUTH_TOKEN`. When `KXM_AUTH_TOKEN` is unset, the admin token is read from, or generated once into, `hub-env.json` under the user state root.
|
|
499
|
+
|
|
500
|
+
No command-specific options.
|
|
501
|
+
|
|
502
|
+
- Writes `.kxm/state/hub.pid`, the SQLite store `.kxm/state/kxm.db` (or `KXM_DATA_PATH`), and `.kxm/logs/kxm-hub.jsonl`.
|
|
503
|
+
- On installs other than a source checkout, prints a cached update notice and refreshes it from the release source.
|
|
504
|
+
- `--dry-run` prints the plan (JSON key `workspace`) and starts nothing. Otherwise there is no JSON result; the exit code is the hub process's exit code.
|
|
505
|
+
|
|
506
|
+
Start a hub on a chosen port:
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
KXM_PORT=46315 KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm hub start
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
```text
|
|
513
|
+
kxm hub listening at http://127.0.0.1:46315; storage=/work/proj/.kxm/state/kxm.db; auth=token
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
```bash
|
|
517
|
+
kxm hub start --dry-run --json
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
```text
|
|
521
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"hub start","dryRun":true,"workspace":"/work/proj/.kxm"}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### `kxm hub stop`
|
|
525
|
+
|
|
526
|
+
```text
|
|
527
|
+
kxm hub stop [--wait-ms <ms>]
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Requests a generation-matched shutdown of every managed hub and worker in the workspace by writing `hub.stop` and `worker-*.stop` control files next to the live `*.pid` claims, then waits for the claims to clear. An orphaned hub server whose wrapper died is sent `SIGTERM`, then `SIGKILL` if it lingers.
|
|
531
|
+
|
|
532
|
+
| Option | Argument | Default | Description |
|
|
533
|
+
|---|---|---|---|
|
|
534
|
+
| `--wait-ms` | `<ms>` | `5000` | How long to wait for PID files to clear |
|
|
535
|
+
|
|
536
|
+
- `--wait-ms` is clamped to 100 through 30000.
|
|
537
|
+
- Mutates process state. `--dry-run` lists the PID files (JSON key `pidFiles`) and signals nothing.
|
|
538
|
+
- JSON keys: `requested`, `stopped`, `timedOut`, `orphans` (when any), `ignored`.
|
|
539
|
+
- Exit 1 when the state directory has no claims (`no_pid_files`), when no claim belongs to a live process, or when the wait times out.
|
|
540
|
+
|
|
541
|
+
```bash
|
|
542
|
+
kxm hub stop --dry-run --json
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
```text
|
|
546
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"stop","dryRun":true,"pidFiles":["hub.pid"]}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
```bash
|
|
550
|
+
kxm hub stop --wait-ms 8000 --json
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
```text
|
|
554
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"stop","requested":["hub.pid"],"stopped":["hub.pid"],"timedOut":[],"ignored":[]}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### `kxm hub bind`
|
|
558
|
+
|
|
559
|
+
```text
|
|
560
|
+
kxm hub bind <url>
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
Binds this machine to a running hub by writing `hub-binding.json` under the user state root, then probes the hub's health for up to 300 ms. Every hub client uses the binding when `KXM_SERVER_URL` is unset.
|
|
564
|
+
|
|
565
|
+
- Arguments: `<url>`, Hub base URL (http or https).
|
|
566
|
+
- A URL with credentials, a query, a fragment, or a scheme other than http or https fails with `hub_url_invalid` (exit 2).
|
|
567
|
+
- A remote (non-loopback) URL is refused with `hub_bind_unauthenticated` (exit 2, `nextAction: "export_kxm_auth_token"`) unless a credential for the current project resolves from `KXM_AUTH_TOKEN` or the persisted `hub-env.json`. A malformed record fails with `hub_credential_unreadable` (exit 2).
|
|
568
|
+
- Mutates the binding file. `--dry-run` validates and prints the plan without writing.
|
|
569
|
+
- JSON keys: `url`, `scope`, `file`, `health` (`on`, `off`, or `unknown`), `probeMs`.
|
|
570
|
+
|
|
571
|
+
```bash
|
|
572
|
+
kxm hub bind http://127.0.0.1:7331 --dry-run
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
```text
|
|
576
|
+
would bind hub http://127.0.0.1:7331 (loopback)
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
kxm hub bind https://hub.example.com --dry-run --json
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
```text
|
|
584
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"hub bind","error":"hub_bind_unauthenticated","url":"https://hub.example.com","scope":"remote","project":"proj","nextAction":"export_kxm_auth_token","hint":"export KXM_AUTH_TOKEN (or point KXM_STATE_HOME at the hub-env record that already holds one), then re-run; the hub itself requires a token beyond loopback (needs a token for project proj)"}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### `kxm hub unbind`
|
|
588
|
+
|
|
589
|
+
```text
|
|
590
|
+
kxm hub unbind
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
Removes this machine's hub binding, including a malformed binding record.
|
|
594
|
+
|
|
595
|
+
No command-specific options.
|
|
596
|
+
|
|
597
|
+
- Mutates the binding file. `--dry-run` prints the file it would remove.
|
|
598
|
+
- JSON keys: `url`, `file`. Exit 1 with `hub_not_bound` when there is no binding.
|
|
599
|
+
|
|
600
|
+
```bash
|
|
601
|
+
kxm hub unbind --dry-run --json
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
```text
|
|
605
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"hub unbind","dryRun":true,"file":"/state/hub-binding.json"}
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
## `kxm session`
|
|
609
|
+
|
|
610
|
+
Session manifests, process claims, the session-start briefing, and local session tokens. None of these commands launches an agent.
|
|
611
|
+
|
|
612
|
+
### `kxm session status`
|
|
613
|
+
|
|
614
|
+
```text
|
|
615
|
+
kxm session status
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
Lists the `*.pid` claim files and `worker-recovery-*.json` envelopes in the workspace state directory and whether each claimed process is alive. It does not read session manifests.
|
|
619
|
+
|
|
620
|
+
No command-specific options.
|
|
621
|
+
|
|
622
|
+
- Reads only. No hub needed.
|
|
623
|
+
- JSON keys: `claims` (`file`, `role`, `pid`, `startedAt`, `live`), `recoveries` (`file`, `reason`, `agentName`, `project`, `createdAt`, `runId`, `stageId`, `freshSession`).
|
|
624
|
+
|
|
625
|
+
```bash
|
|
626
|
+
kxm session status
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
```text
|
|
630
|
+
0 session claim(s), 0 recovery envelope(s)
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
With a hub running:
|
|
634
|
+
|
|
635
|
+
```bash
|
|
636
|
+
kxm session status --json
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
```text
|
|
640
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"session status","claims":[{"file":"hub.pid","role":"hub","pid":81619,"startedAt":"2026-09-23T13:53:08.896Z","live":true}],"recoveries":[]}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### `kxm session brief`
|
|
644
|
+
|
|
645
|
+
```text
|
|
646
|
+
kxm session brief [--status] [--token]
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
Prints recent tasks (workflow runs) and plans (journal entries) from the local hub store, with a status line for harness chrome. It probes the hub at `KXM_SERVER_URL` or the bound URL for up to 300 ms; with neither set it reports the hub as off (`evidence: "unconfigured"`). It never starts a hub and never prints message bodies.
|
|
650
|
+
|
|
651
|
+
| Option | Argument | Default | Description |
|
|
652
|
+
|---|---|---|---|
|
|
653
|
+
| `--status` | none | off | Print only the status line |
|
|
654
|
+
| `--token` | none | off | Issue interactive session token with operator policy |
|
|
655
|
+
|
|
656
|
+
- Side effects: on first use it mints a 24-hour operator session token and writes it to `<KXM_USER_CONFIG_DIR>/session.token` (mode 0600), and it caches the brief in `.kxm/state/session-brief.json`. Under `--dry-run` it still probes the hub and prints the brief, but it mints no token, writes neither file, and appends a `dry run: would write <file>` line for each (JSON: `dryRun` and `planned`); with no saved token the output carries no token. `--token --dry-run` plans only the token file.
|
|
657
|
+
- The default text output ends with the session token, and `--token` prints only the token. Treat the output as a credential.
|
|
658
|
+
- JSON (`kxm.session-brief.v1`) keys: `generatedAt`, `staleSeconds`, `source`, `hub` (`state`, `evidence`, `online`, `url`, `scope`), `stats`, `tasks`, `plans`, `statusLine`, `widgetLines`, `sessionToken`.
|
|
659
|
+
|
|
660
|
+
```bash
|
|
661
|
+
kxm session brief
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
```text
|
|
665
|
+
kxm hub:on · idle · dirty
|
|
666
|
+
|
|
667
|
+
No recent tasks or plans.
|
|
668
|
+
|
|
669
|
+
Session token: <token>
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
```bash
|
|
673
|
+
kxm session brief --status
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
```text
|
|
677
|
+
kxm hub:on · idle
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
```bash
|
|
681
|
+
kxm session brief --json
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
```text
|
|
685
|
+
{"schema":"kxm.session-brief.v1","generatedAt":"2026-09-23T13:49:55.253Z","staleSeconds":5,"source":"legacy","hub":{"state":"off","evidence":"probed","online":false,"url":"http://127.0.0.1:59998","scope":"loopback"},"stats":{"activeTasks":0,"waitingTasks":0,"planCount":0,"inbox":0,"runTotal":0},"tasks":[],"plans":[],"statusLine":"kxm hub:off · idle",...,"sessionToken":"<token>"}
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
Before the first token exists:
|
|
689
|
+
|
|
690
|
+
```bash
|
|
691
|
+
kxm session brief --status --dry-run
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
```text
|
|
695
|
+
kxm hub:on · idle · dirty
|
|
696
|
+
dry run: would write ~/.config/kxm/session.token
|
|
697
|
+
dry run: would write /work/proj/.kxm/state/session-brief.json
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
### `kxm session token`
|
|
701
|
+
|
|
702
|
+
```text
|
|
703
|
+
kxm session token [--status] [--clear] [--issue]
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
Identical to [`kxm auth token`](#kxm-auth-token), including its JSON (`command` is `auth token`).
|
|
707
|
+
|
|
708
|
+
| Option | Argument | Default | Description |
|
|
709
|
+
|---|---|---|---|
|
|
710
|
+
| `--status` | none | off | Check status of the active session token |
|
|
711
|
+
| `--clear` | none | off | Clear persisted disk session token |
|
|
712
|
+
| `--issue` | none | off | Force issuing a fresh session token |
|
|
713
|
+
|
|
714
|
+
```bash
|
|
715
|
+
kxm session token --status --json
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
```text
|
|
719
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"auth token","source":"disk","valid":true,"sessionId":"session-280238cf-867f-4852-a09a-0ae88fe5d01c","issuedAt":"2026-09-23T13:49:55.195Z","expiresAt":"2026-09-24T13:49:55.195Z","path":"~/.config/kxm/session.token"}
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
### `kxm session start`
|
|
723
|
+
|
|
724
|
+
```text
|
|
725
|
+
kxm session start (--workflow <id> | --mix <names>) [--id <id>]
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
Writes a `kxm.session.v1` manifest and creates asset directories. It does not start any process or dispatch a workflow.
|
|
729
|
+
|
|
730
|
+
| Option | Argument | Default | Description |
|
|
731
|
+
|---|---|---|---|
|
|
732
|
+
| `--id` | `<id>` | `session_<12 hex>` | Session id |
|
|
733
|
+
| `--workflow` | `<id>` | none | Workflow definition id |
|
|
734
|
+
| `--mix` | `<names>` | none | Comma-separated agent and gate names |
|
|
735
|
+
|
|
736
|
+
- Exactly one of `--workflow` or `--mix` is required (exit 2 otherwise).
|
|
737
|
+
- Names are resolved against the legacy workspace files `.kxm/config/agents.json` and `.kxm/config/gates.json`. A project created by `kxm init` has neither, so `--mix` fails there with `unknown worker name in session roster` (exit 2) and `--workflow` records an empty roster.
|
|
738
|
+
- Writes `.kxm/assets/sessions/<id>/session.json` with `inputs/` and `outputs/`; `--workflow` also creates `.kxm/assets/workflows/<id>/{inputs,outputs,generated}`. `--dry-run` writes nothing.
|
|
739
|
+
- JSON keys: `session` (`schema`, `id`, `host`, `mode`, `workers`, `createdAt`, `assetDir`, `workflowId`), `created`, `dryRun`.
|
|
740
|
+
|
|
741
|
+
```bash
|
|
742
|
+
kxm session start --id demo --workflow default --dry-run
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
```text
|
|
746
|
+
session demo (workflow)
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
```bash
|
|
750
|
+
kxm session start --id review-pass --mix reviewer,test-gate
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
Not run: needs `.kxm/config/agents.json` and `gates.json` entries with those names.
|
|
754
|
+
|
|
755
|
+
### `kxm session stop`
|
|
756
|
+
|
|
757
|
+
```text
|
|
758
|
+
kxm session stop [--wait-ms <ms>]
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
The same operation as [`kxm hub stop`](#kxm-hub-stop): it stops every managed hub and worker in the workspace and is not scoped to one session.
|
|
762
|
+
|
|
763
|
+
| Option | Argument | Default | Description |
|
|
764
|
+
|---|---|---|---|
|
|
765
|
+
| `--wait-ms` | `<ms>` | `5000` | How long to wait for PID files to clear |
|
|
766
|
+
|
|
767
|
+
```bash
|
|
768
|
+
kxm session stop --dry-run
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
```text
|
|
772
|
+
would signal pid files
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
## `kxm dash`
|
|
776
|
+
|
|
777
|
+
```text
|
|
778
|
+
kxm dash [--screen <name>]
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
Opens the live, read-only dashboard over the hub's server-sent events and the local hub store. On a terminal it is interactive (`1`–`7` switch tabs, `h` help, `q` quit). Without a terminal it prints one plain snapshot and exits.
|
|
782
|
+
|
|
783
|
+
| Option | Argument | Default | Description |
|
|
784
|
+
|---|---|---|---|
|
|
785
|
+
| `--screen` | `<name>` | `agents` | agents, tasks, workflows, plans, inbox, procs, or spend |
|
|
786
|
+
|
|
787
|
+
- Needs a hub for live data. Reads only.
|
|
788
|
+
- `--json` is refused (exit 2); use `kxm hub view`. An unknown screen exits 2 with `unknown_screen`. `--dry-run` prints `serverUrl`, `transport`, and `screen`.
|
|
789
|
+
|
|
790
|
+
```bash
|
|
791
|
+
kxm dash --screen workflows
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
```text
|
|
795
|
+
kxm dash ● hub ok ● ready live ops 0/5 online updated 13:53:46 UTC · http://127.0.0.1:46315
|
|
796
|
+
1 Agents 0/5 2 Tasks 0 [3 Workflows 0] 4 Plans 0 5 Inbox 0 6 Procs 1/1 7 Spend 0
|
|
797
|
+
list detail
|
|
798
|
+
Nothing here yet No run selected
|
|
799
|
+
tab Workflows · list · 1–7 tabs · h help · a/r/d/s/c · q quit · live
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
```bash
|
|
803
|
+
kxm dash --dry-run --json
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
```text
|
|
807
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"dash","dryRun":true,"serverUrl":"http://127.0.0.1:59998","transport":"sse"}
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
## `kxm studio`
|
|
811
|
+
|
|
812
|
+
Web Studio layout utilities. Neither subcommand needs a hub.
|
|
813
|
+
|
|
814
|
+
### `kxm studio layout`
|
|
815
|
+
|
|
816
|
+
```text
|
|
817
|
+
kxm studio layout [workflowPath]
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
Compiles a workflow definition and prints the Studio layout JSON (`kxm.studio-layout.v1`): a stepper, a DAG of nodes and edges, and role swimlanes. Without a path it reads `.kxm/workflows/default.yaml` under the discovered project root, or a built-in sample workflow when that file does not exist. Swimlane timings are placeholders, and `workflowId` is always reported as `default`.
|
|
821
|
+
|
|
822
|
+
- Arguments: `[workflowPath]`, a workflow YAML file.
|
|
823
|
+
- No command-specific options. Reads only. Text mode prints the same layout as indented JSON.
|
|
824
|
+
- JSON keys: `layout` (`schema`, `workflowId`, `generatedAt`, `stepper`, `dag`, `temporalSwimlanes`).
|
|
825
|
+
|
|
826
|
+
```bash
|
|
827
|
+
kxm studio layout --json
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
```text
|
|
831
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"studio layout","layout":{"schema":"kxm.studio-layout.v1","workflowId":"default",...,"stepper":[{"id":"plan","label":"plan","kind":"agent","status":"pending"},{"id":"implement",...},{"id":"verify","label":"verify","kind":"gate","status":"pending"}],...}}
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
### `kxm studio serve`
|
|
835
|
+
|
|
836
|
+
```text
|
|
837
|
+
kxm studio serve [-p <port>] [--host <host>] [--token <token>]
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
Serves the Web Studio on `http://127.0.0.1:4242` until interrupted. It serves `/`, `/health`, `GET /api/layout`, and `POST /api/mutate`; mutations require the session token. The plan comes from `.kxm/workflows/default.yaml` in the current directory, or the first YAML file in `.kxm/workflows/`.
|
|
841
|
+
|
|
842
|
+
| Option | Argument | Default | Description |
|
|
843
|
+
|---|---|---|---|
|
|
844
|
+
| `-p`, `--port` | `<port>` | `4242` | Port to bind (default: 4242) |
|
|
845
|
+
| `--host` | `<host>` | `127.0.0.1` | Host address to bind |
|
|
846
|
+
| `--token` | `<token>` | `KXM_SESSION_TOKEN`, then the on-disk session token | Session token for mutation authentication |
|
|
847
|
+
|
|
848
|
+
- Honors `--dry-run` (JSON keys `port`, `host`). A live server prints `port`, `host`, `url` and runs until `SIGINT` or `SIGTERM`.
|
|
849
|
+
|
|
850
|
+
```bash
|
|
851
|
+
kxm studio serve --dry-run
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
```text
|
|
855
|
+
would start studio server on http://127.0.0.1:4242
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
```bash
|
|
859
|
+
kxm studio serve --port 5000
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
Not run: starts a long-lived server.
|
|
863
|
+
|
|
864
|
+
## `kxm harness`
|
|
865
|
+
|
|
866
|
+
### `kxm harness list`
|
|
867
|
+
|
|
868
|
+
```text
|
|
869
|
+
kxm harness list
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
Probes the built-in harness catalog (`pi`, `claude`, `kimi`, `codex`, `deepseek`, `grok`, `agy`) and reports which are installed, which are authenticated, whether KXM can dispatch to them, and which native updaters exist. Detection runs `<harness> --version`; authentication runs the harness's own status command (`claude auth status`, `kimi provider list`, `codex login status`, `grok models`, `agy models`), which may contact that harness's service.
|
|
873
|
+
|
|
874
|
+
No command-specific options.
|
|
875
|
+
|
|
876
|
+
- Reads only. No hub needed. Always exits 0.
|
|
877
|
+
- JSON keys: `defaultHarness`, `harnesses` (each with `id`, `label`, `default`, `mode`, `detected`, `authenticated`, `dispatch` (`status`, `supported`, `reason`), `canUpdate` (`self`, `extensions`, `models`), `issues`).
|
|
878
|
+
|
|
879
|
+
Captured with no harness CLIs on `PATH`:
|
|
880
|
+
|
|
881
|
+
```bash
|
|
882
|
+
kxm harness list
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
```text
|
|
886
|
+
default harness: pi (omit agent harness: to use headless Pi)
|
|
887
|
+
enable/disable = Git YAML (.kxm/agents, .kxm/models) or the harness's own plugin CLI
|
|
888
|
+
governed kxm skills are not auto-updated
|
|
889
|
+
id default detected auth dispatch updates
|
|
890
|
+
pi yes no no no (not_detected) self,extensions,models
|
|
891
|
+
claude no no no no (not_detected) self,extensions
|
|
892
|
+
kimi no no no no (not_detected) self
|
|
893
|
+
codex no no no no (not_detected) self
|
|
894
|
+
deepseek no no no no (not_detected) self
|
|
895
|
+
grok no no no no (not_detected) self
|
|
896
|
+
agy no no no no (not_detected) self
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
```bash
|
|
900
|
+
kxm harness list --json
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
```text
|
|
904
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"harness list","defaultHarness":"pi","harnesses":[{"id":"pi","label":"Pi","default":true,"mode":"headless","detected":false,"authenticated":false,"dispatch":{"status":"no","supported":false,"reason":"not_detected"},"canUpdate":{"self":true,"extensions":true,"models":true},"issues":[]},...]}
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
## `kxm auth`
|
|
908
|
+
|
|
909
|
+
### `kxm auth token`
|
|
910
|
+
|
|
911
|
+
```text
|
|
912
|
+
kxm auth token [--status] [--clear] [--issue]
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
Inspects, issues, or clears the local session token that scopes CLI agent-tool commands (`peer`, `workflow checkpoint|record|wait`). A token is a `kxm.session-token.v1` record with an operator tool policy and a 24-hour expiry, stored in `<KXM_USER_CONFIG_DIR>/session.token`.
|
|
916
|
+
|
|
917
|
+
| Option | Argument | Default | Description |
|
|
918
|
+
|---|---|---|---|
|
|
919
|
+
| `--status` | none | off | Check status of the active session token |
|
|
920
|
+
| `--clear` | none | off | Clear persisted disk session token |
|
|
921
|
+
| `--issue` | none | off | Force issuing a fresh session token |
|
|
922
|
+
|
|
923
|
+
- With no flag, prints the valid on-disk token, minting and saving one if none exists. `--issue` always mints and saves a new one. `--clear` deletes the file. `--status` checks `KXM_SESSION_TOKEN` first, then the file.
|
|
924
|
+
- Mutates (except `--status`). Under `--dry-run`, `--issue` (or no flag with no saved token) plans the token file write and prints no token, `--clear` plans the deletion (`cleared` reports whether the file exists), and no flag with a saved token prints that token as usual. No hub needed.
|
|
925
|
+
- JSON keys: `token`; `cleared`; or for `--status`: `source` (`env` or `disk`), `valid`, `sessionId`, `issuedAt`, `expiresAt`, `path`. Dry runs add `dryRun` and `planned`.
|
|
926
|
+
- `--status` exits 1 with `no_token` when neither source has a token, and 1 when the environment token is invalid or expired.
|
|
927
|
+
- A malformed or expired `KXM_SESSION_TOKEN` or token file makes agent-tool commands fail with `session_token_invalid`; a policy that excludes a tool fails with `tool_policy_denied`.
|
|
928
|
+
|
|
929
|
+
```bash
|
|
930
|
+
kxm auth token --status
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
```text
|
|
934
|
+
No active session token found in env or disk
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
```bash
|
|
938
|
+
kxm auth token --issue --dry-run --json
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
```text
|
|
942
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"auth token","dryRun":true,"planned":[{"action":"write","target":"~/.config/kxm/session.token"}]}
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
```bash
|
|
946
|
+
kxm auth token --issue --json
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
Not run: stores a credential.
|
|
950
|
+
|
|
951
|
+
## `kxm update`
|
|
952
|
+
|
|
953
|
+
```text
|
|
954
|
+
kxm update [harness] [--check | --kxm] [--self | --extensions | --models]
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
Checks for or applies a KXM operator package update, and runs the native updaters of detected harnesses.
|
|
958
|
+
|
|
959
|
+
| Option | Argument | Default | Description |
|
|
960
|
+
|---|---|---|---|
|
|
961
|
+
| `--check` | none | off | Check for a kxm package update without applying |
|
|
962
|
+
| `--kxm` | none | off | Apply the kxm operator package update (GitHub release tarball or npm) |
|
|
963
|
+
| `--self` | none | off | Update only the harness CLI |
|
|
964
|
+
| `--extensions` | none | off | Update only extensions/plugins (Pi packages, Claude kxm) |
|
|
965
|
+
| `--models` | none | off | Refresh model catalogs where the harness supports it |
|
|
966
|
+
|
|
967
|
+
- Arguments: `[harness]`, Harness id (default: every detected harness).
|
|
968
|
+
- `--check` cannot be combined with any other update flag or a harness (exit 2, `scope_conflict`), and at most one of `--self`, `--extensions`, `--models` is allowed (exit 2).
|
|
969
|
+
- From a source checkout, `--check` reports the running version without network access, and `--kxm` is refused (exit 2, `install_kind_source`) with an instruction to `git pull`. Only npm-global installs can apply `--kxm`; other install kinds exit 2 with `install_kind_<kind>`. A GitHub release must publish a sha256 digest for `kxm-<version>.tgz` or the install fails closed (`release_digest_missing`, `release_digest_mismatch`).
|
|
970
|
+
- Settings come only from `update.yaml` under the user state root (`auto: true` enables auto-apply); a project `.kxm/update.yaml` is ignored with a warning.
|
|
971
|
+
- Without `--check` or a lone `--kxm`, KXM probes harnesses (as `harness list` does) and runs each updater for the selected scope. An unknown harness id exits 2 (`unknown_harness` step); a failed step exits 1.
|
|
972
|
+
- Honors `--dry-run`: steps are planned, not run, and the cached update notice is not refreshed.
|
|
973
|
+
- JSON keys: `--check` gives `current`, `available`, `auto`, `source`, `latest`, `message`, `installKind`, `root`; otherwise `dryRun`, `scope`, `notice`, `kxm` (when applying), `steps` (`harness`, `scope`, `command`, `args`, `outcome`, `detail`), `installKind`, `root`.
|
|
974
|
+
|
|
975
|
+
```bash
|
|
976
|
+
kxm update --check --dry-run --json
|
|
977
|
+
```
|
|
978
|
+
|
|
979
|
+
```text
|
|
980
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"update check","current":"0.7.1","available":false,"auto":false,"source":"github","installKind":"source","root":"/work/kxm","message":"kxm 0.7.1 (running from source at /work/kxm)"}
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
```bash
|
|
984
|
+
kxm update --dry-run
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
```text
|
|
988
|
+
nothing to update
|
|
989
|
+
```
|
|
990
|
+
|
|
991
|
+
```bash
|
|
992
|
+
kxm update --kxm --dry-run --json
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
```text
|
|
996
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"update","error":"install_kind_source","installKind":"source","root":"/work/kxm","instruction":"kxm is running from source at /work/kxm; update it with git pull there, not kxm update --kxm"}
|
|
997
|
+
```
|
|
998
|
+
|
|
999
|
+
## `kxm models`
|
|
1000
|
+
|
|
1001
|
+
```text
|
|
1002
|
+
kxm models
|
|
1003
|
+
```
|
|
1004
|
+
|
|
1005
|
+
Opens an interactive screen over `.kxm/models/inventory.yaml` that shows each model's route state and role bindings. Keys: `a` admit, `d` disable, `r` add a role binding, `x` remove a role binding, `q` quit. Changes are written to `.kxm/routes.yaml` and `.kxm/roles/<role>.yaml` in `KXM_WORKDIR` or the current directory.
|
|
1006
|
+
|
|
1007
|
+
- Needs an interactive terminal. With `--json` or without a TTY it exits 2 with `interactive_tty_required`.
|
|
1008
|
+
|
|
1009
|
+
```bash
|
|
1010
|
+
kxm models --json
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
```text
|
|
1014
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"models","error":"interactive_tty_required"}
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
### `kxm models inventory-refresh`
|
|
1018
|
+
|
|
1019
|
+
```text
|
|
1020
|
+
kxm models inventory-refresh
|
|
1021
|
+
kxm models refresh
|
|
1022
|
+
```
|
|
1023
|
+
|
|
1024
|
+
Refreshes the YAML model inventory from the OpenRouter (`https://openrouter.ai/api/v1/models`) and Nous (`https://inference-api.nousresearch.com/v1/models`) catalogs, recording standard and discount prices. `OPENROUTER_API_KEY` and `NOUS_API_KEY` are sent when set; `KXM_OPENROUTER_MODELS_URL` and `KXM_NOUS_MODELS_URL` override the endpoints. `refresh` is an alias.
|
|
1025
|
+
|
|
1026
|
+
No command-specific options.
|
|
1027
|
+
|
|
1028
|
+
- Writes `.kxm/models/inventory.yaml`. Calls external services. Honors `--dry-run`.
|
|
1029
|
+
- JSON keys: `output`, `models`, `sources` (per source: `url`, `ok`, `error`). Exit 1 when any source failed.
|
|
1030
|
+
|
|
1031
|
+
```bash
|
|
1032
|
+
kxm models refresh --dry-run
|
|
1033
|
+
```
|
|
1034
|
+
|
|
1035
|
+
```text
|
|
1036
|
+
would refresh .kxm/models/inventory.yaml
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
## `kxm routes`
|
|
1040
|
+
|
|
1041
|
+
Admits or disables model routes recorded in `.kxm/routes.yaml` (`kxm.routes.v2`) in `KXM_WORKDIR` or the current directory. A retired `.kxm/producers.yaml` makes these commands fail. None needs a hub.
|
|
1042
|
+
|
|
1043
|
+
### `kxm routes list`
|
|
1044
|
+
|
|
1045
|
+
```text
|
|
1046
|
+
kxm routes list
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
Lists admitted and disabled routes.
|
|
1050
|
+
|
|
1051
|
+
No command-specific options.
|
|
1052
|
+
|
|
1053
|
+
- Reads only. JSON keys: `policy` (`schema`, `updatedAt`, `admitted`, `disabled`, `roles`).
|
|
1054
|
+
|
|
1055
|
+
```bash
|
|
1056
|
+
kxm routes list
|
|
1057
|
+
```
|
|
1058
|
+
|
|
1059
|
+
```text
|
|
1060
|
+
no route decisions
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
```bash
|
|
1064
|
+
kxm routes list --json
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
```text
|
|
1068
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"routes list","policy":{"schema":"kxm.routes.v2","updatedAt":"2026-09-23T13:50:08.663Z","admitted":[],"disabled":[],"roles":{}}}
|
|
1069
|
+
```
|
|
1070
|
+
|
|
1071
|
+
### `kxm routes count`
|
|
1072
|
+
|
|
1073
|
+
```text
|
|
1074
|
+
kxm routes count
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
Counts admitted and disabled routes.
|
|
1078
|
+
|
|
1079
|
+
No command-specific options.
|
|
1080
|
+
|
|
1081
|
+
- Reads only. JSON keys: `admitted`, `disabled`, `summary`.
|
|
1082
|
+
|
|
1083
|
+
```bash
|
|
1084
|
+
kxm routes count
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
```text
|
|
1088
|
+
0 admitted / 0 disabled
|
|
1089
|
+
```
|
|
1090
|
+
|
|
1091
|
+
### `kxm routes admit`
|
|
1092
|
+
|
|
1093
|
+
```text
|
|
1094
|
+
kxm routes admit [--model <id>]
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
Admits a model route from the inventory.
|
|
1098
|
+
|
|
1099
|
+
| Option | Argument | Default | Description |
|
|
1100
|
+
|---|---|---|---|
|
|
1101
|
+
| `--model` | `<id>` | interactive picker | Exact model id; omit to choose interactively |
|
|
1102
|
+
|
|
1103
|
+
- The model must exist in `.kxm/models/inventory.yaml` (case-insensitive match). Without `--model`, a terminal shows a numbered picker of up to 100 models. With no inventory, no TTY, or `--json`, it exits 2 with `model_selection_required`.
|
|
1104
|
+
- Writes `.kxm/routes.yaml`. Honors `--dry-run`.
|
|
1105
|
+
- JSON keys: `model`, `policy` (or `dryRun`).
|
|
1106
|
+
|
|
1107
|
+
```bash
|
|
1108
|
+
kxm routes admit --model x-ai/grok-4.6 --dry-run
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
Not run with an inventory; without one it exits 2 with `model_selection_required`.
|
|
1112
|
+
|
|
1113
|
+
### `kxm routes disable`
|
|
1114
|
+
|
|
1115
|
+
```text
|
|
1116
|
+
kxm routes disable [--model <id>]
|
|
1117
|
+
```
|
|
1118
|
+
|
|
1119
|
+
Disables a model route from the inventory. Same selection rules, output, and errors as `routes admit`.
|
|
1120
|
+
|
|
1121
|
+
| Option | Argument | Default | Description |
|
|
1122
|
+
|---|---|---|---|
|
|
1123
|
+
| `--model` | `<id>` | interactive picker | Exact model id; omit to choose interactively |
|
|
1124
|
+
|
|
1125
|
+
```bash
|
|
1126
|
+
kxm routes disable --dry-run --json
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
```text
|
|
1130
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"routes disabled","error":"model_selection_required"}
|
|
1131
|
+
```
|
|
1132
|
+
|
|
1133
|
+
## `kxm role`
|
|
1134
|
+
|
|
1135
|
+
Manages role definitions (`kxm.role.v1`) and role-seat host bindings (`kxm.role-hosts.v1`). Local scope is `.kxm/roles/` and `.kxm/role-hosts.yaml` in the current directory; global scope is `<KXM_USER_CONFIG_DIR>/roles/` and `<KXM_USER_CONFIG_DIR>/role-hosts.yaml`. A local role with the same ID overrides a global one. `kxm role` with no subcommand runs `role list`. For `--pick` without a value on a non-interactive shell, set `KXM_PICK_SELECT` to an index or ID. Errors from this group are plain text on stderr, even with `--json`.
|
|
1136
|
+
|
|
1137
|
+
### `kxm role list`
|
|
1138
|
+
|
|
1139
|
+
```text
|
|
1140
|
+
kxm role list [--scope all|global|local]
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
Lists configured roles across scopes.
|
|
1144
|
+
|
|
1145
|
+
| Option | Argument | Default | Description |
|
|
1146
|
+
|---|---|---|---|
|
|
1147
|
+
| `--scope` | `<scope>` | `all` | Filter by scope: all, global, or local |
|
|
1148
|
+
|
|
1149
|
+
- Reads only. JSON keys: `roles`.
|
|
1150
|
+
|
|
1151
|
+
```bash
|
|
1152
|
+
kxm role list
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
```text
|
|
1156
|
+
No roles configured.
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
### `kxm role get`
|
|
1160
|
+
|
|
1161
|
+
```text
|
|
1162
|
+
kxm role get <roleId> [--scope all|global|local]
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
Prints a role definition as YAML.
|
|
1166
|
+
|
|
1167
|
+
| Option | Argument | Default | Description |
|
|
1168
|
+
|---|---|---|---|
|
|
1169
|
+
| `--scope` | `<scope>` | `all` | Filter by scope: all, global, or local |
|
|
1170
|
+
|
|
1171
|
+
- Reads only. JSON keys: `roleId`, `scope`, `filePath`, `role`. A missing role prints `kxm: role '<id>' not found` and exits 1.
|
|
1172
|
+
|
|
1173
|
+
```bash
|
|
1174
|
+
kxm role get writer --scope local
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
Not run with a configured role; in a fresh project it exits 1 with `kxm: role 'writer' not found`.
|
|
1178
|
+
|
|
1179
|
+
### `kxm role add`
|
|
1180
|
+
|
|
1181
|
+
```text
|
|
1182
|
+
kxm role add [roleId] [--file <path>] [--description <text>] [--skills <skills>] [--harness <harness>] [--model <model>] [--scope global|local] [--overwrite] [--pick [selection]]
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
Adds a role definition. Without a role ID, or with `--pick`, you choose from the built-in templates (`writer`, `planner`, `critic-arch`, `critic-cli`, `verifier`) and, for local scope, existing global roles. With `--file`, the YAML file is used and its `id` is replaced by the role ID.
|
|
1186
|
+
|
|
1187
|
+
| Option | Argument | Default | Description |
|
|
1188
|
+
|---|---|---|---|
|
|
1189
|
+
| `--file` | `<path>` | none | Path to YAML role definition file |
|
|
1190
|
+
| `--description` | `<text>` | `Role <id>` | Role description |
|
|
1191
|
+
| `--skills` | `<skills>` | none | Comma-separated skills list |
|
|
1192
|
+
| `--harness` | `<harness>` | `pi` when `--model` is set | Primary harness name (e.g. grok, claude, agy, pi) |
|
|
1193
|
+
| `--model` | `<model>` | none | Primary model identifier (e.g. grok-4.6, fable, gemini-3.8-flash-high) |
|
|
1194
|
+
| `--scope` | `<scope>` | `local` | Configuration scope: global or local (default: local) |
|
|
1195
|
+
| `--overwrite` | none | off | Overwrite existing role definition if present |
|
|
1196
|
+
| `--pick` | `[selection]` | none | Pick from available role templates (index or id) |
|
|
1197
|
+
|
|
1198
|
+
- Writes `<scope dir>/roles/<id>.yaml`. `--dry-run` plans the write and writes nothing.
|
|
1199
|
+
- JSON keys: `roleId`, `id`, `filePath`, `scope`.
|
|
1200
|
+
|
|
1201
|
+
```bash
|
|
1202
|
+
kxm role add demo-role --description "Demo role" --dry-run --json
|
|
1203
|
+
```
|
|
1204
|
+
|
|
1205
|
+
```text
|
|
1206
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"role add","roleId":"demo-role","id":"demo-role","filePath":"/work/proj/.kxm/roles/demo-role.yaml","scope":"local","dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/roles/demo-role.yaml"}]}
|
|
1207
|
+
```
|
|
1208
|
+
|
|
1209
|
+
Add a reviewer role with a Claude model, and copy a built-in template into global scope (Not run):
|
|
1210
|
+
|
|
1211
|
+
```bash
|
|
1212
|
+
kxm role add reviewer --description "Independent reviewer" --harness claude --model fable --skills kxm
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
```bash
|
|
1216
|
+
kxm role add --pick critic-arch --scope global
|
|
1217
|
+
```
|
|
1218
|
+
|
|
1219
|
+
### `kxm role remove`
|
|
1220
|
+
|
|
1221
|
+
```text
|
|
1222
|
+
kxm role remove [roleId] [--scope global|local] [--pick [selection]]
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
Removes a role definition file.
|
|
1226
|
+
|
|
1227
|
+
| Option | Argument | Default | Description |
|
|
1228
|
+
|---|---|---|---|
|
|
1229
|
+
| `--scope` | `<scope>` | `local` | Configuration scope: global or local (default: local) |
|
|
1230
|
+
| `--pick` | `[selection]` | none | Pick a role to remove (index or id) |
|
|
1231
|
+
|
|
1232
|
+
- Deletes a file. `--dry-run` plans the deletion, deletes nothing, and reports `removed: false`.
|
|
1233
|
+
- JSON keys: `roleId`, `id`, `removed`, `filePath`, `scope`.
|
|
1234
|
+
|
|
1235
|
+
```bash
|
|
1236
|
+
kxm role remove demo-role --dry-run --json
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
```text
|
|
1240
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"role remove","roleId":"demo-role","id":"demo-role","removed":false,"filePath":"/work/proj/.kxm/roles/demo-role.yaml","scope":"local","dryRun":true,"planned":[{"action":"delete","target":"/work/proj/.kxm/roles/demo-role.yaml"}]}
|
|
1241
|
+
```
|
|
1242
|
+
|
|
1243
|
+
### `kxm role modify`
|
|
1244
|
+
|
|
1245
|
+
```text
|
|
1246
|
+
kxm role modify [roleId] [--description <text>] [--add-skill <skill>] [--remove-skill <skill>] [--add-model <harness:model>] [--remove-model <model>] [--scope global|local] [--pick [selection]]
|
|
1247
|
+
```
|
|
1248
|
+
|
|
1249
|
+
Updates an existing role's description, skills, or model roster and rewrites its file.
|
|
1250
|
+
|
|
1251
|
+
| Option | Argument | Default | Description |
|
|
1252
|
+
|---|---|---|---|
|
|
1253
|
+
| `--description` | `<text>` | unchanged | Updated description |
|
|
1254
|
+
| `--add-skill` | `<skill>` | none | Skill to add |
|
|
1255
|
+
| `--remove-skill` | `<skill>` | none | Skill to remove |
|
|
1256
|
+
| `--add-model` | `<harness:model>` | none | Model to add to roster |
|
|
1257
|
+
| `--remove-model` | `<model>` | none | Model to remove from roster |
|
|
1258
|
+
| `--scope` | `<scope>` | first match | Configuration scope: global or local |
|
|
1259
|
+
| `--pick` | `[selection]` | none | Pick a role to modify (index or id) |
|
|
1260
|
+
|
|
1261
|
+
- `--add-model` without a colon uses harness `pi`. `--dry-run` returns the modified role and plans the write without making it.
|
|
1262
|
+
- JSON keys: `roleId`, `id`, `role`, `filePath`, `scope`.
|
|
1263
|
+
|
|
1264
|
+
```bash
|
|
1265
|
+
kxm role modify demo-role --add-skill kxm --dry-run --json
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
```text
|
|
1269
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"role modify","roleId":"demo-role","id":"demo-role","role":{"schema":"kxm.role.v1","id":"demo-role","description":"Demo role","skills":["kxm"],"roster":[]},"filePath":"/work/proj/.kxm/roles/demo-role.yaml","scope":"local","dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/roles/demo-role.yaml"}]}
|
|
1270
|
+
```
|
|
1271
|
+
|
|
1272
|
+
Add a Claude model to a role's roster (Not run):
|
|
1273
|
+
|
|
1274
|
+
```bash
|
|
1275
|
+
kxm role modify reviewer --add-model claude:fable --add-skill kxm-peer
|
|
1276
|
+
```
|
|
1277
|
+
|
|
1278
|
+
### `kxm role hosts`
|
|
1279
|
+
|
|
1280
|
+
```text
|
|
1281
|
+
kxm role hosts [--scope all|global|local]
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
Lists role seats (`critic-arch`, `critic-cli`, `planner`, `verifier`, `writer`, plus any configured seat) and the host, model, and effort each resolves to, with the source of the decision (`override`, `role-hosts`, `seat-default`, `role-roster`, or `fallback`).
|
|
1285
|
+
|
|
1286
|
+
| Option | Argument | Default | Description |
|
|
1287
|
+
|---|---|---|---|
|
|
1288
|
+
| `--scope` | `<scope>` | `all` | Filter by scope: all, global, or local |
|
|
1289
|
+
|
|
1290
|
+
- Reads only. JSON keys: `scope`, `filePath`, `seats` (`seatId`, `host`, `model`, `provider`, `effort`, `source`, `configuredHost`, `configuredModel`), `hostProviders`.
|
|
1291
|
+
|
|
1292
|
+
```bash
|
|
1293
|
+
kxm role hosts
|
|
1294
|
+
```
|
|
1295
|
+
|
|
1296
|
+
```text
|
|
1297
|
+
ROLE SEATS (default):
|
|
1298
|
+
critic-arch -> host: pi [anthropic/claude-fable-5.1] (via seat-default)
|
|
1299
|
+
critic-cli -> host: pi [openai/gpt-5.6-sol] (via seat-default)
|
|
1300
|
+
planner -> host: pi [anthropic/claude-fable-5.1] (via seat-default)
|
|
1301
|
+
verifier -> host: pi [evaluator] (via seat-default)
|
|
1302
|
+
writer -> host: grok [x-ai/grok-4.6] (via seat-default)
|
|
1303
|
+
```
|
|
1304
|
+
|
|
1305
|
+
### `kxm role set-host`
|
|
1306
|
+
|
|
1307
|
+
```text
|
|
1308
|
+
kxm role set-host <seatId> <host> [--model <model>] [--effort low|medium|high|xhigh] [--scope global|local]
|
|
1309
|
+
```
|
|
1310
|
+
|
|
1311
|
+
Binds a role seat to a host in `role-hosts.yaml`.
|
|
1312
|
+
|
|
1313
|
+
| Option | Argument | Default | Description |
|
|
1314
|
+
|---|---|---|---|
|
|
1315
|
+
| `--model` | `<model>` | none | Model identifier for this seat |
|
|
1316
|
+
| `--effort` | `<effort>` | none | Effort level: low, medium, high, xhigh |
|
|
1317
|
+
| `--scope` | `<scope>` | `local` | Configuration scope: global or local (default: local) |
|
|
1318
|
+
|
|
1319
|
+
- Writes `.kxm/role-hosts.yaml` (or the global file). `--dry-run` plans the write and writes nothing.
|
|
1320
|
+
- JSON keys: `seatId`, `host`, `binding`, `filePath`, `scope`.
|
|
1321
|
+
|
|
1322
|
+
```bash
|
|
1323
|
+
kxm role set-host writer claude --model fable --effort high --dry-run --json
|
|
1324
|
+
```
|
|
1325
|
+
|
|
1326
|
+
```text
|
|
1327
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"role set-host","seatId":"writer","host":"claude","binding":{"host":"claude","model":"fable","effort":"high"},"filePath":"/work/proj/.kxm/role-hosts.yaml","scope":"local","dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/role-hosts.yaml"}]}
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
### `kxm role resume`
|
|
1331
|
+
|
|
1332
|
+
```text
|
|
1333
|
+
kxm role resume <runId> [ruling]
|
|
1334
|
+
```
|
|
1335
|
+
|
|
1336
|
+
Resumes an audit-escalated run with an operator directive. The default ruling is `operator_ruling: waived and resumed`.
|
|
1337
|
+
|
|
1338
|
+
- Arguments: `<runId>`; `[ruling]`, free text recorded with the decision.
|
|
1339
|
+
- For a KXM run ID (`run_` followed by 32 hex digits) inside a project, posts an `audit_escalation` signal with action `unblock` to the Runtime, starting the supervisor if needed. `--dry-run` plans the request without starting the supervisor. JSON keys: `runId`, `ruling`, `unblocked`.
|
|
1340
|
+
- For any other ID, updates the hub store at `.kxm/state/kxm.db` in the current directory directly (ignoring `--workspace` and `KXM_DATA_PATH`) and adds a `decision` journal entry. `--dry-run` reads the store read-only, reports the stage it would resume and the resulting `status`, and plans the write. JSON keys: `runId`, `stageId`, `ruling`, `status`.
|
|
1341
|
+
- Errors: `resume_failed` (exit 1), or a plain `not found` line (exit 1).
|
|
1342
|
+
|
|
1343
|
+
```bash
|
|
1344
|
+
kxm role resume run_0123456789abcdef0123456789abcdef "waive the audit" --dry-run --json
|
|
1345
|
+
```
|
|
1346
|
+
|
|
1347
|
+
```text
|
|
1348
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"role resume","runId":"run_0123456789abcdef0123456789abcdef","ruling":"waive the audit","dryRun":true,"planned":[{"action":"request","target":"POST kxm-runtime /v1/runs/run_0123456789abcdef0123456789abcdef/signal (audit_escalation unblock)"}]}
|
|
1349
|
+
```
|
|
1350
|
+
|
|
1351
|
+
A hub workflow run waiting on an audit escalation:
|
|
1352
|
+
|
|
1353
|
+
```bash
|
|
1354
|
+
kxm role resume wf_dry_run "carry on" --dry-run
|
|
1355
|
+
```
|
|
1356
|
+
|
|
1357
|
+
```text
|
|
1358
|
+
dry run: resume workflow run wf_dry_run (stage: review)
|
|
1359
|
+
would write /work/proj/.kxm/state/kxm.db (workflow_runs wf_dry_run, one workflow_journal decision)
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
## `kxm run`
|
|
1363
|
+
|
|
1364
|
+
```text
|
|
1365
|
+
kxm run <workflow> [prompt...]
|
|
1366
|
+
```
|
|
1367
|
+
|
|
1368
|
+
Create a KXM run (offline-first; `kxm runs drive <runId> --simulated` executes it model-free). The run is immutable and pins the project's `homeRuntimeId`, config revision, and executor and tool policy revisions, and it stores only a hash of the prompt. The Runtime supervisor is started first if it is not running. No steps execute until the run is driven (see [`kxm runs drive`](#kxm-runs-drive)); the text output's second line prints the command that drives the new run model-free and the one that cancels it.
|
|
1369
|
+
|
|
1370
|
+
- Arguments: `<workflow>`, Workflow id to run (a file under `.kxm/workflows/`); `[prompt...]`, Run prompt (hashed, never stored raw).
|
|
1371
|
+
- No command-specific options. Refuses `--workspace` (exit 2).
|
|
1372
|
+
- Needs a KXM project. Starts and uses the Runtime; no hub needed. Honors `--dry-run`, which validates the project and prints the plan without starting the supervisor.
|
|
1373
|
+
- JSON keys: `phase`, `idempotent`, `run` (`runId`, `homeRuntimeId`, `status`, `configRevision`), `supervisor` (`runtimeId`, `port`, `started`). Dry run: `projectRoot`, `workflowId`, `configRevision`. The JSON result does not carry the drive command.
|
|
1374
|
+
- Errors: `workflow_required` (exit 2), `project_required`, `run_workflow_unknown`, `run_failed` with `issues` (any invalid file in the project fails the load, for example `gate_outcome_impossible`), `run_io_failed` (exit 1).
|
|
1375
|
+
- The `default` workflow that `kxm init` writes sets `limits.maxAgentTimeMs`, which the Runtime does not enforce yet, so a run of it is created but `kxm runs drive` refuses it with `run_handoff_required`. A workflow written by `kxm workflow add <id> --template implement-and-verify` omits that limit.
|
|
1376
|
+
|
|
1377
|
+
```bash
|
|
1378
|
+
kxm run default "Fix the flaky login test" --dry-run
|
|
1379
|
+
```
|
|
1380
|
+
|
|
1381
|
+
```text
|
|
1382
|
+
run plan: workflow default at sha256:80457232cbfc… (no run created)
|
|
1383
|
+
```
|
|
1384
|
+
|
|
1385
|
+
```bash
|
|
1386
|
+
kxm run default "Fix the flaky login test" --dry-run --json
|
|
1387
|
+
```
|
|
1388
|
+
|
|
1389
|
+
```text
|
|
1390
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"run","dryRun":true,"projectRoot":"/work/proj","workflowId":"default","configRevision":"sha256:80457232cbfc0d1a88c53a2b693061083c83df6e95409e3ae7f75ccfc9f93cf4"}
|
|
1391
|
+
```
|
|
1392
|
+
|
|
1393
|
+
Create a run (this starts the Runtime supervisor; stop it afterwards with `kxm runtime stop`):
|
|
1394
|
+
|
|
1395
|
+
```bash
|
|
1396
|
+
kxm run default "Fix the flaky login test"
|
|
1397
|
+
```
|
|
1398
|
+
|
|
1399
|
+
```text
|
|
1400
|
+
run created: run_a80e84c98f514299b82f0157f4537ea3 (home rtm_1a42e069…, config sha256:b45f8f51a506…)
|
|
1401
|
+
drive it model-free: kxm runs drive run_a80e84c98f514299b82f0157f4537ea3 --simulated --wait (or cancel: kxm runs cancel run_a80e84c98f514299b82f0157f4537ea3)
|
|
1402
|
+
```
|
|
1403
|
+
|
|
1404
|
+
## `kxm runs`
|
|
1405
|
+
|
|
1406
|
+
Reads and drives runs through the Runtime supervisor. Every subcommand needs a KXM project, and every subcommand except a dry run starts the supervisor if it is not running. Under `--dry-run`, `status`, `list`, and `receipt` read from a supervisor that is already running and otherwise exit 2 with `dry_run_unsupported`; `drive` and `cancel` print a plan without contacting it. The run ID is the `runId` printed by `kxm run`. Errors carry `issues` from the Runtime, for example `run_unknown`.
|
|
1407
|
+
|
|
1408
|
+
### `kxm runs status`
|
|
1409
|
+
|
|
1410
|
+
```text
|
|
1411
|
+
kxm runs status <runId>
|
|
1412
|
+
```
|
|
1413
|
+
|
|
1414
|
+
Show the projected status of a run, including durable drive receipt state (open / receipt verified / unsettled / orphaned).
|
|
1415
|
+
|
|
1416
|
+
- Arguments: `<runId>`, Run id. No command-specific options. Reads run state, but starts the supervisor if needed (not under `--dry-run`).
|
|
1417
|
+
- Text: `run <id>: <status> (workflow <id>, updated <time>)`, plus a drive line such as `drive <id>: open`, `completed (receipt verified)`, `unsettled <reason>`, `handoff`, `cancelled (<reason>)`, or `no receipt (orphaned)`.
|
|
1418
|
+
- JSON keys: `run` (`runId`, `status`, `workflowId`, `configRevision`, `updatedAt`, ...), `drive` (`driveId`, `mode`, `openedAt`, `receipt`, `verified`, `divergence`).
|
|
1419
|
+
- Errors: `project_required`, `run_status_failed`, `run_status_io_failed` (exit 1).
|
|
1420
|
+
|
|
1421
|
+
```bash
|
|
1422
|
+
kxm runs status run_a80e84c98f514299b82f0157f4537ea3
|
|
1423
|
+
```
|
|
1424
|
+
|
|
1425
|
+
```text
|
|
1426
|
+
run run_a80e84c98f514299b82f0157f4537ea3: preparing (workflow default, updated 2026-09-23T17:47:29.682Z)
|
|
1427
|
+
```
|
|
1428
|
+
|
|
1429
|
+
With no supervisor running:
|
|
1430
|
+
|
|
1431
|
+
```bash
|
|
1432
|
+
kxm runs status run_0123456789abcdef0123456789abcdef --dry-run
|
|
1433
|
+
```
|
|
1434
|
+
|
|
1435
|
+
```text
|
|
1436
|
+
kxm runs status --dry-run refused: the Runtime supervisor is not running and --dry-run will not start it
|
|
1437
|
+
```
|
|
1438
|
+
|
|
1439
|
+
### `kxm runs drive`
|
|
1440
|
+
|
|
1441
|
+
```text
|
|
1442
|
+
kxm runs drive <runId> [--simulated] [--wait] [--timeout-ms <n>]
|
|
1443
|
+
```
|
|
1444
|
+
|
|
1445
|
+
Opens a drive of the run. With `--simulated`, a model-free producer reports every agent step as passed. Without `--simulated` the drive runs in live mode: each agent step invokes its harness through a one-shot producer, and the agent's model must be an admitted route (otherwise `producer_route_not_admitted`).
|
|
1446
|
+
|
|
1447
|
+
| Option | Argument | Default | Description |
|
|
1448
|
+
|---|---|---|---|
|
|
1449
|
+
| `--simulated` | none | off | Use the model-free simulation producer |
|
|
1450
|
+
| `--wait` | none | off | Wait until a drive receipt is recorded; exits 0 only for a VERIFIED COMPLETED settlement |
|
|
1451
|
+
| `--timeout-ms` | `<n>` | `60000` | Wait timeout in milliseconds (default 60000, max 600000) |
|
|
1452
|
+
|
|
1453
|
+
- Arguments: `<runId>`, Run id.
|
|
1454
|
+
- `--timeout-ms` applies only with `--wait` and must be an integer from 1 to 600000 (`run_drive_timeout_invalid`, exit 1).
|
|
1455
|
+
- Mutates run state. Honors `--dry-run`.
|
|
1456
|
+
- JSON keys without `--wait`: `runId`, `driveId`, `poll`, `mode`, `status` (`accepted`). With `--wait`: `receipt`, `verified`; a timeout prints `error: "timeout"`.
|
|
1457
|
+
- Exit 0 when accepted, or with `--wait` only for a verified completed settlement; otherwise 1. Runtime refusals include `run_handoff_required` and `run_busy`, printed as `run drive failed: <request path>: <code>: <message>` (JSON: `error: "run_drive_failed"` with the code in `issues`). A `run_handoff_required` message ends with `(handoff reason <reason>; field <field>; detail <detail>)`, each part capped at 200 characters, so the refusal names what to change.
|
|
1458
|
+
|
|
1459
|
+
```bash
|
|
1460
|
+
kxm runs drive run_0123456789abcdef0123456789abcdef --simulated --dry-run
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
```text
|
|
1464
|
+
drive plan: run run_0123456789abcdef0123456789abcdef in simulated mode (no events written)
|
|
1465
|
+
```
|
|
1466
|
+
|
|
1467
|
+
The `default` workflow from `kxm init` is handed off (see [`kxm run`](#kxm-run)):
|
|
1468
|
+
|
|
1469
|
+
```bash
|
|
1470
|
+
kxm runs drive run_a80e84c98f514299b82f0157f4537ea3 --simulated
|
|
1471
|
+
```
|
|
1472
|
+
|
|
1473
|
+
```text
|
|
1474
|
+
run drive failed: /v1/runs/run_a80e84c98f514299b82f0157f4537ea3/drive?projectRoot=%2Fwork%2Fproj: run_handoff_required: runtime request failed with HTTP 409 (handoff reason limit_unsupported; field limits.maxAgentTimeMs; detail agent-time budget enforcement is not available in this slice)
|
|
1475
|
+
```
|
|
1476
|
+
|
|
1477
|
+
```bash
|
|
1478
|
+
kxm runs drive run_0123456789abcdef0123456789abcdef --simulated --wait --timeout-ms 120000
|
|
1479
|
+
```
|
|
1480
|
+
|
|
1481
|
+
Not run: starts the Runtime and writes run events.
|
|
1482
|
+
|
|
1483
|
+
### `kxm runs receipt`
|
|
1484
|
+
|
|
1485
|
+
```text
|
|
1486
|
+
kxm runs receipt <runId> [--all]
|
|
1487
|
+
```
|
|
1488
|
+
|
|
1489
|
+
Print the newest drive receipt for a run.
|
|
1490
|
+
|
|
1491
|
+
| Option | Argument | Default | Description |
|
|
1492
|
+
|---|---|---|---|
|
|
1493
|
+
| `--all` | none | off | Print the capped receipt list for the run |
|
|
1494
|
+
|
|
1495
|
+
- Arguments: `<runId>`, Run id. Text mode prints the newest receipt's settlement as JSON; `--all` prints the list. Starts the supervisor if needed (not under `--dry-run`).
|
|
1496
|
+
- JSON keys: `receipt`, or `receipts` with `--all`. Exit 1 with `no_receipts` when the run was never driven.
|
|
1497
|
+
|
|
1498
|
+
```bash
|
|
1499
|
+
kxm runs receipt run_0123456789abcdef0123456789abcdef --all --json
|
|
1500
|
+
```
|
|
1501
|
+
|
|
1502
|
+
Not run: starts the Runtime supervisor.
|
|
1503
|
+
|
|
1504
|
+
### `kxm runs cancel`
|
|
1505
|
+
|
|
1506
|
+
```text
|
|
1507
|
+
kxm runs cancel <runId>
|
|
1508
|
+
```
|
|
1509
|
+
|
|
1510
|
+
Durably request cancellation of a run: records `run.cancel_requested` then `run.status_changed`. Cancelling a terminal run is an idempotent no-op.
|
|
1511
|
+
|
|
1512
|
+
- Arguments: `<runId>`, Run id. No command-specific options.
|
|
1513
|
+
- Mutates run state. Honors `--dry-run`.
|
|
1514
|
+
- JSON keys: `idempotent`, `run` (`runId`, `status`).
|
|
1515
|
+
|
|
1516
|
+
```bash
|
|
1517
|
+
kxm runs cancel run_0123456789abcdef0123456789abcdef --dry-run
|
|
1518
|
+
```
|
|
1519
|
+
|
|
1520
|
+
```text
|
|
1521
|
+
cancel plan: run run_0123456789abcdef0123456789abcdef (no events written)
|
|
1522
|
+
```
|
|
1523
|
+
|
|
1524
|
+
### `kxm runs list`
|
|
1525
|
+
|
|
1526
|
+
```text
|
|
1527
|
+
kxm runs list
|
|
1528
|
+
```
|
|
1529
|
+
|
|
1530
|
+
List recent runs for the current project. A run whose event log could not be folded is marked `[state unverified: <reason>]`.
|
|
1531
|
+
|
|
1532
|
+
No command-specific options.
|
|
1533
|
+
|
|
1534
|
+
- JSON keys: `runs` (`runId`, `status`, `workflowId`, `createdAt`, `projectionError`). Text prints `no runs` when empty. Starts the supervisor if needed (not under `--dry-run`).
|
|
1535
|
+
|
|
1536
|
+
```bash
|
|
1537
|
+
kxm runs list
|
|
1538
|
+
```
|
|
1539
|
+
|
|
1540
|
+
Not run: starts the Runtime supervisor.
|
|
1541
|
+
|
|
1542
|
+
## `kxm runtime`
|
|
1543
|
+
|
|
1544
|
+
Manages the detached KXM Runtime supervisor: a token-authenticated API on a random `127.0.0.1` port with a stable logical runtime identity, state under `<state root>/runtime/`, and an outbox that syncs run state to the hub.
|
|
1545
|
+
|
|
1546
|
+
### `kxm runtime start`
|
|
1547
|
+
|
|
1548
|
+
```text
|
|
1549
|
+
kxm runtime start
|
|
1550
|
+
```
|
|
1551
|
+
|
|
1552
|
+
Start the Runtime supervisor if not running.
|
|
1553
|
+
|
|
1554
|
+
No command-specific options.
|
|
1555
|
+
|
|
1556
|
+
- Starts a detached process. Honors `--dry-run`.
|
|
1557
|
+
- JSON keys: `runtimeId`, `port`, `started`.
|
|
1558
|
+
|
|
1559
|
+
```bash
|
|
1560
|
+
kxm runtime start --dry-run
|
|
1561
|
+
```
|
|
1562
|
+
|
|
1563
|
+
```text
|
|
1564
|
+
runtime supervisor would auto-start
|
|
1565
|
+
```
|
|
1566
|
+
|
|
1567
|
+
### `kxm runtime status`
|
|
1568
|
+
|
|
1569
|
+
```text
|
|
1570
|
+
kxm runtime status
|
|
1571
|
+
```
|
|
1572
|
+
|
|
1573
|
+
Show Runtime supervisor liveness, judged by its heartbeat as well as its PID. When it is running, also shows each project's outbox sync state (`pending`, `acked`, `refused` counts and the refusal codes).
|
|
1574
|
+
|
|
1575
|
+
No command-specific options.
|
|
1576
|
+
|
|
1577
|
+
- Reads only. Never starts the supervisor.
|
|
1578
|
+
- JSON keys: `running`, `runtimeId`, `pid`, `port`, `state`, `heartbeatAt`, `startedAt`, `sync`.
|
|
1579
|
+
- Exit 0 when running, 1 when not (the JSON still says `ok: true`).
|
|
1580
|
+
|
|
1581
|
+
```bash
|
|
1582
|
+
kxm runtime status
|
|
1583
|
+
```
|
|
1584
|
+
|
|
1585
|
+
```text
|
|
1586
|
+
runtime supervisor is not running
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1589
|
+
```bash
|
|
1590
|
+
kxm runtime status --json
|
|
1591
|
+
```
|
|
1592
|
+
|
|
1593
|
+
```text
|
|
1594
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"runtime status","running":false}
|
|
1595
|
+
```
|
|
1596
|
+
|
|
1597
|
+
### `kxm runtime sync-retry`
|
|
1598
|
+
|
|
1599
|
+
```text
|
|
1600
|
+
kxm runtime sync-retry
|
|
1601
|
+
```
|
|
1602
|
+
|
|
1603
|
+
Re-queue outbox rows the hub durably refused, after the hub-side state is corrected.
|
|
1604
|
+
|
|
1605
|
+
No command-specific options.
|
|
1606
|
+
|
|
1607
|
+
- Needs a running supervisor (it never starts one) and a KXM project. Honors `--dry-run`, but still checks the supervisor first.
|
|
1608
|
+
- JSON keys: `retried`, `projectId`, and the Runtime's result fields.
|
|
1609
|
+
- Errors: `runtime_not_running`, `project_required` (exit 1).
|
|
1610
|
+
|
|
1611
|
+
```bash
|
|
1612
|
+
kxm runtime sync-retry --dry-run --json
|
|
1613
|
+
```
|
|
1614
|
+
|
|
1615
|
+
```text
|
|
1616
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"runtime sync-retry","error":"runtime_not_running"}
|
|
1617
|
+
```
|
|
1618
|
+
|
|
1619
|
+
### `kxm runtime stop`
|
|
1620
|
+
|
|
1621
|
+
```text
|
|
1622
|
+
kxm runtime stop
|
|
1623
|
+
```
|
|
1624
|
+
|
|
1625
|
+
Gracefully stop the Runtime supervisor.
|
|
1626
|
+
|
|
1627
|
+
No command-specific options.
|
|
1628
|
+
|
|
1629
|
+
- Honors `--dry-run`. When nothing is running it prints `stopped: false` and exits 0.
|
|
1630
|
+
- JSON keys: `stopped`.
|
|
1631
|
+
|
|
1632
|
+
With no supervisor running (the not-running check happens before the dry-run check):
|
|
1633
|
+
|
|
1634
|
+
```bash
|
|
1635
|
+
kxm runtime stop --dry-run --json
|
|
1636
|
+
```
|
|
1637
|
+
|
|
1638
|
+
```text
|
|
1639
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"runtime stop","stopped":false}
|
|
1640
|
+
```
|
|
1641
|
+
|
|
1642
|
+
## `kxm agent`
|
|
1643
|
+
|
|
1644
|
+
### `kxm agent worker`
|
|
1645
|
+
|
|
1646
|
+
```text
|
|
1647
|
+
kxm agent worker --name <name> --project <project> [--model <id>] [--fallback-models <ids>] [--tools <names>] [--session-isolation workflow|off] [--no-continue] [--fresh-start]
|
|
1648
|
+
```
|
|
1649
|
+
|
|
1650
|
+
Starts a long-lived, supervised Pi RPC worker in the foreground through `scripts/kxm-worker.mjs`. The worker does not read models, tools, roles, or ownership from any workspace file; pass them explicitly.
|
|
1651
|
+
|
|
1652
|
+
| Option | Argument | Default | Description |
|
|
1653
|
+
|---|---|---|---|
|
|
1654
|
+
| `--name` | `<name>` | `KXM_AGENT_NAME` | Agent name |
|
|
1655
|
+
| `--project` | `<project>` | `KXM_PROJECT` | Hub project |
|
|
1656
|
+
| `--model` | `<id>` | `KXM_WORKER_MODEL`, else the Pi default | Primary model |
|
|
1657
|
+
| `--fallback-models` | `<ids>` | `KXM_WORKER_FALLBACK_MODELS` | Comma-separated fallback models |
|
|
1658
|
+
| `--tools` | `<names>` | `KXM_WORKER_TOOLS`, else Pi defaults | Comma-separated Pi tool allowlist |
|
|
1659
|
+
| `--session-isolation` | `<mode>` | `off` | Pi session isolation: workflow or off (default: off for upgrade compatibility) |
|
|
1660
|
+
| `--no-continue` | none | continue on | Disable every session resume |
|
|
1661
|
+
| `--fresh-start` | none | off | Skip only the initial session resume |
|
|
1662
|
+
|
|
1663
|
+
- Needs Pi and a reachable hub. Runs until stopped (`kxm hub stop` stops managed workers too). The exit code is the worker's.
|
|
1664
|
+
- A name and project are required (exit 2 otherwise); an invalid isolation mode exits 2.
|
|
1665
|
+
- `--dry-run` prints a `kxm.worker-result.v1` envelope with `workspace`, `name`, `project`, `model`, `fallbackModels`, `tools`, `sessionIsolation`, `continue`, `freshStart`.
|
|
1666
|
+
- The remaining worker variables are described in [Configuration](configuration.md#long-lived-worker-settings).
|
|
1667
|
+
|
|
1668
|
+
```bash
|
|
1669
|
+
kxm agent worker --name reviewer --project demo --model xai/grok-4.6 --tools read,grep,find,ls --session-isolation workflow --fresh-start --dry-run
|
|
1670
|
+
```
|
|
1671
|
+
|
|
1672
|
+
```text
|
|
1673
|
+
would start worker
|
|
1674
|
+
```
|
|
1675
|
+
|
|
1676
|
+
```bash
|
|
1677
|
+
kxm agent worker --name coordinator --project demo --model antigravity/claude-sonnet-4-6 --fallback-models xai/grok-4.6 --session-isolation workflow
|
|
1678
|
+
```
|
|
1679
|
+
|
|
1680
|
+
Not run: starts a long-lived Pi worker.
|
|
1681
|
+
|
|
1682
|
+
## `kxm workflow`
|
|
1683
|
+
|
|
1684
|
+
Hub workflow runs (signed-webhook workflows with stages, evidence, waits, and a journal) and workflow definition files. `list`, `get`, and `export` read the local hub store, not a remote hub. `checkpoint`, `record`, and `wait` call the hub as an agent, like the [`peer`](#kxm-peer) commands, and share their policy checks and output shape. `definitions`, `add`, `remove`, and `modify` edit `kxm.workflow.v1` files in `.kxm/workflows/` (local) or `<KXM_USER_CONFIG_DIR>/workflows/` (global).
|
|
1685
|
+
|
|
1686
|
+
### `kxm workflow list`
|
|
1687
|
+
|
|
1688
|
+
```text
|
|
1689
|
+
kxm workflow list
|
|
1690
|
+
```
|
|
1691
|
+
|
|
1692
|
+
List local workflow runs: the newest 200 runs in `.kxm/state/kxm.db` (or `KXM_DATA_PATH`), opened read-only.
|
|
1693
|
+
|
|
1694
|
+
No command-specific options.
|
|
1695
|
+
|
|
1696
|
+
- JSON keys: `runs`. Exit 1 with `state_unavailable` when the store does not exist.
|
|
1697
|
+
|
|
1698
|
+
```bash
|
|
1699
|
+
kxm workflow list --json
|
|
1700
|
+
```
|
|
1701
|
+
|
|
1702
|
+
```text
|
|
1703
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"workflow list","runs":[]}
|
|
1704
|
+
```
|
|
1705
|
+
|
|
1706
|
+
### `kxm workflow get`
|
|
1707
|
+
|
|
1708
|
+
```text
|
|
1709
|
+
kxm workflow get <runId>
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
Show one local workflow run with its stages, evidence, waits, and journal.
|
|
1713
|
+
|
|
1714
|
+
- Arguments: `<runId>`, Workflow run ID. No command-specific options. Reads only.
|
|
1715
|
+
- JSON keys: `run`, `journal`. Exit 1 with `workflow_not_found` or `state_unavailable`.
|
|
1716
|
+
|
|
1717
|
+
```bash
|
|
1718
|
+
kxm workflow get wf_missing --json
|
|
1719
|
+
```
|
|
1720
|
+
|
|
1721
|
+
```text
|
|
1722
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"workflow get","error":"workflow_not_found"}
|
|
1723
|
+
```
|
|
1724
|
+
|
|
1725
|
+
### `kxm workflow checkpoint`
|
|
1726
|
+
|
|
1727
|
+
```text
|
|
1728
|
+
kxm workflow checkpoint [runId] [stageId] [status] [summary] [--evidence <json>] [--evidence-refs <json>]
|
|
1729
|
+
```
|
|
1730
|
+
|
|
1731
|
+
Record a workflow stage checkpoint with evidence. Warnings and failures require another attempt until the stage passes or its attempts are exhausted. Peer-reply requirements must cite durable message IDs through `--evidence-refs`; caller-written evidence strings cannot satisfy them.
|
|
1732
|
+
|
|
1733
|
+
| Option | Argument | Default | Description |
|
|
1734
|
+
|---|---|---|---|
|
|
1735
|
+
| `--run-id` | `<id>` | none | Workflow run ID |
|
|
1736
|
+
| `--stage-id` | `<id>` | none | Active stage ID |
|
|
1737
|
+
| `--status` | `<status>` | none | passed, warning, or failed |
|
|
1738
|
+
| `--summary` | `<text>` | none | Stage summary |
|
|
1739
|
+
| `--evidence` | `<json>` | none | Key-value evidence JSON |
|
|
1740
|
+
| `--evidence-refs` | `<json>` | none | Peer evidence references JSON |
|
|
1741
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
1742
|
+
|
|
1743
|
+
- Positional arguments and options are interchangeable; `--payload` supplies any of the fields as one JSON object, and explicit flags override it. `--evidence` is an object of up to 64 string values; `--evidence-refs` maps each requirement to `{"messageIds":[...]}` (1 to 16 IDs).
|
|
1744
|
+
- Needs a hub. Mutates the run. Honors `--dry-run` (prints the parsed `args`).
|
|
1745
|
+
- Output is the hub's checkpoint result. Policy refusals: `tool_policy_denied`, `session_token_invalid`, `attempt_token_invalid`.
|
|
1746
|
+
|
|
1747
|
+
```bash
|
|
1748
|
+
kxm workflow checkpoint wf_123 implement passed "Tests pass" --evidence '{"implementation-diff":"commit abc123"}' --dry-run --json
|
|
1749
|
+
```
|
|
1750
|
+
|
|
1751
|
+
```text
|
|
1752
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"workflow checkpoint","dryRun":true,"args":{"evidence":{"implementation-diff":"commit abc123"},"runId":"wf_123","stageId":"implement","status":"passed","summary":"Tests pass"}}
|
|
1753
|
+
```
|
|
1754
|
+
|
|
1755
|
+
```bash
|
|
1756
|
+
kxm workflow checkpoint --run-id wf_123 --stage-id review --status passed --summary "Two reviews agree" --evidence-refs '{"independent peer reviews":{"messageIds":["msg_a","msg_b"]}}'
|
|
1757
|
+
```
|
|
1758
|
+
|
|
1759
|
+
Not run: writes to a hub workflow.
|
|
1760
|
+
|
|
1761
|
+
### `kxm workflow record`
|
|
1762
|
+
|
|
1763
|
+
```text
|
|
1764
|
+
kxm workflow record [runId] [category] [area] [summary] [--stage-id <id>] [--severity <level>] [--details <text>] [--evidence <items...>] [--related-entry-ids <ids...>]
|
|
1765
|
+
```
|
|
1766
|
+
|
|
1767
|
+
Record workflow journal knowledge in one of ten categories: plan, decision, contradiction, error, lesson, observation, hypothesis, experiment, state-change, or skill-candidate.
|
|
1768
|
+
|
|
1769
|
+
| Option | Argument | Default | Description |
|
|
1770
|
+
|---|---|---|---|
|
|
1771
|
+
| `--run-id` | `<id>` | none | Workflow run ID |
|
|
1772
|
+
| `--category` | `<category>` | none | plan, decision, contradiction, error, lesson, observation, hypothesis, experiment, state-change, skill-candidate |
|
|
1773
|
+
| `--area` | `<area>` | the stage's area with `--stage-id` | harness, gates, implementation, workflow, documentation, security, other (defaults to the stage area with --stage-id) |
|
|
1774
|
+
| `--stage-id` | `<id>` | none | Stage the entry is about; the hub derives attempt and default area |
|
|
1775
|
+
| `--severity` | `<level>` | `info` | info, warning, error |
|
|
1776
|
+
| `--summary` | `<text>` | none | Entry summary |
|
|
1777
|
+
| `--details` | `<text>` | none | Detailed text |
|
|
1778
|
+
| `--evidence` | `<items...>` | none | Evidence strings |
|
|
1779
|
+
| `--related-entry-ids` | `<ids...>` | none | Related entry IDs |
|
|
1780
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
1781
|
+
|
|
1782
|
+
- `--evidence` (up to 32) and `--related-entry-ids` (up to 16) take space-separated values. `lesson` and `skill-candidate` entries require evidence.
|
|
1783
|
+
- Area is optional. With three positionals and no `--summary`, the third positional is the summary: `record <runId> <category> <summary>`. The four-positional form `record <runId> <category> <area> <summary>` still works.
|
|
1784
|
+
- `--stage-id` binds the entry to that stage. The hub derives the attempt (the current attempt for an in-progress or waiting stage, the last attempt consumed for a finished stage); callers cannot set it. Without `--area`, the entry takes the stage's declared area. With neither an area nor a stage that declares one, the hub answers 400 `invalid_improvement_area`; a stage that is not part of the run answers `invalid_journal_relation`.
|
|
1785
|
+
- The journal covers hub webhook runs only. A `kxm run` ID answers `workflow_not_found`.
|
|
1786
|
+
- Needs a hub. Mutates the journal. Honors `--dry-run`.
|
|
1787
|
+
|
|
1788
|
+
```bash
|
|
1789
|
+
kxm workflow record wf_123 lesson gates "Flaky test hid a race" --severity warning --evidence https://ci.example.com/run/42 --dry-run --json
|
|
1790
|
+
```
|
|
1791
|
+
|
|
1792
|
+
```text
|
|
1793
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"workflow record","dryRun":true,"args":{"severity":"warning","evidence":["https://ci.example.com/run/42"],"runId":"wf_123","category":"lesson","area":"gates","summary":"Flaky test hid a race"}}
|
|
1794
|
+
```
|
|
1795
|
+
|
|
1796
|
+
Bound to a stage, with the area taken from the stage:
|
|
1797
|
+
|
|
1798
|
+
```bash
|
|
1799
|
+
kxm workflow record wf_123 lesson "Flaky test hid a race" --stage-id verify --evidence https://ci.example.com/run/42 --dry-run --json
|
|
1800
|
+
```
|
|
1801
|
+
|
|
1802
|
+
```text
|
|
1803
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"workflow record","dryRun":true,"args":{"stageId":"verify","evidence":["https://ci.example.com/run/42"],"runId":"wf_123","category":"lesson","summary":"Flaky test hid a race"}}
|
|
1804
|
+
```
|
|
1805
|
+
|
|
1806
|
+
### `kxm workflow wait`
|
|
1807
|
+
|
|
1808
|
+
```text
|
|
1809
|
+
kxm workflow wait [runId] [stageId] [signalKey] [summary] [--evidence <json>] [--evidence-refs <json>] [--timeout-ms <ms>]
|
|
1810
|
+
```
|
|
1811
|
+
|
|
1812
|
+
Wait for a workflow signal callback: pauses the active stage until a signed external callback checkpoints it. For a KXM run ID (`run_` followed by 32 hex digits) inside a project, the wait is registered with the Runtime instead of the hub (the supervisor starts if needed).
|
|
1813
|
+
|
|
1814
|
+
| Option | Argument | Default | Description |
|
|
1815
|
+
|---|---|---|---|
|
|
1816
|
+
| `--run-id` | `<id>` | none | Workflow run ID |
|
|
1817
|
+
| `--stage-id` | `<id>` | none | Active stage ID |
|
|
1818
|
+
| `--signal-key` | `<key>` | none | Wait signal key |
|
|
1819
|
+
| `--summary` | `<text>` | none | Expected result summary |
|
|
1820
|
+
| `--evidence` | `<json>` | none | Evidence JSON |
|
|
1821
|
+
| `--evidence-refs` | `<json>` | none | Peer evidence refs JSON |
|
|
1822
|
+
| `--timeout-ms` | `<ms>` | hub default (24 hours) | Wait timeout in milliseconds |
|
|
1823
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
1824
|
+
|
|
1825
|
+
- `--timeout-ms` accepts 1000 through 2592000000 (30 days).
|
|
1826
|
+
- Needs a hub (or the Runtime for KXM runs). Mutates the run. Honors `--dry-run`.
|
|
1827
|
+
|
|
1828
|
+
```bash
|
|
1829
|
+
kxm workflow wait wf_123 verify github-pr-42-checks "Waiting on CI" --timeout-ms 3600000 --dry-run --json
|
|
1830
|
+
```
|
|
1831
|
+
|
|
1832
|
+
```text
|
|
1833
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"workflow wait","dryRun":true,"args":{"timeoutMs":3600000,"runId":"wf_123","stageId":"verify","signalKey":"github-pr-42-checks","summary":"Waiting on CI"}}
|
|
1834
|
+
```
|
|
1835
|
+
|
|
1836
|
+
### `kxm workflow signal`
|
|
1837
|
+
|
|
1838
|
+
```text
|
|
1839
|
+
kxm workflow signal <runId> <signalKey> <status> <summary> [evidence...] [--delivery-id <id>]
|
|
1840
|
+
```
|
|
1841
|
+
|
|
1842
|
+
Post a signed workflow callback or unblock a KXM run. It is [`kxm gate signal`](#kxm-gate-signal) without `--recovery-action`; see that section for credentials, output, and errors.
|
|
1843
|
+
|
|
1844
|
+
| Option | Argument | Default | Description |
|
|
1845
|
+
|---|---|---|---|
|
|
1846
|
+
| `--delivery-id` | `<id>` | `cli-signal:<uuid>` | Stable callback delivery ID |
|
|
1847
|
+
|
|
1848
|
+
- Arguments: `<runId>` Workflow run ID; `<signalKey>` Wait signal key; `<status>` passed, warning, or failed; `<summary>` Callback summary; `[evidence...]` required-key=evidence pairs.
|
|
1849
|
+
|
|
1850
|
+
```bash
|
|
1851
|
+
KXM_WORKFLOW_ID=provenance-review KXM_WORKFLOW_SIGNAL_SECRET="$SIGNAL_SECRET" kxm workflow signal wf_123 ci-checks passed "CI green" --dry-run --json
|
|
1852
|
+
```
|
|
1853
|
+
|
|
1854
|
+
```text
|
|
1855
|
+
{"schema":"kxm.worker-result.v1","ok":true,"command":"signal","runId":"wf_123","signalKey":"ci-checks","status":"passed","evidence":{},...,"outcome":"passed","summary":"would post signed signal"}
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
### `kxm workflow start`
|
|
1859
|
+
|
|
1860
|
+
```text
|
|
1861
|
+
kxm workflow start [definitionId] [--payload <json|@file>] [--delivery-id <id>] [--event <name>]
|
|
1862
|
+
```
|
|
1863
|
+
|
|
1864
|
+
POST a signed workflow-start webhook to `<hub>/v1/webhooks/<definitionId>`. The body is HMAC-SHA256 signed (`x-hub-signature-256`) and carries a delivery ID (`x-kxm-delivery-id`) so the hub deduplicates retries.
|
|
1865
|
+
|
|
1866
|
+
| Option | Argument | Default | Description |
|
|
1867
|
+
|---|---|---|---|
|
|
1868
|
+
| `--payload` | `<json>` | `{}` | JSON object or @file |
|
|
1869
|
+
| `--delivery-id` | `<id>` | `cli-<uuid>` | Stable provider delivery ID |
|
|
1870
|
+
| `--event` | `<name>` | none | Optional provider event name |
|
|
1871
|
+
|
|
1872
|
+
- Arguments: `[definitionId]`, Workflow definition ID (default `KXM_WORKFLOW_ID`).
|
|
1873
|
+
- The secret comes from the definition's `secretEnv` when `KXM_WEBHOOK_WORKFLOWS` or `KXM_WEBHOOK_WORKFLOWS_FILE` is configured (never both), otherwise from `KXM_WORKFLOW_SECRET`. `--event` is sent as `x-github-event` and added to the payload as `event` when the payload has none.
|
|
1874
|
+
- Needs a hub. Creates a run. Honors `--dry-run`.
|
|
1875
|
+
- JSON keys: `definitionId`, `deliveryId`, `status`, `runId`, `duplicate` (dry run: `definitionId`, `deliveryId`, `event`).
|
|
1876
|
+
- Errors: missing definition ID or secret (plain text, exit 2), `invalid_payload` (exit 2, the payload must be a JSON object), `workflow_start_failed` (exit 1).
|
|
1877
|
+
|
|
1878
|
+
```bash
|
|
1879
|
+
KXM_WORKFLOW_SECRET="$SECRET" kxm workflow start provenance-review --payload '{"task":{"id":"T-1","summary":"Review auth change"}}' --dry-run
|
|
1880
|
+
```
|
|
1881
|
+
|
|
1882
|
+
```text
|
|
1883
|
+
would POST a signed workflow webhook
|
|
1884
|
+
```
|
|
1885
|
+
|
|
1886
|
+
```bash
|
|
1887
|
+
KXM_WEBHOOK_WORKFLOWS_FILE=workflows.json kxm workflow start provenance-review --payload @payload.json --delivery-id jira-T-1 --event issue_updated
|
|
1888
|
+
```
|
|
1889
|
+
|
|
1890
|
+
Not run: posts to a hub and starts a workflow.
|
|
1891
|
+
|
|
1892
|
+
### `kxm workflow export`
|
|
1893
|
+
|
|
1894
|
+
```text
|
|
1895
|
+
kxm workflow export <runId> [--input <file>] [--out-dir <dir>]
|
|
1896
|
+
```
|
|
1897
|
+
|
|
1898
|
+
Export a proposed retrospective: writes `<runId>.json` and `<runId>.md` built from the run and its journal. The source is the local hub store, or an offline snapshot (`{"run":...,"journal":[...]}`) with `--input`.
|
|
1899
|
+
|
|
1900
|
+
| Option | Argument | Default | Description |
|
|
1901
|
+
|---|---|---|---|
|
|
1902
|
+
| `--input` | `<file>` | local store | Offline snapshot JSON |
|
|
1903
|
+
| `--out-dir` | `<dir>` | `.kxm/assets/retrospectives` | Directory under workspace assets |
|
|
1904
|
+
|
|
1905
|
+
- Arguments: `<runId>`, Workflow run ID.
|
|
1906
|
+
- `--out-dir` must resolve inside the workspace assets directory (`output_outside_workspace_assets`, exit 2).
|
|
1907
|
+
- Writes two files. Honors `--dry-run`.
|
|
1908
|
+
- JSON keys: `jsonPath`, `mdPath`, `reviewDecision`. Errors (exit 1): `state_database_not_found`, `workflow_not_found`, `snapshot_missing`, `run_id_mismatch`.
|
|
1909
|
+
|
|
1910
|
+
```bash
|
|
1911
|
+
kxm workflow export wf_missing --dry-run --json
|
|
1912
|
+
```
|
|
1913
|
+
|
|
1914
|
+
```text
|
|
1915
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"retrospective export","error":"workflow_not_found"}
|
|
1916
|
+
```
|
|
1917
|
+
|
|
1918
|
+
### `kxm workflow definitions`
|
|
1919
|
+
|
|
1920
|
+
```text
|
|
1921
|
+
kxm workflow definitions [--scope all|global|local]
|
|
1922
|
+
```
|
|
1923
|
+
|
|
1924
|
+
List workflow definitions across scopes.
|
|
1925
|
+
|
|
1926
|
+
| Option | Argument | Default | Description |
|
|
1927
|
+
|---|---|---|---|
|
|
1928
|
+
| `--scope` | `<scope>` | `all` | Filter by scope: all, global, or local |
|
|
1929
|
+
|
|
1930
|
+
- Reads only. JSON keys: `workflows` (`id`, `description`, `scope`, `filePath`, `stepCount`, `roles`).
|
|
1931
|
+
|
|
1932
|
+
```bash
|
|
1933
|
+
kxm workflow definitions
|
|
1934
|
+
```
|
|
1935
|
+
|
|
1936
|
+
```text
|
|
1937
|
+
WORKFLOW DEFINITIONS:
|
|
1938
|
+
default [local] 3 steps (roles: coordinator, implementer) Plan, implement, and verify a local change.
|
|
1939
|
+
```
|
|
1940
|
+
|
|
1941
|
+
### `kxm workflow add`
|
|
1942
|
+
|
|
1943
|
+
```text
|
|
1944
|
+
kxm workflow add [workflowId] [--template <name> | --file <path> | --pick [selection]] [--description <text>] [--scope global|local] [--overwrite]
|
|
1945
|
+
```
|
|
1946
|
+
|
|
1947
|
+
Add a workflow definition to global or local configuration. With `--template <name>`, the named built-in template is written under the workflow ID. Without a workflow ID, or with `--pick`, you choose from the built-in templates and, for local scope, existing global definitions. With `--file`, the YAML file is copied as-is. Otherwise a one-step scaffold is written: one `implementer` agent step with write access to `control` that ends the run `completed` on `passed` and `failed` on `failed`.
|
|
1948
|
+
|
|
1949
|
+
| Option | Argument | Default | Description |
|
|
1950
|
+
|---|---|---|---|
|
|
1951
|
+
| `--file` | `<path>` | none | Path to YAML workflow definition file |
|
|
1952
|
+
| `--description` | `<text>` | `Workflow <id>`, or the template's | Workflow description |
|
|
1953
|
+
| `--scope` | `<scope>` | `local` | Configuration scope: global or local (default: local) |
|
|
1954
|
+
| `--overwrite` | none | off | Overwrite existing workflow definition if present |
|
|
1955
|
+
| `--pick` | `[selection]` | none | Pick from available workflow templates (index or id) |
|
|
1956
|
+
| `--template` | `<name>` | none | Start from a built-in template: `implement-and-verify`, `dual-critic-review`, or `spec-and-plan` |
|
|
1957
|
+
|
|
1958
|
+
- Templates: `implement-and-verify` runs the `implementer` agent, then the project's `test` gate, and a failing gate (`implementation-failure`) sends the work back to `implement` at most twice. `dual-critic-review` adds two review steps between them, both run as the `coordinator` agent with read access; point `review-arch` and `review-cli` at your own agents for independent critics. `spec-and-plan` plans and then reviews the plan, both as `coordinator`, reading the repository only.
|
|
1959
|
+
- The templates and the scaffold are valid `kxm.workflow.v1` definitions that use only what `kxm init` creates: the `coordinator` and `implementer` agents, the `control` repository, and the `test` gate. Each was checked with `kxm init --json` and `kxm run <id> --dry-run` for this page. A new file under `.kxm/workflows/` is a permission expansion that `kxm trust check` asks you to review before you commit it.
|
|
1960
|
+
- Writes `<scope dir>/workflows/<id>.yaml`. `kxm run` loads only `.kxm/workflows/`, so a `--scope global` definition is not runnable until it is copied into a project. `--dry-run` plans the write and writes nothing.
|
|
1961
|
+
- `--template` refusals exit 2 and honor `--json`: `workflow_template_unknown` (the text names the three templates), `workflow_id_required` (no workflow ID), and `workflow_add_conflict` (combined with `--file` or `--pick`). An existing definition without `--overwrite` exits 1 with a plain `workflow add failed: workflow_already_exists: ...` line, also under `--dry-run`.
|
|
1962
|
+
- JSON keys: `workflowId`, `id`, `filePath`, `scope`.
|
|
1963
|
+
|
|
1964
|
+
Start a first workflow from a template:
|
|
1965
|
+
|
|
1966
|
+
```bash
|
|
1967
|
+
kxm workflow add implement --template implement-and-verify
|
|
1968
|
+
```
|
|
1969
|
+
|
|
1970
|
+
```text
|
|
1971
|
+
Added workflow 'implement' to local (/work/proj/.kxm/workflows/implement.yaml)
|
|
1972
|
+
```
|
|
1973
|
+
|
|
1974
|
+
```bash
|
|
1975
|
+
kxm workflow add demo-flow --description "Demo" --dry-run --json
|
|
1976
|
+
```
|
|
1977
|
+
|
|
1978
|
+
```text
|
|
1979
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"workflow add","workflowId":"demo-flow","id":"demo-flow","filePath":"/work/proj/.kxm/workflows/demo-flow.yaml","scope":"local","dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/workflows/demo-flow.yaml"}]}
|
|
1980
|
+
```
|
|
1981
|
+
|
|
1982
|
+
```bash
|
|
1983
|
+
kxm workflow add implement --template nope
|
|
1984
|
+
```
|
|
1985
|
+
|
|
1986
|
+
```text
|
|
1987
|
+
workflow add failed: unknown template nope; choose implement-and-verify, dual-critic-review, spec-and-plan
|
|
1988
|
+
```
|
|
1989
|
+
|
|
1990
|
+
Add a definition you wrote yourself (Not run):
|
|
1991
|
+
|
|
1992
|
+
```bash
|
|
1993
|
+
kxm workflow add release-check --file ./release-check.yaml
|
|
1994
|
+
```
|
|
1995
|
+
|
|
1996
|
+
### `kxm workflow remove`
|
|
1997
|
+
|
|
1998
|
+
```text
|
|
1999
|
+
kxm workflow remove [workflowId] [--scope global|local] [--pick [selection]]
|
|
2000
|
+
```
|
|
2001
|
+
|
|
2002
|
+
Remove a workflow definition.
|
|
2003
|
+
|
|
2004
|
+
| Option | Argument | Default | Description |
|
|
2005
|
+
|---|---|---|---|
|
|
2006
|
+
| `--scope` | `<scope>` | `local` | Configuration scope: global or local (default: local) |
|
|
2007
|
+
| `--pick` | `[selection]` | none | Pick a workflow to remove (index or id) |
|
|
2008
|
+
|
|
2009
|
+
- Deletes a file. `--dry-run` plans the deletion, deletes nothing, and reports `removed: false`. JSON keys: `workflowId`, `id`, `removed`, `filePath`, `scope`.
|
|
2010
|
+
|
|
2011
|
+
```bash
|
|
2012
|
+
kxm workflow remove release-check --dry-run
|
|
2013
|
+
```
|
|
2014
|
+
|
|
2015
|
+
```text
|
|
2016
|
+
dry run: remove workflow 'release-check' from local
|
|
2017
|
+
would delete /work/proj/.kxm/workflows/release-check.yaml
|
|
2018
|
+
```
|
|
2019
|
+
|
|
2020
|
+
### `kxm workflow modify`
|
|
2021
|
+
|
|
2022
|
+
```text
|
|
2023
|
+
kxm workflow modify [workflowId] [--description <text>] [--scope global|local] [--pick [selection]]
|
|
2024
|
+
```
|
|
2025
|
+
|
|
2026
|
+
Modify a workflow definition's description and rewrite its file.
|
|
2027
|
+
|
|
2028
|
+
| Option | Argument | Default | Description |
|
|
2029
|
+
|---|---|---|---|
|
|
2030
|
+
| `--description` | `<text>` | unchanged | Updated description |
|
|
2031
|
+
| `--scope` | `<scope>` | first match | Configuration scope: global or local |
|
|
2032
|
+
| `--pick` | `[selection]` | none | Pick a workflow to modify (index or id) |
|
|
2033
|
+
|
|
2034
|
+
- Rewrites the file (re-serialized YAML). `--dry-run` returns the modified definition and plans the write without making it. JSON keys: `workflowId`, `id`, `workflow`, `filePath`, `scope`.
|
|
2035
|
+
|
|
2036
|
+
```bash
|
|
2037
|
+
kxm workflow modify default --description "Changed" --dry-run --json
|
|
2038
|
+
```
|
|
2039
|
+
|
|
2040
|
+
```text
|
|
2041
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"workflow modify","workflowId":"default","id":"default","workflow":{"schema":"kxm.workflow.v1","description":"Changed","coordinator":"coordinator",...},"filePath":"/work/proj/.kxm/workflows/default.yaml","scope":"local","dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/workflows/default.yaml"}]}
|
|
2042
|
+
```
|
|
2043
|
+
|
|
2044
|
+
## `kxm gate`
|
|
2045
|
+
|
|
2046
|
+
Validates workflow definitions and operates evidence gates. The group has exactly five gates; names declared in a workspace `gates.json` that do not map to one of them have no runner, and there is no generic subcommand that runs a gate by name. Results use the `kxm.worker-result.v1` envelope and, outside `--dry-run`, are appended to `.kxm/logs/telemetry.jsonl`.
|
|
2047
|
+
|
|
2048
|
+
### `kxm gate validate`
|
|
2049
|
+
|
|
2050
|
+
```text
|
|
2051
|
+
kxm gate validate [--file <path>]
|
|
2052
|
+
```
|
|
2053
|
+
|
|
2054
|
+
Parse workflow definitions without printing secrets, using the same single source the hub loads: `--file`, else `KXM_WEBHOOK_WORKFLOWS_FILE`, else inline `KXM_WEBHOOK_WORKFLOWS`.
|
|
2055
|
+
|
|
2056
|
+
| Option | Argument | Default | Description |
|
|
2057
|
+
|---|---|---|---|
|
|
2058
|
+
| `--file` | `<path>` | configured source | Workflow definition file |
|
|
2059
|
+
|
|
2060
|
+
- Each definition's `secretEnv` must name a set variable holding at least 16 characters (likewise `signalSecretEnv` when declared); otherwise parsing fails, for example with `workflow.secret must be a string`.
|
|
2061
|
+
- Reads definitions; appends telemetry. No hub needed.
|
|
2062
|
+
- JSON keys: `source`, `file`, `workflows` (`id`, `secretConfigured`, `signalSecretConfigured`), `warnings`; `outcome` is `warning` when warnings exist.
|
|
2063
|
+
- Exit 2 for `workflow_source_required` or `ambiguous_workflow_source` (both variables set); exit 1 for `file_not_found` or a parse error.
|
|
2064
|
+
|
|
2065
|
+
```bash
|
|
2066
|
+
KXM_WORKFLOW_SECRET="$SECRET" kxm gate validate --file workflows.json
|
|
2067
|
+
```
|
|
2068
|
+
|
|
2069
|
+
```text
|
|
2070
|
+
validated 1 workflow(s) from file with 1 warning(s)
|
|
2071
|
+
```
|
|
2072
|
+
|
|
2073
|
+
```bash
|
|
2074
|
+
KXM_WORKFLOW_SECRET="$SECRET" kxm gate validate --file workflows.json --json
|
|
2075
|
+
```
|
|
2076
|
+
|
|
2077
|
+
```text
|
|
2078
|
+
{"schema":"kxm.worker-result.v1","ok":true,"command":"validate","source":"file","file":"/work/proj/workflows.json","workflows":[{"id":"provenance-review","secretConfigured":true,"signalSecretConfigured":false}],"warnings":["workflow provenance-review stage review evidence policy independent peer reviews: degradation.minProducers is 1 (< 2); a single producer can satisfy the degraded peer-reply quorum"],...,"outcome":"warning",...}
|
|
2079
|
+
```
|
|
2080
|
+
|
|
2081
|
+
### `kxm gate artifacts-exist`
|
|
2082
|
+
|
|
2083
|
+
```text
|
|
2084
|
+
kxm gate artifacts-exist --path <file>
|
|
2085
|
+
```
|
|
2086
|
+
|
|
2087
|
+
Verify a non-empty file under workspace assets. The path resolves against the current directory and must be a regular, non-empty file inside the workspace assets directory both lexically and after resolving links.
|
|
2088
|
+
|
|
2089
|
+
| Option | Argument | Default | Description |
|
|
2090
|
+
|---|---|---|---|
|
|
2091
|
+
| `--path` | `<file>` | required | Artifact file under workspace assets |
|
|
2092
|
+
|
|
2093
|
+
- Reads the file; appends telemetry.
|
|
2094
|
+
- JSON keys: `path`, `bytes`. Exit 1 with `artifact_missing`, `artifact_empty`, `artifact_not_file`, `artifact_unreadable`, or `artifact_outside_workspace_assets`; a missing `--path` exits 2.
|
|
2095
|
+
|
|
2096
|
+
```bash
|
|
2097
|
+
kxm gate artifacts-exist --path .kxm/assets/reports/summary.md
|
|
2098
|
+
```
|
|
2099
|
+
|
|
2100
|
+
```text
|
|
2101
|
+
artifact exists and is non-empty under workspace assets
|
|
2102
|
+
```
|
|
2103
|
+
|
|
2104
|
+
```bash
|
|
2105
|
+
kxm gate artifacts-exist --path README.md --json
|
|
2106
|
+
```
|
|
2107
|
+
|
|
2108
|
+
```text
|
|
2109
|
+
{"schema":"kxm.worker-result.v1","ok":false,"command":"artifacts-exist","error":"artifact_outside_workspace_assets","path":"/work/proj/README.md",...,"outcome":"failed","summary":"artifact verification failed: artifact_outside_workspace_assets"}
|
|
2110
|
+
```
|
|
2111
|
+
|
|
2112
|
+
### `kxm gate degrade`
|
|
2113
|
+
|
|
2114
|
+
```text
|
|
2115
|
+
kxm gate degrade <runId> <stageId> --requirement <key> --reason <text>
|
|
2116
|
+
```
|
|
2117
|
+
|
|
2118
|
+
Approve a configured lower peer quorum for the current attempt of a stage, as allowed by that requirement's evidence policy. Uses the administrative token in `KXM_AUTH_TOKEN`; do not put secrets in the reason.
|
|
2119
|
+
|
|
2120
|
+
| Option | Argument | Default | Description |
|
|
2121
|
+
|---|---|---|---|
|
|
2122
|
+
| `--requirement` | `<key>` | none | Canonical requirement key |
|
|
2123
|
+
| `--reason` | `<text>` | none | Non-secret operator reason |
|
|
2124
|
+
|
|
2125
|
+
- Arguments: `<runId>` Workflow run ID; `<stageId>` Active stage ID.
|
|
2126
|
+
- Both options and `KXM_AUTH_TOKEN` are required (plain text, exit 2).
|
|
2127
|
+
- Needs a hub. Mutates the run. Honors `--dry-run`.
|
|
2128
|
+
- JSON keys: `runId`, `stageId`, `requirementKey`, `status`, `duplicate`, `approvalId`. Failure: `workflow_degradation_failed` (exit 1).
|
|
2129
|
+
|
|
2130
|
+
```bash
|
|
2131
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm gate degrade wf_123 review --requirement "independent peer reviews" --reason "one reviewer offline" --dry-run
|
|
2132
|
+
```
|
|
2133
|
+
|
|
2134
|
+
```text
|
|
2135
|
+
would approve configured degraded quorum for wf_123/review/independent peer reviews
|
|
2136
|
+
```
|
|
2137
|
+
|
|
2138
|
+
### `kxm gate signal`
|
|
2139
|
+
|
|
2140
|
+
```text
|
|
2141
|
+
kxm gate signal <runId> <signalKey> <status> <summary> [evidence...] [--delivery-id <id>] [--recovery-action <action>]
|
|
2142
|
+
```
|
|
2143
|
+
|
|
2144
|
+
Post a signed workflow callback that checkpoints a waiting stage.
|
|
2145
|
+
|
|
2146
|
+
| Option | Argument | Default | Description |
|
|
2147
|
+
|---|---|---|---|
|
|
2148
|
+
| `--delivery-id` | `<id>` | `cli-signal:<uuid>` | Stable callback delivery ID |
|
|
2149
|
+
| `--recovery-action` | `<action>` | none | KXM recovery action: retry, fail, cancel, unblock |
|
|
2150
|
+
|
|
2151
|
+
- Arguments: `<runId>` Workflow run ID; `<signalKey>` Wait signal key; `<status>` passed, warning, or failed; `<summary>` Callback summary; `[evidence...]` required-key=evidence pairs.
|
|
2152
|
+
- For a KXM run ID (`run_` followed by 32 hex digits) inside a project, the signal goes to the Runtime (the supervisor starts if needed) and `--recovery-action` is passed through. JSON keys: `runId`, `signalKey`, `status`, `unblocked`, `deliveryId`.
|
|
2153
|
+
- Otherwise it is a hub webhook callback: `KXM_WORKFLOW_ID` names the definition, and the secret is the definition's `signalSecretEnv` (falling back to `secretEnv`) when a definition source is configured, else `KXM_WORKFLOW_SIGNAL_SECRET`. JSON keys: `duplicate`, `deliveryId`.
|
|
2154
|
+
- Reuse `--delivery-id` to retry one unchanged callback without a duplicate.
|
|
2155
|
+
- Honors `--dry-run`. Exit 2 for a missing argument, an invalid status, malformed or duplicate evidence keys, or missing `KXM_WORKFLOW_ID` or secret; exit 1 for `signal_failed`.
|
|
2156
|
+
|
|
2157
|
+
```bash
|
|
2158
|
+
KXM_WORKFLOW_ID=provenance-review KXM_WORKFLOW_SIGNAL_SECRET="$SIGNAL_SECRET" kxm gate signal wf_123 ci-checks passed "CI green" "tests=https://ci.example.com/run/42" --dry-run --json
|
|
2159
|
+
```
|
|
2160
|
+
|
|
2161
|
+
```text
|
|
2162
|
+
{"schema":"kxm.worker-result.v1","ok":true,"command":"signal","runId":"wf_123","signalKey":"ci-checks","status":"passed","evidence":{"tests":"https://ci.example.com/run/42"},...,"outcome":"passed","summary":"would post signed signal"}
|
|
2163
|
+
```
|
|
2164
|
+
|
|
2165
|
+
```bash
|
|
2166
|
+
kxm gate signal run_0123456789abcdef0123456789abcdef verify passed "operator verified" --recovery-action unblock --dry-run
|
|
2167
|
+
```
|
|
2168
|
+
|
|
2169
|
+
```text
|
|
2170
|
+
would post signal to KXM run
|
|
2171
|
+
```
|
|
2172
|
+
|
|
2173
|
+
### `kxm gate github`
|
|
2174
|
+
|
|
2175
|
+
GitHub adapters. The only adapter is `watch`.
|
|
2176
|
+
|
|
2177
|
+
### `kxm gate github watch`
|
|
2178
|
+
|
|
2179
|
+
```text
|
|
2180
|
+
kxm gate github watch --run-id <id> --stage-id <id> --signal-key <key> --repo <owner/name> --pr <number> [--required <names>] [--timeout-ms <ms>] [--interval-ms <ms>] [--delivery-id <id>]
|
|
2181
|
+
```
|
|
2182
|
+
|
|
2183
|
+
Poll required checks and post the signed signal. The adapter polls the pull request's head commit check runs on `api.github.com` until every required check concludes or the timeout expires, then posts a signed `passed`, `warning`, or `failed` callback. On timeout it posts `failed` with summary `github_watch_timeout` and exits 4.
|
|
2184
|
+
|
|
2185
|
+
| Option | Argument | Default | Description |
|
|
2186
|
+
|---|---|---|---|
|
|
2187
|
+
| `--run-id` | `<id>` | required | Workflow run ID |
|
|
2188
|
+
| `--stage-id` | `<id>` | required | Waiting stage ID |
|
|
2189
|
+
| `--signal-key` | `<key>` | required | Wait signal key |
|
|
2190
|
+
| `--repo` | `<owner/name>` | required | GitHub repository |
|
|
2191
|
+
| `--pr` | `<number>` | required | Pull request number |
|
|
2192
|
+
| `--required` | `<names>` | none | Comma-separated required check names |
|
|
2193
|
+
| `--timeout-ms` | `<ms>` | `1800000` | Watch timeout |
|
|
2194
|
+
| `--interval-ms` | `<ms>` | `15000` | Poll interval |
|
|
2195
|
+
| `--delivery-id` | `<id>` | generated per wait | Stable callback delivery ID |
|
|
2196
|
+
|
|
2197
|
+
- Needs `KXM_WORKFLOW_ID`, a signal secret (as for `gate signal`), and `GITHUB_TOKEN` or `GH_TOKEN`. Without a GitHub token it exits 1 with summary `github_auth_unavailable` and `skipped: true`, without calling GitHub.
|
|
2198
|
+
- Calls GitHub and the hub. `--dry-run` still polls GitHub but does not post.
|
|
2199
|
+
- JSON keys: `posted`, `status`, `summary`, `evidence`, `deliveryId`, `skipped`. Failure summaries include `github_pr_unavailable`, `github_head_unavailable`, `github_checks_unavailable`, `workflow_not_waiting`, `signal_failed`. A payload that would contain a secret is refused with `redaction_failure`.
|
|
2200
|
+
|
|
2201
|
+
```bash
|
|
2202
|
+
KXM_WORKFLOW_ID=provenance-review KXM_WORKFLOW_SIGNAL_SECRET="$SIGNAL_SECRET" kxm gate github watch --run-id wf_123 --stage-id review --signal-key github-pr-42-checks --repo acme/web --pr 42 --required build,test --dry-run --json
|
|
2203
|
+
```
|
|
2204
|
+
|
|
2205
|
+
```text
|
|
2206
|
+
{"schema":"kxm.worker-result.v1","ok":false,"command":"github watch","posted":false,"evidence":{},"skipped":true,...,"outcome":"failed","summary":"github_auth_unavailable"}
|
|
2207
|
+
```
|
|
2208
|
+
|
|
2209
|
+
Captured without a GitHub token. With `GITHUB_TOKEN` set, the same command polls GitHub (Not run).
|
|
2210
|
+
|
|
2211
|
+
## `kxm peer`
|
|
2212
|
+
|
|
2213
|
+
Peer agent messaging through the hub. Each invocation connects to the hub as a short-lived agent named `KXM_AGENT_NAME` (default `cli-<pid>`) in project `KXM_PROJECT` (default: the `package.json` name, else the directory name), using `KXM_AUTH_TOKEN`, a project token, or the persisted `hub-env.json` credential. That agent appears in `peer list` and the dashboard. Every subcommand accepts `--payload <json>` with the tool's fields as one object; explicit flags override it. Tool policy from `KXM_ATTEMPT_TOKEN`, `KXM_SESSION_TOKEN`, or the on-disk session token is enforced first (`tool_policy_denied`, `session_token_invalid`, `attempt_token_invalid`).
|
|
2214
|
+
|
|
2215
|
+
All subcommands need a hub, honor `--dry-run` (printing the parsed `args` without connecting), print the hub's result object on success, and print `{"ok":false,"error":"command_failed","detail":"..."}` with exit 1 on failure. Malformed `--payload` exits 2 with `invalid_payload`.
|
|
2216
|
+
|
|
2217
|
+
### `kxm peer list`
|
|
2218
|
+
|
|
2219
|
+
```text
|
|
2220
|
+
kxm peer list [--include-offline]
|
|
2221
|
+
```
|
|
2222
|
+
|
|
2223
|
+
List peer agents in this project's hub pool with host and presence.
|
|
2224
|
+
|
|
2225
|
+
| Option | Argument | Default | Description |
|
|
2226
|
+
|---|---|---|---|
|
|
2227
|
+
| `--include-offline` | none | off | Also list registered peers whose hub lease has expired |
|
|
2228
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
2229
|
+
|
|
2230
|
+
- Reads the roster (the call itself registers the CLI agent). Output keys: `agents` (`id`, `name`, `purpose`, `project`, `connectedAt`, `lastSeenAt`, `online`, `host`, `leaseExpiresAt`, `presence`).
|
|
2231
|
+
|
|
2232
|
+
```bash
|
|
2233
|
+
kxm peer list --json
|
|
2234
|
+
```
|
|
2235
|
+
|
|
2236
|
+
```text
|
|
2237
|
+
{"schema":"kxm.cli-result.v1","agents":[{"id":"agt_0c91aef519734fc1bd36518d2fc1cf4e","name":"cli-85922","purpose":"CLI agent client","project":"proj","connectedAt":"2026-09-23T13:53:24.142Z","lastSeenAt":"2026-09-23T13:53:24.156Z","online":true,"host":"host.local","leaseExpiresAt":"2026-09-23T13:53:54.156Z","presence":"online"}]}
|
|
2238
|
+
```
|
|
2239
|
+
|
|
2240
|
+
### `kxm peer send`
|
|
2241
|
+
|
|
2242
|
+
```text
|
|
2243
|
+
kxm peer send [target] [content] [--delivery <mode>] [--correlation-id <id>] [--idempotency-key <key>] [--workflow-context <json>] [--ttl-ms <ms>] [--allow-offline]
|
|
2244
|
+
```
|
|
2245
|
+
|
|
2246
|
+
Send a focused request to a peer agent. Returns a message ID for `peer get` and `peer await`.
|
|
2247
|
+
|
|
2248
|
+
| Option | Argument | Default | Description |
|
|
2249
|
+
|---|---|---|---|
|
|
2250
|
+
| `--target` | `<name>` | none | Peer name or agent ID |
|
|
2251
|
+
| `--content` | `<text>` | none | Focused request content |
|
|
2252
|
+
| `--delivery` | `<mode>` | `followUp` | steer, followUp, or nextTurn |
|
|
2253
|
+
| `--correlation-id` | `<id>` | none | Task grouping ID |
|
|
2254
|
+
| `--idempotency-key` | `<key>` | none | Deduplication key |
|
|
2255
|
+
| `--workflow-context` | `<json>` | none | Workflow context JSON |
|
|
2256
|
+
| `--ttl-ms` | `<ms>` | hub default (24 hours) | Message TTL in milliseconds |
|
|
2257
|
+
| `--allow-offline` | none | off | Queue the request if the target is registered but offline |
|
|
2258
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
2259
|
+
|
|
2260
|
+
- `--workflow-context` is `{"runId","stageId","requirementKey","attempt"}` and is the only way a reply can count as peer evidence. `--ttl-ms` accepts 1000 through 604800000.
|
|
2261
|
+
- Mutates (queues a message). Output keys: `messageId`, `status`, `target`.
|
|
2262
|
+
|
|
2263
|
+
```bash
|
|
2264
|
+
kxm peer send reviewer "Review the diff in PR 42 and list blocking issues" --dry-run --json
|
|
2265
|
+
```
|
|
2266
|
+
|
|
2267
|
+
```text
|
|
2268
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"peer send","dryRun":true,"args":{"target":"reviewer","content":"Review the diff in PR 42 and list blocking issues"}}
|
|
2269
|
+
```
|
|
2270
|
+
|
|
2271
|
+
```bash
|
|
2272
|
+
kxm peer send reviewer "Independent review of the auth change" --workflow-context '{"runId":"wf_123","stageId":"review","requirementKey":"independent peer reviews","attempt":1}' --idempotency-key wf_123:review:1
|
|
2273
|
+
```
|
|
2274
|
+
|
|
2275
|
+
Not run: sends a message through a hub.
|
|
2276
|
+
|
|
2277
|
+
### `kxm peer get`
|
|
2278
|
+
|
|
2279
|
+
```text
|
|
2280
|
+
kxm peer get [messageId]
|
|
2281
|
+
```
|
|
2282
|
+
|
|
2283
|
+
Check a peer request status and reply.
|
|
2284
|
+
|
|
2285
|
+
| Option | Argument | Default | Description |
|
|
2286
|
+
|---|---|---|---|
|
|
2287
|
+
| `--message-id` | `<id>` | none | Message ID |
|
|
2288
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
2289
|
+
|
|
2290
|
+
- Reads only. Output is the stored message.
|
|
2291
|
+
|
|
2292
|
+
```bash
|
|
2293
|
+
kxm peer get msg_missing --json
|
|
2294
|
+
```
|
|
2295
|
+
|
|
2296
|
+
```text
|
|
2297
|
+
{"schema":"kxm.cli-result.v1","ok":false,"error":"command_failed","detail":"message not found"}
|
|
2298
|
+
```
|
|
2299
|
+
|
|
2300
|
+
### `kxm peer await`
|
|
2301
|
+
|
|
2302
|
+
```text
|
|
2303
|
+
kxm peer await [messageId] [--timeout-ms <ms>]
|
|
2304
|
+
```
|
|
2305
|
+
|
|
2306
|
+
Wait for a peer request reply (capped at 60 seconds). Longer waits belong in a workflow wait step.
|
|
2307
|
+
|
|
2308
|
+
| Option | Argument | Default | Description |
|
|
2309
|
+
|---|---|---|---|
|
|
2310
|
+
| `--message-id` | `<id>` | none | Message ID |
|
|
2311
|
+
| `--timeout-ms` | `<ms>` | `60000` | Timeout in milliseconds (max 60000) |
|
|
2312
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
2313
|
+
|
|
2314
|
+
- Reads only. Output is the reply or a terminal error.
|
|
2315
|
+
|
|
2316
|
+
```bash
|
|
2317
|
+
kxm peer await msg_abc --timeout-ms 30000 --dry-run --json
|
|
2318
|
+
```
|
|
2319
|
+
|
|
2320
|
+
```text
|
|
2321
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"peer await","dryRun":true,"args":{"timeoutMs":30000,"messageId":"msg_abc"}}
|
|
2322
|
+
```
|
|
2323
|
+
|
|
2324
|
+
### `kxm peer cancel`
|
|
2325
|
+
|
|
2326
|
+
```text
|
|
2327
|
+
kxm peer cancel [messageId]
|
|
2328
|
+
```
|
|
2329
|
+
|
|
2330
|
+
Cancel a sent peer request. Only the agent that sent the request can cancel it, so run with the sender's `KXM_AGENT_NAME`.
|
|
2331
|
+
|
|
2332
|
+
| Option | Argument | Default | Description |
|
|
2333
|
+
|---|---|---|---|
|
|
2334
|
+
| `--message-id` | `<id>` | none | Message ID |
|
|
2335
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
2336
|
+
|
|
2337
|
+
- Mutates the message.
|
|
2338
|
+
|
|
2339
|
+
```bash
|
|
2340
|
+
kxm peer cancel msg_abc --dry-run --json
|
|
2341
|
+
```
|
|
2342
|
+
|
|
2343
|
+
```text
|
|
2344
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"peer cancel","dryRun":true,"args":{"messageId":"msg_abc"}}
|
|
2345
|
+
```
|
|
2346
|
+
|
|
2347
|
+
### `kxm peer fanout`
|
|
2348
|
+
|
|
2349
|
+
```text
|
|
2350
|
+
kxm peer fanout --targets <name>... --content <text> [--correlation-id <id>] [--idempotency-key-prefix <prefix>] [--workflow-context <json>] [--ttl-ms <ms>] [--timeout-ms <ms>]
|
|
2351
|
+
```
|
|
2352
|
+
|
|
2353
|
+
Send the same request to one through three peers and return their replies for comparison. A local timeout returns pending entries with durable message IDs; repeat the exact command (same correlation ID and prefix) to retry without duplicates.
|
|
2354
|
+
|
|
2355
|
+
| Option | Argument | Default | Description |
|
|
2356
|
+
|---|---|---|---|
|
|
2357
|
+
| `--targets` | `<items...>` | none | Target peer names (1-3) |
|
|
2358
|
+
| `--content` | `<text>` | none | Request content |
|
|
2359
|
+
| `--correlation-id` | `<id>` | none | Task grouping ID |
|
|
2360
|
+
| `--idempotency-key-prefix` | `<prefix>` | none | Idempotency prefix |
|
|
2361
|
+
| `--workflow-context` | `<json>` | none | Workflow context JSON |
|
|
2362
|
+
| `--ttl-ms` | `<ms>` | hub default (24 hours) | Message TTL in milliseconds |
|
|
2363
|
+
| `--timeout-ms` | `<ms>` | `1800000` (30 minutes) | Timeout in milliseconds |
|
|
2364
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
2365
|
+
|
|
2366
|
+
- `--targets` takes space-separated names (a comma-joined value is sent as one name). `--timeout-ms` accepts 100 through 1800000.
|
|
2367
|
+
- Mutates (queues messages). Output keys: `responses`.
|
|
2368
|
+
|
|
2369
|
+
```bash
|
|
2370
|
+
kxm peer fanout --targets reviewer critic --content "Independent review of PR 42" --correlation-id wf_123 --idempotency-key-prefix pr42 --dry-run --json
|
|
2371
|
+
```
|
|
2372
|
+
|
|
2373
|
+
```text
|
|
2374
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"peer fanout","dryRun":true,"args":{"targets":["reviewer","critic"],"content":"Independent review of PR 42","correlationId":"wf_123","idempotencyKeyPrefix":"pr42"}}
|
|
2375
|
+
```
|
|
2376
|
+
|
|
2377
|
+
### `kxm peer inbox`
|
|
2378
|
+
|
|
2379
|
+
```text
|
|
2380
|
+
kxm peer inbox
|
|
2381
|
+
```
|
|
2382
|
+
|
|
2383
|
+
List inbound peer requests. From the CLI this always returns `{"messages":[]}`: the inbox lives in a long-running harness session, which a one-shot CLI call does not have. Use `kxm dash --screen inbox` to see pending requests.
|
|
2384
|
+
|
|
2385
|
+
| Option | Argument | Default | Description |
|
|
2386
|
+
|---|---|---|---|
|
|
2387
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
2388
|
+
|
|
2389
|
+
```bash
|
|
2390
|
+
kxm peer inbox --json
|
|
2391
|
+
```
|
|
2392
|
+
|
|
2393
|
+
```text
|
|
2394
|
+
{"schema":"kxm.cli-result.v1","messages":[]}
|
|
2395
|
+
```
|
|
2396
|
+
|
|
2397
|
+
### `kxm peer reply`
|
|
2398
|
+
|
|
2399
|
+
```text
|
|
2400
|
+
kxm peer reply [messageId] [content]
|
|
2401
|
+
```
|
|
2402
|
+
|
|
2403
|
+
Reply to an inbound request. Only the request's recipient may reply (`message_forbidden` otherwise), so run with the recipient's `KXM_AGENT_NAME`.
|
|
2404
|
+
|
|
2405
|
+
| Option | Argument | Default | Description |
|
|
2406
|
+
|---|---|---|---|
|
|
2407
|
+
| `--message-id` | `<id>` | none | Message ID |
|
|
2408
|
+
| `--content` | `<text>` | none | Reply content |
|
|
2409
|
+
| `--payload` | `<json>` | none | JSON payload |
|
|
2410
|
+
|
|
2411
|
+
- Mutates the message. Output keys: `messageId`, `status`, `recipient`.
|
|
2412
|
+
|
|
2413
|
+
```bash
|
|
2414
|
+
kxm peer reply msg_abc "LGTM with one nit" --dry-run --json
|
|
2415
|
+
```
|
|
2416
|
+
|
|
2417
|
+
```text
|
|
2418
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"peer reply","dryRun":true,"args":{"messageId":"msg_abc","content":"LGTM with one nit"}}
|
|
2419
|
+
```
|
|
2420
|
+
|
|
2421
|
+
## `kxm task`
|
|
2422
|
+
|
|
2423
|
+
Project tasks stored as `kxm.task.v1` YAML in `.kxm/tasks/` in the current directory. `kxm task` with no subcommand runs `task list`. None needs a hub. Errors are plain text on stderr, even with `--json`.
|
|
2424
|
+
|
|
2425
|
+
### `kxm task create`
|
|
2426
|
+
|
|
2427
|
+
```text
|
|
2428
|
+
kxm task create <title> [--goal <goalId>] [--objective <text>] [--workflow <id>] [--tracker github|jira] [--issue <key>]
|
|
2429
|
+
```
|
|
2430
|
+
|
|
2431
|
+
Create a task with status `todo`.
|
|
2432
|
+
|
|
2433
|
+
| Option | Argument | Default | Description |
|
|
2434
|
+
|---|---|---|---|
|
|
2435
|
+
| `--goal` | `<goalId>` | none | Parent goal ID |
|
|
2436
|
+
| `--objective` | `<text>` | the title | Task objective |
|
|
2437
|
+
| `--workflow` | `<id>` | none | Assigned workflow ID |
|
|
2438
|
+
| `--tracker` | `<tracker>` | none | Issue tracker (github or jira) |
|
|
2439
|
+
| `--issue` | `<key>` | none | Issue number or Jira key |
|
|
2440
|
+
|
|
2441
|
+
- A tracker link is recorded only when both `--tracker` and `--issue` are given.
|
|
2442
|
+
- Writes `.kxm/tasks/<id>.yaml`. `--dry-run` shows the task it would create and plans the write; the ID is assigned when the task is created, so a dry run's ID is not the one a real run gets. JSON keys: `task`.
|
|
2443
|
+
|
|
2444
|
+
```bash
|
|
2445
|
+
kxm task create "Fix flaky test" --objective "Stabilize CI" --workflow default --dry-run --json
|
|
2446
|
+
```
|
|
2447
|
+
|
|
2448
|
+
```text
|
|
2449
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"task create","task":{"schema":"kxm.task.v1","id":"task_0e77833bc462","title":"Fix flaky test","objective":"Stabilize CI","acceptanceCriteria":[],"status":"todo","assignedWorkflow":"default",...},"dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/tasks/task_0e77833bc462.yaml"}]}
|
|
2450
|
+
```
|
|
2451
|
+
|
|
2452
|
+
### `kxm task list`
|
|
2453
|
+
|
|
2454
|
+
```text
|
|
2455
|
+
kxm task list [--goal <goalId>] [--status <status>]
|
|
2456
|
+
```
|
|
2457
|
+
|
|
2458
|
+
List project tasks.
|
|
2459
|
+
|
|
2460
|
+
| Option | Argument | Default | Description |
|
|
2461
|
+
|---|---|---|---|
|
|
2462
|
+
| `--goal` | `<goalId>` | none | Filter by goal ID |
|
|
2463
|
+
| `--status` | `<status>` | none | Filter by status: todo, in_progress, blocked, in_review, done |
|
|
2464
|
+
|
|
2465
|
+
- Reads only. JSON keys: `count`, `tasks`.
|
|
2466
|
+
|
|
2467
|
+
```bash
|
|
2468
|
+
kxm task list
|
|
2469
|
+
```
|
|
2470
|
+
|
|
2471
|
+
```text
|
|
2472
|
+
[todo] task_4f79c0833e41: Fix flaky test -> default
|
|
2473
|
+
```
|
|
2474
|
+
|
|
2475
|
+
### `kxm task get`
|
|
2476
|
+
|
|
2477
|
+
```text
|
|
2478
|
+
kxm task get <taskId>
|
|
2479
|
+
```
|
|
2480
|
+
|
|
2481
|
+
Get task details and linked workflow status.
|
|
2482
|
+
|
|
2483
|
+
- Reads only. JSON keys: `task`. A missing task prints `Task <id> not found` and exits 1.
|
|
2484
|
+
|
|
2485
|
+
```bash
|
|
2486
|
+
kxm task get task_4f79c0833e41
|
|
2487
|
+
```
|
|
2488
|
+
|
|
2489
|
+
```text
|
|
2490
|
+
Task: task_4f79c0833e41
|
|
2491
|
+
Title: Fix flaky test
|
|
2492
|
+
Status: todo
|
|
2493
|
+
Objective: Stabilize CI
|
|
2494
|
+
Workflow: default
|
|
2495
|
+
```
|
|
2496
|
+
|
|
2497
|
+
### `kxm task run`
|
|
2498
|
+
|
|
2499
|
+
```text
|
|
2500
|
+
kxm task run <taskId>
|
|
2501
|
+
```
|
|
2502
|
+
|
|
2503
|
+
Launch a workflow run driven by this task: runs `kxm run <workflow> <objective>` with the task's assigned workflow (default `default`), then sets the task status to `in_progress` when that succeeds.
|
|
2504
|
+
|
|
2505
|
+
- Output, requirements, and errors are those of [`kxm run`](#kxm-run), including the `--workspace` refusal.
|
|
2506
|
+
- Mutates the task file. `--dry-run` validates the project and the workflow as `kxm run --dry-run` does, then plans the run request and the task file write without making either; the status stays unchanged. Dry-run JSON keys: `taskId`, `projectRoot`, `workflowId`, `configRevision`, `status` (the status it would set), `dryRun`, `planned`.
|
|
2507
|
+
|
|
2508
|
+
```bash
|
|
2509
|
+
kxm task run task_4f79c0833e41 --dry-run
|
|
2510
|
+
```
|
|
2511
|
+
|
|
2512
|
+
```text
|
|
2513
|
+
dry run: run workflow default for task task_4f79c0833e41, then mark it in_progress
|
|
2514
|
+
would request POST kxm-runtime /v1/runs (starts the Runtime supervisor if it is not running)
|
|
2515
|
+
would write /work/proj/.kxm/tasks/task_4f79c0833e41.yaml
|
|
2516
|
+
```
|
|
2517
|
+
|
|
2518
|
+
### `kxm task sync`
|
|
2519
|
+
|
|
2520
|
+
```text
|
|
2521
|
+
kxm task sync <taskId>
|
|
2522
|
+
```
|
|
2523
|
+
|
|
2524
|
+
Sync task status and evidence with its linked issue board. In 0.7.1 this is local only: it marks the task's tracker link `synced` and updates timestamps without contacting GitHub or Jira.
|
|
2525
|
+
|
|
2526
|
+
- Writes the task file. `--dry-run` returns the synced task and plans the write without making it. JSON keys: `task`.
|
|
2527
|
+
- Exit 1 when the task does not exist or has no tracker link.
|
|
2528
|
+
|
|
2529
|
+
```bash
|
|
2530
|
+
kxm task sync task_4f79c0833e41 --json
|
|
2531
|
+
```
|
|
2532
|
+
|
|
2533
|
+
```text
|
|
2534
|
+
task sync failed: Task task_4f79c0833e41 does not have an associated issue board tracker
|
|
2535
|
+
```
|
|
2536
|
+
|
|
2537
|
+
## `kxm goal`
|
|
2538
|
+
|
|
2539
|
+
Project goals stored as `kxm.goal.v1` YAML in `.kxm/goals/` in the current directory. `kxm goal` with no subcommand runs `goal list`. No hub needed.
|
|
2540
|
+
|
|
2541
|
+
### `kxm goal create`
|
|
2542
|
+
|
|
2543
|
+
```text
|
|
2544
|
+
kxm goal create <title> [--area <area>] [--metric <metric...>] [--target-date <date>]
|
|
2545
|
+
```
|
|
2546
|
+
|
|
2547
|
+
Create a project goal with status `active`.
|
|
2548
|
+
|
|
2549
|
+
| Option | Argument | Default | Description |
|
|
2550
|
+
|---|---|---|---|
|
|
2551
|
+
| `--area` | `<area>` | none | Workflow area (e.g. software-engineering, security-reliability) |
|
|
2552
|
+
| `--metric` | `<metric...>` | none | Success metrics for this goal |
|
|
2553
|
+
| `--target-date` | `<date>` | none | Target achievement date (ISO-8601 or YYYY-MM-DD) |
|
|
2554
|
+
|
|
2555
|
+
- Writes `.kxm/goals/<id>.yaml`. `--dry-run` shows the goal it would create and plans the write; the ID is assigned when the goal is created. JSON keys: `goal`.
|
|
2556
|
+
|
|
2557
|
+
```bash
|
|
2558
|
+
kxm goal create "Ship v1" --area software-engineering --dry-run --json
|
|
2559
|
+
```
|
|
2560
|
+
|
|
2561
|
+
```text
|
|
2562
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"goal create","goal":{"schema":"kxm.goal.v1","id":"goal_47c05405528d","title":"Ship v1","area":"software-engineering","status":"active","successMetrics":[],"createdAt":"2026-09-23T17:51:23.667Z","updatedAt":"2026-09-23T17:51:23.667Z"},"dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/goals/goal_47c05405528d.yaml"}]}
|
|
2563
|
+
```
|
|
2564
|
+
|
|
2565
|
+
With metrics and a target date (Not run):
|
|
2566
|
+
|
|
2567
|
+
```bash
|
|
2568
|
+
kxm goal create "Ship v1" --area software-engineering --metric "p95 < 300ms" "zero sev1" --target-date 2026-12-01
|
|
2569
|
+
```
|
|
2570
|
+
|
|
2571
|
+
### `kxm goal list`
|
|
2572
|
+
|
|
2573
|
+
```text
|
|
2574
|
+
kxm goal list
|
|
2575
|
+
```
|
|
2576
|
+
|
|
2577
|
+
List project goals.
|
|
2578
|
+
|
|
2579
|
+
No command-specific options.
|
|
2580
|
+
|
|
2581
|
+
- Reads only. JSON keys: `count`, `goals`.
|
|
2582
|
+
|
|
2583
|
+
```bash
|
|
2584
|
+
kxm goal list
|
|
2585
|
+
```
|
|
2586
|
+
|
|
2587
|
+
```text
|
|
2588
|
+
[active] goal_cebbbf714ed4: Ship v1 (software-engineering)
|
|
2589
|
+
```
|
|
2590
|
+
|
|
2591
|
+
## `kxm suggest`
|
|
2592
|
+
|
|
2593
|
+
```text
|
|
2594
|
+
kxm suggest <prompt...>
|
|
2595
|
+
```
|
|
2596
|
+
|
|
2597
|
+
Recommends a workflow, area, roles, and skills for a prompt or issue description using keyword matching and the detected harnesses. The suggested workflow ID comes from a built-in catalog and may not exist in your project; check with `kxm workflow definitions` before running the suggested command.
|
|
2598
|
+
|
|
2599
|
+
- Arguments: `<prompt...>`, the task description.
|
|
2600
|
+
- No command-specific options. Probes harnesses as `harness list` does; reads nothing else. No hub needed.
|
|
2601
|
+
- Suggested skills are always KXM command skills shipped in `plugins/kxm/skills` (for example `kxm-workflow`, `kxm-runs`, `kxm-peer`, `kxm-context-memory`), never the KontextMind knowledge-plane skills.
|
|
2602
|
+
- JSON keys: `prompt`, `workflowId`, `area`, `confidence`, `reasons`, `suggestedSkills`, `roles` (`planner`, `writer`, `critics`, `verifier`), `suggestedCommand`.
|
|
2603
|
+
|
|
2604
|
+
```bash
|
|
2605
|
+
kxm suggest "Add retry with backoff to the payment webhook handler"
|
|
2606
|
+
```
|
|
2607
|
+
|
|
2608
|
+
```text
|
|
2609
|
+
Suggested Workflow: software-engineering/feature-implementation (software-engineering)
|
|
2610
|
+
Confidence: 65%
|
|
2611
|
+
Reasons: Matched keywords: add
|
|
2612
|
+
Suggested Skills: kxm-workflow, kxm-peer, kxm-context-memory
|
|
2613
|
+
Roles:
|
|
2614
|
+
Planner: claude (fable)
|
|
2615
|
+
Writer: grok (grok-4.6)
|
|
2616
|
+
Critics: claude:fable, codex:gpt-5.6-sol
|
|
2617
|
+
Verifier: npm run verify
|
|
2618
|
+
|
|
2619
|
+
Execute with:
|
|
2620
|
+
kxm run software-engineering/feature-implementation "Add retry with backoff to the payment webhook handler"
|
|
2621
|
+
```
|
|
2622
|
+
|
|
2623
|
+
## `kxm explain`
|
|
2624
|
+
|
|
2625
|
+
```text
|
|
2626
|
+
kxm explain [--mode <name>] [--domains <list>] [--model <id>]
|
|
2627
|
+
```
|
|
2628
|
+
|
|
2629
|
+
Pre-flight context footprint and token cost inspection for workflow modes. The estimate uses a fixed base prompt size, the length of each configured context file (1500 characters when a file is missing), domain prompt snippets, and 650 characters per active tool, at about 3.8 characters per token. Modes come from `.kxm/modes.yaml` or the built-in defaults; costs come from the project price catalog and stay unknown when it is missing or unverified.
|
|
2630
|
+
|
|
2631
|
+
| Option | Argument | Default | Description |
|
|
2632
|
+
|---|---|---|---|
|
|
2633
|
+
| `--mode` | `<name>` | `coder` | Major mode (coder, planner, auditor, browser) |
|
|
2634
|
+
| `--domains` | `<list>` | none | Comma-separated domain modules (git, k8s, database, browser) |
|
|
2635
|
+
| `--model` | `<id>` | mode default | Target model identifier (e.g. grok/grok-4.6, claude/fable) |
|
|
2636
|
+
|
|
2637
|
+
- Reads only. No hub needed.
|
|
2638
|
+
- JSON keys: `majorMode`, `enabledDomains`, `model`, `breakdown` (`name`, `chars`, `estimatedTokens`), `totalChars`, `totalTokens`, `contextWindowRatio`, `projectedCost`, `catalogStatus`, `catalogReason`.
|
|
2639
|
+
|
|
2640
|
+
```bash
|
|
2641
|
+
kxm explain
|
|
2642
|
+
```
|
|
2643
|
+
|
|
2644
|
+
```text
|
|
2645
|
+
════════════════════════════════════════════════════════════
|
|
2646
|
+
KXM PRE-FLIGHT CONTEXT EXPLAIN
|
|
2647
|
+
════════════════════════════════════════════════════════════
|
|
2648
|
+
Major Mode: coder
|
|
2649
|
+
Enabled Domains: (none)
|
|
2650
|
+
Target Model: grok/grok-4.6
|
|
2651
|
+
Catalog status: price catalog missing
|
|
2652
|
+
|
|
2653
|
+
CONTEXT BREAKDOWN:
|
|
2654
|
+
• Base System Prompt (coder) 843 tokens
|
|
2655
|
+
• Context File: AGENTS.md 395 tokens
|
|
2656
|
+
• Tool Schemas (4 active tools) 685 tokens
|
|
2657
|
+
────────────────────────────────────────────────────────────
|
|
2658
|
+
TOTAL PROMPT FOOTPRINT: 1,923 tokens (1% of 200k window)
|
|
2659
|
+
...
|
|
2660
|
+
```
|
|
2661
|
+
|
|
2662
|
+
```bash
|
|
2663
|
+
kxm explain --mode planner --domains git,k8s --model grok/grok-4.6 --json
|
|
2664
|
+
```
|
|
2665
|
+
|
|
2666
|
+
```text
|
|
2667
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"explain","majorMode":"planner","enabledDomains":["git","k8s"],"model":"grok/grok-4.6","breakdown":[...],"totalChars":10022,"totalTokens":2640,"contextWindowRatio":1.3,"projectedCost":{"inputCostUsd":null,"cacheReadCostUsd":null,"outputCostEstimateUsd":null},"catalogStatus":"missing","catalogReason":"price catalog missing"}
|
|
2668
|
+
```
|
|
2669
|
+
|
|
2670
|
+
## `kxm context`
|
|
2671
|
+
|
|
2672
|
+
KXM context operating-system queries. Every subcommand POSTs to the hub's `/v1/context/*` API as the control plane, authenticating only with `KXM_AUTH_TOKEN` (the persisted `hub-env.json` credential is not used; without the variable the hub answers 401 `invalid_auth`). The first argument is the project scope. Results carry the hub's HTTP `status` and response fields. Exit 0 on a 2xx response, 1 otherwise. An unreachable hub crashes the command with a stack trace (exit 1, no JSON). Agents reach the same data through the `kxm_context`, `kxm_recall`, `kxm_state`, `kxm_episode`, and `kxm_promote` tools; there is no `kxm_explain` tool.
|
|
2673
|
+
|
|
2674
|
+
### `kxm context get`
|
|
2675
|
+
|
|
2676
|
+
```text
|
|
2677
|
+
kxm context get <project> --role <role> --task <task> [--run <runId>] [--stage <stageId>] [--budget <tokens>] [--kinds <kinds>]
|
|
2678
|
+
```
|
|
2679
|
+
|
|
2680
|
+
Assemble a role-aware context packet within a token budget.
|
|
2681
|
+
|
|
2682
|
+
| Option | Argument | Default | Description |
|
|
2683
|
+
|---|---|---|---|
|
|
2684
|
+
| `--role` | `<role>` | required | Requesting role (repro, planner, critic, implementer, verifier, or custom) |
|
|
2685
|
+
| `--task` | `<task>` | required | What the role is trying to do |
|
|
2686
|
+
| `--run` | `<runId>` | none | Workflow run scope |
|
|
2687
|
+
| `--stage` | `<stageId>` | none | Workflow stage scope |
|
|
2688
|
+
| `--budget` | `<tokens>` | hub default | Token budget for the packet |
|
|
2689
|
+
| `--kinds` | `<kinds>` | all | Comma-separated item kinds to include |
|
|
2690
|
+
|
|
2691
|
+
- `--budget` must be an integer from 512 to 200000 (exit 2).
|
|
2692
|
+
- Reads only. Output keys: `status`, `packet` (`workingState`, `currentState`, `knowledge`, `evidence`, `episodes`, `skills`, `contradictions`, `unresolvedGaps`, `provenanceSummary`, `estimatedTokens`), `audit`.
|
|
2693
|
+
- Selection is deterministic. Eligible items are ordered by open contradiction, project before `_shared`, task-matched before unmatched, role kind priority, lexical BM25 relevance to `--task`, confidence, authority, recency (newest first), then id. The budget is filled first-fit: an item that does not fit is skipped and smaller ones still fill it.
|
|
2694
|
+
- `audit.relevance` holds numbers only: `taskTokens` (distinct task words after stopword removal), `matchedCandidates` (eligible items sharing a task word) and `selected` (each selected item's rounded score, in `selectedIds` order).
|
|
2695
|
+
|
|
2696
|
+
```bash
|
|
2697
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context get proj --role planner --task "Plan the auth refactor" --budget 4000 --json
|
|
2698
|
+
```
|
|
2699
|
+
|
|
2700
|
+
```text
|
|
2701
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"context get","status":200,"packet":{"workingState":{},"currentState":[],"knowledge":[],"evidence":[],"episodes":[],"skills":[],"contradictions":[],"unresolvedGaps":["no context records exist for this project yet"],"provenanceSummary":{},"estimatedTokens":0},"audit":{"request":{"project":"proj","role":"planner","task":"Plan the auth refactor"},"selectedIds":[],"provenanceSummary":{},"estimatedTokens":0,"budgetTokens":4000,"candidateCount":0,"excludedSuperseded":0,"unresolvedGaps":["no context records exist for this project yet"],"relevance":{"taskTokens":3,"matchedCandidates":0,"selected":[]}}}
|
|
2702
|
+
```
|
|
2703
|
+
|
|
2704
|
+
```bash
|
|
2705
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context get proj --role planner --task "Plan the auth refactor"
|
|
2706
|
+
```
|
|
2707
|
+
|
|
2708
|
+
```text
|
|
2709
|
+
context get assembled
|
|
2710
|
+
```
|
|
2711
|
+
|
|
2712
|
+
Without `KXM_AUTH_TOKEN`:
|
|
2713
|
+
|
|
2714
|
+
```bash
|
|
2715
|
+
kxm context get proj --role planner --task "Plan the auth refactor" --json
|
|
2716
|
+
```
|
|
2717
|
+
|
|
2718
|
+
```text
|
|
2719
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"context get","status":401,"error":"invalid administrative authentication token","code":"invalid_auth",...,"nextAction":"check_project_token"}
|
|
2720
|
+
```
|
|
2721
|
+
|
|
2722
|
+
### `kxm context recall`
|
|
2723
|
+
|
|
2724
|
+
```text
|
|
2725
|
+
kxm context recall <project> [--query <text>] [--kinds <kinds>] [--limit <n>]
|
|
2726
|
+
```
|
|
2727
|
+
|
|
2728
|
+
Search durable context records (metadata only).
|
|
2729
|
+
|
|
2730
|
+
| Option | Argument | Default | Description |
|
|
2731
|
+
|---|---|---|---|
|
|
2732
|
+
| `--query` | `<text>` | none | Query against summaries and state keys |
|
|
2733
|
+
| `--kinds` | `<kinds>` | all | Comma-separated item kinds to include |
|
|
2734
|
+
| `--limit` | `<n>` | hub default | Maximum results (1-100) |
|
|
2735
|
+
|
|
2736
|
+
- Ranking: items whose summary or state key contains the whole query (ignoring case) come first, then items that share a word with it, by BM25 relevance, then id. Items with neither are left out; an empty query returns every item in id order.
|
|
2737
|
+
- Reads only. Output keys: `status`, `items` (metadata plus a numeric `relevance`; never summaries), `unresolvedGaps`.
|
|
2738
|
+
|
|
2739
|
+
```bash
|
|
2740
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context recall proj --query auth --limit 5 --json
|
|
2741
|
+
```
|
|
2742
|
+
|
|
2743
|
+
```text
|
|
2744
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"context recall","status":200,"items":[],"unresolvedGaps":["no matching context records"]}
|
|
2745
|
+
```
|
|
2746
|
+
|
|
2747
|
+
### `kxm context state`
|
|
2748
|
+
|
|
2749
|
+
```text
|
|
2750
|
+
kxm context state <project> <key> [--as-of <iso>]
|
|
2751
|
+
```
|
|
2752
|
+
|
|
2753
|
+
Current or historical value for one state key.
|
|
2754
|
+
|
|
2755
|
+
| Option | Argument | Default | Description |
|
|
2756
|
+
|---|---|---|---|
|
|
2757
|
+
| `--as-of` | `<iso>` | now | Historical timestamp query |
|
|
2758
|
+
|
|
2759
|
+
- Reads only. Output keys: `status`, `state` (`null` when unset), `key`.
|
|
2760
|
+
|
|
2761
|
+
```bash
|
|
2762
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context state proj release.freeze --json
|
|
2763
|
+
```
|
|
2764
|
+
|
|
2765
|
+
```text
|
|
2766
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"context state","status":200,"state":null,"key":"release.freeze"}
|
|
2767
|
+
```
|
|
2768
|
+
|
|
2769
|
+
### `kxm context episode`
|
|
2770
|
+
|
|
2771
|
+
```text
|
|
2772
|
+
kxm context episode <project> [--run <runId>]
|
|
2773
|
+
```
|
|
2774
|
+
|
|
2775
|
+
Episodic learning records from workflow journals.
|
|
2776
|
+
|
|
2777
|
+
| Option | Argument | Default | Description |
|
|
2778
|
+
|---|---|---|---|
|
|
2779
|
+
| `--run` | `<runId>` | all runs | Limit to one workflow run |
|
|
2780
|
+
|
|
2781
|
+
- Reads only. Output keys: `status`, `episodes`.
|
|
2782
|
+
|
|
2783
|
+
```bash
|
|
2784
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context episode proj --json
|
|
2785
|
+
```
|
|
2786
|
+
|
|
2787
|
+
```text
|
|
2788
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"context episode","status":200,"episodes":[]}
|
|
2789
|
+
```
|
|
2790
|
+
|
|
2791
|
+
### `kxm context promote`
|
|
2792
|
+
|
|
2793
|
+
```text
|
|
2794
|
+
kxm context promote <project> <proposalId> --evidence <refs>
|
|
2795
|
+
```
|
|
2796
|
+
|
|
2797
|
+
Promote an approved state proposal (control plane).
|
|
2798
|
+
|
|
2799
|
+
| Option | Argument | Default | Description |
|
|
2800
|
+
|---|---|---|---|
|
|
2801
|
+
| `--evidence` | `<refs>` | required | Comma-separated durable evidence references |
|
|
2802
|
+
|
|
2803
|
+
- `--evidence` must contain at least one reference (exit 2).
|
|
2804
|
+
- Mutates hub state. `--dry-run` sends nothing and plans the request (`POST <hub>/v1/context/state/promote`).
|
|
2805
|
+
- Errors from the hub include `state_proposal_not_found` (404).
|
|
2806
|
+
|
|
2807
|
+
```bash
|
|
2808
|
+
kxm context promote proj prop_1 --evidence wf_1:journal:1 --dry-run
|
|
2809
|
+
```
|
|
2810
|
+
|
|
2811
|
+
```text
|
|
2812
|
+
dry run: promote proposal prop_1 in proj
|
|
2813
|
+
would request POST http://127.0.0.1:7331/v1/context/state/promote
|
|
2814
|
+
```
|
|
2815
|
+
|
|
2816
|
+
```bash
|
|
2817
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context promote proj prop_missing --evidence wf_1:journal:1 --json
|
|
2818
|
+
```
|
|
2819
|
+
|
|
2820
|
+
```text
|
|
2821
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"context promote","status":404,"error":"state proposal prop_missing not found","code":"state_proposal_not_found",...}
|
|
2822
|
+
```
|
|
2823
|
+
|
|
2824
|
+
### `kxm context explain`
|
|
2825
|
+
|
|
2826
|
+
```text
|
|
2827
|
+
kxm context explain <project> <itemId>
|
|
2828
|
+
```
|
|
2829
|
+
|
|
2830
|
+
Explain which evidence and lineage back a context item.
|
|
2831
|
+
|
|
2832
|
+
- Arguments: `<project>` Project scope; `<itemId>` Context item ID. No command-specific options. Reads only.
|
|
2833
|
+
- Output keys: `status`, `found`, `lineage`, `evidenceRefs`, `sources`.
|
|
2834
|
+
|
|
2835
|
+
```bash
|
|
2836
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context explain proj ctx_missing --json
|
|
2837
|
+
```
|
|
2838
|
+
|
|
2839
|
+
```text
|
|
2840
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"context explain","status":200,"found":false,"lineage":[],"evidenceRefs":[],"sources":[]}
|
|
2841
|
+
```
|
|
2842
|
+
|
|
2843
|
+
### `kxm context wiki-compile`
|
|
2844
|
+
|
|
2845
|
+
```text
|
|
2846
|
+
kxm context wiki-compile <project> [--out <dir>]
|
|
2847
|
+
```
|
|
2848
|
+
|
|
2849
|
+
Compile the Karpathy-style knowledge wiki for review. Without `--out` the pages are listed but not written.
|
|
2850
|
+
|
|
2851
|
+
| Option | Argument | Default | Description |
|
|
2852
|
+
|---|---|---|---|
|
|
2853
|
+
| `--out` | `<dir>` | dry-run output only | Workspace root to write .kxm/knowledge/wiki into (default: dry-run output only) |
|
|
2854
|
+
|
|
2855
|
+
- With `--out`, writes the pages under `<dir>/.kxm/knowledge/wiki/`. With `--out` and `--dry-run`, the hub still compiles (a read) and the pages are listed as `planned` writes; nothing is written.
|
|
2856
|
+
- Output keys: `project`, `pages`, `openContradictions`, and `written` and `outDir` or `dryRun: true` (plus `outDir` and `planned` for `--out --dry-run`).
|
|
2857
|
+
|
|
2858
|
+
```bash
|
|
2859
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context wiki-compile proj --json
|
|
2860
|
+
```
|
|
2861
|
+
|
|
2862
|
+
```text
|
|
2863
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"context wiki-compile","project":"proj","pages":[".kxm/knowledge/wiki/architecture/proj-state.md",".kxm/knowledge/wiki/contradictions/proj.md",".kxm/knowledge/wiki/index.md"],"openContradictions":0,"dryRun":true}
|
|
2864
|
+
```
|
|
2865
|
+
|
|
2866
|
+
### `kxm context wiki-lint`
|
|
2867
|
+
|
|
2868
|
+
```text
|
|
2869
|
+
kxm context wiki-lint <project>
|
|
2870
|
+
```
|
|
2871
|
+
|
|
2872
|
+
Lint a compiled wiki for broken refs, orphans, and stale state. Compiles on the hub and reports the lint findings without writing files.
|
|
2873
|
+
|
|
2874
|
+
- Reads only. Output keys: `project`, `issues` (`severity`, `rule`, `path`, `message`), `audit`.
|
|
2875
|
+
- Exit 1 when any issue has severity `error`.
|
|
2876
|
+
|
|
2877
|
+
```bash
|
|
2878
|
+
KXM_AUTH_TOKEN="$ADMIN_TOKEN" kxm context wiki-lint proj
|
|
2879
|
+
```
|
|
2880
|
+
|
|
2881
|
+
Captured as JSON:
|
|
2882
|
+
|
|
2883
|
+
```text
|
|
2884
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"context wiki-lint","project":"proj","issues":[],"audit":{"project":"proj","pages":[...],"stateItems":0,"contextItems":0,"contradictions":0,"compiledAt":"2026-09-23T13:53:26.436Z"}}
|
|
2885
|
+
```
|
|
2886
|
+
|
|
2887
|
+
## `kxm memory`
|
|
2888
|
+
|
|
2889
|
+
Harness-agnostic Git memory. Active facts are Markdown files with `kxm.memory.v1` front matter in `.kxm/memory/`; candidates live in `.kxm/memory/candidates/` and become facts when a reviewed PR moves them. All paths are relative to the current directory. No hub needed.
|
|
2890
|
+
|
|
2891
|
+
### `kxm memory brief`
|
|
2892
|
+
|
|
2893
|
+
```text
|
|
2894
|
+
kxm memory brief
|
|
2895
|
+
```
|
|
2896
|
+
|
|
2897
|
+
Show active project memory facts for harness context.
|
|
2898
|
+
|
|
2899
|
+
No command-specific options.
|
|
2900
|
+
|
|
2901
|
+
- Reads only. JSON keys: `brief` (`schema`, `generatedAt`, `count`, `facts`).
|
|
2902
|
+
|
|
2903
|
+
```bash
|
|
2904
|
+
kxm memory brief
|
|
2905
|
+
```
|
|
2906
|
+
|
|
2907
|
+
```text
|
|
2908
|
+
No active project memory facts.
|
|
2909
|
+
```
|
|
2910
|
+
|
|
2911
|
+
```bash
|
|
2912
|
+
kxm memory brief --json
|
|
2913
|
+
```
|
|
2914
|
+
|
|
2915
|
+
```text
|
|
2916
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"memory brief","brief":{"schema":"kxm.memory-brief.v1","generatedAt":"2026-09-23T13:52:20.033Z","count":0,"facts":[]}}
|
|
2917
|
+
```
|
|
2918
|
+
|
|
2919
|
+
### `kxm memory note`
|
|
2920
|
+
|
|
2921
|
+
```text
|
|
2922
|
+
kxm memory note <fact> [--scope <scope>] [--kind <kind>] [--body <text>]
|
|
2923
|
+
```
|
|
2924
|
+
|
|
2925
|
+
Record an evidence-based memory candidate (promoted via PR).
|
|
2926
|
+
|
|
2927
|
+
| Option | Argument | Default | Description |
|
|
2928
|
+
|---|---|---|---|
|
|
2929
|
+
| `--scope` | `<scope>` | `project` | Scope: agent, project, run, or operator (default: project) |
|
|
2930
|
+
| `--kind` | `<kind>` | `learning` | Kind: decision, architecture, convention, policy, learning (default: learning) |
|
|
2931
|
+
| `--body` | `<text>` | none | Detailed markdown context for the fact |
|
|
2932
|
+
|
|
2933
|
+
- Arguments: `<fact>`, Summary of the observed fact or learning.
|
|
2934
|
+
- Writes `.kxm/memory/candidates/<id>.md`. `--dry-run` shows the candidate and plans the write; the ID is assigned when the candidate is recorded.
|
|
2935
|
+
- JSON keys: `candidate`, `path`.
|
|
2936
|
+
|
|
2937
|
+
```bash
|
|
2938
|
+
kxm memory note "Use pnpm, not npm" --kind convention --dry-run --json
|
|
2939
|
+
```
|
|
2940
|
+
|
|
2941
|
+
```text
|
|
2942
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"memory note","candidate":{"schema":"kxm.memory.v1","id":"cand_project_bf337cc76dda","scope":"project","kind":"convention","summary":"Use pnpm, not npm",...,"lifecycle":"active","evidenceRefs":[]},"path":".kxm/memory/candidates/cand_project_bf337cc76dda.md","dryRun":true,"planned":[{"action":"write","target":"/work/proj/.kxm/memory/candidates/cand_project_bf337cc76dda.md"}]}
|
|
2943
|
+
```
|
|
2944
|
+
|
|
2945
|
+
### `kxm memory sync`
|
|
2946
|
+
|
|
2947
|
+
```text
|
|
2948
|
+
kxm memory sync
|
|
2949
|
+
```
|
|
2950
|
+
|
|
2951
|
+
Regenerate memory projection blocks across AGENTS.md, CLAUDE.md, and GEMINI.md: rewrites the section between `<!-- kxm:memory:start -->` and `<!-- kxm:memory:end -->` in each file from the active facts.
|
|
2952
|
+
|
|
2953
|
+
No command-specific options.
|
|
2954
|
+
|
|
2955
|
+
- Writes up to three files in the current directory. `--dry-run` reports which files it would update or create and plans the writes without making them.
|
|
2956
|
+
- Warning: a missing `CLAUDE.md` or `GEMINI.md` is created with a header copied from the KXM repository's own agent instructions (planner role, Grok as default writer, links to `plans/implementation-plan.md`). Review or replace the header before committing in another project.
|
|
2957
|
+
- JSON keys: `updated`, `created`.
|
|
2958
|
+
|
|
2959
|
+
In a project without these files:
|
|
2960
|
+
|
|
2961
|
+
```bash
|
|
2962
|
+
kxm memory sync --dry-run --json
|
|
2963
|
+
```
|
|
2964
|
+
|
|
2965
|
+
```text
|
|
2966
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"memory sync","updated":[],"created":["AGENTS.md","CLAUDE.md","GEMINI.md"],"dryRun":true,"planned":[{"action":"write","target":"/work/proj/AGENTS.md"},{"action":"write","target":"/work/proj/CLAUDE.md"},{"action":"write","target":"/work/proj/GEMINI.md"}]}
|
|
2967
|
+
```
|
|
2968
|
+
|
|
2969
|
+
## `kxm skills`
|
|
2970
|
+
|
|
2971
|
+
Governed skill candidate lifecycle under `.kxm/skills/` in `KXM_WORKDIR` or the current directory: `candidates/`, `promoted/`, `quarantined/`, `rejected/`, `history/<id>.jsonl`, and `patches/<id>.patch`. No hub needed. Errors are plain text on stderr.
|
|
2972
|
+
|
|
2973
|
+
### `kxm skills create`
|
|
2974
|
+
|
|
2975
|
+
```text
|
|
2976
|
+
kxm skills create --file <path> --name <name> --created-by <id> --harness <name> --models <models> [--description <text>] [--run <ids>] [--journal <ids>] [--receipt <refs>] [--supersedes <id>]
|
|
2977
|
+
```
|
|
2978
|
+
|
|
2979
|
+
Submit a skill candidate from verified episodes.
|
|
2980
|
+
|
|
2981
|
+
| Option | Argument | Default | Description |
|
|
2982
|
+
|---|---|---|---|
|
|
2983
|
+
| `--file` | `<path>` | required | SKILL.md content file |
|
|
2984
|
+
| `--name` | `<name>` | required | Skill name |
|
|
2985
|
+
| `--description` | `<text>` | empty | Short description |
|
|
2986
|
+
| `--created-by` | `<id>` | required | Author identity |
|
|
2987
|
+
| `--run` | `<ids>` | none | Comma-separated source run IDs |
|
|
2988
|
+
| `--journal` | `<ids>` | none | Comma-separated source journal entry IDs |
|
|
2989
|
+
| `--receipt` | `<refs>` | none | Comma-separated evidence receipts |
|
|
2990
|
+
| `--harness` | `<name>` | required | Harness compatibility (pi, claude-code, ...) |
|
|
2991
|
+
| `--models` | `<models>` | required | Comma-separated compatible models |
|
|
2992
|
+
| `--supersedes` | `<id>` | none | Prior skill this candidate supersedes |
|
|
2993
|
+
|
|
2994
|
+
- Writes a candidate. Honors `--dry-run`. JSON keys: `metadata` (or `name` for a dry run).
|
|
2995
|
+
|
|
2996
|
+
```bash
|
|
2997
|
+
kxm skills create --file SKILL.md --name retry-backoff --created-by alice --harness pi --models xai/grok-4.6 --run wf_123 --dry-run --json
|
|
2998
|
+
```
|
|
2999
|
+
|
|
3000
|
+
```text
|
|
3001
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"skills create","dryRun":true,"name":"retry-backoff"}
|
|
3002
|
+
```
|
|
3003
|
+
|
|
3004
|
+
### `kxm skills evaluate`
|
|
3005
|
+
|
|
3006
|
+
```text
|
|
3007
|
+
kxm skills evaluate <skillId> --kind <kind> --evaluator <version> [--fail] [--score <n>] [--details <text>]
|
|
3008
|
+
```
|
|
3009
|
+
|
|
3010
|
+
Record a protected evaluation for a candidate. A failed evaluation can quarantine the candidate.
|
|
3011
|
+
|
|
3012
|
+
| Option | Argument | Default | Description |
|
|
3013
|
+
|---|---|---|---|
|
|
3014
|
+
| `--kind` | `<kind>` | required | static-review, sandbox, functional, safety, or optimization |
|
|
3015
|
+
| `--evaluator` | `<version>` | required | Evaluator version |
|
|
3016
|
+
| `--fail` | none | off | Record a failed evaluation |
|
|
3017
|
+
| `--score` | `<n>` | none | Numeric score |
|
|
3018
|
+
| `--details` | `<text>` | none | Bounded evaluation details |
|
|
3019
|
+
|
|
3020
|
+
- Arguments: `<skillId>`, Skill candidate ID. Mutates. `--dry-run` returns the evaluation and whether it would quarantine the candidate, and plans the history write (and the move to `quarantined/`) without making them.
|
|
3021
|
+
- JSON keys: `skillId`, `quarantined`, `evaluation`.
|
|
3022
|
+
|
|
3023
|
+
```bash
|
|
3024
|
+
kxm skills evaluate skill_x --kind static-review --evaluator v1 --json
|
|
3025
|
+
```
|
|
3026
|
+
|
|
3027
|
+
```text
|
|
3028
|
+
skills evaluate failed: skill skill_x not found in candidate
|
|
3029
|
+
```
|
|
3030
|
+
|
|
3031
|
+
### `kxm skills promote`
|
|
3032
|
+
|
|
3033
|
+
```text
|
|
3034
|
+
kxm skills promote <skillId> --decided-by <id> --evidence <refs> [--reason <text>]
|
|
3035
|
+
```
|
|
3036
|
+
|
|
3037
|
+
Promote a candidate that passed all protected evaluations (`static-review`, `sandbox`, `functional`, `safety`). The promoter must differ from the author. Writes the promoted skill and a patch that adds `.kxm/skills/promoted/<id>/SKILL.md` for review.
|
|
3038
|
+
|
|
3039
|
+
| Option | Argument | Default | Description |
|
|
3040
|
+
|---|---|---|---|
|
|
3041
|
+
| `--decided-by` | `<id>` | required | Promoter identity (must differ from the author) |
|
|
3042
|
+
| `--evidence` | `<refs>` | required | Comma-separated durable evidence references |
|
|
3043
|
+
| `--reason` | `<text>` | `passed protected evaluation` | Decision reason |
|
|
3044
|
+
|
|
3045
|
+
- Mutates. `--dry-run` checks the evaluations and the promoter as a real promotion does, returns the metadata with the patch it would write, and plans the promoted files, the patch, and the history entry without writing them. JSON keys: `skillId`, `metadata`, `patchPath`.
|
|
3046
|
+
|
|
3047
|
+
```bash
|
|
3048
|
+
kxm skills promote seed-skill.af5155e66be7 --decided-by promoter --evidence receipt:seed --dry-run
|
|
3049
|
+
```
|
|
3050
|
+
|
|
3051
|
+
```text
|
|
3052
|
+
dry run: promote skill seed-skill.af5155e66be7
|
|
3053
|
+
would write /work/proj/.kxm/skills/promoted/seed-skill.af5155e66be7/SKILL.md
|
|
3054
|
+
would write /work/proj/.kxm/skills/promoted/seed-skill.af5155e66be7/metadata.json
|
|
3055
|
+
would write /work/proj/.kxm/skills/patches/seed-skill.af5155e66be7.patch
|
|
3056
|
+
would write /work/proj/.kxm/skills/history/seed-skill.af5155e66be7.jsonl
|
|
3057
|
+
```
|
|
3058
|
+
|
|
3059
|
+
```bash
|
|
3060
|
+
kxm skills promote skill_x --decided-by bob --evidence wf_123:journal:4
|
|
3061
|
+
```
|
|
3062
|
+
|
|
3063
|
+
Not run: needs a candidate that passed every required evaluation.
|
|
3064
|
+
|
|
3065
|
+
### `kxm skills reject`
|
|
3066
|
+
|
|
3067
|
+
```text
|
|
3068
|
+
kxm skills reject <skillId> --decided-by <id> [--reason <text>]
|
|
3069
|
+
```
|
|
3070
|
+
|
|
3071
|
+
Reject a candidate; history is retained for learning.
|
|
3072
|
+
|
|
3073
|
+
| Option | Argument | Default | Description |
|
|
3074
|
+
|---|---|---|---|
|
|
3075
|
+
| `--decided-by` | `<id>` | required | Decider identity |
|
|
3076
|
+
| `--reason` | `<text>` | `rejected` | Decision reason |
|
|
3077
|
+
|
|
3078
|
+
- Mutates. `--dry-run` plans the move to `rejected/` and the history entry without making them. JSON keys: `skillId`, `metadata`.
|
|
3079
|
+
|
|
3080
|
+
```bash
|
|
3081
|
+
kxm skills reject skill_x --decided-by bob --reason "duplicates an existing skill"
|
|
3082
|
+
```
|
|
3083
|
+
|
|
3084
|
+
Not run: needs an existing candidate.
|
|
3085
|
+
|
|
3086
|
+
### `kxm skills list`
|
|
3087
|
+
|
|
3088
|
+
```text
|
|
3089
|
+
kxm skills list [--state <state>]
|
|
3090
|
+
```
|
|
3091
|
+
|
|
3092
|
+
List skills by state.
|
|
3093
|
+
|
|
3094
|
+
| Option | Argument | Default | Description |
|
|
3095
|
+
|---|---|---|---|
|
|
3096
|
+
| `--state` | `<state>` | `promoted` | candidate, promoted, quarantined, or rejected |
|
|
3097
|
+
|
|
3098
|
+
- Reads only. JSON keys: `state`, `skills` (`id`, `name`, `version`, `createdBy`, `createdAt`, `models`). An invalid state exits 1.
|
|
3099
|
+
|
|
3100
|
+
```bash
|
|
3101
|
+
kxm skills list --state candidate
|
|
3102
|
+
```
|
|
3103
|
+
|
|
3104
|
+
```text
|
|
3105
|
+
0 candidate skill(s)
|
|
3106
|
+
```
|
|
3107
|
+
|
|
3108
|
+
### `kxm skills verify`
|
|
3109
|
+
|
|
3110
|
+
```text
|
|
3111
|
+
kxm skills verify <skillId> [--state <state>]
|
|
3112
|
+
```
|
|
3113
|
+
|
|
3114
|
+
Verify a stored skill against its pinned content hash.
|
|
3115
|
+
|
|
3116
|
+
| Option | Argument | Default | Description |
|
|
3117
|
+
|---|---|---|---|
|
|
3118
|
+
| `--state` | `<state>` | `promoted` | candidate, promoted, quarantined, or rejected |
|
|
3119
|
+
|
|
3120
|
+
- Reads only. JSON keys: `skillId`, `state`, `contentSha256`. A missing skill or a hash mismatch exits 1.
|
|
3121
|
+
|
|
3122
|
+
```bash
|
|
3123
|
+
kxm skills verify skill_x --json
|
|
3124
|
+
```
|
|
3125
|
+
|
|
3126
|
+
```text
|
|
3127
|
+
skills verify failed: skill skill_x not found in promoted
|
|
3128
|
+
```
|
|
3129
|
+
|
|
3130
|
+
## `kxm improve`
|
|
3131
|
+
|
|
3132
|
+
Proposes coded-repeat candidates from this project's Runtime routing records and telemetry. `kxm improve` with no subcommand runs `improve report`.
|
|
3133
|
+
|
|
3134
|
+
### `kxm improve report`
|
|
3135
|
+
|
|
3136
|
+
```text
|
|
3137
|
+
kxm improve report [--file <path>] [--out-dir <path>]
|
|
3138
|
+
```
|
|
3139
|
+
|
|
3140
|
+
Generate the improvement report and candidates from routing records. Inside a KXM project (the current directory's Git root holds `.kxm/project.yaml`) it reads the project's Runtime event store, then `telemetry.jsonl` in the workspace logs directory; `--file` reads only the named file. Routing records (`kxm.routing-record.v1` and `v2`, bare or nested under `routing`, `envelope.routing`, or a `routing.attempt.recorded` event) are grouped by workflow, step, agent role, and ask. Groups that qualify become proposed candidates, each written as a `.diff` and a `.json` file. Nothing is applied.
|
|
3141
|
+
|
|
3142
|
+
| Option | Argument | Default | Description |
|
|
3143
|
+
|---|---|---|---|
|
|
3144
|
+
| `--file` | `<path>` | the Runtime store, then `.kxm/logs/telemetry.jsonl` | Read only this routing-record JSONL instead of the project's Runtime store and telemetry |
|
|
3145
|
+
| `--out-dir` | `<path>` | `<project>/.kxm/candidates` | Directory for candidates (default .kxm/candidates) |
|
|
3146
|
+
|
|
3147
|
+
- The Runtime store is `<state root>/runtime/projects/<key>/run-events.db`, with the key derived from the checkout's real path, so each checkout and worktree reads only its own. It is opened read-only for one query over its events table and is never created, written, or migrated. Outside a KXM project only telemetry is read, and the text output says `Runtime store not read`.
|
|
3148
|
+
- A telemetry record whose `attemptId` the store already supplied is dropped (`duplicatesDropped`). Attempts from simulated drives are excluded (`excludedSimulated`). Each Runtime attempt's outcome is resolved from the event log and never written back: `accepted` when the run completed and the step was not re-entered, `reworked` when the step was entered again, `failed` when the run failed, undecided (`undecided`) when the run was cancelled or is still running.
|
|
3149
|
+
- A group becomes a candidate only when the same objective was decided in at least 2 runs, at least 0.75 of its decided records were accepted, and its step writes no repository. A group that passes but misses shows `no (writes-repository)` or `no (ask-not-repeated)`. `Weighted` is the recency-weighted record count (`improvement.telemetryHalfLifeDays`); it orders rows and never decides candidacy.
|
|
3150
|
+
- Reads `improvement.*` from the project and user configuration (see [`kxm.config.v1`](config-reference.md#personalization-settings-kxmconfigv1)) and reports each candidate's promotion readiness under `improvement.promotionPolicy`. Readiness never authorizes anything. Under `critic_quorum` every candidate reports not ready, because this command cites no critic receipts. A configuration that cannot be loaded exits 1 with `config_invalid`.
|
|
3151
|
+
- A Runtime store that exists but cannot be read exits 1 with `improve_source_unreadable`; `detail` names the path.
|
|
3152
|
+
- Writes candidate files under `--out-dir` (relative to the current directory) and the report at `.kxm/assets/improvements/<timestamp>.json`. Honors `--dry-run` (writes neither). No hub needed.
|
|
3153
|
+
- JSON keys: `path`, `events`, `recordsCount`, `groupsCount`, `candidatesCount`, `candidates`, `report` (`schema`, `createdAt`, `reviewDecision`, `recordsCount`, `groups`, `candidates`, `promotionPolicy`, `promotion`), `sources`, `projectRoot` (`null` outside a project).
|
|
3154
|
+
- Each `sources` entry has `kind` (`engine`, `telemetry`, or `file`), `path`, `exists`, `records`, and `duplicatesDropped`; the `engine` entry also has `skippedInvalid`, `excludedSimulated`, and `undecided`.
|
|
3155
|
+
- Each `report.groups` row has `workflowHash`, `workflowId` (Runtime records), `stepId`, `agentRole`, `promptHash`, `recurrence`, `distinctRuns`, `askRecurrence`, `undecidedRecords`, `meanCost`, `meanLatency`, `verifyPassRate` (accepted share of decided records), `rework`, `weightedRecurrence`, `undatedRecords`, `costSamples`, `writesRepository`, `evidenceRefs`, `isCandidate`, and, when they apply, `excludedReason`, `candidateKind`, and `candidateId`.
|
|
3156
|
+
- Each `report.promotion` entry has `candidateId`, `policy`, `readyForReview`, and `reason`.
|
|
3157
|
+
|
|
3158
|
+
With no routing records yet, from the project root:
|
|
3159
|
+
|
|
3160
|
+
```bash
|
|
3161
|
+
kxm improve --dry-run
|
|
3162
|
+
```
|
|
3163
|
+
|
|
3164
|
+
```text
|
|
3165
|
+
Sources:
|
|
3166
|
+
engine /home/me/.local/state/kxm/runtime/projects/605a33e70739a298f89939ca/run-events.db (exists=false, records=0, skippedInvalid=0, excludedSimulated=0, undecided=0, duplicatesDropped=0)
|
|
3167
|
+
telemetry /work/proj/.kxm/logs/telemetry.jsonl (exists=false, records=0, duplicatesDropped=0)
|
|
3168
|
+
Project root: /work/proj
|
|
3169
|
+
|
|
3170
|
+
Improvement Report (0 record(s), 0 group(s), 0 candidate(s); promotion policy manual_pr)
|
|
3171
|
+
|
|
3172
|
+
Workflow Step Role Prompt Records Runs Asks Weighted Cost ($) Latency (ms) Accepted Rework Candidate
|
|
3173
|
+
------------------------------------------------------------------------------------------------------------------------------------------
|
|
3174
|
+
```
|
|
3175
|
+
|
|
3176
|
+
```bash
|
|
3177
|
+
kxm improve report --dry-run --json
|
|
3178
|
+
```
|
|
3179
|
+
|
|
3180
|
+
```text
|
|
3181
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"improve","dryRun":true,"path":"/work/proj/.kxm/assets/improvements/2026-09-23T16-42-18-170Z.json","events":0,"recordsCount":0,"groupsCount":0,"candidatesCount":0,"candidates":[],"report":{"schema":"kxm.improvement-report.v2","createdAt":"2026-09-23T16:42:18.170Z","reviewDecision":"proposed","recordsCount":0,"groups":[],"candidates":[],"promotionPolicy":"manual_pr","promotion":[]},"sources":[{"kind":"engine","path":"/home/me/.local/state/kxm/runtime/projects/605a33e70739a298f89939ca/run-events.db","exists":false,"records":0,"skippedInvalid":0,"excludedSimulated":0,"undecided":0,"duplicatesDropped":0},{"kind":"telemetry","path":"/work/proj/.kxm/logs/telemetry.jsonl","exists":false,"records":0,"duplicatesDropped":0}],"projectRoot":"/work/proj"}
|
|
3182
|
+
```
|
|
3183
|
+
|
|
3184
|
+
When the Runtime store exists but is not a readable database:
|
|
3185
|
+
|
|
3186
|
+
```bash
|
|
3187
|
+
kxm improve report --json
|
|
3188
|
+
```
|
|
3189
|
+
|
|
3190
|
+
```text
|
|
3191
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"improve","error":"improve_source_unreadable","detail":"/home/me/.local/state/kxm/runtime/projects/605a33e70739a298f89939ca/run-events.db: file is not a database"}
|
|
3192
|
+
```
|
|
3193
|
+
|
|
3194
|
+
## `kxm routing`
|
|
3195
|
+
|
|
3196
|
+
Model and harness routing telemetry. No hub needed.
|
|
3197
|
+
|
|
3198
|
+
### `kxm routing report`
|
|
3199
|
+
|
|
3200
|
+
```text
|
|
3201
|
+
kxm routing report [-f <path>] [-l] [--prices <path>]
|
|
3202
|
+
```
|
|
3203
|
+
|
|
3204
|
+
Compare verified completion, cost, and rework per behavioral configuration. The table ranks routes quality-first with columns Harness, Model, Effort, Role, Att, Pass%, Rwk%, p50(ms), p95(ms), CtxTok, Metered($), $/Acc, Unm, Unk, Quota, and optionally ListEquiv($).
|
|
3205
|
+
|
|
3206
|
+
Without `--file` it reads the same sources as [`kxm improve report`](#kxm-improve-report): the current project's Runtime event store (read-only), then the workspace `telemetry.jsonl`, dropping a telemetry copy of an attempt the store already supplied and excluding simulated drives. A Runtime attempt counts toward Pass% only when the event log shows its run completed without the step being re-entered.
|
|
3207
|
+
|
|
3208
|
+
| Option | Argument | Default | Description |
|
|
3209
|
+
|---|---|---|---|
|
|
3210
|
+
| `-f`, `--file` | `<path>` | the Runtime store, then workspace telemetry | Telemetry or event log JSONL file (default: workspace telemetry) |
|
|
3211
|
+
| `-l`, `--equivalent-list-cost` | none | off | Include equivalent list price column using price catalog |
|
|
3212
|
+
| `--list-prices` | none | off | Alias for --equivalent-list-cost |
|
|
3213
|
+
| `--prices` | `<path>` | `.kxm/prices.yaml` | Path to price catalog (default: .kxm/prices.yaml) |
|
|
3214
|
+
|
|
3215
|
+
- Reads only. A price catalog that cannot be loaded is skipped silently.
|
|
3216
|
+
- The `--file` help text still says `(default: workspace telemetry)`; without `--file` the Runtime store is read first, as described above. A Runtime store that exists but cannot be read exits 1 with `improve_source_unreadable`.
|
|
3217
|
+
- The text output does not list the sources, and prints `no routing records in telemetry` when no source holds a record. The Rwk% column counts records with `transitions` greater than 0, which Runtime records never set.
|
|
3218
|
+
- JSON keys: `file` (the telemetry path, also when the Runtime store was read), `sources` (without `--file`; the same shape as in `kxm improve`), `configurations` (per behavioral hash for v1 records), `report` (`schema`, `generatedAt`, `totalAttempts`, `rows`).
|
|
3219
|
+
|
|
3220
|
+
With no routing records yet:
|
|
3221
|
+
|
|
3222
|
+
```bash
|
|
3223
|
+
kxm routing report
|
|
3224
|
+
```
|
|
3225
|
+
|
|
3226
|
+
```text
|
|
3227
|
+
no routing records in telemetry
|
|
3228
|
+
```
|
|
3229
|
+
|
|
3230
|
+
```bash
|
|
3231
|
+
kxm routing report --json
|
|
3232
|
+
```
|
|
3233
|
+
|
|
3234
|
+
```text
|
|
3235
|
+
{"schema":"kxm.cli-result.v1","ok":true,"command":"routing report","file":"/work/proj/.kxm/logs/telemetry.jsonl","sources":[{"kind":"engine","path":"/home/me/.local/state/kxm/runtime/projects/605a33e70739a298f89939ca/run-events.db","exists":false,"records":0,"skippedInvalid":0,"excludedSimulated":0,"undecided":0,"duplicatesDropped":0},{"kind":"telemetry","path":"/work/proj/.kxm/logs/telemetry.jsonl","exists":false,"records":0,"duplicatesDropped":0}],"configurations":[],"report":{"schema":"kxm.routing-report.v1","generatedAt":"2026-09-23T16:42:18.482Z","totalAttempts":0,"rows":[]}}
|
|
3236
|
+
```
|
|
3237
|
+
|
|
3238
|
+
Read an explicit file and add the list-price column (the missing catalog is skipped):
|
|
3239
|
+
|
|
3240
|
+
```bash
|
|
3241
|
+
kxm routing report --file .kxm/logs/telemetry.jsonl -l --prices .kxm/prices.yaml
|
|
3242
|
+
```
|
|
3243
|
+
|
|
3244
|
+
```text
|
|
3245
|
+
no routing records in telemetry
|
|
3246
|
+
```
|
|
3247
|
+
|
|
3248
|
+
### `kxm routing benchmark`
|
|
3249
|
+
|
|
3250
|
+
```text
|
|
3251
|
+
kxm routing benchmark [--task <fixture>] [--arms <models>] [--runs <count>]
|
|
3252
|
+
```
|
|
3253
|
+
|
|
3254
|
+
Dedicated offline benchmark for side-by-side model comparison (Decision Q12). In 0.7.1 this prints fixed placeholder figures: it does not run any model, read the task, or measure anything. Latency, tokens, cost, and outcome are constants chosen from the model name. Do not use its output for routing decisions.
|
|
3255
|
+
|
|
3256
|
+
| Option | Argument | Default | Description |
|
|
3257
|
+
|---|---|---|---|
|
|
3258
|
+
| `--task` | `<fixture>` | `Deterministic benchmark task` | Task prompt or fixture path for benchmark comparison |
|
|
3259
|
+
| `--arms` | `<models>` | `grok/grok-4.6,claude/fable,pi/qwen3-coder-plus` | Comma-separated model routes to benchmark (e.g. grok/grok-4.6,claude/fable) |
|
|
3260
|
+
| `--runs` | `<count>` | `1` | Benchmark runs per arm |
|
|
3261
|
+
|
|
3262
|
+
- Reads nothing. JSON keys: `task`, `runs`, `timestamp`, `arms` (`harness`, `model`, `latencyMs`, `tokensIn`, `tokensOut`, `costUsd`, `outcome`).
|
|
3263
|
+
|
|
3264
|
+
```bash
|
|
3265
|
+
kxm routing benchmark
|
|
3266
|
+
```
|
|
3267
|
+
|
|
3268
|
+
```text
|
|
3269
|
+
Routing Benchmark Results (task: Deterministic benchmark task, runs: 1)
|
|
3270
|
+
Harness Model Latency(ms) TokensIn TokensOut Cost($) Outcome
|
|
3271
|
+
grok grok-4.6 420 1200 450 $0.17 passed
|
|
3272
|
+
claude fable 680 1200 450 $0.45 passed
|
|
3273
|
+
pi qwen3-coder-plus 560 1200 450 $0.12 passed
|
|
3274
|
+
```
|
|
3275
|
+
|
|
3276
|
+
## `kxm backup`
|
|
3277
|
+
|
|
3278
|
+
```text
|
|
3279
|
+
kxm backup [--out <dir>]
|
|
3280
|
+
```
|
|
3281
|
+
|
|
3282
|
+
Creates a verified SQLite backup with a hashed `kxm.backup-manifest.v1` manifest. It discovers stores relative to the current directory: the hub store `.kxm/state/kxm.db`, and `registry.db`, `bindings.db`, and `events/*.db` under `.kxm/runtime/`. It ignores `--workspace` and `KXM_DATA_PATH`, and it does not include the Runtime supervisor's stores under the user state root.
|
|
3283
|
+
|
|
3284
|
+
| Option | Argument | Default | Description |
|
|
3285
|
+
|---|---|---|---|
|
|
3286
|
+
| `--out` | `<dir>` | `.kxm/backups/backup-<timestamp>` | Directory to write backup and manifest |
|
|
3287
|
+
|
|
3288
|
+
- Writes a copy of each store and `manifest.json`. `--dry-run` lists the stores it found and the files it would write without opening any store, so no WAL is checkpointed (JSON: `outDir`, `stores` with `storeId`, `sourcePath`, `backupFile`, plus `dryRun` and `planned`).
|
|
3289
|
+
- JSON keys: `backupId`, `outDir`, `manifest` (`schema`, `backupId`, `createdAt`, `projectRoot`, `stores` with `storeId`, `sourcePath`, `backupFile`, `schemaVersion`, `sha256`, `bytes`, `integrity`; `manifestSha256`).
|
|
3290
|
+
- Exit 1 with `backup_failed`; `issues` carry codes such as `backup_no_stores` and `database_corrupted`.
|
|
3291
|
+
|
|
3292
|
+
```bash
|
|
3293
|
+
kxm backup --out ../bk
|
|
3294
|
+
```
|
|
3295
|
+
|
|
3296
|
+
```text
|
|
3297
|
+
Created SQLite backup with 1 store(s):
|
|
3298
|
+
- hub-store: /work/proj/.kxm/state/kxm.db -> kxm.db (schema v5, 110592 bytes, sha256 sha256:56c6d...)
|
|
3299
|
+
Manifest: /work/bk/manifest.json
|
|
3300
|
+
```
|
|
3301
|
+
|
|
3302
|
+
In a project with a hub store:
|
|
3303
|
+
|
|
3304
|
+
```bash
|
|
3305
|
+
kxm backup --dry-run
|
|
3306
|
+
```
|
|
3307
|
+
|
|
3308
|
+
```text
|
|
3309
|
+
dry run: back up 1 store(s) to /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z (sources are not opened, so their WAL is not checkpointed)
|
|
3310
|
+
would write /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z/kxm.db
|
|
3311
|
+
would write /work/proj/.kxm/backups/backup-2026-09-23T17-44-51-277Z/manifest.json
|
|
3312
|
+
```
|
|
3313
|
+
|
|
3314
|
+
In a project without a hub store yet:
|
|
3315
|
+
|
|
3316
|
+
```bash
|
|
3317
|
+
kxm backup --json
|
|
3318
|
+
```
|
|
3319
|
+
|
|
3320
|
+
```text
|
|
3321
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"backup","error":"backup_failed","issues":[{"phase":"semantic","code":"backup_no_stores","file":"/work/proj","message":"no existing SQLite stores found to backup"}]}
|
|
3322
|
+
```
|
|
3323
|
+
|
|
3324
|
+
## `kxm restore`
|
|
3325
|
+
|
|
3326
|
+
```text
|
|
3327
|
+
kxm restore <manifest>
|
|
3328
|
+
```
|
|
3329
|
+
|
|
3330
|
+
Restores SQLite stores from a verified backup manifest. It checks the manifest schema, that every backup file is present, and each file's digest, then restores each store to its recorded source path (rebased onto the current directory when the manifest came from another project root).
|
|
3331
|
+
|
|
3332
|
+
- Arguments: `<manifest>`, path to `manifest.json`.
|
|
3333
|
+
- No command-specific options.
|
|
3334
|
+
- Overwrites live stores. Stop the hub and the Runtime before restoring.
|
|
3335
|
+
- Before overwriting anything, a restore checks every store's recorded schema version against the ceiling for that store, so a store newer than this build is refused (`runtime_schema_newer`) before the first file is replaced. `--dry-run` runs the same manifest, file, digest, and schema checks and plans each target it would overwrite (and any `-wal` or `-shm` sidecar it would delete) without touching them. Dry-run JSON keys: `backupId`, `manifestPath`, `stores` (`storeId`, `targetPath`, `schemaVersion`), `dryRun`, `planned`.
|
|
3336
|
+
- JSON keys: `backupId`, `manifestPath`, `restoredStores` (`storeId`, `sourcePath`, `backupFile`, `schemaVersion`, `integrity`).
|
|
3337
|
+
- Exit 1 with `restore_failed`; `issues` carry codes such as `runtime_path_invalid`, `restore_manifest_invalid`, `restore_file_missing`, `restore_manifest_digest_mismatch`, and `runtime_schema_newer`.
|
|
3338
|
+
|
|
3339
|
+
```bash
|
|
3340
|
+
kxm restore ../bk/manifest.json --dry-run
|
|
3341
|
+
```
|
|
3342
|
+
|
|
3343
|
+
```text
|
|
3344
|
+
dry run: restore 1 store(s) from /work/bk/manifest.json; digests verified against the manifest
|
|
3345
|
+
would write /work/proj/.kxm/state/kxm.db
|
|
3346
|
+
```
|
|
3347
|
+
|
|
3348
|
+
A missing manifest:
|
|
3349
|
+
|
|
3350
|
+
```bash
|
|
3351
|
+
kxm restore nope.json --json
|
|
3352
|
+
```
|
|
3353
|
+
|
|
3354
|
+
```text
|
|
3355
|
+
{"schema":"kxm.cli-result.v1","ok":false,"command":"restore","error":"restore_failed","issues":[{"phase":"semantic","code":"runtime_path_invalid","file":"/work/proj/nope.json","message":"manifest path /work/proj/nope.json does not exist"}]}
|
|
3356
|
+
```
|
|
3357
|
+
|
|
3358
|
+
## `kxm tenant`
|
|
3359
|
+
|
|
3360
|
+
### `kxm tenant status`
|
|
3361
|
+
|
|
3362
|
+
```text
|
|
3363
|
+
kxm tenant status
|
|
3364
|
+
```
|
|
3365
|
+
|
|
3366
|
+
Read hub metadata and authoritative Runtime run state as one labeled view, for machine clients such as the portal backend. It reads both sources concurrently (5 second hub deadline). The hub part covers the agent roster, message queue, plans, and the hub's own workflow runs; the Runtime part covers event-log-folded runs with their `homeRuntimeId`. It attaches to a running supervisor and never starts one, and it resolves only the administrative hub credential.
|
|
3367
|
+
|
|
3368
|
+
No command-specific options.
|
|
3369
|
+
|
|
3370
|
+
- Needs a KXM project. Reads only.
|
|
3371
|
+
- An unreadable source is reported as `unavailable` with a reason (`hub_unreachable`, `hub_timeout`, `hub_unauthorized`, `hub_response_invalid`, `hub_credential_unreadable`, `runtime_supervisor_not_running`), and `degraded` is `true`. Hub and Runtime runs have separate ID spaces, so a comparison with no shared ID is `unverified` (`run_identity_link_absent`), never agreement.
|
|
3372
|
+
- JSON (`kxm.tenant-status.v1`) keys: `project`, `generatedAt`, `hubUrl`, `bindingScope`, `hub` (`state`, `observedAt`, `value` or `reason`), `runtime`, `runComparison`, `degraded`.
|
|
3373
|
+
- Exit 0 when at least one source was read; 1 with `tenant_status_no_source` when neither was, or `project_required`.
|
|
3374
|
+
|
|
3375
|
+
```bash
|
|
3376
|
+
kxm tenant status
|
|
3377
|
+
```
|
|
3378
|
+
|
|
3379
|
+
```text
|
|
3380
|
+
tenant prj_83994a28aa6b472992394a5936c6b7c2 @ http://127.0.0.1:46315 (loopback)
|
|
3381
|
+
hub 0/0 agents online, 0 hub runs, 0 open messages
|
|
3382
|
+
runtime unavailable (runtime_supervisor_not_running)
|
|
3383
|
+
cross-check: unavailable (runtime_runtime_supervisor_not_running)
|
|
3384
|
+
```
|
|
3385
|
+
|
|
3386
|
+
```bash
|
|
3387
|
+
kxm tenant status --json
|
|
3388
|
+
```
|
|
3389
|
+
|
|
3390
|
+
```text
|
|
3391
|
+
{"schema":"kxm.tenant-status.v1","ok":true,"command":"tenant status","project":"prj_83994a28aa6b472992394a5936c6b7c2","generatedAt":"2026-09-23T13:53:27.391Z","hubUrl":"http://127.0.0.1:46315","bindingScope":"loopback","hub":{"state":"ok",...},"runtime":{"state":"unavailable","observedAt":"2026-09-23T13:53:27.384Z","reason":"runtime_supervisor_not_running"},"runComparison":{"state":"unavailable","reason":"runtime_runtime_supervisor_not_running"},"degraded":true}
|
|
3392
|
+
```
|
|
3393
|
+
|
|
3394
|
+
## `kxm ssh`
|
|
3395
|
+
|
|
3396
|
+
Multiplexed remote SSH execution. Commands reuse an OpenSSH ControlMaster socket in `.kxm/run/ssh-sockets/` in the current directory (`ControlPersist=10m`, `BatchMode=yes`, `StrictHostKeyChecking=yes`, 120 second timeout). JSON results carry `ok`, `action`, `host`, and the fields below, but no `command` field except `ssh close`. Under `--dry-run`, `ssh run`, `ssh file`, and `ssh close` connect to nothing: they print a plan (`command`, `host`, the remote command or path, `dryRun`, and `planned` with action `ssh`) instead. `ssh info` reads only, with or without the flag.
|
|
3397
|
+
|
|
3398
|
+
### `kxm ssh info`
|
|
3399
|
+
|
|
3400
|
+
```text
|
|
3401
|
+
kxm ssh info [host]
|
|
3402
|
+
```
|
|
3403
|
+
|
|
3404
|
+
Discover SSH host aliases and parameters safely without opening sockets. Without a host it lists the aliases in `~/.ssh/config`; with a host it resolves that host's effective settings with `ssh -G`.
|
|
3405
|
+
|
|
3406
|
+
- Arguments: `[host]`. No command-specific options. Reads only; no network connection.
|
|
3407
|
+
- JSON keys: `action`, `hosts` (`alias`, `hostName`, `user`, `port`), `durationMs`, and for one host `host`, `resolvedHost`, `user`, `port`.
|
|
3408
|
+
|
|
3409
|
+
```bash
|
|
3410
|
+
kxm ssh info
|
|
3411
|
+
```
|
|
3412
|
+
|
|
3413
|
+
```text
|
|
3414
|
+
No configured SSH host aliases found in ~/.ssh/config
|
|
3415
|
+
```
|
|
3416
|
+
|
|
3417
|
+
```bash
|
|
3418
|
+
kxm ssh info --json
|
|
3419
|
+
```
|
|
3420
|
+
|
|
3421
|
+
```text
|
|
3422
|
+
{"schema":"kxm.cli-result.v1","ok":true,"action":"info","hosts":[],"durationMs":0}
|
|
3423
|
+
```
|
|
3424
|
+
|
|
3425
|
+
### `kxm ssh run`
|
|
3426
|
+
|
|
3427
|
+
```text
|
|
3428
|
+
kxm ssh run <host> <command...> [--sudo]
|
|
3429
|
+
```
|
|
3430
|
+
|
|
3431
|
+
Execute a command on a remote SSH host via multiplexed ControlMaster socket. Commands that match KXM's destructive-command patterns are refused before connecting.
|
|
3432
|
+
|
|
3433
|
+
| Option | Argument | Default | Description |
|
|
3434
|
+
|---|---|---|---|
|
|
3435
|
+
| `--sudo` | none | off | Execute remote command with sudo privileges |
|
|
3436
|
+
|
|
3437
|
+
- Connects to the remote host and runs the command. `--dry-run` connects to nothing and prints the command it would run.
|
|
3438
|
+
- JSON keys: `exitCode`, `stdout`, `stderr`, `truncated`, `socketReused`, `durationMs`, `error`. The exit code is the remote command's.
|
|
3439
|
+
|
|
3440
|
+
```bash
|
|
3441
|
+
kxm ssh run build-01 uptime --dry-run
|
|
3442
|
+
```
|
|
3443
|
+
|
|
3444
|
+
```text
|
|
3445
|
+
dry run: run a command on build-01
|
|
3446
|
+
would ssh build-01: uptime
|
|
3447
|
+
```
|
|
3448
|
+
|
|
3449
|
+
```bash
|
|
3450
|
+
kxm ssh run build-01 uptime
|
|
3451
|
+
```
|
|
3452
|
+
|
|
3453
|
+
Not run: connects to a remote host.
|
|
3454
|
+
|
|
3455
|
+
### `kxm ssh file`
|
|
3456
|
+
|
|
3457
|
+
```text
|
|
3458
|
+
kxm ssh file <host> <path> (--read | --content <text> [--append]) [--sudo]
|
|
3459
|
+
```
|
|
3460
|
+
|
|
3461
|
+
Read or write remote files over SSH.
|
|
3462
|
+
|
|
3463
|
+
| Option | Argument | Default | Description |
|
|
3464
|
+
|---|---|---|---|
|
|
3465
|
+
| `--content` | `<text>` | empty | Content to write to remote file |
|
|
3466
|
+
| `--read` | none | off | Read remote file content |
|
|
3467
|
+
| `--append` | none | off | Append content to remote file |
|
|
3468
|
+
| `--sudo` | none | off | Use sudo privileges on remote file |
|
|
3469
|
+
|
|
3470
|
+
- Warning: without `--read` or `--append` the command overwrites the remote file, with empty content when `--content` is omitted.
|
|
3471
|
+
- Connects to the remote host; `--dry-run` connects to nothing and names the read or write it would make. JSON keys include `stdout` for reads and `bytesProcessed` for writes.
|
|
3472
|
+
|
|
3473
|
+
```bash
|
|
3474
|
+
kxm ssh file build-01 /etc/hostname --read
|
|
3475
|
+
```
|
|
3476
|
+
|
|
3477
|
+
Not run: connects to a remote host.
|
|
3478
|
+
|
|
3479
|
+
### `kxm ssh close`
|
|
3480
|
+
|
|
3481
|
+
```text
|
|
3482
|
+
kxm ssh close <host>
|
|
3483
|
+
```
|
|
3484
|
+
|
|
3485
|
+
Close active ControlMaster socket for an SSH host (`ssh -O stop`).
|
|
3486
|
+
|
|
3487
|
+
- Always exits 0. JSON keys: `closed`, `command`, `host`.
|
|
3488
|
+
|
|
3489
|
+
```bash
|
|
3490
|
+
kxm ssh close build-01
|
|
3491
|
+
```
|
|
3492
|
+
|
|
3493
|
+
Not run: talks to a local SSH control socket for a real host.
|
|
3494
|
+
|
|
3495
|
+
## `kxm help`
|
|
3496
|
+
|
|
3497
|
+
```text
|
|
3498
|
+
kxm help [command]
|
|
3499
|
+
```
|
|
3500
|
+
|
|
3501
|
+
Shows help for the CLI or one command, like `--help`. Every group also has a `help` subcommand (`kxm runs help status`). Exits 0.
|
|
3502
|
+
|
|
3503
|
+
```bash
|
|
3504
|
+
kxm help runs
|
|
3505
|
+
```
|
|
3506
|
+
|
|
3507
|
+
```text
|
|
3508
|
+
Usage: kxm runs [options] [command]
|
|
3509
|
+
|
|
3510
|
+
Inspect KXM runs
|
|
3511
|
+
...
|
|
3512
|
+
```
|
|
3513
|
+
|
|
3514
|
+
## Known behavior gaps in 0.7.1
|
|
3515
|
+
|
|
3516
|
+
These are behaviors of the current build that differ from what the help text or the flag names suggest. Each is also noted in the command's section.
|
|
3517
|
+
|
|
3518
|
+
- The `default` workflow that `kxm init` writes sets `limits.maxAgentTimeMs`, so `kxm runs drive` hands every run of it off with `run_handoff_required` (`limit_unsupported`). Use a `kxm workflow add --template` workflow, or remove the limit, to drive a first run.
|
|
3519
|
+
- `kxm memory sync` creates `CLAUDE.md` and `GEMINI.md` with headers taken from the KXM repository's own instructions.
|
|
3520
|
+
- `kxm routing benchmark` prints constant placeholder figures.
|
|
3521
|
+
- `kxm task sync` does not contact GitHub or Jira.
|
|
3522
|
+
- `kxm runs drive` without `--simulated` runs live harness calls, although its description says "model-free simulation".
|
|
3523
|
+
- `kxm peer inbox` always returns an empty list from the CLI.
|
|
3524
|
+
- `kxm context` subcommands crash with a stack trace when the hub is unreachable, and they ignore the persisted hub credential.
|
|
3525
|
+
- `kxm completion <shell>` generates a command list that includes a nonexistent `plan` command, omits `models`, `routes`, `explain`, and `ssh`, lists a nonexistent `goal get`, and omits `runs drive`, `runs receipt`, `runtime sync-retry`, and `improve report`.
|
|
3526
|
+
- `kxm backup` does not include the Runtime supervisor's stores under the user state root, and its JSON shows `manifestSha256` redacted.
|
|
3527
|
+
- `--help` after an unknown subcommand (for example `kxm hub nope --help`) prints the parent group's help and exits 0, so `--help` cannot be used to test whether a subcommand exists; compare the `Usage:` line instead.
|