one-code-extension 0.4.0 → 0.5.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 (419) hide show
  1. package/README.md +219 -219
  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 +32 -23
  7. package/docs/guide/doctor.md +20 -13
  8. package/docs/guide/hooks.md +18 -3
  9. package/docs/guide/installation.md +27 -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 +66 -34
  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 +123 -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 +515 -0
  56. package/extensions/background/index.ts +514 -236
  57. package/extensions/background/loop-fire.ts +136 -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 +52 -0
  63. package/extensions/background/wakeup.ts +159 -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 +88 -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 +229 -71
  77. package/extensions/btw/panel.ts +228 -100
  78. package/extensions/btw/prompt.ts +41 -4
  79. package/extensions/claude-compat/index.ts +7 -11
  80. package/extensions/claude-context/index.ts +446 -58
  81. package/extensions/compaction/cut.ts +157 -0
  82. package/extensions/compaction/index.ts +216 -75
  83. package/extensions/compaction/kept-thinking.ts +62 -0
  84. package/extensions/compaction/prompt.ts +15 -12
  85. package/extensions/context-budget/index.ts +24 -5
  86. package/extensions/context-management/index.ts +25 -0
  87. package/extensions/doctor/build.ts +59 -8
  88. package/extensions/doctor/builtins.ts +84 -0
  89. package/extensions/doctor/cli.ts +7 -1
  90. package/extensions/doctor/compat.ts +88 -23
  91. package/extensions/doctor/dependencies.ts +41 -5
  92. package/extensions/doctor/fix-prompt.ts +9 -2
  93. package/extensions/doctor/index.ts +102 -58
  94. package/extensions/doctor/models.ts +102 -63
  95. package/extensions/doctor/presets.ts +42 -27
  96. package/extensions/doctor/report.ts +19 -2
  97. package/extensions/doctor/viewer.ts +49 -27
  98. package/extensions/effort/index.ts +72 -19
  99. package/extensions/effort/settings.ts +21 -0
  100. package/extensions/effort/slider.ts +24 -20
  101. package/extensions/exit/index.ts +32 -1
  102. package/extensions/file-tracker/index.ts +337 -26
  103. package/extensions/file-tracker/replay.ts +96 -10
  104. package/extensions/file-tracker/restore.ts +63 -0
  105. package/extensions/file-tracker/results.ts +66 -0
  106. package/extensions/file-tracker/shell-reads.ts +211 -0
  107. package/extensions/file-tracker/tracker.ts +32 -15
  108. package/extensions/footer/footer-line.ts +45 -24
  109. package/extensions/footer/index.ts +47 -2
  110. package/extensions/footer/pr.ts +34 -5
  111. package/extensions/hooks/compaction.ts +7 -0
  112. package/extensions/hooks/executor.ts +32 -30
  113. package/extensions/hooks/index.ts +198 -31
  114. package/extensions/hooks/matcher.ts +3 -0
  115. package/extensions/hooks/protocol.ts +41 -3
  116. package/extensions/hooks/settings.ts +50 -19
  117. package/extensions/hooks/subagent-bridge.ts +2 -0
  118. package/extensions/hooks/trust.ts +13 -5
  119. package/extensions/idle-compact/index.ts +119 -0
  120. package/extensions/idle-compact/policy.ts +143 -0
  121. package/extensions/init/index.ts +11 -10
  122. package/extensions/init/prompt.ts +25 -32
  123. package/extensions/interrupted/index.ts +13 -1
  124. package/extensions/kept-thinking/index.ts +27 -0
  125. package/extensions/lib/agent-cron.ts +130 -0
  126. package/extensions/lib/agent-loader.ts +15 -1
  127. package/extensions/lib/agent-view.ts +85 -0
  128. package/extensions/lib/anthropic-payload.ts +82 -1
  129. package/extensions/lib/anthropic-server-call.ts +230 -0
  130. package/extensions/lib/anthropic-server-tools.ts +485 -0
  131. package/extensions/lib/app-launch.mjs +94 -0
  132. package/extensions/lib/argument-hints.ts +190 -0
  133. package/extensions/lib/atomic-write.ts +6 -2
  134. package/extensions/lib/auto-memory.ts +75 -0
  135. package/extensions/lib/bash-parser.ts +84 -0
  136. package/extensions/lib/btw-fork.ts +93 -0
  137. package/extensions/lib/child-extensions.ts +42 -0
  138. package/extensions/lib/child-writes.ts +45 -0
  139. package/extensions/lib/claude-context.ts +515 -100
  140. package/extensions/lib/claude-external-includes.ts +68 -0
  141. package/extensions/lib/claude-id.ts +22 -0
  142. package/extensions/lib/claude-rules.ts +323 -0
  143. package/extensions/lib/claude-settings.ts +76 -4
  144. package/extensions/lib/compaction-boundary.ts +36 -0
  145. package/extensions/lib/compaction-keep.mjs +83 -0
  146. package/extensions/lib/config-mode.ts +112 -0
  147. package/extensions/lib/consent-dialogs.ts +63 -0
  148. package/extensions/lib/consent-preview.ts +5 -1
  149. package/extensions/lib/consent-stores.ts +48 -0
  150. package/extensions/lib/context-facts.ts +78 -0
  151. package/extensions/lib/context-stack.ts +81 -0
  152. package/extensions/lib/deferred.ts +219 -25
  153. package/extensions/lib/dock-rows.ts +60 -0
  154. package/extensions/lib/empty-tool-result.ts +27 -0
  155. package/extensions/lib/environment-block.ts +76 -0
  156. package/extensions/lib/fetch-timeout.ts +24 -6
  157. package/extensions/{system-prompt → lib}/git-status.ts +51 -13
  158. package/extensions/lib/git.ts +75 -13
  159. package/extensions/lib/grammars/LICENSE-tree-sitter-bash +21 -0
  160. package/extensions/lib/grammars/README.md +2 -0
  161. package/extensions/lib/grammars/tree-sitter-bash.wasm +0 -0
  162. package/extensions/lib/guide-docs.ts +45 -0
  163. package/extensions/lib/headless-output.ts +46 -0
  164. package/extensions/lib/hook-gate.ts +7 -7
  165. package/extensions/lib/interrupt.ts +20 -4
  166. package/extensions/lib/key-input.ts +455 -0
  167. package/extensions/lib/keys.ts +14 -1
  168. package/extensions/lib/local-command.ts +47 -13
  169. package/extensions/lib/mcp-overrides.ts +1 -1
  170. package/extensions/lib/mcp-share.ts +46 -0
  171. package/extensions/lib/memory-content.ts +146 -0
  172. package/extensions/lib/memory-index.ts +18 -0
  173. package/extensions/lib/memory.ts +134 -123
  174. package/extensions/lib/model-catalog/huggingface.json +174 -0
  175. package/extensions/lib/model-catalog/models-dev.json +18297 -0
  176. package/extensions/lib/model-catalog/openrouter.json +5252 -0
  177. package/extensions/lib/model-catalog-data.ts +513 -0
  178. package/extensions/lib/model-catalog.ts +462 -0
  179. package/extensions/lib/model-choice-warnings.ts +137 -0
  180. package/extensions/lib/model-pairings.ts +152 -0
  181. package/extensions/{auto-mode → lib}/model-picker.ts +26 -43
  182. package/extensions/lib/model-policy.ts +112 -15
  183. package/extensions/lib/model-tier.ts +283 -355
  184. package/extensions/lib/model-unusable.ts +1 -1
  185. package/extensions/lib/newer-model.ts +100 -0
  186. package/extensions/lib/notices.ts +87 -0
  187. package/extensions/lib/notifications.ts +308 -64
  188. package/extensions/lib/one-code-settings.ts +74 -8
  189. package/extensions/lib/open-browser.ts +63 -0
  190. package/extensions/lib/openrouter-generation.ts +94 -0
  191. package/extensions/lib/operation-deadline.ts +30 -0
  192. package/extensions/lib/original-command.ts +4 -4
  193. package/extensions/lib/package-version.ts +1 -1
  194. package/extensions/lib/panel-focus.ts +134 -0
  195. package/extensions/lib/paths.ts +17 -2
  196. package/extensions/lib/permission-gate.ts +72 -6
  197. package/extensions/lib/persisted-output.ts +60 -8
  198. package/extensions/lib/pi-ai-estimate.ts +19 -3
  199. package/extensions/lib/pi-version.ts +21 -2
  200. package/extensions/lib/plan-mode-channels.ts +20 -5
  201. package/extensions/lib/plugins.ts +26 -17
  202. package/extensions/lib/powershell-parse-script.ts +208 -0
  203. package/extensions/lib/powershell-parser.ts +344 -0
  204. package/extensions/lib/process-tree.ts +131 -8
  205. package/extensions/lib/prompt-options.ts +82 -0
  206. package/extensions/lib/queued-delivery.ts +44 -0
  207. package/extensions/lib/reminders.ts +364 -58
  208. package/extensions/lib/replaced-builtins.mjs +199 -0
  209. package/extensions/lib/replay-call.ts +70 -0
  210. package/extensions/lib/request-replay.ts +439 -0
  211. package/extensions/lib/scratchpad.ts +81 -14
  212. package/extensions/lib/send-now-channel.ts +7 -0
  213. package/extensions/lib/session-model-tier.ts +51 -0
  214. package/extensions/lib/session-work.ts +64 -0
  215. package/extensions/lib/settings-channels.ts +4 -4
  216. package/extensions/lib/shell-exit-semantics.ts +170 -0
  217. package/extensions/lib/shell-quote.ts +11 -0
  218. package/extensions/lib/shell-result.ts +70 -0
  219. package/extensions/lib/shell-spawn.ts +70 -6
  220. package/extensions/lib/shell-tool.ts +75 -25
  221. package/extensions/lib/side-call-cache.ts +124 -0
  222. package/extensions/lib/side-call-run.ts +96 -0
  223. package/extensions/lib/side-call-usage.ts +38 -0
  224. package/extensions/lib/side-call.ts +13 -1
  225. package/extensions/lib/single-flight.ts +18 -0
  226. package/extensions/lib/skill-body.ts +42 -0
  227. package/extensions/lib/skill-scan.ts +63 -24
  228. package/extensions/lib/spill-file.ts +140 -0
  229. package/extensions/lib/subagent-handback.ts +113 -0
  230. package/extensions/lib/system-role.ts +156 -0
  231. package/extensions/lib/terminal-text.ts +114 -0
  232. package/extensions/lib/text-width.ts +47 -16
  233. package/extensions/lib/timer-ops.ts +20 -0
  234. package/extensions/lib/tool-additions.ts +149 -0
  235. package/extensions/lib/tool-call-corruption.ts +134 -0
  236. package/extensions/lib/tool-path.ts +66 -0
  237. package/extensions/lib/tool-variants.ts +69 -0
  238. package/extensions/lib/tui-render.ts +255 -27
  239. package/extensions/lib/turn-budget-layout.ts +143 -0
  240. package/extensions/lib/update-check.mjs +15 -2
  241. package/extensions/lib/usage-bus.ts +1 -1
  242. package/extensions/lib/user-denial.ts +38 -0
  243. package/extensions/lib/workspace-channel.ts +16 -0
  244. package/extensions/lib/worktree-channel.ts +31 -3
  245. package/extensions/lib/worktree-isolation.ts +40 -10
  246. package/extensions/lsp/client.ts +8 -9
  247. package/extensions/lsp/index.ts +70 -4
  248. package/extensions/lsp/keep-alive.ts +1 -1
  249. package/extensions/lsp/trust.ts +119 -0
  250. package/extensions/lsp/watcher.ts +1 -1
  251. package/extensions/mcp/announce.ts +87 -5
  252. package/extensions/mcp/client.ts +161 -48
  253. package/extensions/mcp/config.ts +132 -8
  254. package/extensions/mcp/discovery.ts +19 -0
  255. package/extensions/mcp/index.ts +209 -71
  256. package/extensions/mcp/oauth/browser.ts +38 -17
  257. package/extensions/mcp/oauth/flow.ts +25 -17
  258. package/extensions/mcp/oauth/provider.ts +14 -8
  259. package/extensions/mcp/oauth/store.ts +34 -16
  260. package/extensions/mcp/panel/keys.ts +12 -11
  261. package/extensions/mcp/panel/render.ts +9 -6
  262. package/extensions/mcp/schema.ts +104 -5
  263. package/extensions/mcp/trust.ts +151 -67
  264. package/extensions/memory/entries.ts +23 -14
  265. package/extensions/memory/index.ts +134 -28
  266. package/extensions/memory/open-external.ts +33 -18
  267. package/extensions/memory/panel.ts +135 -26
  268. package/extensions/newer-model/index.ts +31 -0
  269. package/extensions/notebook/description.ts +18 -0
  270. package/extensions/notebook/index.ts +6 -5
  271. package/extensions/notebook/notebook.ts +1 -1
  272. package/extensions/permissions/index.ts +1300 -381
  273. package/extensions/permissions/matcher.ts +425 -74
  274. package/extensions/permissions/modes.ts +6 -4
  275. package/extensions/permissions/panel/host.ts +130 -0
  276. package/extensions/permissions/panel/keys.ts +48 -0
  277. package/extensions/permissions/panel/render.ts +450 -0
  278. package/extensions/permissions/panel/state.ts +550 -0
  279. package/extensions/permissions/powershell-cmdlets.ts +198 -0
  280. package/extensions/permissions/powershell-paths.ts +197 -0
  281. package/extensions/permissions/powershell-rules.ts +207 -280
  282. package/extensions/permissions/powershell-tree.ts +557 -0
  283. package/extensions/permissions/project-trust.ts +27 -11
  284. package/extensions/permissions/protected-paths.ts +14 -2
  285. package/extensions/permissions/session-grant.ts +6 -0
  286. package/extensions/permissions/settings.ts +166 -31
  287. package/extensions/permissions/subagent-gate.ts +25 -0
  288. package/extensions/permissions/workspace.ts +78 -0
  289. package/extensions/plan-mode/index.ts +156 -69
  290. package/extensions/plan-mode/reminder.ts +89 -21
  291. package/extensions/plan-mode/texts.ts +177 -0
  292. package/extensions/plan-mode/viewer.ts +92 -27
  293. package/extensions/plugins/counts.ts +3 -3
  294. package/extensions/plugins/index.ts +61 -46
  295. package/extensions/plugins/install/install.ts +16 -0
  296. package/extensions/plugins/marketplace/sync.ts +9 -3
  297. package/extensions/plugins/marketplace/types.ts +3 -1
  298. package/extensions/plugins/panel/keys.ts +21 -24
  299. package/extensions/plugins/panel/render.ts +12 -6
  300. package/extensions/plugins/shell-expand.ts +107 -0
  301. package/extensions/plugins/template.ts +32 -15
  302. package/extensions/powershell/child.ts +7 -0
  303. package/extensions/powershell/description.ts +38 -6
  304. package/extensions/powershell/guards.ts +1 -1
  305. package/extensions/powershell/index.ts +12 -7
  306. package/extensions/recap/index.ts +65 -60
  307. package/extensions/recap/prompt.ts +2 -2
  308. package/extensions/recap/scheduler.ts +3 -5
  309. package/extensions/search-tools/grep-merge.ts +39 -0
  310. package/extensions/search-tools/index.ts +0 -0
  311. package/extensions/send-now/chord.ts +62 -0
  312. package/extensions/send-now/index.ts +133 -0
  313. package/extensions/session-title/index.ts +3 -0
  314. package/extensions/session-title/title.ts +4 -1
  315. package/extensions/skill/code-review.ts +97 -0
  316. package/extensions/skill/index.ts +421 -101
  317. package/extensions/skill/invoke.ts +128 -18
  318. package/extensions/skill/listing.ts +133 -9
  319. package/extensions/skill/panel/keys.ts +15 -16
  320. package/extensions/skill/panel/render.ts +5 -2
  321. package/extensions/skill/panel/state.ts +12 -1
  322. package/extensions/subagents/agent-args.ts +39 -0
  323. package/extensions/subagents/agent-description.ts +132 -0
  324. package/extensions/subagents/agents.ts +116 -23
  325. package/extensions/subagents/announce.ts +69 -0
  326. package/extensions/subagents/default-model.ts +2 -3
  327. package/extensions/subagents/delegation-steer.ts +4 -4
  328. package/extensions/subagents/fork-cache.ts +76 -0
  329. package/extensions/subagents/guide-agent.ts +189 -0
  330. package/extensions/subagents/hand-back-review.ts +3 -0
  331. package/extensions/subagents/index.ts +1493 -824
  332. package/extensions/subagents/live-runs.ts +26 -6
  333. package/extensions/subagents/model-select.ts +38 -25
  334. package/extensions/subagents/outcome.ts +2 -2
  335. package/extensions/subagents/panel-keys.ts +73 -31
  336. package/extensions/subagents/panel-render.ts +120 -96
  337. package/extensions/subagents/panel-widget.ts +60 -89
  338. package/extensions/subagents/runner.ts +108 -80
  339. package/extensions/subagents/runs.ts +39 -5
  340. package/extensions/subagents/send-to-main-tool.ts +1 -1
  341. package/extensions/subagents/session-turns.ts +32 -8
  342. package/extensions/subagents/shell-panel.ts +36 -178
  343. package/extensions/subagents/tasks-dialog.ts +170 -0
  344. package/extensions/subagents/viewport-mirror.ts +95 -0
  345. package/extensions/subagents/worktree.ts +57 -13
  346. package/extensions/system-prompt/environment.ts +19 -19
  347. package/extensions/system-prompt/idle-turn.ts +65 -0
  348. package/extensions/system-prompt/index.ts +131 -47
  349. package/extensions/system-prompt/template.ts +24 -50
  350. package/extensions/system-prompt/tiers/common.ts +23 -64
  351. package/extensions/system-prompt/tiers/frontier.ts +32 -11
  352. package/extensions/system-prompt/tiers/low.ts +67 -45
  353. package/extensions/system-prompt/tiers/mid.ts +96 -38
  354. package/extensions/system-reminder/index.ts +175 -13
  355. package/extensions/tasks/descriptions.ts +190 -0
  356. package/extensions/tasks/index.ts +120 -41
  357. package/extensions/tasks/store.ts +83 -16
  358. package/extensions/tool-call-corruption/child.ts +7 -0
  359. package/extensions/tool-call-corruption/index.ts +237 -0
  360. package/extensions/tool-search/announce.ts +16 -0
  361. package/extensions/tool-search/index.ts +189 -41
  362. package/extensions/tool-style/index.ts +68 -10
  363. package/extensions/tool-style/write-description.ts +40 -0
  364. package/extensions/tool-style/write-render.ts +237 -0
  365. package/extensions/turn-duration/index.ts +7 -3
  366. package/extensions/turn-duration/line.ts +47 -4
  367. package/extensions/web/backends.ts +6 -9
  368. package/extensions/web/description.ts +50 -0
  369. package/extensions/web/index.ts +118 -53
  370. package/extensions/web/native-call.ts +15 -0
  371. package/extensions/web/native-results.ts +41 -0
  372. package/extensions/web-fetch/description.ts +42 -0
  373. package/extensions/web-fetch/extract.ts +53 -6
  374. package/extensions/web-fetch/index.ts +125 -76
  375. package/extensions/web-fetch/page-content.ts +19 -0
  376. package/extensions/web-fetch/response.ts +49 -0
  377. package/extensions/web-fetch/summarize.ts +9 -10
  378. package/extensions/workflow/agent-session.ts +105 -18
  379. package/extensions/workflow/args.ts +24 -0
  380. package/extensions/workflow/description.ts +67 -0
  381. package/extensions/workflow/globals.ts +17 -3
  382. package/extensions/workflow/index.ts +145 -162
  383. package/extensions/workflow/records.ts +1 -0
  384. package/extensions/workflow/run-manager.ts +29 -6
  385. package/extensions/workflow/saved-workflows.ts +3 -2
  386. package/extensions/workflow/types.ts +22 -1
  387. package/extensions/workflow/viewer.ts +54 -24
  388. package/extensions/workflow/widget.ts +20 -0
  389. package/extensions/worktree/descriptions.ts +91 -0
  390. package/extensions/worktree/guards.ts +316 -54
  391. package/extensions/worktree/index.ts +121 -39
  392. package/extensions/worktree/powershell-guards.ts +167 -0
  393. package/extensions/worktree/rewrite.ts +14 -16
  394. package/package.json +19 -7
  395. package/skills/artifact-design/SKILL.md +85 -0
  396. package/skills/code-review/SKILL.md +20 -20
  397. package/skills/code-review/cells/arguments-and-flags.md +19 -0
  398. package/skills/code-review/cells/high-3x5-recall-verify.md +137 -0
  399. package/skills/code-review/cells/high-8-inline.md +122 -0
  400. package/skills/code-review/cells/low-1-pass-max4.md +27 -0
  401. package/skills/code-review/cells/low-1-pass-min-files-4.md +28 -0
  402. package/skills/code-review/cells/max-5x5-verify-sweep.md +162 -0
  403. package/skills/code-review/cells/medium-3x5-verify.md +132 -0
  404. package/skills/code-review/cells/minimal-prompt.md +32 -0
  405. package/skills/code-review/cells/xhigh-10-inline-sweep.md +149 -0
  406. package/skills/code-review/cells/xhigh-5x5-verify-sweep.md +162 -0
  407. package/skills/fewer-permission-prompts/SKILL.md +1 -1
  408. package/skills/loop/SKILL.md +11 -0
  409. package/skills/security-review/SKILL.md +2 -5
  410. package/skills/simplify/SKILL.md +7 -5
  411. package/skills/workflow-authoring/SKILL.md +143 -0
  412. package/themes/onecode-light.json +1 -1
  413. package/themes/onecode.json +1 -1
  414. package/types/app.d.ts +58 -0
  415. package/types/community-packages.d.ts +26 -1
  416. package/extensions/auto-mode/recoverability.ts +0 -229
  417. package/extensions/lib/capability-index.ts +0 -466
  418. package/extensions/lib/model-facts.generated.json +0 -2675
  419. package/extensions/lib/model-facts.ts +0 -162
