@knightcodeai/cli-linux-arm64 0.11.1 → 0.11.3

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/bin/CHANGELOG.md CHANGED
@@ -1,5 +1,101 @@
1
1
  # @knightcodeai/cli
2
2
 
3
+ ## 0.11.3
4
+
5
+ ### Added
6
+
7
+ - Added Anthropic workload identity federation from the Anthropic SDK environment variables `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID` and `ANTHROPIC_IDENTITY_TOKEN_FILE`, plus the optional `ANTHROPIC_SERVICE_ACCOUNT_ID` and `ANTHROPIC_WORKSPACE_ID`. API keys and `ANTHROPIC_AUTH_TOKEN` take precedence.
8
+
9
+ - Added a copy-code login method to Anthropic sign-in for machines where the browser runs elsewhere and the localhost callback cannot load. `/login` now asks for browser or copy-code login, and copy-code login asks you to paste the code Anthropic shows.
10
+
11
+ - Added `quietStartup: "header"`, which keeps the startup header with version and key hints but hides the model scope line and loaded-resource listing.
12
+
13
+ - Added Radius to `/login`: "Sign in with Radius" is the last top-level option, with its status, and after signing in `/login` offers to add the Radius MCP server to the global `mcp.json` with `"auth": { "provider": "radius" }`. Cancelling a login returns to the menu it was started from, only subscription-backed providers are labeled "subscription" (other OAuth sign-ins say "account"), and providers without credentials say "not configured".
14
+
15
+ - Added `models.generateImages()` to codemode scripts. It runs image models such as OpenRouter's with the session's credentials and returns image blocks that `image()` attaches to the result; usage counts toward the session cost. Extensions can call `ctx.modelRegistry.generateImages()`.
16
+
17
+ - Added `"auth": { "provider": "<provider>" }` for HTTP MCP servers to send a provider's current `/login` token as the bearer token instead of using MCP OAuth. The token is read on every request, so provider refreshes apply. It is only allowed in the global `mcp.json` and from extensions, and requires https except on loopback hosts.
18
+
19
+ - Added an `oauth.authServerMetadataUrl` setting for MCP servers that advertise a wrong OAuth authorization server or none. KnightCode uses the configured metadata document instead of discovery.
20
+
21
+ ### Changed
22
+
23
+ - Changed the default TUI mode to fullscreen. Set `tuiMode` to `"regular"` or pass `--tui-mode regular` to keep the terminal's normal scrollback.
24
+
25
+ - Changed codemode to cost far fewer prompt tokens and to say how to recover from errors. The `codemode` description lists the script globals in one line each and points to the new Codemode docs page; reading a tool or `models` member that does not exist names the close matches, so scripts that probed with `typeof tools.name` must use `"name" in tools`.
26
+
27
+ - Changed `/arminsayshi` to play a 3D version in fullscreen mode, with one cube per pixel of Armin.
28
+
29
+ - Changed MCP OAuth credential storage to key credentials by server name and URL, so MCP servers with the same URL can sign in with different accounts. Credentials stored by URL alone move to the first server that uses them.
30
+
31
+ - Changed `/reload` to enable tools newly added to the `defaultTools` setting. Tools removed from it stay enabled, tools turned off during the session stay off unless newly added, and `--tools`, `--no-tools` and `--no-builtin-tools` still override the setting.
32
+
33
+ - Changed MCP servers without `direct` tools to connect in the background instead of blocking the first prompt. They are listed in a short `mcp_servers` system prompt section, and are waited for when a codemode script names them, a script searches tools, or `tool_search` runs. The `codemode` and `tool_search` descriptions no longer change when servers connect.
34
+
35
+ ### Fixed
36
+
37
+ - Fixed provider retries aborting or firing immediately when a `Retry-After` or `retry-after-ms` value is too large to represent, such as `1e999`. They now use exponential backoff, as they do for an unparseable date.
38
+
39
+ - Fixed Anthropic requests failing when a tool schema uses keywords Anthropic strict tool use rejects, such as `minimum` and `maximum`. Such tools are now sent non-strict.
40
+
41
+ - Fixed MCP servers that ask for more scope (`insufficient_scope`) requesting sign-in over and over. The new sign-in requested only the missing scopes, so the new token lost access the previous one had; it now keeps the granted scopes.
42
+
43
+ - Fixed memory retained per rendered message in the transcript: user messages keep one copy of each rendered line instead of two, and markdown, text and box components flatten their cached lines. A long assistant message keeps about a fifth of the heap it kept before.
44
+
45
+ - Fixed deferred MCP tools that `tool_search` loaded being dropped on resume and `/reload` even when their server reconnected before the next prompt, because the session restored its tools before the MCP servers reconnected.
46
+
47
+ - Fixed the system theme making pastel palettes such as Catppuccin Frappe much more vivid; palette colors now keep their chroma.
48
+
49
+ - Fixed `--provider` without `--model` being silently ignored and running the default model from another provider; it now fails with an error.
50
+
51
+ - Fixed prompt submission slowing down with session length, because resolving the session's model selection looked up the model catalog once per assistant message, and model lookups slowing down for providers with a refreshed remote catalog.
52
+
53
+ - Fixed MCP OAuth sign-in failing with `Invalid scope` when the token response contains `"scope": ""`, and similar failures for other empty or `null` optional OAuth fields, including `expires_in: null` marking the token as already expired.
54
+
55
+ - Fixed codemode scripts calling the wrong MCP tool when two tool names differ only in `-` and `_`, such as `read-file` and `read_file`. MCP tool and namespace names now replace `-` with `_` (`mcp__my-server__x` is now `mcp__my_server__x`), colliding tools of a server all get a hash suffix, and server names that differ only in `-` and `_` are rejected.
56
+
57
+ - Fixed collapsed `codemode` and MCP tool results filling the screen when the output is one long line, such as minified JSON. The preview is now limited to wrapped lines instead of logical lines.
58
+
59
+ - Fixed `codemode.mode: "only"` listing `read`, `bash`, `edit` and `write` in the system prompt's tool list although requests only declare `codemode`.
60
+
61
+ - Fixed extension commands registered without a string name or a handler crashing KnightCode when typing `/`. The extension now fails to load with an error instead.
62
+
63
+ - Fixed switching to another OpenAI Responses model after a codemode call failing with an invalid item id. A replayed grammar tool call now drops any id that does not match its item type, since `custom_tool_call` ids must start with `ctc_` and `function_call` ids with `fc_`.
64
+
65
+ - Fixed Together's DeepSeek V4 Pro losing its high reasoning-effort level after Together renamed the model to `deepseek-ai/DeepSeek-V4-Pro-0813`.
66
+
67
+ - Fixed color bleeding past mouse selections and search highlights in fullscreen mode when a styled token ends at the highlight boundary.
68
+
69
+ - Fixed slash command completion not working after leading whitespace in the editor. Typing ` /mod` now completes to ` /model` and keeps the whitespace.
70
+
71
+ ### Security
72
+
73
+ - Security: MCP OAuth sign-in now rejects an authorization response whose `iss` parameter names another authorization server before exchanging the code (RFC 9207).
74
+
75
+ ## 0.11.2
76
+
77
+ ### Added
78
+
79
+ - Added an `oauth.clientName` setting for MCP servers (`knightcode mcp add --oauth-client-name`) to change the client name sent during OAuth client registration, for servers such as Figma that only accept known clients.
80
+
81
+ - Added a `description` field for MCP servers (`knightcode mcp add --description`), shown next to the server in the `codemode` and `tool_search` descriptions, and a `describeNamespace(name)` codemode helper that returns a namespace's instructions and tool names.
82
+
83
+ ### Changed
84
+
85
+ - Changed the `codemode` description to list MCP servers instead of their tools, so it no longer changes when a server's tool list changes. Scripts find tools with `searchTools()` and read server instructions with `describeNamespace()`; `codemode-deferred` is now an alias for `codemode`, and `direct` exposure keeps tools visible to the model.
86
+
87
+ ### Fixed
88
+
89
+ - Fixed codemode `image()` accepting malformed base64 data or unsupported image types, which stored an invalid image block that made every later provider request fail with HTTP 400. It now throws a `TypeError` unless the data is valid base64 of a PNG, JPEG, GIF, or WebP image, takes the MIME type from the image signature, and strips line breaks from wrapped base64.
90
+
91
+ - Fixed codemode failing to start its script worker from the standalone Windows executable.
92
+
93
+ - Fixed the `/mcp` sign-in URL not being clickable when it wraps across lines. It is now a terminal hyperlink with a `Cmd/Ctrl+click to open` line, like `/login`.
94
+
95
+ - Fixed new sessions intermittently ignoring the saved default model, or warning that no models are available, when it belongs to an extension-registered native provider with a stored credential.
96
+
97
+ - Fixed context overflow errors from the Z.AI China endpoint ("Prompt exceeds max length") not being recognised, so compaction and retry now trigger for them as they do for the global endpoint.
98
+
3
99
  ## 0.11.1
4
100
 
5
101
  ### Added
package/bin/docs/cli.md CHANGED
@@ -58,10 +58,10 @@ RPC mode rejects `@file` arguments. JSON and RPC modes reserve stdout for protoc
58
58
  knightcode --model sonnet:high
59
59
  ```
60
60
 
61
- See [Choose a Model](models.md) for model selection and [Provider Authentication](providers.md) for credentials.
61
+ See [Choose a Model](models.md) for model selection and [Providers](providers.md) for credentials.
62
62
 
63
63
  - `--provider <name>`<br>
64
- Restricts `--model` lookup to one provider.
64
+ Restricts `--model` lookup to one provider. It requires `--model`.
65
65
  - `--model <pattern>`<br>
66
66
  Selects by exact ID or fuzzy ID/name match. It accepts `provider/id` and an optional `:<thinking>` suffix.
67
67
  - `--api-key <key>`<br>
@@ -163,21 +163,11 @@ This keeps `read`, `bash`, `edit`, and `write` and adds `codemode`. For one invo
163
163
  knightcode --tools read,bash,edit,write,codemode
164
164
  ```
165
165
 
166
- Codemode is useful without MCP: scripts can run several tool calls in parallel, filter large output before it reaches the model, and call classifier models such as TypeSafe's Jev through `models.classify()` (see [Classifier models](models.md#use-classifier-models)).
166
+ Codemode is useful without MCP: scripts can run several tool calls in parallel, filter large output before it reaches the model, call classifier models such as TypeSafe's Jev through `models.classify()` (see [Classifier models](models.md#use-classifier-models)), and generate images through `models.generateImages()` (see [Image models](models.md#use-image-models)).
167
167
 
