lsd-pi 1.2.4 → 1.3.2

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 (252) hide show
  1. package/README.md +22 -16
  2. package/dist/app-paths.d.ts +4 -0
  3. package/dist/app-paths.js +4 -0
  4. package/dist/bedrock-auth.d.ts +4 -0
  5. package/dist/bedrock-auth.js +4 -0
  6. package/dist/bundled-extension-paths.d.ts +4 -0
  7. package/dist/bundled-extension-paths.js +4 -0
  8. package/dist/cli-theme.d.ts +2 -2
  9. package/dist/cli-theme.js +13 -14
  10. package/dist/cli.js +43 -3
  11. package/dist/codex-rotate-settings.d.ts +4 -0
  12. package/dist/codex-rotate-settings.js +4 -0
  13. package/dist/help-text.d.ts +4 -0
  14. package/dist/help-text.js +4 -0
  15. package/dist/lsd-brand.d.ts +4 -0
  16. package/dist/lsd-brand.js +4 -0
  17. package/dist/onboarding-llm.d.ts +5 -0
  18. package/dist/onboarding-llm.js +5 -0
  19. package/dist/project-sessions.d.ts +4 -0
  20. package/dist/project-sessions.js +4 -0
  21. package/dist/resources/agents/generic.md +1 -0
  22. package/dist/resources/agents/scout.md +8 -1
  23. package/dist/resources/agents/worker.md +1 -0
  24. package/dist/resources/extensions/ask-user-questions.js +70 -0
  25. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +6 -16
  26. package/dist/resources/extensions/mac-tools/index.js +19 -34
  27. package/dist/resources/extensions/memory/index.js +20 -2
  28. package/dist/resources/extensions/shared/interview-ui.js +103 -20
  29. package/dist/resources/extensions/slash-commands/plan.js +18 -17
  30. package/dist/resources/extensions/slash-commands/tools.js +40 -4
  31. package/dist/resources/extensions/subagent/agent-switcher-component.js +208 -0
  32. package/dist/resources/extensions/subagent/agent-switcher-model.js +107 -0
  33. package/dist/resources/extensions/subagent/background-job-manager.js +11 -6
  34. package/dist/resources/extensions/subagent/background-runner.js +4 -0
  35. package/dist/resources/extensions/subagent/index.js +714 -21
  36. package/dist/resources/extensions/subagent/launch-helpers.js +19 -5
  37. package/dist/shared-paths.d.ts +4 -0
  38. package/dist/shared-paths.js +4 -0
  39. package/dist/shared-preferences.d.ts +4 -0
  40. package/dist/shared-preferences.js +4 -0
  41. package/dist/startup-model-validation.d.ts +1 -1
  42. package/dist/startup-timings.d.ts +4 -0
  43. package/dist/startup-timings.js +4 -0
  44. package/dist/update-check.d.ts +4 -0
  45. package/dist/update-check.js +4 -0
  46. package/dist/update-cmd.d.ts +4 -0
  47. package/dist/update-cmd.js +4 -0
  48. package/dist/welcome-screen.js +4 -4
  49. package/dist/wizard.d.ts +4 -0
  50. package/dist/wizard.js +4 -0
  51. package/package.json +1 -1
  52. package/packages/pi-agent-core/dist/agent.d.ts +9 -0
  53. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  54. package/packages/pi-agent-core/dist/agent.js +89 -5
  55. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  56. package/packages/pi-agent-core/dist/types.d.ts +13 -2
  57. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  58. package/packages/pi-agent-core/dist/types.js.map +1 -1
  59. package/packages/pi-agent-core/src/agent.ts +110 -4
  60. package/packages/pi-agent-core/src/types.ts +12 -3
  61. package/packages/pi-ai/dist/adaptive/classifier.d.ts +29 -0
  62. package/packages/pi-ai/dist/adaptive/classifier.d.ts.map +1 -0
  63. package/packages/pi-ai/dist/adaptive/classifier.js +72 -0
  64. package/packages/pi-ai/dist/adaptive/classifier.js.map +1 -0
  65. package/packages/pi-ai/dist/adaptive/classifier.test.d.ts +2 -0
  66. package/packages/pi-ai/dist/adaptive/classifier.test.d.ts.map +1 -0
  67. package/packages/pi-ai/dist/adaptive/classifier.test.js +32 -0
  68. package/packages/pi-ai/dist/adaptive/classifier.test.js.map +1 -0
  69. package/packages/pi-ai/dist/index.d.ts +1 -0
  70. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  71. package/packages/pi-ai/dist/index.js +1 -0
  72. package/packages/pi-ai/dist/index.js.map +1 -1
  73. package/packages/pi-ai/dist/providers/amazon-bedrock.js +0 -2
  74. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  75. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  76. package/packages/pi-ai/dist/providers/anthropic-shared.js +0 -2
  77. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  78. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts +1 -1
  79. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  80. package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  81. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  82. package/packages/pi-ai/dist/providers/google-gemini-cli.js +0 -4
  83. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  84. package/packages/pi-ai/dist/providers/google-vertex.js +0 -5
  85. package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
  86. package/packages/pi-ai/dist/providers/google.js +0 -5
  87. package/packages/pi-ai/dist/providers/google.js.map +1 -1
  88. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +1 -1
  89. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  90. package/packages/pi-ai/dist/providers/openai-codex-responses.js +0 -2
  91. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  92. package/packages/pi-ai/dist/providers/openai-completions.d.ts +1 -1
  93. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  94. package/packages/pi-ai/dist/providers/openai-completions.js +0 -1
  95. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  96. package/packages/pi-ai/dist/providers/openai-responses.d.ts +1 -1
  97. package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  98. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  99. package/packages/pi-ai/dist/providers/openai-shared.d.ts +0 -1
  100. package/packages/pi-ai/dist/providers/openai-shared.d.ts.map +1 -1
  101. package/packages/pi-ai/dist/providers/openai-shared.js +0 -4
  102. package/packages/pi-ai/dist/providers/openai-shared.js.map +1 -1
  103. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  104. package/packages/pi-ai/dist/providers/simple-options.js +0 -1
  105. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  106. package/packages/pi-ai/dist/types.d.ts +1 -2
  107. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  108. package/packages/pi-ai/dist/types.js.map +1 -1
  109. package/packages/pi-ai/src/adaptive/classifier.test.ts +38 -0
  110. package/packages/pi-ai/src/adaptive/classifier.ts +107 -0
  111. package/packages/pi-ai/src/index.ts +1 -0
  112. package/packages/pi-ai/src/providers/amazon-bedrock.ts +0 -2
  113. package/packages/pi-ai/src/providers/anthropic-shared.ts +0 -2
  114. package/packages/pi-ai/src/providers/azure-openai-responses.ts +1 -1
  115. package/packages/pi-ai/src/providers/google-gemini-cli.ts +0 -4
  116. package/packages/pi-ai/src/providers/google-vertex.ts +0 -5
  117. package/packages/pi-ai/src/providers/google.ts +0 -5
  118. package/packages/pi-ai/src/providers/openai-codex-responses.ts +1 -3
  119. package/packages/pi-ai/src/providers/openai-completions.ts +1 -2
  120. package/packages/pi-ai/src/providers/openai-responses.ts +1 -1
  121. package/packages/pi-ai/src/providers/openai-shared.ts +0 -3
  122. package/packages/pi-ai/src/providers/simple-options.ts +0 -1
  123. package/packages/pi-ai/src/types.ts +1 -2
  124. package/packages/pi-coding-agent/dist/cli/args.js +2 -2
  125. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  126. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +7 -2
  127. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  128. package/packages/pi-coding-agent/dist/core/agent-session.js +53 -20
  129. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  130. package/packages/pi-coding-agent/dist/core/lsp/lsp.md +3 -1
  131. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  132. package/packages/pi-coding-agent/dist/core/sdk.js +32 -6
  133. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  134. package/packages/pi-coding-agent/dist/core/sdk.test.js +37 -0
  135. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  136. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +8 -0
  137. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  138. package/packages/pi-coding-agent/dist/core/session-manager.js +4 -0
  139. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  140. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +12 -7
  141. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  142. package/packages/pi-coding-agent/dist/core/settings-manager.js +20 -2
  143. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  144. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  145. package/packages/pi-coding-agent/dist/core/skills.js +4 -1
  146. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -1
  148. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  149. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  150. package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -2
  151. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  152. package/packages/pi-coding-agent/dist/core/tools/grep.js +1 -1
  153. package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  154. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -0
  155. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/tools/index.js +2 -0
  157. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/tools/pty.d.ts +10 -1
  159. package/packages/pi-coding-agent/dist/core/tools/pty.d.ts.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/tools/pty.js +29 -3
  161. package/packages/pi-coding-agent/dist/core/tools/pty.js.map +1 -1
  162. package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js +1 -1
  163. package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js.map +1 -1
  164. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +12 -2
  166. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  167. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +7 -2
  168. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  169. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +23 -4
  170. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  171. package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  172. package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js +1 -2
  173. package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  175. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +9 -0
  176. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  178. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +53 -2
  179. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  180. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +2 -2
  181. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  182. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +10 -6
  183. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +1 -1
  185. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/modes/print-mode.js +6 -0
  188. package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  190. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +20 -0
  191. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  192. package/packages/pi-coding-agent/dist/tests/path-display.test.js +15 -0
  193. package/packages/pi-coding-agent/dist/tests/path-display.test.js.map +1 -1
  194. package/packages/pi-coding-agent/package.json +1 -1
  195. package/packages/pi-coding-agent/src/cli/args.ts +2 -2
  196. package/packages/pi-coding-agent/src/core/agent-session.ts +58 -21
  197. package/packages/pi-coding-agent/src/core/lsp/lsp.md +3 -1
  198. package/packages/pi-coding-agent/src/core/sdk.test.ts +45 -0
  199. package/packages/pi-coding-agent/src/core/sdk.ts +35 -6
  200. package/packages/pi-coding-agent/src/core/session-manager.ts +12 -0
  201. package/packages/pi-coding-agent/src/core/settings-manager.ts +32 -9
  202. package/packages/pi-coding-agent/src/core/skills.ts +4 -1
  203. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -1
  204. package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -2
  205. package/packages/pi-coding-agent/src/core/tools/grep.ts +1 -1
  206. package/packages/pi-coding-agent/src/core/tools/index.ts +3 -0
  207. package/packages/pi-coding-agent/src/core/tools/pty.ts +45 -6
  208. package/packages/pi-coding-agent/src/modes/interactive/components/embedded-terminal.ts +1 -1
  209. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -2
  210. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +31 -7
  211. package/packages/pi-coding-agent/src/modes/interactive/components/thinking-selector.ts +1 -2
  212. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +9 -0
  213. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +65 -3
  214. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +11 -7
  215. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +1 -1
  216. package/packages/pi-coding-agent/src/modes/print-mode.ts +6 -0
  217. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +29 -0
  218. package/packages/pi-coding-agent/src/tests/path-display.test.ts +17 -0
  219. package/packages/pi-tui/dist/components/loader.d.ts +5 -2
  220. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  221. package/packages/pi-tui/dist/components/loader.js +33 -3
  222. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  223. package/packages/pi-tui/src/components/loader.ts +31 -3
  224. package/packages/rpc-client/src/index.ts +1 -1
  225. package/packages/rpc-client/src/rpc-client.ts +29 -0
  226. package/packages/rpc-client/src/rpc-types.ts +1 -1
  227. package/pkg/dist/modes/interactive/theme/theme.d.ts +2 -2
  228. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  229. package/pkg/dist/modes/interactive/theme/theme.js +10 -6
  230. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  231. package/pkg/dist/modes/interactive/theme/themes.js +1 -1
  232. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  233. package/pkg/package.json +1 -1
  234. package/src/resources/agents/generic.md +1 -0
  235. package/src/resources/agents/scout.md +8 -1
  236. package/src/resources/agents/worker.md +1 -0
  237. package/src/resources/extensions/ask-user-questions.ts +88 -0
  238. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +6 -16
  239. package/src/resources/extensions/mac-tools/index.ts +19 -34
  240. package/src/resources/extensions/memory/index.ts +22 -2
  241. package/src/resources/extensions/shared/interview-ui.ts +108 -15
  242. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +61 -0
  243. package/src/resources/extensions/shared/tests/custom-ui-fallbacks.test.ts +46 -0
  244. package/src/resources/extensions/slash-commands/plan.ts +18 -19
  245. package/src/resources/extensions/slash-commands/tools.ts +43 -4
  246. package/src/resources/extensions/subagent/agent-switcher-component.ts +228 -0
  247. package/src/resources/extensions/subagent/agent-switcher-model.ts +160 -0
  248. package/src/resources/extensions/subagent/background-job-manager.ts +29 -6
  249. package/src/resources/extensions/subagent/background-runner.ts +8 -0
  250. package/src/resources/extensions/subagent/background-types.ts +4 -0
  251. package/src/resources/extensions/subagent/index.ts +834 -19
  252. package/src/resources/extensions/subagent/launch-helpers.ts +15 -4
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # LSD
2
2
 