@@ -1,86 +1,110 @@
1
1
  /**
2
- * Pure state, key decoding, and rendering for the `/btw` answer overlay — Claude
3
- * Code's side-question panel: a focused, scrollable view of the answer with the
4
- * question dim above it. `↑/↓` (and PgUp/PgDn) scroll, `c` copies the answer,
5
- * `Esc` closes.
2
+ * Pure state, key decoding, and rendering for the `/btw` panel, laid out as
3
+ * Claude Code's: the session's earlier side questions (the last five, with a
4
+ * count of older ones), the current question marked `/btw`, the answer
5
+ * indented under them, and a hint line naming only the keys that apply.
6
6
  *
7
- * Kept free of pi imports so the scroll maths and layout are unit-tested; the
8
- * extension owns the overlay, repaint, and the actual clipboard write. CC's
9
- * panel also offers `f to fork`; One Code omits it (pi exposes no primitive to
10
- * branch a session with an injected exchange) — docs/decisions/btw.md.
7
+ * Shift+←/→, `[`/`]` and Tab/Shift+Tab browse the earlier answers, ↑/↓ scroll
8
+ * (PgUp/PgDn and Home/End too), `c` copies the answer on screen, `f` forks the
9
+ * current answer into a background subagent, `x` clears the history, and Esc,
10
+ * Enter, Space or `q` close.
11
+ *
12
+ * Kept free of pi imports so the browse and scroll maths and the layout are
13
+ * unit-tested; the extension owns the overlay, the model call, the clipboard
14
+ * write and the fork request.
11
15
  */
