@knightcodeai/cli 0.17.3 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/CHANGELOG.md +1293 -0
  2. package/README.md +2 -2
  3. package/dist/bundle/chunks/anthropic-messages-A2IH2IY3.js +6 -0
  4. package/dist/bundle/chunks/anthropic.js +101 -0
  5. package/dist/bundle/chunks/azure-openai-responses-XZILQZOG.js +2 -0
  6. package/dist/bundle/chunks/bedrock-converse-stream.js +89 -0
  7. package/dist/bundle/chunks/chunk-4CRI7BMY.js +2 -0
  8. package/dist/bundle/chunks/chunk-57BPR4HF.js +2 -0
  9. package/dist/bundle/chunks/chunk-A5LJINMT.js +2 -0
  10. package/dist/bundle/chunks/chunk-AANBXVWQ.js +2 -0
  11. package/dist/bundle/chunks/chunk-ACHHEROF.js +7 -0
  12. package/dist/bundle/chunks/chunk-AFR2OW6S.js +108 -0
  13. package/dist/bundle/chunks/chunk-AHB7JV5B.js +2 -0
  14. package/dist/bundle/chunks/chunk-B2FT7RH5.js +2 -0
  15. package/dist/bundle/chunks/chunk-BRKUE2MD.js +2 -0
  16. package/dist/bundle/chunks/chunk-DKOURXGU.js +2 -0
  17. package/dist/bundle/chunks/chunk-DVFCXHT4.js +2 -0
  18. package/dist/bundle/chunks/chunk-EPYT326Y.js +30 -0
  19. package/dist/bundle/chunks/chunk-ETOMYYZC.js +2 -0
  20. package/dist/bundle/chunks/chunk-FA32X2UJ.js +7 -0
  21. package/dist/bundle/chunks/chunk-FHM6KUY3.js +44 -0
  22. package/dist/bundle/chunks/chunk-FO7CEQB3.js +11 -0
  23. package/dist/bundle/chunks/chunk-GHVXUCGU.js +130 -0
  24. package/dist/bundle/chunks/chunk-HHWP56PR.js +2 -0
  25. package/dist/bundle/chunks/chunk-HSL72VZI.js +2 -0
  26. package/dist/bundle/chunks/chunk-HUQB436V.js +2 -0
  27. package/dist/bundle/chunks/chunk-HWXGL4YB.js +2 -0
  28. package/dist/bundle/chunks/chunk-KQKUEQJA.js +6 -0
  29. package/dist/bundle/chunks/chunk-M5GCRGV6.js +1333 -0
  30. package/dist/bundle/chunks/chunk-MB4QRS7Y.js +9 -0
  31. package/dist/bundle/chunks/chunk-MXIWLMNT.js +8 -0
  32. package/dist/bundle/chunks/chunk-N6VDWLND.js +2 -0
  33. package/dist/bundle/chunks/chunk-NCIBB66G.js +2 -0
  34. package/dist/bundle/chunks/chunk-NDQ5OW6U.js +2 -0
  35. package/dist/bundle/chunks/chunk-NNCIIYD6.js +2 -0
  36. package/dist/bundle/chunks/chunk-O6JSP6YG.js +6 -0
  37. package/dist/bundle/chunks/chunk-OFST7FDG.js +2 -0
  38. package/dist/bundle/chunks/chunk-SPAUY3RD.js +12 -0
  39. package/dist/bundle/chunks/chunk-U5XE4RWR.js +2 -0
  40. package/dist/bundle/chunks/chunk-UZWP3NHW.js +2 -0
  41. package/dist/bundle/chunks/chunk-V5ANFNKF.js +11 -0
  42. package/dist/bundle/chunks/chunk-VJJ6J35N.js +20 -0
  43. package/dist/bundle/chunks/chunk-XIRAUXOE.js +58 -0
  44. package/dist/bundle/chunks/chunk-ZW7FVRHT.js +31 -0
  45. package/dist/bundle/chunks/cli-6ZTWO6GL.js +51 -0
  46. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-6E2UM7IG.js +2 -0
  47. package/dist/bundle/chunks/codemode-worker.js +478 -0
  48. package/dist/bundle/chunks/dist-DKI7Q6GY.js +13 -0
  49. package/dist/bundle/chunks/easter-egg-3d-FDCGDUF3.js +2 -0
  50. package/dist/bundle/chunks/execute-VSDU5VSN.js +499 -0
  51. package/dist/bundle/chunks/github-copilot.js +2 -0
  52. package/dist/bundle/chunks/google-generative-ai-CSWR3ORZ.js +2 -0
  53. package/dist/bundle/chunks/google-vertex-QIDRFOFB.js +2 -0
  54. package/dist/bundle/chunks/image-resize-worker.js +2 -0
  55. package/dist/bundle/chunks/jiti-loader-BXVX3Y2R.js +21 -0
  56. package/dist/bundle/chunks/jiti-static-loader-NNBCFAO5.js +2 -0
  57. package/dist/bundle/chunks/kimi-coding.js +2 -0
  58. package/dist/bundle/chunks/knightcode-messages-3GNOTMSI.js +8 -0
  59. package/dist/bundle/chunks/lib-IHWMWJDR.js +9 -0
  60. package/dist/bundle/chunks/llama-cpp-classify-HRPRKOZA.js +22 -0
  61. package/dist/bundle/chunks/meta.js +2 -0
  62. package/dist/bundle/chunks/mistral-conversations-46TK5OBA.js +5 -0
  63. package/dist/bundle/chunks/multipart-parser-VTTMF2EO.js +3 -0
  64. package/dist/bundle/chunks/node-7S3GFMOZ.js +16 -0
  65. package/dist/bundle/chunks/node-MAEICQNS.js +2 -0
  66. package/dist/bundle/chunks/openai-chatgpt.js +101 -0
  67. package/dist/bundle/chunks/openai-codex-responses-IT7VEKUU.js +10 -0
  68. package/dist/bundle/chunks/openai-codex.js +101 -0
  69. package/dist/bundle/chunks/openai-completions-LOKIW33V.js +7 -0
  70. package/dist/bundle/chunks/openai-decisions-4F3LWHMG.js +5 -0
  71. package/dist/bundle/chunks/openai-responses-OK36GJXP.js +3 -0
  72. package/dist/bundle/chunks/openrouter-images-ZI7LLZ4Y.js +2 -0
  73. package/dist/bundle/chunks/openrouter.js +101 -0
  74. package/dist/bundle/chunks/radius.js +101 -0
  75. package/dist/bundle/chunks/runtime-RMPIV5AR.js +2 -0
  76. package/dist/bundle/chunks/src-ETRMT73D.js +4 -0
  77. package/dist/bundle/chunks/typesafe-system-one-J2CJBWEH.js +2 -0
  78. package/dist/bundle/chunks/virtual-modules-EGJP3AJA.js +2 -0
  79. package/dist/bundle/chunks/xai.js +2 -0
  80. package/dist/bundle/cli-runtime.js +3 -0
  81. package/dist/bundle/cli.js +5 -0
  82. package/dist/bundle/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
  83. package/dist/bundle/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
  84. package/dist/bundle/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
  85. package/dist/bundle/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
  86. package/dist/bundle/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
  87. package/dist/bundle/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
  88. package/dist/core/export-html/template.css +1015 -0
  89. package/dist/core/export-html/template.html +55 -0
  90. package/dist/core/export-html/template.js +1929 -0
  91. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  92. package/dist/core/export-html/vendor/marked.min.js +78 -0
  93. package/dist/modes/interactive/theme/dark.json +74 -0
  94. package/dist/modes/interactive/theme/light.json +74 -0
  95. package/dist/modes/interactive/theme/system-theme.ts +579 -0
  96. package/dist/modes/interactive/theme/theme-controller.ts +253 -0
  97. package/dist/modes/interactive/theme/theme-schema.ts +145 -0
  98. package/dist/modes/interactive/theme/theme-tokens.ts +145 -0
  99. package/dist/modes/interactive/theme/theme.ts +1076 -0
  100. package/docs/app-server.md +479 -0
  101. package/docs/app-server.schema.json +8128 -0
  102. package/docs/cli-integration.md +106 -0
  103. package/docs/cli.md +393 -0
  104. package/docs/codemode.md +230 -0
  105. package/docs/compaction.md +463 -0
  106. package/docs/configuration.md +48 -0
  107. package/docs/containerization.md +143 -0
  108. package/docs/custom-provider.md +173 -0
  109. package/docs/desktop.md +73 -0
  110. package/docs/docs.json +236 -0
  111. package/docs/environment-variables.md +138 -0
  112. package/docs/extensions.md +314 -0
  113. package/docs/how-knightcode-works.md +49 -0
  114. package/docs/images/doom-extension.png +0 -0
  115. package/docs/images/interactive-mode.png +0 -0
  116. package/docs/images/tree-view.png +0 -0
  117. package/docs/index.md +39 -0
  118. package/docs/json.md +226 -0
  119. package/docs/keybindings.md +197 -0
  120. package/docs/llama-cpp.md +121 -0
  121. package/docs/mcp.md +272 -0
  122. package/docs/message-types.md +279 -0
  123. package/docs/models-configuration.md +187 -0
  124. package/docs/models.md +221 -0
  125. package/docs/nvidia-rtx-llama-cpp.md +96 -0
  126. package/docs/packages.md +129 -0
  127. package/docs/plan-mode.md +121 -0
  128. package/docs/prompt-templates.md +59 -0
  129. package/docs/providers.md +282 -0
  130. package/docs/quickstart.md +128 -0
  131. package/docs/remote.md +87 -0
  132. package/docs/rpc-commands.md +860 -0
  133. package/docs/rpc-extension-ui.md +214 -0
  134. package/docs/rpc.md +193 -0
  135. package/docs/sdk.md +197 -0
  136. package/docs/security.md +99 -0
  137. package/docs/session-format.md +358 -0
  138. package/docs/sessions.md +135 -0
  139. package/docs/settings.md +220 -0
  140. package/docs/shell-aliases.md +93 -0
  141. package/docs/skills.md +93 -0
  142. package/docs/slash-commands.md +78 -0
  143. package/docs/terminal-setup.md +242 -0
  144. package/docs/termux.md +117 -0
  145. package/docs/themes.md +140 -0
  146. package/docs/tmux.md +55 -0
  147. package/docs/tui.md +125 -0
  148. package/docs/usage.md +167 -0
  149. package/docs/virtual-models.md +114 -0
  150. package/docs/windows.md +67 -0
  151. package/examples/README.md +36 -0
  152. package/examples/extensions/README.md +214 -0
  153. package/examples/extensions/auto-commit-on-exit.ts +55 -0
  154. package/examples/extensions/bash-spawn-hook.ts +30 -0
  155. package/examples/extensions/bookmark.ts +50 -0
  156. package/examples/extensions/border-status-editor.ts +151 -0
  157. package/examples/extensions/built-in-tool-renderer.ts +225 -0
  158. package/examples/extensions/claude-rules.ts +89 -0
  159. package/examples/extensions/commands.ts +72 -0
  160. package/examples/extensions/confirm-destructive.ts +60 -0
  161. package/examples/extensions/custom-compaction.ts +118 -0
  162. package/examples/extensions/custom-footer.ts +66 -0
  163. package/examples/extensions/custom-header.ts +73 -0
  164. package/examples/extensions/custom-provider-anthropic/index.ts +617 -0
  165. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  166. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  167. package/examples/extensions/custom-provider-gitlab-duo/index.ts +399 -0
  168. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  169. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  170. package/examples/extensions/debug-provider.ts +90 -0
  171. package/examples/extensions/dirty-repo-guard.ts +56 -0
  172. package/examples/extensions/doom-overlay/README.md +46 -0
  173. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  174. package/examples/extensions/doom-overlay/doom/doomgeneric_knightcode.c +72 -0
  175. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  176. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  177. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  178. package/examples/extensions/doom-overlay/index.ts +74 -0
  179. package/examples/extensions/doom-overlay/wad-finder.ts +55 -0
  180. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  181. package/examples/extensions/dynamic-resources/dynamic.json +75 -0
  182. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  183. package/examples/extensions/dynamic-resources/index.ts +15 -0
  184. package/examples/extensions/dynamic-tools.ts +74 -0
  185. package/examples/extensions/entry-renderer.ts +41 -0
  186. package/examples/extensions/event-bus.ts +43 -0
  187. package/examples/extensions/file-trigger.ts +41 -0
  188. package/examples/extensions/git-checkpoint.ts +53 -0
  189. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  190. package/examples/extensions/github-issue-autocomplete.ts +185 -0
  191. package/examples/extensions/gondolin/index.ts +531 -0
  192. package/examples/extensions/gondolin/package-lock.json +185 -0
  193. package/examples/extensions/gondolin/package.json +19 -0
  194. package/examples/extensions/handoff.ts +190 -0
  195. package/examples/extensions/hello.ts +26 -0
  196. package/examples/extensions/hidden-thinking-label.ts +53 -0
  197. package/examples/extensions/inline-bash.ts +94 -0
  198. package/examples/extensions/input-transform-streaming.ts +39 -0
  199. package/examples/extensions/input-transform.ts +43 -0
  200. package/examples/extensions/interactive-shell.ts +196 -0
  201. package/examples/extensions/jev-router.ts +113 -0
  202. package/examples/extensions/mac-system-theme.ts +47 -0
  203. package/examples/extensions/message-renderer.ts +59 -0
  204. package/examples/extensions/minimal-mode.ts +353 -0
  205. package/examples/extensions/modal-editor.ts +85 -0
  206. package/examples/extensions/model-status.ts +31 -0
  207. package/examples/extensions/notify.ts +57 -0
  208. package/examples/extensions/overlay-qa-tests.ts +1450 -0
  209. package/examples/extensions/overlay-test.ts +153 -0
  210. package/examples/extensions/permission-gate.ts +34 -0
  211. package/examples/extensions/pirate.ts +47 -0
  212. package/examples/extensions/plan-mode/README.md +66 -0
  213. package/examples/extensions/plan-mode/index.ts +387 -0
  214. package/examples/extensions/plan-mode/utils.ts +168 -0
  215. package/examples/extensions/preset.ts +436 -0
  216. package/examples/extensions/project-trust.ts +64 -0
  217. package/examples/extensions/prompt-customizer.ts +49 -0
  218. package/examples/extensions/protected-paths.ts +30 -0
  219. package/examples/extensions/provider-payload.ts +18 -0
  220. package/examples/extensions/qna.ts +118 -0
  221. package/examples/extensions/question.ts +278 -0
  222. package/examples/extensions/questionnaire.ts +440 -0
  223. package/examples/extensions/rainbow-editor.ts +88 -0
  224. package/examples/extensions/reload-runtime.ts +37 -0
  225. package/examples/extensions/rpc-demo.ts +118 -0
  226. package/examples/extensions/sandbox/index.ts +321 -0
  227. package/examples/extensions/sandbox/package-lock.json +92 -0
  228. package/examples/extensions/sandbox/package.json +19 -0
  229. package/examples/extensions/send-user-message.ts +97 -0
  230. package/examples/extensions/session-name.ts +27 -0
  231. package/examples/extensions/shutdown-command.ts +63 -0
  232. package/examples/extensions/snake.ts +343 -0
  233. package/examples/extensions/space-invaders.ts +560 -0
  234. package/examples/extensions/ssh.ts +220 -0
  235. package/examples/extensions/status-line.ts +32 -0
  236. package/examples/extensions/structured-output.ts +65 -0
  237. package/examples/extensions/subagent/README.md +177 -0
  238. package/examples/extensions/subagent/agents/planner.md +37 -0
  239. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  240. package/examples/extensions/subagent/agents/scout.md +50 -0
  241. package/examples/extensions/subagent/agents/worker.md +24 -0
  242. package/examples/extensions/subagent/agents.ts +157 -0
  243. package/examples/extensions/subagent/index.ts +1010 -0
  244. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  245. package/examples/extensions/subagent/prompts/implement.md +10 -0
  246. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  247. package/examples/extensions/summarize.ts +199 -0
  248. package/examples/extensions/system-prompt-header.ts +17 -0
  249. package/examples/extensions/tic-tac-toe.ts +1004 -0
  250. package/examples/extensions/timed-confirm.ts +70 -0
  251. package/examples/extensions/titlebar-spinner.ts +58 -0
  252. package/examples/extensions/todo.ts +294 -0
  253. package/examples/extensions/tool-override.ts +144 -0
  254. package/examples/extensions/tools.ts +146 -0
  255. package/examples/extensions/trigger-compact.ts +50 -0
  256. package/examples/extensions/truncated-tool.ts +195 -0
  257. package/examples/extensions/widget-placement.ts +9 -0
  258. package/examples/extensions/with-deps/index.ts +32 -0
  259. package/examples/extensions/with-deps/package-lock.json +31 -0
  260. package/examples/extensions/with-deps/package.json +22 -0
  261. package/examples/extensions/working-indicator.ts +121 -0
  262. package/examples/extensions/working-message-test.ts +25 -0
  263. package/examples/rpc-client.ts +35 -0
  264. package/examples/rpc-extension-ui.ts +661 -0
  265. package/examples/sdk/01-minimal.ts +26 -0
  266. package/examples/sdk/02-custom-model.ts +49 -0
  267. package/examples/sdk/03-custom-prompt.ts +70 -0
  268. package/examples/sdk/04-skills.ts +55 -0
  269. package/examples/sdk/05-tools.ts +48 -0
  270. package/examples/sdk/06-extensions.ts +94 -0
  271. package/examples/sdk/07-context-files.ts +42 -0
  272. package/examples/sdk/08-prompt-templates.ts +51 -0
  273. package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
  274. package/examples/sdk/10-settings.ts +53 -0
  275. package/examples/sdk/11-sessions.ts +52 -0
  276. package/examples/sdk/12-full-control.ts +74 -0
  277. package/examples/sdk/13-session-runtime.ts +67 -0
  278. package/examples/sdk/14-codemode-mcp.ts +61 -0
  279. package/examples/sdk/README.md +141 -0
  280. package/package.json +15 -15
  281. package/bin/knightcode +0 -62
