@butlerw/vellum 0.1.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 (446) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +411 -0
  3. package/__fixtures__/responses/code-generation.json +42 -0
  4. package/__fixtures__/responses/error-response.json +20 -0
  5. package/__fixtures__/responses/hello-world.json +32 -0
  6. package/dist/auth-6MCXESOH.js +26 -0
  7. package/dist/chunk-SECXJGWA.js +597 -0
  8. package/dist/index.js +34023 -0
  9. package/package.json +67 -0
  10. package/src/__tests__/commands.e2e.test.ts +728 -0
  11. package/src/__tests__/credentials.test.ts +713 -0
  12. package/src/__tests__/mode-e2e.test.ts +391 -0
  13. package/src/__tests__/tui-integration.test.tsx +1271 -0
  14. package/src/agents/__tests__/task-persistence.test.ts +235 -0
  15. package/src/agents/commands/delegate.ts +240 -0
  16. package/src/agents/commands/index.ts +10 -0
  17. package/src/agents/commands/resume.ts +335 -0
  18. package/src/agents/index.ts +29 -0
  19. package/src/agents/task-persistence.ts +272 -0
  20. package/src/agents/task-resumption.ts +242 -0
  21. package/src/app.tsx +4737 -0
  22. package/src/commands/__tests__/.gitkeep +1 -0
  23. package/src/commands/__tests__/agents.test.ts +606 -0
  24. package/src/commands/__tests__/auth.test.ts +626 -0
  25. package/src/commands/__tests__/autocomplete.test.ts +683 -0
  26. package/src/commands/__tests__/batch.test.ts +287 -0
  27. package/src/commands/__tests__/chain-pipe-parser.test.ts +654 -0
  28. package/src/commands/__tests__/completion.test.ts +238 -0
  29. package/src/commands/__tests__/core.test.ts +363 -0
  30. package/src/commands/__tests__/executor.test.ts +496 -0
  31. package/src/commands/__tests__/exit-codes.test.ts +220 -0
  32. package/src/commands/__tests__/init.test.ts +243 -0
  33. package/src/commands/__tests__/language.test.ts +353 -0
  34. package/src/commands/__tests__/mode-cli.test.ts +667 -0
  35. package/src/commands/__tests__/model.test.ts +277 -0
  36. package/src/commands/__tests__/parser.test.ts +493 -0
  37. package/src/commands/__tests__/performance.bench.ts +380 -0
  38. package/src/commands/__tests__/registry.test.ts +534 -0
  39. package/src/commands/__tests__/resume.test.ts +449 -0
  40. package/src/commands/__tests__/security.test.ts +845 -0
  41. package/src/commands/__tests__/stream-json.test.ts +372 -0
  42. package/src/commands/__tests__/user-commands.test.ts +597 -0
  43. package/src/commands/adapters.ts +267 -0
  44. package/src/commands/agent.ts +395 -0
  45. package/src/commands/agents/generate.ts +506 -0
  46. package/src/commands/agents/index.ts +272 -0
  47. package/src/commands/agents/show.ts +271 -0
  48. package/src/commands/agents/validate.ts +387 -0
  49. package/src/commands/auth.ts +883 -0
  50. package/src/commands/autocomplete.ts +480 -0
  51. package/src/commands/batch/command.ts +388 -0
  52. package/src/commands/batch/executor.ts +361 -0
  53. package/src/commands/batch/index.ts +12 -0
  54. package/src/commands/commit.ts +235 -0
  55. package/src/commands/completion/index.ts +371 -0
  56. package/src/commands/condense.ts +191 -0
  57. package/src/commands/config.ts +344 -0
  58. package/src/commands/context-provider.ts +173 -0
  59. package/src/commands/copy.ts +329 -0
  60. package/src/commands/core/clear.ts +38 -0
  61. package/src/commands/core/exit.ts +43 -0
  62. package/src/commands/core/help.ts +354 -0
  63. package/src/commands/core/index.ts +15 -0
  64. package/src/commands/cost.ts +179 -0
  65. package/src/commands/credentials.tsx +618 -0
  66. package/src/commands/custom-agents/__tests__/custom-agents.test.ts +709 -0
  67. package/src/commands/custom-agents/create.ts +377 -0
  68. package/src/commands/custom-agents/export.ts +135 -0
  69. package/src/commands/custom-agents/import.ts +199 -0
  70. package/src/commands/custom-agents/index.ts +372 -0
  71. package/src/commands/custom-agents/info.ts +318 -0
  72. package/src/commands/custom-agents/list.ts +267 -0
  73. package/src/commands/custom-agents/validate.ts +388 -0
  74. package/src/commands/diff-mode.ts +241 -0
  75. package/src/commands/env.ts +53 -0
  76. package/src/commands/executor.ts +579 -0
  77. package/src/commands/exit-codes.ts +202 -0
  78. package/src/commands/index.ts +701 -0
  79. package/src/commands/init/index.ts +15 -0
  80. package/src/commands/init/prompts.ts +366 -0
  81. package/src/commands/init/templates/commands-readme.md +80 -0
  82. package/src/commands/init/templates/example-command.md +79 -0
  83. package/src/commands/init/templates/example-skill.md +168 -0
  84. package/src/commands/init/templates/example-workflow.md +101 -0
  85. package/src/commands/init/templates/prompts-readme.md +52 -0
  86. package/src/commands/init/templates/rules-readme.md +63 -0
  87. package/src/commands/init/templates/skills-readme.md +83 -0
  88. package/src/commands/init/templates/workflows-readme.md +94 -0
  89. package/src/commands/init.ts +391 -0
  90. package/src/commands/install.ts +90 -0
  91. package/src/commands/language.ts +191 -0
  92. package/src/commands/loaders/.gitkeep +1 -0
  93. package/src/commands/lsp.ts +199 -0
  94. package/src/commands/markdown-commands.ts +253 -0
  95. package/src/commands/mcp.ts +588 -0
  96. package/src/commands/memory/export.ts +341 -0
  97. package/src/commands/memory/index.ts +148 -0
  98. package/src/commands/memory/list.ts +261 -0
  99. package/src/commands/memory/search.ts +346 -0
  100. package/src/commands/memory/utils.ts +15 -0
  101. package/src/commands/metrics.ts +75 -0
  102. package/src/commands/migrate/index.ts +16 -0
  103. package/src/commands/migrate/prompts.ts +477 -0
  104. package/src/commands/mode.ts +331 -0
  105. package/src/commands/model.ts +298 -0
  106. package/src/commands/onboard.ts +205 -0
  107. package/src/commands/open.ts +169 -0
  108. package/src/commands/output/stream-json.ts +373 -0
  109. package/src/commands/parser/chain-parser.ts +370 -0
  110. package/src/commands/parser/index.ts +29 -0
  111. package/src/commands/parser/pipe-parser.ts +480 -0
  112. package/src/commands/parser.ts +588 -0
  113. package/src/commands/persistence.ts +355 -0
  114. package/src/commands/progress.ts +18 -0
  115. package/src/commands/prompt/index.ts +17 -0
  116. package/src/commands/prompt/validate.ts +621 -0
  117. package/src/commands/prompt-priority.ts +401 -0
  118. package/src/commands/registry.ts +374 -0
  119. package/src/commands/sandbox/index.ts +131 -0
  120. package/src/commands/security/index.ts +21 -0
  121. package/src/commands/security/input-sanitizer.ts +168 -0
  122. package/src/commands/security/permission-checker.ts +456 -0
  123. package/src/commands/security/sensitive-data.ts +350 -0
  124. package/src/commands/session/delete.ts +38 -0
  125. package/src/commands/session/export.ts +39 -0
  126. package/src/commands/session/index.ts +26 -0
  127. package/src/commands/session/list.ts +26 -0
  128. package/src/commands/session/resume.ts +562 -0
  129. package/src/commands/session/search.ts +434 -0
  130. package/src/commands/session/show.ts +26 -0
  131. package/src/commands/settings.ts +368 -0
  132. package/src/commands/setup.ts +23 -0
  133. package/src/commands/shell/index.ts +16 -0
  134. package/src/commands/shell/setup.ts +422 -0
  135. package/src/commands/shell-init.ts +50 -0
  136. package/src/commands/shell-integration/index.ts +194 -0
  137. package/src/commands/skill.ts +1220 -0
  138. package/src/commands/spec.ts +558 -0
  139. package/src/commands/status.ts +246 -0
  140. package/src/commands/theme.ts +211 -0
  141. package/src/commands/think.ts +551 -0
  142. package/src/commands/trust.ts +211 -0
  143. package/src/commands/tutorial.ts +522 -0
  144. package/src/commands/types.ts +512 -0
  145. package/src/commands/update.ts +274 -0
  146. package/src/commands/usage.ts +213 -0
  147. package/src/commands/user-commands.ts +630 -0
  148. package/src/commands/utils.ts +142 -0
  149. package/src/commands/vim.ts +152 -0
  150. package/src/commands/workflow.ts +257 -0
  151. package/src/components/header.tsx +25 -0
  152. package/src/components/input.tsx +25 -0
  153. package/src/components/message-list.tsx +32 -0
  154. package/src/components/status-bar.tsx +23 -0
  155. package/src/index.tsx +614 -0
  156. package/src/onboarding/__tests__/tutorial.test.ts +740 -0
  157. package/src/onboarding/index.ts +69 -0
  158. package/src/onboarding/tips/index.ts +9 -0
  159. package/src/onboarding/tips/tip-engine.ts +459 -0
  160. package/src/onboarding/tutorial/index.ts +88 -0
  161. package/src/onboarding/tutorial/lessons/basics.ts +151 -0
  162. package/src/onboarding/tutorial/lessons/index.ts +151 -0
  163. package/src/onboarding/tutorial/lessons/modes.ts +230 -0
  164. package/src/onboarding/tutorial/lessons/tools.ts +172 -0
  165. package/src/onboarding/tutorial/progress-tracker.ts +350 -0
  166. package/src/onboarding/tutorial/storage.ts +249 -0
  167. package/src/onboarding/tutorial/tutorial-system.ts +462 -0
  168. package/src/onboarding/tutorial/types.ts +310 -0
  169. package/src/orchestrator-singleton.ts +129 -0
  170. package/src/shutdown.ts +33 -0
  171. package/src/test/e2e/assertions.ts +267 -0
  172. package/src/test/e2e/fixtures.ts +204 -0
  173. package/src/test/e2e/harness.ts +575 -0
  174. package/src/test/e2e/index.ts +57 -0
  175. package/src/test/e2e/types.ts +228 -0
  176. package/src/test/fixtures/__tests__/fake-response-loader.test.ts +314 -0
  177. package/src/test/fixtures/fake-response-loader.ts +314 -0
  178. package/src/test/fixtures/index.ts +20 -0
  179. package/src/tui/__tests__/mcp-panel.test.tsx +82 -0
  180. package/src/tui/__tests__/mcp-wiring.test.tsx +78 -0
  181. package/src/tui/__tests__/mode-components.test.tsx +395 -0
  182. package/src/tui/__tests__/permission-ask-flow.test.tsx +138 -0
  183. package/src/tui/__tests__/sidebar-panel-data.test.tsx +148 -0
  184. package/src/tui/__tests__/tools-panel-hotkeys.test.tsx +41 -0
  185. package/src/tui/adapters/agent-adapter.ts +1008 -0
  186. package/src/tui/adapters/index.ts +48 -0
  187. package/src/tui/adapters/message-adapter.ts +315 -0
  188. package/src/tui/adapters/persistence-bridge.ts +331 -0
  189. package/src/tui/adapters/session-adapter.ts +419 -0
  190. package/src/tui/buffered-stdout.ts +223 -0
  191. package/src/tui/components/AgentProgress.tsx +424 -0
  192. package/src/tui/components/Banner/AsciiArt.ts +160 -0
  193. package/src/tui/components/Banner/Banner.tsx +355 -0
  194. package/src/tui/components/Banner/ShimmerContext.tsx +131 -0
  195. package/src/tui/components/Banner/ShimmerText.tsx +193 -0
  196. package/src/tui/components/Banner/TypeWriterGradient.tsx +321 -0
  197. package/src/tui/components/Banner/index.ts +61 -0
  198. package/src/tui/components/Banner/useShimmer.ts +241 -0
  199. package/src/tui/components/ChatView.tsx +11 -0
  200. package/src/tui/components/Checkpoint/CheckpointDiffView.tsx +371 -0
  201. package/src/tui/components/Checkpoint/SnapshotCheckpointPanel.tsx +440 -0
  202. package/src/tui/components/Checkpoint/index.ts +19 -0
  203. package/src/tui/components/CostDisplay.tsx +226 -0
  204. package/src/tui/components/InitErrorBanner.tsx +122 -0
  205. package/src/tui/components/Input/Autocomplete.tsx +603 -0
  206. package/src/tui/components/Input/EnhancedCommandInput.tsx +471 -0
  207. package/src/tui/components/Input/HighlightedText.tsx +236 -0
  208. package/src/tui/components/Input/MentionAutocomplete.tsx +375 -0
  209. package/src/tui/components/Input/TextInput.tsx +1002 -0
  210. package/src/tui/components/Input/__tests__/Autocomplete.test.tsx +374 -0
  211. package/src/tui/components/Input/__tests__/TextInput.test.tsx +241 -0
  212. package/src/tui/components/Input/__tests__/highlight.test.ts +219 -0
  213. package/src/tui/components/Input/__tests__/slash-command-utils.test.ts +104 -0
  214. package/src/tui/components/Input/highlight.ts +362 -0
  215. package/src/tui/components/Input/index.ts +36 -0
  216. package/src/tui/components/Input/slash-command-utils.ts +135 -0
  217. package/src/tui/components/Layout.tsx +432 -0
  218. package/src/tui/components/McpPanel.tsx +137 -0
  219. package/src/tui/components/MemoryPanel.tsx +448 -0
  220. package/src/tui/components/Messages/CodeBlock.tsx +527 -0
  221. package/src/tui/components/Messages/DiffView.tsx +679 -0
  222. package/src/tui/components/Messages/ImageReference.tsx +89 -0
  223. package/src/tui/components/Messages/MarkdownBlock.tsx +228 -0
  224. package/src/tui/components/Messages/MarkdownRenderer.tsx +498 -0
  225. package/src/tui/components/Messages/MessageBubble.tsx +270 -0
  226. package/src/tui/components/Messages/MessageList.tsx +1719 -0
  227. package/src/tui/components/Messages/StreamingText.tsx +216 -0
  228. package/src/tui/components/Messages/ThinkingBlock.tsx +408 -0
  229. package/src/tui/components/Messages/ToolResultPreview.tsx +243 -0
  230. package/src/tui/components/Messages/__tests__/CodeBlock.test.tsx +296 -0
  231. package/src/tui/components/Messages/__tests__/DiffView.test.tsx +239 -0
  232. package/src/tui/components/Messages/__tests__/MarkdownRenderer.test.tsx +303 -0
  233. package/src/tui/components/Messages/__tests__/MessageBubble.test.tsx +268 -0
  234. package/src/tui/components/Messages/__tests__/MessageList.test.tsx +324 -0
  235. package/src/tui/components/Messages/__tests__/StreamingText.test.tsx +215 -0
  236. package/src/tui/components/Messages/index.ts +25 -0
  237. package/src/tui/components/ModeIndicator.tsx +177 -0
  238. package/src/tui/components/ModeSelector.tsx +216 -0
  239. package/src/tui/components/ModelSelector.tsx +339 -0
  240. package/src/tui/components/OnboardingWizard.tsx +670 -0
  241. package/src/tui/components/PhaseProgressIndicator.tsx +270 -0
  242. package/src/tui/components/RateLimitIndicator.tsx +82 -0
  243. package/src/tui/components/ScreenReaderLayout.tsx +295 -0
  244. package/src/tui/components/SettingsPanel.tsx +643 -0
  245. package/src/tui/components/Sidebar/SystemStatusPanel.tsx +284 -0
  246. package/src/tui/components/Sidebar/index.ts +9 -0
  247. package/src/tui/components/Status/ModelStatusBar.tsx +270 -0
  248. package/src/tui/components/Status/index.ts +12 -0
  249. package/src/tui/components/StatusBar/AgentModeIndicator.tsx +257 -0
  250. package/src/tui/components/StatusBar/ContextProgress.tsx +167 -0
  251. package/src/tui/components/StatusBar/FileChangesIndicator.tsx +62 -0
  252. package/src/tui/components/StatusBar/GitIndicator.tsx +89 -0
  253. package/src/tui/components/StatusBar/HeaderBar.tsx +126 -0
  254. package/src/tui/components/StatusBar/ModelIndicator.tsx +157 -0
  255. package/src/tui/components/StatusBar/PersistenceStatusIndicator.tsx +210 -0
  256. package/src/tui/components/StatusBar/ResilienceIndicator.tsx +106 -0
  257. package/src/tui/components/StatusBar/SandboxIndicator.tsx +167 -0
  258. package/src/tui/components/StatusBar/StatusBar.tsx +368 -0
  259. package/src/tui/components/StatusBar/ThinkingModeIndicator.tsx +170 -0
  260. package/src/tui/components/StatusBar/TokenBreakdown.tsx +246 -0
  261. package/src/tui/components/StatusBar/TokenCounter.tsx +135 -0
  262. package/src/tui/components/StatusBar/TrustModeIndicator.tsx +130 -0
  263. package/src/tui/components/StatusBar/WorkspaceIndicator.tsx +86 -0
  264. package/src/tui/components/StatusBar/__tests__/AgentModeIndicator.test.tsx +193 -0
  265. package/src/tui/components/StatusBar/__tests__/StatusBar.test.tsx +729 -0
  266. package/src/tui/components/StatusBar/index.ts +60 -0
  267. package/src/tui/components/TipBanner.tsx +115 -0
  268. package/src/tui/components/TodoItem.tsx +208 -0
  269. package/src/tui/components/TodoPanel.tsx +455 -0
  270. package/src/tui/components/Tools/ApprovalQueue.tsx +407 -0
  271. package/src/tui/components/Tools/OptionSelector.tsx +160 -0
  272. package/src/tui/components/Tools/PermissionDialog.tsx +286 -0
  273. package/src/tui/components/Tools/ToolParams.tsx +483 -0
  274. package/src/tui/components/Tools/ToolsPanel.tsx +178 -0
  275. package/src/tui/components/Tools/__tests__/PermissionDialog.test.tsx +510 -0
  276. package/src/tui/components/Tools/__tests__/ToolParams.test.tsx +432 -0
  277. package/src/tui/components/Tools/index.ts +21 -0
  278. package/src/tui/components/TrustPrompt.tsx +279 -0
  279. package/src/tui/components/UpdateBanner.tsx +166 -0
  280. package/src/tui/components/VimModeIndicator.tsx +112 -0
  281. package/src/tui/components/backtrack/BacktrackControls.tsx +402 -0
  282. package/src/tui/components/backtrack/index.ts +13 -0
  283. package/src/tui/components/common/AutoApprovalStatus.tsx +251 -0
  284. package/src/tui/components/common/CostWarning.tsx +294 -0
  285. package/src/tui/components/common/DynamicShortcutHints.tsx +209 -0
  286. package/src/tui/components/common/EnhancedLoadingIndicator.tsx +305 -0
  287. package/src/tui/components/common/ErrorBoundary.tsx +140 -0
  288. package/src/tui/components/common/GradientText.tsx +224 -0
  289. package/src/tui/components/common/HotkeyHelpModal.tsx +193 -0
  290. package/src/tui/components/common/HotkeyHints.tsx +70 -0
  291. package/src/tui/components/common/MaxSizedBox.tsx +354 -0
  292. package/src/tui/components/common/NewMessagesBadge.tsx +65 -0
  293. package/src/tui/components/common/ProtectedFileLegend.tsx +89 -0
  294. package/src/tui/components/common/ScrollIndicator.tsx +160 -0
  295. package/src/tui/components/common/Spinner.tsx +342 -0
  296. package/src/tui/components/common/StreamingIndicator.tsx +316 -0
  297. package/src/tui/components/common/VirtualizedList/VirtualizedList.tsx +428 -0
  298. package/src/tui/components/common/VirtualizedList/hooks/index.ts +19 -0
  299. package/src/tui/components/common/VirtualizedList/hooks/useBatchedScroll.ts +64 -0
  300. package/src/tui/components/common/VirtualizedList/hooks/useScrollAnchor.ts +290 -0
  301. package/src/tui/components/common/VirtualizedList/hooks/useVirtualization.ts +340 -0
  302. package/src/tui/components/common/VirtualizedList/index.ts +30 -0
  303. package/src/tui/components/common/VirtualizedList/types.ts +107 -0
  304. package/src/tui/components/common/__tests__/NewMessagesBadge.test.tsx +74 -0
  305. package/src/tui/components/common/__tests__/ScrollIndicator.test.tsx +193 -0
  306. package/src/tui/components/common/index.ts +110 -0
  307. package/src/tui/components/index.ts +79 -0
  308. package/src/tui/components/session/CheckpointPanel.tsx +323 -0
  309. package/src/tui/components/session/RollbackDialog.tsx +169 -0
  310. package/src/tui/components/session/SessionItem.tsx +136 -0
  311. package/src/tui/components/session/SessionListPanel.tsx +252 -0
  312. package/src/tui/components/session/SessionPicker.tsx +449 -0
  313. package/src/tui/components/session/SessionPreview.tsx +240 -0
  314. package/src/tui/components/session/__tests__/session.test.tsx +408 -0
  315. package/src/tui/components/session/index.ts +28 -0
  316. package/src/tui/components/session/types.ts +116 -0
  317. package/src/tui/components/theme/__tests__/tokens.test.ts +471 -0
  318. package/src/tui/components/theme/index.ts +227 -0
  319. package/src/tui/components/theme/tokens.ts +484 -0
  320. package/src/tui/config/defaults.ts +134 -0
  321. package/src/tui/config/index.ts +17 -0
  322. package/src/tui/context/AnimationContext.tsx +284 -0
  323. package/src/tui/context/AppContext.tsx +349 -0
  324. package/src/tui/context/BracketedPasteContext.tsx +372 -0
  325. package/src/tui/context/LspContext.tsx +192 -0
  326. package/src/tui/context/McpContext.tsx +325 -0
  327. package/src/tui/context/MessagesContext.tsx +870 -0
  328. package/src/tui/context/OverflowContext.tsx +213 -0
  329. package/src/tui/context/RateLimitContext.tsx +108 -0
  330. package/src/tui/context/ResilienceContext.tsx +275 -0
  331. package/src/tui/context/RootProvider.tsx +136 -0
  332. package/src/tui/context/ScrollContext.tsx +331 -0
  333. package/src/tui/context/ToolsContext.tsx +702 -0
  334. package/src/tui/context/__tests__/BracketedPasteContext.test.tsx +416 -0
  335. package/src/tui/context/index.ts +140 -0
  336. package/src/tui/enterprise-integration.ts +282 -0
  337. package/src/tui/hooks/__tests__/useBacktrack.test.tsx +138 -0
  338. package/src/tui/hooks/__tests__/useBracketedPaste.test.tsx +222 -0
  339. package/src/tui/hooks/__tests__/useCopyMode.test.tsx +336 -0
  340. package/src/tui/hooks/__tests__/useHotkeys.ctrl-input.test.tsx +96 -0
  341. package/src/tui/hooks/__tests__/useHotkeys.test.tsx +454 -0
  342. package/src/tui/hooks/__tests__/useInputHistory.test.tsx +660 -0
  343. package/src/tui/hooks/__tests__/useLineBuffer.test.ts +295 -0
  344. package/src/tui/hooks/__tests__/useModeController.test.ts +137 -0
  345. package/src/tui/hooks/__tests__/useModeShortcuts.test.tsx +142 -0
  346. package/src/tui/hooks/__tests__/useScrollController.test.ts +464 -0
  347. package/src/tui/hooks/__tests__/useVim.test.tsx +531 -0
  348. package/src/tui/hooks/index.ts +252 -0
  349. package/src/tui/hooks/useAgentLoop.ts +712 -0
  350. package/src/tui/hooks/useAlternateBuffer.ts +398 -0
  351. package/src/tui/hooks/useAnimatedScrollbar.ts +241 -0
  352. package/src/tui/hooks/useBacktrack.ts +443 -0
  353. package/src/tui/hooks/useBracketedPaste.ts +104 -0
  354. package/src/tui/hooks/useCollapsible.ts +240 -0
  355. package/src/tui/hooks/useCopyMode.ts +382 -0
  356. package/src/tui/hooks/useCostSummary.ts +75 -0
  357. package/src/tui/hooks/useDesktopNotification.ts +414 -0
  358. package/src/tui/hooks/useDiffMode.ts +44 -0
  359. package/src/tui/hooks/useFileChangeStats.ts +110 -0
  360. package/src/tui/hooks/useFileSuggestions.ts +284 -0
  361. package/src/tui/hooks/useFlickerDetector.ts +250 -0
  362. package/src/tui/hooks/useGitStatus.ts +200 -0
  363. package/src/tui/hooks/useHotkeys.ts +579 -0
  364. package/src/tui/hooks/useImagePaste.ts +114 -0
  365. package/src/tui/hooks/useInputHighlight.ts +145 -0
  366. package/src/tui/hooks/useInputHistory.ts +246 -0
  367. package/src/tui/hooks/useKeyboardScroll.ts +209 -0
  368. package/src/tui/hooks/useLineBuffer.ts +356 -0
  369. package/src/tui/hooks/useMentionAutocomplete.ts +235 -0
  370. package/src/tui/hooks/useModeController.ts +167 -0
  371. package/src/tui/hooks/useModeShortcuts.ts +196 -0
  372. package/src/tui/hooks/usePermissionHandler.ts +146 -0
  373. package/src/tui/hooks/usePersistence.ts +480 -0
  374. package/src/tui/hooks/usePersistenceShortcuts.ts +225 -0
  375. package/src/tui/hooks/usePlaceholderRotation.ts +143 -0
  376. package/src/tui/hooks/useProviderStatus.ts +270 -0
  377. package/src/tui/hooks/useRateLimitStatus.ts +90 -0
  378. package/src/tui/hooks/useScreenReader.ts +315 -0
  379. package/src/tui/hooks/useScrollController.ts +450 -0
  380. package/src/tui/hooks/useScrollEventBatcher.ts +185 -0
  381. package/src/tui/hooks/useSidebarPanelData.ts +115 -0
  382. package/src/tui/hooks/useSmoothScroll.ts +202 -0
  383. package/src/tui/hooks/useSnapshots.ts +300 -0
  384. package/src/tui/hooks/useStateAndRef.ts +50 -0
  385. package/src/tui/hooks/useTerminalSize.ts +206 -0
  386. package/src/tui/hooks/useToolApprovalController.ts +91 -0
  387. package/src/tui/hooks/useVim.ts +334 -0
  388. package/src/tui/hooks/useWorkspace.ts +56 -0
  389. package/src/tui/i18n/__tests__/init.test.ts +278 -0
  390. package/src/tui/i18n/__tests__/language-config.test.ts +199 -0
  391. package/src/tui/i18n/__tests__/locale-detection.test.ts +250 -0
  392. package/src/tui/i18n/__tests__/settings-integration.test.ts +262 -0
  393. package/src/tui/i18n/index.ts +72 -0
  394. package/src/tui/i18n/init.ts +131 -0
  395. package/src/tui/i18n/language-config.ts +106 -0
  396. package/src/tui/i18n/locale-detection.ts +173 -0
  397. package/src/tui/i18n/settings-integration.ts +557 -0
  398. package/src/tui/i18n/tui-namespace.ts +538 -0
  399. package/src/tui/i18n/types.ts +312 -0
  400. package/src/tui/index.ts +43 -0
  401. package/src/tui/lsp-integration.ts +409 -0
  402. package/src/tui/metrics-integration.ts +366 -0
  403. package/src/tui/plugins.ts +383 -0
  404. package/src/tui/resilience.ts +342 -0
  405. package/src/tui/sandbox-integration.ts +317 -0
  406. package/src/tui/services/clipboard.ts +348 -0
  407. package/src/tui/services/fuzzy-search.ts +441 -0
  408. package/src/tui/services/index.ts +72 -0
  409. package/src/tui/services/markdown-renderer.ts +565 -0
  410. package/src/tui/services/open-external.ts +247 -0
  411. package/src/tui/services/syntax-highlighter.ts +483 -0
  412. package/src/tui/slash-commands.ts +12 -0
  413. package/src/tui/theme/index.ts +15 -0
  414. package/src/tui/theme/provider.tsx +206 -0
  415. package/src/tui/tip-integration.ts +300 -0
  416. package/src/tui/types/__tests__/ink-extended.test.ts +121 -0
  417. package/src/tui/types/ink-extended.ts +87 -0
  418. package/src/tui/utils/__tests__/bracketedPaste.test.ts +231 -0
  419. package/src/tui/utils/__tests__/heightEstimator.test.ts +157 -0
  420. package/src/tui/utils/__tests__/text-width.test.ts +158 -0
  421. package/src/tui/utils/__tests__/textSanitizer.test.ts +266 -0
  422. package/src/tui/utils/__tests__/ui-sizing.test.ts +169 -0
  423. package/src/tui/utils/bracketedPaste.ts +107 -0
  424. package/src/tui/utils/cursor-manager.ts +131 -0
  425. package/src/tui/utils/detectTerminal.ts +596 -0
  426. package/src/tui/utils/findLastSafeSplitPoint.ts +92 -0
  427. package/src/tui/utils/heightEstimator.ts +198 -0
  428. package/src/tui/utils/index.ts +91 -0
  429. package/src/tui/utils/isNarrowWidth.ts +52 -0
  430. package/src/tui/utils/stdoutGuard.ts +90 -0
  431. package/src/tui/utils/synchronized-update.ts +70 -0
  432. package/src/tui/utils/text-width.ts +225 -0
  433. package/src/tui/utils/textSanitizer.ts +225 -0
  434. package/src/tui/utils/textUtils.ts +114 -0
  435. package/src/tui/utils/ui-sizing.ts +192 -0
  436. package/src/tui-blessed/app.ts +160 -0
  437. package/src/tui-blessed/index.ts +2 -0
  438. package/src/tui-blessed/neo-blessed.d.ts +6 -0
  439. package/src/tui-blessed/test.ts +21 -0
  440. package/src/tui-blessed/types.ts +14 -0
  441. package/src/utils/icons.ts +130 -0
  442. package/src/utils/index.ts +33 -0
  443. package/src/utils/resume-hint.ts +86 -0
  444. package/src/version.ts +1 -0
  445. package/tsconfig.json +8 -0
  446. package/vitest.config.ts +35 -0
