one-code-extension 0.4.1 → 0.6.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 (439) hide show
  1. package/README.md +16 -5
  2. package/agents/general-purpose.md +2 -2
  3. package/docs/guide/README.md +2 -1
  4. package/docs/guide/bring-your-claude-code-setup.md +60 -9
  5. package/docs/guide/configuration.md +48 -14
  6. package/docs/guide/differences-from-claude-code.md +40 -28
  7. package/docs/guide/doctor.md +20 -13
  8. package/docs/guide/hooks.md +18 -3
  9. package/docs/guide/installation.md +26 -4
  10. package/docs/guide/permissions-modes-and-auto-mode.md +225 -49
  11. package/docs/guide/providers-and-models.md +137 -54
  12. package/docs/guide/reference.md +27 -15
  13. package/docs/guide/sessions-and-context.md +69 -16
  14. package/docs/guide/skills-plugins-and-mcp.md +57 -20
  15. package/docs/guide/subagents-and-workflows.md +95 -29
  16. package/docs/guide/tasks-and-background-work.md +101 -26
  17. package/docs/guide/terminal-interface.md +24 -12
  18. package/docs/guide/tools.md +46 -5
  19. package/docs/guide/troubleshooting.md +13 -9
  20. package/docs/guide/windows.md +58 -31
  21. package/extensions/artifacts/gallery.ts +227 -0
  22. package/extensions/artifacts/index.ts +288 -0
  23. package/extensions/artifacts/store.ts +570 -0
  24. package/extensions/artifacts/viewer.ts +199 -0
  25. package/extensions/ask-user/description.ts +67 -0
  26. package/extensions/ask-user/dialogs.ts +80 -0
  27. package/extensions/ask-user/index.ts +37 -33
  28. package/extensions/ask-user/questions.ts +32 -7
  29. package/extensions/ask-user/widget.ts +45 -25
  30. package/extensions/auto-mode/actions.ts +6 -0
  31. package/extensions/auto-mode/cache.ts +88 -0
  32. package/extensions/auto-mode/classifier-prompt.ts +5 -4
  33. package/extensions/auto-mode/classifier.ts +290 -65
  34. package/extensions/auto-mode/config.ts +72 -20
  35. package/extensions/auto-mode/decision-log.ts +2 -0
  36. package/extensions/auto-mode/defaults.ts +1 -1
  37. package/extensions/auto-mode/denials.ts +124 -0
  38. package/extensions/auto-mode/git-checkout-programs.ts +187 -0
  39. package/extensions/auto-mode/git-status-meta.ts +159 -0
  40. package/extensions/auto-mode/history.ts +189 -0
  41. package/extensions/auto-mode/instructions.ts +58 -52
  42. package/extensions/auto-mode/model-select.ts +159 -134
  43. package/extensions/auto-mode/paths.ts +57 -5
  44. package/extensions/auto-mode/pause.ts +57 -2
  45. package/extensions/auto-mode/prompt.ts +37 -21
  46. package/extensions/auto-mode/read-only-options.ts +724 -0
  47. package/extensions/auto-mode/resolved-paths-meta.ts +133 -0
  48. package/extensions/auto-mode/rules.ts +18 -1
  49. package/extensions/auto-mode/safety-floor.ts +361 -18
  50. package/extensions/auto-mode/setup-run.ts +20 -14
  51. package/extensions/auto-mode/shell-analysis.ts +764 -490
  52. package/extensions/auto-mode/shell-parse.ts +885 -0
  53. package/extensions/auto-mode/system-note.ts +33 -0
  54. package/extensions/auto-mode/transcript.ts +80 -51
  55. package/extensions/background/cron.ts +642 -0
  56. package/extensions/background/index.ts +614 -248
  57. package/extensions/background/loop-fire.ts +173 -0
  58. package/extensions/background/loop-preamble.ts +59 -0
  59. package/extensions/background/loop-skill.ts +163 -0
  60. package/extensions/background/monitor-batch.ts +53 -0
  61. package/extensions/background/noop-fold.ts +128 -0
  62. package/extensions/background/switch-guard.ts +56 -0
  63. package/extensions/background/wakeup.ts +178 -55
  64. package/extensions/bash/background.ts +53 -17
  65. package/extensions/bash/child.ts +7 -0
  66. package/extensions/bash/description.ts +188 -0
  67. package/extensions/bash/guards.ts +15 -67
  68. package/extensions/bash/index.ts +66 -35
  69. package/extensions/branding/compaction-keep.ts +63 -0
  70. package/extensions/branding/declined.ts +22 -0
  71. package/extensions/branding/index.ts +133 -9
  72. package/extensions/branding/prompt-editor.ts +53 -6
  73. package/extensions/branding/queued-edit.ts +31 -0
  74. package/extensions/branding/replaced-builtins.ts +68 -0
  75. package/extensions/branding/startup.ts +33 -71
  76. package/extensions/btw/index.ts +250 -78
  77. package/extensions/btw/panel.ts +228 -100
  78. package/extensions/btw/prompt.ts +41 -4
  79. package/extensions/cache-marks/index.ts +42 -0
  80. package/extensions/claude-compat/index.ts +7 -11
  81. package/extensions/claude-context/index.ts +436 -63
  82. package/extensions/compaction/cut.ts +157 -0
  83. package/extensions/compaction/index.ts +219 -75
  84. package/extensions/compaction/kept-thinking.ts +62 -0
  85. package/extensions/compaction/prompt.ts +15 -12
  86. package/extensions/context-budget/budget.ts +16 -2
  87. package/extensions/context-budget/index.ts +35 -15
  88. package/extensions/context-management/index.ts +36 -28
  89. package/extensions/doctor/build.ts +59 -8
  90. package/extensions/doctor/builtins.ts +84 -0
  91. package/extensions/doctor/cli.ts +7 -1
  92. package/extensions/doctor/compat.ts +88 -23
  93. package/extensions/doctor/dependencies.ts +41 -5
  94. package/extensions/doctor/fix-prompt.ts +9 -2
  95. package/extensions/doctor/index.ts +102 -58
  96. package/extensions/doctor/models.ts +102 -63
  97. package/extensions/doctor/presets.ts +42 -27
  98. package/extensions/doctor/report.ts +19 -2
  99. package/extensions/doctor/viewer.ts +49 -27
  100. package/extensions/effort/index.ts +141 -25
  101. package/extensions/effort/settings.ts +21 -0
  102. package/extensions/effort/slider.ts +24 -20
  103. package/extensions/exit/index.ts +32 -1
  104. package/extensions/file-tracker/index.ts +420 -42
  105. package/extensions/file-tracker/replay.ts +137 -24
  106. package/extensions/file-tracker/restore.ts +66 -0
  107. package/extensions/file-tracker/results.ts +66 -0
  108. package/extensions/file-tracker/shell-reads.ts +211 -0
  109. package/extensions/file-tracker/tracker.ts +45 -15
  110. package/extensions/footer/footer-line.ts +45 -24
  111. package/extensions/footer/index.ts +47 -2
  112. package/extensions/footer/pr.ts +34 -5
  113. package/extensions/hooks/compaction.ts +7 -0
  114. package/extensions/hooks/executor.ts +32 -30
  115. package/extensions/hooks/index.ts +209 -58
  116. package/extensions/hooks/matcher.ts +3 -0
  117. package/extensions/hooks/prompt-context.ts +59 -0
  118. package/extensions/hooks/protocol.ts +41 -3
  119. package/extensions/hooks/settings.ts +50 -19
  120. package/extensions/hooks/subagent-bridge.ts +2 -0
  121. package/extensions/hooks/trust.ts +26 -12
  122. package/extensions/idle-compact/index.ts +119 -0
  123. package/extensions/idle-compact/policy.ts +143 -0
  124. package/extensions/init/index.ts +11 -10
  125. package/extensions/init/prompt.ts +25 -32
  126. package/extensions/interrupted/index.ts +13 -1
  127. package/extensions/kept-thinking/index.ts +27 -0
  128. package/extensions/ledger/index.ts +46 -0
  129. package/extensions/ledger/wire.ts +154 -0
  130. package/extensions/lib/agent-cron.ts +146 -0
  131. package/extensions/lib/agent-loader.ts +18 -3
  132. package/extensions/lib/agent-view.ts +85 -0
  133. package/extensions/lib/anthropic-auth.ts +98 -0
  134. package/extensions/lib/anthropic-payload.ts +82 -1
  135. package/extensions/lib/anthropic-server-call.ts +230 -0
  136. package/extensions/lib/anthropic-server-tools.ts +485 -0
  137. package/extensions/lib/app-launch.mjs +94 -0
  138. package/extensions/lib/argument-hints.ts +190 -0
  139. package/extensions/lib/atomic-write.ts +6 -2
  140. package/extensions/lib/auto-memory.ts +75 -0
  141. package/extensions/lib/bash-parser.ts +84 -0
  142. package/extensions/lib/btw-fork.ts +93 -0
  143. package/extensions/lib/child-extensions.ts +52 -0
  144. package/extensions/lib/child-writes.ts +45 -0
  145. package/extensions/lib/claude-context.ts +515 -100
  146. package/extensions/lib/claude-external-includes.ts +68 -0
  147. package/extensions/lib/claude-id.ts +22 -0
  148. package/extensions/lib/claude-rules.ts +323 -0
  149. package/extensions/lib/claude-settings.ts +76 -4
  150. package/extensions/lib/compaction-boundary.ts +36 -0
  151. package/extensions/lib/compaction-keep.mjs +83 -0
  152. package/extensions/lib/config-mode.ts +112 -0
  153. package/extensions/lib/consent-dialogs.ts +63 -0
  154. package/extensions/lib/consent-preview.ts +5 -1
  155. package/extensions/lib/consent-stores.ts +48 -0
  156. package/extensions/lib/context-facts.ts +97 -0
  157. package/extensions/lib/covered-messages.ts +23 -0
  158. package/extensions/lib/deferred.ts +359 -25
  159. package/extensions/lib/dock-rows.ts +60 -0
  160. package/extensions/lib/empty-tool-result.ts +27 -0
  161. package/extensions/lib/environment-block.ts +76 -0
  162. package/extensions/lib/fetch-timeout.ts +24 -6
  163. package/extensions/{system-prompt → lib}/git-status.ts +51 -13
  164. package/extensions/lib/git.ts +75 -13
  165. package/extensions/lib/grammars/LICENSE-tree-sitter-bash +21 -0
  166. package/extensions/lib/grammars/README.md +2 -0
  167. package/extensions/lib/grammars/tree-sitter-bash.wasm +0 -0
  168. package/extensions/lib/guide-docs.ts +45 -0
  169. package/extensions/lib/headless-output.ts +46 -0
  170. package/extensions/lib/hook-gate.ts +7 -7
  171. package/extensions/lib/interrupt.ts +20 -4
  172. package/extensions/lib/key-input.ts +455 -0
  173. package/extensions/lib/keys.ts +14 -1
  174. package/extensions/lib/ledger/fold-memo.ts +49 -0
  175. package/extensions/lib/ledger/fold.ts +265 -0
  176. package/extensions/lib/ledger/layout.ts +72 -0
  177. package/extensions/lib/ledger/plan.ts +102 -0
  178. package/extensions/lib/ledger/records.ts +276 -0
  179. package/extensions/lib/ledger/state.ts +47 -0
  180. package/extensions/lib/ledger/validate.ts +141 -0
  181. package/extensions/lib/ledger/wire.ts +632 -0
  182. package/extensions/lib/local-command.ts +71 -19
  183. package/extensions/lib/mcp-overrides.ts +1 -1
  184. package/extensions/lib/mcp-share.ts +46 -0
  185. package/extensions/lib/memory-content.ts +146 -0
  186. package/extensions/lib/memory-index.ts +18 -0
  187. package/extensions/lib/memory.ts +134 -123
  188. package/extensions/lib/model-catalog/huggingface.json +178 -0
  189. package/extensions/lib/model-catalog/models-dev.json +18533 -0
  190. package/extensions/lib/model-catalog/openrouter.json +5050 -0
  191. package/extensions/lib/model-catalog-data.ts +513 -0
  192. package/extensions/lib/model-catalog.ts +462 -0
  193. package/extensions/lib/model-choice-warnings.ts +137 -0
  194. package/extensions/lib/model-pairings.ts +152 -0
  195. package/extensions/{auto-mode → lib}/model-picker.ts +26 -43
  196. package/extensions/lib/model-policy.ts +112 -15
  197. package/extensions/lib/model-tier.ts +283 -355
  198. package/extensions/lib/model-unusable.ts +1 -1
  199. package/extensions/lib/newer-model.ts +100 -0
  200. package/extensions/lib/notices.ts +87 -0
  201. package/extensions/lib/notifications.ts +357 -73
  202. package/extensions/lib/one-code-settings.ts +74 -8
  203. package/extensions/lib/open-browser.ts +63 -0
  204. package/extensions/lib/openrouter-generation.ts +94 -0
  205. package/extensions/lib/operation-deadline.ts +30 -0
  206. package/extensions/lib/original-command.ts +4 -4
  207. package/extensions/lib/package-version.ts +1 -1
  208. package/extensions/lib/panel-focus.ts +134 -0
  209. package/extensions/lib/paths.ts +17 -2
  210. package/extensions/lib/permission-gate.ts +72 -6
  211. package/extensions/lib/persisted-output.ts +60 -8
  212. package/extensions/lib/pi-ai-estimate.ts +19 -3
  213. package/extensions/lib/pi-version.ts +38 -2
  214. package/extensions/lib/plan-mode-channels.ts +42 -5
  215. package/extensions/lib/plugins.ts +26 -17
  216. package/extensions/lib/powershell-parse-script.ts +208 -0
  217. package/extensions/lib/powershell-parser.ts +344 -0
  218. package/extensions/lib/previous-mark.ts +101 -0
  219. package/extensions/lib/process-state.ts +48 -0
  220. package/extensions/lib/process-tree.ts +132 -8
  221. package/extensions/lib/prompt-options.ts +82 -0
  222. package/extensions/lib/queued-delivery.ts +44 -0
  223. package/extensions/lib/reminders.ts +370 -358
  224. package/extensions/lib/replaced-builtins.mjs +199 -0
  225. package/extensions/lib/replay-call.ts +70 -0
  226. package/extensions/lib/request-replay.ts +547 -0
  227. package/extensions/lib/scratchpad.ts +81 -14
  228. package/extensions/lib/send-now-channel.ts +7 -0
  229. package/extensions/lib/session-model-tier.ts +51 -0
  230. package/extensions/lib/session-work.ts +64 -0
  231. package/extensions/lib/settings-channels.ts +4 -4
  232. package/extensions/lib/shell-exit-semantics.ts +170 -0
  233. package/extensions/lib/shell-quote.ts +11 -0
  234. package/extensions/lib/shell-result.ts +70 -0
  235. package/extensions/lib/shell-spawn.ts +70 -6
  236. package/extensions/lib/shell-tool.ts +75 -25
  237. package/extensions/lib/side-call-cache.ts +124 -0
  238. package/extensions/lib/side-call-run.ts +96 -0
  239. package/extensions/lib/side-call-usage.ts +38 -0
  240. package/extensions/lib/side-call.ts +24 -1
  241. package/extensions/lib/single-flight.ts +18 -0
  242. package/extensions/lib/skill-body.ts +42 -0
  243. package/extensions/lib/skill-scan.ts +63 -24
  244. package/extensions/lib/spill-file.ts +140 -0
  245. package/extensions/lib/subagent-handback.ts +112 -0
  246. package/extensions/lib/system-role.ts +156 -0
  247. package/extensions/lib/terminal-text.ts +114 -0
  248. package/extensions/lib/text-width.ts +47 -16
  249. package/extensions/lib/timer-ops.ts +20 -0
  250. package/extensions/lib/tool-additions.ts +129 -0
  251. package/extensions/lib/tool-call-corruption.ts +134 -0
  252. package/extensions/lib/tool-path.ts +66 -0
  253. package/extensions/lib/tool-variants.ts +69 -0
  254. package/extensions/lib/tui-render.ts +255 -27
  255. package/extensions/lib/turn-budget-layout.ts +159 -0
  256. package/extensions/lib/update-check.mjs +15 -2
  257. package/extensions/lib/usage-bus.ts +1 -1
  258. package/extensions/lib/user-denial.ts +38 -0
  259. package/extensions/lib/workspace-channel.ts +16 -0
  260. package/extensions/lib/worktree-channel.ts +31 -3
  261. package/extensions/lib/worktree-isolation.ts +40 -10
  262. package/extensions/lsp/client.ts +8 -9
  263. package/extensions/lsp/index.ts +76 -12
  264. package/extensions/lsp/keep-alive.ts +1 -1
  265. package/extensions/lsp/trust.ts +119 -0
  266. package/extensions/lsp/watcher.ts +1 -1
  267. package/extensions/mcp/announce.ts +90 -43
  268. package/extensions/mcp/client.ts +161 -48
  269. package/extensions/mcp/config.ts +132 -8
  270. package/extensions/mcp/discovery.ts +19 -0
  271. package/extensions/mcp/index.ts +220 -121
  272. package/extensions/mcp/oauth/browser.ts +38 -17
  273. package/extensions/mcp/oauth/flow.ts +25 -17
  274. package/extensions/mcp/oauth/provider.ts +14 -8
  275. package/extensions/mcp/oauth/store.ts +34 -16
  276. package/extensions/mcp/panel/keys.ts +12 -11
  277. package/extensions/mcp/panel/render.ts +9 -6
  278. package/extensions/mcp/schema.ts +104 -5
  279. package/extensions/mcp/trust.ts +164 -73
  280. package/extensions/memory/entries.ts +23 -14
  281. package/extensions/memory/index.ts +134 -28
  282. package/extensions/memory/open-external.ts +33 -18
  283. package/extensions/memory/panel.ts +135 -26
  284. package/extensions/model-default/index.ts +86 -19
  285. package/extensions/newer-model/index.ts +31 -0
  286. package/extensions/notebook/description.ts +18 -0
  287. package/extensions/notebook/index.ts +6 -5
  288. package/extensions/notebook/notebook.ts +1 -1
  289. package/extensions/permissions/index.ts +1426 -398
  290. package/extensions/permissions/matcher.ts +425 -74
  291. package/extensions/permissions/modes.ts +11 -4
  292. package/extensions/permissions/panel/host.ts +130 -0
  293. package/extensions/permissions/panel/keys.ts +48 -0
  294. package/extensions/permissions/panel/render.ts +450 -0
  295. package/extensions/permissions/panel/state.ts +550 -0
  296. package/extensions/permissions/powershell-cmdlets.ts +198 -0
  297. package/extensions/permissions/powershell-paths.ts +197 -0
  298. package/extensions/permissions/powershell-rules.ts +207 -280
  299. package/extensions/permissions/powershell-tree.ts +557 -0
  300. package/extensions/permissions/project-trust.ts +27 -11
  301. package/extensions/permissions/protected-paths.ts +14 -2
  302. package/extensions/permissions/session-grant.ts +6 -0
  303. package/extensions/permissions/settings.ts +166 -31
  304. package/extensions/permissions/subagent-gate.ts +25 -0
  305. package/extensions/permissions/workspace.ts +78 -0
  306. package/extensions/plan-mode/index.ts +276 -92
  307. package/extensions/plan-mode/reminder.ts +89 -21
  308. package/extensions/plan-mode/run-state.ts +26 -0
  309. package/extensions/plan-mode/texts.ts +177 -0
  310. package/extensions/plan-mode/viewer.ts +92 -27
  311. package/extensions/plugins/counts.ts +3 -3
  312. package/extensions/plugins/index.ts +64 -46
  313. package/extensions/plugins/install/install.ts +16 -0
  314. package/extensions/plugins/marketplace/sync.ts +9 -3
  315. package/extensions/plugins/marketplace/types.ts +3 -1
  316. package/extensions/plugins/panel/keys.ts +21 -24
  317. package/extensions/plugins/panel/render.ts +12 -6
  318. package/extensions/plugins/shell-expand.ts +107 -0
  319. package/extensions/plugins/template.ts +32 -15
  320. package/extensions/powershell/child.ts +7 -0
  321. package/extensions/powershell/description.ts +38 -6
  322. package/extensions/powershell/guards.ts +1 -1
  323. package/extensions/powershell/index.ts +14 -7
  324. package/extensions/recap/index.ts +73 -71
  325. package/extensions/recap/prompt.ts +2 -2
  326. package/extensions/recap/scheduler.ts +3 -5
  327. package/extensions/search-tools/grep-merge.ts +39 -0
  328. package/extensions/search-tools/index.ts +0 -0
  329. package/extensions/send-now/chord.ts +62 -0
  330. package/extensions/send-now/index.ts +133 -0
  331. package/extensions/session-title/index.ts +3 -0
  332. package/extensions/session-title/title.ts +4 -1
  333. package/extensions/skill/announce.ts +30 -0
  334. package/extensions/skill/code-review.ts +97 -0
  335. package/extensions/skill/index.ts +469 -132
  336. package/extensions/skill/invoke.ts +118 -75
  337. package/extensions/skill/listing.ts +133 -9
  338. package/extensions/skill/panel/keys.ts +15 -16
  339. package/extensions/skill/panel/render.ts +5 -2
  340. package/extensions/skill/panel/state.ts +12 -1
  341. package/extensions/subagents/agent-args.ts +39 -0
  342. package/extensions/subagents/agent-description.ts +132 -0
  343. package/extensions/subagents/agents.ts +146 -31
  344. package/extensions/subagents/default-model.ts +2 -3
  345. package/extensions/subagents/delegation-steer.ts +4 -4
  346. package/extensions/subagents/fork-cache.ts +82 -0
  347. package/extensions/subagents/guide-agent.ts +189 -0
  348. package/extensions/subagents/hand-back-review.ts +3 -0
  349. package/extensions/subagents/index.ts +1594 -852
  350. package/extensions/subagents/live-runs.ts +26 -6
  351. package/extensions/subagents/model-select.ts +38 -25
  352. package/extensions/subagents/outcome.ts +5 -2
  353. package/extensions/subagents/panel-keys.ts +73 -31
  354. package/extensions/subagents/panel-render.ts +120 -96
  355. package/extensions/subagents/panel-widget.ts +60 -89
  356. package/extensions/subagents/parent-mode.ts +50 -0
  357. package/extensions/subagents/pending-claim.ts +18 -1
  358. package/extensions/subagents/runner.ts +135 -80
  359. package/extensions/subagents/runs.ts +44 -5
  360. package/extensions/subagents/send-to-main-tool.ts +1 -1
  361. package/extensions/subagents/session-turns.ts +32 -8
  362. package/extensions/subagents/shell-panel.ts +36 -178
  363. package/extensions/subagents/tasks-dialog.ts +170 -0
  364. package/extensions/subagents/viewport-mirror.ts +95 -0
  365. package/extensions/subagents/worktree.ts +57 -13
  366. package/extensions/system-prompt/environment.ts +19 -19
  367. package/extensions/system-prompt/idle-turn.ts +65 -0
  368. package/extensions/system-prompt/index.ts +165 -47
  369. package/extensions/system-prompt/template.ts +34 -51
  370. package/extensions/system-prompt/tiers/common.ts +23 -64
  371. package/extensions/system-prompt/tiers/frontier.ts +32 -11
  372. package/extensions/system-prompt/tiers/low.ts +67 -45
  373. package/extensions/system-prompt/tiers/mid.ts +96 -38
  374. package/extensions/system-reminder/index.ts +204 -70
  375. package/extensions/tasks/descriptions.ts +190 -0
  376. package/extensions/tasks/index.ts +120 -41
  377. package/extensions/tasks/store.ts +83 -16
  378. package/extensions/tool-call-corruption/child.ts +7 -0
  379. package/extensions/tool-call-corruption/index.ts +237 -0
  380. package/extensions/tool-search/index.ts +366 -144
  381. package/extensions/tool-style/index.ts +68 -10
  382. package/extensions/tool-style/write-description.ts +40 -0
  383. package/extensions/tool-style/write-render.ts +237 -0
  384. package/extensions/turn-duration/index.ts +7 -3
  385. package/extensions/turn-duration/line.ts +47 -4
  386. package/extensions/web/backends.ts +6 -9
  387. package/extensions/web/description.ts +50 -0
  388. package/extensions/web/index.ts +118 -53
  389. package/extensions/web/native-call.ts +15 -0
  390. package/extensions/web/native-results.ts +41 -0
  391. package/extensions/web-fetch/description.ts +42 -0
  392. package/extensions/web-fetch/extract.ts +53 -6
  393. package/extensions/web-fetch/index.ts +125 -76
  394. package/extensions/web-fetch/page-content.ts +19 -0
  395. package/extensions/web-fetch/response.ts +49 -0
  396. package/extensions/web-fetch/summarize.ts +9 -10
  397. package/extensions/workflow/agent-session.ts +108 -18
  398. package/extensions/workflow/args.ts +24 -0
  399. package/extensions/workflow/description.ts +67 -0
  400. package/extensions/workflow/globals.ts +17 -3
  401. package/extensions/workflow/index.ts +157 -162
  402. package/extensions/workflow/records.ts +1 -0
  403. package/extensions/workflow/run-manager.ts +33 -6
  404. package/extensions/workflow/saved-workflows.ts +3 -2
  405. package/extensions/workflow/types.ts +22 -1
  406. package/extensions/workflow/viewer.ts +54 -24
  407. package/extensions/workflow/widget.ts +20 -0
  408. package/extensions/worktree/descriptions.ts +91 -0
  409. package/extensions/worktree/guards.ts +316 -54
  410. package/extensions/worktree/index.ts +162 -44
  411. package/extensions/worktree/powershell-guards.ts +167 -0
  412. package/extensions/worktree/rewrite.ts +14 -16
  413. package/package.json +21 -7
  414. package/skills/artifact-design/SKILL.md +85 -0
  415. package/skills/code-review/SKILL.md +20 -20
  416. package/skills/code-review/cells/arguments-and-flags.md +19 -0
  417. package/skills/code-review/cells/high-3x5-recall-verify.md +137 -0
  418. package/skills/code-review/cells/high-8-inline.md +122 -0
  419. package/skills/code-review/cells/low-1-pass-max4.md +27 -0
  420. package/skills/code-review/cells/low-1-pass-min-files-4.md +28 -0
  421. package/skills/code-review/cells/max-5x5-verify-sweep.md +162 -0
  422. package/skills/code-review/cells/medium-3x5-verify.md +132 -0
  423. package/skills/code-review/cells/minimal-prompt.md +32 -0
  424. package/skills/code-review/cells/xhigh-10-inline-sweep.md +149 -0
  425. package/skills/code-review/cells/xhigh-5x5-verify-sweep.md +162 -0
  426. package/skills/fewer-permission-prompts/SKILL.md +1 -1
  427. package/skills/loop/SKILL.md +11 -0
  428. package/skills/security-review/SKILL.md +2 -5
  429. package/skills/simplify/SKILL.md +7 -5
  430. package/skills/workflow-authoring/SKILL.md +143 -0
  431. package/themes/onecode-light.json +1 -1
  432. package/themes/onecode.json +1 -1
  433. package/types/app.d.ts +58 -0
  434. package/types/community-packages.d.ts +26 -1
  435. package/extensions/auto-mode/recoverability.ts +0 -229
  436. package/extensions/lib/capability-index.ts +0 -466
  437. package/extensions/lib/model-facts.generated.json +0 -2675
  438. package/extensions/lib/model-facts.ts +0 -162
  439. package/extensions/tool-search/announce.ts +0 -42
