@kontextmind/kxm 0.7.94 → 0.7.96
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/README.md +39 -9
- package/CHANGELOG.md +1 -1
- package/README.md +147 -257
- package/SECURITY.md +21 -12
- package/docs/README.md +133 -54
- package/docs/adr/ADR-0002-browser-automation-steel-doks.md +24 -18
- package/docs/adr/ADR-0003-sqlite-only-store.md +100 -0
- package/docs/adr/ADR-0004-edge-identity-authentik.md +99 -0
- package/docs/adr/README.md +33 -0
- package/docs/concepts/architecture.md +262 -0
- package/docs/concepts/data-and-storage.md +194 -0
- package/docs/concepts/trust-model.md +152 -0
- package/docs/contracts/README.md +22 -14
- package/docs/contracts/effects-and-recovery.md +3 -0
- package/docs/contracts/migration.md +2 -2
- package/docs/contracts/routing.md +6 -5
- package/docs/contributing/assignment-runner.md +388 -0
- package/docs/contributing/ci-and-release.md +231 -0
- package/docs/contributing/development.md +362 -0
- package/docs/contributing/harness-routing-internals.md +192 -0
- package/docs/{packages.md → contributing/packages.md} +13 -15
- package/docs/{skills → contributing}/repo-work-delivery.md +20 -21
- package/docs/contributing/test-matrix.md +208 -0
- package/docs/{tui-components.md → contributing/tui-components.md} +30 -22
- package/docs/contributing/writing-docs.md +340 -0
- package/docs/glossary.md +471 -0
- package/docs/guides/agent-skills.md +137 -0
- package/docs/guides/browser-automation.md +160 -0
- package/docs/guides/context-and-memory.md +352 -0
- package/docs/guides/continuous-improvement.md +228 -0
- package/docs/guides/governed-skills.md +173 -0
- package/docs/guides/nous-providers.md +186 -0
- package/docs/guides/peer-messaging.md +304 -0
- package/docs/guides/pi-workers.md +219 -0
- package/docs/guides/provenance-gates.md +313 -0
- package/docs/guides/webhook-workflows.md +364 -0
- package/docs/kb/how-credentials-retrieved-safely.md +38 -12
- package/docs/kb/how-to-capture-and-annotate-section.md +15 -13
- package/docs/kb/how-to-connect-playwright-to-steel.md +16 -11
- package/docs/kb/how-to-recover-expired-session-or-orphan.md +26 -16
- package/docs/kb/how-to-resume-after-mfa.md +19 -11
- package/docs/kb/how-to-take-over-session.md +17 -13
- package/docs/kb/why-authentication-disappeared.md +22 -14
- package/docs/kb/why-automation-opened-different-browser.md +23 -14
- package/docs/kb/why-session-viewer-cannot-control.md +13 -12
- package/docs/operations/backup-and-restore.md +248 -0
- package/docs/operations/deploy.md +307 -0
- package/docs/operations/monitoring.md +209 -0
- package/docs/operations/runtime-sync.md +192 -0
- package/docs/operations/troubleshooting.md +265 -0
- package/docs/operations/upgrade.md +124 -0
- package/docs/prompts/browser-annotate-feedback.md +7 -7
- package/docs/prompts/browser-diagnose-recover.md +11 -10
- package/docs/prompts/browser-explore.md +7 -7
- package/docs/prompts/browser-repro-fix.md +7 -7
- package/docs/prompts/browser-start.md +12 -11
- package/docs/prompts/browser-takeover.md +8 -8
- package/docs/{cli-reference.md → reference/cli-reference.md} +83 -41
- package/docs/{config-reference.md → reference/config-reference.md} +159 -148
- package/docs/reference/configuration.md +299 -0
- package/docs/reference/harness-routing.md +508 -0
- package/docs/reference/http-api.md +203 -0
- package/docs/reference/tools.md +370 -0
- package/docs/{workflow-guide.md → reference/workflow-catalog.md} +92 -153
- package/docs/reference/workflow-definitions.md +286 -0
- package/docs/start/first-workflow.md +287 -0
- package/docs/start/install.md +146 -0
- package/docs/start/quickstart-claude-code.md +405 -0
- package/docs/start/quickstart-pi.md +213 -0
- package/docs/templates/README.md +78 -73
- package/docs/templates/adr.md +13 -13
- package/docs/templates/architecture.md +55 -71
- package/docs/templates/bug-fix.md +13 -16
- package/docs/templates/feature.md +14 -19
- package/docs/templates/handoff.md +44 -46
- package/docs/templates/postmortem.md +30 -43
- package/docs/templates/research.md +15 -20
- package/docs/templates/review.md +49 -50
- package/docs/templates/runbook.md +38 -30
- package/docs/templates/test-plan.md +16 -23
- package/docs/templates/test-report.md +14 -17
- package/examples/README.md +9 -5
- package/examples/provenance-workflow.json +1 -1
- package/examples/webhook-workflows/jira-development.json +59 -0
- package/examples/webhook-workflows/jira-issue-updated.json +12 -0
- package/package.json +2 -2
- package/packages/core/tui/README.md +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/README.md +31 -32
- package/plugins/kxm/dist/cli.js +5 -5
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime.js +1 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm/references/protocol.md +3 -1
- package/plugins/kxm/skills/kxm-browser-auth/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-browser-diagnostics/SKILL.md +5 -5
- package/plugins/kxm/skills/kxm-browser-explore/SKILL.md +2 -2
- package/plugins/kxm/skills/kxm-browser-session/SKILL.md +10 -13
- package/plugins/kxm/skills/kxm-browser-takeover/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-browser-verify/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-context-memory/SKILL.md +13 -4
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +3 -1
- package/plugins/kxm/skills/kxm-mind-setup/SKILL.md +2 -1
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +31 -54
- 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-routing-improve/SKILL.md +15 -7
- package/plugins/kxm/skills/kxm-runs/SKILL.md +11 -5
- package/plugins/kxm/skills/kxm-session/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-tasks/SKILL.md +9 -7
- package/plugins/kxm/skills/kxm-workflow/SKILL.md +10 -2
- package/plugins/kxm/src/cli/system.ts +1 -1
- package/plugins/kxm/src/cli.ts +3 -3
- package/plugins/kxm/src/init-guide-setup.ts +1 -1
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/modes.ts +1 -1
- package/schemas/README.md +1 -1
- package/docs/agent-communication-envelopes-and-gates.md +0 -553
- package/docs/agent-skills.md +0 -198
- package/docs/architecture.md +0 -245
- package/docs/assignment-runner.md +0 -264
- package/docs/browser-automation.md +0 -139
- package/docs/configuration.md +0 -437
- package/docs/continuous-improvement.md +0 -226
- package/docs/getting-started.md +0 -277
- package/docs/harness-routing.md +0 -616
- package/docs/kb/qa-authentik-authentication.md +0 -97
- package/docs/kb/qa-extension-install-and-hub-bootstrap.md +0 -85
- package/docs/kb/qa-hub-on-a-public-host.md +0 -48
- package/docs/kb/qa-sqlite-vs-duckdb.md +0 -35
- package/docs/kb/qa-what-the-hub-stores.md +0 -64
- package/docs/kxm-handbook.md +0 -1181
- package/docs/operations.md +0 -510
- package/docs/operator-pi-packages.md +0 -67
- package/docs/provenance-gates.md +0 -295
- package/docs/skills.md +0 -47
- package/docs/test-matrix.md +0 -132
- package/docs/troubleshooting.md +0 -293
- package/docs/webhook-workflows.md +0 -240
|
@@ -7,22 +7,30 @@ project: "kxm"
|
|
|
7
7
|
status: "accepted"
|
|
8
8
|
owner: "@operator"
|
|
9
9
|
created: "2026-09-14"
|
|
10
|
-
updated: "2026-09-
|
|
10
|
+
updated: "2026-09-23"
|
|
11
11
|
authority: "instruction"
|
|
12
12
|
confidence: "verified"
|
|
13
|
-
summary: "
|
|
13
|
+
summary: "The verification and observation refresh an agent performs before resuming after MFA."
|
|
14
14
|
tags: ["browser", "mfa", "resume", "verification"]
|
|
15
|
-
related: ["docs/kb/how-to-take-over-session.md", "docs/browser-automation.md"]
|
|
15
|
+
related: ["docs/kb/how-to-take-over-session.md", "docs/guides/browser-automation.md"]
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
# How does an agent resume after MFA?
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
After you complete an MFA challenge in the session viewer, the agent does not
|
|
21
|
+
click blindly. It follows this sequence:
|
|
21
22
|
|
|
22
|
-
1. **State
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
1. **State transition.** The session moves from `HUMAN_CONTROL` to
|
|
24
|
+
`VERIFY_AUTHENTICATION`. The `SteelClient` keeps this state in memory for
|
|
25
|
+
its own lifetime; a new client does not inherit it.
|
|
26
|
+
2. **CDP re-attachment.** The agent re-queries the active tab from the Steel
|
|
27
|
+
CDP endpoint.
|
|
28
|
+
3. **Application state check.**
|
|
29
|
+
- It confirms that `page.url()` left the MFA prompt for the intended page,
|
|
30
|
+
for example `/dashboard`.
|
|
31
|
+
- It looks for signed-in elements such as an account menu or a sign-out
|
|
32
|
+
button.
|
|
33
|
+
4. **Observation refresh.** It takes a fresh `agent-browser snapshot`, or
|
|
34
|
+
queries fresh DOM locators, before the next action.
|
|
35
|
+
5. **Control returns.** The session returns to `AGENT_CONTROL` and the task
|
|
36
|
+
continues.
|
|
@@ -7,26 +7,30 @@ project: "kxm"
|
|
|
7
7
|
status: "accepted"
|
|
8
8
|
owner: "@operator"
|
|
9
9
|
created: "2026-09-14"
|
|
10
|
-
updated: "2026-09-
|
|
10
|
+
updated: "2026-09-23"
|
|
11
11
|
authority: "instruction"
|
|
12
12
|
confidence: "verified"
|
|
13
|
-
summary: "
|
|
13
|
+
summary: "Take over an active Steel browser session at an authentication gate."
|
|
14
14
|
tags: ["browser", "takeover", "auth", "mfa"]
|
|
15
|
-
related: ["docs/browser-automation.md", "docs/kb/how-to-resume-after-mfa.md"]
|
|
15
|
+
related: ["docs/guides/browser-automation.md", "docs/kb/how-to-resume-after-mfa.md"]
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
# How do I take over a browser session to log in?
|
|
19
19
|
|
|
20
|
-
When an agent
|
|
20
|
+
When an agent reaches a login screen, an OAuth prompt or a security challenge,
|
|
21
|
+
it stops and asks you to take over, following the `kxm-browser-takeover` skill.
|
|
21
22
|
|
|
22
23
|
## Steps
|
|
23
24
|
|
|
24
|
-
1. **Copy the
|
|
25
|
-
The
|
|
26
|
-
`
|
|
27
|
-
2. **Open the
|
|
28
|
-
|
|
29
|
-
3. **
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
1. **Copy the takeover URL.** The agent prints a session viewer link such as
|
|
26
|
+
`<steel-ui-url>?sessionId=<session-id>`. The viewer URL is `STEEL_UI_URL`,
|
|
27
|
+
or `<steel-api-url>/ui` when that is unset.
|
|
28
|
+
2. **Open the session viewer** in your desktop browser. It shows a live
|
|
29
|
+
screencast of the remote browser the agent was driving.
|
|
30
|
+
3. **Sign in.** Enter the username, password or security key in the session.
|
|
31
|
+
If clicks on the screencast do not register, use the DevTools inspector at
|
|
32
|
+
`<steel-api-url>/v1/devtools/inspector.html`; see
|
|
33
|
+
[Why can I view a session but not control it?](why-session-viewer-cannot-control.md).
|
|
34
|
+
4. **Signal completion.** Return to the agent's terminal session and tell it
|
|
35
|
+
`auth complete` or `proceed`. It then verifies the sign-in before it resumes;
|
|
36
|
+
see [How does an agent resume after MFA?](how-to-resume-after-mfa.md).
|
|
@@ -7,26 +7,34 @@ project: "kxm"
|
|
|
7
7
|
status: "accepted"
|
|
8
8
|
owner: "@operator"
|
|
9
9
|
created: "2026-09-14"
|
|
10
|
-
updated: "2026-09-
|
|
10
|
+
updated: "2026-09-23"
|
|
11
11
|
authority: "instruction"
|
|
12
12
|
confidence: "verified"
|
|
13
|
-
summary: "
|
|
13
|
+
summary: "Diagnose lost sign-in state: session expiry, a new session instead of an attached one, and cookie scoping."
|
|
14
14
|
tags: ["browser", "authentication", "cookies", "troubleshooting"]
|
|
15
|
-
related: ["docs/browser-automation.md", "docs/kb/why-automation-opened-different-browser.md"]
|
|
15
|
+
related: ["docs/guides/browser-automation.md", "docs/kb/why-automation-opened-different-browser.md"]
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
# Why did authentication disappear?
|
|
19
19
|
|
|
20
|
-
If an agent was
|
|
20
|
+
If an agent was signed in on an earlier step or run and now sees a login screen
|
|
21
|
+
again, one of these is usually the cause.
|
|
21
22
|
|
|
22
|
-
##
|
|
23
|
+
## Causes and fixes
|
|
23
24
|
|
|
24
|
-
1. **
|
|
25
|
-
- Steel sessions are ephemeral
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- **Fix
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
25
|
+
1. **The session was released or expired.**
|
|
26
|
+
- Steel sessions are ephemeral. When a session reaches its timeout (the KXM
|
|
27
|
+
client defaults to five minutes) or is released through
|
|
28
|
+
`POST /v1/sessions/<session-id>/release`, its cookies and local storage
|
|
29
|
+
are gone.
|
|
30
|
+
- **Fix:** to reuse sign-in state across tasks, save Playwright
|
|
31
|
+
`storageState` and load it when you start the next session.
|
|
32
|
+
2. **A new session was launched instead of attaching to the existing one.**
|
|
33
|
+
- A new session starts with a clean browser profile.
|
|
34
|
+
- **Fix:** make sure the task passes the existing `sessionId` to
|
|
35
|
+
`getSession()`, or connects to the existing CDP endpoint.
|
|
36
|
+
3. **Cookies were scoped to another domain.**
|
|
37
|
+
- Sign-in flows often set cookies on a subdomain, such as
|
|
38
|
+
`auth.example.com`, that `app.example.com` does not receive.
|
|
39
|
+
- **Fix:** make sure the cookies were issued for the primary domain, or that
|
|
40
|
+
the single sign-on redirect finished, before you save state.
|
|
@@ -7,26 +7,35 @@ project: "kxm"
|
|
|
7
7
|
status: "accepted"
|
|
8
8
|
owner: "@operator"
|
|
9
9
|
created: "2026-09-14"
|
|
10
|
-
updated: "2026-09-
|
|
10
|
+
updated: "2026-09-23"
|
|
11
11
|
authority: "instruction"
|
|
12
12
|
confidence: "verified"
|
|
13
|
-
summary: "
|
|
13
|
+
summary: "Prevent accidental local browser launches and make Playwright and agent-browser attach to remote Steel."
|
|
14
14
|
tags: ["browser", "cdp", "playwright", "agent-browser", "troubleshooting"]
|
|
15
|
-
related: ["docs/browser-automation.md", "docs/kb/how-to-connect-playwright-to-steel.md"]
|
|
15
|
+
related: ["docs/guides/browser-automation.md", "docs/kb/how-to-connect-playwright-to-steel.md"]
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
# Why did automation open a different browser?
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
You expected automation to run on your Steel deployment, but a local Chrome
|
|
21
|
+
window opened, or the agent's actions never appeared in the Steel session
|
|
22
|
+
viewer.
|
|
21
23
|
|
|
22
|
-
##
|
|
24
|
+
## Causes
|
|
23
25
|
|
|
24
|
-
1. **
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
|
|
26
|
+
1. **The script called `chromium.launch()` instead of
|
|
27
|
+
`chromium.connectOverCDP()`.**
|
|
28
|
+
- `chromium.launch()` starts a browser on the local machine.
|
|
29
|
+
- **Fix:** in Playwright, connect with `chromium.connectOverCDP(cdpUrl)`.
|
|
30
|
+
2. **`agent-browser` ran without `--cdp`.**
|
|
31
|
+
- `agent-browser open <url>` without `--cdp` starts a local headless
|
|
32
|
+
browser.
|
|
33
|
+
- **Fix:** always pass the session's CDP URL:
|
|
34
|
+
`--cdp "wss://<steel-host>/v1/devtools?sessionId=<session-id>&apiKey=<steel-api-key>"`.
|
|
35
|
+
Build it with `formatCDPEndpoint()`; see
|
|
36
|
+
[How do I connect Playwright to the existing Steel session?](how-to-connect-playwright-to-steel.md).
|
|
37
|
+
3. **Environment variables were missing.**
|
|
38
|
+
- A script that falls back to local execution when `STEEL_CDP_URL` is
|
|
39
|
+
unset launches a local browser.
|
|
40
|
+
- **Fix:** load `STEEL_CDP_URL`, or `STEEL_API_URL` and `STEEL_API_KEY`,
|
|
41
|
+
from your secret manager before the run.
|
|
@@ -7,25 +7,26 @@ project: "kxm"
|
|
|
7
7
|
status: "accepted"
|
|
8
8
|
owner: "@operator"
|
|
9
9
|
created: "2026-09-14"
|
|
10
|
-
updated: "2026-09-
|
|
10
|
+
updated: "2026-09-23"
|
|
11
11
|
authority: "instruction"
|
|
12
12
|
confidence: "verified"
|
|
13
|
-
summary: "
|
|
13
|
+
summary: "The self-hosted Steel screencast viewer versus the DevTools inspector for interactive control."
|
|
14
14
|
tags: ["browser", "takeover", "steel", "ui"]
|
|
15
|
-
related: ["docs/browser-automation.md", "docs/kb/how-to-take-over-session.md"]
|
|
15
|
+
related: ["docs/guides/browser-automation.md", "docs/kb/how-to-take-over-session.md"]
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
# Why can I view a session but not control it?
|
|
19
19
|
|
|
20
|
-
In self-hosted open-source Steel (`steel-dev/steel-browser`), the web UI at
|
|
20
|
+
In self-hosted open-source Steel (`steel-dev/steel-browser`), the web UI at
|
|
21
|
+
`/ui` shows a live screencast, event logs and network activity. Depending on how
|
|
22
|
+
the canvas is captured, clicks on the video may not reach the browser.
|
|
21
23
|
|
|
22
24
|
## Resolution
|
|
23
25
|
|
|
24
|
-
1. **Use the Chrome DevTools
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Ensure the agent is in `HUMAN_CONTROL` state so automation does not race or override your clicks.
|
|
26
|
+
1. **Use the Chrome DevTools inspector.** Open the inspector page of your Steel
|
|
27
|
+
deployment, `<steel-api-url>/v1/devtools/inspector.html`, or the remote
|
|
28
|
+
debugger port your deployment exposes.
|
|
29
|
+
2. **Interact through DevTools.** The inspector gives full control of the DOM,
|
|
30
|
+
console, network and storage.
|
|
31
|
+
3. **Keep the agent out of the way.** Make sure the session is in
|
|
32
|
+
`HUMAN_CONTROL`, so automation does not race your clicks.
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Back up and restore KXM
|
|
2
|
+
|
|
3
|
+
Protect every piece of KXM state, not only the hub database, and bring it back after a disk loss, a bad change, or a move to a new host. This page is for operators. You learn which six roots hold state, what `kxm backup` and `kxm restore` do and do not cover, and a stopped-state procedure for the rest.
|
|
4
|
+
|
|
5
|
+
## Before you begin
|
|
6
|
+
|
|
7
|
+
- The `kxm` CLI and the project checkout, on the machine that runs the hub and the [Runtime](../glossary.md#runtime).
|
|
8
|
+
- Permission to stop the hub, the Runtime supervisor, and anything that restarts them.
|
|
9
|
+
- Protected, preferably encrypted, backup storage. Backups contain message bodies, prompts and, if you include them, credentials.
|
|
10
|
+
|
|
11
|
+
## Know where state lives
|
|
12
|
+
|
|
13
|
+
KXM spreads state over six roots. Some of them move with environment variables, and a backup that assumes one location silently misses another. The following diagram shows each root, what it holds, and the variable that moves it.
|
|
14
|
+
|
|
15
|
+
```mermaid
|
|
16
|
+
flowchart TB
|
|
17
|
+
subgraph R["$R checkout root: the Git checkout, never moves"]
|
|
18
|
+
R1["Project definition: .kxm/project.yaml, config.yaml, agents/, models/, workflows/, gates.yaml, roles/, role-hosts.yaml, routes.yaml, roster.yaml, prices.yaml, repo/, project/env.yaml"]
|
|
19
|
+
R2["Durable records: .kxm/memory/, skills/, goals/, tasks/, candidates/"]
|
|
20
|
+
end
|
|
21
|
+
subgraph D["$D workspace: KXM_WORKSPACE_DIR or --workspace, default $R/.kxm"]
|
|
22
|
+
D1["logs/ (KXM_LOGS_DIR): kxm-hub.jsonl (KXM_LOG_PATH), worker logs, telemetry.jsonl"]
|
|
23
|
+
D2["assets/ (KXM_ASSETS_DIR): retrospectives, improvements, evidence"]
|
|
24
|
+
end
|
|
25
|
+
subgraph W["$W workspace state: KXM_STATE_DIR, default $D/state"]
|
|
26
|
+
W1["kxm.db hub store (KXM_DATA_PATH)"]
|
|
27
|
+
W2["Pi sessions, worker manifests, PID claims"]
|
|
28
|
+
end
|
|
29
|
+
subgraph S["$S user state root: KXM_STATE_HOME"]
|
|
30
|
+
S1["runtime/registry.db, runtime/projects/KEY/run-events.db and prompt sidecars"]
|
|
31
|
+
S2["hub-env.json, hub-binding.json, update.yaml, projects/HASH/repository-bindings.json"]
|
|
32
|
+
end
|
|
33
|
+
subgraph C["$C user config: KXM_USER_CONFIG_DIR, default ~/.config/kxm"]
|
|
34
|
+
C1["config.yaml, roles/, workflows/, role-hosts.yaml, session.token"]
|
|
35
|
+
end
|
|
36
|
+
subgraph T["$T federated telemetry: XDG_CONFIG_HOME/kxm/telemetry"]
|
|
37
|
+
T1["model-metrics.jsonl, not written by any command today"]
|
|
38
|
+
end
|
|
39
|
+
R -->|".kxm/ by default"| D
|
|
40
|
+
D -->|"state/ by default"| W
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
| Root | Default | Moved by |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `$R` checkout | The Git checkout | Nothing. `.kxm/` definition files always stay here |
|
|
46
|
+
| `$D` workspace | `$R/.kxm` | `KXM_WORKSPACE_DIR` or `--workspace`, relative to `KXM_WORKDIR` or the current directory |
|
|
47
|
+
| `$W` workspace state | `$D/state` | `KXM_STATE_DIR`; `KXM_DATA_PATH` moves only `kxm.db` |
|
|
48
|
+
| `$S` user state root | `~/.local/state/kxm` (Linux, honoring `XDG_STATE_HOME`), `~/Library/Application Support/KXM` (macOS), `%LOCALAPPDATA%\KXM` (Windows) | `KXM_STATE_HOME`, which must be absolute |
|
|
49
|
+
| `$C` user config | `~/.config/kxm` | `KXM_USER_CONFIG_DIR` |
|
|
50
|
+
| `$T` federated telemetry | `~/.config/kxm/telemetry` | `XDG_CONFIG_HOME` |
|
|
51
|
+
|
|
52
|
+
Three override rules catch people out:
|
|
53
|
+
|
|
54
|
+
- `--workspace` derives `config/`, `logs/`, `assets/` and `state/` from one directory and ignores the per-directory variables. Without it, `KXM_CONFIG_DIR`, `KXM_LOGS_DIR`, `KXM_ASSETS_DIR` and `KXM_STATE_DIR` each move only their own target. `KXM_STATE_DIR=/srv/state` alone leaves `$D` at `$R/.kxm`.
|
|
55
|
+
- A relative `KXM_STATE_HOME` fails with `local_state_root_not_absolute`. A relative `XDG_STATE_HOME` or `LOCALAPPDATA` base is ignored without an error, and the platform default is used.
|
|
56
|
+
- `KXM_WORKER_LOG_PATH` and `KXM_AGENT_LOG_PATH` move worker logs out of `$D/logs`.
|
|
57
|
+
|
|
58
|
+
Record every override with the backup. A restore that lands where the running service does not look is not a restore.
|
|
59
|
+
|
|
60
|
+
## Know what each backup covers
|
|
61
|
+
|
|
62
|
+
`kxm backup` protects SQLite stores it can find from the current directory. Everything else needs the stopped-state copy described below.
|
|
63
|
+
|
|
64
|
+
> [!WARNING]
|
|
65
|
+
> `kxm backup` does not back up the Runtime. It looks for Runtime stores under `.kxm/runtime/` in the checkout, but the Runtime writes them under the user state root (`$S/runtime/registry.db` and `$S/runtime/projects/<key>/run-events.db`). In practice a backup holds only the hub store. Back up the Runtime stores and their prompt sidecars by hand, stopped, as shown in [Back up everything else](#back-up-everything-else).
|
|
66
|
+
|
|
67
|
+
| Path | Holds | In `kxm backup` |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| `$W/kxm.db` | Hub store: agents, messages, workflow runs, journals, context items, leases, synced run facts | Yes, at `<current directory>/.kxm/state/kxm.db` only |
|
|
70
|
+
| `$S/runtime/registry.db` | Runtime registry: projects, their roots, the supervisor identity and claim | No |
|
|
71
|
+
| `$S/runtime/projects/<key>/run-events.db` | Event-sourced runs, drive receipts, gate evidence, the sync outbox | No |
|
|
72
|
+
| `$S/runtime/projects/<key>/run-events.db.run-prompts.json` | Run prompt text; restoring a store without it loses every prompt | No |
|
|
73
|
+
| `$S/projects/<hash>/repository-bindings.json`, `$S/update.yaml` | Member repository paths; updater settings | No |
|
|
74
|
+
| `$S/hub-env.json`, `$S/hub-binding.json`, `$C/session.token` | Credentials and the machine's hub binding | No; prefer regenerating secrets to copying them |
|
|
75
|
+
| `$R/.kxm/` definition files and durable records | Project, roles, routes, prices, roster, memory, skills, goals, tasks, candidates | No; commit them to Git or copy the checkout |
|
|
76
|
+
| Each member repository's `.kxm/repo/*.yaml` | Member definition and environment | No; they live in the member's own checkout |
|
|
77
|
+
| `$W/worker-*.json`, `$W/pi-sessions/` | Worker routing and recovery manifests; Pi model history | No; manifests are required for resumable workers, Pi history is optional |
|
|
78
|
+
| `$D/assets/`, `$D/logs/` | Retrospectives and evidence; logs and local usage accounting (`telemetry.jsonl`) | No |
|
|
79
|
+
| `$C` | User-level roles, workflows and settings | No |
|
|
80
|
+
|
|
81
|
+
A restore without `roster.yaml`, `routes.yaml` or `prices.yaml` comes back healthy but with different admission and cost behavior, so treat them as part of the backup even though they are plain files. `kxm improve report --out-dir` can write candidates outside `$R/.kxm/candidates/`; include that directory if you use it.
|
|
82
|
+
|
|
83
|
+
These files are disposable and need no backup: `hub.pid`, `hub.stop`, `worker-*.pid`, `session-brief.json`, `update-check.json`, `runtime/supervisor.token`, `runtime/supervisor.error`.
|
|
84
|
+
|
|
85
|
+
## Back up the hub store with `kxm backup`
|
|
86
|
+
|
|
87
|
+
Run it from the checkout root. It resolves stores from the current directory and ignores `--workspace`, `KXM_WORKDIR`, `KXM_STATE_DIR` and `KXM_DATA_PATH`, so a relocated hub database is not found.
|
|
88
|
+
|
|
89
|
+
Preview first. A dry run lists what it would write, opens no store and writes nothing:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
cd /srv/kxm/product
|
|
93
|
+
kxm backup --dry-run
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Expected output:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
dry run: back up 1 store(s) to /srv/kxm/product/.kxm/backups/backup-2026-09-23T18-29-09-107Z (sources are not opened, so their WAL is not checkpointed)
|
|
100
|
+
would write /srv/kxm/product/.kxm/backups/backup-2026-09-23T18-29-09-107Z/kxm.db
|
|
101
|
+
would write /srv/kxm/product/.kxm/backups/backup-2026-09-23T18-29-09-107Z/manifest.json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then write the backup outside the checkout:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
kxm backup --out /backups/kxm/2026-09-23/hub
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Expected output:
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
Created SQLite backup with 1 store(s):
|
|
114
|
+
- hub-store: /srv/kxm/product/.kxm/state/kxm.db -> kxm.db (schema v5, 110592 bytes, sha256 sha256:86549...)
|
|
115
|
+
Manifest: /backups/kxm/2026-09-23/hub/manifest.json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
For each store, `kxm backup` checkpoints the write-ahead log, runs `PRAGMA integrity_check`, copies the database with `VACUUM INTO`, checks the copy's integrity, sets mode `0600`, and records its schema version and SHA-256 in `manifest.json` (`kxm.backup-manifest.v1`). `VACUUM INTO` reads one consistent snapshot, so the hub can keep running during this step.
|
|
119
|
+
|
|
120
|
+
> [!NOTE]
|
|
121
|
+
> Without `--out`, backups go to `.kxm/backups/` inside the checkout. Keep that directory out of Git, or always pass `--out`.
|
|
122
|
+
|
|
123
|
+
It fails with `backup_no_stores` when `.kxm/state/kxm.db` does not exist under the current directory, and with `database_corrupted` when an integrity check fails.
|
|
124
|
+
|
|
125
|
+
## Back up everything else
|
|
126
|
+
|
|
127
|
+
Copy the remaining state with both services stopped. SQLite runs in write-ahead-log mode, so a plain copy of a live database can miss committed data.
|
|
128
|
+
|
|
129
|
+
1. Stop the Runtime, then the hub, and confirm both are down:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
kxm runtime stop
|
|
133
|
+
kxm hub stop
|
|
134
|
+
kxm runtime status # expect "runtime supervisor is not running" and exit status 1
|
|
135
|
+
kxm hub view # expect "hub health=false ready=false" and exit status 1
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
2. Keep them down until the copy finishes. Pause your service manager's restart policy, Pi sessions with `hub.autoStart: background`, and anything that runs Runtime commands, because `kxm run`, `kxm runs list` and similar commands start the supervisor on demand.
|
|
139
|
+
3. Copy the hub store and the user state root:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
S="${KXM_STATE_HOME:-$HOME/.local/state/kxm}" # macOS: "$HOME/Library/Application Support/KXM"
|
|
143
|
+
B=/backups/kxm/2026-09-23
|
|
144
|
+
mkdir -p "$B"
|
|
145
|
+
kxm backup --out "$B/hub"
|
|
146
|
+
tar -C "$S" --exclude 'supervisor.token' --exclude 'hub-env.json' -czf "$B/user-state.tgz" .
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The archive holds `registry.db`, every project's `run-events.db` with any `-wal` and `-shm` files and its `.run-prompts.json` sidecar, the repository bindings, the hub binding and `update.yaml`. It leaves out the credential file; keep tokens in your secret store, or include `hub-env.json` and protect the archive as a secret.
|
|
150
|
+
|
|
151
|
+
If `KXM_STATE_DIR` or `KXM_DATA_PATH` moved the hub database, `kxm backup` fails with `backup_no_stores`. With both services stopped, copy that database file and any `-wal` and `-shm` files instead.
|
|
152
|
+
4. Copy the other roots your recovery needs: the checkout's untracked `.kxm/` records, `$D/assets/`, `$W/worker-*.json` (and `$W/pi-sessions/` only if your policy keeps model history), and `$C`.
|
|
153
|
+
5. Record the KXM version (`kxm --version`), the configuration commit, the schema versions from `manifest.json`, and every override variable, next to the copy.
|
|
154
|
+
6. Start the hub, then the Runtime with `kxm runtime start`, and resume the paused restart policies.
|
|
155
|
+
|
|
156
|
+
Keep at least one previous backup, and bound retention: run events and prompt sidecars grow with every run.
|
|
157
|
+
|
|
158
|
+
## Restore with `kxm restore`
|
|
159
|
+
|
|
160
|
+
`kxm restore` overwrites the live database and deletes its `-wal` and `-shm` files, and it does not check whether the hub is running. Stop the hub and the Runtime first, and move the current state aside rather than deleting it.
|
|
161
|
+
|
|
162
|
+
Preview the restore. The dry run performs every check below and lists what it would overwrite:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
cd /srv/kxm/product
|
|
166
|
+
kxm restore /backups/kxm/2026-09-23/hub/manifest.json --dry-run
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Expected output:
|
|
170
|
+
|
|
171
|
+
```text
|
|
172
|
+
dry run: restore 1 store(s) from /backups/kxm/2026-09-23/hub/manifest.json; digests verified against the manifest
|
|
173
|
+
would write /srv/kxm/product/.kxm/state/kxm.db
|
|
174
|
+
would delete /srv/kxm/product/.kxm/state/kxm.db-wal
|
|
175
|
+
would delete /srv/kxm/product/.kxm/state/kxm.db-shm
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Then run it without `--dry-run`:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
kxm restore /backups/kxm/2026-09-23/hub/manifest.json
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Expected output:
|
|
185
|
+
|
|
186
|
+
```text
|
|
187
|
+
Restored 1 SQLite store(s) from /backups/kxm/2026-09-23/hub/manifest.json:
|
|
188
|
+
- hub-store: -> /srv/kxm/product/.kxm/state/kxm.db (schema v5, integrity ok)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Before it overwrites anything, `kxm restore` checks that the manifest is a `kxm.backup-manifest.v1` document, that every listed file exists, that each file's SHA-256 matches the manifest, and that no store is newer than this build supports. The manifest's own `manifestSha256` is not checked.
|
|
192
|
+
|
|
193
|
+
It then checks each backup's integrity and schema version again, copies it into place with mode `0600`, and checks the result. Each store returns to its recorded path, rebased onto the current directory when the manifest came from another checkout.
|
|
194
|
+
|
|
195
|
+
### Restore ceilings
|
|
196
|
+
|
|
197
|
+
A backup newer than this build is refused with `runtime_schema_newer` before any file changes. KXM has no migrations: an older backup restores, but its store then refuses to open with `runtime_schema_outdated`. Restore an older backup with the release that wrote it; see [Upgrade KXM](upgrade.md#understand-schema-changes).
|
|
198
|
+
|
|
199
|
+
The ceilings come from `KXM_BACKUP_CEILINGS` in `plugins/kxm/src/database.ts` and match each store's own schema version:
|
|
200
|
+
|
|
201
|
+
| Store id | Highest schema version restored |
|
|
202
|
+
|---|---|
|
|
203
|
+
| `hub-store` | 5 |
|
|
204
|
+
| `registry` | 1 |
|
|
205
|
+
| `events:<key>` | 7 |
|
|
206
|
+
| `binding-store` | 1 (no current store uses it) |
|
|
207
|
+
|
|
208
|
+
### Restore the Runtime stores by hand
|
|
209
|
+
|
|
210
|
+
1. Stop the Runtime and the hub, as in the backup procedure.
|
|
211
|
+
2. Move `$S/runtime/registry.db` and `$S/runtime/projects/` aside.
|
|
212
|
+
3. Extract the archive into the user state root:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
S="${KXM_STATE_HOME:-$HOME/.local/state/kxm}"
|
|
216
|
+
tar -C "$S" -xzf /backups/kxm/2026-09-23/user-state.tgz
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The archive also brings back the hub binding, `update.yaml` and repository bindings.
|
|
220
|
+
4. Keep the checkout at the same absolute path. The Runtime derives each project's store key from the canonical checkout path, so a checkout restored elsewhere does not find its runs.
|
|
221
|
+
|
|
222
|
+
## Verify the restore
|
|
223
|
+
|
|
224
|
+
1. Start the hub and check `/ready` and `kxm hub view`, including that the reported `loopback` or `remote` scope matches the environment.
|
|
225
|
+
2. Run `kxm runtime start`, then `kxm runtime status`, and wait for the sync state to return to `ok`.
|
|
226
|
+
3. Run `kxm runs list`, open one run with `kxm runs status <run-id>`, and confirm its prompt sidecar came back. A run store without its sidecar is a partial restore.
|
|
227
|
+
4. Send one test request between two agents.
|
|
228
|
+
|
|
229
|
+
Test a full restore on a spare machine before you rely on it, and repeat the test periodically.
|
|
230
|
+
|
|
231
|
+
## Troubleshooting
|
|
232
|
+
|
|
233
|
+
| Symptom | Cause | Fix |
|
|
234
|
+
|---|---|---|
|
|
235
|
+
| `backup_no_stores` | No `.kxm/state/kxm.db` under the current directory, or it was moved with `KXM_STATE_DIR` or `KXM_DATA_PATH` | Run from the checkout root; copy a relocated database with the stopped-state procedure |
|
|
236
|
+
| Runs are missing after a restore | `kxm backup` never contained the Runtime stores | Restore `$S/runtime/` from the stopped-state archive |
|
|
237
|
+
| `restore_manifest_digest_mismatch` | A backup file changed after the manifest was written | Use another backup; do not edit files in a backup set |
|
|
238
|
+
| `restore_file_missing` | A file listed in the manifest is not beside it | Copy the whole backup directory, not only `manifest.json` |
|
|
239
|
+
| `runtime_schema_mismatch` | A backup file's schema version differs from the one its manifest records | Use another backup set; never mix files between sets |
|
|
240
|
+
| `runtime_schema_newer` | The backup came from a newer release | Upgrade KXM first, then restore |
|
|
241
|
+
| The hub refuses to start with `runtime_schema_outdated` | The restored store is older than this build | Run the release that wrote it, or start fresh |
|
|
242
|
+
|
|
243
|
+
## Next steps
|
|
244
|
+
|
|
245
|
+
- Move to a new release safely: [Upgrade KXM](upgrade.md)
|
|
246
|
+
- What each store contains and how sensitive it is: [Data and storage](../concepts/data-and-storage.md)
|
|
247
|
+
- Watch the restored service: [Monitor KXM](monitoring.md)
|
|
248
|
+
- Exact flags and JSON fields: [CLI reference](../reference/cli-reference.md#kxm-backup)
|