168
168
  ### How codemode works
169
169
 
170
- Codemode scripts run in a QuickJS sandbox that can only reach the other tools, through `tools.<name>(args)`; `ALL_TOOLS` lists them. Output comes from `text(value)`, `image(dataUrlOrImageContent)`, `console.*`, and a top-level `return value`; `exit()` ends the script early. The result starts with `Script completed` or `Script failed`, the wall time, and the output; a failed script keeps its partial output, followed by `Script error:` and the error.
171
-
172
- A script may start with an options line such as `// @options: {"max_output_tokens": 2000, "timeout_ms": 60000}`. `max_output_tokens` (default 10000) limits the output: longer output keeps its start and end, and the full text is written to a temp file whose path is included in the result. `timeout_ms` is a hard deadline, unset by default.
173
-
174
- While `codemode` is active, `codemode.mode` in [settings](settings.md#tools) decides how the other tools are presented. With `on` (default) declared tools keep being declared and their descriptions show how to call them from scripts. With `only` they are hidden from the model and listed in the `codemode` description instead, so the model calls them through scripts.
175
-
176
- The `codemode` description lists the callable tools with their TypeScript declarations, grouped by namespace (for example one MCP server). Declarations share a budget of 3000 estimated tokens (`codemode.inlineBudget` in [settings](settings.md#tools)); every namespace is still listed with its tool count, and the description says whether the list is complete. Scripts find the rest with `await searchTools(query, { limit, namespace })`, which ranks tools with BM25, and `await describeTool(name)`, or by filtering `ALL_TOOLS`.
177
-
178
- Tools with an output schema resolve to structured values: `bash` to `{ output, truncated, full_output_path?, exit_code, wall_time_seconds }`, also for non-zero exit codes, and MCP tools to their `CallToolResult`. Other tools resolve to their text output. The `output` of `bash` is not limited to the 2000 lines or 50KB the model sees: it holds up to 1 MiB, and longer output keeps its first and last 512 KiB around an omission marker, with `truncated` set and the full output in `full_output_path`.
179
-
180
- `store(key, value)` and `load(key)` keep JSON values across `codemode` calls: each successful script that stores values appends a `codemode-store` custom entry to the session, so resumed sessions keep the values and each branch sees only the values written on its path. Scripts can also use `models`: `getModelsOfType`, `getAvailableOfType`, and `getModelOfType` list the model catalog, and `classify(model, context)` runs a classifier model with the session's credentials, at most four at a time per script.
170
+ Scripts run in a QuickJS sandbox and reach the other tools through `tools.<name>(args)`. [Codemode](codemode.md) describes the script API, how tools are listed and found, the `store()` and `models` globals, and the limits.
181
171
 
182
172
  ### Tool search
183
173
 
@@ -231,7 +221,7 @@ See [Configuration](configuration.md) for saved configuration, [Security](securi
231
221
  - `--append-system-prompt <text|path>`<br>
232
222
  Appends text or an existing file to the system prompt and is repeatable.
233
223
  - `--tui-mode <mode>`<br>
234
- Uses `regular` or `fullscreen` terminal mode.
224
+ Uses `fullscreen` (default) or `regular` terminal mode.
235
225
  - `--verbose`<br>
236
226
  Shows verbose interactive startup information, overriding `quietStartup`.
237
227
  - `-a`, `--approve`<br>
@@ -294,7 +284,7 @@ Add `--force` to reinstall KnightCode when the selected update includes KnightCo
294
284
  knightcode auth check --provider openai --json
295
285
  ```
296
286
 
297
- Authentication commands require `--provider <provider>` or `--model <model>`. See [Provider Authentication](providers.md) for supported methods.
287
+ Authentication commands require `--provider <provider>` or `--model <model>`. See [Providers](providers.md) for supported methods.
298
288
 
299
289
  | Command | Description |
300
290
  |---|---|
@@ -320,12 +310,12 @@ These commands work outside a session, so agents can run them through `bash`. Se
320
310
  | Command | Description |
321
311
  |---|---|
322
312
  | `knightcode mcp add <server> [options] -- <command> [args...]` | Add or replace a stdio server in `mcp.json`; `--env KEY=VALUE` (repeatable) and `--cwd <dir>` set its environment and working directory. Arguments after the command are passed to it |
323
- | `knightcode mcp add <server> [options] --url <url>` | Add or replace a streamable HTTP server; `--header KEY=VALUE` (repeatable), `--bearer-token-env-var <NAME>` (sends `Authorization: Bearer ${NAME}`), `--oauth-client-id`, `--oauth-client-secret`, and `--oauth-callback-port` configure authentication |
313
+ | `knightcode mcp add <server> [options] --url <url>` | Add or replace a streamable HTTP server; `--header KEY=VALUE` (repeatable), `--bearer-token-env-var <NAME>` (sends `Authorization: Bearer ${NAME}`), `--oauth-client-id`, `--oauth-client-secret`, `--oauth-callback-port`, and `--oauth-client-name` configure authentication |
324
314
  | `knightcode mcp remove <server>` | Remove a server from `mcp.json`; stored OAuth credentials are kept |
325
315
  | `knightcode mcp list [--json]` | Connect to every enabled server and print its state, tools, and errors; exit with `1` when a config entry is invalid or an enabled server is not connected |
326
316
  | `knightcode mcp login <server> [--timeout <seconds>]` | Sign in to an OAuth server: open the authorization page and wait for the browser (default 300 seconds); a terminal also accepts the pasted redirect URL |
327
317
  | `knightcode mcp logout <server>` | Delete the stored OAuth credentials of a server |
328
318
 
329
- `add` and `remove` change `~/.knightcode/agent/mcp.json`, or `.knightcode/mcp.json` in the current directory with `--local` (`-l`). `add` also takes `--exposure <mode>` (see [Exposure](mcp.md#exposure)) and does not connect; run `knightcode mcp list` to check the server.
319
+ `add` and `remove` change `~/.knightcode/agent/mcp.json`, or `.knightcode/mcp.json` in the current directory with `--local` (`-l`). `add` also takes `--exposure <mode>` (see [Exposure](mcp.md#exposure)) and `--description <text>` and does not connect; run `knightcode mcp list` to check the server.
330
320
 
331
321
  Project `.knightcode/mcp.json` files are only read for projects that are already trusted.
@@ -0,0 +1,207 @@
1
+ # Codemode
2
+
3
+ The `codemode` tool lets the model write a JavaScript script that calls KnightCode's other tools and runs non-LLM models, such as classifiers and image models. Only the script's output reaches the model, so a script can run calls in parallel and filter large results before the model sees them. To turn it on, see [Enable codemode](cli.md#enable-codemode).
4
+
5
+ ## Scripts
6
+
7
+ The tool input is raw JavaScript source, not JSON and not a markdown code fence. It runs as the body of an async function in a QuickJS sandbox, so top-level `await` and `return` work. The sandbox has no Node APIs, file system, network, or timers; scripts reach the outside world only through tools and `models`.
8
+
9
+ A script may start with an options line:
10
+
11
+ ```js
12
+ // @options: {"max_output_tokens": 2000, "timeout_ms": 60000}
13
+ ```
14
+
15
+ - `max_output_tokens` (default 10000) limits the output. Longer output keeps its start and end, and the full text is written to a temp file whose path is included in the result.
16
+ - `timeout_ms` is a hard deadline for the whole script. It is unset by default. Image generation can take minutes, so do not set a short deadline for scripts that generate images.
17
+
18
+ The result starts with `Script completed` or `Script failed`, the wall time, and the output. A failed script keeps its partial output, followed by `Script error:` and the error. Tool calls are real: calls made before a failure are not undone. Calls still running when the script ends are cancelled, and unawaited promises are discarded.
19
+
20
+ ## Globals
21
+
22
+ | Global | Purpose |
23
+ |---|---|
24
+ | `tools.<name>(args)` | Call a tool. See [Call tools](#call-tools). |
25
+ | `text(value)` | Add a text item to the output. Strings are added as is, other values as JSON. |
26
+ | `image(value)` | Add an image to the output: a base64 `data:` URL, an `{ image_url }` object, or an image block `{ type: "image", data, mimeType }` such as those returned by MCP tools and `models.generateImages()`. Remote URLs are not supported. PNG, JPEG, GIF, and WebP are accepted. |
27
+ | `console.log(...)` | Like `text()`; `info`, `warn`, `error`, and `debug` do the same. |
28
+ | `return value` | A top-level `return` adds the value like `text()`. |
29
+ | `exit()` | End the script successfully. |
30
+ | `store(key, value)` / `load(key)` | Keep small JSON values across `codemode` calls. See [Store values](#store-values). |
31
+ | `ALL_TOOLS` | Every callable tool as `{ name, description }`, including tools the description does not list. |
32
+ | `searchTools(query, { limit?, namespace? })` | Rank callable tools by relevance (BM25, default limit 8). Resolves to `{ name, description }[]`. |
33
+ | `describeTool(name)` | Resolves to a tool's description and TypeScript declaration, or `undefined`. |
34
+ | `describeNamespace(name)` | Resolves to `{ name, description?, instructions?, tools }` for a namespace such as an MCP server, or `undefined`. |
35
+ | `models` | List and run non-LLM models. See [Models](#models). |
36
+
37
+ ## Call tools
38
+
39
+ Every tool the session can call is a method of `tools`, named by its identifier: characters that are not valid in a JavaScript identifier become `_`, so the MCP tool `mcp__dev-radius__search` is `tools.mcp__dev_radius__search`. Each method takes one object with the tool's arguments.
40
+
41
+ What a call resolves to depends on the tool:
42
+
43
+ - Tools with an output schema resolve to a structured value. `bash` resolves to `{ output, truncated, full_output_path?, exit_code, wall_time_seconds }`, also for non-zero exit codes. Its `output` is not limited to the 2000 lines or 50KB the model sees: it holds up to 1 MiB, and longer output keeps its first and last 512 KiB around an omission marker, with `truncated` set and the full output in `full_output_path`.
44
+ - MCP tools resolve to their `CallToolResult`, including `isError` and `structuredContent`.
45
+ - Other tools, such as `read`, `edit`, and `write`, resolve to their text output.
46
+
47
+ A call that fails, is blocked, or gets invalid arguments rejects with an `Error` that carries the tool's error text. Use `Promise.allSettled()` to keep the results of the calls that succeed.
48
+
49
+ The `codemode` description lists tools with their TypeScript declarations, grouped by namespace (for example one MCP server). Tools with `deferred` exposure, which includes MCP tools with the default `codemode` exposure, are not listed, so the description stays the same while MCP servers connect. Listed declarations share a budget of 3000 estimated tokens (`codemode.inlineBudget` in [settings](settings.md#tools)). Scripts find the other tools with `searchTools()`, `describeTool()`, `describeNamespace()`, or by filtering `ALL_TOOLS`.
50
+
51
+ While `codemode` is active, `codemode.mode` in [settings](settings.md#tools) decides how the other tools are presented. With `on` (default) declared tools stay declared, and their descriptions say how to call them from scripts. With `only` they are hidden from the model and listed in the `codemode` description instead, so the model calls them through scripts.
52
+
53
+ ## Store values
54
+
55
+ `store(key, value)` keeps a JSON value under a string key for later `codemode` calls; storing `undefined` deletes the key. `load(key)` returns the value, or `undefined`. Writes are kept only when the script succeeds: each successful script that stores values appends a `codemode-store` custom entry to the session, so resumed sessions keep the values and each branch sees only the values written on its path.
56
+
57
+ The store is for small state such as IDs, cursors, or summaries. One value may have at most 262144 characters of JSON and all values together at most 1048576. Do not store image data; show images with `image()` or write them to a file with a tool.
58
+
59
+ ## Models
60
+
61
+ `models` reaches the model catalog and runs non-LLM models with the session's credentials: classifiers, which answer typed questions about JSON state, and image models, which generate images. Chat models are listed but cannot be run from scripts. Which classifier and image models exist is described in [Use classifier models](models.md#use-classifier-models) and [Use image models](models.md#use-image-models).
62
+
63
+ ```ts
64
+ type ModelType = "chat" | "image" | "classifier";
65
+
66
+ /** A catalog entry. `provider` and `id` identify it; other fields depend on the type. */
67
+ interface ModelInfo {
68
+ type?: ModelType;
69
+ provider: string;
70
+ id: string;
71
+ name: string;
72
+ api: string;
73
+ input: ("text" | "image")[];
74
+ contextWindow?: number;
75
+ [key: string]: unknown;
76
+ }
77
+
78
+ declare const models: {
79
+ /** Every known model of a type, optionally for one provider. */
80
+ getModelsOfType(type: ModelType, provider?: string): Promise<ModelInfo[]>;
81
+ /** Models of a type whose provider has working credentials. */
82
+ getAvailableOfType(type: ModelType, provider?: string): Promise<ModelInfo[]>;
83
+ /** One catalog entry, or undefined. */
84
+ getModelOfType(type: ModelType, provider: string, id: string): Promise<ModelInfo | undefined>;
85
+ /** Answer `context.questions` about `context.state`; answers are in `result.answers` by question ID. */
86
+ classify(model: ModelInfo, context: ClassifierContext): Promise<ClassifierResult>;
87
+ /** Generate images from `context.input` text and image blocks; show `result.output` blocks with image(). Can take minutes. */
88
+ generateImages(model: ModelInfo, context: ImagesContext): Promise<ImagesResult>;
89
+ };
90
+ ```
91
+
92
+ `classify()` and `generateImages()` use only the `provider` and `id` of `model`, so `{ provider, id }` works as well. They do not throw on provider errors: check `stopReason` and `errorMessage`. At most four such calls run at once per script; more calls wait for a free slot, so `Promise.all()` over many items is fine. Their usage is added to the `codemode` tool result and counts toward the session cost.
93
+
94
+ Model IDs differ between providers, for example `typesafe/jev-latest` and `openrouter/typesafe/jev-1.13`. Use `models.getAvailableOfType(type)` to find the IDs that work with the current credentials.
95
+
96
+ ### Classify
97
+
98
+ ```ts
99
+ interface ClassifierContext {
100
+ /** The data to classify. */
101
+ state: Record<string, unknown>;
102
+ /** Questions by ID. One call answers all of them. */
103
+ questions: Record<string, ClassifierQuestion>;
104
+ }
105
+
106
+ type ClassifierQuestion =
107
+ /** Pick one label. `criteria` maps each label to what it means. */
108
+ | { type: "choice"; instructions: string; criteria: Record<string, string> }
109
+ /** Score on an ordered scale. `criteria` describes each level, lowest first. */
110
+ | { type: "score"; instructions: string; criteria: string[] }
111
+ /** Yes or no. */
112
+ | { type: "bool"; instructions: string; criteria: { true: string; false: string } };
113
+
114
+ interface ClassifierResult {
115
+ provider: string;
116
+ model: string;
117
+ /** Answers by question ID. */
118
+ answers: Record<string, ClassifierAnswer>;
119
+ usage?: ModelUsage;
120
+ stopReason: "stop" | "error" | "aborted";
121
+ errorMessage?: string;
122
+ }
123
+
124
+ type ClassifierAnswer =
125
+ | { type: "choice"; choice: string; probabilities: Record<string, number>; confidence: number }
126
+ /** `score` is the expected level index, from 0 to `criteria.length - 1`. */
127
+ | { type: "score"; score: number; confidence: number }
128
+ /** Probability of `true`. */
129
+ | { type: "bool"; probability: number };
130
+
131
+ /** Token counts and cost in USD, when the service reports them. */
132
+ type ModelUsage = { input: number; output: number; totalTokens: number; cost: { total: number } };
133
+ ```
134
+
135
+ Classify several items by calling `classify()` once per item. This script sorts feedback messages, for example ones a tool returned earlier in the script:
136
+
137
+ ```js
138
+ const jev = await models.getModelOfType("classifier", "typesafe", "jev-latest");
139
+ const results = await Promise.all(
140
+ messages.map((message) =>
141
+ models.classify(jev, {
142
+ state: { message },
143
+ questions: {
144
+ sentiment: {
145
+ type: "choice",
146
+ instructions: "How does the user feel about the product?",
147
+ criteria: { positive: "Satisfied or happy", negative: "Unhappy or frustrated", neutral: "Neither" },
148
+ },
149
+ urgency: {
150
+ type: "score",
151
+ instructions: "How urgently does this need a reply?",
152
+ criteria: ["no reply needed", "reply this week", "reply today"],
153
+ },
154
+ },
155
+ }),
156
+ ),
157
+ );
158
+ return results.map((result, i) =>
159
+ result.stopReason === "stop"
160
+ ? { message: messages[i], sentiment: result.answers.sentiment.choice, urgency: result.answers.urgency.score }
161
+ : { message: messages[i], error: result.errorMessage },
162
+ );
163
+ ```
164
+
165
+ ### Generate images
166
+
167
+ ```ts
168
+ interface ImagesContext {
169
+ /** The prompt as text blocks, plus image blocks to edit or use as references. */
170
+ input: (TextBlock | ImageBlock)[];
171
+ }
172
+
173
+ interface ImagesResult {
174
+ provider: string;
175
+ model: string;
176
+ /** Generated images, and text blocks for models that also return text. */
177
+ output: (TextBlock | ImageBlock)[];
178
+ usage?: ModelUsage;
179
+ stopReason: "stop" | "error" | "aborted";
180
+ errorMessage?: string;
181
+ }
182
+
183
+ type TextBlock = { type: "text"; text: string };
184
+ /** `data` is base64. */
185
+ type ImageBlock = { type: "image"; data: string; mimeType: string };
186
+ ```
187
+
188
+ Show generated images with `image(block)`. Do not print `data` with `text()`, `console`, or `return`: it is large and the model cannot read it as text. Generated images are not saved to disk; to keep one, write it to a file with a tool.
189
+
190
+ ```js
191
+ // @options: {"timeout_ms": 300000}
192
+ const painter = await models.getModelOfType("image", "openrouter", "google/gemini-2.5-flash-image");
193
+ const result = await models.generateImages(painter, {
194
+ input: [{ type: "text", text: "A red fox in the snow, watercolor" }],
195
+ });
196
+ if (result.stopReason !== "stop") return result.errorMessage;
197
+ for (const block of result.output) {
198
+ if (block.type === "image") image(block);
199
+ else text(block.text);
200
+ }
201
+ ```
202
+
203
+ ## Limits
204
+
205
+ - A script's VM has 256 MB of memory. Running out throws `InternalError: out of memory`; filter or aggregate large data instead of accumulating it.
206
+ - A script that waits on a promise that can never settle (no tool call pending) fails immediately, since there are no timers.
207
+ - Scripts cannot start other `codemode` scripts.
@@ -140,6 +140,10 @@
140
140
  "title": "CLI",
141
141
  "path": "cli.md"
142
142
  },
143
+ {
144
+ "title": "Codemode",
145
+ "path": "codemode.md"
146
+ },
143
147
  {
144
148
  "title": "Slash Commands",
145
149
  "path": "slash-commands.md"
@@ -157,7 +161,7 @@
157
161
  "path": "keybindings.md"
158
162
  },
159
163
  {
160
- "title": "Provider Authentication",
164
+ "title": "Providers",
161
165
  "path": "providers.md"
162
166
  },
163
167
  {
@@ -6,7 +6,7 @@ KnightCode uses environment variables in three ways:
6
6
  - KnightCode sets process markers so child processes can identify KnightCode as the launching agent.
7
7
  - Commands run by the LLM-callable shell tools receive `KNIGHTCODE_*` variables describing the current session.
8
8
 
9
- Provider API-key variables are documented separately in [Provider Authentication](providers.md#use-an-api-key-from-the-environment).
9
+ Provider API-key variables are documented separately in [Providers](providers.md#use-an-api-key-from-the-environment).
10
10
 
11
11
  ## Process Marker
12
12
 
@@ -100,4 +100,4 @@ These variables are read by KnightCode itself:
100
100
  | `VISUAL`, `EDITOR` | External editor fallback when `externalEditor` is unset |
101
101
  | `HTTP_PROXY`, `HTTPS_PROXY` | Proxy outbound HTTP requests |
102
102
 
103
- Provider credentials such as `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and cloud-provider configuration are listed in [Provider Authentication](providers.md#use-an-api-key-from-the-environment).
103
+ Provider credentials such as `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and provider-specific configuration are listed in [Providers](providers.md#use-an-api-key-from-the-environment).
@@ -159,7 +159,7 @@ See [`hello.ts`](../examples/extensions/hello.ts), [`todo.ts`](../examples/exten
159
159
  - `deferred`: like `codemode`, but codemode tools do not list it; `tool_search` can find and activate it.
160
160
  - `hidden`: registered but unreachable. Re-register a tool with `exposure: "hidden"` to withdraw it, since tools cannot be unregistered.
161
161
 
162
- `namespace: { name, description }` groups related tools, as MCP servers do. Codemode tools list a namespace under one heading.
162
+ `namespace: { name, 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)`.
163
163
 
164
164
  Registering a `direct` or `model-only` tool activates it; 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`, and `annotations`.
165
165
 
@@ -177,7 +177,7 @@ knightcode.on("tool_call", async (event, ctx) => {
177
177
  });
178
178
  ```
179
179
 
180
- 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 and namespace. 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. `codemode` and `tool_search` use only this hook, `exposure`, and `ctx.executeTool()`, so another tool can implement the same behavior under a different name.
180
+ 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 and namespace. 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. `codemode` uses only this hook, `exposure`, and `ctx.executeTool()`, so another tool can implement the same behavior under a different name.
181
181
 
182
182
  ### Activate tools dynamically
183
183
 
@@ -187,7 +187,7 @@ KnightCode records the initial prompt and tool set in the transcript's first sys
187
187
 
188
188
  ### MCP servers
189
189
 
190
- `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`, `enabled`, and `timeout`.
190
+ `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`.
191
191
 
192
192
  ```typescript
193
193
  knightcode.registerMcpServer("jira", { url: "https://mcp.example.com/jira", exposure: "codemode" });
package/bin/docs/index.md CHANGED
@@ -30,7 +30,7 @@ Use the [Quickstart customization chooser](quickstart.md#choose-how-to-customize
30
30
 
31
31
  ## Find reference and setup information
32
32
 
33
- Use the reference pages to look up [CLI options](cli.md), [settings](settings.md), [provider authentication](providers.md), [keybindings](keybindings.md), and [environment variables](environment-variables.md).
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
34
 
35
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
36
 
package/bin/docs/mcp.md CHANGED
@@ -1,10 +1,37 @@
1
1
  # MCP Servers
2
2
 
3
- KnightCode connects to [Model Context Protocol](https://modelcontextprotocol.io) servers over stdio or streamable HTTP and makes their tools available to the model.
3
+ KnightCode connects to [Model Context Protocol](https://modelcontextprotocol.io) servers over stdio or streamable HTTP and makes their tools and resources available to the model.
4
+
5
+ ## Quick setup
6
+
7
+ Add a local stdio server, check the connection, then start KnightCode:
8
+
9
+ ```bash
10
+ knightcode mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem .
11
+ knightcode mcp list
12
+ knightcode
13
+ ```
14
+
15
+ For a remote server:
16
+
17
+ ```bash
18
+ knightcode mcp add docs --url https://example.com/mcp --bearer-token-env-var DOCS_TOKEN
19
+ knightcode mcp list
20
+ ```
21
+
22
+ These commands add user-level servers by default. Add `--local` or `-l` to write the project configuration instead:
23
+
24
+ ```bash
25
+ knightcode mcp add -l tools --env API_KEY='${TOOLS_KEY}' -- uvx tools-mcp
26
+ ```
27
+
28
+ Use `/mcp` inside an interactive session to inspect connections, sign in, reconnect, change exposure, or enable and disable servers. Run `/reload` after adding, removing, or changing a server outside the session.
4
29
 
5
30
  ## Configure servers
6
31
 
7
- Add servers to `~/.knightcode/agent/mcp.json`, or to `.knightcode/mcp.json` in a project. The format matches other MCP clients, so existing `mcpServers` entries can be copied over:
32
+ KnightCode reads user-level servers from `~/.knightcode/agent/mcp.json` and project servers from `.knightcode/mcp.json`. Project configuration is read only after [project trust](security.md#understand-project-trust) is granted. A project entry replaces a user-level entry with the same name.
33
+
34
+ The format matches other MCP clients:
8
35
 
9
36
  ```json
10
37
  {
@@ -16,77 +43,66 @@ Add servers to `~/.knightcode/agent/mcp.json`, or to `.knightcode/mcp.json` in a
16
43
  "docs": {
17
44
  "url": "https://example.com/mcp",
18
45
  "headers": { "Authorization": "Bearer ${DOCS_TOKEN}" },
19
- "exposure": "direct"
46
+ "description": "Search and read the product documentation"
20
47
  }
21
48
  }
22
49
  }
23
50
  ```
24
51
 
25
- - stdio servers take `command`, `args`, `env`, and `cwd`. Relative `cwd` resolves against the session directory. A leading `~/` in `command`, an argument, or `cwd` names the home directory.
26
- - HTTP servers take `url`, `headers`, and `oauth` (see [Sign in with OAuth](#sign-in-with-oauth)). The legacy SSE transport is not supported.
27
- - `env` and `headers` values can reference environment variables (`${NAME}`) or commands (`!command`), like provider API keys.
28
- - `timeout` sets the per-request timeout in seconds (default 60). Progress notifications from the server reset it.
29
- - `enabled: false` keeps an entry without connecting to it.
52
+ Stdio servers use `command`, `args`, `env`, and `cwd`. Relative `cwd` values resolve against the session directory. A leading `~/` in `command`, an argument, or `cwd` names the home directory.
30
53
 
31
- Project entries replace global entries with the same name. A project `mcp.json` is only read after the project is trusted, because stdio servers run commands.
54
+ HTTP servers use `url`, `headers`, and `oauth` (see [Authenticate with OAuth](#authenticate-with-oauth)). The legacy SSE transport is not supported.
32
55
 
33
- `knightcode mcp add` and `knightcode mcp remove` edit the file from a shell (see [MCP commands](cli.md#mcp-commands)):
56
+ Both server types support:
34
57
 
35
- ```bash
36
- knightcode mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem .
37
- knightcode mcp add docs --url https://example.com/mcp --bearer-token-env-var DOCS_TOKEN --exposure direct
38
- knightcode mcp add -l tools --env API_KEY='${TOOLS_KEY}' -- uvx tools-mcp
39
- knightcode mcp remove docs
40
- ```
58
+ - `timeout`: per-request timeout in seconds (default 60). Progress notifications reset it.
59
+ - `enabled: false`: keep the entry without connecting to it.
60
+ - `exposure` and `toolExposure`: control how tools reach the model (see [Control tool exposure](#control-tool-exposure)).
61
+ - `description`: what the server offers, in a sentence. For servers with `codemode` or `deferred` tools, it describes the server in the system prompt's server list (see [Control tool exposure](#control-tool-exposure)), tool search ranks the server's tools by it, and codemode's `describeNamespace()` returns it. Without it, the first line of the server instructions is used once the server connects.
62
+
63
+ Keep personal servers and servers with credentials in the user-level file. Use the project file only for servers the project requires, and only in trusted projects.
41
64
 
42
- Rules that are easy to get wrong:
65
+ ### Configuration rules
43
66
 
44
- - Server names may only contain letters, digits, `_`, and `-`. Tools are named `mcp__<server>__<tool>`.
45
- - `type` is optional: a `command` makes a stdio server and a `url` a streamable HTTP server. When present, it must be `stdio`, `http`, or `streamable-http`. `sse` is rejected; most servers that document an SSE endpoint also serve streamable HTTP, often at `/mcp` instead of `/sse`.
46
- - `command` is a single executable and `args` its arguments, not one shell string.
47
- - Keep secrets out of the file: use `${NAME}` for environment variables, as in `"Authorization": "Bearer ${GITHUB_TOKEN}"`, or `!command` to run a command. A command must make up the whole value, so it has to print the header value itself: `"Authorization": "!echo Bearer $(gh auth token)"`.
48
- - Invalid entries are skipped and reported; the other servers still connect.
67
+ - Server names may contain only letters, digits, `_`, and `-`. Tools are named `mcp__<server>__<tool>`, with every character other than letters, digits, and `_` replaced by `_`; tools of a server whose names then collide all get a hash suffix. Server names that differ only in `-` and `_` count as the same server: a second one is rejected, and a `mcp.json` server overrides a registered one.
68
+ - `type` is optional. A `command` selects stdio and a `url` selects streamable HTTP. When present, `type` must be `stdio`, `http`, or `streamable-http`.
69
+ - `sse` is rejected. Servers that document an SSE endpoint often also provide streamable HTTP, commonly at `/mcp` instead of `/sse`.
70
+ - `command` is one executable and `args` contains its arguments. It is not a shell command string.
71
+ - `env` and `headers` values can use environment variables such as `${GITHUB_TOKEN}`. They can also run a command with `!command`, but the command must make up the whole value, for example `"Authorization": "!echo Bearer $(gh auth token)"`.
72
+ - Invalid entries are reported and skipped without preventing other servers from connecting.
49
73
 
50
- ## Set up servers
74
+ `knightcode mcp add` and `knightcode mcp remove` cover common changes from a shell. See [MCP commands](cli.md#mcp-commands) for their options.
51
75
 
52
- When asked to add an MCP server, the agent should:
76
+ ### Inspect or change a server
53
77
 
54
- 1. Add simple servers with `knightcode mcp add` (add `-l` for the project file), or edit `mcp.json` directly for settings the command does not cover. Put personal servers and servers with credentials in `~/.knightcode/agent/mcp.json`. Use the project `.knightcode/mcp.json` only for servers the project itself needs, and only in trusted projects.
55
- 2. Convert entries written for other clients:
56
- - Claude Desktop, Claude Code, and Cursor use the same `mcpServers` shape; copy the entry.
57
- - VS Code uses a top-level `servers` object and `inputs` prompts; move the entry under `mcpServers` and replace `${input:...}` with `${NAME}` environment variables.
58
- - Codex uses TOML (`[mcp_servers.<name>]` with `command`, `args`, `env`, or `url`); write the same fields as JSON.
59
- - opencode uses `"type": "local"` with `command` as an array (split it into `command` and `args`), `"type": "remote"` for URLs, `environment` for `env`, and `{env:NAME}` for `${NAME}`.
60
- 3. Run `knightcode mcp list` to check the entry. It connects to every enabled server and prints the state, the tools, and errors such as the stderr of a stdio server that failed to start. It exits with 1 while anything is wrong.
61
- 4. For a server that needs a sign-in, run `knightcode mcp login <server>`. It opens the authorization page in the user's browser and waits until the user approves access; tell the user to approve it. A running session uses the new credentials on its next turn.
62
- 5. Tell the user to run `/reload` (or start a new session) so the running session connects to added or changed servers.
78
+ `/mcp` lists configured servers with their state, tool count, exposure, and configuration source. Servers that need attention appear first. Select a server to inspect its tools and connection details, reconnect, sign in or out, change exposure, or enable and disable it.
63
79
 
64
- KnightCode connects when a session starts. The first prompt waits up to 10 seconds for startup connections; the tools of servers that take longer become available once they connect. HTTP connections that fail with a network error or a transient status (408, 429, 5xx) are retried twice. A server that drops its connection shows as disconnected and is reconnected on the next call. When a server announces that its tool list changed, new tools are added and withdrawn tools become unreachable until the server offers them again.
80
+ Exposure and enabled-state changes are saved to the file that defines the server without replacing unrelated content. Disabled servers remain listed. Outside the interactive TUI, `/mcp` prints server status; `/mcp login <server>`, `/mcp logout <server>`, and `/mcp reconnect <server>` perform those actions directly.
65
81
 
66
- Config errors, servers that failed to connect, and servers that need a sign-in are reported once after startup.
82
+ Shell commands work without a session: `knightcode mcp add`, `knightcode mcp remove`, `knightcode mcp list`, `knightcode mcp login`, and `knightcode mcp logout`. Shell commands do not load extensions.
67
83
 
68
- Log messages servers send with MCP logging notifications are appended to `~/.knightcode/agent/mcp.log` as `<time> [<server>] <level> <logger>: <message>`. The file is moved to `mcp.log.1` when it grows past 5 MB.
84
+ ### Diagnose connection problems
69
85
 
70
- ## Manage servers
86
+ Run `knightcode mcp list` to connect to every enabled server and print its state, tools, and errors. It exits with status 1 when an entry is invalid or an enabled server is not connected. `/mcp` shows the full connection error and the tail of stderr from a failed stdio server.
71
87
 
72
- `/mcp` opens the server manager. It lists every configured server with its state, tool count, exposure, and whether it comes from the global or the project `mcp.json`; servers that need attention come first. Select a server to:
88
+ KnightCode reports configuration errors, failed connections, and required sign-ins once after startup. Server logging notifications are appended to `~/.knightcode/agent/mcp.log` as `<time> [<server>] <level> <logger>: <message>`. The file moves to `mcp.log.1` after it grows past 5 MB.
73
89
 
74
- - sign in, for OAuth servers that need it (see [Sign in with OAuth](#sign-in-with-oauth))
75
- - see its tools, its command or URL, and the full connection error, including the tail of a stdio server's stderr
76
- - reconnect
77
- - sign out, which deletes the stored OAuth credentials
78
- - change its exposure (see [Exposure](#exposure))
79
- - disable or enable it
90
+ KnightCode connects every enabled server in the background when a session starts. A server's tools appear once it connects; the `codemode` description does not list them, so it does not change when servers connect. The first prompt waits up to 10 seconds only for servers with `direct` tools, which must be declared in its request. Other servers are waited for when they are needed: a codemode script waits for the servers it names (`mcp__<server>`) and, when it calls `searchTools()` or reads `ALL_TOOLS`, for all of them; `tool_search` and the resource tools also wait for all of them. HTTP network errors and transient statuses (408, 429, and 5xx) are retried twice. A dropped connection is shown as disconnected and reconnects on the next call. When a server announces a changed tool list, new tools are added and withdrawn tools become unreachable.
80
91
 
81
- Exposure changes and enabling or disabling are saved to the `mcp.json` that defines the server; other content of the file is kept. Disabled servers stay listed so they can be enabled again.
92
+ Stopping a stdio server closes its stdin, sends SIGTERM, then sends SIGKILL to its process group. This also stops servers launched through wrappers such as `npx` or `uvx`.
82
93
 
83
- Outside the interactive TUI, `/mcp` prints the server status. `/mcp login <server>`, `/mcp logout <server>`, and `/mcp reconnect <server>` run those actions directly.
94
+ ## Migrate configuration from another client
84
95
 
85
- From a shell, `knightcode mcp add`, `knightcode mcp remove`, `knightcode mcp list`, `knightcode mcp login <server>`, and `knightcode mcp logout <server>` manage servers without a session (see [MCP commands](cli.md#mcp-commands)).
96
+ Move the converted entry under `mcpServers` in `mcp.json`, then run `knightcode mcp list` to validate it.
86
97
 
87
- Stopping a stdio server closes its stdin, then sends SIGTERM and finally SIGKILL to its whole process group, so servers started through wrappers such as `npx` or `uvx` do not linger.
98
+ | Client | Conversion |
99
+ |---|---|
100
+ | Claude Desktop, Claude Code, or Cursor | Copy the existing `mcpServers` entry. |
101
+ | VS Code | Move an entry from the top-level `servers` object and replace `${input:...}` prompts with `${NAME}` environment variables. |
102
+ | Codex | Convert `[mcp_servers.<name>]` TOML fields such as `command`, `args`, `env`, and `url` to JSON. |
103
+ | OpenCode | Convert `"type": "local"` to a stdio entry, split its `command` array into `command` and `args`, rename `environment` to `env`, and replace `{env:NAME}` with `${NAME}`. Convert `"type": "remote"` to a URL entry. |
88
104
 
89
- ## Sign in with OAuth
105
+ ## Authenticate with OAuth
90
106
 
91
107
  Remote servers that use OAuth, such as Sentry, need no credentials in `mcp.json`:
92
108
 
@@ -98,11 +114,13 @@ Remote servers that use OAuth, such as Sentry, need no credentials in `mcp.json`
98
114
  }
99
115
  ```
100
116
 
101
- When such a server rejects the connection, `/mcp` shows it as needing sign-in. Select it and choose "Sign in" (or run `/mcp login sentry`, or `knightcode mcp login sentry` in a shell) to open the authorization page in your browser. After you approve access, the browser redirects to a temporary server on `127.0.0.1` and knightcode connects. If the browser runs on another machine, for example over SSH, paste the URL it was redirected to into the sign-in screen instead.
117
+ When the server rejects an unauthenticated connection, `/mcp` shows that it needs sign-in. Select "Sign in", run `/mcp login sentry`, or run `knightcode mcp login sentry`. KnightCode opens the authorization page and waits for approval. If the browser runs on another machine, such as over SSH, paste its redirected URL into the sign-in screen. A running session uses the new credentials on its next turn.
118
+
119
+ KnightCode registers itself with the authorization server, stores tokens in `~/.knightcode/agent/mcp-auth.json`, and refreshes access tokens when they expire or the server rejects them. If a server later requests additional scope, KnightCode asks for sign-in again. Signing out deletes the stored credentials.
102
120
 
103
- KnightCode registers itself with the authorization server (dynamic client registration), stores tokens in `~/.knightcode/agent/mcp-auth.json`, and refreshes access tokens automatically when they expire or the server rejects them. If the server later asks for more scope than was granted, it shows as needing sign-in again, and signing in requests the new scope. "Sign out" in `/mcp` (or `/mcp logout sentry`) deletes the stored credentials.
121
+ Credentials belong to a server name and URL. Servers with the same URL under different names, such as one per account, sign in separately; servers with the same name and URL in different `mcp.json` files share one sign-in.
104
122
 
105
- OAuth applies to HTTP servers without an `Authorization` header. For authorization servers that do not support dynamic client registration, configure a pre-registered client:
123
+ OAuth applies to HTTP servers without an `Authorization` header. For a server that does not support dynamic client registration, configure a registered client:
106
124
 
107
125
  ```json
108
126
  {
@@ -115,21 +133,55 @@ OAuth applies to HTTP servers without an `Authorization` header. For authorizati
115
133
  }
116
134
  ```
117
135
 
118
- The redirect URI must match the one registered for the client. `callbackPort` fixes it to `http://127.0.0.1:<port>/callback`. For another redirect URI, set `callbackUrl`, for example `"callbackUrl": "http://localhost:8080/oauth/callback"`. It must be an `http` URI on `localhost`, `127.0.0.1`, or `[::1]`, and is sent exactly as written. Without a port in `callbackUrl`, knightcode listens on `callbackPort`, or on a free port, and adds it to the URI; authorization servers accept any port for loopback redirects (RFC 8252). `clientSecret` is optional and can reference environment variables or commands.
136
+ The redirect URI must match the registered URI. `callbackPort` uses `http://127.0.0.1:<port>/callback`. To use another URI, set `callbackUrl`; it must use HTTP on `localhost`, `127.0.0.1`, or `[::1]`. KnightCode sends it exactly as written. When `callbackUrl` omits a port, KnightCode uses `callbackPort` or a free port and adds it to the URI, as allowed for loopback redirects by RFC 8252. `clientSecret` is optional and can use an environment variable or command.
119
137
 
120
- `scope` sets the scopes to request, separated by spaces, for servers that do not advertise the ones they need. Without it, knightcode requests the scopes the server advertises. When a server later asks for more scope, knightcode requests those on top of `scope`.
138
+ Set `scope` to a space-separated list for servers that do not advertise their required scopes. Otherwise, KnightCode requests the advertised scopes. Later scope requests are added to the configured value.
121
139
 
122
- ## Exposure
140
+ KnightCode registers as `knightcode`. Some servers only accept registrations from known clients. Set `clientName` to send another name:
123
141
 
124
- Each server's tools are registered as `mcp__<server>__<tool>`. The `exposure` setting controls how the model reaches them:
142
+ ```json
143
+ {
144
+ "mcpServers": {
145
+ "figma": { "url": "https://mcp.figma.com/mcp", "oauth": { "clientName": "Claude Code" } }
146
+ }
147
+ }
148
+ ```
125
149
 
126
- - `codemode` (default): the tools are callable from [`codemode`](cli.md#tools) scripts and listed in the `codemode` tool's description, but are not declared to the model. Large MCP tool lists stay out of the model's tool declarations, and scripts can call several MCP tools, in parallel if needed, while returning only the part of the result the model needs. KnightCode activates the `codemode` tool when such a server connects. Large servers do not fill the description: declarations share a token budget, and scripts find the remaining tools with `searchTools()` (see [`codemode`](cli.md#tools)).
127
- - `codemode-deferred`: like `codemode`, but the tools are not listed in the `codemode` tool's description either; it only names the server and its tool count. Scripts call them by name and find them with `searchTools()` or in `ALL_TOOLS`. Use it for large servers that codemode scripts use rarely.
128
- - `deferred`: the tools are not declared to the model until the [`tool_search`](cli.md#tools) tool loads them. The model searches, and the matches are declared from its next call on and called directly, without codemode. KnightCode activates the `tool_search` tool when such a server connects. Use it for large servers without codemode.
129
- - `direct`: the tools are declared to the model like built-in tools, and are also callable from codemode.
130
- - `hidden`: the tools are registered but cannot be called.
150
+ The name is only sent when KnightCode registers a client. To register again under a new name, sign out first.
131
151
 
132
- `toolExposure` sets the exposure of single tools and overrides `exposure` for them. Keys are tool names as the server offers them, or patterns where `*` matches any characters. An exact name wins over patterns; among patterns, the first match in the object wins. With `hidden` as the server's exposure, only the listed tools are reachable:
152
+ KnightCode finds the authorization server through the server's protected resource metadata (RFC 9728) and checks that the authorization server's metadata names the expected issuer (RFC 8414). Some servers advertise the wrong authorization server or none, so sign-in opens a page that does not exist. Set `authServerMetadataUrl` to the metadata document of the right authorization server:
153
+
154
+ ```json
155
+ {
156
+ "mcpServers": {
157
+ "example": {
158
+ "url": "https://mcp.example.com/mcp",
159
+ "oauth": { "authServerMetadataUrl": "https://example.okta.com/.well-known/openid-configuration" }
160
+ }
161
+ }
162
+ }
163
+ ```
164
+
165
+ KnightCode uses that document instead of discovery and trusts it as configured, so only point it at a document you trust. The URL must use HTTPS, except on `localhost`, `127.0.0.1`, or `[::1]`.
166
+
167
+ ## Control tool exposure
168
+
169
+ Each server tool is registered as `mcp__<server>__<tool>`. The server's `exposure` determines how the model reaches it:
170
+
171
+ | Exposure | Behavior | Typical use |
172
+ |---|---|---|
173
+ | `codemode` (default) | Callable from [`codemode`](cli.md#tools) scripts, but neither declared to the model nor listed in the codemode description. Scripts find tools with `searchTools()`, `describeTool()`, or `ALL_TOOLS`. | General MCP servers, especially when scripts should combine or filter calls. |
174
+ | `deferred` | Not declared until [`tool_search`](cli.md#tools) loads a match for the next model call. | Large servers whose tools should be called directly after discovery. |
175
+ | `direct` | Declared to the model like a built-in tool and also callable from codemode. | Small, frequently used tool sets. |
176
+ | `hidden` | Registered but unreachable. | Servers or tools that should remain unavailable. |
177
+
178
+ `codemode-deferred` is accepted as an alias for `codemode`.
179
+
180
+ Servers with `codemode` or `deferred` tools are listed in the `mcp_servers` section of the system prompt, with how their tools are reached and one line from the configured `description` or, once connected, from the server instructions. KnightCode updates the section when a prompt starts, after waiting for servers with `direct` tools. When it changed, for example because a server connected and its summary became available, KnightCode appends the new section to the conversation instead of changing tool declarations, so earlier messages stay cached. `describeNamespace()` and the `namespace` option of `searchTools()` accept `mcp__dev-radius`, `mcp__dev_radius`, `dev-radius`, or `dev_radius`.
181
+
182
+ KnightCode activates `codemode` when a server with `codemode` exposure connects. It activates `tool_search` for a server with `deferred` exposure. To make the model see a tool without searching, give it `direct` exposure with `toolExposure`.
183
+
184
+ `toolExposure` overrides the server exposure for individual tools. Keys are exact server tool names or patterns where `*` matches any characters. Exact names win over patterns; among patterns, the first match wins. A server with `hidden` exposure can expose only selected tools:
133
185
 
134
186
  ```json
135
187
  {
@@ -147,42 +199,50 @@ Each server's tools are registered as `mcp__<server>__<tool>`. The `exposure` se
147
199
  }
148
200
  ```
149
201
 
150
- `knightcode mcp list` marks tools whose exposure differs from the server's, and the Tools view in `/mcp` shows it too.
202
+ `knightcode mcp list` marks tools whose exposure differs from their server. The Tools view in `/mcp` also shows the effective exposure.
151
203
 
152
- Tools that are not declared (`codemode`, `codemode-deferred`, and `deferred` exposure) are reachable through either tool: codemode scripts can call all of them, and `tool_search` can load any of them. For example, with `codemode` active, scripts can call the tools of a `deferred` server, and with `tool_search` active, the model can load the tools of a `codemode` server.
204
+ Tools with `codemode` or `deferred` exposure can be reached through either indirect mechanism: codemode scripts can call them, and `tool_search` can load them. Codemode calls do not depend on the active tool set, so they remain available after `/tree`, resume, and fork. Tools loaded by `tool_search` are recorded in the transcript and remain declared on that branch.
153
205
 
154
- Tools called from codemode scripts do not depend on the active tool set, so they stay callable after `/tree`, resume, and fork. Tools loaded by `tool_search` are recorded in the transcript like any other tool change and stay declared on that branch. To keep `codemode` active without MCP servers too, add `"defaultTools": ["+codemode"]` to [settings](settings.md#tools). To keep knightcode from activating the `codemode` tool, set `"autoEnableCodemode": false` at the top level of `mcp.json`, next to `mcpServers`. A project `mcp.json` value overrides the global one. KnightCode warns once when neither `codemode` nor `tool_search` is active, since the tools then cannot be called.
206
+ To keep `codemode` active without MCP servers, add `"defaultTools": ["+codemode"]` to [settings](settings.md#tools). To prevent automatic codemode activation, set `"autoEnableCodemode": false` beside `mcpServers`. A project value overrides the user-level value. KnightCode warns once when neither `codemode` nor `tool_search` is active and non-direct tools cannot be called.
155
207
 
156
- Text results over 20KB reach the model with the middle cut out, in the format Codex uses: the start and end of the text around a `…N chars truncated…` marker. The full text is saved to a temp file whose path the result names. Codemode scripts always receive the whole result, so a script can filter a large result down to what the model needs.
208
+ Text results over 20 KB reach the model with their middle removed around a `…N chars truncated…` marker. The full text is saved to a temporary file named in the result. Codemode scripts receive the complete result and can reduce it before returning output to the model.
157
209
 
158
- Codemode scripts receive an MCP tool's whole `CallToolResult` (`content` blocks as sent by the server, `structuredContent`, and `isError`), and the `codemode` description declares it as `CallToolResult<T>`. A result with `isError` resolves in scripts and is reported to the model as an error for direct calls. `image(result.content[0])` forwards an image block to the model. The server's `instructions` describe its tools in the `codemode` description.
210
+ Codemode scripts receive the complete MCP `CallToolResult`, including `content`, `structuredContent`, and `isError`. A result with `isError` resolves inside scripts but is reported as an error for direct calls. `image(result.content[0])` forwards an image block. Server instructions are not part of any tool description; scripts read them with `describeNamespace("mcp__<server>")`, which also returns the server's tool names.
159
211
 
160
- ## Resources
212
+ ## Use resources
161
213
 
162
- When a connected server offers [resources](https://modelcontextprotocol.io/specification/2025-11-25/server/resources), knightcode adds the resource tools Codex and opencode use:
214
+ When a connected server offers [resources](https://modelcontextprotocol.io/specification/2025-11-25/server/resources), KnightCode adds the resource tools used by Codex and OpenCode:
163
215
 
164
- - `list_mcp_resources` lists resources as JSON: `{ server?, resources: [{ server, uri, name, ... }], nextCursor? }`. With `server`, it lists one page of that server, and `cursor` continues with the next one. Without, it lists every resource of every server.
165
- - `list_mcp_resource_templates` lists URI templates for resources the servers do not list, in the same way.
166
- - `read_mcp_resource` reads a resource given `server` and `uri`. Text resources reach the model as text and images as images; other binary resources are saved to temp files, and the model sees the file path. Scripts receive `{ server, uri, contents }`.
216
+ - `list_mcp_resources` lists resources as JSON: `{ server?, resources: [{ server, uri, name, ... }], nextCursor? }`. With `server`, it lists one page; `cursor` continues with the next page. Without `server`, it lists every resource from every server.
217
+ - `list_mcp_resource_templates` lists URI templates for resources the servers do not list directly.
218
+ - `read_mcp_resource` reads a resource by `server` and `uri`. Text reaches the model as text and images as images. Other binary resources are saved to temporary files, and the model receives the path. Scripts receive `{ server, uri, contents }`.
167
219
 
168
- The tools reach every enabled server with resources whose exposure is not `hidden`, and take the widest exposure among them: `direct` if one of the servers is direct, else `codemode`, else `codemode-deferred`, else `deferred`. Resource links in tool results name `read_mcp_resource` and the server.
220
+ These tools reach every enabled, non-hidden server with resources. Their exposure is the widest exposure among those servers: `direct`, then `codemode` or `deferred`. Resource links in tool results identify `read_mcp_resource` and the server.
169
221
 
170
- Resources for MCP Apps (`ui://` URIs or `text/html;profile=mcp-app`) are left out of the listings, since knightcode does not render them, and so are resource icons.
222
+ Resources for MCP Apps, identified by `ui://` URIs or `text/html;profile=mcp-app`, are omitted because KnightCode does not render them. Resource icons are also omitted.
171
223
 
172
- Reading and listing resources is retried once after a transient HTTP error (408, 429, 5xx). Tool calls are not retried, since the server may have run them.
224
+ Reading and listing resources is retried once after a transient HTTP error (408, 429, or 5xx). Tool calls are not retried because the server may already have performed them.
173
225
 
174
226
  ## Permissions
175
227
 
176
- Every MCP call goes through knightcode's tool pipeline, so `tool_call` and `tool_result` extension handlers, including permission gates, apply to MCP tools. Calls made from codemode scripts carry the `codemode` call's id as `parentToolCallId`. `knightcode.getAllTools()` reports the tool annotations servers declare (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`), so a permission extension can confirm only calls that change something (see [Extensions](extensions.md#tool-exposure)). The resource tools are marked read-only.
228
+ Every MCP call passes through KnightCode's tool pipeline. Extension `tool_call` and `tool_result` handlers, including permission gates, therefore apply to MCP tools. Calls made from codemode scripts carry the codemode call ID as `parentToolCallId`.
229
+
230
+ `knightcode.getAllTools()` reports the annotations declared by each server: `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint`. Permission extensions can use these hints to decide which calls require confirmation (see [Tool exposure](extensions.md#tool-exposure)). Resource tools are marked read-only.
231
+
232
+ ## Extensions and SDK
233
+
234
+ ### Add servers from extensions
235
+
236
+ Extensions can add servers for the current session with `knightcode.registerMcpServer(name, config)`, using the same shape as an `mcpServers` entry (see [MCP servers in extensions](extensions.md#mcp-servers)). Registered servers connect like configured servers and appear in `/mcp` with the extension as their source.
177
237
 
178
- ## Servers from extensions
238
+ Changes to enabled state or exposure apply only to the current session. A file-configured server with the same name takes precedence, and `/mcp` lists the overridden registration. `knightcode mcp` shell commands do not load extensions and only see file-configured servers.
179
239
 
180
- Extensions can add servers for the current session with `knightcode.registerMcpServer(name, config)`, using the same config shape as `mcp.json` (see [Extensions](extensions.md#mcp-servers)). They connect like configured servers and appear in `/mcp` with the extension as their source. Enabling, disabling, and exposure changes for them apply to the current session only. A server in `mcp.json` with the same name takes precedence; `/mcp` lists the overridden registration. `knightcode mcp` shell commands do not load extensions and only see `mcp.json` servers.
240
+ ### Replace the built-in MCP support
181
241
 
182
- ## Other MCP extensions
242
+ An installed extension that registers `/mcp`, such as `knightcode-mcp-adapter`, replaces the built-in MCP support for sessions. KnightCode then does not read `mcp.json` or connect its servers in a session, and `/mcp` belongs to the extension. Remove the extension to restore the built-in behavior. To disable built-in MCP support without a replacement, disable `mcp` under Built-in in `knightcode config`, or set `"extensions": ["-builtin:mcp"]` in [settings](settings.md#resources).
183
243
 
184
- An installed extension that registers the `/mcp` command, such as `knightcode-mcp-adapter`, replaces the built-in MCP support: knightcode then neither reads `mcp.json` in sessions nor connects servers, and `/mcp` belongs to that extension. Remove the extension to use the built-in support. To turn off the built-in support without installing another extension, disable `mcp` under Built-in in `knightcode config`, or set `"extensions": ["-builtin:mcp"]` in [settings](settings.md#resources); `knightcode mcp` shell commands still work. Likewise, an extension that registers a tool named `codemode` or `tool_search` replaces the built-in tool of that name. `knightcode mcp` shell commands always use the built-in support.
244
+ An extension that registers `codemode` or `tool_search` similarly replaces the built-in tool with that name. Shell-level `knightcode mcp` commands always use the built-in implementation.
185
245
 
186
- ## SDK
246
+ ### Use MCP from the SDK
187
247
 
188
- SDK sessions do not load the built-in extensions. Add the MCP extension, the codemode extension for `codemode` and `codemode-deferred` servers, and the tool search extension for `deferred` servers to the resource loader. See [SDK](sdk.md#codemode-mcp).
248
+ SDK sessions do not load built-in extensions. Add the MCP extension, the codemode extension for `codemode` servers, and the tool-search extension for `deferred` servers to the resource loader. See [Codemode and MCP](sdk.md#codemode-mcp).
@@ -18,7 +18,7 @@ Browse the [model catalog](https://knightcode.dev/models) for current providers,
18
18
 
19
19
  Run `/login` and select a provider. KnightCode stores credentials in [`auth.json`](configuration.md#agent-directory). Run `/logout` to remove stored credentials for a provider.
20
20
 
21
- You can instead provide an API key through the provider's environment variable. This is useful in CI and other environments where KnightCode should not write credentials. [Provider Authentication](providers.md) lists the variables and cloud-provider setup.
21
+ You can instead provide an API key through the provider's environment variable. This is useful in CI and other environments where KnightCode should not write credentials. [Providers](providers.md) lists the variables and provider-specific setup.
22
22
 
23
23
  When several credential sources are configured, KnightCode uses a runtime `--api-key` first, then a stored `auth.json` credential, an `apiKey` from `models.json`, and finally the provider's environment variables or ambient cloud credentials. Provider extensions can define their own authentication behavior.
24
24
 
@@ -131,10 +131,31 @@ const result = await models.classify(jev, {
131
131
  return result.answers;
132
132
  ```
133
133
 
134
+ [Codemode](codemode.md#classify) describes the question and answer types.
135
+
134
136
  When the service reports token counts, as all System One services do, `result.usage` carries them with their cost. KnightCode adds the usage of a script's classifier calls to the `codemode` tool result, so it counts toward the session cost in the footer and `/session`. The cost uses the model's catalog price; models without one, such as TypeSafe's direct `jev-latest`, report tokens at no cost.
135
137
 
136
138
  Extensions call classifiers through `ctx.modelRegistry.classify()`, without codemode. [Virtual models](virtual-models.md#route-requests) can use them to route requests; see the `jev-router.ts` example.
137
139
 
140
+ ## Use image models
141
+
142
+ Image models generate images from a prompt and optional input images. KnightCode lists OpenRouter's image models, such as `google/gemini-2.5-flash-image` and `black-forest-labs/flux.2-pro`, under the `openrouter` provider; they use the same `OPENROUTER_API_KEY` or `/login` credential as its chat models.
143
+
144
+ Like classifier models, image models do not appear in `/model`; the model reaches them through the [`codemode`](cli.md#enable-codemode) tool. Scripts list them with `models.getAvailableOfType("image")` and call `models.generateImages(model, { input })`. The result's `output` holds base64 image blocks, which `image()` attaches to the `codemode` result so the model sees them:
145
+
146
+ ```js
147
+ const painter = await models.getModelOfType("image", "openrouter", "google/gemini-2.5-flash-image");
148
+ const result = await models.generateImages(painter, {
149
+ input: [{ type: "text", text: "A red fox in the snow, watercolor" }],
150
+ });
151
+ if (result.stopReason !== "stop") return result.errorMessage;
152
+ for (const block of result.output) if (block.type === "image") image(block);
153
+ ```
154
+
155
+ `input` can also contain `{ type: "image", data, mimeType }` blocks to edit or use as references. KnightCode adds the usage of a script's image calls to the `codemode` tool result, like classifier calls. Generated images are not saved to disk. [Codemode](codemode.md#generate-images) describes the full API.
156
+
157
+ Extensions generate images through `ctx.modelRegistry.generateImages()`, without codemode.
158
+
138
159
  ## Add a custom provider
139
160
 
140
161
  Use an extension when the provider needs custom streaming, model discovery, or authentication behavior. See [Custom Providers](custom-provider.md) for the extension workflow.
@@ -1,4 +1,4 @@
1
- # Provider Authentication
1
+ # Providers
2
2
 
3
3
  Most hosted providers support one or both of these authentication methods:
4
4
 
@@ -17,8 +17,6 @@ Run `/logout` and select a provider to remove its stored credential. This does n
17
17
 
18
18
  `auth.json` can contain API keys and OAuth tokens. Keep it private and do not commit it.
19
19
 
20
- Radius authentication uses its gateway catalog and caches refreshed model metadata for later offline startup. A custom Radius gateway configured in `models.json` uses its own catalog rather than inheriting the public `radius.pi.dev` catalog.
21
-
22
20
  ## Use an API key from the environment
23
21
 
24
22
  Environment variables are useful in CI and anywhere KnightCode should not store the key. Set the variable before starting KnightCode:
@@ -28,7 +26,7 @@ export ANTHROPIC_API_KEY=sk-ant-...
28
26
  knightcode
29
27
  ```
30
28
 
31
- This table covers providers with a single primary API-key variable. Providers that need additional configuration or support ambient credentials are covered under [Cloud providers](#cloud-providers).
29
+ This table covers providers with a single primary API-key variable. Providers that need additional configuration or support ambient credentials are covered under [Provider Specific Config](#provider-specific-config).
32
30
 
33
31
  | Provider | Environment variable |
34
32
  |---|---|
@@ -69,6 +67,8 @@ This table covers providers with a single primary API-key variable. Providers th
69
67
 
70
68
  Anthropic also recognizes `ANTHROPIC_OAUTH_TOKEN` as an API credential and `ANTHROPIC_AUTH_TOKEN` as bearer authentication.
71
69
 
70
+ With no key or token set, Anthropic uses workload identity federation when `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID` and `ANTHROPIC_IDENTITY_TOKEN_FILE` are set: the Anthropic SDK exchanges the identity token for a short-lived access token and refreshes it itself (re-reading the identity token file, so keep that file fresh for long sessions). `ANTHROPIC_SERVICE_ACCOUNT_ID` and `ANTHROPIC_WORKSPACE_ID` are passed through when set.
71
+
72
72
  ## Load an API key from a command
73
73
 
74
74
  To use a secret manager without writing the resolved key to disk, set a provider's `key` in `auth.json` to a command prefixed with `!`:
@@ -84,9 +84,9 @@ To use a secret manager without writing the resolved key to disk, set a provider
84
84
 
85
85
  KnightCode runs the command when the key is first needed and caches its standard output for the process lifetime. Empty output, a timeout, or a nonzero exit leaves the key unresolved until KnightCode restarts.
86
86
 
87
- ## Cloud Providers
87
+ ## Provider Specific Config
88
88
 
89
- The providers below need additional settings or can use credentials supplied by their cloud platform.
89
+ The providers below have additional setup, need additional settings, or can use credentials supplied by their platform.
90
90
 
91
91
  A stored API-key credential can include an `env` object. Its values take priority over the process environment for that provider:
92
92
 
@@ -102,6 +102,18 @@ A stored API-key credential can include an `env` object. Its values take priorit
102
102
  }
103
103
  ```
104
104
 
105
+ ### Radius
106
+
107
+ Radius is a service crafted for KnightCode by the builders of KnightCode, Earendil Works. It provides a customizable AI gateway with organization-level controls and analytics built in, and artifacts for sharing what you create with KnightCode.
108
+
109
+ To get started, run `/login radius` in KnightCode. This adds Radius as a provider, and its models appear in `/model` like any other provider's.
110
+
111
+ Radius also has an MCP server, so KnightCode can manage Radius for you.
112
+
113
+ Radius is currently in early alpha and evolving quickly. See [radius.earendil.com](https://radius.earendil.com) for more.
114
+
115
+ Radius authentication uses its gateway catalog and caches refreshed model metadata for later offline startup. A custom Radius gateway configured in `models.json` uses its own catalog rather than inheriting the public `radius.pi.dev` catalog.
116
+
105
117
  ### Azure OpenAI
106
118
 
107
119
  Set an API key plus either a base URL or resource name:
package/bin/docs/sdk.md CHANGED
@@ -113,7 +113,7 @@ Inline extension factories can be supplied through `DefaultResourceLoader`. Give
113
113
 
114
114
  <a id="codemode-mcp"></a>
115
115
 
116
- The CLI loads `codemode`, `tool_search`, and MCP as built-in extensions. SDK sessions do not; add `createCodemodeExtension()`, `createToolSearchExtension()`, and `createMcpExtension()` to the `extensionFactories` of `DefaultResourceLoader`. `codemode` and `tool_search` are registered inactive: enable them through the `defaultTools` setting (`["+codemode", "+tool_search"]` keeps the other default tools), or let the MCP extension activate them: `codemode` for servers with `codemode` or `codemode-deferred` exposure, `tool_search` for servers with `deferred` exposure. The MCP extension connects its servers on `session_start`, so call `session.bindExtensions()`. See [Codemode and MCP](../examples/sdk/14-codemode-mcp.ts).
116
+ The CLI loads `codemode`, `tool_search`, and MCP as built-in extensions. SDK sessions do not; add `createCodemodeExtension()`, `createToolSearchExtension()`, and `createMcpExtension()` to the `extensionFactories` of `DefaultResourceLoader`. `codemode` and `tool_search` are registered inactive: enable them through the `defaultTools` setting (`["+codemode", "+tool_search"]` keeps the other default tools), or let the MCP extension activate them: `codemode` for servers with `codemode` exposure, `tool_search` for servers with `deferred` exposure. The MCP extension connects its servers on `session_start`, so call `session.bindExtensions()`. See [Codemode and MCP](../examples/sdk/14-codemode-mcp.ts).
117
117
 
118
118
  See the focused examples for [models](../examples/sdk/02-custom-model.ts), [tools](../examples/sdk/05-tools.ts), [extensions](../examples/sdk/06-extensions.ts), and [full control](../examples/sdk/12-full-control.ts).
119
119
 
@@ -140,7 +140,7 @@ See the focused examples for [models](../examples/sdk/02-custom-model.ts), [tool
140
140
 
141
141
  ## Resources
142
142
 
143
- - [Choose a Model](models.md) covers model selection and compatible endpoints; [Provider Authentication](providers.md) covers credentials and cloud-provider setup.
143
+ - [Choose a Model](models.md) covers model selection and compatible endpoints; [Providers](providers.md) covers credentials and provider-specific setup.
144
144
  - [Configuration](configuration.md) explains normal discovery and settings; [Settings](settings.md) lists every setting.
145
145
  - [Sessions and Context](sessions.md) explains session behavior; [Session Format](session-format.md) defines persisted entries; [Message Types](message-types.md) defines shared transcript values.
146
146
  - [Extensions](extensions.md), [Skills](skills.md), and [Prompt Templates](prompt-templates.md) document resources supplied through a `ResourceLoader`.
@@ -38,7 +38,7 @@ See [Choose a Model](models.md) for model selection and thinking controls.
38
38
  | Setting | Type | Default | Description |
39
39
  |---|---|---|---|
40
40
  | `defaultTools` | `string[]` | `read`, `bash`, `edit`, `write` | Tools enabled at startup. Plain names replace the defaults; `+name` adds a tool and `-name` removes one. An empty array disables all built-in tools but not extension or SDK tools. |
41
- | `codemode.mode` | `"on"` \| `"only"` | `"on"` | How the `codemode` tool presents tools while it is active. `on`: declared tools get their `codemode` declaration appended to their description, and `codemode` lists only tools that are not declared (MCP `codemode` exposure). `only`: `codemode` lists every tool scripts can call, and active built-in and extension tools are hidden from the model, so it reaches them through `codemode`. |
41
+ | `codemode.mode` | `"on"` \| `"only"` | `"on"` | How the `codemode` tool presents tools while it is active. `on`: declared tools get a note on calling them from scripts appended to their description, and `codemode` lists only tools that are not declared. `only`: `codemode` lists every tool scripts can call, and active built-in and extension tools are hidden from the model, so it reaches them through `codemode`. |
42
42
  | `codemode.inlineBudget` | number | `3000` | Estimated tokens (characters / 4) the `codemode` tool's description may spend on tool declarations. Tools that do not fit are left out and found with `searchTools()`. `0` lists only namespaces. |
43
43
 
44
44
  Available built-in tools are `read`, `bash`, `powershell`, `edit`, `write`, `grep`, `find`, and `ls`. `defaultTools` can also name `codemode` and `tool_search`, which built-in extensions register inactive, and other extension tools registered inactive.
@@ -53,6 +53,8 @@ A list of only `+name` and `-name` entries changes the inherited selection inste
53
53
 
54
54
  This replaces `bash` with `powershell` and enables `grep`: `["-bash", "+powershell", "+grep"]`. Project settings apply on top of user settings: a project list with only `+name` and `-name` entries changes the user's selection, and a project list with a plain name replaces it. In one list, plain names form the selection, and `+name` and `-name` then apply in order.
55
55
 
56
+ `/reload` enables tools newly added to `defaultTools`. It does not disable tools removed from it or re-enable unchanged tools you turned off. `--tools`, `--no-tools`, and `--no-builtin-tools` override `defaultTools`, also on reload.
57
+
56
58
  CLI tool options override this setting for one invocation; `--tools` does not accept `+name` or `-name`. See [Command Line](cli.md#tools).
57
59
 
58
60
  The [web tools](usage.md#web-tools) `webfetch` and `websearch` are not part of `defaultTools`. `/tools` turns them on and stores their settings, including the search provider and Brave key, in `~/.knightcode/agent/tools.json`.
@@ -90,8 +92,8 @@ See [Compaction Reference](compaction.md) for trigger, summarization, and valida
90
92
  | Setting | Type | Default | Description |
91
93
  |---|---|---|---|
92
94
  | `theme` | string | `"system"` | Built-in or custom theme name. `system` derives colors from the terminal theme. |
93
- | `quietStartup` | boolean | `false` | Hide the startup header. |
94
- | `tuiMode` | `"regular" \| "fullscreen"` | `"regular"` | Interactive terminal UI mode. Fullscreen captures the mouse and owns text selection, so dragging copies to the clipboard; regular leaves selection and copying to the terminal emulator (see [Text selection and copy](terminal-setup.md#text-selection-and-copy)). |
95
+ | `quietStartup` | boolean \| `"header"` | `false` | `true` hides the startup header and loaded-resource listing. `"header"` keeps the header (version and key hints) but hides the model scope line and loaded-resource listing. |
96
+ | `tuiMode` | `"regular" \| "fullscreen"` | `"fullscreen"` | Interactive terminal UI mode. Fullscreen captures the mouse and owns text selection, so dragging copies to the clipboard; regular leaves selection and copying to the terminal emulator (see [Text selection and copy](terminal-setup.md#text-selection-and-copy)). |
95
97
  | `fullscreenExitOutput` | `"transcript" \| "resume-hint"` | `"transcript"` | Output printed when fullscreen mode exits. |
96
98
  | `fullscreenScrollbar` | `"auto" \| "always" \| "hidden"` | `"auto"` | Fullscreen transcript scrollbar behavior. |
97
99
  | `fullscreenCopyOnSelect` | boolean | `true` | Copy selected text automatically in fullscreen mode. When disabled, selections stay highlighted and `Ctrl+X` copies the active selection. Has no effect in regular mode. |
package/bin/docs/usage.md CHANGED
@@ -132,7 +132,7 @@ Use `/share` to upload the session and get a viewer link. With Radius authentica
132
132
 
133
133
  ## Adjust the terminal
134
134
 
135
- Regular mode uses the terminal's normal scrollback. Fullscreen mode keeps the editor and status area fixed while the transcript scrolls within the terminal window. Choose a mode through `/settings` or `--tui-mode`.
135
+ Fullscreen mode, the default, keeps the editor and status area fixed while the transcript scrolls within the terminal window. Regular mode uses the terminal's normal scrollback. Choose a mode through `/settings` or `--tui-mode`.
136
136
 
137
137
  Terminal support for mouse input, keyboard shortcuts, and inline images varies. See [Terminal Setup](terminal-setup.md) for platform-specific configuration and [Keybindings](keybindings.md) for every configurable shortcut. Run `/hotkeys` to inspect the shortcuts active in your current session.
138
138
 
package/bin/knightcode CHANGED
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/bin/knightcode
3
- size: 111880624 bytes
4
- sha256: ea5aea1a002484879d9ddf4cfc0dc81b7a1109c4d4641438a1bde0b2ec46deb4
3
+ size: 111763925 bytes
4
+ sha256: 0922f0af159ed94b8fb11ed65d78fd465edcaf819dd11cdf247e747f1b23853b
package/bin/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knightcodeai/cli",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "description": "KnightCode — a local, BYOK terminal coding agent powered by OpenRouter.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -37,11 +37,11 @@
37
37
  "test": "vitest --run"
38
38
  },
39
39
  "optionalDependencies": {
40
- "@knightcodeai/cli-linux-x64": "0.11.1",
41
- "@knightcodeai/cli-linux-arm64": "0.11.1",
42
- "@knightcodeai/cli-darwin-x64": "0.11.1",
43
- "@knightcodeai/cli-darwin-arm64": "0.11.1",
44
- "@knightcodeai/cli-win32-x64": "0.11.1"
40
+ "@knightcodeai/cli-linux-x64": "0.11.3",
41
+ "@knightcodeai/cli-linux-arm64": "0.11.3",
42
+ "@knightcodeai/cli-darwin-x64": "0.11.3",
43
+ "@knightcodeai/cli-darwin-arm64": "0.11.3",
44
+ "@knightcodeai/cli-win32-x64": "0.11.3"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@agentclientprotocol/sdk": "1.4.0",
@@ -54,7 +54,6 @@
54
54
  "@knightcode/remote": "workspace:*",
55
55
  "@knightcode/tools": "workspace:*",
56
56
  "@knightcode/server": "workspace:*",
57
- "@knightcode/session-backend-sqlite": "workspace:*",
58
57
  "@knightcode/tui": "workspace:*",
59
58
  "@silvia-odwyer/photon-node": "0.3.4",
60
59
  "@types/cross-spawn": "6.0.6",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knightcodeai/cli-linux-arm64",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",