@@ -5,8 +5,9 @@
5
5
  * server found in .mcp.json" and remembers the answer in
6
6
  * `enabledMcpjsonServers` / `disabledMcpjsonServers` /
7
7
  * `enableAllProjectMcpServers`. One Code honours those three keys READ-ONLY
8
- * (user and `.claude/settings.local.json` scopes — never the checked-in
9
- * project `settings.json`, which would let a repo approve itself) and keeps its
8
+ * (the approving two from the user's settings only, the disable list from
9
+ * `.claude/settings.local.json` too — never the checked-in project
10
+ * `settings.json`, which would let a repo approve itself) and keeps its
10
11
  * own answers under `~/.onecode`, keyed to a hash of each server's config so a
11
12
  * changed command re-prompts (CC keys by name alone). Servers from
12
13
  * `~/.claude.json` and plugins never prompt: the user wrote the first, and
@@ -14,8 +15,9 @@
14
15
  * ARE prompted (that file can be checked in — `git clone && onecode` would
15
16
  * otherwise spawn its servers with no consent, review H1); CC never reads
16
17
  * `mcpServers` from that file at all. Its `enableAll*`/`enabledMcpjsonServers`
17
- * policy keys are honoured only when the file is not git-tracked, for the same
18
- * reason.
18
+ * policy keys are never honoured, for the same reason: git provenance cannot
19
+ * tell a user's file from one shipped with a copied checkout
20
+ * (`readClaudeMcpjsonPolicy`).
19
21
  *