12
16
 
13
- import { panelTopRule, safeThemePaint, truncateLine, wrapPlainText } from "../lib/tui-render.ts";
17
+ import type { BtwExchange } from "./prompt.ts";
18
+ import { keyId, keyText } from "../lib/key-input.ts";
19
+ import { panelTopRule, safeThemeBold, safeThemePaint, truncateLine, wrapPlainText } from "../lib/tui-render.ts";
14
20
 
15
21
  export const BTW_MAX_HEIGHT = 24;
16
22
 
17
- /** Key hint shown at the foot of the panel. Every key here is discoverable. */
18
- export const BTW_HINT = "↑/↓ to scroll · c to copy · Esc to close";
23
+ /** Earlier questions listed (and browsable) above the current one. */
24
+ export const SHOWN_HISTORY = 5;
19
25
 
20
- /** Most echoed question lines shown in the header, so it can't starve the body. */
21
- export const MAX_QUESTION_LINES = 4;
26
+ /** Lines one ↑/↓ press scrolls. */
27
+ const SCROLL_STEP = 3;
22
28
 
23
- /**
24
- * The panel's body state. The pure module owns the text for each phase so every
25
- * appearance (loading, error, answer) is rendered — and tested — here rather
26
- * than assembled by the extension wiring.
27
- */
28
- export type BtwBody = { kind: "loading" } | { kind: "error"; message: string } | { kind: "answer"; text: string };
29
+ /** Columns the answer is indented by, under the question list. */
30
+ const ANSWER_INDENT = 4;
29
31
 