package/src/index.tsx ADDED
@@ -0,0 +1,614 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ AgentLoop,
4
+ APPROVAL_POLICIES,
5
+ type ApprovalPolicy,
6
+ BUILTIN_CODING_MODES,
7
+ CODING_MODES,
8
+ type CodingMode,
9
+ OnboardingWizard as CoreOnboardingWizard,
10
+ createAgentFactory,
11
+ LLM,
12
+ normalizeMode,
13
+ SANDBOX_POLICIES,
14
+ type SandboxPolicy,
15
+ UnifiedToolContainer,
16
+ } from "@vellum/core";
17
+ import { ProviderRegistry } from "@vellum/provider";
18
+ import { createId } from "@vellum/shared";
19
+ import { Command } from "commander";
20
+ import { render } from "ink";
21
+ import { registerDelegateCommand } from "./agents/commands/index.js";
22
+ import { App } from "./app.js";
23
+ import { handleAgentsGenerate } from "./commands/agents/generate.js";
24
+ import { handleAgentsShow } from "./commands/agents/show.js";
25
+ import { handleAgentsValidate } from "./commands/agents/validate.js";
26
+ import {
27
+ renderCredentialsAdd,
28
+ renderCredentialsList,
29
+ renderCredentialsRemove,
30
+ } from "./commands/credentials.js";
31
+ import { executeInit } from "./commands/init.js";
32
+ import { createLspCommand } from "./commands/lsp.js";
33
+ import {
34
+ handleSkillCreate,
35
+ handleSkillList,
36
+ handleSkillShow,
37
+ handleSkillValidate,
38
+ } from "./commands/skill.js";
39
+ import { getEffectiveThinkingConfig } from "./commands/think.js";
40
+ import type { CommandResult } from "./commands/types.js";
41
+ import { getOrCreateOrchestrator } from "./orchestrator-singleton.js";
42
+ import { executeShutdownCleanup, getShutdownCleanup, setShutdownCleanup } from "./shutdown.js";
43
+ import { BufferedStdout, createCompatStdout, setActiveStdout } from "./tui/buffered-stdout.js";
44
+ import { initI18n } from "./tui/i18n/index.js";
45
+
46
+ import {
47
+ getAlternateBufferSetting,
48
+ getDefaultAlternateBufferEnabled,
49
+ } from "./tui/i18n/settings-integration.js";
50
+ import { isConptyTerminal } from "./tui/utils/detectTerminal.js";
51
+ import { version } from "./version.js";
52
+
53
+ // ============================================
54
+ // Helper: Get message from CommandResult
55
+ // ============================================
56
+
57
+ /**
58
+ * Extract display message from CommandResult
59
+ */
60
+ function getResultMessage(result: CommandResult): string {
61
+ switch (result.kind) {
62
+ case "success":
63
+ return result.message ?? "";
64
+ case "error":
65
+ return result.message;
66
+ case "interactive":
67
+ return result.prompt.message;
68
+ case "pending":
69
+ return result.operation.message;
70
+ }
71
+ }
72
+ // ============================================
73
+ // T-VIRTUAL-SCROLL: Working Stdio Proxy for Ink
74
+ // ============================================
75
+
76
+ /**
77
+ * Creates working stdio proxies for Ink rendering.
78
+ *
79
+ * This fixes an issue where Ink's stdout/stderr writes can get intercepted
80
+ * or cause issues in VS Code terminal. By proxying through the original
81
+ * write functions bound to process.stdout/stderr, we ensure atomic writes.
82
+ *
83
+ * Pattern adapted from Gemini CLI's terminal handling.
84
+ */
85
+ function createWorkingStdio(): {
86
+ stdout: typeof process.stdout;
87
+ stderr: typeof process.stderr;
88
+ } {
89
+ const originalWrite = process.stdout.write.bind(process.stdout);
90
+ const originalErrWrite = process.stderr.write.bind(process.stderr);
91
+
92
+ const inkStdout = new Proxy(process.stdout, {
93
+ get(target, prop, receiver) {
94
+ if (prop === "write") return originalWrite;
95
+ const value = Reflect.get(target, prop, receiver);
96
+ return typeof value === "function" ? value.bind(target) : value;
97
+ },
98
+ });
99
+
100
+ const inkStderr = new Proxy(process.stderr, {
101
+ get(target, prop, receiver) {
102
+ if (prop === "write") return originalErrWrite;
103
+ const value = Reflect.get(target, prop, receiver);
104
+ return typeof value === "function" ? value.bind(target) : value;
105
+ },
106
+ });
107
+
108
+ return {
109
+ stdout: inkStdout as typeof process.stdout,
110
+ stderr: inkStderr as typeof process.stderr,
111
+ };
112
+ }
113
+
114
+ // ============================================
115
+ // Graceful Shutdown Setup (T030)
116
+ // ============================================
117
+
118
+ /**
119
+ * Handle process signals for graceful shutdown.
120
+ */
121
+ function setupGlobalShutdownHandlers(): void {
122
+ const signals: NodeJS.Signals[] = ["SIGINT", "SIGTERM", "SIGQUIT"];
123
+
124
+ for (const signal of signals) {
125
+ process.on(signal, () => {
126
+ console.log(`\n[CLI] Received ${signal}, shutting down gracefully...`);
127
+ executeShutdownCleanup();
128
+ // Give time for cleanup, then exit
129
+ setTimeout(() => process.exit(0), 100);
130
+ });
131
+ }
132
+ }
133
+
134
+ // Setup handlers early
135
+ setupGlobalShutdownHandlers();
136
+
137
+ // =============================================================================
138
+ // T037-T040: Mode CLI Flag Interfaces
139
+ // =============================================================================
140
+
141
+ /**
142
+ * Chat command options including mode flags.
143
+ */
144
+ export interface ChatOptions {
145
+ /** Model to use for AI responses */
146
+ model: string;
147
+ /** Provider to use (anthropic, openai, etc.) */
148
+ provider: string;
149
+ /** Language/locale for UI */
150
+ language?: string;
151
+ /** Coding mode (vibe, plan, spec) */
152
+ mode: CodingMode;
153
+ /** Approval policy override */
154
+ approval?: ApprovalPolicy;
155
+ /** Sandbox policy override */
156
+ sandbox?: SandboxPolicy;
157
+ /** Full-auto shortcut flag */
158
+ fullAuto?: boolean;
159
+ /** UI theme (dark, parchment, dracula, etc.) */
160
+ theme?: string;
161
+ /** Force banner display on startup */
162
+ banner?: boolean;
163
+ }
164
+
165
+ /**
166
+ * Parse mode flag with validation.
167
+ * Supports both new modes (vibe, plan, spec) and legacy modes (code, draft, debug, ask).
168
+ * @param value - User input value
169
+ * @returns Validated CodingMode
170
+ */
171
+ function parseMode(value: string): CodingMode {
172
+ const result = normalizeMode(value);
173
+ return result.mode;
174
+ }
175
+
176
+ /**
177
+ * Parse approval policy flag with validation.
178
+ * @param value - User input value
179
+ * @returns Validated ApprovalPolicy
180
+ */
181
+ function parseApproval(value: string): ApprovalPolicy {
182
+ const valid = APPROVAL_POLICIES as readonly string[];
183
+ if (!valid.includes(value)) {
184
+ throw new Error(`Invalid approval: ${value}. Valid options: ${valid.join(", ")}`);
185
+ }
186
+ return value as ApprovalPolicy;
187
+ }
188
+
189
+ /**
190
+ * Parse sandbox policy flag with validation.
191
+ * @param value - User input value
192
+ * @returns Validated SandboxPolicy
193
+ */
194
+ function parseSandbox(value: string): SandboxPolicy {
195
+ const valid = SANDBOX_POLICIES as readonly string[];
196
+ if (!valid.includes(value)) {
197
+ throw new Error(`Invalid sandbox: ${value}. Valid options: ${valid.join(", ")}`);
198
+ }
199
+ return value as SandboxPolicy;
200
+ }
201
+
202
+ const program = new Command();
203
+
204
+ program.name("vellum").description("Next-generation AI coding agent").version(version);
205
+
206
+ // =============================================================================
207
+ // T037-T040: Chat Command with Mode Flags
208
+ // =============================================================================
209
+
210
+ program
211
+ .command("chat", { isDefault: true })
212
+ .description("Start interactive chat session")
213
+ .option("-m, --model <model>", "Model to use", "claude-sonnet-4-20250514")
214
+ .option("-p, --provider <provider>", "Provider to use", "anthropic")
215
+ .option("-l, --language <locale>", "Language/locale to use (e.g., en, zh)")
216
+ // T037: --mode flag
217
+ .option("--mode <mode>", `Set coding mode (${CODING_MODES.join("|")})`, parseMode, "vibe")
218
+ // T038: --approval flag
219
+ .option(
220
+ "--approval <policy>",
221
+ `Set approval policy (${APPROVAL_POLICIES.join("|")})`,
222
+ parseApproval
223
+ )
224
+ // T039: --sandbox flag
225
+ .option("--sandbox <policy>", `Set sandbox policy (${SANDBOX_POLICIES.join("|")})`, parseSandbox)
226
+ // T040: --full-auto shortcut
227
+ .option("--full-auto", "Shortcut for --mode=vibe --approval=full-auto", false)
228
+ // Theme selection
229
+ .option("--theme <theme>", "UI theme (dark|parchment|dracula|etc.)", "parchment")
230
+ .option("--banner", "Show banner on startup", false)
231
+ .action(async (options: ChatOptions) => {
232
+ // T040: Apply --full-auto shortcut
233
+ let effectiveMode = options.mode;
234
+ let effectiveApproval = options.approval;
235
+
236
+ if (options.fullAuto) {
237
+ effectiveMode = "vibe";
238
+ effectiveApproval = "full-auto";
239
+ }
240
+
241
+ // Initialize i18n before rendering (T019)
242
+ initI18n({ cliLanguage: options.language });
243
+
244
+ // Load user's saved configuration from onboarding
245
+ // CLI flags override user config if explicitly provided
246
+ let effectiveProvider = options.provider;
247
+ let effectiveModel = options.model;
248
+
249
+ try {
250
+ const wizard = new CoreOnboardingWizard();
251
+ const loadResult = await wizard.loadState();
252
+ if (loadResult.ok) {
253
+ const userConfig = wizard.generateConfig();
254
+ if (userConfig.provider) {
255
+ effectiveProvider = userConfig.provider;
256
+ }
257
+ if (userConfig.model) {
258
+ effectiveModel = userConfig.model;
259
+ }
260
+ }
261
+ } catch {
262
+ // Use CLI defaults if config loading fails
263
+ }
264
+
265
+ // Create AgentLoop with real LLM provider
266
+ let agentLoop: AgentLoop | undefined;
267
+ let initError: Error | undefined;
268
+ try {
269
+ // Initialize credential manager for secure credential resolution
270
+ const { createCredentialManager } = await import("./commands/auth.js");
271
+ const credentialManager = await createCredentialManager();
272
+
273
+ // Initialize provider registry with credential manager
274
+ const providerRegistry = new ProviderRegistry({
275
+ credentialManager: credentialManager,
276
+ });
277
+ LLM.initialize(providerRegistry);
278
+
279
+ // Get mode config for the selected coding mode
280
+ const modeConfig = BUILTIN_CODING_MODES[effectiveMode];
281
+
282
+ // Initialize orchestrator singleton for task delegation
283
+ const orchestrator = getOrCreateOrchestrator();
284
+
285
+ // Create PromptBuilder with MD prompts (REQ-001: Use MD prompts)
286
+ const { promptBuilder, cleanup } = await createAgentFactory({
287
+ cwd: process.cwd(),
288
+ projectRoot: process.cwd(),
289
+ role: "base", // Load base.md for identity
290
+ mode: effectiveMode, // Load vibe.md/plan.md/spec.md
291
+ });
292
+
293
+ // Register cleanup for graceful shutdown
294
+ setShutdownCleanup(cleanup);
295
+
296
+ // Create unified tool container (T045: Single source of truth for tools)
297
+ const toolContainer = new UnifiedToolContainer({
298
+ cwd: process.cwd(),
299
+ });
300
+ toolContainer.registerBuiltins();
301
+
302
+ // Create AgentLoop with PromptBuilder and unified tool container
303
+ agentLoop = new AgentLoop({
304
+ sessionId: createId(),
305
+ mode: modeConfig,
306
+ providerType: effectiveProvider,
307
+ model: effectiveModel,
308
+ cwd: process.cwd(),
309
+ projectRoot: process.cwd(),
310
+ interactive: true,
311
+ orchestrator,
312
+ promptBuilder, // Use MD-loaded prompts
313
+ // Dynamic thinking config getter for runtime /think toggling
314
+ getThinkingConfig: getEffectiveThinkingConfig,
315
+ // T045: Wire unified tool container
316
+ tools: toolContainer.getProviderToolDefinitions(),
317
+ toolExecutor: toolContainer.getExecutor(),
318
+ // Enable AGENTS.md and Skills integration for project context
319
+ enableAgentsIntegration: true,
320
+ enableSkillsIntegration: true,
321
+ });
322
+ } catch (error) {
323
+ initError = error instanceof Error ? error : new Error(String(error));
324
+ console.error("[CLI] Failed to initialize agent:", initError.message);
325
+ // Continue without agentLoop - App will show error banner and fall back to echo mode
326
+ }
327
+
328
+ const isVSCodeTerminal =
329
+ process.env.TERM_PROGRAM === "vscode" ||
330
+ process.env.VSCODE_INJECTION === "1" ||
331
+ Boolean(process.env.VSCODE_GIT_IPC_HANDLE);
332
+ const isScreenReaderActive = Boolean(
333
+ process.env.ACCESSIBILITY === "true" || process.env.SCREEN_READER === "true"
334
+ );
335
+ // T-VIRTUAL-SCROLL: Enable debug mode for static output testing
336
+ // Set VELLUM_STATIC_OUTPUT=1 to enable non-replacing output (each update renders separately)
337
+ const isStaticOutputMode = Boolean(process.env.VELLUM_STATIC_OUTPUT === "1");
338
+
339
+ // T-VIRTUAL-SCROLL: Get working stdio proxies for Ink
340
+ // Always use proxied stdio to ensure proper write handling in VS Code terminal
341
+ const { stdout: inkStdoutProxy, stderr: inkStderr } = createWorkingStdio();
342
+
343
+ // Synchronized Output (DEC 2026): Only enable on Windows + VS Code terminal
344
+ // by reusing the existing detection in createCompatStdout().
345
+ const compatStdout = createCompatStdout();
346
+ const useBufferedStdout = compatStdout instanceof BufferedStdout;
347
+
348
+ // Set active stdout for modules that need to write outside Ink
349
+ if (useBufferedStdout) {
350
+ setActiveStdout(compatStdout);
351
+ }
352
+
353
+ // Preserve existing behavior everywhere else (proxy stdout).
354
+ const inkStdout: NodeJS.WriteStream = useBufferedStdout ? compatStdout : inkStdoutProxy;
355
+
356
+ if (useBufferedStdout) {
357
+ // Compose with existing shutdown cleanup so we don't lose agent cleanup.
358
+ const previousCleanup = getShutdownCleanup();
359
+ setShutdownCleanup(() => {
360
+ previousCleanup?.();
361
+ (compatStdout as BufferedStdout).dispose();
362
+ });
363
+ }
364
+
365
+ // Build Ink render options
366
+ // Key changes from Gemini CLI analysis:
367
+ // - Always use stdio proxy (prevents write interception issues)
368
+ // - patchConsole: false (prevent Ink from hijacking console)
369
+ // - exitOnCtrlC: false (let app handle Ctrl+C for proper cleanup)
370
+ // - incrementalRendering linked to alternateBuffer state
371
+ // - Removed maxFps: 20 (let Ink manage frame rate naturally)
372
+ const userAltBufferSetting = getAlternateBufferSetting();
373
+ const defaultAltBuffer = getDefaultAlternateBufferEnabled();
374
+ const resolvedAltBuffer = userAltBufferSetting ?? defaultAltBuffer;
375
+ const isConpty = isConptyTerminal();
376
+ const allowAlternateBuffer = !isConpty || userAltBufferSetting === true;
377
+ const useAlternateBuffer =
378
+ !isScreenReaderActive && !isStaticOutputMode && resolvedAltBuffer && allowAlternateBuffer;
379
+ const incrementalRendering = !isStaticOutputMode;
380
+ const inkRenderOptions = isVSCodeTerminal
381
+ ? {
382
+ stdout: inkStdout,
383
+ stderr: inkStderr,
384
+ stdin: process.stdin,
385
+ patchConsole: useAlternateBuffer,
386
+ exitOnCtrlC: false,
387
+ alternateBuffer: useAlternateBuffer,
388
+ incrementalRendering,
389
+ debug: isStaticOutputMode,
390
+ }
391
+ : {
392
+ stdout: inkStdout,
393
+ stderr: inkStderr,
394
+ stdin: process.stdin,
395
+ patchConsole: useAlternateBuffer,
396
+ exitOnCtrlC: false,
397
+ alternateBuffer: useAlternateBuffer,
398
+ incrementalRendering,
399
+ debug: isStaticOutputMode,
400
+ };
401
+
402
+ render(
403
+ <App
404
+ model={effectiveModel}
405
+ provider={effectiveProvider}
406
+ mode={effectiveMode}
407
+ approval={effectiveApproval}
408
+ sandbox={options.sandbox}
409
+ theme={options.theme as import("./tui/theme/index.js").ThemeName}
410
+ banner={options.banner}
411
+ agentLoop={agentLoop}
412
+ initError={initError}
413
+ />,
414
+ inkRenderOptions
415
+ );
416
+ });
417
+
418
+ program
419
+ .command("run <prompt>")
420
+ .description("Run a single prompt")
421
+ .option("-m, --model <model>", "Model to use", "claude-sonnet-4-20250514")
422
+ .action(async (prompt, options) => {
423
+ console.log(`Running: ${prompt} with model ${options.model}`);
424
+ // TODO: Implement single run
425
+ });
426
+
427
+ program
428
+ .command("config")
429
+ .description("Manage configuration")
430
+ .action(() => {
431
+ console.log("Config management coming soon");
432
+ });
433
+
434
+ // =============================================================================
435
+ // Credentials Command (T022)
436
+ // =============================================================================
437
+
438
+ const credentialsCmd = program
439
+ .command("credentials")
440
+ .description("Manage API credentials for LLM providers");
441
+
442
+ credentialsCmd
443
+ .command("list", { isDefault: true })
444
+ .description("List all stored credentials (masked values)")
445
+ .action(() => {
446
+ renderCredentialsList();
447
+ });
448
+
449
+ credentialsCmd
450
+ .command("add <provider>")
451
+ .description("Add or update credential for a provider")
452
+ .action((provider: string) => {
453
+ renderCredentialsAdd(provider);
454
+ });
455
+
456
+ credentialsCmd
457
+ .command("remove <provider>")
458
+ .alias("rm")
459
+ .description("Remove credential for a provider")
460
+ .action((provider: string) => {
461
+ renderCredentialsRemove(provider);
462
+ });
463
+
464
+ // =============================================================================
465
+ // Init Command (T039-T041)
466
+ // =============================================================================
467
+
468
+ program
469
+ .command("init")
470
+ .description("Initialize AGENTS.md for your project")
471
+ .option("-f, --force", "Overwrite existing AGENTS.md without prompting")
472
+ .option("-m, --minimal", "Skip wizard prompts, use defaults")
473
+ .action(async (options) => {
474
+ const result = await executeInit({
475
+ force: options.force,
476
+ minimal: options.minimal,
477
+ nonInteractive: false,
478
+ });
479
+ process.exit(result.exitCode);
480
+ });
481
+
482
+ // =============================================================================
483
+ // Agents Command Group (T042-T046)
484
+ // =============================================================================
485
+
486
+ const agentsCmd = program.command("agents").description("Manage AGENTS.md configuration");
487
+
488
+ agentsCmd
489
+ .command("show", { isDefault: true })
490
+ .description("Display merged AGENTS.md configuration")
491
+ .option("-j, --json", "Output as JSON")
492
+ .option("-v, --verbose", "Show all details including sources")
493
+ .option("-s, --scope <path>", "Show config for specific file/directory")
494
+ .action(async (options) => {
495
+ const result = await handleAgentsShow({
496
+ json: options.json,
497
+ verbose: options.verbose,
498
+ scope: options.scope,
499
+ });
500
+ console.log(getResultMessage(result));
501
+ process.exit(result.kind === "success" ? 0 : 1);
502
+ });
503
+
504
+ agentsCmd
505
+ .command("validate [file]")
506
+ .description("Validate AGENTS.md syntax and structure")
507
+ .option("-v, --verbose", "Show verbose output")
508
+ .option("-j, --json", "Output as JSON")
509
+ .action(async (file, options) => {
510
+ const result = await handleAgentsValidate({
511
+ file,
512
+ verbose: options.verbose,
513
+ json: options.json,
514
+ });
515
+ console.log(getResultMessage(result));
516
+ process.exit(result.kind === "success" ? 0 : 1);
517
+ });
518
+
519
+ agentsCmd
520
+ .command("generate")
521
+ .description("Generate AGENTS.md based on detected project stack")
522
+ .option("-o, --output <path>", "Output file path (default: ./AGENTS.md)")
523
+ .option("-m, --merge", "Merge with existing file")
524
+ .option("--dry-run", "Preview generated content without writing")
525
+ .action(async (options) => {
526
+ const result = await handleAgentsGenerate({
527
+ output: options.output,
528
+ merge: options.merge,
529
+ dryRun: options.dryRun,
530
+ });
531
+ console.log(getResultMessage(result));
532
+ process.exit(result.kind === "success" ? 0 : 1);
533
+ });
534
+
535
+ // =============================================================================
536
+ // Skill Command Group (T033-T037)
537
+ // =============================================================================
538
+
539
+ const skillCmd = program.command("skill").description("Manage skills for AI context");
540
+
541
+ skillCmd
542
+ .command("list", { isDefault: true })
543
+ .description("List all available skills")
544
+ .option("-s, --source <source>", "Filter by source (workspace, user, global, builtin)")
545
+ .option("-j, --json", "Output as JSON")
546
+ .option("-v, --verbose", "Show full descriptions and triggers")
547
+ .action(async (options) => {
548
+ const result = await handleSkillList({
549
+ source: options.source,
550
+ json: options.json,
551
+ verbose: options.verbose,
552
+ });
553
+ console.log(getResultMessage(result));
554
+ process.exit(result.kind === "success" ? 0 : 1);
555
+ });
556
+
557
+ skillCmd
558
+ .command("show <name>")
559
+ .description("Show details of a specific skill")
560
+ .option("-c, --content", "Show full SKILL.md content")
561
+ .option("-j, --json", "Output as JSON")
562
+ .action(async (name, options) => {
563
+ const result = await handleSkillShow(name, {
564
+ content: options.content,
565
+ json: options.json,
566
+ });
567
+ console.log(getResultMessage(result));
568
+ process.exit(result.kind === "success" ? 0 : 1);
569
+ });
570
+
571
+ skillCmd
572
+ .command("create <name>")
573
+ .description("Create a new skill from template")
574
+ .option("-l, --location <location>", "Location: workspace, user, or global")
575
+ .option("-f, --force", "Overwrite if skill already exists")
576
+ .option("-n, --non-interactive", "Non-interactive mode (use defaults)")
577
+ .action(async (name, options) => {
578
+ const result = await handleSkillCreate(name, {
579
+ location: options.location,
580
+ force: options.force,
581
+ nonInteractive: options.nonInteractive,
582
+ });
583
+ process.exit(result.exitCode);
584
+ });
585
+
586
+ skillCmd
587
+ .command("validate")
588
+ .description("Validate skill(s)")
589
+ .option("-s, --skill <name>", "Validate single skill by name")
590
+ .option("--strict", "Treat warnings as errors")
591
+ .option("-j, --json", "Output as JSON")
592
+ .action(async (options) => {
593
+ const result = await handleSkillValidate({
594
+ skill: options.skill,
595
+ strict: options.strict,
596
+ json: options.json,
597
+ });
598
+ console.log(getResultMessage(result));
599
+ process.exit(result.kind === "success" ? 0 : 1);
600
+ });
601
+
602
+ // =============================================================================
603
+ // Agent Commands (T044 - Multi-Agent Orchestration)
604
+ // =============================================================================
605
+
606
+ registerDelegateCommand(program);
607
+
608
+ // =============================================================================
609
+ // LSP Command (Phase 30)
610
+ // =============================================================================
611
+
612
+ program.addCommand(createLspCommand());
613
+
614
+ program.parse();