20
22
  * A "No" is persisted as a project-scope disable (`lib/mcp-overrides.ts`), so
21
23
  * the server shows as disabled in `/mcp` and Enable there brings it back —
@@ -23,17 +25,16 @@
23
25
  * only. Same shape as `hooks/trust.ts`.
24
26
  */
25
27
 
26
- import { execFile } from "node:child_process";
27
28
  import { createHash } from "node:crypto";
28
- import { promisify } from "node:util";
29
29
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
30
30
  import { basename, dirname, join } from "node:path";
31
- import { readSettingsFile, settingsPaths } from "../lib/claude-settings.ts";
31
+ import { readSettingsFile, type SettingsSource, settingsSources } from "../lib/claude-settings.ts";
32
+ import { claudeSourcesOn } from "../lib/config-mode.ts";
32
33
  import { boundConsentItems } from "../lib/consent-preview.ts";
33
- import { oneCodeStateDir } from "../lib/paths.ts";
34
+ import { consentStorePath } from "../lib/consent-stores.ts";
35
+ import { processState } from "../lib/process-state.ts";
34
36
  import type { McpServer } from "./config.ts";
35
-
36
- const execFileAsync = promisify(execFile);
37
+ import { escapeControlText } from "../lib/terminal-text.ts";
37
38
 