3
- **Looks Sort of Done** — a standalone coding-agent CLI built on the Pi SDK. Use all your AI providers and all your loved features from Claude Code, Codex, and Gemini in one place.
3
+ **Looks Sort of Done** — a standalone AI coding-agent CLI built on the Pi SDK. Use all your AI providers and all your loved features from Claude Code, Codex, and Gemini in one place.
4
4
 
5
5
  ![LSD Screenshot](./lsd.png)
6
6
 
@@ -12,24 +12,28 @@ npm install -g lsd-pi@latest
12
12
 
13
13
  ## What LSD is
14
14
 
15
- LSD is a general-purpose coding agent CLI. It combines:
16
-
17
- - **Interactive TUI** inspired by Gemini CLI — including an embedded interactive terminal inside the LSD CLI that both you and the agent can use, so the agent is not blocked by commands or tools that require terminal interaction
18
- - **Memory system and permission modes** inspired by Claude Code
19
- - **Sandbox isolation** inspired by Codex
20
- - **Auto mode** — a classifier-based autonomous execution mode
21
- - **Remote questions** — relay agent prompts to Telegram, Discord, or Slack so you can respond from your phone
22
- - **Background subagents, skills, worktrees, sessions, usage tracking, and more**
23
-
24
- - **Package:** `lsd-pi`
25
- - **Binary:** `lsd`
26
- - **Alt binary:** `lsd-cli`
27
- - **Project config dir:** `.lsd/`
28
- - **User config dir:** `~/.lsd/`
15
+ LSD is a general-purpose coding agent that lives in your terminal. It combines:
16
+
17
+ - **Interactive TUI** with an embedded terminal both you and the agent can interact with CLI programs, so the agent never gets blocked by interactive commands
18
+ - **Multi-provider LLM support** Claude, GPT, Gemini, Mistral, Bedrock, Vertex AI, and more
19
+ - **Persistent memory** remembers your preferences and project context across sessions
20
+ - **Browser automation** — full Playwright integration for web testing and scraping
21
+ - **Code intelligence** — LSP-based navigation (go-to-definition, references, rename) in typed codebases
22
+ - **Auto mode** classifier-based autonomous execution for low-risk operations
23
+ - **Remote questions** — relay prompts to Telegram, Discord, or Slack so you can respond from your phone
24
+ - **Background subagents** — delegate tasks to isolated workers (scout, reviewer, planner)
25
+ - **Worktrees** — isolated git branches for parallel workstreams
26
+ - **Sessions** resumable conversation history per project directory
27
+ - **Voice input** speak your prompts (macOS native, Linux via Groq)
28
+ - **Usage tracking** token consumption and cost reporting
29
+ - **~25 bundled extensions** — memory, browser-tools, subagent, codex-rotate, search, and more
30
+ - **Sandbox isolation** — restrict filesystem writes to the project directory
31
+
32
+ **Package:** `lsd-pi` · **Binary:** `lsd` · **Project config:** `.lsd/` · **User config:** `~/.lsd/`
29
33
 
