@knightcodeai/cli 0.17.4 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1293 -0
- package/README.md +2 -2
- package/dist/bundle/chunks/anthropic-messages-A2IH2IY3.js +6 -0
- package/dist/bundle/chunks/anthropic.js +101 -0
- package/dist/bundle/chunks/azure-openai-responses-XZILQZOG.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +89 -0
- package/dist/bundle/chunks/chunk-4CRI7BMY.js +2 -0
- package/dist/bundle/chunks/chunk-57BPR4HF.js +2 -0
- package/dist/bundle/chunks/chunk-A5LJINMT.js +2 -0
- package/dist/bundle/chunks/chunk-AANBXVWQ.js +2 -0
- package/dist/bundle/chunks/chunk-ACHHEROF.js +7 -0
- package/dist/bundle/chunks/chunk-AFR2OW6S.js +108 -0
- package/dist/bundle/chunks/chunk-AHB7JV5B.js +2 -0
- package/dist/bundle/chunks/chunk-B2FT7RH5.js +2 -0
- package/dist/bundle/chunks/chunk-BRKUE2MD.js +2 -0
- package/dist/bundle/chunks/chunk-DKOURXGU.js +2 -0
- package/dist/bundle/chunks/chunk-DVFCXHT4.js +2 -0
- package/dist/bundle/chunks/chunk-EPYT326Y.js +30 -0
- package/dist/bundle/chunks/chunk-ETOMYYZC.js +2 -0
- package/dist/bundle/chunks/chunk-FA32X2UJ.js +7 -0
- package/dist/bundle/chunks/chunk-FHM6KUY3.js +44 -0
- package/dist/bundle/chunks/chunk-FO7CEQB3.js +11 -0
- package/dist/bundle/chunks/chunk-GHVXUCGU.js +130 -0
- package/dist/bundle/chunks/chunk-HHWP56PR.js +2 -0
- package/dist/bundle/chunks/chunk-HSL72VZI.js +2 -0
- package/dist/bundle/chunks/chunk-HUQB436V.js +2 -0
- package/dist/bundle/chunks/chunk-HWXGL4YB.js +2 -0
- package/dist/bundle/chunks/chunk-KQKUEQJA.js +6 -0
- package/dist/bundle/chunks/chunk-M5GCRGV6.js +1333 -0
- package/dist/bundle/chunks/chunk-MB4QRS7Y.js +9 -0
- package/dist/bundle/chunks/chunk-MXIWLMNT.js +8 -0
- package/dist/bundle/chunks/chunk-N6VDWLND.js +2 -0
- package/dist/bundle/chunks/chunk-NCIBB66G.js +2 -0
- package/dist/bundle/chunks/chunk-NDQ5OW6U.js +2 -0
- package/dist/bundle/chunks/chunk-NNCIIYD6.js +2 -0
- package/dist/bundle/chunks/chunk-O6JSP6YG.js +6 -0
- package/dist/bundle/chunks/chunk-OFST7FDG.js +2 -0
- package/dist/bundle/chunks/chunk-SPAUY3RD.js +12 -0
- package/dist/bundle/chunks/chunk-U5XE4RWR.js +2 -0
- package/dist/bundle/chunks/chunk-UZWP3NHW.js +2 -0
- package/dist/bundle/chunks/chunk-V5ANFNKF.js +11 -0
- package/dist/bundle/chunks/chunk-VJJ6J35N.js +20 -0
- package/dist/bundle/chunks/chunk-XIRAUXOE.js +58 -0
- package/dist/bundle/chunks/chunk-ZW7FVRHT.js +31 -0
- package/dist/bundle/chunks/cli-6ZTWO6GL.js +51 -0
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-6E2UM7IG.js +2 -0
- package/dist/bundle/chunks/codemode-worker.js +478 -0
- package/dist/bundle/chunks/dist-DKI7Q6GY.js +13 -0
- package/dist/bundle/chunks/easter-egg-3d-FDCGDUF3.js +2 -0
- package/dist/bundle/chunks/execute-VSDU5VSN.js +499 -0
- package/dist/bundle/chunks/github-copilot.js +2 -0
- package/dist/bundle/chunks/google-generative-ai-CSWR3ORZ.js +2 -0
- package/dist/bundle/chunks/google-vertex-QIDRFOFB.js +2 -0
- package/dist/bundle/chunks/image-resize-worker.js +2 -0
- package/dist/bundle/chunks/jiti-loader-BXVX3Y2R.js +21 -0
- package/dist/bundle/chunks/jiti-static-loader-NNBCFAO5.js +2 -0
- package/dist/bundle/chunks/kimi-coding.js +2 -0
- package/dist/bundle/chunks/knightcode-messages-3GNOTMSI.js +8 -0
- package/dist/bundle/chunks/lib-IHWMWJDR.js +9 -0
- package/dist/bundle/chunks/llama-cpp-classify-HRPRKOZA.js +22 -0
- package/dist/bundle/chunks/meta.js +2 -0
- package/dist/bundle/chunks/mistral-conversations-46TK5OBA.js +5 -0
- package/dist/bundle/chunks/multipart-parser-VTTMF2EO.js +3 -0
- package/dist/bundle/chunks/node-7S3GFMOZ.js +16 -0
- package/dist/bundle/chunks/node-MAEICQNS.js +2 -0
- package/dist/bundle/chunks/openai-chatgpt.js +101 -0
- package/dist/bundle/chunks/openai-codex-responses-IT7VEKUU.js +10 -0
- package/dist/bundle/chunks/openai-codex.js +101 -0
- package/dist/bundle/chunks/openai-completions-LOKIW33V.js +7 -0
- package/dist/bundle/chunks/openai-decisions-4F3LWHMG.js +5 -0
- package/dist/bundle/chunks/openai-responses-OK36GJXP.js +3 -0
- package/dist/bundle/chunks/openrouter-images-ZI7LLZ4Y.js +2 -0
- package/dist/bundle/chunks/openrouter.js +101 -0
- package/dist/bundle/chunks/radius.js +101 -0
- package/dist/bundle/chunks/runtime-RMPIV5AR.js +2 -0
- package/dist/bundle/chunks/src-ETRMT73D.js +4 -0
- package/dist/bundle/chunks/typesafe-system-one-J2CJBWEH.js +2 -0
- package/dist/bundle/chunks/virtual-modules-EGJP3AJA.js +2 -0
- package/dist/bundle/chunks/xai.js +2 -0
- package/dist/bundle/cli-runtime.js +3 -0
- package/dist/bundle/cli.js +5 -0
- package/dist/bundle/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/dist/bundle/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/dist/bundle/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
- package/dist/bundle/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
- package/dist/bundle/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
- package/dist/bundle/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
- package/dist/core/export-html/template.css +1015 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1929 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +78 -0
- package/dist/modes/interactive/theme/dark.json +74 -0
- package/dist/modes/interactive/theme/light.json +74 -0
- package/dist/modes/interactive/theme/system-theme.ts +579 -0
- package/dist/modes/interactive/theme/theme-controller.ts +253 -0
- package/dist/modes/interactive/theme/theme-schema.ts +145 -0
- package/dist/modes/interactive/theme/theme-tokens.ts +145 -0
- package/dist/modes/interactive/theme/theme.ts +1076 -0
- package/docs/app-server.md +479 -0
- package/docs/app-server.schema.json +8128 -0
- package/docs/cli-integration.md +106 -0
- package/docs/cli.md +393 -0
- package/docs/codemode.md +230 -0
- package/docs/compaction.md +463 -0
- package/docs/configuration.md +48 -0
- package/docs/containerization.md +143 -0
- package/docs/custom-provider.md +173 -0
- package/docs/desktop.md +73 -0
- package/docs/docs.json +236 -0
- package/docs/environment-variables.md +138 -0
- package/docs/extensions.md +314 -0
- package/docs/how-knightcode-works.md +49 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/index.md +39 -0
- package/docs/json.md +226 -0
- package/docs/keybindings.md +197 -0
- package/docs/llama-cpp.md +121 -0
- package/docs/mcp.md +272 -0
- package/docs/message-types.md +279 -0
- package/docs/models-configuration.md +187 -0
- package/docs/models.md +221 -0
- package/docs/nvidia-rtx-llama-cpp.md +96 -0
- package/docs/packages.md +129 -0
- package/docs/plan-mode.md +121 -0
- package/docs/prompt-templates.md +59 -0
- package/docs/providers.md +282 -0
- package/docs/quickstart.md +128 -0
- package/docs/remote.md +87 -0
- package/docs/rpc-commands.md +860 -0
- package/docs/rpc-extension-ui.md +214 -0
- package/docs/rpc.md +193 -0
- package/docs/sdk.md +197 -0
- package/docs/security.md +99 -0
- package/docs/session-format.md +358 -0
- package/docs/sessions.md +135 -0
- package/docs/settings.md +220 -0
- package/docs/shell-aliases.md +93 -0
- package/docs/skills.md +93 -0
- package/docs/slash-commands.md +78 -0
- package/docs/terminal-setup.md +242 -0
- package/docs/termux.md +117 -0
- package/docs/themes.md +140 -0
- package/docs/tmux.md +55 -0
- package/docs/tui.md +125 -0
- package/docs/usage.md +167 -0
- package/docs/virtual-models.md +114 -0
- package/docs/windows.md +67 -0
- package/examples/README.md +36 -0
- package/examples/extensions/README.md +214 -0
- package/examples/extensions/auto-commit-on-exit.ts +55 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/border-status-editor.ts +151 -0
- package/examples/extensions/built-in-tool-renderer.ts +225 -0
- package/examples/extensions/claude-rules.ts +89 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +60 -0
- package/examples/extensions/custom-compaction.ts +118 -0
- package/examples/extensions/custom-footer.ts +66 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +617 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +399 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/debug-provider.ts +90 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_knightcode.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +55 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +75 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/entry-renderer.ts +41 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/github-issue-autocomplete.ts +185 -0
- package/examples/extensions/gondolin/index.ts +531 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +190 -0
- package/examples/extensions/hello.ts +26 -0
- package/examples/extensions/hidden-thinking-label.ts +53 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/jev-router.ts +113 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +353 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +57 -0
- package/examples/extensions/overlay-qa-tests.ts +1450 -0
- package/examples/extensions/overlay-test.ts +153 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +66 -0
- package/examples/extensions/plan-mode/index.ts +387 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +436 -0
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +49 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +18 -0
- package/examples/extensions/qna.ts +118 -0
- package/examples/extensions/question.ts +278 -0
- package/examples/extensions/questionnaire.ts +440 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +118 -0
- package/examples/extensions/sandbox/index.ts +321 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +32 -0
- package/examples/extensions/structured-output.ts +65 -0
- package/examples/extensions/subagent/README.md +177 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +157 -0
- package/examples/extensions/subagent/index.ts +1010 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +199 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/tic-tac-toe.ts +1004 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +294 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +146 -0
- package/examples/extensions/trigger-compact.ts +50 -0
- package/examples/extensions/truncated-tool.ts +195 -0
- package/examples/extensions/widget-placement.ts +9 -0
- package/examples/extensions/with-deps/index.ts +32 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/extensions/working-indicator.ts +121 -0
- package/examples/extensions/working-message-test.ts +25 -0
- package/examples/rpc-client.ts +35 -0
- package/examples/rpc-extension-ui.ts +661 -0
- package/examples/sdk/01-minimal.ts +26 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +70 -0
- package/examples/sdk/04-skills.ts +55 -0
- package/examples/sdk/05-tools.ts +48 -0
- package/examples/sdk/06-extensions.ts +94 -0
- package/examples/sdk/07-context-files.ts +42 -0
- package/examples/sdk/08-prompt-templates.ts +51 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
- package/examples/sdk/10-settings.ts +53 -0
- package/examples/sdk/11-sessions.ts +52 -0
- package/examples/sdk/12-full-control.ts +74 -0
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/14-codemode-mcp.ts +61 -0
- package/examples/sdk/README.md +141 -0
- package/package.json +15 -15
- package/bin/knightcode +0 -62
package/docs/security.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Run KnightCode safely
|
|
2
|
+
|
|
3
|
+
Treat model-generated commands and code as untrusted. KnightCode can read, change, and execute files with the permissions of the account that started it, and it does not ask for approval before every tool call. Extensions, package installers, language servers, and other child processes run with those same permissions unless an operating-system or virtualization boundary restricts them.
|
|
4
|
+
|
|
5
|
+
Files, comments, instructions, command output, and model responses can steer the model through prompt injection. Project trust controls which project resources load at startup, but it does not make that content or the resulting actions safe.
|
|
6
|
+
|
|
7
|
+
Safety comes from limiting the files, credentials, processes, and network services KnightCode can access and affect if a generated action is wrong or hostile. Watching the transcript, using project trust, and reviewing changes do not create a security boundary.
|
|
8
|
+
|
|
9
|
+
## Choose how to run KnightCode
|
|
10
|
+
|
|
11
|
+
Different ways of running KnightCode place different limits on what generated commands can access:
|
|
12
|
+
|
|
13
|
+
| How KnightCode runs | What remains protected |
|
|
14
|
+
|---|---|
|
|
15
|
+
| Directly, with the permissions of its operating-system user | Anything that user cannot access. A dedicated user account can narrow those permissions, but KnightCode still shares the operating system and network with other users. |
|
|
16
|
+
| Entirely inside a container, virtual machine, or sandbox | Host files and processes that you do not expose to the environment. Credentials and network services remain accessible if you make them available inside it. This is usually the strongest practical option. |
|
|
17
|
+
| Outside the isolated environment, with only its built-in tools running inside | Host resources are protected from actions performed through those tools. KnightCode itself and other extensions remain outside the boundary, so this is a narrower form of isolation. |
|
|
18
|
+
|
|
19
|
+
The working folder controls resource discovery and the default location for tools, but it does not prevent commands from accessing other paths available to the KnightCode process.
|
|
20
|
+
|
|
21
|
+
Whichever option you choose, only provide the files and services required for the task. Keep credentials outside the environment where possible, or use narrowly scoped, short-lived credentials. Restrict network access when commands do not need it.
|
|
22
|
+
|
|
23
|
+
For setup instructions and the limitations of each isolation method, see [Run KnightCode in an isolated environment](containerization.md).
|
|
24
|
+
|
|
25
|
+
<a id="project-trust"></a>
|
|
26
|
+
|
|
27
|
+
## Understand project trust
|
|
28
|
+
|
|
29
|
+
Project trust controls whether KnightCode loads most settings and resources supplied by a working folder. It prevents a folder from silently loading executable extensions before you approve it.
|
|
30
|
+
|
|
31
|
+
Project trust is not a complete startup boundary. KnightCode reads the project `sessionDir` setting while selecting or creating a session, before it resolves project trust. Declining trust prevents the remaining project settings and protected resources from loading, but it cannot undo that initial session-directory lookup.
|
|
32
|
+
|
|
33
|
+
Project trust does not limit what tool calls can access or affect. After KnightCode starts, enabled tools still use the operating-system permissions of the KnightCode process. Instructions and other content in the folder can also influence the model.
|
|
34
|
+
|
|
35
|
+
### Resources protected by project trust
|
|
36
|
+
|
|
37
|
+
KnightCode requires a project-trust decision when it finds any of these resources from the current working directory:
|
|
38
|
+
|
|
39
|
+
- `.knightcode/settings.json`
|
|
40
|
+
- `.knightcode/mcp.json`
|
|
41
|
+
- `.knightcode/extensions`, `.knightcode/skills`, `.knightcode/prompts`, or `.knightcode/themes`
|
|
42
|
+
- `.knightcode/SYSTEM.md` or `.knightcode/APPEND_SYSTEM.md`
|
|
43
|
+
- project `.agents/skills` in the current directory or an ancestor directory
|
|
44
|
+
|
|
45
|
+
A bare `.knightcode` directory does not require project trust.
|
|
46
|
+
|
|
47
|
+
Granting project trust allows KnightCode to load:
|
|
48
|
+
|
|
49
|
+
- project settings
|
|
50
|
+
- project MCP servers from `.knightcode/mcp.json`
|
|
51
|
+
- extensions, skills, prompt templates, themes, and system-prompt files under `.knightcode`
|
|
52
|
+
- missing packages configured through project settings
|
|
53
|
+
- project-local and project-package extensions
|
|
54
|
+
|
|
55
|
+
Declining project trust skips those protected resources, except for the initial `sessionDir` lookup described above.
|
|
56
|
+
|
|
57
|
+
Context files such as `AGENTS.override.md`, `AGENTS.md`, and `CLAUDE.md` load regardless of project trust unless you disable context loading. Treat instructions in a folder as untrusted input even when you decline project trust.
|
|
58
|
+
|
|
59
|
+
### How KnightCode chooses a trust decision
|
|
60
|
+
|
|
61
|
+
A command-line `--approve` or `--no-approve` override applies first. When protected resources exist and there is no command-line override:
|
|
62
|
+
|
|
63
|
+
1. User-level and command-line extensions can handle the `project_trust` event. The first extension that returns yes or no owns the decision.
|
|
64
|
+
2. If no extension decides, KnightCode looks for a saved decision for the current directory or one of its parents. The closest decision applies.
|
|
65
|
+
3. If no saved decision applies, KnightCode follows the global `defaultProjectTrust` setting, whose default is `"ask"`.
|
|
66
|
+
|
|
67
|
+
Saved decisions use canonical directory paths and live in:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
~/.knightcode/agent/trust.json
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use `/trust` to save a decision for future KnightCode processes.
|
|
74
|
+
|
|
75
|
+
### Project trust without an interactive prompt
|
|
76
|
+
|
|
77
|
+
Print, JSON, and RPC modes cannot show the built-in trust prompt. If no command-line override, extension, or saved decision applies:
|
|
78
|
+
|
|
79
|
+
- `defaultProjectTrust: "always"` loads protected project resources.
|
|
80
|
+
- `defaultProjectTrust: "ask"` or `"never"` skips them.
|
|
81
|
+
|
|
82
|
+
Use `--approve` or `--no-approve` when an automated run needs an explicit one-time decision.
|
|
83
|
+
|
|
84
|
+
## Reduce impact and improve recovery
|
|
85
|
+
|
|
86
|
+
These practices do not replace isolation, but they reduce exposure or make recovery easier:
|
|
87
|
+
|
|
88
|
+
- Give KnightCode access only to files and services required for the task.
|
|
89
|
+
- Use snapshots, backups, or version control before substantial changes.
|
|
90
|
+
- Review extensions and packages before loading them. Extensions execute inside the KnightCode process.
|
|
91
|
+
- Prefer narrowly scoped, short-lived credentials.
|
|
92
|
+
- Review diffs and generated output before applying results to another system.
|
|
93
|
+
- Review sessions before exporting or sharing them. They can contain prompts, tool arguments, command output, file contents, and credentials exposed during the conversation.
|
|
94
|
+
|
|
95
|
+
## Report a security issue
|
|
96
|
+
|
|
97
|
+
Follow the repository [Security Policy](https://github.com/KnightCodeAI/knightcode/blob/main/SECURITY.md). Do not open a public issue for a security-sensitive report.
|
|
98
|
+
|
|
99
|
+
Expected local-agent behavior, prompt injection from untrusted content, lack of a built-in sandbox, and behavior from user-installed extensions or skills are generally outside the security boundary unless the report demonstrates a privilege-boundary bypass or access that the local user did not already have.
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Session File Format
|
|
2
|
+
|
|
3
|
+
Sessions are stored as JSONL (JSON Lines) files. Each line is a JSON object with a `type` field. Session entries form a tree structure via `id`/`parentId` fields, enabling in-place branching without creating new files.
|
|
4
|
+
|
|
5
|
+
For programmatic creation, persistence, and tree navigation, see the [`SessionManager` API](sdk.md#sessionmanager-api).
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## File Location
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
~/.knightcode/agent/sessions/--<path>--/<timestamp>_<session-id>.jsonl
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
By default, `<session-id>` is a UUID. Callers can supply a custom ID through the SDK or `--session-id`. For `<path>`, KnightCode removes the leading path separator and replaces `/`, `\\`, and `:` with `-`.
|
|
15
|
+
|
|
16
|
+
## Deleting Sessions
|
|
17
|
+
|
|
18
|
+
Sessions can be removed by deleting their `.jsonl` files under `~/.knightcode/agent/sessions/`.
|
|
19
|
+
|
|
20
|
+
KnightCode also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, knightcode uses the `trash` CLI to avoid permanent deletion.
|
|
21
|
+
|
|
22
|
+
## Session Version
|
|
23
|
+
|
|
24
|
+
Sessions have a version field in the header:
|
|
25
|
+
|
|
26
|
+
- **Version 1**: Linear entry sequence (legacy, auto-migrated on load)
|
|
27
|
+
- **Version 2**: Tree structure with `id`/`parentId` linking
|
|
28
|
+
- **Version 3**: Renamed `hookMessage` role to `custom` (extensions unification)
|
|
29
|
+
|
|
30
|
+
Existing sessions are automatically migrated to the current version (v3) when
|
|
31
|
+
opened by an owning manager. Read-only discovery, history, export, and fork-source
|
|
32
|
+
reads do not rewrite or migrate the source file. See [ownership](sessions.md#session-ownership).
|
|
33
|
+
|
|
34
|
+
## Source Files
|
|
35
|
+
|
|
36
|
+
Source on GitHub ([knightcode](https://github.com/KnightCodeAI/knightcode)):
|
|
37
|
+
- [`packages/cli/src/core/session-manager.ts`](https://github.com/KnightCodeAI/knightcode/blob/main/packages/cli/src/core/session-manager.ts) - Session entry types and SessionManager
|
|
38
|
+
- [Message Types](message-types.md) - Shared message and content-block reference
|
|
39
|
+
- [`packages/cli/src/core/messages.ts`](https://github.com/KnightCodeAI/knightcode/blob/main/packages/cli/src/core/messages.ts) - Extended message types
|
|
40
|
+
- [`packages/ai/src/types.ts`](https://github.com/KnightCodeAI/knightcode/blob/main/packages/ai/src/types.ts) - Base message and content-block types
|
|
41
|
+
- [`packages/agent/src/types.ts`](https://github.com/KnightCodeAI/knightcode/blob/main/packages/agent/src/types.ts) - Extensible `AgentMessage` union
|
|
42
|
+
|
|
43
|
+
For TypeScript definitions in your project, inspect `node_modules/@knightcodeai/cli/dist/` and `node_modules/@knightcode/ai/dist/`.
|
|
44
|
+
|
|
45
|
+
## Messages
|
|
46
|
+
|
|
47
|
+
A `message` entry stores an [`AgentMessage`](message-types.md). Message content blocks, roles, usage, and message timestamps are defined in [Message Types](message-types.md).
|
|
48
|
+
|
|
49
|
+
Session entry timestamps are ISO 8601 strings. The nested message timestamp is a Unix timestamp in milliseconds.
|
|
50
|
+
|
|
51
|
+
## Entry Base
|
|
52
|
+
|
|
53
|
+
All entries (except `SessionHeader`) extend `SessionEntryBase`:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
interface SessionEntryBase {
|
|
57
|
+
type: string;
|
|
58
|
+
id: string; // Usually an 8-char hex ID; may fall back to a full UUID
|
|
59
|
+
parentId: string | null; // Parent entry ID (null for a root entry)
|
|
60
|
+
timestamp: string; // ISO timestamp
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Entry Types
|
|
65
|
+
|
|
66
|
+
### SessionHeader
|
|
67
|
+
|
|
68
|
+
First line of the file. Metadata only, not part of the tree (no `id`/`parentId`).
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{"type":"session","version":3,"id":"uuid","timestamp":"2024-12-03T14:00:00.000Z","cwd":"/path/to/project"}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
For sessions with a parent (created via `/fork`, `/clone`, or `newSession({ parentSession })`):
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{"type":"session","version":3,"id":"uuid","timestamp":"2024-12-03T14:00:00.000Z","cwd":"/path/to/project","parentSession":"/path/to/original/session.jsonl"}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### SessionMessageEntry
|
|
81
|
+
|
|
82
|
+
A message in the conversation. The `message` field contains an `AgentMessage`. System messages carry the prompt and tool loadout: the first request of a session persists one with every prompt section and tool declaration, and later changes persist as system messages that patch `sections` by name (`null` removes one) and list `toolsAdded`/`toolsRemoved`. Replaying them in order yields the current prompt and tools; there is no separate prompt state entry.
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{"type":"message","id":"a0b1c2d3","parentId":null,"timestamp":"2024-12-03T14:00:00.000Z","message":{"role":"system","content":"","sections":{"preamble":"You are an expert coding assistant...","tools":"<tools>\n- read: ...\n</tools>","cwd":"/project"},"toolsAdded":[{"name":"read","description":"...","parameters":{}}],"timestamp":1733234400000}}
|
|
86
|
+
{"type":"message","id":"d4e5f6g7","parentId":"c3d4e5f6","timestamp":"2024-12-03T14:04:00.000Z","message":{"role":"system","content":"","sections":{"skills":"<skills>...</skills>"},"toolsRemoved":[{"name":"write"}],"timestamp":1733234640000}}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Sessions created before system messages existed have no leading system message; the first request declares the current prompt as a later system message, which replays the same way.
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{"type":"message","id":"a1b2c3d4","parentId":"prev1234","timestamp":"2024-12-03T14:00:01.000Z","message":{"role":"user","content":"Hello","timestamp":1733234401000}}
|
|
93
|
+
{"type":"message","id":"b2c3d4e5","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:00:02.000Z","message":{"role":"assistant","content":[{"type":"text","text":"Hi!"}],"api":"anthropic-messages","provider":"anthropic","model":"claude-sonnet-4-5","usage":{...},"stopReason":"stop","timestamp":1733234402000}}
|
|
94
|
+
{"type":"message","id":"c3d4e5f6","parentId":"b2c3d4e5","timestamp":"2024-12-03T14:00:03.000Z","message":{"role":"toolResult","toolCallId":"call_123","toolName":"bash","content":[{"type":"text","text":"output"}],"isError":false,"timestamp":1733234403000}}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Assistant messages name the model that produced them. Newer messages also record `thinkingLevel`, the KnightCode thinking level requested for that response.
|
|
98
|
+
|
|
99
|
+
Assistant `durationMs`, when present, measures the reply from its numeric
|
|
100
|
+
`timestamp`; the app server derives final text/reasoning completion times from
|
|
101
|
+
these fields.
|
|
102
|
+
|
|
103
|
+
### ModelChangeEntry
|
|
104
|
+
|
|
105
|
+
Emitted when the user switches models mid-session. The latest entry is the selected model, which may be a [virtual model](virtual-models.md); assistant messages then name the physical model that answered.
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{"type":"model_change","id":"d4e5f6g7","parentId":"c3d4e5f6","timestamp":"2024-12-03T14:05:00.000Z","provider":"openai","modelId":"gpt-4o"}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### ThinkingLevelChangeEntry
|
|
112
|
+
|
|
113
|
+
Emitted when the user changes the thinking/reasoning level.
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{"type":"thinking_level_change","id":"e5f6g7h8","parentId":"d4e5f6g7","timestamp":"2024-12-03T14:06:00.000Z","thinkingLevel":"high"}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### UsageEntry
|
|
120
|
+
|
|
121
|
+
Records model-attributed usage that is not an assistant message and does not participate in LLM context. `kind` is an arbitrary string identifying the operation; for example, cache warming uses `"cache_warm"`.
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{"type":"usage","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:08:00.000Z","kind":"cache_warm","provider":"anthropic","model":"claude-sonnet-4-5","usage":{"input":0,"output":0,"cacheRead":50000,"cacheWrite":0,"totalTokens":50000,"cost":{"input":0,"output":0,"cacheRead":0.015,"cacheWrite":0,"total":0.015}}}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Usage entries contribute to session token and cost totals. KnightCode hides them from the conversation tree. Consumers should treat unknown `kind` values as normal usage rather than rejecting them.
|
|
128
|
+
|
|
129
|
+
### CompactionEntry
|
|
130
|
+
|
|
131
|
+
Created when context is compacted. Stores a summary of earlier messages and a complete system prompt/tool checkpoint.
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{"type":"compaction","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:10:00.000Z","summary":"User discussed X, Y, Z...","firstKeptEntryId":"c3d4e5f6","tokensBefore":50000,"systemMessage":{"role":"system","content":"You are a coding assistant.","toolsAdded":[],"timestamp":1733235000000}}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`firstKeptEntryId` is required. It identifies the first entry retained from before the compaction entry. When rebuilding context, KnightCode replaces older summarized entries with the compaction summary and keeps the range beginning at this entry. A retain-none compaction stores its own ID in this field, so no preceding entries are retained.
|
|
138
|
+
|
|
139
|
+
Optional fields:
|
|
140
|
+
- `systemMessage`: The replayed prompt sections and tool declarations at the compaction boundary; it becomes the leading system message of the compacted context, and system messages among the kept entries are dropped in its favor. It is absent on older session entries.
|
|
141
|
+
- `usage`: LLM usage from generating the summary; included in session token and cost totals
|
|
142
|
+
- `details`: Implementation-specific data (e.g., `{ readFiles: string[], modifiedFiles: string[] }` for default, or custom data for extensions)
|
|
143
|
+
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if knightcode-generated (legacy field name)
|
|
144
|
+
|
|
145
|
+
### ContextEditEntry
|
|
146
|
+
|
|
147
|
+
Append-only edit of one earlier context-producing entry. It changes only future model context; the target entry and its metadata remain unchanged in raw history, UI, exports, and session accounting.
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{"type":"context_edit","id":"g6h7i8j9","parentId":"f6g7h8i9","timestamp":"2024-12-03T14:11:00.000Z","targetId":"c3d4e5f6","replacement":null}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Targets may be user, assistant, tool-result, or custom-message entries. `replacement: null` omits the target from model context. A non-null `replacement` replaces only the target message content. String replacements for assistant and tool-result entries are normalized to one text block because those roles require content arrays. If several edits target the same entry, the latest edit on the active branch wins. Edits are branch-relative: navigating to a point before the edit reveals the target's original contribution again.
|
|
154
|
+
|
|
155
|
+
### BranchSummaryEntry
|
|
156
|
+
|
|
157
|
+
Created when switching branches via `/tree` with an LLM generated summary of the left branch up to the common ancestor. Captures context from the abandoned path.
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{"type":"branch_summary","id":"g7h8i9j0","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:15:00.000Z","fromId":"f6g7h8i9","summary":"Branch explored approach A..."}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`parentId` is the entry from which the new branch continues. `fromId` is the previous leaf whose abandoned path was summarized.
|
|
164
|
+
|
|
165
|
+
Optional fields:
|
|
166
|
+
- `usage`: LLM usage from generating the summary; included in session token and cost totals
|
|
167
|
+
- `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default, or custom data for extensions
|
|
168
|
+
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if knightcode-generated (legacy field name)
|
|
169
|
+
|
|
170
|
+
### CustomEntry
|
|
171
|
+
|
|
172
|
+
Extension state persistence. Does NOT participate in LLM context.
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{"type":"custom","id":"h8i9j0k1","parentId":"g7h8i9j0","timestamp":"2024-12-03T14:20:00.000Z","customType":"my-extension","data":{"count":42}}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Use `customType` to identify your extension's entries on reload. Interactive mode can render custom entries via `knightcode.registerEntryRenderer(customType, renderer)`, but they still do not participate in LLM context.
|
|
179
|
+
|
|
180
|
+
KnightCode stores [virtual model](virtual-models.md) router state as custom entries with `customType` `knightcode.virtual-model-state` and `data` `{ provider, modelId, state }`.
|
|
181
|
+
|
|
182
|
+
#### Turn boundaries
|
|
183
|
+
|
|
184
|
+
The built-in turn-marker extension writes `knightcode.turn` at the first
|
|
185
|
+
`agent_start` of a run and `knightcode.turnEnd` at `agent_settled`:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{"type":"custom","id":"turn1234","parentId":"prev1234","timestamp":"2026-10-11T14:00:00.000Z","customType":"knightcode.turn"}
|
|
189
|
+
{"type":"custom","id":"end12345","parentId":"reply123","timestamp":"2026-10-11T14:00:05.000Z","customType":"knightcode.turnEnd","data":{"status":"completed"}}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
End status is `completed`, `interrupted`, or `failed`, with optional
|
|
193
|
+
`error: {message, kind}`. Kinds are `auth`, `rateLimit`, `contextOverflow`,
|
|
194
|
+
`network`, `provider`, and `other`, classified from the error text. For example:
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{"type":"custom","id":"end54321","parentId":"reply123","timestamp":"2026-10-11T14:00:05.000Z","customType":"knightcode.turnEnd","data":{"status":"failed","error":{"message":"Too many requests","kind":"rateLimit"}}}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
An end entry whose `error` is a plain string reads as
|
|
201
|
+
`{message: <string>, kind: "other"}`. The marker/end-entry timestamps define the app server's final turn
|
|
202
|
+
`startedAt`/`completedAt` in Unix milliseconds.
|
|
203
|
+
|
|
204
|
+
The marker's entry ID is the [app-server](app-server.md) turn ID. Retries,
|
|
205
|
+
automatic recovery, and steering before settlement share one boundary. A later independent prompt starts another turn. A marker without a
|
|
206
|
+
valid end entry reads as `interrupted`, including after a crash.
|
|
207
|
+
|
|
208
|
+
Item IDs are deterministic ordinals within the turn, such as
|
|
209
|
+
`turn1234:user:0`, except tool calls, which retain their original call IDs.
|
|
210
|
+
Assistant text/thinking ordinals follow finalized content order; nested calls
|
|
211
|
+
are live-only. Unmarked legacy history is grouped by user-message boundaries
|
|
212
|
+
and uses those entry IDs as turn IDs. Turn markers are custom entries, not a new
|
|
213
|
+
session-file version, and never enter model context.
|
|
214
|
+
|
|
215
|
+
App-server approval modes use `customType: "knightcode.approvalMode"` with `data`
|
|
216
|
+
of `ask`, `autoEdit`, or `fullAccess`. The latest value on the branch wins;
|
|
217
|
+
malformed stored data restores as `ask` rather than widening access.
|
|
218
|
+
|
|
219
|
+
#### Plan mode snapshots
|
|
220
|
+
|
|
221
|
+
The built-in [plan mode](plan-mode.md) writes full snapshots with
|
|
222
|
+
`customType: "plan-mode"`:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{"type":"custom","id":"plan1234","parentId":"prev1234","timestamp":"2024-12-03T14:20:00.000Z","customType":"plan-mode","data":{"mode":"off","draft":{"revision":2,"markdown":"# Changes\n..."},"approved":2}}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`mode` is `off` or `planning`; `draft` and `approved` are optional. An approved
|
|
229
|
+
revision must equal the draft revision and exist only while off. The latest
|
|
230
|
+
snapshot on the selected branch wins, including entries omitted from model
|
|
231
|
+
context by compaction. Exit and approval retain the draft; entry and submission
|
|
232
|
+
clear approval. Malformed state refuses restoration rather than dropping the
|
|
233
|
+
restrictions. No session version change is needed.
|
|
234
|
+
|
|
235
|
+
### CustomMessageEntry
|
|
236
|
+
|
|
237
|
+
Extension-injected messages that DO participate in LLM context.
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{"type":"custom_message","id":"i9j0k1l2","parentId":"h8i9j0k1","timestamp":"2024-12-03T14:25:00.000Z","customType":"my-extension","content":"Injected context...","display":true}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Fields:
|
|
244
|
+
- `content`: String or `(TextContent | ImageContent)[]` (same as UserMessage)
|
|
245
|
+
- `display`: `true` = show in TUI with distinct styling, `false` = hidden
|
|
246
|
+
- `details`: Optional extension-specific metadata (not sent to LLM)
|
|
247
|
+
|
|
248
|
+
Plan-mode messages use `customType: "plan-mode"`, `display: false`, and
|
|
249
|
+
`details.kind` of `instructions`, `reminder`, `exit`, or `recovery`. Recovery
|
|
250
|
+
also stores `id` (the compaction entry ID), `revision` when present, and `status`
|
|
251
|
+
(`planning` or `approved`). Its content is frozen when appended, so later
|
|
252
|
+
revisions cannot change earlier request content.
|
|
253
|
+
|
|
254
|
+
### LabelEntry
|
|
255
|
+
|
|
256
|
+
User-defined bookmark/marker on an entry.
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{"type":"label","id":"j0k1l2m3","parentId":"i9j0k1l2","timestamp":"2024-12-03T14:30:00.000Z","targetId":"a1b2c3d4","label":"checkpoint-1"}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Set `label` to `undefined` to clear a label.
|
|
263
|
+
|
|
264
|
+
### SessionInfoEntry
|
|
265
|
+
|
|
266
|
+
Session metadata (e.g., user-defined display name). Set via `/name`, `--name` / `-n`, or `knightcode.setSessionName()` in extensions.
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{"type":"session_info","id":"k1l2m3n4","parentId":"j0k1l2m3","timestamp":"2024-12-03T14:35:00.000Z","name":"Refactor auth module"}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The session name is displayed in the session selector (`/resume`) instead of the first message when set.
|
|
273
|
+
|
|
274
|
+
## Tree Structure
|
|
275
|
+
|
|
276
|
+
Entries normally form one tree, but navigation APIs can create multiple roots:
|
|
277
|
+
- A root entry has `parentId: null`; the first entry is initially the root
|
|
278
|
+
- Each non-root entry points to its parent via `parentId`
|
|
279
|
+
- Branching creates new children from an earlier entry
|
|
280
|
+
- The "leaf" is the current position in the tree
|
|
281
|
+
- Calling `resetLeaf()` or `branchWithSummary(null, ...)` allows a later entry to become another root
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
[user msg] ─── [assistant] ─── [user msg] ─── [assistant] ─┬─ [user msg] ← current leaf
|
|
285
|
+
│
|
|
286
|
+
└─ [branch_summary] ─── [user msg] ← alternate branch
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Context Building
|
|
290
|
+
|
|
291
|
+
`buildContextEntries()` walks from the current leaf to the root, producing the active entry list while honoring compaction:
|
|
292
|
+
|
|
293
|
+
1. Collects all entries on the path
|
|
294
|
+
2. If one or more `CompactionEntry` values are on the path, uses the latest one:
|
|
295
|
+
- Includes the compaction entry first
|
|
296
|
+
- Includes non-system entries from `firstKeptEntryId` up to, but not including, the compaction entry
|
|
297
|
+
- Includes entries after the compaction entry
|
|
298
|
+
3. Preserves non-message entries in the selected range so interactive mode can render them
|
|
299
|
+
|
|
300
|
+
`buildSessionProjection()` then applies the latest `context_edit` for each selected target. It returns the model-visible messages together with their source entries. Omitted targets produce no message; replacements retain the source entry's role and metadata while changing only content. The raw selected entries are not modified.
|
|
301
|
+
|
|
302
|
+
`buildSessionContext()` builds on that projection to produce the message list for the LLM:
|
|
303
|
+
|
|
304
|
+
1. Extracts current model and thinking level settings from the full path
|
|
305
|
+
2. Converts selected entries to messages:
|
|
306
|
+
- `message` -> stored `AgentMessage`
|
|
307
|
+
- `compaction` -> complete system checkpoint followed by `compactionSummary`
|
|
308
|
+
- `branch_summary` -> `branchSummary`
|
|
309
|
+
- `custom_message` -> `CustomMessage`
|
|
310
|
+
- `context_edit` -> no context message of its own
|
|
311
|
+
- `usage` and `custom` -> no context message
|
|
312
|
+
|
|
313
|
+
The compaction summary replaces entries before `firstKeptEntryId`. Pre-compaction system messages are folded into the complete checkpoint rather than replayed from the retained range. Retained non-system entries and all entries after the compaction remain available to the LLM.
|
|
314
|
+
|
|
315
|
+
## Parsing Example
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import { readFileSync } from "fs";
|
|
319
|
+
|
|
320
|
+
const lines = readFileSync("session.jsonl", "utf8").trim().split("\n");
|
|
321
|
+
|
|
322
|
+
for (const line of lines) {
|
|
323
|
+
const entry = JSON.parse(line);
|
|
324
|
+
|
|
325
|
+
switch (entry.type) {
|
|
326
|
+
case "session":
|
|
327
|
+
console.log(`Session v${entry.version ?? 1}: ${entry.id}`);
|
|
328
|
+
break;
|
|
329
|
+
case "message":
|
|
330
|
+
console.log(`[${entry.id}] ${entry.message.role}: ${JSON.stringify(entry.message.content)}`);
|
|
331
|
+
break;
|
|
332
|
+
case "compaction":
|
|
333
|
+
console.log(`[${entry.id}] Compaction: ${entry.tokensBefore} tokens summarized`);
|
|
334
|
+
break;
|
|
335
|
+
case "branch_summary":
|
|
336
|
+
console.log(`[${entry.id}] Branch from ${entry.fromId}`);
|
|
337
|
+
break;
|
|
338
|
+
case "usage":
|
|
339
|
+
console.log(`[${entry.id}] Usage (${entry.kind}): ${entry.usage.totalTokens} tokens`);
|
|
340
|
+
break;
|
|
341
|
+
case "custom":
|
|
342
|
+
console.log(`[${entry.id}] Custom (${entry.customType}): ${JSON.stringify(entry.data)}`);
|
|
343
|
+
break;
|
|
344
|
+
case "custom_message":
|
|
345
|
+
console.log(`[${entry.id}] Extension message (${entry.customType}): ${entry.content}`);
|
|
346
|
+
break;
|
|
347
|
+
case "label":
|
|
348
|
+
console.log(`[${entry.id}] Label "${entry.label}" on ${entry.targetId}`);
|
|
349
|
+
break;
|
|
350
|
+
case "model_change":
|
|
351
|
+
console.log(`[${entry.id}] Model: ${entry.provider}/${entry.modelId}`);
|
|
352
|
+
break;
|
|
353
|
+
case "thinking_level_change":
|
|
354
|
+
console.log(`[${entry.id}] Thinking: ${entry.thinkingLevel}`);
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
```
|
package/docs/sessions.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Sessions and Context
|
|
2
|
+
|
|
3
|
+
KnightCode saves a conversation as a session. The active branch of that session supplies conversation history for the next model request. Use session commands to continue work, explore another branch, or reduce the amount of history sent to the model.
|
|
4
|
+
|
|
5
|
+
## Continue or switch sessions
|
|
6
|
+
|
|
7
|
+
KnightCode saves sessions automatically unless you start it with `--no-session`.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
knightcode --continue
|
|
11
|
+
knightcode --resume
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`--continue` opens the most recent session for the current working directory. `--resume` opens the session picker. In interactive mode, `/resume` opens the same picker and `/new` starts a new session.
|
|
15
|
+
|
|
16
|
+
Use `/name` or `--name` to assign a recognizable session name. Run `/session` to verify the current session file, ID, message count, token usage, and cost.
|
|
17
|
+
|
|
18
|
+
The session picker lets you search, rename, and delete sessions. It can also show paths, change sorting, and limit results to named sessions. See [Keybindings](keybindings.md#sessions) for its shortcuts.
|
|
19
|
+
|
|
20
|
+
## Choose how to branch
|
|
21
|
+
|
|
22
|
+
KnightCode stores entries as a tree, so returning to an earlier point does not erase the branch you leave.
|
|
23
|
+
|
|
24
|
+
| Action | Result | Use it when |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `/tree` | Moves within the current session file | Related alternatives should stay together |
|
|
27
|
+
| `/fork` | Creates a new session from an earlier user message | The alternative should become separate work |
|
|
28
|
+
| `/clone` | Copies the active branch into a new session | You want a separate copy of the current state |
|
|
29
|
+
| `/undo` | Returns to an earlier user message on the current branch, optionally restoring files | You want to take back the last turns |
|
|
30
|
+
|
|
31
|
+
In `/tree`, select a user message to put its text back in the editor. Edit and submit it to create another branch. Selecting an assistant response or another entry continues after that entry with an empty editor.
|
|
32
|
+
|
|
33
|
+
<p align="center"><img src="images/tree-view.png" alt="The /tree view showing a session with two branches, user messages, assistant replies, and tool calls" width="750"></p>
|
|
34
|
+
|
|
35
|
+
Selecting a point while the model is responding cancels that response. Navigation cannot proceed while compaction or another tree navigation is still running; wait for it to finish and retry.
|
|
36
|
+
|
|
37
|
+
When you leave a branch, KnightCode can summarize it and attach that summary to the branch you enter. This preserves relevant work from the abandoned path without including every message from it.
|
|
38
|
+
|
|
39
|
+
For the persisted tree and entry types, see [Session Format](session-format.md).
|
|
40
|
+
|
|
41
|
+
## Undoing with `/undo`
|
|
42
|
+
|
|
43
|
+
`/undo` is the quick form of `/tree` for the common case: pick a user message on the current
|
|
44
|
+
branch and go back to it. It lists only user messages, newest at the bottom, with the time
|
|
45
|
+
and how many files an undo to that point would restore. Enter goes back; the turns after the
|
|
46
|
+
chosen message are left as an abandoned branch (still reachable through `/tree`) and the
|
|
47
|
+
message text returns to the editor for editing and resubmitting. `/undo` never summarizes the
|
|
48
|
+
branch it leaves.
|
|
49
|
+
|
|
50
|
+
### File Restore
|
|
51
|
+
|
|
52
|
+
Before `edit` or `write` changes a file, KnightCode copies the original into
|
|
53
|
+
`~/.knightcode/agent/file-history/<session id>/`, once per file per user turn. When you go
|
|
54
|
+
back past a turn that changed files, through `/undo`, `/tree`, or double-Escape, you are asked:
|
|
55
|
+
|
|
56
|
+
- **Conversation only**: files stay as they are.
|
|
57
|
+
- **Conversation and N files**: every file the abandoned turns touched is put back to its
|
|
58
|
+
content from before those turns; files they created are deleted.
|
|
59
|
+
|
|
60
|
+
Escape at that prompt cancels the navigation entirely.
|
|
61
|
+
|
|
62
|
+
Limits:
|
|
63
|
+
|
|
64
|
+
- Changes made by shell commands (`bash`, `powershell`) are not tracked. The prompt says so
|
|
65
|
+
when a shell command ran in the abandoned turns.
|
|
66
|
+
- Edits made by subagents or outside KnightCode are not tracked either; a tracked file is
|
|
67
|
+
restored to its backup regardless of who changed it afterwards.
|
|
68
|
+
- If you go back without restoring files and later go back further, only the edits on the
|
|
69
|
+
branch you are on are restored.
|
|
70
|
+
- Jumping sideways to another branch with `/tree` restores to the fork point; edits on the
|
|
71
|
+
target branch are not re-applied.
|
|
72
|
+
|
|
73
|
+
Backups older than 30 days are removed at startup. Set `KNIGHTCODE_DISABLE_FILE_CHECKPOINTS=1`
|
|
74
|
+
to turn file tracking off; `/undo` then rewinds the conversation only.
|
|
75
|
+
|
|
76
|
+
## Manage conversation context
|
|
77
|
+
|
|
78
|
+
The model receives the active branch, not every branch in the session file. KnightCode combines that history with the system prompt, discovered context files, available tools, and loaded skill descriptions. [How KnightCode Works](how-knightcode-works.md#context) describes how those inputs are assembled.
|
|
79
|
+
|
|
80
|
+
The footer shows current context usage. When the active context approaches the model's limit, KnightCode normally compacts older history automatically. Compaction adds a summary and keeps recent messages. It does not delete the original session entries.
|
|
81
|
+
|
|
82
|
+
Run `/compact` to compact manually. You can add instructions when the summary should preserve a particular topic or decision. Configure automatic compaction and retained history through [Settings](settings.md#compaction).
|
|
83
|
+
|
|
84
|
+
Compaction can fail if the provider is unavailable or cannot accept the summarization request. Correct the provider problem and run `/compact` again. Disabling automatic compaction does not disable the manual command.
|
|
85
|
+
|
|
86
|
+
See [Compaction Reference](compaction.md) for thresholds, retained boundaries, branch-summary behavior, and extension hooks.
|
|
87
|
+
|
|
88
|
+
## Control session storage
|
|
89
|
+
|
|
90
|
+
By default, KnightCode stores sessions under `~/.knightcode/agent/sessions/`, grouped by working directory. Use `--session-dir`, `KNIGHTCODE_CODING_AGENT_SESSION_DIR`, or the `sessionDir` setting to choose another location. The CLI option has highest precedence.
|
|
91
|
+
|
|
92
|
+
Use `--no-session` for an ephemeral run. An ephemeral session cannot be resumed after KnightCode exits.
|
|
93
|
+
|
|
94
|
+
Use `--session` when you already know the session path or ID. Use `--fork` to create a new session from an existing session before interactive mode starts.
|
|
95
|
+
|
|
96
|
+
## Session ownership
|
|
97
|
+
|
|
98
|
+
Only one KnightCode process may write a persisted session at a time. Opening a
|
|
99
|
+
session locks its canonical file path and canonical parent directory binding.
|
|
100
|
+
Symlink and Windows junction aliases identify the same file; hard-linked
|
|
101
|
+
transcripts are refused because distinct names could bypass ownership. Managers
|
|
102
|
+
inside one process share counted ownership; the final `close()` releases it.
|
|
103
|
+
|
|
104
|
+
If another terminal or the [app server](app-server.md) owns the session, terminal
|
|
105
|
+
startup and `/resume` offer to continue in a fork. Accepting reads the source
|
|
106
|
+
without changing it and creates an independently owned transcript. Declining
|
|
107
|
+
keeps the current interactive session. Non-interactive invocations fail rather
|
|
108
|
+
than waiting for input.
|
|
109
|
+
|
|
110
|
+
Locks are refreshed while live. After a crashed or stalled owner's lock expires,
|
|
111
|
+
another process can take it. The old owner detects this before writes, refuses
|
|
112
|
+
mutations, and never removes the new owner's lock. Read-only listings, exports,
|
|
113
|
+
history reads, and fork-source reads need no ownership and never repair or migrate
|
|
114
|
+
the source. Repairs and migrations happen only when an owner opens it.
|
|
115
|
+
|
|
116
|
+
Closing a persisted manager is final: it remains readable but cannot write again.
|
|
117
|
+
Reopen through a new `SessionManager.open()` after closing or disposing its
|
|
118
|
+
session. See the [SDK ownership example](sdk.md#session-ownership).
|
|
119
|
+
|
|
120
|
+
App-server archive/unarchive operations own both source and destination until
|
|
121
|
+
publication and lookup updates finish. They refuse collisions, publish without
|
|
122
|
+
replacement, and report recovery paths if a move cannot finish; they do not
|
|
123
|
+
silently overwrite another transcript.
|
|
124
|
+
|
|
125
|
+
## Export or share a session
|
|
126
|
+
|
|
127
|
+
Use `/export` to write the current session as HTML or JSONL. Use `/share` to upload it and get a viewer link. By default, KnightCode uses a Radius artifact when Radius authentication is configured; otherwise, it uses a private GitHub gist. Set [`sessionShareDestination`](settings.md#sessions-and-context) to `gist` or `radius` to force one destination.
|
|
128
|
+
|
|
129
|
+
Review exported or shared sessions first. They can contain prompts, model responses, tool arguments, command output, file contents, and extension messages.
|
|
130
|
+
|
|
131
|
+
## Report a bug
|
|
132
|
+
|
|
133
|
+
Run `/bug [description]` to prepare a private report for the KnightCode maintainers. You can include the session transcript, omit it, or ask the current model to summarize the problem. Review any transcript or generated summary because it can contain sensitive conversation data.
|
|
134
|
+
|
|
135
|
+
The report includes environment and provider configuration without credential values, plus recorded error diagnostics. Upload it to the maintainers through `remote.knightcode.dev` or export the same report as a zip to inspect and share yourself. Uploads do not require a login and are always anonymous. If an upload fails, KnightCode offers to export the zip.
|