38
39
  interface ProjectApprovals {
39
40
  /** "Use this and all future MCP servers in this project" was chosen. */
@@ -47,19 +48,42 @@ interface ApprovalStore {
47
48
  }
48
49
 
49
50
  export function approvalStorePath(): string {
50
- return join(oneCodeStateDir(), "mcp", "project-approvals.json");
51
+ return consentStorePath("mcp");
51
52
  }
52
53
 
53
54
  /**
54
- * A server whose config a repository can ship (a project `.mcp.json` or a
55
- * checked-in `.claude/settings.local.json`) — so it is consent-gated. A
56
- * plugin's `.mcp.json` (also named `.mcp.json`) is excluded: installing the
57
- * plugin was the consent.
55
+ * A server whose config a repository can ship (a project `.mcp.json`, a
56
+ * checked-in `.claude/settings.local.json`, or pi's project `.pi/mcp.json`) —
57
+ * so it is consent-gated. A plugin's `.mcp.json` (also named `.mcp.json`) is
58
+ * excluded: installing the plugin was the consent. pi's user file
59
+ * (`<agentDir>/mcp.json`) is the user's own, like `~/.claude.json`.
58
60
  */
59
61
  export function isProjectScopedServer(server: McpServer, pluginConfigPaths: ReadonlySet<string>): boolean {
60
62
  if (pluginConfigPaths.has(server.source)) return false;
61
63
  const base = basename(server.source);
62
- return base === ".mcp.json" || base === "settings.local.json";
64
+ return base === ".mcp.json" || base === "settings.local.json" || server.piOrigin === "project";
65
+ }
66
+
67
+ /** A server from a project `.mcp.json`: the only kind Claude Code's own answers approve. */
68
+ function definedInMcpjson(server: McpServer): boolean {
69
+ return basename(server.source) === ".mcp.json";
70
+ }
71
+
72
+ /** The project file a consent-gated server comes from, as the dialog names it. */
73
+ function configLabel(server: McpServer): string {
74
+ if (definedInLocalSettings(server)) return ".claude/settings.local.json";
75
+ // pi's project file is `<dir>/<pi's config dir>/mcp.json`, `.pi/mcp.json` unless pi is rebranded.
76
+ return server.piOrigin === "project" ? `${basename(dirname(server.source))}/mcp.json` : ".mcp.json";
77
+ }
78
+
79
+ /** "a and b" for the distinct config files of `servers`. */
80
+ function configLabels(servers: McpServer[]): string {
81
+ return [...new Set(servers.map(configLabel))].join(" and ");
82
+ }
83
+
84
+ /** A server defined in `.claude/settings.local.json` rather than a `.mcp.json`. */
85
+ function definedInLocalSettings(server: McpServer): boolean {
86
+ return basename(server.source) === "settings.local.json";
63
87
  }
64
88
 
65
89
  /** The directory the `.mcp.json` lives in — approvals are per config file, not per cwd. */
@@ -79,12 +103,15 @@ function canonicalize(value: unknown): unknown {
79
103
  return value;
80
104
  }
81
105
 
82
- /** Everything that decides what the server runs or talks to; `source`/`missingEnv` are not part of it. */
106
+ /**
107
+ * Everything that decides what the server runs or talks to; `source`/`missingEnv` are not part of it.
108
+ * A stdio `cwd` (pi's files only) joins the material only when set, so existing approvals keep their hash.
109
+ */
83
110
  export function hashServerConfig(server: McpServer): string {
84
111
  const material =
85
112
  server.kind === "stdio"
86
- ? { kind: "stdio", command: server.command, args: server.args, env: server.env ?? {} }
87
- : { kind: "http", url: server.url, headers: server.headers ?? {} };
113
+ ? { kind: "stdio", command: server.command, args: server.args, env: server.env ?? {}, ...(server.cwd ? { cwd: server.cwd } : {}) }
114
+ : { kind: "http", url: server.url, headers: server.headers ?? {}, ...(server.transport ? { transport: server.transport } : {}) };
88
115
  return createHash("sha256").update(JSON.stringify(canonicalize(material))).digest("hex");
89
116
  }
90
117
 
@@ -100,45 +127,36 @@ function stringArray(value: unknown): string[] {
100
127
  }
101
128
 
102
129
  /**
103
- * Whether `.claude/settings.local.json`'s policy keys may be trusted: true ONLY
104
- * when git ran to a verdict and the file is not a tracked file (untracked in a
105
- * repo, or no repo at all — either way not something a `git clone` shipped).
106
- * FAILS CLOSED: git missing, a timeout, or any result we cannot interpret
107
- * returns false, so a checked-in file that we could not prove untracked is not
108
- * trusted (review H1 — a fail-open here silently re-opens the self-approval
109
- * hole). Async so it never blocks the event loop from the connect path
110
- * (findings §15: never do slow synchronous work on the startup path).
130
+ * Claude Code's answers that One Code honours. The approving keys
131
+ * (`enableAllProjectMcpServers`, `enabledMcpjsonServers`) count only from the
132
+ * user's `~/.claude/settings.json`. Until 2026-09-27 they also counted from a
133
+ * `.claude/settings.local.json` that git reported untracked, but a directory
134
+ * that carries its own `.git` (a tarball of a working copy, a copied or
135
+ * synced checkout) makes a shipped file untracked too, so its servers
136
+ * connected with no prompt, headless included. No check of the local file
137
+ * can tell who wrote it, so it no longer approves anything: its servers go
138
+ * through One Code's own dialog and hash-keyed store. Its
139
+ * `disabledMcpjsonServers` only tightens, so it is still honoured. Async for
140
+ * its callers; nothing here shells out any more.
111
141
  */
112
- async function localPolicyFileIsTrusted(cwd: string, path: string): Promise<boolean> {
113
- try {
114
- await execFileAsync("git", ["ls-files", "--error-unmatch", "--", path], { cwd, timeout: 5_000 });
115
- return false; // exit 0 → tracked → do not trust its policy keys
116
- } catch (error) {
117
- // execFile rejects with `code` = the numeric exit code on a non-zero exit
118
- // (1 = untracked in a repo, 128 = not a repo — both mean "not tracked, safe
119
- // to trust"); a spawn failure gives a string code (e.g. "ENOENT") and a
120
- // timeout gives a non-numeric code — those are "could not decide" → closed.
121
- return typeof (error as { code?: unknown }).code === "number";
122
- }
123
- }
124
-
125
142
  export async function readClaudeMcpjsonPolicy(cwd: string, home: string): Promise<ClaudeMcpjsonPolicy> {
126
- const paths = settingsPaths(cwd, home);
143
+ // Independent mode (lib/config-mode.ts) reads the same keys from One Code's
144
+ // user file, and only the tightening one from its per-repo file.
145
+ const claude = claudeSourcesOn();
146
+ const userScope: SettingsSource = claude ? "claude-user" : "onecode-user";
147
+ const localScope: SettingsSource = claude ? "project-local" : "onecode-project";
127
148
  const policy: ClaudeMcpjsonPolicy = { enableAll: false, enabled: new Set(), disabled: new Set() };
128
- // Deliberately not `paths.project`: a checked-in settings.json granting
149
+ // Deliberately not the project file: a checked-in settings.json granting
129
150
  // enableAllProjectMcpServers would be the repo approving its own servers.
130
- // The local file is read only when it is provably not git-tracked (an
131
- // untracked, user-authored file), for the same reason — a checked-in
132
- // settings.local.json would otherwise approve the repo's own .mcp.json
133
- // servers (review H1).
134
- const sources = [paths.user];
135
- if (await localPolicyFileIsTrusted(cwd, paths.local)) sources.push(paths.local);
136
- for (const path of sources) {
151
+ // The local file is in the checkout too, whatever git says about it.
152
+ for (const [source, path] of settingsSources(cwd, home)) {
153
+ if (source !== userScope && source !== localScope) continue;
137
154
  const file = readSettingsFile(path);
138
155
  if (!file) continue;
156
+ for (const name of stringArray(file.disabledMcpjsonServers)) policy.disabled.add(name);
157
+ if (source === localScope) continue;
139
158
  if (typeof file.enableAllProjectMcpServers === "boolean") policy.enableAll = file.enableAllProjectMcpServers;
140
159
  for (const name of stringArray(file.enabledMcpjsonServers)) policy.enabled.add(name);
141
- for (const name of stringArray(file.disabledMcpjsonServers)) policy.disabled.add(name);
142
160
  }
143
161
  return policy;
144
162
  }
@@ -182,25 +200,81 @@ export function persistEnableAll(projectRoot: string, storePath = approvalStoreP
182
200
  writeStore(storePath, store);
183
201
  }
184
202
 
203
+ /**
204
+ * Why `/mcp`'s Reconnect must not connect a server, or undefined. A server
205
+ * whose config references an unset variable is never connected (startup
206
+ * skips it and never asks for consent), so Reconnect must not either: it
207
+ * would spawn the command with the variable expanded to nothing, and a
208
+ * project server would run with no consent.
209
+ */
210
+ export function reconnectRefusal(server: McpServer): string | undefined {
211
+ if (!server.missingEnv?.length) return undefined;
212
+ const names = server.missingEnv.join(", ");
213
+ return `"${server.name}" needs ${names} set in the environment. Set ${server.missingEnv.length === 1 ? "it" : "them"} and restart One Code.`;
214
+ }
215
+
185
216
  export const CHOICE_ALL = "Use this and all future MCP servers in this project";
186
217
  export const CHOICE_THIS = "Use this MCP server";
187
218
  export const CHOICE_THESE = "Use these MCP servers";
188
219
  export const CHOICE_NO = "No";
189
220
 
190
- /** Claude Code's dialog title for one or several newly found servers. */
191
- export function promptTitle(names: string[]): string {
221
+ /** Claude Code's dialog title for one or several newly found servers; `file` names where they were found. */
222
+ export function promptTitle(names: string[], file = ".mcp.json"): string {
192
223
  return names.length === 1
193
- ? `New MCP server found in .mcp.json: ${names[0]}`
194
- : `${names.length} new MCP servers found in .mcp.json`;
224
+ ? `New MCP server found in ${file}: ${escapeControlText(names[0])}`
225
+ : `${names.length} new MCP servers found in ${file}`;
226
+ }
227
+
228
+ /**
229
+ * Environment variables that change what a stdio server's command runs, or
230
+ * where it loads code from: an interpreter's preload and search paths, the
231
+ * dynamic loader's, `PATH`, and npm's config. Matched case-insensitively
232
+ * (Windows environment names are). The consent dialog shows these values in
233
+ * full, because `npx -y some-mcp` with `NODE_OPTIONS=--require ./x.js` is not
234
+ * the command it looks like.
235
+ */
236
+ const EXECUTION_ENV = new Set([
237
+ "PATH",
238
+ "NODE_OPTIONS",
239
+ "NODE_PATH",
240
+ "LD_PRELOAD",
241
+ "LD_LIBRARY_PATH",
242
+ "LD_AUDIT",
243
+ "PYTHONPATH",
244
+ "PYTHONSTARTUP",
245
+ "PYTHONHOME",
246
+ "PERL5OPT",
247
+ "PERL5LIB",
248
+ "RUBYOPT",
249
+ "RUBYLIB",
250
+ "BASH_ENV",
251
+ "ENV",
252
+ "JAVA_TOOL_OPTIONS",
253
+ "_JAVA_OPTIONS",
254
+ "JDK_JAVA_OPTIONS",
255
+ "ELECTRON_RUN_AS_NODE",
256
+ "GIT_SSH_COMMAND",
257
+ "GIT_EXEC_PATH",
258
+ "COMSPEC",
259
+ "PATHEXT",
260
+ ]);
261
+ const EXECUTION_ENV_PREFIXES = ["DYLD_", "NPM_CONFIG_"];
262
+
263
+ /** Whether an env key changes what a server's command executes (`EXECUTION_ENV`). */
264
+ export function changesExecution(key: string): boolean {
265
+ const upper = key.toUpperCase();
266
+ return EXECUTION_ENV.has(upper) || EXECUTION_ENV_PREFIXES.some((prefix) => upper.startsWith(prefix));
195
267
  }
196
268
 
197
269
  /**
198
270
  * One line per server naming what would run, for the dialog body. Commands and
199
- * URLs are shown in full (a truncated one hides where a padded attack lives),
200
- * env values are never echoed, but the variable NAMES a server's
201
- * command/args/env/headers reference are listed (from `referencedEnv`, captured
202
- * before expansion) — approving a URL should not silently ship a credential the
203
- * header interpolates (review M5).
271
+ * URLs are shown in full (a truncated one hides where a padded attack lives).
272
+ * Every `env` key a stdio server sets is named; the values of the keys that
273
+ * change what executes (`changesExecution`) are shown in full, quoted, and the
274
+ * rest are not echoed, since they are usually credentials. The variable NAMES
275
+ * a server's command/args/env/headers reference are listed too (from
276
+ * `referencedEnv`, captured before expansion) — approving a URL should not
277
+ * silently ship a credential the header interpolates (review M5).
204
278
  */
205
279
  export function describeServers(servers: McpServer[]): string {
206
280
  const lines = servers.map((server) => {
@@ -210,14 +284,17 @@ export function describeServers(servers: McpServer[]): string {
210
284
  : `${server.name}: ${server.url}`;
211
285
  const vars = server.referencedEnv ?? [];
212
286
  const headerNames = server.kind === "http" ? Object.keys(server.headers ?? {}) : [];
287
+ const env = server.kind === "stdio" ? Object.entries(server.env ?? {}) : [];
213
288
  const notes = [
289
+ server.kind === "stdio" && server.cwd ? `cwd: ${server.cwd}` : "",
290
+ env.length ? `env: ${env.map(([key, value]) => (changesExecution(key) ? `${key}=${JSON.stringify(value)}` : key)).join(", ")}` : "",
214
291
  vars.length ? `uses ${vars.map((v) => `$${v}`).join(", ")}` : "",
215
292
  headerNames.length ? `headers: ${headerNames.join(", ")}` : "",
216
293
  ].filter(Boolean);
217
294
  return notes.length ? `${what}\n (${notes.join("; ")})` : what;
218
295
  });
219
296
  // Bound the modal: a very long command/url or many servers cannot flood it.
220
- return boundConsentItems(lines, "review .mcp.json before approving");
297
+ return boundConsentItems(lines, `review ${configLabels(servers)} before approving`);
221
298
  }
222
299
 
223
300
  export interface McpTrustDeps {
@@ -237,8 +314,14 @@ export interface McpTrustOutcome {
237
314
  withheld: { server: McpServer; reason: "declined" | "not-approved" | "disabled-by-claude-settings" }[];
238
315
  }
239
316
 
240
- /** Process-lifetime memory per project+server+hash, so /clear (a new session_start) does not re-ask a "No". */
241
- const sessionDecisions = new Map<string, boolean>();
317
+ /**
318
+ * Process-lifetime memory per project+server+hash, so /clear (a new
319
+ * session_start) and /reload do not re-ask a "No". Process state
320
+ * (lib/process-state.ts), not module scope: pi evaluates this module again
321
+ * at `/reload` and at a `/resume` into another directory (lifecycle grid
322
+ * R3-L13).
323
+ */
324
+ const sessionDecisions = () => processState("mcp:trust-decisions", () => new Map<string, boolean>());
242
325
  const pendingPrompts = new Map<string, Promise<string | undefined>>();
243
326
 
244
327
  /**
@@ -255,9 +338,8 @@ export async function approveMcpServers(
255
338
  const approved: McpServer[] = [];
256
339
  const withheld: McpTrustOutcome["withheld"] = [];
257
340
  const pending: McpServer[] = [];
258
- // Reading CC's policy shells out to git (localPolicyFileIsTrusted), so only
259
- // do it when a server actually needs consent — a session with only
260
- // user-scope or plugin servers must not pay a git spawn at connect.
341
+ // Reading CC's policy reads two settings files, so only do it when a
342
+ // server actually needs consent.
261
343
  const anyProjectScoped = servers.some((s) => isProjectScopedServer(s, pluginConfigPaths));
262
344
  const claude: ClaudeMcpjsonPolicy = anyProjectScoped
263
345
  ? await readClaudeMcpjsonPolicy(cwd, home)
@@ -272,7 +354,12 @@ export async function approveMcpServers(
272
354
  withheld.push({ server, reason: "disabled-by-claude-settings" });
273
355
  continue;
274
356
  }
275
- if (claude.enableAll || claude.enabled.has(server.name)) {
357
+ // Claude Code's own answers approve `.mcp.json` servers only. A server
358
+ // DEFINED in settings.local.json must never be approved by that same
359
+ // file's `enableAllProjectMcpServers` (SECURITY-REVIEW-2026-09-23 H4), and
360
+ // one from pi's `.pi/mcp.json` is not a file those answers were about: both
361
+ // go through One Code's hash-keyed consent below, like any other.
362
+ if (definedInMcpjson(server) && (claude.enableAll || claude.enabled.has(server.name))) {
276
363
  approved.push(server);
277
364
  continue;
278
365
  }
@@ -283,7 +370,7 @@ export async function approveMcpServers(
283
370
  approved.push(server);
284
371
  continue;
285
372
  }
286
- const remembered = sessionDecisions.get(`${root}:${server.name}:${hash}`);
373
+ const remembered = sessionDecisions().get(`${root}:${server.name}:${hash}`);
287
374
  if (remembered === true) approved.push(server);
288
375
  else if (remembered === false) withheld.push({ server, reason: "declined" });
289
376
  else pending.push(server);
@@ -293,8 +380,12 @@ export async function approveMcpServers(
293
380
 
294
381
  if (!deps.hasUI) {
295
382
  for (const server of pending) withheld.push({ server, reason: "not-approved" });
383
+ // enabledMcpjsonServers approves `.mcp.json` servers only (above), so the
384
+ // hint names it only when one of those is waiting.
385
+ const fromMcpjson = pending.some(definedInMcpjson);
386
+ const sources = configLabels(pending);
296
387
  deps.notify(
297
- `Skipped ${pending.length} MCP server${pending.length === 1 ? "" : "s"} from .mcp.json (${pending.map((s) => s.name).join(", ")}): not yet approved and no UI to ask. Approve once in an interactive session, or set enabledMcpjsonServers in .claude/settings.local.json.`,
388
+ `Skipped ${pending.length} MCP server${pending.length === 1 ? "" : "s"} from ${sources} (${pending.map((s) => s.name).join(", ")}): not yet approved and no UI to ask. Approve once in an interactive session${fromMcpjson ? ", or set enabledMcpjsonServers in ~/.claude/settings.json" : ""}.`,
298
389
  );
299
390
  return { approved, withheld };
300
391
  }
@@ -306,7 +397,7 @@ export async function approveMcpServers(
306
397
  if (!prompt) {
307
398
  const useLabel = pending.length === 1 ? CHOICE_THIS : CHOICE_THESE;
308
399
  prompt = deps
309
- .select(`${promptTitle(names)}\n\n${describeServers(pending)}\n\nThese run on your machine.`, [CHOICE_ALL, useLabel, CHOICE_NO])
400
+ .select(`${promptTitle(names, configLabels(pending))}\n\n${describeServers(pending)}\n\nThese run on your machine.`, [CHOICE_ALL, useLabel, CHOICE_NO])
310
401
  .finally(() => pendingPrompts.delete(key));
311
402
  pendingPrompts.set(key, prompt);
312
403
  }
@@ -316,25 +407,25 @@ export async function approveMcpServers(
316
407
  const root = projectRootOf(server);
317
408
  const decisionKey = `${root}:${server.name}:${hashServerConfig(server)}`;
318
409
  if (choice === CHOICE_ALL || choice === CHOICE_THIS || choice === CHOICE_THESE) {
319
- sessionDecisions.set(decisionKey, true);
410
+ sessionDecisions().set(decisionKey, true);
320
411
  if (choice === CHOICE_ALL) persistEnableAll(root, deps.storePath);
321
412
  persistApproval(root, server, deps.storePath);
322
413
  approved.push(server);
323
414
  } else {
324
- sessionDecisions.set(decisionKey, false);
415
+ sessionDecisions().set(decisionKey, false);
325
416
  withheld.push({ server, reason: "declined" });
326
417
  // An explicit "No" is remembered as a disable; Escape is this session only.
327
418
  if (choice === CHOICE_NO) deps.disable(server);
328
419
  }
329
420
  }
330
421
  if (choice !== CHOICE_ALL && choice !== CHOICE_THIS && choice !== CHOICE_THESE) {
331
- deps.notify(`MCP server${pending.length === 1 ? "" : "s"} from .mcp.json not connected (${names.join(", ")}); enable in /mcp.`);
422
+ deps.notify(`MCP server${pending.length === 1 ? "" : "s"} from ${configLabels(pending)} not connected (${names.join(", ")}); enable in /mcp.`);
332
423
  }
333
424
  return { approved, withheld };
334
425
  }
335
426
 
336
427
  /** Test seam. */
337
428
  export function resetMcpTrustSessionState(): void {
338
- sessionDecisions.clear();
429
+ sessionDecisions().clear();
339
430
  pendingPrompts.clear();
340
431
  }
@@ -24,6 +24,7 @@ import {
24
24
  ONECODE_DESCRIPTOR,
25
25
  ONECODE_GLOBAL_DESCRIPTOR,
26
26
  PROJECT_DESCRIPTOR,
27
+ instructionRule,
27
28
  } from "../lib/claude-context.ts";
28
29
  import { forwardSlashes, isRelativeInside, tildify } from "../lib/paths.ts";
29
30
  import { tryReadFile } from "../lib/plugins.ts";
@@ -69,12 +70,16 @@ export function buildMemoryEntries(opts: {
69
70
  home: string;
70
71
  homeClaudeDir: string;
71
72
  homeOneCodeDir: string;
72
- memoryDir: string;
73
+ /** The auto-memory folder; undefined while auto-memory is off (no folder row, as in Claude Code). */
74
+ memoryDir: string | undefined;
73
75
  }): MemoryEntry[] {
74
76
  const { cwd, home, homeClaudeDir, homeOneCodeDir, memoryDir } = opts;
75
- // agentsFallback so a directory's AGENTS.md (when it has no CLAUDE.md) is in the
76
- // list, matching what the # claudeMd block sends.
77
- const discovered = discoverContextFilePaths({ cwd, homeClaudeDir, homeOneCodeDir, agentsFallback: true });
77
+ // The same rule the # claudeMd block uses, so the list matches what it sends.
78
+ const rule = instructionRule(home);
79
+ // Independent mode (lib/config-mode.ts) reads no CLAUDE.md: its always-offered
80
+ // files are the global ONECODE.md and the project's AGENTS.md instead.
81
+ const independent = rule === "agents-md";
82
+ const discovered = discoverContextFilePaths({ cwd, homeClaudeDir, homeOneCodeDir, rule });
78
83
  const referenced = referencedImports(discovered, home);
79
84
  // (descriptor, dir) → the discovered path, so per-dir lookups reuse the real
80
85
  // on-disk casing discovery already resolved (no second stat/readdir here).
@@ -91,15 +96,15 @@ export function buildMemoryEntries(opts: {
91
96
  const disp = (path: string) => displayPath(path, cwd, home);
92
97
 
93
98
  // Global user instructions — always offered, matching CC (created on save).
94
- const globalClaude = join(homeClaudeDir, "CLAUDE.md");
99
+ const globalOneCode = found.get(`${ONECODE_GLOBAL_DESCRIPTOR}\0${homeOneCodeDir}`);
100
+ const globalUser = independent ? (globalOneCode ?? join(homeOneCodeDir, "ONECODE.md")) : join(homeClaudeDir, "CLAUDE.md");
95
101
  add({
96
102
  title: "User instructions",
97
- description: `Saved in ${disp(globalClaude)}`,
98
- path: globalClaude,
103
+ description: `Saved in ${disp(globalUser)}`,
104
+ path: globalUser,
99
105
  kind: "file",
100
- exists: found.has(`${GLOBAL_DESCRIPTOR}\0${homeClaudeDir}`),
106
+ exists: independent ? globalOneCode !== undefined : found.has(`${GLOBAL_DESCRIPTOR}\0${homeClaudeDir}`),
101
107
  });
102
- const globalOneCode = found.get(`${ONECODE_GLOBAL_DESCRIPTOR}\0${homeOneCodeDir}`);
103
108
  if (globalOneCode) {
104
109
  add({
105
110
  title: "One Code user instructions",
@@ -114,13 +119,14 @@ export function buildMemoryEntries(opts: {
114
119
  const isCwd = d === cwd;
115
120
  const claude = join(d, "CLAUDE.md");
116
121
  if (isCwd) {
117
- // Project instructions — always offered (created on save).
122
+ // Project instructions — always offered (created on save): AGENTS.md in independent mode.
123
+ const [name, descriptor] = independent ? ["AGENTS.md", AGENTS_DESCRIPTOR] : ["CLAUDE.md", PROJECT_DESCRIPTOR];
118
124
  add({
119
125
  title: "Project instructions",
120
- description: `Checked in at ${disp(claude)}`,
121
- path: claude,
126
+ description: `Checked in at ${disp(join(d, name))}`,
127
+ path: join(d, name),
122
128
  kind: "file",
123
- exists: found.has(`${PROJECT_DESCRIPTOR}\0${d}`),
129
+ exists: found.has(`${descriptor}\0${d}`),
124
130
  });
125
131
  } else if (found.has(`${PROJECT_DESCRIPTOR}\0${d}`)) {
126
132
  add({ title: disp(claude), path: claude, kind: "file", exists: true });
@@ -143,6 +149,9 @@ export function buildMemoryEntries(opts: {
143
149
  exists: true,
144
150
  });
145
151
  }
152
+ // `.claude/AGENTS.md`, which the AGENTS.md fallback loads too.
153
+ const dotClaudeAgents = found.get(`${AGENTS_DESCRIPTOR}\0${join(d, ".claude")}`);
154
+ if (dotClaudeAgents) add({ title: disp(dotClaudeAgents), path: dotClaudeAgents, kind: "file", exists: true });
146
155
 
147
156
  const oneCode = found.get(`${ONECODE_DESCRIPTOR}\0${d}`);
148
157
  if (oneCode) {
@@ -156,7 +165,7 @@ export function buildMemoryEntries(opts: {
156
165
  }
157
166
  }
158
167
 
159
- add({ title: "Open auto-memory folder", path: memoryDir, kind: "folder", exists: true });
168
+ if (memoryDir) add({ title: "Open auto-memory folder", path: memoryDir, kind: "folder", exists: true });
160
169
  return entries;
161
170
  }
162
171