30
34
  ### Fork lineage
31
35
 
32
- LSD is a fork of **GSD 2**. The GSD-specific project workflow layer was stripped out. LSD is centered on being a general-purpose coding agent CLI — the agent shell, tools, TUI, browser tools, sessions, worktrees, and integrations remain core.
36
+ LSD is a fork of **GSD 2** with the GSD-specific project workflow layer stripped out. The agent shell, tools, TUI, browser automation, sessions, worktrees, and integrations remain core.
33
37
 
34
38
  ---
35
39
 
@@ -675,6 +679,8 @@ See [`docs/`](./docs/) for deeper details:
675
679
  - [Skills](./docs/skills.md)
676
680
  - [Custom Models](./docs/custom-models.md)
677
681
 
682
+ For contributors: [LEARNING.md](./LEARNING.md) is the developer onboarding guide.
683
+
678
684
  ---
679
685
 
680
686
  ## Development
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Central path constants for the entire app. Everything resolves off appRoot
3
+ * (defaults to ~/.lsd, overridable via LSD_HOME / GSD_HOME env vars).
4
+ */
1
5
  export declare const appRoot: string;
2
6
  export declare const agentDir: string;
3
7
  export declare const sessionsDir: string;
package/dist/app-paths.js CHANGED
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Central path constants for the entire app. Everything resolves off appRoot
3
+ * (defaults to ~/.lsd, overridable via LSD_HOME / GSD_HOME env vars).
4
+ */
1
5
  import { homedir } from 'os';