30
- /** The text shown in the body for a given phase. */
31
- function bodyText(body: BtwBody): string {
32
- switch (body.kind) {
33
- case "loading":
34
- return "Thinking…";
35
- case "error":
36
- return `Side question failed: ${body.message}`;
37
- case "answer":
38
- return body.text || "(no answer)";
39
- }
40
- }
32
+ /** Columns the question list is indented by. */
33
+ const LIST_INDENT = 2;
34
+
35
+ /** The current question's body: its answer, a failure, or still waiting. */
36
+ export type BtwBody = { kind: "loading" } | { kind: "error"; message: string } | { kind: "answer"; text: string };
41
37
 
42
38
  export interface BtwPanelState {
43
- /** First body line shown (0 = top). */
39
+ /** First answer line shown (0 = top). */
44
40
  offset: number;
45
41
  /** Largest valid offset for the current viewport; render keeps it current. */
46
42
  maxOffset: number;
47
- /** Visible body lines in the current viewport; render keeps it current. */
43
+ /** Visible answer lines in the current viewport; render keeps it current. */
48
44
  viewport: number;
49
- /** Set for one frame after a copy so the footer can confirm it. */
45
+ /** Set for one frame after a copy so the hint can confirm it. */
50
46
  copied: boolean;
47
+ /** Why the last copy failed (no clipboard route), shown in the hint until the next key. */
48
+ copyError?: string;
49
+ /** The earlier exchange on screen (an index into the history), or null for the current question. */
50
+ selected: number | null;
51
51
  }
