@knightcodeai/cli 0.17.4 → 0.18.1
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 +1303 -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-253N4337.js +7 -0
- package/dist/bundle/chunks/chunk-2QIKI63P.js +108 -0
- package/dist/bundle/chunks/chunk-3LX7U45C.js +130 -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-AHB7JV5B.js +2 -0
- package/dist/bundle/chunks/chunk-B2FT7RH5.js +2 -0
- package/dist/bundle/chunks/chunk-BPNRVFVQ.js +2 -0
- package/dist/bundle/chunks/chunk-BRKUE2MD.js +2 -0
- package/dist/bundle/chunks/chunk-BXZL5C3N.js +58 -0
- package/dist/bundle/chunks/chunk-DGACKL4S.js +30 -0
- package/dist/bundle/chunks/chunk-DKOURXGU.js +2 -0
- package/dist/bundle/chunks/chunk-DVFCXHT4.js +2 -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-FXS5MU6B.js +2 -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-LROWZ6UF.js +1333 -0
- package/dist/bundle/chunks/chunk-MOALMQWH.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-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-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-ZW7FVRHT.js +31 -0
- package/dist/bundle/chunks/cli-DFJTSQI6.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-7O2AHLAQ.js +2 -0
- package/dist/bundle/chunks/execute-4CLOTQIS.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-IN7ZPKFY.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-7VXI3TVN.js +2 -0
- package/dist/bundle/chunks/xai.js +2 -0
- package/dist/bundle/cli-runtime.js +3 -0
- package/dist/bundle/cli.js +16 -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 +225 -0
- package/docs/desktop.md +73 -0
- package/docs/docs.json +236 -0
- package/docs/environment-variables.md +138 -0
- package/docs/extensions.md +420 -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 +195 -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
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# Extensions
|
|
2
|
+
|
|
3
|
+
Extensions are TypeScript modules that add executable behavior to KnightCode. Use one when a workflow needs tools, commands, event handlers, model providers, session state, or terminal UI rather than instructions alone.
|
|
4
|
+
|
|
5
|
+
An extension runs inside the KnightCode process with the same operating-system permissions. It can inspect prompts, tool calls, files, credentials, and session history, so load extensions only from sources you trust.
|
|
6
|
+
|
|
7
|
+
Typical extensions add an agent tool, protect paths, confirm dangerous commands, react to session events, modify context, expose a command, or display persistent status.
|
|
8
|
+
|
|
9
|
+
<a id="quick-start"></a>
|
|
10
|
+
<a id="writing-an-extension"></a>
|
|
11
|
+
<a id="create-an-extension"></a>
|
|
12
|
+
|
|
13
|
+
## Create and load an extension
|
|
14
|
+
|
|
15
|
+
An extension exports a default factory that receives `ExtensionAPI`. The factory registers capabilities for the current extension runtime.
|
|
16
|
+
|
|
17
|
+
Create `~/.knightcode/agent/extensions/hello.ts`:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import type { ExtensionAPI } from "@knightcodeai/cli";
|
|
21
|
+
|
|
22
|
+
export default function (knightcode: ExtensionAPI) {
|
|
23
|
+
knightcode.registerCommand("hello", {
|
|
24
|
+
description: "Show a greeting",
|
|
25
|
+
handler: async (name, ctx) => {
|
|
26
|
+
ctx.ui.notify(`Hello, ${name || "world"}!`, "info");
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Start KnightCode and run `/hello`. During development, load a file directly:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
knightcode --extension ./hello.ts
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
KnightCode uses `jiti`, so local TypeScript extensions do not need a separate compilation step. Use [KnightCode packages](packages.md) for distributed extensions and dependencies.
|
|
39
|
+
|
|
40
|
+
<a id="extension-locations"></a>
|
|
41
|
+
<a id="available-imports"></a>
|
|
42
|
+
<a id="choose-where-it-loads"></a>
|
|
43
|
+
|
|
44
|
+
## Add it to KnightCode
|
|
45
|
+
|
|
46
|
+
Place the extension in your user or project extensions directory. KnightCode loads direct TypeScript or JavaScript files and subdirectories containing an `index.ts` or `index.js` entry point.
|
|
47
|
+
|
|
48
|
+
Use a single file for a small extension and a directory for a multi-file implementation. Put npm dependencies in a nearby `package.json`. See [Configuration](configuration.md) for conventional locations and [Settings](settings.md#resources) for additional paths.
|
|
49
|
+
|
|
50
|
+
Reload replaces the extension runtime, so code after `await ctx.reload()` must not reuse state from the old runtime. Only personal and explicit command-line extensions can participate in the `project_trust` event that runs before project extensions load.
|
|
51
|
+
|
|
52
|
+
<a id="understand-the-lifecycle"></a>
|
|
53
|
+
|
|
54
|
+
## Understand the runtime lifecycle
|
|
55
|
+
|
|
56
|
+
The factory can be synchronous or asynchronous. KnightCode waits for an asynchronous factory before startup continues, allowing it to fetch configuration or register providers needed during startup.
|
|
57
|
+
|
|
58
|
+
Do not start processes, sockets, watchers, or timers in the factory because some invocations load extensions without starting a session.
|
|
59
|
+
Start long-lived resources from `session_start` or from the command or tool that needs them.
|
|
60
|
+
Close session-scoped resources from an idempotent `session_shutdown` handler.
|
|
61
|
+
|
|
62
|
+
A normal prompt follows this hook sequence:
|
|
63
|
+
|
|
64
|
+
```mermaid
|
|
65
|
+
flowchart TD
|
|
66
|
+
Input["input"] --> Before["before_agent_start"]
|
|
67
|
+
Before --> AgentStart["agent_start"]
|
|
68
|
+
AgentStart --> TurnStart["turn_start"]
|
|
69
|
+
TurnStart --> Context["context"]
|
|
70
|
+
Context --> ContextSystem["context_with_system"]
|
|
71
|
+
ContextSystem --> Headers["before_provider_headers"]
|
|
72
|
+
Headers --> Request["before_provider_request"]
|
|
73
|
+
Request --> Response["after_provider_response"]
|
|
74
|
+
Response --> Stream["provider_stream_event and assistant message events"]
|
|
75
|
+
Stream --> ToolDecision{"Assistant requested tools?"}
|
|
76
|
+
ToolDecision -->|yes| ToolStart["tool_execution_start"]
|
|
77
|
+
ToolStart --> ToolCall["tool_call"]
|
|
78
|
+
ToolCall --> Execute["execute and tool_execution_update"]
|
|
79
|
+
Execute --> ToolResult["tool_result"]
|
|
80
|
+
ToolResult --> ToolEnd["tool_execution_end"]
|
|
81
|
+
ToolEnd --> TurnEnd["turn_end"]
|
|
82
|
+
ToolDecision -->|no| TurnEnd
|
|
83
|
+
TurnEnd --> MoreTurns{"Another model turn required?"}
|
|
84
|
+
MoreTurns -->|yes| TurnStart
|
|
85
|
+
MoreTurns -->|no| AgentEnd["agent_end"]
|
|
86
|
+
AgentEnd --> MoreRuns{"Retry, recovery, compaction retry, or queued work?"}
|
|
87
|
+
MoreRuns -->|yes| AgentStart
|
|
88
|
+
MoreRuns -->|no| BeforeSettle["agent_before_settle"]
|
|
89
|
+
BeforeSettle --> Continue{"Continuation requested?"}
|
|
90
|
+
Continue -->|yes| AgentStart
|
|
91
|
+
Continue -->|no| Settled["agent_settled"]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The lifecycle involves these event groups:
|
|
95
|
+
|
|
96
|
+
| Area | Events |
|
|
97
|
+
|---|---|
|
|
98
|
+
| Input preparation | `input`, `before_agent_start` |
|
|
99
|
+
| Agent run | `agent_start`, `agent_end` |
|
|
100
|
+
| Model turn | `turn_start`, `context`, `context_with_system`, `turn_end` |
|
|
101
|
+
| Provider call | `before_provider_headers`, `before_provider_request`, `after_provider_response`, `provider_stream_event` |
|
|
102
|
+
| Message lifecycle | `message_start`, `message_update`, `message_end` |
|
|
103
|
+
| Tool execution | `tool_execution_start`, `tool_call`, `tool_execution_update`, `tool_result`, `tool_execution_end` |
|
|
104
|
+
| Settlement | `agent_before_settle`, `agent_settled` |
|
|
105
|
+
|
|
106
|
+
KnightCode counts as busy while a run starts, including the compaction check and `before_agent_start`, so messages sent meanwhile go into the starting run. Message lifecycle events also cover user and tool-result messages; the diagram places only the assistant stream where it occurs in each model turn.
|
|
107
|
+
|
|
108
|
+
Tool hooks run for each tool call, and one assistant response can start another turn by returning tool calls. Provider hooks run only when that transport exposes the corresponding stage. See the exported declarations in [`extensions/types.ts`](https://github.com/KnightCodeAI/knightcode/blob/main/packages/cli/src/core/extensions/types.ts) for exact event payloads and result types.
|
|
109
|
+
|
|
110
|
+
Session startup and replacement follow a separate lifecycle:
|
|
111
|
+
|
|
112
|
+
```mermaid
|
|
113
|
+
flowchart TD
|
|
114
|
+
Startup["Process startup"] --> Trust["project_trust when needed"]
|
|
115
|
+
Trust --> SessionStart["session_start"]
|
|
116
|
+
Switch["/new or /resume"] --> BeforeSwitch["session_before_switch"]
|
|
117
|
+
Fork["/fork or /clone"] --> BeforeFork["session_before_fork"]
|
|
118
|
+
BeforeSwitch --> Shutdown["session_shutdown"]
|
|
119
|
+
BeforeFork --> Shutdown
|
|
120
|
+
Reload["reload"] --> Shutdown
|
|
121
|
+
Shutdown --> Replacing{"Replacing the runtime?"}
|
|
122
|
+
Replacing -->|yes| Replacement["load replacement extension runtime"]
|
|
123
|
+
Replacement --> SessionStart
|
|
124
|
+
Replacing -->|no| Stop["process exits"]
|
|
125
|
+
SessionStart --> Discover["resources_discover"]
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`project_trust` runs before trusted project resources load and can run again when session replacement enters a new working directory. Retries, recovery, compaction, and queued messages can start another agent run after `agent_end`, so `agent_end` is not a final-idle signal. Reload and session replacement invalidate the old runtime. Code after `await ctx.reload()` still belongs to the old runtime and must not reuse its session-bound state.
|
|
129
|
+
|
|
130
|
+
### Choose an event by intent
|
|
131
|
+
|
|
132
|
+
| Goal | Event |
|
|
133
|
+
|---|---|
|
|
134
|
+
| Inspect, transform, or consume raw user input | `input` |
|
|
135
|
+
| Change prompt sections, active tools, or add context before a run | `before_agent_start` |
|
|
136
|
+
| Observe one low-level agent run | `agent_start`, `agent_end` |
|
|
137
|
+
| Act after one model response and its tool calls | `turn_end` |
|
|
138
|
+
| Filter conversation messages for one provider request | `context` |
|
|
139
|
+
| Transform the complete transcript, including system messages | `context_with_system` |
|
|
140
|
+
| Change request headers or the serialized provider payload | `before_provider_headers`, `before_provider_request` |
|
|
141
|
+
| Observe provider response metadata or parsed stream events | `after_provider_response`, `provider_stream_event` |
|
|
142
|
+
| Authorize or modify a tool call | `tool_call` |
|
|
143
|
+
| Redact, annotate, or replace a tool result | `tool_result` |
|
|
144
|
+
| Append final entries or request one last continuation | `agent_before_settle` |
|
|
145
|
+
| Run notification work after automatic processing has stopped | `agent_settled` |
|
|
146
|
+
| Initialize or release session-scoped resources | `session_start`, `session_shutdown` |
|
|
147
|
+
|
|
148
|
+
<a id="agent_start--agent_end--agent_before_settle--agent_settled"></a>
|
|
149
|
+
|
|
150
|
+
Use `agent_before_settle` when an extension must append entries or request one final continuation. Use `agent_settled` for notification-only work that should run after KnightCode has no automatic continuation remaining.
|
|
151
|
+
|
|
152
|
+
<a id="extensionapi-methods"></a>
|
|
153
|
+
|
|
154
|
+
## Choose an integration point
|
|
155
|
+
|
|
156
|
+
| Capability | Main API |
|
|
157
|
+
|---|---|
|
|
158
|
+
| Observe or modify lifecycle behavior | `knightcode.on()` |
|
|
159
|
+
| Add a model-callable operation | `knightcode.registerTool()` |
|
|
160
|
+
| Add a `/` command | `knightcode.registerCommand()` |
|
|
161
|
+
| Add a shortcut or CLI flag | `knightcode.registerShortcut()` or `knightcode.registerFlag()` |
|
|
162
|
+
| Send user or custom messages | `knightcode.sendUserMessage()` or `knightcode.sendMessage()` |
|
|
163
|
+
| Persist non-context session data | `knightcode.appendEntry()` |
|
|
164
|
+
| Change active tools, model, or thinking level | Session control methods on `knightcode` |
|
|
165
|
+
| Add a model provider | `knightcode.registerProvider()` |
|
|
166
|
+
| Add an MCP server | `knightcode.registerMcpServer()` |
|
|
167
|
+
| Route each request to a model | [`knightcode.registerVirtualModel()`](virtual-models.md) |
|
|
168
|
+
| Add terminal rendering | Renderer registration and `ctx.ui` |
|
|
169
|
+
| Communicate with another extension | `knightcode.events` |
|
|
170
|
+
|
|
171
|
+
Use the exported declarations in [`extensions/types.ts`](https://github.com/KnightCodeAI/knightcode/blob/main/packages/cli/src/core/extensions/types.ts) for exact event, context, tool, and result types.
|
|
172
|
+
|
|
173
|
+
## Follow the extension contracts
|
|
174
|
+
|
|
175
|
+
<a id="events"></a>
|
|
176
|
+
<a id="work-with-events"></a>
|
|
177
|
+
|
|
178
|
+
### Events and concurrency
|
|
179
|
+
|
|
180
|
+
Handlers run in extension load and registration order. `knightcode.on()` returns a function that unsubscribes that registration; changes do not affect a dispatch already in progress.
|
|
181
|
+
Some events notify; others transform data, replace results, or cancel an operation.
|
|
182
|
+
Use each event’s declared result type rather than assuming every return value has an effect.
|
|
183
|
+
|
|
184
|
+
Events cover resource discovery, sessions, agent and message lifecycle, providers, tools, and raw input.
|
|
185
|
+
|
|
186
|
+
#### Understand handler composition
|
|
187
|
+
|
|
188
|
+
| Pattern | Behavior |
|
|
189
|
+
|---|---|
|
|
190
|
+
| Notification | Return values are ignored. Use the event for observation only. |
|
|
191
|
+
| In-place mutation | Later handlers see changes to values such as `before_provider_headers.headers`, `before_agent_start.systemPromptOptions`, and `tool_call.input`. |
|
|
192
|
+
| Chained transformation | Later handlers receive the value returned by earlier `input`, `context`, `context_with_system`, `message_end`, `tool_result`, and `before_provider_request` handlers. |
|
|
193
|
+
| Gate | A handled input, blocked tool call, cancelled session operation, or handled `user_bash` command stops that operation's normal fallback path. |
|
|
194
|
+
| Actionable boundary | Each `turn_end` or `agent_before_settle` handler sees the entries and continuation decision proposed so far. |
|
|
195
|
+
| Last override | The last `cache_warming_decision` handler that returns an action wins. |
|
|
196
|
+
|
|
197
|
+
Notification handlers should not perform slow work on a streaming event. Transform handlers should preserve fields they do not intentionally own, and gate handlers should fail closed when their safety decision cannot be made.
|
|
198
|
+
|
|
199
|
+
`before_agent_start` exposes both the current prompt and its structured `systemPromptOptions`. `event.messageType` says what started the run: `"user"` for a prompt or `knightcode.sendUserMessage()`, with `prompt` and `images`; `"custom"` for `knightcode.sendMessage(..., { triggerTurn: true })`, with the starting `message` and no `prompt`. A returned `message` is added to either kind of run; check `messageType` to skip runs started by custom messages. Prefer changing prompt sections, selected tools, or guidelines so KnightCode can append a transcript delta. Returning `systemPrompt`, or setting `forceSystemPrompt`, replaces the whole prompt for that run while the transcript continues recording the structured sections. Providers receive the forced text as their leading system prompt.
|
|
200
|
+
|
|
201
|
+
`message_end` can replace a finalized message while preserving its role. `tool_call` can mutate input or block execution. `tool_result` handlers compose, with each handler seeing prior changes.
|
|
202
|
+
|
|
203
|
+
<a id="provider_stream_event"></a>
|
|
204
|
+
|
|
205
|
+
`provider_stream_event` fires for each parsed provider stream event before KnightCode normalizes it. The event identifies the provider, API, and model; `event.data` is the earliest structured value available to KnightCode, not necessarily the original HTTP bytes or SSE frame. Treat it as read-only because mutation can affect normalization. The event is notification-only and is not persisted.
|
|
206
|
+
|
|
207
|
+
Handlers are awaited in stream order, so slow handlers delay stream consumption. Handler errors are reported without changing the provider response. See [`debug-provider.ts`](../examples/extensions/debug-provider.ts) for an opt-in viewer that groups raw events by assistant message.
|
|
208
|
+
|
|
209
|
+
<a id="context_with_system"></a>
|
|
210
|
+
|
|
211
|
+
`context` transforms conversation messages without prompt and tool system messages; KnightCode restores that state afterward. Use `context_with_system` only when a request-local transformation must own the complete transcript, and keep a system message at index zero.
|
|
212
|
+
|
|
213
|
+
`turn_end` and `agent_before_settle` are actionable boundaries. Their handlers can chain proposed `custom`, `custom_message`, `context_edit`, or `compaction` entries and return `continue: true` for one next model request. Returning `end: true` ends the owning run after valid entries are committed; it overrides continuation and does not drain queued user input. `event.end` exposes the accumulated end request, which later handlers cannot undo. Guard continuation conditions because an unconditional continuation can loop. Use the exported event declarations for the complete validation and ordering contract.
|
|
214
|
+
|
|
215
|
+
<a id="cache_warming_decision"></a>
|
|
216
|
+
|
|
217
|
+
`cache_warming_decision` can override an idle prompt-cache refresh with `{ action: "warm" }` or `{ action: "stop" }`. The last handler that returns an action wins.
|
|
218
|
+
|
|
219
|
+
Tool calls from one assistant message can run in parallel.
|
|
220
|
+
Do not assume a sibling call or result exists when another tool event runs.
|
|
221
|
+
Use `ctx.signal` for nested work owned by an active turn; commands and idle session events often have no operation signal.
|
|
222
|
+
|
|
223
|
+
A `user_bash` handler that returns `undefined` passes the command to the next handler and then to local execution if no handler handles it. Returning `operations` or `result` stops propagation. A handler failure blocks the command rather than falling through to local execution.
|
|
224
|
+
|
|
225
|
+
<a id="custom-tools"></a>
|
|
226
|
+
<a id="register-tools"></a>
|
|
227
|
+
|
|
228
|
+
### Tools
|
|
229
|
+
|
|
230
|
+
A custom tool defines a name, model-facing description, TypeBox parameter schema, and `execute()` function.
|
|
231
|
+
Its result requires model-facing `content` and a `details` field for rendering or state reconstruction.
|
|
232
|
+
Use `details: undefined` when there are no structured details. If the tool makes nested model calls, include their `usage` in the result so session totals remain accurate.
|
|
233
|
+
|
|
234
|
+
Throw from `execute()` to produce a failed tool result.
|
|
235
|
+
Returning an object does not mark it as an error.
|
|
236
|
+
Return `terminate: true` only when the agent should skip its automatic follow-up after every completed tool in that batch agrees to terminate.
|
|
237
|
+
|
|
238
|
+
Use sequential execution when tools share mutable in-memory state.
|
|
239
|
+
File-mutating tools should wrap the complete read-modify-write operation with `withFileMutationQueue()`.
|
|
240
|
+
Truncate large model-facing results and tell the model where to read the complete output.
|
|
241
|
+
|
|
242
|
+
Declare `outputSchema` and return a matching `structuredContent` when the result is data. The model still receives `content`; programmatic callers such as codemode scripts receive `structuredContent` instead of the text. Tools without `outputSchema` are passed to scripts as their text content. To report a failure that still carries data, return the result with `isError: true` instead of throwing: the model sees an error, and scripts still receive `structuredContent`.
|
|
243
|
+
|
|
244
|
+
A tool can run other tools with `ctx.executeTool(name, args, { signal, onUpdate })`. Nested calls go through argument validation and the `tool_call` and `tool_result` handlers like model-issued calls, and emit `tool_execution_start`, `tool_execution_update`, and `tool_execution_end`; all of these events carry `parentToolCallId`, and their `toolCallId` is assigned by knightcode as `<parent id>/<n>`. These ids do not appear as tool calls or tool results in the transcript. Nested calls do not add transcript entries: their results only reach the calling tool, which reports them itself, for example through `onUpdate` and `details`. The session keeps a bounded record of them (name, arguments, status, duration, error; never results) as `nestedCalls` on the calling tool's result message. It is used for compaction file lists and shown in HTML exports. Arguments over 8 KiB per call or 32 KiB per tool result are omitted, at most 256 calls are kept, and `complete: false` marks a record that lost anything. The `usage` of nested results, at every depth, is added to the calling tool's result `usage`, so a tool reports only its own usage, not that of the tools it called. `ctx.tools` lists the tools `ctx.executeTool()` can call. `tool_result` handlers that redact `content` should also replace `structuredContent`; replacing only `content` drops it.
|
|
245
|
+
|
|
246
|
+
See [`hello.ts`](../examples/extensions/hello.ts), [`todo.ts`](../examples/extensions/todo.ts), [`dynamic-tools.ts`](../examples/extensions/dynamic-tools.ts), and [`truncated-tool.ts`](../examples/extensions/truncated-tool.ts).
|
|
247
|
+
|
|
248
|
+
### Tool exposure
|
|
249
|
+
|
|
250
|
+
`exposure` controls how the model reaches a tool. "Callable" means callable from other tools through `ctx.executeTool()` (`ctx.tools`), as the `codemode` tool's scripts do:
|
|
251
|
+
|
|
252
|
+
- `direct` (default): declared to the model while active, and callable while active.
|
|
253
|
+
- `model-only`: declared to the model while active, never callable. Use it for tools that orchestrate other tools or ask the user.
|
|
254
|
+
- `codemode`: callable whenever registered, and listed by the `codemode` tool. Not declared to the model unless activated explicitly.
|
|
255
|
+
- `deferred`: like `codemode`, but codemode tools do not list it; `tool_search` can find and activate it.
|
|
256
|
+
- `hidden`: registered but unreachable. Re-register a tool with `exposure: "hidden"` to withdraw it, since tools cannot be unregistered.
|
|
257
|
+
|
|
258
|
+
`namespace: { name, aliases, description, instructions }` groups related tools, as MCP servers do. Codemode tools list a namespace under one heading with its `description`. `instructions` holds longer usage guidance; it is not listed, and codemode scripts read it with `describeNamespace(name)`. `aliases` are other names scripts may look the namespace up by, for example the server name `docs` for `mcp__docs`; a name and the same name as a script identifier (`my-docs`, `my_docs`) match alike.
|
|
259
|
+
|
|
260
|
+
Registering a `direct` or `model-only` tool activates it unless `defaultActive: false` keeps it optional; the other exposures are not activated on registration. The active set (`knightcode.getActiveTools()`, `knightcode.setActiveTools()`) is the set of tools declared to the model. `knightcode.getAllTools()` reports each tool's `exposure`, `namespace`, `annotations`, and `reachesTools`.
|
|
261
|
+
|
|
262
|
+
`annotations` are hints about what a tool does, with the meaning of MCP tool annotations: `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint`. MCP tools carry the hints their server declares. Missing hints take the MCP defaults: a tool is not read-only, and may be destructive and reach an open world. The hints are not verified, but a permission extension can use them to decide which calls to confirm. This confirms the calls Codex asks approval for:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
knightcode.on("tool_call", async (event, ctx) => {
|
|
266
|
+
const hints = knightcode.getAllTools().find((tool) => tool.name === event.toolName)?.annotations;
|
|
267
|
+
const needsApproval =
|
|
268
|
+
hints?.destructiveHint === true ||
|
|
269
|
+
(!hints?.readOnlyHint && ((hints?.destructiveHint ?? true) || (hints?.openWorldHint ?? true)));
|
|
270
|
+
if (needsApproval && !(await ctx.ui.confirm("Allow tool call?", event.toolName))) {
|
|
271
|
+
return { block: true, reason: `${event.toolName} was not approved` };
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
A tool that orchestrates other tools can adjust what the model sees while it is active with `prepareLoadout(loadout)`. It runs whenever the active tools change and receives the declared tools, the callable tools, and every registered tool with its exposure, namespace, and prompt guidelines. It returns replacement `descriptions` for declared tools (including its own) and `hiddenDeclarations`: active tools whose declarations requests leave out while they stay active and callable. The default system prompt leaves hidden tools out of its tool list and rules, and names no tool in the skills hint when the file reader is hidden, so the orchestrating tool should present their guidelines itself. `codemode` uses only this hook, `exposure`, `reachesTools`, and `ctx.executeTool()`, so another tool can implement the same behavior under a different name.
|
|
277
|
+
|
|
278
|
+
A tool that reaches other tools declares which ones a call may reach with `reachesTools(input)`: `"all"`, or the words of the input that may name them, where a word refers to every tool or namespace whose name it contains. `codemode` returns `"all"` for scripts that search or list tools and the words of the script otherwise; `tool_search` always returns `"all"`. Extensions that register tools late use it from their `tool_call` handler to finish registering the tools a call needs before it runs, as the MCP extension does for servers that are still connecting. The MCP extension also activates `codemode` or `tool_search` for MCP tools only when the tool of that name declares `reachesTools`.
|
|
279
|
+
|
|
280
|
+
### Activate tools dynamically
|
|
281
|
+
|
|
282
|
+
Register every tool first, keep optional tools inactive, and use `knightcode.setActiveTools()` from a loader tool to select the desired active tools. Names must already be registered; unknown names are ignored.
|
|
283
|
+
|
|
284
|
+
KnightCode records the initial prompt and tool set in the transcript's first system message, then appends tool and prompt changes before the next model request. Providers that cannot represent the transition receive a complete transcript checkpoint, which can invalidate the cached prefix.
|
|
285
|
+
|
|
286
|
+
### Tool rendering
|
|
287
|
+
|
|
288
|
+
A tool's `renderCall` and `renderResult` draw its calls in the interactive transcript and in HTML exports. `knightcode.registerToolRenderer((toolName, next) => renderers)` chooses renderers for calls to any tool, including tools that are not registered yet, such as MCP tools in a resumed session before their server connected. `next()` returns what the remaining resolvers (in extension load order), then the registered tool, would use, so `next() ?? mine` only fills in.
|
|
289
|
+
|
|
290
|
+
### MCP servers
|
|
291
|
+
|
|
292
|
+
`knightcode.registerMcpServer(name, config)` adds an MCP server for the current session. `config` has the shape of an `mcpServers` entry in [`mcp.json`](mcp.md): `command`, `args`, `env`, and `cwd` for stdio servers, `url`, `headers`, and `oauth` for HTTP servers, plus `exposure`, `toolExposure`, `description`, `enabled`, and `timeout`.
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
knightcode.registerMcpServer("jira", { url: "https://mcp.example.com/jira", exposure: "codemode" });
|
|
296
|
+
knightcode.unregisterMcpServer("jira");
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Servers registered while the extension loads connect when the session starts, together with the `mcp.json` servers; servers registered later connect right away, and `knightcode.unregisterMcpServer()` closes the connection and makes the server's tools unreachable. Registrations are not saved: register again on every load, for example based on the extension's own settings. A server in `mcp.json` with the same name takes precedence, and `/mcp` shows the override. Registering the same name again replaces the extension's earlier registration; names registered by another extension, invalid names, and invalid configs throw.
|
|
300
|
+
|
|
301
|
+
The built-in MCP support connects registered servers. When nothing does, because another extension replaced it (see [MCP](mcp.md#other-mcp-extensions)), each registration is reported as an extension error. Other MCP extensions can connect registered servers too: read them with `knightcode.getMcpServers()` on `session_start` and handle the `mcp_servers_change` event for later changes.
|
|
302
|
+
|
|
303
|
+
<a id="extensioncontext"></a>
|
|
304
|
+
<a id="extensioncommandcontext"></a>
|
|
305
|
+
<a id="use-extension-context"></a>
|
|
306
|
+
|
|
307
|
+
### Context and session changes
|
|
308
|
+
|
|
309
|
+
`ExtensionContext` provides the working directory, mode, UI, session manager, model runtime, abort signal, context usage, and controls for compaction and shutdown.
|
|
310
|
+
Use `ctx.modelRegistry.streamSimple()` for provider-neutral nested model calls.
|
|
311
|
+
Use `ctx.modelRegistry.getAvailableClassifiers()` and `ctx.modelRegistry.classify()` to ask a classifier model structured questions, as the built-in [classifier gate](usage.md#classifier-gate) does.
|
|
312
|
+
|
|
313
|
+
Command handlers receive `ExtensionCommandContext`, which adds operations for waiting until idle, reloading, tree navigation, and session replacement.
|
|
314
|
+
These operations are command-only because calling them from lifecycle handlers can deadlock the runtime.
|
|
315
|
+
|
|
316
|
+
Use `await ctx.sendUserMessage(content, options)` in a command when completion
|
|
317
|
+
must include the dispatched run. It rejects dispatch or preflight failures and
|
|
318
|
+
resolves after command handling or complete agent settlement. During an active
|
|
319
|
+
run, a message sent with `deliverAs` is only queued: the promise resolves once
|
|
320
|
+
it is queued, not when that run settles. The replacement context's method has
|
|
321
|
+
the same contract. The originating prompt receives the nested dispatch's
|
|
322
|
+
acceptance once, before settlement; command-only completion reports `handled`. Command-handler failures are reported and rethrown rather
|
|
323
|
+
than acknowledged as successful. `knightcode.sendUserMessage()` remains
|
|
324
|
+
fire-and-forget; waiting for idle after calling it is not equivalent because
|
|
325
|
+
asynchronous preflight may still be running.
|
|
326
|
+
|
|
327
|
+
`ctx.newSession({ preserveModel: true, setup, withSession })` optionally keeps
|
|
328
|
+
the outgoing model and reasoning level instead of the host defaults. Capture
|
|
329
|
+
plain data before replacement and dispatch through `withSession`'s context.
|
|
330
|
+
|
|
331
|
+
Session replacement invalidates the old context. Capture only plain data before switching, then use the fresh context supplied to `withSession` for session-bound work.
|
|
332
|
+
|
|
333
|
+
<a id="state-management"></a>
|
|
334
|
+
<a id="persist-state"></a>
|
|
335
|
+
|
|
336
|
+
### State
|
|
337
|
+
|
|
338
|
+
Module-level variables are shared by every session in the process that loads
|
|
339
|
+
the extension, and so are the providers it registers: one session calling
|
|
340
|
+
`unregisterProvider` removes the provider for all of them. The desktop app's
|
|
341
|
+
app server runs many sessions in one process, so keep per-session state inside
|
|
342
|
+
the factory closure, not at module level. Virtual models are the exception:
|
|
343
|
+
each session keeps its own route. Active cached factories are pinned; up to
|
|
344
|
+
256 inactive factories remain. Eviction or `/reload` can re-evaluate a module
|
|
345
|
+
on a future load, so module globals are not persistent storage. Eviction
|
|
346
|
+
never tears down a live session's extension.
|
|
347
|
+
|
|
348
|
+
Choose storage based on how state participates in the conversation:
|
|
349
|
+
|
|
350
|
+
| State | Storage |
|
|
351
|
+
|---|---|
|
|
352
|
+
| Tool state that follows the active branch | Tool-result `details` |
|
|
353
|
+
| Durable data excluded from model context | `knightcode.appendEntry()` |
|
|
354
|
+
| Custom content stored and sent to the model | `knightcode.sendMessage()` |
|
|
355
|
+
| Data outside one session | External storage |
|
|
356
|
+
|
|
357
|
+
Reconstruct branch-sensitive state from `ctx.sessionManager.getBranch()` during `session_start`.
|
|
358
|
+
Do not rebuild it from every file entry because abandoned branches represent alternative histories.
|
|
359
|
+
Register an entry or message renderer when custom stored content should appear in the transcript.
|
|
360
|
+
|
|
361
|
+
<a id="custom-ui"></a>
|
|
362
|
+
<a id="mode-behavior"></a>
|
|
363
|
+
<a id="interact-with-the-user"></a>
|
|
364
|
+
<a id="account-for-each-mode"></a>
|
|
365
|
+
|
|
366
|
+
### UI and modes
|
|
367
|
+
|
|
368
|
+
`ctx.ui` provides dialogs, notifications, status text, widgets, titles, editor access, and custom components.
|
|
369
|
+
Use `ctx.ui.custom()` only when the interaction needs its own rendering and input.
|
|
370
|
+
See [Terminal UI](tui.md) for component, focus, overlay, theme, and performance guidance.
|
|
371
|
+
|
|
372
|
+
Extensions load in interactive, RPC, JSON, print, and desktop modes.
|
|
373
|
+
Desktop mode currently has no extension UI (`hasUI` is false); terminal
|
|
374
|
+
components remain unavailable even when desktop dialogs are added.
|
|
375
|
+
Interactive mode provides the complete terminal UI. The [DOOM overlay example](../examples/extensions/doom-overlay/) uses a custom overlay component to render a game frame by frame:
|
|
376
|
+
|
|
377
|
+
<p align="center"><img src="images/doom-extension.png" alt="The DOOM overlay example running over a KnightCode session" width="750"></p>
|
|
378
|
+
|
|
379
|
+
RPC can forward supported dialogs and notifications through the [RPC Extension UI protocol](rpc-extension-ui.md), but not custom terminal components; JSON and print modes have no UI.
|
|
380
|
+
Guard terminal-only behavior with `ctx.mode === "tui"` and use `ctx.hasUI` for interactions supported by interactive and RPC clients.
|
|
381
|
+
|
|
382
|
+
Keep tool and event behavior independent from rendering so non-interactive modes remain functional.
|
|
383
|
+
|
|
384
|
+
<a id="error-handling"></a>
|
|
385
|
+
<a id="handle-errors-and-shutdown"></a>
|
|
386
|
+
|
|
387
|
+
### Errors and cleanup
|
|
388
|
+
|
|
389
|
+
KnightCode reports handler errors and continues where possible. A `tool_call` handler failure blocks the tool as a fail-safe; a tool execution failure becomes an error result for the model.
|
|
390
|
+
|
|
391
|
+
Throw the exported `ExtensionStartupError` from `session_start` when an unsafe
|
|
392
|
+
runtime must refuse initialization. Binding or reload propagates it to the
|
|
393
|
+
host, and the failed session cannot prompt a provider, compact, or run
|
|
394
|
+
extension commands until successful startup/reload clears the failure. Ordinary
|
|
395
|
+
handler errors remain nonfatal.
|
|
396
|
+
|
|
397
|
+
Release resources in `session_shutdown` even when normal operation attempted cleanup.
|
|
398
|
+
Keep cleanup idempotent because cancellation, reload, session replacement, and process exit can converge on the same path.
|
|
399
|
+
Use `ctx.shutdown()` to request an orderly process shutdown.
|
|
400
|
+
|
|
401
|
+
<a id="examples-reference"></a>
|
|
402
|
+
<a id="use-examples-as-the-implementation-reference"></a>
|
|
403
|
+
|
|
404
|
+
## Examples and reference
|
|
405
|
+
|
|
406
|
+
The checked [extension examples](../examples/extensions/) are the implementation reference. Start with the smallest example matching the behavior you need:
|
|
407
|
+
|
|
408
|
+
| Goal | Start with | Why |
|
|
409
|
+
|---|---|---|
|
|
410
|
+
| Confirm or block tool calls | [`permission-gate.ts`](../examples/extensions/permission-gate.ts) | Combines `tool_call`, mode-aware UI, and fail-closed behavior. |
|
|
411
|
+
| Modify prompt sections for a run | [`prompt-customizer.ts`](../examples/extensions/prompt-customizer.ts) | Uses structured prompt options instead of replacing the complete prompt. |
|
|
412
|
+
| Keep branch-aware tool state | [`todo.ts`](../examples/extensions/todo.ts) | Reconstructs state from persisted entries and renders it in the TUI. |
|
|
413
|
+
| Register tools after startup | [`dynamic-tools.ts`](../examples/extensions/dynamic-tools.ts) | Shares registration logic between lifecycle and command handlers. |
|
|
414
|
+
| Run cancellable model work from a command | [`qna.ts`](../examples/extensions/qna.ts) | Combines nested model calls, cancellation, and custom UI. |
|
|
415
|
+
| Replace the main editor | [`modal-editor.ts`](../examples/extensions/modal-editor.ts) | Extends `CustomEditor` while preserving application controls. |
|
|
416
|
+
| Run finalization at shutdown | [`auto-commit-on-exit.ts`](../examples/extensions/auto-commit-on-exit.ts) | Uses the session shutdown hook for finalization work. |
|
|
417
|
+
| Route built-in tools to another machine | [`ssh.ts`](../examples/extensions/ssh.ts) | Reuses tool operation interfaces instead of recreating tool contracts. |
|
|
418
|
+
| Add OAuth and provider-specific streaming | [`custom-provider-gitlab-duo/`](../examples/extensions/custom-provider-gitlab-duo/) | Shows a complete provider integration while delegating supported protocols. |
|
|
419
|
+
|
|
420
|
+
Use [Custom Providers](custom-provider.md) for model-service integrations, [Terminal UI](tui.md) for custom components, and [KnightCode Packages](packages.md) to install or distribute extensions with other resources. Use the exported declarations for exact signatures, payloads, and result schemas; this guide focuses on lifecycle choices, composition, and durable implementation patterns.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# How KnightCode Works
|
|
2
|
+
|
|
3
|
+
KnightCode coordinates model requests, tool execution, context assembly, and session storage. A session is KnightCode's record of a conversation, including messages, tool calls and results, model changes, compactions, and other events.
|
|
4
|
+
|
|
5
|
+
Messages and events in a session form a tree. Each path through that tree is a branch. The branch ending at the current entry is the active branch and supplies the history for the next model request.
|
|
6
|
+
|
|
7
|
+
## Agent loop
|
|
8
|
+
|
|
9
|
+
A submitted message is added to the active branch. KnightCode builds a model request from the system prompt, active branch, available tools, and model settings, then sends it through the selected provider.
|
|
10
|
+
|
|
11
|
+
The provider streams an assistant response, which can contain text and tool calls. KnightCode records the response, executes each tool call, and records the results. That completes one turn. If tool results or queued messages require another model request, KnightCode starts another turn. Otherwise, the run ends.
|
|
12
|
+
|
|
13
|
+
Steering messages enter after the current assistant turn. Follow-up messages enter after the agent has finished its pending work. Aborting stops the current run and returns queued messages to the editor.
|
|
14
|
+
|
|
15
|
+
## Context
|
|
16
|
+
|
|
17
|
+
The active branch supplies conversation history. KnightCode converts its session entries into model-compatible user, assistant, and tool-result messages.
|
|
18
|
+
|
|
19
|
+
KnightCode builds the system prompt from its base instructions and discovered context files. The request also carries tool definitions and skill descriptions.
|
|
20
|
+
|
|
21
|
+
Full skill instructions are loaded on demand. Extensions can add instructions or transform context.
|
|
22
|
+
|
|
23
|
+
Prompt templates expand editor input before it becomes a user message. Selected files, images, pasted text, and shell output can become message content.
|
|
24
|
+
|
|
25
|
+
## Sessions
|
|
26
|
+
|
|
27
|
+
Persistent sessions are JSONL files. Each tree entry has an ID and refers to its parent. The current entry identifies the active branch.
|
|
28
|
+
|
|
29
|
+
Continuing from an earlier entry creates another branch in the same file. Forking and cloning copy selected history into a new session file.
|
|
30
|
+
|
|
31
|
+
Model context is reconstructed from the active branch. Compaction inserts a summary entry that replaces older messages in subsequent model requests. The original entries remain in the session tree.
|
|
32
|
+
|
|
33
|
+
## Interfaces
|
|
34
|
+
|
|
35
|
+
Interactive mode renders session and agent events in the terminal. Print mode runs a prompt and writes the final response. JSON mode writes agent events as JSONL.
|
|
36
|
+
|
|
37
|
+
RPC mode accepts JSONL commands on stdin and writes responses and events to stdout. The TypeScript SDK creates and controls agent sessions in process.
|
|
38
|
+
|
|
39
|
+
All interfaces use the same agent and session mechanisms.
|
|
40
|
+
|
|
41
|
+
## Extensions and resources
|
|
42
|
+
|
|
43
|
+
Extensions are TypeScript modules loaded into the KnightCode process. Their factory functions register tools, commands, shortcuts, providers, event handlers, renderers, and terminal UI.
|
|
44
|
+
|
|
45
|
+
Skills provide on-demand instructions and supporting files. Prompt templates provide reusable message text. Themes provide terminal colors. KnightCode packages distribute these resources through npm or git.
|
|
46
|
+
|
|
47
|
+
## Trust and permissions
|
|
48
|
+
|
|
49
|
+
KnightCode resolves project trust before loading project settings and resources. After the trust decision and project-resource loading, KnightCode loads context files. Enabled tools use the operating-system permissions of the KnightCode process. Extensions execute inside that process.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# KnightCode
|
|
2
|
+
|
|
3
|
+
KnightCode is an extensible AI agent that works from your terminal. Give it a goal and a working folder, and it can inspect files, run commands, edit content, and work through multi-step tasks.
|
|
4
|
+
|
|
5
|
+
Use KnightCode for software development, research notes, writing projects, data files, or hobby work. You can use KnightCode as is, prompt it to adapt itself to your workflow, or build other applications powered by KnightCode using the SDK.
|
|
6
|
+
|
|
7
|
+
## Start using KnightCode
|
|
8
|
+
|
|
9
|
+
New to KnightCode? Follow the [Quickstart](quickstart.md) to install KnightCode, connect a model, and complete your first task.
|
|
10
|
+
|
|
11
|
+
If KnightCode is already installed, choose what you want to do:
|
|
12
|
+
|
|
13
|
+
- [Use KnightCode interactively](usage.md) to add files, run commands, direct ongoing work, and export results.
|
|
14
|
+
- [Choose a model](models.md) or connect a subscription, API key, local model, or compatible endpoint.
|
|
15
|
+
- [Continue or branch a session](sessions.md) to resume work or explore another approach without losing history.
|
|
16
|
+
- [Configure KnightCode](configuration.md) for your preferences, working folders, instructions, and reusable resources.
|
|
17
|
+
- [Understand how KnightCode works](how-knightcode-works.md), including tools, context, sessions, and the agent loop.
|
|
18
|
+
|
|
19
|
+
## Customize KnightCode
|
|
20
|
+
|
|
21
|
+
KnightCode can reuse prompts, load specialized instructions, add executable integrations, change its terminal interface, connect model services, and distribute these resources as packages.
|
|
22
|
+
Use the [Quickstart customization chooser](quickstart.md#choose-how-to-customize-knightcode) to select the smallest mechanism that meets your need.
|
|
23
|
+
|
|
24
|
+
## Automate or embed KnightCode
|
|
25
|
+
|
|
26
|
+
- Use [print mode](cli.md#invocation-and-output) for one-off and scripted tasks.
|
|
27
|
+
- Use [JSON event stream mode](json.md) to consume structured events from one run.
|
|
28
|
+
- Use [RPC mode](rpc.md) to control a separate KnightCode process.
|
|
29
|
+
- Use the [TypeScript SDK](sdk.md) to run KnightCode inside an application.
|
|
30
|
+
|
|
31
|
+
## Find reference and setup information
|
|
32
|
+
|
|
33
|
+
Use the reference pages to look up [CLI options](cli.md), [settings](settings.md), [providers](providers.md), [keybindings](keybindings.md), and [environment variables](environment-variables.md).
|
|
34
|
+
|
|
35
|
+
For platform-specific help, see [Terminal Setup](terminal-setup.md), [Windows](windows.md), [tmux](tmux.md), [Termux on Android](termux.md), or [Containerization](containerization.md).
|
|
36
|
+
|
|
37
|
+
## Work safely
|
|
38
|
+
|
|
39
|
+
KnightCode's tools and extensions run with the permissions of the KnightCode process. Project trust controls which project resources KnightCode loads, but it does not sandbox tool calls. Review [Security](security.md) before using untrusted files, repositories, extensions, or unattended automation.
|