2
6
  import { join } from 'path';
3
7
  export const appRoot = process.env.LSD_HOME || process.env.GSD_HOME || join(homedir(), '.lsd');
@@ -1,3 +1,7 @@
1
+ /**
2
+ * AWS Bedrock credential handling — encodes/decodes SSO or access-key credentials
3
+ * to JSON for storage in auth.json, and hydrates AWS_* env vars at runtime.
4
+ */
1
5
  import type { AuthStorage } from '@gsd/pi-coding-agent';
2
6
  export declare const BEDROCK_PROVIDER_ID = "amazon-bedrock";
3
7
  export type BedrockCredentialInput = {
@@ -1,3 +1,7 @@
1
+ /**
2
+ * AWS Bedrock credential handling — encodes/decodes SSO or access-key credentials
3
+ * to JSON for storage in auth.json, and hydrates AWS_* env vars at runtime.
4
+ */
1
5
  export const BEDROCK_PROVIDER_ID = 'amazon-bedrock';
2
6
  export function encodeBedrockCredential(credential) {
3
7
  return JSON.stringify({ version: 1, ...credential });
@@ -1,2 +1,6 @@
1
+ /**
2
+ * Serializes/deserializes extension file paths to a delimiter-separated string
3
+ * so they can be passed via the LSD_BUNDLED_EXTENSIONS env var between loader.ts and cli.ts.
4
+ */
1
5
  export declare function serializeBundledExtensionPaths(paths: readonly string[], pathDelimiter?: ";" | ":"): string;
2
6
  export declare function parseBundledExtensionPaths(value: string | undefined, pathDelimiter?: ";" | ":"): string[];
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Serializes/deserializes extension file paths to a delimiter-separated string
3
+ * so they can be passed via the LSD_BUNDLED_EXTENSIONS env var between loader.ts and cli.ts.
4
+ */
1
5
  import { delimiter } from "node:path";
2
6
  export function serializeBundledExtensionPaths(paths, pathDelimiter = delimiter) {
3
7
  return paths.filter(Boolean).join(pathDelimiter);
@@ -3,10 +3,10 @@
3
3
  * output (welcome screen, sessions list, worktree CLI, update prompt, onboarding).
4
4
  *
5
5
  * Colors are read lazily from active theme via getResolvedThemeColors() so
6
- * that custom user themes propagate to CLI output automatically.
6
+ * that custom user themes and accent presets propagate to CLI output automatically.
7
7
  * Falls back to built-in dark-theme defaults if the theme cannot be loaded.
8
8
  */
9
- /** Returns an accent hex color from the active theme (e.g. `'#4a8cf7'`). */
9
+ /** Returns the accent hex color from the active theme (e.g. `'#4a8cf7'`). */
10
10
  export declare function accentHex(): string;
11
11
  /** Wrap text in the theme's accent color using raw ANSI 24-bit escapes. */
12
12
  export declare const accentAnsi: (s: string) => string;
package/dist/cli-theme.js CHANGED
@@ -3,27 +3,26 @@
3
3
  * output (welcome screen, sessions list, worktree CLI, update prompt, onboarding).
4
4
  *
5
5
  * Colors are read lazily from active theme via getResolvedThemeColors() so
6
- * that custom user themes propagate to CLI output automatically.
6
+ * that custom user themes and accent presets propagate to CLI output automatically.
7
7
  * Falls back to built-in dark-theme defaults if the theme cannot be loaded.
8
8
  */
9
9
  import { getResolvedThemeColors } from '@gsd/pi-coding-agent';
10
- // ── Lazy theme cache ─────────────────────────────────────────────────────────
11
- let _colors = null;
10
+ // ── Theme color resolver ──────────────────────────────────────────────────────
11
+ // Not cached — getResolvedThemeColors() reads the globalThis theme instance which
12
+ // is updated whenever initTheme() or setTheme() is called (e.g. by cli.ts before
13
+ // the welcome screen, or by InteractiveMode when the user changes the accent).
12
14
  function colors() {
13
- if (!_colors) {
14
- try {
15
- const resolved = getResolvedThemeColors();
16
- _colors = resolved ?? { accent: '#4a8cf7', borderAccent: '#4a8cf7', borderMuted: '#1e3a8a' };
17
- }
18
- catch {
19
- // Theme not yet on disk (first run) — use built-in dark defaults
20
- _colors = { accent: '#4a8cf7', borderAccent: '#4a8cf7', borderMuted: '#1e3a8a' };
21
- }
15
+ try {
16
+ const resolved = getResolvedThemeColors();
17
+ return resolved ?? { accent: '#4a8cf7', borderAccent: '#4a8cf7', borderMuted: '#1e3a8a' };
18
+ }
19
+ catch {
20
+ // Theme not yet initialised (first run) — use built-in dark defaults
21
+ return { accent: '#4a8cf7', borderAccent: '#4a8cf7', borderMuted: '#1e3a8a' };
22
22
  }
23
- return _colors;
24
23
  }
25
24
  // ── Hex accessor (for chalk.hex()) ───────────────────────────────────────────
26
- /** Returns an accent hex color from the active theme (e.g. `'#4a8cf7'`). */
25
+ /** Returns the accent hex color from the active theme (e.g. `'#4a8cf7'`). */
27
26
  export function accentHex() {
28
27
  return colors().accent ?? '#4a8cf7';
29
28
  }
package/dist/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- import { AuthStorage, DefaultResourceLoader, ModelRegistry, runPackageCommand, SettingsManager, SessionManager, createAgentSession, allBuiltInTools, InteractiveMode, resetStdinForTui, runPrintMode, runRpcMode, } from '@gsd/pi-coding-agent';
1
+ import { AuthStorage, DefaultResourceLoader, ModelRegistry, runPackageCommand, SettingsManager, SessionManager, createAgentSession, allBuiltInTools, InteractiveMode, resetStdinForTui, runPrintMode, runRpcMode, initTheme, } from '@gsd/pi-coding-agent';
2
2
  import { spawnSync } from 'node:child_process';
3
3
  import { readFileSync } from 'node:fs';
4
4
  import { join } from 'node:path';
@@ -55,6 +55,21 @@ function parseCliArgs(argv) {
55
55
  else if (arg === '--no-session') {
56
56
  flags.noSession = true;
57
57
  }
58
+ else if (arg === '--parent-session' && i + 1 < args.length) {
59
+ flags.parentSession = args[++i];
60
+ }
61
+ else if (arg === '--subagent-name' && i + 1 < args.length) {
62
+ flags.subagentName = args[++i];
63
+ }
64
+ else if (arg === '--subagent-task' && i + 1 < args.length) {
65
+ flags.subagentTask = args[++i];
66
+ }
67
+ else if (arg === '--subagent-tools' && i + 1 < args.length) {
68
+ flags.subagentTools = args[++i].split(',').filter(Boolean);
69
+ }
70
+ else if (arg === '--subagent-system-prompt-file' && i + 1 < args.length) {
71
+ flags.subagentSystemPromptFile = args[++i];
72
+ }
58
73
  else if (arg === '--model' && i + 1 < args.length) {
59
74
  flags.model = args[++i];
60
75
  }
@@ -349,9 +364,29 @@ if (!settingsManager.getCollapseChangelog()) {
349
364
  // ---------------------------------------------------------------------------
350
365
  if (isPrintMode) {
351
366
  await ensureRtkBootstrap();
367
+ const printCwd = process.cwd();
368
+ const printSessionsDir = getProjectSessionsDir(printCwd);
352
369
  const sessionManager = cliFlags.noSession
353
- ? SessionManager.inMemory()
354
- : SessionManager.create(process.cwd());
370
+ ? SessionManager.inMemory(printCwd)
371
+ : SessionManager.create(printCwd, printSessionsDir);
372
+ let subagentSystemPrompt;
373
+ if (cliFlags.subagentSystemPromptFile) {
374
+ try {
375
+ subagentSystemPrompt = readFileSync(cliFlags.subagentSystemPromptFile, 'utf-8');
376
+ }
377
+ catch {
378
+ subagentSystemPrompt = undefined;
379
+ }
380
+ }
381
+ if (!cliFlags.noSession && (cliFlags.parentSession || cliFlags.subagentName || subagentSystemPrompt || cliFlags.subagentTools?.length)) {
382
+ sessionManager.newSession({
383
+ parentSession: cliFlags.parentSession,
384
+ subagentName: cliFlags.subagentName,
385
+ subagentTask: cliFlags.subagentTask,
386
+ subagentSystemPrompt,
387
+ subagentTools: cliFlags.subagentTools,
388
+ });
389
+ }
355
390
  // Read --append-system-prompt file content (subagent writes agent system prompts to temp files)
356
391
  let appendSystemPrompt;
357
392
  if (cliFlags.appendSystemPrompt) {
@@ -587,6 +622,11 @@ if (!process.stdin.isTTY || !process.stdout.isTTY) {
587
622
  process.stderr.write('[lsd] lsd headless Auto-mode without TUI\n');
588
623
  process.exit(1);
589
624
  }
625
+ // Initialise the theme (including accent preset) before the welcome screen so
626
+ // that accentHex() returns the user's saved accent colour instead of the
627
+ // base-theme default. InteractiveMode will call initTheme() again with the
628
+ // file-watcher enabled — this early call is intentionally watcher-free.
629
+ initTheme(settingsManager.getTheme() || undefined, false, settingsManager.getThemeAccent());
590
630
  // Welcome screen — shown on every fresh interactive session before TUI takes over.
591
631
  // Skip when the first-run banner was already printed in loader.ts (prevents double banner).
592
632
  if (!process.env.GSD_FIRST_RUN_BANNER) {
@@ -1 +1,5 @@
1
+ /**
2
+ * Checks whether Codex rotation is enabled for a project, reading from
3
+ * project settings, global settings, or preferences YAML (in that priority order).
4
+ */
1
5
  export declare function isCodexRotateEnabled(basePath?: string): boolean;
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Checks whether Codex rotation is enabled for a project, reading from
3
+ * project settings, global settings, or preferences YAML (in that priority order).
4
+ */
1
5
  import { existsSync, readFileSync } from 'node:fs';
2
6
  import { join } from 'node:path';
3
7
  import { agentDir } from './app-paths.js';
@@ -1,2 +1,6 @@
1
+ /**
2
+ * Help text for every `lsd` subcommand. Rendered by the CLI when the user
3
+ * passes --help or an unknown subcommand.
4
+ */
1
5
  export declare function printHelp(version: string): void;
2
6
  export declare function printSubcommandHelp(subcommand: string, version: string): boolean;
package/dist/help-text.js CHANGED
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Help text for every `lsd` subcommand. Rendered by the CLI when the user
3
+ * passes --help or an unknown subcommand.
4
+ */
1
5
  const SUBCOMMAND_HELP = {
2
6
  config: [
3
7
  'Usage: lsd config',
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Brand color constants (yellow/blue/pink) and chalk helpers for consistent
3
+ * terminal theming across the CLI.
4
+ */
1
5
  export declare const LSD_YELLOW = "#facc15";
2
6
  export declare const LSD_BLUE = "#3b82f6";
3
7
  export declare const LSD_PINK = "#ec4899";
package/dist/lsd-brand.js CHANGED
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Brand color constants (yellow/blue/pink) and chalk helpers for consistent
3
+ * terminal theming across the CLI.
4
+ */
1
5
  import chalk from 'chalk';
2
6
  export const LSD_YELLOW = '#facc15';
3
7
  export const LSD_BLUE = '#3b82f6';
@@ -1,3 +1,8 @@
1
+ /**
2
+ * LLM provider registry and onboarding wizard helpers — lists available providers,
3
+ * presents picker options for browser vs API-key auth flows, and decides whether
4
+ * the first-run onboarding should trigger.
5
+ */
1
6
  import type { AuthStorage } from '@gsd/pi-coding-agent';
2
7
  export { BEDROCK_PROVIDER_ID } from './bedrock-auth.js';
3
8
  export type LlmProviderOption = {
@@ -1,3 +1,8 @@
1
+ /**
2
+ * LLM provider registry and onboarding wizard helpers — lists available providers,
3
+ * presents picker options for browser vs API-key auth flows, and decides whether
4
+ * the first-run onboarding should trigger.
5
+ */
1
6
  import { BEDROCK_PROVIDER_ID } from './bedrock-auth.js';
2
7
  export { BEDROCK_PROVIDER_ID } from './bedrock-auth.js';
3
8
  export const LLM_PROVIDER_IDS = [
@@ -1 +1,5 @@
1
+ /**
2
+ * Encodes a project directory path into a safe directory name for per-project
3
+ * session storage under ~/.lsd/sessions/ (e.g. "/Users/alice/my-app" → "--Users-alice-my-app--").
4
+ */
1
5
  export declare function getProjectSessionsDir(cwd: string, baseSessionsDir?: string): string;
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Encodes a project directory path into a safe directory name for per-project
3
+ * session storage under ~/.lsd/sessions/ (e.g. "/Users/alice/my-app" → "--Users-alice-my-app--").
4
+ */
1
5
  import { join } from "node:path";
2
6
  import { sessionsDir as defaultSessionsDir } from "./app-paths.js";
3
7
  export function getProjectSessionsDir(cwd, baseSessionsDir = defaultSessionsDir) {
@@ -12,6 +12,7 @@ Guidelines:
12
12
  - Prefer straightforward execution over elaborate planning.
13
13
  - If the task clearly belongs to a specialist domain (for example deep codebase recon or web research), you may say so in your notes, but still complete the assigned task when possible.
14
14
  - Do **not** spawn additional subagents unless the parent task explicitly tells you to do so.
15
+ - Do **not** call `ask_user_questions`. There is no human available. Make reasonable autonomous decisions.
15
16
  - Keep your final handoff concise and actionable.
16
17
 
17
18
  Output format when finished:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: scout
3
3
  description: Fast codebase recon that returns compressed context for handoff to other agents
4
- tools: read, lsp, grep, find, ls, bash
4
+ tools: read, lsp, grep, find, ls
5
5
  model: $budget_model
6
6
  ---
7
7
 
@@ -9,6 +9,13 @@ You are a scout. Quickly investigate a codebase and return structured findings t
9
9
 
10
10
  Your output will be passed to an agent who has NOT seen the files you explored.
11
11
 
12
+ Read-only constraint (strict):
13
+ - You are a **read-only** reconnaissance agent.
14
+ - Never modify files, never run code that writes to disk, and never perform any mutating/refactoring operation.
15
+ - Allowed operations are limited to inspection and navigation.
16
+ - With LSP, use read-only actions only (e.g., symbols, definition, references, hover, diagnostics, incoming/outgoing calls). Do **not** use rename, format, or code actions that apply edits.
17
+ - Do **not** call `ask_user_questions`. There is no human available. Operate fully autonomously.
18
+
12
19
  Scope boundary:
13
20
  - Scout is for reconnaissance and mapping only.
14
21
  - Do **not** perform full code review, security audit, bug triage, ranking of issues, or final recommendations as if you were the reviewer.
@@ -8,6 +8,7 @@ You are a worker agent with full capabilities. You operate in an isolated contex
8
8
  Work autonomously to complete the assigned task. Use all available tools as needed, with one important restriction:
9
9
 
10
10
  - Do **not** spawn subagents or act as an orchestrator unless the parent task explicitly instructs you to do so.
11
+ - Do **not** call `ask_user_questions`. There is no human available. Make reasonable autonomous decisions.
11
12
  - If the task looks like GSD orchestration, planning, scouting, parallel dispatch, or review routing, stop and report that the caller should use the appropriate specialist agent instead (for example: `gsd-worker`, `gsd-scout`, `gsd-reviewer`, or the top-level orchestrator).
12
13
  - In particular, do **not** call `gsd_scout`, `subagent`, `launch_parallel_view`, or `gsd_execute_parallel` on your own initiative.
13
14
 
@@ -18,6 +18,13 @@ const OptionSchema = Type.Object({
18
18
  label: Type.String({ description: "User-facing label (1-5 words)" }),
19
19
  description: Type.String({ description: "One short sentence explaining impact/tradeoff if selected" }),
20
20
  });
21
+ const ShowWhenSchema = Type.Object({
22
+ questionId: Type.String({ description: "Earlier question id this question depends on" }),
23
+ selectedAnyOf: Type.Array(Type.String(), {
24
+ description: "Show this question only when the earlier question selection includes one of these labels",
25
+ minItems: 1,
26
+ }),
27
+ });
21
28
  const QuestionSchema = Type.Object({
22
29
  id: Type.String({ description: "Stable identifier for mapping answers (snake_case)" }),
23
30
  header: Type.String({ description: "Short header label shown in the UI (12 or fewer chars)" }),
@@ -28,6 +35,7 @@ const QuestionSchema = Type.Object({
28
35
  allowMultiple: Type.Optional(Type.Boolean({
29
36
  description: "If true, the user can select multiple options using SPACE to toggle and ENTER to confirm. No 'None of the above' option is added. Default: false.",
30
37
  })),
38
+ showWhen: Type.Optional(ShowWhenSchema),
31
39
  });
32
40
  const AskUserQuestionsParams = Type.Object({
33
41
  questions: Type.Array(QuestionSchema, {
@@ -43,6 +51,34 @@ function errorResult(message, questions = []) {
43
51
  };
44
52
  }
45
53
  /** Convert the shared RoundResult into the JSON the LLM expects. */
54
+ function selectedLabels(answer) {
55
+ if (!answer)
56
+ return [];
57
+ return answer.answers.filter((item) => typeof item === "string" && !item.startsWith("user_note:"));
58
+ }
59
+ function shouldAskQuestion(question, answers) {
60
+ if (!question.showWhen)
61
+ return true;
62
+ const controlling = answers[question.showWhen.questionId];
63
+ if (!controlling)
64
+ return false;
65
+ const selected = selectedLabels(controlling);
66
+ return selected.some((label) => question.showWhen?.selectedAnyOf.includes(label));
67
+ }
68
+ function selectedRoundLabels(answer) {
69
+ if (!answer)
70
+ return [];
71
+ return (Array.isArray(answer.selected) ? answer.selected : [answer.selected]).filter((item) => typeof item === "string" && item.length > 0);
72
+ }
73
+ function shouldRenderRoundQuestion(question, answers) {
74
+ if (!question.showWhen)
75
+ return true;
76
+ const controlling = answers[question.showWhen.questionId];
77
+ if (!controlling)
78
+ return false;
79
+ const selected = selectedRoundLabels(controlling);
80
+ return selected.some((label) => question.showWhen?.selectedAnyOf.includes(label));
81
+ }
46
82
  function formatForLLM(result) {
47
83
  const answers = {};
48
84
  for (const [id, answer] of Object.entries(result.answers)) {
@@ -71,6 +107,7 @@ export default function AskUserQuestions(pi) {
71
107
  "Keep questions to 1 when possible; never exceed 3.",
72
108
  "For single-select: each question must have 2-3 options. Put the recommended option first with '(Recommended)' suffix. Do not include an 'Other' or 'None of the above' option - the client adds one automatically.",
73
109
  "For multi-select: set allowMultiple: true. The user can pick any number of options. No 'None of the above' is added.",
110
+ "For conditional follow-ups, use showWhen.questionId and showWhen.selectedAnyOf on a later question so it only appears after the matching earlier answer.",
74
111
  ],
75
112
  parameters: AskUserQuestionsParams,
76
113
  async execute(_toolCallId, params, signal, _onUpdate, ctx) {
@@ -83,6 +120,32 @@ export default function AskUserQuestions(pi) {
83
120
  return errorResult(`Error: ask_user_questions requires non-empty options for every question (question "${q.id}" has none)`, params.questions);
84
121
  }
85
122
  }
123
+ for (let i = 0; i < params.questions.length; i++) {
124
+ const q = params.questions[i];
125
+ if (!q.showWhen)
126
+ continue;
127
+ const controllerIndex = params.questions.findIndex((candidate) => candidate.id === q.showWhen?.questionId);
128
+ if (controllerIndex < 0 || controllerIndex >= i) {
129
+ return errorResult(`Error: question "${q.id}" has invalid showWhen.questionId "${q.showWhen.questionId}" (must reference an earlier question id)`, params.questions);
130
+ }
131
+ if (!q.showWhen.selectedAnyOf || q.showWhen.selectedAnyOf.length === 0) {
132
+ return errorResult(`Error: question "${q.id}" showWhen.selectedAnyOf must include at least one option label`, params.questions);
133
+ }
134
+ const controller = params.questions[controllerIndex];
135
+ const validLabels = [
136
+ ...controller.options.map((option) => option.label),
137
+ ...(!controller.allowMultiple ? [OTHER_OPTION_LABEL] : []),
138
+ ];
139
+ const invalidLabels = q.showWhen.selectedAnyOf.filter((label) => !validLabels.includes(label));
140
+ if (invalidLabels.length > 0) {
141
+ return errorResult(`Error: question "${q.id}" showWhen.selectedAnyOf contains unknown option labels: ${invalidLabels.join(", ")}`, params.questions);
142
+ }
143
+ }
144
+ // Subagents have no human to respond — fail fast and tell the model to decide autonomously.
145
+ if (process.argv.includes('--subagent-name')) {
146
+ return errorResult("Error: ask_user_questions cannot be used inside a subagent. " +
147
+ "There is no human available. Make a reasonable autonomous decision and proceed.", params.questions);
148
+ }
86
149
  if (!ctx.hasUI) {
87
150
  return errorResult("Error: UI not available (non-interactive mode)", params.questions);
88
151
  }
@@ -94,6 +157,9 @@ export default function AskUserQuestions(pi) {
94
157
  if (!result) {
95
158
  const answers = {};
96
159
  for (const q of params.questions) {
160
+ if (!shouldAskQuestion(q, answers)) {
161
+ continue;
162
+ }
97
163
  const options = q.options.map((o) => o.label);
98
164
  if (!q.allowMultiple) {
99
165
  options.push(OTHER_OPTION_LABEL);
@@ -185,6 +251,8 @@ export default function AskUserQuestions(pi) {
185
251
  lines.push(theme.fg("dim", details.channel));
186
252
  if (details.response) {
187
253
  for (const q of questions) {
254
+ if (!shouldAskQuestion(q, details.response.answers))
255
+ continue;
188
256
  const answer = details.response.answers[q.id];
189
257
  if (!answer) {
190
258
  lines.push(`${theme.fg("accent", q.header)}: ${theme.fg("dim", "(no answer)")}`);
@@ -205,6 +273,8 @@ export default function AskUserQuestions(pi) {
205
273
  }
206
274
  const lines = [];
207
275
  for (const q of details.questions) {
276
+ if (!shouldRenderRoundQuestion(q, details.response.answers))
277
+ continue;
208
278
  const answer = details.response.answers[q.id];
209
279
  if (!answer) {
210
280
  lines.push(`${theme.fg("accent", q.header)}: ${theme.fg("dim", "(no answer)")}`);
@@ -23,22 +23,12 @@ export function registerBgShellTool(pi, state) {
23
23
  "signal (send OS signal), list (all processes with status), kill (terminate), restart (kill + relaunch), " +
24
24
  "group_status (health of a process group), highlights (significant output lines only).",
25
25
  promptGuidelines: [
26
- "Use bg_shell to start long-running processes (servers, watchers, builds) that should not block the agent.",
27
- "After starting a server, use 'wait_for_ready' to efficiently block until it's listening avoids polling loops entirely.",
28
- "Use 'digest' instead of 'output' when you just need status — it returns a structured ~30-token summary instead of ~2000 tokens of raw output.",
29
- "Use 'highlights' to see only significant output (errors, URLs, results) typically 5-15 lines instead of hundreds.",
30
- "Use 'output' only when you need raw lines for debugging — add filter:'error|warning' to narrow results.",
31
- "The 'output' action returns only new output since the last check (incremental). Repeated calls are cheap on context.",
32
- "Set type:'server' and ready_port:3000 for dev servers so readiness detection is automatic.",
33
- "Set group:'my-stack' on related processes to manage them together with 'group_status'.",
34
- "Use 'run' to execute a command on a persistent shell session and block until it completes — returns structured output + exit code. Shell state (env vars, cwd, virtualenvs) persists across runs.",
35
- "Use 'send_and_wait' for interactive CLIs: send input and wait for expected output pattern.",
36
- "Use 'env' to check the current working directory and active environment variables of a shell session — useful after cd, source, or export commands.",
37
- "Background processes are session-scoped by default: a new session reaps them unless you set persist_across_sessions:true.",
38
- "Use 'restart' to kill and relaunch with the same config — preserves restart count.",
39
- "Background processes are auto-classified (server/build/test/watcher) based on the command.",
40
- "Process crashes and errors are automatically surfaced as alerts at the start of your next turn — you don't need to poll.",
41
- "To create a persistent shell session: bg_shell start with type:'shell'. The session stays alive for interactive use with 'send', 'send_and_wait', or 'run'.",
26
+ "Use bg_shell for long-running processes (servers, watchers, builds). Set type:'server' and ready_port for dev servers.",
27
+ "Use 'digest' for status (~30 tokens), 'highlights' for key output, 'output' only for raw debugging. All are incremental.",
28
+ "Use 'run' to execute a command on a persistent shell (state persists). Use 'send_and_wait' for interactive CLIs.",
29
+ "Use 'wait_for_ready' after starting a serverblocks until the port/pattern matches.",
30
+ "Use group:'name' to manage related processes together; 'group_status' for health.",
31
+ "Crashes are auto-surfaced next turn. Use persist_across_sessions:true to survive session restarts.",
42
32
  ],
43
33
  parameters: Type.Object({
44
34
  action: StringEnum([