@@ -0,0 +1,479 @@
1
+ # App Server
2
+
3
+ `knightcode app-server` hosts many conversation threads in one process. The
4
+ threads share models and credentials but own separate session files, extension
5
+ runtimes, tools, approvals, and turn queues. The desktop app can spawn it; scripts
6
+ can use the same protocol.
7
+
8
+ The transport is newline-delimited JSON over stdin/stdout. Messages use JSON-RPC
9
+ 2.0 request, response, and notification shapes without a `"jsonrpc"` field.
10
+ There is no protocol version number: the client and the server ship together,
11
+ and a client that needs a newer server checks `serverInfo.version`. It is
12
+ separate from the single-session [RPC mode](rpc.md). Worktrees, diffs, git operations and
13
+ extension dialogs are later phases; this server does not implement them yet.
14
+
15
+ ## Starting
16
+
17
+ ```sh
18
+ knightcode app-server [-e <extension>]... [--session-dir <dir>]
19
+ ```
20
+
21
+ `-e` / `--extension` is repeatable. Paths resolve against the process working
22
+ directory and load in each thread as explicitly trusted CLI paths. Project-local
23
+ resources still follow [project trust](security.md#understand-project-trust).
24
+ Extension dialogs and custom UI are not yet available in desktop mode; extensions
25
+ see `mode: "desktop"` and `hasUI: false`.
26
+
27
+ Session storage uses `--session-dir`, then
28
+ `KNIGHTCODE_CODING_AGENT_SESSION_DIR`, then the global `sessionDir` setting.
29
+ Without an override, sessions use the per-project layout described in
30
+ [Sessions](sessions.md). stdout carries only protocol messages; logs go to stderr.
31
+ Closing stdin shuts down the server. `knightcode app-server --help` (or `-h`)
32
+ prints usage on stderr and exits without opening a connection.
33
+
34
+ ## Handshake
35
+
36
+ Send a request with a string or numeric `id`:
37
+
38
+ ```json
39
+ {"id":1,"method":"initialize","params":{"clientInfo":{"name":"example","version":"1.0"},"capabilities":{"optOutNotifications":["item/reasoning/delta"]}}}
40
+ ```
41
+
42
+ The result contains `serverInfo` and `platform: {os, arch, homeDir}`. `os` is `win32`, `darwin`, or `linux`.
43
+ `capabilities.optOutNotifications` is an optional array of at most 256 method
44
+ names, scoped to this connection. Unknown names are tolerated. It filters only
45
+ notifications, never responses or server requests such as approvals.
46
+
47
+ Wait for its result, then send the notification:
48
+
49
+ ```json
50
+ {"method":"initialized","params":{}}
51
+ ```
52
+
53
+ Only then send other requests. Requests before initialization return `notInitialized`. Unknown methods return
54
+ `methodNotFound`; invalid parameters return `invalidParams`.
55
+
56
+ ## Threads and turns
57
+
58
+ Start a thread with its project directory:
59
+
60
+ ```json
61
+ {"id":2,"method":"thread/start","params":{"cwd":"/path/to/project","approvalMode":"ask"}}
62
+ {"id":3,"method":"model/list","params":{}}
63
+ ```
64
+
65
+ Wait for each response. `thread/start` and `thread/fork` return
66
+ `{thread, warnings}`. A fork is named after its source with ` (fork)` appended. `thread/resume` also returns warnings; render them from the
67
+ response, because they can occur before subscription. A warning has
68
+ `{message, source, path?, line?, column?}`, where `source` is `settings`,
69
+ `extension`, `trust`, or `server`. Malformed settings, refused extension loads,
70
+ and undecided project trust do not silently disappear. Later extension errors
71
+ send a subscriber-only `warning` with `threadId`.
72
+
73
+ Threads and list summaries include `createdAt` (header creation time) and
74
+ optional `forkedFromId` (the parent's header ID, not a UUID inferred from its
75
+ filename). List summaries use file modification time for `updatedAt`; loaded
76
+ threads use the latest entry time, falling back to the header. Their `status`
77
+ is one of:
78
+
79
+ - `{type: "notLoaded"}`
80
+ - `{type: "idle"}`
81
+ - `{type: "active", waitingOn: []}`; the array can contain `approval` and `dialog`.
82
+ - `{type: "systemError", message}`; ownership loss remains visible after unload
83
+ until a successful reload.
84
+
85
+ `thread/status/changed` broadcasts these objects, including the first opening
86
+ and last closing of an approval or dialog.
87
+
88
+ Extension providers appear in `model/list` after a thread has loaded them.
89
+ Each model has `thinkingLevels`, the accepted picker values; non-reasoning
90
+ models report `["off"]`. Pick a model using `thread/settings/update`, with
91
+ `threadId` and `model: {provider, id}`, before starting a turn if no usable model
92
+ is selected.
93
+
94
+ ```json
95
+ {"id":4,"method":"turn/start","params":{"threadId":"THREAD_ID","text":"Explain this repository","requestId":"client-start-1","clientMessageId":"optimistic-1","images":[{"path":"/absolute/path/screenshot.png"}]}}
96
+ ```
97
+
98
+ A start returns `{status, threadId, requestId}`. `status` is `started`, `handled`
99
+ (an extension consumed the input), or `cancelled` (cancelled before acceptance).
100
+ It does not wait for the turn to finish. The optional client token `requestId`
101
+ is echoed in the response and `turn/started`; it is distinct from the JSON request
102
+ `id`. Session-replacing commands preserve it and return the effective target
103
+ thread ID. The first acceptance wins even if cancellation follows later.
104
+
105
+ `turn/start` and `turn/queue/add` accept optional `clientMessageId` (1–128
106
+ characters). It is echoed on the first live `userMessage` of the turn the input
107
+ starts, after input transformations; it is not persisted. A handled or removed
108
+ input creates no matching item.
109
+ Their `images` accept inline `{mimeType, data}` base64 images or `{path}` on the
110
+ server's shared filesystem. Path images must be absolute, regular PNG, JPEG,
111
+ GIF, or WebP files of at most 20 MiB; missing, relative, non-image, directory,
112
+ and oversized inputs return `invalidParams`.
113
+
114
+ A plain text turn sends these notifications in order:
115
+
116
+ 1. `turn/started`
117
+ 2. `item/started` and `item/completed` for the user message
118
+ 3. `item/started` for the agent message
119
+ 4. Zero or more `item/agentMessage/delta` notifications
120
+ 5. `item/completed` for the agent message
121
+ 6. `turn/completed`
122
+
123
+ A turn is one agent run between durable start and end entries. Automatic retries,
124
+ recovery, and steering may span several low-level agent runs inside it. Turn IDs come from persisted marker entries; item IDs use durable
125
+ ordinals except tool calls, which retain their call IDs. Final messages decide
126
+ item contents and statuses. `Turn` requires numeric `startedAt` and optionally
127
+ has `completedAt`; items optionally carry both. Times are Unix milliseconds,
128
+ unlike thread creation/modification times, which are ISO strings. Durable turn
129
+ markers and end entries determine final turn times. Assistant text/reasoning
130
+ uses message timestamp and duration, and tool calls finish at the tool-result
131
+ timestamp. User, compaction, and extension items may have only completion time.
132
+ Nested calls are live-only. An interrupted turn without an end entry has no
133
+ completion time.
134
+
135
+ Started-item times and streaming contents are provisional. `item/completed`
136
+ replaces **times, text, fileChanges, and index**; do not just append deltas.
137
+ `index` is the item's top-level position in the turn: order by its latest value,
138
+ because a streaming item's index can change at message end. `item/removed`
139
+ withdraws an item dropped by a message-end handler.
140
+ Nested tool calls carry `parentItemId` and no top-level index. A saved turn with
141
+ no end entry reads as `interrupted`. See [Session Format](session-format.md).
142
+
143
+ Completed edit/write calls include `fileChanges: [{path, kind, diff?}]`;
144
+ `kind` is `add`, `modify`, or `delete`. A non-empty tool-result patch becomes
145
+ `diff`. Extension tools can report validated file changes through result details;
146
+ a malformed report is ignored as a whole. Failed calls report no changes.
147
+
148
+ `turn/completed` contains a summary without items, avoiding a second large
149
+ transcript transfer. Failed turns have `error: {message, kind}`, where `kind`
150
+ is `auth`, `rateLimit`, `contextOverflow`, `network`, `provider`, or `other`,
151
+ classified from the error text. Summaries and references bound `error.message` to 2,000 characters;
152
+ full payloads retain it. Interrupted outcomes take precedence over failures.
153
+
154
+ `turn/steer` hands input to the running turn and requires `expectedTurnId`, the
155
+ currently running turn ID. A stale ID returns `turnMismatch`, so a steer never
156
+ lands in a later turn. A steer cannot be taken back once accepted.
157
+
158
+ `turn/queue/add` queues input on the server and returns `{queueId}`. Each queued
159
+ input starts a turn of its own once the thread is idle, oldest first; on an idle
160
+ thread it starts at once. Until it starts it is removable with
161
+ `turn/queue/remove`. A queued input that fails to start (no model, signed out) is
162
+ dropped with an `error` notification. `turn/queue/updated` sends
163
+ `{threadId, steering: [text], followUp: [{id, text}]}`: steers the agent has not
164
+ delivered yet, and the queued inputs.
165
+
166
+ `turn/interrupt` accepts optional `turnId`; a supplied stale ID returns
167
+ `turnMismatch`, while omitting it retains interrupt-current behavior. It drops
168
+ queued inputs, as Escape does in the terminal; the client still has their text
169
+ from `turn/queue/updated` to restore into its composer.
170
+
171
+ An interrupt answers at once; it does not wait for extension hooks. A start
172
+ interrupted during its input hooks or an extension command returns `cancelled`
173
+ and launches nothing, but hooks already running finish. A start interrupted
174
+ later, during compaction before the run or `before_agent_start`, returns
175
+ `started`, and its turn completes `interrupted` without a model request.
176
+
177
+ Settings changes and compaction serialize with starts;
178
+ a thread already running refuses another start with `turnInProgress`. Settlement
179
+ hooks and their deferred dispatch also retain admission until they finish.
180
+ Steering input still waiting in interception belongs to that running
181
+ turn: interruption, unloading, or settlement cancels it. It cannot silently enter
182
+ a later turn; the waiting request returns `invalidParams`.
183
+
184
+ ### Subscriptions and replacement
185
+
186
+ `thread/start`, `thread/resume`, `thread/fork`, and `turn/start` subscribe the
187
+ requesting connection. `thread/unsubscribe` withdraws it. Every initialized
188
+ connection gets thread/sidebar and account updates, including
189
+ `thread/turn/completed: {turn}` for completed, failed, and interrupted outcomes.
190
+ Only subscribers get `turn/completed`, turn/item notifications, deltas, retries,
191
+ queue updates, and `thread/tokenUsage/updated`. Approvals target one subscriber
192
+ at a time.
193
+
194
+ Initialize visible sidebar rows from newest-page `thread/read`, without loading
195
+ or subscribing to all threads or resolving referenced turn payloads. Keep live
196
+ outcomes arriving during a read and apply them after its result. An absent saved
197
+ last-seen turn ID establishes a baseline; live completions can still mark unread.
198
+ Active/waiting status outranks the previous outcome; `systemError` stays separate.
199
+ Desktop OS notifications are for live outcomes, not initial history.
200
+
201
+ `thread/resume` returns history and subscribes in the same synchronous send step.
202
+ Its separate `runningTurn` is a current snapshot, even when an old history cursor
203
+ is supplied. Its required `queue` and `usage` are also live send-time snapshots,
204
+ not values from handler entry or the history cursor. Buffer queue/usage events
205
+ while awaiting the response, install the snapshots (an empty queue clears stale
206
+ state), then replay the buffered events. Invalid cursors subscribe nobody.
207
+ Install `runningTurn` before applying buffered deltas. `thread/replaced` moves
208
+ subscriptions to the new thread; captured old extension contexts become stale.
209
+ `thread/unsubscribe` returns `{status: "unsubscribed" | "notSubscribed"}`.
210
+
211
+ `TokenUsage` contains cumulative `input`, `output`, `cacheRead`, `cacheWrite`,
212
+ and `cost`, plus optional `contextTokens` and required `contextWindow`.
213
+ `thread/tokenUsage/updated: {threadId, turnId, usage}` arrives after every finalized
214
+ assistant reply, including replies before tool results and compacted-history
215
+ billing. `contextTokens` can be absent when the current context is unknown.
216
+
217
+ ### History, listings, and large values
218
+
219
+ `thread/read` reads saved history without loading or locking the thread and never
220
+ writes the source. `thread/resume` loads and owns it. History pages contain at most
221
+ 50 turns, newest page first; turns within a page are chronological. `nextCursor`
222
+ anchors later pages to the original branch prefix, so appends cannot shift the
223
+ page. Diverged, foreign, or malformed cursors return `invalidCursor`.
224
+
225
+ Initial `thread/list` uses a per-directory `.thread-index.json` metadata cache.
226
+ It stats transcripts and rescans only new or changed files; the first cold scan
227
+ still reads their full history. Cached titles are bounded, never full messages,
228
+ and fork origins are cached after resolving parent headers. Warm listings open
229
+ no unchanged transcripts or parent headers. Missing, corrupt, invalid, or
230
+ oversized (over 16 MiB) indexes rebuild safely; cache writes are best effort.
231
+ Directories are scanned sequentially, with at most 64 transcripts open.
232
+
233
+ Continuations use an immutable summary snapshot without rescanning. Up to 32
234
+ snapshots are retained with a five-minute sliding expiry; expired, evicted, or
235
+ filter-mismatched cursors return `invalidCursor`.
236
+
237
+ Large turns/items and tool input/output use immutable payload references rather
238
+ than oversized protocol lines. Call `payload/read` with the reference ID and a
239
+ byte `offset`; concatenate base64-decoded chunks until `eof`. `nextOffset`, when
240
+ present, is the next byte offset, not a character count. References expire after
241
+ 30 minutes without access; reread the thread to obtain new references. IDs grant
242
+ access only to server-owned spool files, not arbitrary filesystem paths.
243
+
244
+ ## Approvals
245
+
246
+ Desktop threads default to `ask`; terminal-mode in-process threads default to
247
+ `fullAccess`. Effective mode is persisted on the branch; invalid stored state
248
+ restores as `ask`.
249
+
250
+ | Tool | `ask` | `autoEdit` | `fullAccess` |
251
+ |---|---|---|---|
252
+ | `read`, `grep`, `find`, `ls`, `ask_user`, `submit_plan` | Allow | Allow | Allow |
253
+ | `edit`, `write` | Ask | Allow | Allow |
254
+ | Shell, other extension, and MCP tools | Ask | Ask | Allow |
255
+
256
+ Built-in plan and classifier restrictions run before this gate. Approvals are
257
+ not a filesystem or operating-system sandbox.
258
+
259
+ The server sends `item/toolCall/requestApproval` with thread/turn/item IDs, the
260
+ tool name, input or an input reference, and required `decisions`. Optional
261
+ `reason` explains the gate (for example, an outside-workspace write), and
262
+ optional `prefix` is the offered shell command prefix. Render the supplied
263
+ choices, not a hardcoded list. Reply to its `id` with a result such as
264
+ `{"decision":"accept"}` or
265
+ `{"decision":"decline","message":"Use the project-local file instead"}`.
266
+ A decline message is optional and bounded to 4,000 characters; it reaches the
267
+ agent as the tool's decline reason. `cancel` always blocks execution. An
268
+ unoffered decision is treated as decline and never grants permission.
269
+
270
+ `acceptForSession` remembers a non-shell tool name for this thread's load,
271
+ never across unloads. **It is never offered for bash or PowerShell.** Shells
272
+ can instead offer `acceptPrefixForSession` with a positively understood prefix.
273
+ For example, a `git status` grant covers `git status --short`, not `git reset`.
274
+ Only simple, recognized command forms get a prefix; chaining, redirection,
275
+ substitution, quoted/escaped command names, script dispatchers, interpreters,
276
+ nested wrappers, and unrecognized subcommand forms fail closed. A later command
277
+ must independently produce exactly the granted prefix, not merely start with
278
+ its text. Grants are shell-specific and confined to this thread's load.
279
+
280
+ The most recent initiating subscriber is asked first. Disconnect or unsubscribe
281
+ cancels that attempt and migrates it to another subscriber; no subscribers means
282
+ cancel. `serverRequest/cancelled` withdraws an outstanding request.
283
+
284
+ ## Method reference
285
+
286
+ All methods require the handshake. Common errors are `notInitialized`,
287
+ `invalidParams`, and `shuttingDown`; the additional errors below are
288
+ method-specific. The generated schema remains the exhaustive field reference.
289
+
290
+ ### `turn/queue/remove`
291
+
292
+ Params: `{threadId, queueId}`. Result: `{removed}`. `removed: true` means the
293
+ input will not start; false means it was unknown, already started, or already
294
+ removed. This does not edit saved history.
295
+ Errors: `threadNotFound`.
296
+
297
+ ```json
298
+ {"id":10,"method":"turn/queue/remove","params":{"threadId":"THREAD_ID","queueId":"QUEUE_ID"}}
299
+ ```
300
+
301
+ ### `config/read`
302
+
303
+ Params: optional `{cwd}`. Result: `{settings, origins, versions, errors}`.
304
+ Without cwd, only global settings are read. With cwd, trusted project settings
305
+ merge over global settings; untrusted project files are not read. `origins`
306
+ maps dotted leaf keys to `global` or `project`. `versions.global` and optional
307
+ `versions.project` are SHA-256 hashes of raw file contents, or `"none"` for an
308
+ absent or unread untrusted scope. Settings, origins, versions, and parse errors
309
+ come from the same scope reads, not cached settings paired with fresh versions.
310
+ Parse errors appear as structured `source: "settings"` warnings with an
311
+ optional path and available one-based line/column; unaffected scopes still read.
312
+ Storage read/lock failures return `internal`.
313
+
314
+ ```json
315
+ {"id":11,"method":"config/read","params":{"cwd":"/path/to/project"}}
316
+ ```
317
+
318
+ ### `config/write`
319
+
320
+ Params: `{scope, key, value, cwd?, expectedVersion?}`. `scope` is `global` or
321
+ `project`; `key` is a dotted key such as `retry.provider.maxRetryDelayMs`.
322
+ `value: null` deletes the leaf. Result: `{version}`, after the write and reload.
323
+ Project writes require cwd and an explicitly trusted project. Writes and ordinary
324
+ settings setters share a per-file queue across manager instances. Under the file
325
+ lock, `expectedVersion`, if present, compares against the current raw-content
326
+ hash; existing migrations run before the edit, so deleting a canonical key does
327
+ not resurrect its legacy alias. Corrupt JSON is refused without overwriting it.
328
+
329
+ Errors: `configConflict` with `data: {version}` when the file changed; reread and
330
+ resolve the conflict rather than blindly retrying. `invalidParams` rejects
331
+ untrusted project writes (`data.reason: "untrusted"`), missing project cwd,
332
+ malformed keys, and prototype-pollution segments (`__proto__`, `constructor`,
333
+ `prototype`). Read/parse/write failures return `internal`.
334
+
335
+ ```json
336
+ {"id":12,"method":"config/write","params":{"scope":"global","key":"theme","value":"dark","expectedVersion":"none"}}
337
+ ```
338
+
339
+ ### `project/trust/read`
340
+
341
+ Params: `{cwd}`. Result: `{trusted, needsTrust}`. `trusted` is true, false, or
342
+ null (undecided); `needsTrust` means project-local resources require a decision.
343
+ This reads the server-owned [trust store](security.md#understand-project-trust),
344
+ not a separate desktop-side preference.
345
+
346
+ ```json
347
+ {"id":13,"method":"project/trust/read","params":{"cwd":"/path/to/project"}}
348
+ ```
349
+
350
+ ### `project/trust/set`
351
+
352
+ Params: `{cwd, trusted}` with a boolean decision. Result: `{}`. Writes the
353
+ server-owned trust store; subsequent loads and config reads use it. Already
354
+ loaded runtimes are not silently rebuilt. A `cwd` that is not an existing
355
+ directory returns `invalidParams`. Filesystem failures return `internal`.
356
+
357
+ ```json
358
+ {"id":14,"method":"project/trust/set","params":{"cwd":"/path/to/project","trusted":true}}
359
+ ```
360
+
361
+ ### `file/search`
362
+
363
+ Params: `{cwd, query, limit?, searchId?}`. `query` is 1–256 characters, `limit`
364
+ is 1–200 (default 50), and `searchId` is at most 128 characters. Result:
365
+ `{files: [{path, score, indices}], truncated}` with cwd-relative paths, fuzzy
366
+ scores, and matched character indices. The server lists paths with `fd` using
367
+ an argument array, never a shell. A newer request using the same `searchId`
368
+ (including from another connection) immediately supersedes the older one,
369
+ which returns `{files: [], truncated: false}` unless shutdown takes precedence.
370
+
371
+ Listings have a ten-second TTL, at most eight cached cwds, and at most two active
372
+ listings. Output is capped at 200,000 paths or 32 MiB stdout, with
373
+ `truncated: true` when the bounded listing is retained; a 15-second timeout
374
+ rejects with `internal`. Partial failed output is usable but never cached;
375
+ empty failed output rejects. No remaining waiters means abort; shutdown always
376
+ returns `shuttingDown`, even if child rejection
377
+ arrives after superseding. `toolMissing` means `fd` is unavailable; other empty
378
+ listing failures return `internal`.
379
+
380
+ ```json
381
+ {"id":15,"method":"file/search","params":{"cwd":"/path/to/project","query":"src/config","limit":20,"searchId":"composer"}}
382
+ ```
383
+
384
+ ### `command/list`
385
+
386
+ Params: `{threadId}` or `{cwd}`. Result: `{commands: [{name, description}]}`:
387
+ extension commands, prompt templates, and skills as `skill:<name>`, without the
388
+ leading `/`. With `cwd`, the server lists what a new thread in that project would
389
+ offer, from a session it builds in memory and never binds: no extension starts,
390
+ and nothing is written. Built-in commands that only work in the terminal
391
+ (`usage`, `llama`, `undo`) are left out.
392
+
393
+ ```json
394
+ {"id":17,"method":"command/list","params":{"cwd":"/path/to/project"}}
395
+ ```
396
+
397
+ ### `thread/delete`
398
+
399
+ Params: `{threadId}`. Result: `{}`. Permanently removes an archived transcript;
400
+ it does not use the interactive resume selector's trash command. Archive first,
401
+ then explicitly delete. The thread must have no running/admitted work. Deletion
402
+ fences new starts and reloads, rechecks archive/busy state inside that fence,
403
+ and locks/verifies the raw file before unlinking. Refused rechecks preserve the
404
+ loaded thread and subscriptions. Success broadcasts `thread/deleted: {threadId}`
405
+ to every initialized connection.
406
+
407
+ Errors: `threadNotFound`, `threadNotArchived`, `turnInProgress`,
408
+ `threadLockedElsewhere`, and `archiveConflict` for hard-linked transcripts;
409
+ filesystem failures return `internal`.
410
+
411
+ ```json
412
+ {"id":16,"method":"thread/delete","params":{"threadId":"ARCHIVED_THREAD_ID"}}
413
+ ```
414
+
415
+ ### `server/diagnostics`
416
+
417
+ Params: `{}`. Result: `rssBytes`, `heapBytes`, `loadedThreads`, `loadingThreads`,
418
+ `payloadFiles`, `payloadBytes`, `inactiveFactories`, `uptimeMs`,
419
+ `listingFilesOpened`, and `listingBytesScanned`. The listing counters are
420
+ cumulative: transcript scans account for file sizes and parent-header lookups
421
+ add opens, but not bytes. They exclude index reads and filesystem stat work.
422
+ Diagnostics observe the shared server, not only this connection.
423
+
424
+ ```json
425
+ {"id":18,"method":"server/diagnostics","params":{}}
426
+ ```
427
+
428
+ ## Ownership, unloading, and shutdown
429
+
430
+ Only one process may own a persisted session file. Symlink/junction aliases share
431
+ ownership; hard-linked transcripts are refused. `threadLockedElsewhere` means
432
+ another process owns it. [Terminal resume](sessions.md#session-ownership) offers
433
+ to fork instead. Read-only discovery and history require no ownership.
434
+
435
+ If ownership is lost to another process, the thread closes with an `error`
436
+ notification rather than continuing writes. Archive/unarchive owns both paths,
437
+ refuses destination collisions, and never overwrites another transcript. An
438
+ `archiveConflict` can include structured recovery data naming surviving files.
439
+
440
+ A thread unloads after ten minutes without a subscriber and with no running work.
441
+ Unloading releases its session lock, owned virtual routes, and extension-cache
442
+ leases. The factory cache retains at most 256 inactive factories plus actively
443
+ leased entries. Runtime module unloading is not promised; see
444
+ [extension state and cache behavior](extensions.md).
445
+
446
+ On stdin EOF or SIGINT/SIGTERM, new input stops immediately, pending login flows
447
+ cancel, and every thread unloads. Accepted requests still receive answers; work
448
+ that cannot finish returns `shuttingDown`. Output drains after accepted requests
449
+ settle. At nine seconds, unfinished accepted dispatches receive `shuttingDown`;
450
+ late results cannot publish a second response. The final second is reserved for
451
+ output drain before the ten-second hard exit, including a client that has stopped
452
+ reading stdout. Trusted JavaScript already executing remains cooperative; the
453
+ server cannot roll back its private effects or preempt a synchronous callback.
454
+
455
+ ## Limits and client reference
456
+
457
+ Limits count UTF-8 bytes:
458
+
459
+ - 64 MiB per stdin line; an oversized line is dropped with an error notification.
460
+ - 64 MiB of pending unread output before the connection aborts.
461
+ - 1 MiB per history/list response, including envelope reserve.
462
+ - 64 KiB per inline turn/item; larger values use references.
463
+ - 48 KiB per payload chunk before base64 encoding.
464
+
465
+ The in-repository `AppServerClient` supports typed `request`, `onNotification`,
466
+ `onRequest`, `readPayload`, `resolveTurn`, and `resolveItem` calls. Its
467
+ `AppServerError` preserves `code`, `message`, and `data` exactly; inspect `data`
468
+ for archive recovery information instead of parsing message strings.
469
+ `createInProcessClient` connects the same server/client over an in-memory
470
+ transport. A host owns the shared context and `ThreadManager`: stop input, dispose
471
+ the context to cancel logins, and await `threads.closeAll()` on shutdown.
472
+
473
+ Every message is defined in [app-server.schema.json](app-server.schema.json).
474
+ Regenerate it from the workspace:
475
+
476
+ ```sh
477
+ cd packages/app-server-protocol
478
+ bun run generate:schema
479
+ ```