52
52
 
53
53
  export function initialBtwState(): BtwPanelState {
54
- return { offset: 0, maxOffset: 0, viewport: 1, copied: false };
54
+ return { offset: 0, maxOffset: 0, viewport: 1, copied: false, selected: null };
55
55
  }
56
56
 
57
- export type BtwKey = { kind: "up" | "down" | "pageUp" | "pageDown" | "top" | "bottom" | "copy" | "close" };
57
+ export type BtwKey =
58
+ | { kind: "up" | "down" | "pageUp" | "pageDown" | "top" | "bottom" | "copy" | "fork" | "clear" | "close" }
59
+ | { kind: "browse"; direction: "older" | "newer"; wrap: boolean };
58
60
 
59
61
  export function decodeBtwKey(data: string): BtwKey | undefined {
60
- switch (data) {
61
- case "\x1b[A":
62
- case "\x1bOA":
63
- case "\x10": // ctrl+p
62
+ switch (keyId(data)) {
63
+ case "up":
64
+ case "ctrl+p":
64
65
  return { kind: "up" };
65
- case "\x1b[B":
66
- case "\x1bOB":
67
- case "\x0e": // ctrl+n
66
+ case "down":
67
+ case "ctrl+n":
68
68
  return { kind: "down" };
69
- case "\x1b[5~":
69
+ case "pageUp":
70
70
  return { kind: "pageUp" };
71
- case "\x1b[6~":
71
+ case "pageDown":
72
72
  return { kind: "pageDown" };
73
- case "\x1b[H":
74
- case "\x1bOH":
73
+ case "home":
75
74
  return { kind: "top" };
76
- case "\x1b[F":
77
- case "\x1bOF":
75
+ case "end":
78
76
  return { kind: "bottom" };
77
+ case "shift+left":
78
+ return { kind: "browse", direction: "older", wrap: false };
79
+ case "shift+right":
80
+ return { kind: "browse", direction: "newer", wrap: false };
81
+ case "tab":
82
+ return { kind: "browse", direction: "older", wrap: true };
83
+ case "shift+tab":
84
+ return { kind: "browse", direction: "newer", wrap: true };
85
+ case "escape":
86
+ case "ctrl+c":
87
+ case "ctrl+d":
88
+ case "enter":
89
+ case "space":
90
+ return { kind: "close" };
91
+ default:
92
+ break;
93
+ }
94
+ switch (keyText(data)) {
95
+ case "[":
96
+ return { kind: "browse", direction: "older", wrap: false };
97
+ case "]":
98
+ return { kind: "browse", direction: "newer", wrap: false };
79
99
  case "c":
80
100
  case "C":
81
101
  return { kind: "copy" };
82
- case "\x1b":
83
- case "\x03": // ctrl+c
102
+ case "f":
103
+ case "F":
104
+ return { kind: "fork" };
105
+ case "x":
106
+ case "X":
107
+ return { kind: "clear" };
84
108
  case "q":
85
109
  return { kind: "close" };
86
110
  default:
@@ -88,7 +112,7 @@ export function decodeBtwKey(data: string): BtwKey | undefined {
88
112
  }
89
113
  }
90
114
 
91
- export type BtwEffect = { kind: "copy" } | { kind: "close" };
115
+ export type BtwEffect = { kind: "copy" } | { kind: "fork" } | { kind: "clear" } | { kind: "close" };
92
116
 
93
117
  /** Page size for PgUp/PgDn: nearly a full viewport, one line of overlap for orientation. */
94
118
  function pageStep(viewport: number): number {
@@ -96,26 +120,68 @@ function pageStep(viewport: number): number {
96
120
  }
97
121
 
98
122
  /**
99
- * Apply a key to the scroll state. Returns an effect for the extension to run
100
- * (copy, close) or undefined for a scroll (repaint only). Offsets are clamped to
101
- * `state.maxOffset`, and pages by `state.viewport` — both set by the most recent
102
- * render from the real viewport.
123
+ * Move the selection one step through the current question and the last
124
+ * SHOWN_HISTORY earlier ones (Claude Code's order: older goes up the list).
125
+ * Without `wrap` it stops at either end; with it, it cycles.
103
126
  */
104
- export function applyBtwKey(state: BtwPanelState, key: BtwKey): BtwEffect | undefined {
127
+ function browse(state: BtwPanelState, historyLength: number, direction: "older" | "newer", wrap: boolean): void {
128
+ const reachable = Math.min(historyLength, SHOWN_HISTORY);
129
+ const distance = state.selected === null ? 0 : historyLength - state.selected;
130
+ const step = direction === "older" ? 1 : -1;
131
+ const next = wrap ? (distance + step + reachable + 1) % (reachable + 1) : Math.min(Math.max(distance + step, 0), reachable);
132
+ if (next === distance) return;
133
+ state.selected = next === 0 ? null : historyLength - next;
134
+ state.offset = 0;
135
+ }
136
+
137
+ /**
138
+ * Copy an answer and report the outcome in the hint line. pi's
139
+ * `copyToClipboard` rejects when no clipboard route works (Wayland without
140
+ * `wl-copy`, X11 without `xclip`); unhandled, that rejection ends the process,
141
+ * so the reason is shown in place of the confirmation instead.
142
+ */
143
+ export function copyAnswer(copy: (text: string) => Promise<void>, text: string, state: BtwPanelState, repaint: () => void): Promise<void> {
144
+ let pending: Promise<void>;
145
+ try {
146
+ pending = Promise.resolve(copy(text));
147
+ } catch (error) {
148
+ pending = Promise.reject(error);
149
+ }
150
+ return pending.then(
151
+ () => {
152
+ state.copied = true;
153
+ state.copyError = undefined;
154
+ repaint();
155
+ },
156
+ (error: unknown) => {
157
+ const reason = error instanceof Error ? error.message : String(error);
158
+ state.copied = false;
159
+ state.copyError = `Copy failed: ${reason.split("\n")[0]}`;
160
+ repaint();
161
+ },
162
+ );
163
+ }
164
+
165
+ /**
166
+ * Apply a key. Returns an effect for the extension to run (copy, fork, clear,
167
+ * close) or undefined for a scroll or browse (repaint only). Offsets clamp to
168
+ * `state.maxOffset` and page by `state.viewport`, both set by the last render.
169
+ */
170
+ export function applyBtwKey(state: BtwPanelState, key: BtwKey, historyLength: number): BtwEffect | undefined {
105
171
  state.copied = false;
106
- const step = pageStep(state.viewport);
172
+ state.copyError = undefined;
107
173
  switch (key.kind) {
108
174
  case "up":
109
- state.offset = Math.max(0, state.offset - 1);
175
+ state.offset = Math.max(0, state.offset - SCROLL_STEP);
110
176
  return undefined;
111
177
  case "down":
112
- state.offset = Math.min(state.maxOffset, state.offset + 1);
178
+ state.offset = Math.min(state.maxOffset, state.offset + SCROLL_STEP);
113
179
  return undefined;
114
180
  case "pageUp":
115
- state.offset = Math.max(0, state.offset - step);
181
+ state.offset = Math.max(0, state.offset - pageStep(state.viewport));
116
182
  return undefined;
117
183
  case "pageDown":
118
- state.offset = Math.min(state.maxOffset, state.offset + step);
184
+ state.offset = Math.min(state.maxOffset, state.offset + pageStep(state.viewport));
119
185
  return undefined;
120
186
  case "top":
121
187
  state.offset = 0;
@@ -123,57 +189,119 @@ export function applyBtwKey(state: BtwPanelState, key: BtwKey): BtwEffect | unde
123
189
  case "bottom":
124
190
  state.offset = state.maxOffset;
125
191
  return undefined;
192
+ case "browse":
193
+ browse(state, historyLength, key.direction, key.wrap);
194
+ return undefined;
126
195
  case "copy":
127
- return { kind: "copy" };
196
+ case "fork":
197
+ case "clear":
128
198
  case "close":
129
- return { kind: "close" };
199
+ return { kind: key.kind };
130
200
  }
131
201
  }
132
202
 
133
203
  /**
134
- * Render the panel to at most `height` lines. The header (the dim question) and
135
- * footer (rule + key hint, with a scroll indicator and a copy confirmation) are
136
- * fixed; the answer scrolls within what remains. Clamps and writes back
137
- * `state.offset`/`state.maxOffset` so key handling scrolls against the real
138
- * body length. Every line is width-truncated (pi-tui crashes on an overwide
139
- * line).
204
+ * Renders an answer to lines at a width: plain wrapping by default, Markdown in
205
+ * the extension. `ref` is stable for one answer (its exchange, or the panel
206
+ * state for the current one), so a renderer can cache by it.
140
207
  */
141
- export function renderBtwPanel(
142
- input: { state: BtwPanelState; question: string; body: BtwBody; width: number; height: number },
143
- theme?: unknown,
144
- ): string[] {
145
- const { state, question, body, width, height } = input;
208
+ export type AnswerRenderer = (text: string, width: number, ref: object) => string[];
209
+
210
+ export interface BtwPanelInput {
211
+ state: BtwPanelState;
212
+ /** The session's earlier exchanges, oldest first. */
213
+ history: readonly BtwExchange[];
214
+ question: string;
215
+ body: BtwBody;
216
+ width: number;
217
+ height: number;
218
+ /** The current answer can be forked (the extension knows whether a fork can start). */
219
+ canFork?: boolean;
220
+ /** A fork request is in flight. */
221
+ forking?: boolean;
222
+ renderAnswer?: AnswerRenderer;
223
+ }
224
+
225
+ /** One question on one line, whitespace collapsed, cut to fit (Claude Code's list row). */
226
+ function questionLine(question: string, width: number): string {
227
+ return truncateLine(question.replace(/\s+/g, " ").trim(), Math.max(20, width - 7));
228
+ }
229
+
230
+ /**
231
+ * Render the panel to at most `height` lines. The answer scrolls within what
232
+ * the question list and hint leave; `state.offset`, `maxOffset` and `viewport`
233
+ * are written back so key handling scrolls against the real answer length.
234
+ * Every line is width-truncated (pi-tui crashes on an overwide line).
235
+ */
236
+ export function renderBtwPanel(input: BtwPanelInput, theme?: unknown): string[] {
237
+ const { state, history, question, body, width, height } = input;
146
238
  const paint = safeThemePaint(theme);
239
+ const bold = safeThemeBold(theme);
147
240
  const inner = Math.max(1, width);
241
+ const pad = " ".repeat(LIST_INDENT);
242
+ if (state.selected !== null && (state.selected < 0 || state.selected >= history.length)) state.selected = null;
243
+ const selected = state.selected === null ? undefined : history[state.selected];
148
244
 
149
- // Cap the echoed question so a long one (a pasted paragraph or URL) cannot
150
- // grow the header past the panel height and starve the answer of rows; a
151
- // truncated last line gets an ellipsis. The answer is what scrolls, not the
152
- // question.
153
- const questionLines = wrapPlainText(question.trim(), inner);
154
- const shownQuestion =
155
- questionLines.length > MAX_QUESTION_LINES
156
- ? [...questionLines.slice(0, MAX_QUESTION_LINES - 1), truncateLine(`${questionLines[MAX_QUESTION_LINES - 1]}…`, inner)]
157
- : questionLines;
158
- const header = [
159
- paint("accent", truncateLine("Side question", inner)),
160
- ...shownQuestion.map((line) => paint("muted", truncateLine(line, inner))),
161
- panelTopRule(paint, inner),
162
- ];
163
-
164
- const bodyAll = wrapPlainText(bodyText(body), inner);
165
- const capacity = Math.max(1, height - header.length - 2); // 2 = footer rule + hint
245
+ // On a short dock, list fewer earlier questions rather than overflow it: the
246
+ // rule, blanks, current question, one answer row and the hint always fit.
247
+ // A browsed question the trimmed list leaves out takes the list's first row
248
+ // (the count's, if that is the only one), so its answer never shows alone.
249
+ const listRows = Math.max(0, height - 7);
250
+ let shownCount = Math.min(SHOWN_HISTORY, history.length);
251
+ while (shownCount > 0 && shownCount + (history.length > shownCount ? 1 : 0) > listRows) shownCount--;
252
+ let start = history.length - shownCount;
253
+ if (state.selected !== null && state.selected < start) {
254
+ if (shownCount === 0 && listRows > 0) shownCount = 1;
255
+ start = Math.min(state.selected, history.length - shownCount);
256
+ }
257
+ const shown = history.slice(start, start + shownCount);
258
+ const hidden = history.length - shown.length;
259
+ const list: string[] = [];
260
+ if (hidden > 0 && shownCount < listRows) list.push(paint("muted", `${pad}(+${hidden} earlier /btw)`));
261
+ shown.forEach((exchange, i) => {
262
+ const text = `${pad}/btw ${questionLine(exchange.question, inner)}`;
263
+ list.push(state.selected === start + i ? bold(text) : paint("muted", text));
264
+ });
265
+ const marker = selected ? paint("muted", "/btw ") : bold(paint("warning", "/btw "));
266
+ list.push(`${pad}${marker}${paint("muted", questionLine(question, inner))}`);
267
+
268
+ const answerWidth = Math.max(1, inner - ANSWER_INDENT);
269
+ const renderAnswer = input.renderAnswer ?? wrapPlainText;
270
+ const answerLines = selected
271
+ ? renderAnswer(selected.answer, answerWidth, selected)
272
+ : body.kind === "answer"
273
+ ? renderAnswer(body.text || "(no answer)", answerWidth, state)
274
+ : body.kind === "error"
275
+ ? wrapPlainText(body.message, answerWidth).map((line) => paint("error", line))
276
+ : [paint("muted", "Answering…")];
277
+
278
+ const header = [panelTopRule(paint, inner), "", ...list, ""];
279
+ const footerRows = 2; // blank + hint
280
+ const capacity = Math.max(1, height - header.length - footerRows);
166
281
  state.viewport = capacity;
167
- state.maxOffset = Math.max(0, bodyAll.length - capacity);
282
+ state.maxOffset = Math.max(0, answerLines.length - capacity);
168
283
  state.offset = Math.min(Math.max(0, state.offset), state.maxOffset);
284
+ const indent = " ".repeat(ANSWER_INDENT);
285
+ const visible = answerLines.slice(state.offset, state.offset + capacity).map((line) => `${indent}${line}`);
169
286
 
170
- const visible = bodyAll.slice(state.offset, state.offset + capacity).map((line) => truncateLine(line, inner));
171
- // Pad a short answer so the footer sits at the panel's foot, not mid-screen.
172
- while (visible.length < capacity) visible.push("");
173
-
174
- const scrollNote = state.maxOffset > 0 ? ` (${state.offset + 1}-${Math.min(state.offset + capacity, bodyAll.length)} of ${bodyAll.length})` : "";
175
- const hint = state.copied ? "Copied to clipboard" : `${BTW_HINT}${scrollNote}`;
176
- const footer = [panelTopRule(paint, inner), paint("muted", truncateLine(hint, inner))];
287
+ const currentAnswer = body.kind === "answer" && body.text !== "";
288
+ const hasAnswer = Boolean(selected) || currentAnswer;
289
+ let hint: string;
290
+ if (input.forking) {
291
+ hint = paint("muted", "Forking…");
292
+ } else {
293
+ const parts: string[] = [];
294
+ if (history.length > 0) parts.push(paint("muted", "⇧←/→ to browse"));
295
+ else if (body.kind !== "loading") parts.push(paint("muted", "↑/↓ to scroll"));
296
+ if (hasAnswer) {
297
+ if (state.copyError) parts.push(paint("error", state.copyError));
298
+ else parts.push(state.copied ? paint("success", "Copied to clipboard") : paint("muted", "c to copy"));
299
+ }
300
+ if (input.canFork && !selected && currentAnswer) parts.push(paint("muted", "f to fork"));
301
+ if (history.length > 0) parts.push(paint("muted", "x to clear history"));
302
+ parts.push(paint("muted", "Esc to close"));
303
+ hint = parts.join(paint("muted", " · "));
304
+ }
177
305
 
178
- return [...header, ...visible, ...footer];
306
+ return [...header, ...visible, "", `${pad}${hint}`].map((line) => truncateLine(line, inner));
179
307
  }
@@ -6,16 +6,19 @@
6
6
  * answering model as a separate, tool-less instance, prepended to the user's
7
7
  * question as the final user message.
8
8
  *
9
- * Kept free of pi imports so the message assembly and text extraction are
9
+ * Kept free of pi imports (pi-ai types only) so the message assembly is
10
10
  * unit-tested; the extension owns the model call, the spinner, and the panel.
11
11
  */
12
12
 
13
+ import type { Api, AssistantMessage, Message, Model, UserMessage } from "@earendil-works/pi-ai";
14
+
13
15
  /**
14
16
  * CC's verbatim side-question reminder (captures/btw.json message 20). It frames
15
17
  * the answering instance as a separate, lightweight, tool-less agent so the
16
- * model answers in one shot from context instead of trying to act. One Code
17
- * backs this framing for real: it sends name-only tool stubs (never live tools)
18
- * and does not persist the exchange, so there genuinely is no follow-up turn.
18
+ * model answers in one shot from context instead of trying to act. Like Claude
19
+ * Code, the replayed request still declares the session's real tools (they are
20
+ * part of the cached prefix); a tool call in the answer is never executed, only
21
+ * its text is shown, and the exchange never reaches the main conversation.
19
22
  */
20
23
  export const SIDE_QUESTION_REMINDER = `<system-reminder>This is a side question from the user. You must answer this question directly in a single response.
21
24
 
@@ -43,3 +46,37 @@ Simply answer the question with the information you have.</system-reminder>`;
43
46
  export function sideQuestionMessage(question: string): string {
44
47
  return `${SIDE_QUESTION_REMINDER}\n\n${question.trim()}`;
45
48
  }
49
+
50
+ /** One answered side question, kept for the rest of the session. */
51
+ export interface BtwExchange {
52
+ question: string;
53
+ answer: string;
54
+ }
55
+
56
+ /** The model an injected assistant message is attributed to. */
57
+ type ModelRef = Pick<Model<Api>, "api" | "provider" | "id">;
58
+
59
+ /**
60
+ * One exchange as the user/assistant pair a later request carries: the bare
61
+ * question (no reminder) and the answer, as Claude Code threads its side
62
+ * session's history into the next side question. A fork gets the same pairs.
63
+ */
64
+ export function exchangeMessages(exchange: BtwExchange, model: ModelRef, timestamp = Date.now()): Message[] {
65
+ const user: UserMessage = { role: "user", content: [{ type: "text", text: exchange.question }], timestamp };
66
+ const assistant: AssistantMessage = {
67
+ role: "assistant",
68
+ content: [{ type: "text", text: exchange.answer }],
69
+ api: model.api,
70
+ provider: model.provider,
71
+ model: model.id,
72
+ usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
73
+ stopReason: "stop",
74
+ timestamp,
75
+ };
76
+ return [user, assistant];
77
+ }
78
+
79
+ /** Every earlier exchange, oldest first, as the messages sent before a new side question. */
80
+ export function historyMessages(exchanges: readonly BtwExchange[], model: ModelRef, timestamp = Date.now()): Message[] {
81
+ return exchanges.flatMap((exchange) => exchangeMessages(exchange, model, timestamp));
82
+ }
@@ -11,7 +11,7 @@
11
11
  * It also points discovery at the catalog of skills bundled with this package
12
12
  * (`<package>/skills`) — Claude Code's self-contained built-in skills, which
13
13
  * ship inside its binary rather than on disk, so nothing else would surface
14
- * them. See docs/decisions/skills-plugins.md and docs/findings (the extraction
14
+ * them. See working-docs/decisions/skills-plugins.md and working-docs/findings (the extraction
15
15
  * process is recorded in .claude/skills/extract-cc-skills/).
16
16
  *
17
17
  * CLAUDE.md needs no handling — pi discovers it natively alongside AGENTS.md.
@@ -19,12 +19,10 @@
19
19
 
20
20
  import { existsSync } from "node:fs";
21
21
  import os from "node:os";
22
- import { join } from "node:path";
23
22
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
24
- import { claudeConfigDir } from "../lib/paths.ts";
25
- import { claudeUserDir } from "../lib/paths.ts";
23
+ import { claudeConfigDir, claudeUserDir } from "../lib/paths.ts";
26
24
 
27
- import { BUNDLED_SKILLS_DIR } from "../lib/skill-scan.ts";
25
+ import { BUNDLED_SKILLS_DIR, commandDirs, skillSourceDirs } from "../lib/skill-scan.ts";
28
26
 
29
27
  /**
30
28
  * `claudeDir` is Claude Code's config dir (honours CLAUDE_CONFIG_DIR), defaulting
@@ -38,19 +36,17 @@ export function claudeResourcePaths(
38
36
  claudeDir: string = claudeUserDir(home),
39
37
  bundledSkillsDir?: string,
40
38
  ): { skillPaths: string[]; promptPaths: string[] } {
39
+ // The folders follow the config mode (lib/skill-scan.ts, lib/config-mode.ts).
41
40
  const candidates = {
42
41
  skillPaths: [
43
- join(claudeDir, "skills"),
44
- join(home, ".agents", "skills"),
45
- join(cwd, ".claude", "skills"),
46
- join(cwd, ".agents", "skills"),
42
+ ...skillSourceDirs(cwd, home, claudeDir).map(({ dir }) => dir),
47
43
  // The bundled catalog is listed LAST so it loses a name collision:
48
44
  // pi keeps the first-loaded skill for a given name, so a user or
49
45
  // project skill of the same name wins and the bundled one is the
50
- // fallback (see docs/decisions/skills-plugins.md).
46
+ // fallback (see working-docs/decisions/skills-plugins.md).
51
47
  ...(bundledSkillsDir ? [bundledSkillsDir] : []),
52
48
  ],
53
- promptPaths: [join(claudeDir, "commands"), join(cwd, ".claude", "commands")],
49
+ promptPaths: commandDirs(cwd, home, claudeDir),
54
50
  };
55
51
  return {
56
52
  skillPaths: candidates.skillPaths.filter((p) => existsSync(p)),