chad-code 1.3.1

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 (338) hide show
  1. package/AGENTS.md +27 -0
  2. package/Dockerfile +18 -0
  3. package/README.md +15 -0
  4. package/README.npm.md +64 -0
  5. package/bin/chad-code +84 -0
  6. package/bunfig.toml +7 -0
  7. package/eslint.config.js +29 -0
  8. package/package.json +107 -0
  9. package/parsers-config.ts +253 -0
  10. package/script/build.ts +167 -0
  11. package/script/postinstall.mjs +122 -0
  12. package/script/publish-registries.ts +187 -0
  13. package/script/publish.ts +93 -0
  14. package/script/schema.ts +47 -0
  15. package/src/acp/README.md +164 -0
  16. package/src/acp/agent.ts +1086 -0
  17. package/src/acp/session.ts +101 -0
  18. package/src/acp/types.ts +22 -0
  19. package/src/agent/agent.ts +253 -0
  20. package/src/agent/generate.txt +75 -0
  21. package/src/agent/prompt/compaction.txt +12 -0
  22. package/src/agent/prompt/explore.txt +18 -0
  23. package/src/agent/prompt/summary.txt +11 -0
  24. package/src/agent/prompt/title.txt +36 -0
  25. package/src/auth/index.ts +70 -0
  26. package/src/bun/index.ts +130 -0
  27. package/src/bus/bus-event.ts +43 -0
  28. package/src/bus/global.ts +10 -0
  29. package/src/bus/index.ts +105 -0
  30. package/src/cli/bootstrap.ts +17 -0
  31. package/src/cli/cmd/acp.ts +69 -0
  32. package/src/cli/cmd/agent.ts +257 -0
  33. package/src/cli/cmd/auth.ts +132 -0
  34. package/src/cli/cmd/cmd.ts +7 -0
  35. package/src/cli/cmd/debug/agent.ts +28 -0
  36. package/src/cli/cmd/debug/config.ts +15 -0
  37. package/src/cli/cmd/debug/file.ts +91 -0
  38. package/src/cli/cmd/debug/index.ts +45 -0
  39. package/src/cli/cmd/debug/lsp.ts +48 -0
  40. package/src/cli/cmd/debug/ripgrep.ts +83 -0
  41. package/src/cli/cmd/debug/scrap.ts +15 -0
  42. package/src/cli/cmd/debug/skill.ts +15 -0
  43. package/src/cli/cmd/debug/snapshot.ts +48 -0
  44. package/src/cli/cmd/export.ts +88 -0
  45. package/src/cli/cmd/generate.ts +38 -0
  46. package/src/cli/cmd/github.ts +32 -0
  47. package/src/cli/cmd/import.ts +98 -0
  48. package/src/cli/cmd/mcp.ts +670 -0
  49. package/src/cli/cmd/models.ts +42 -0
  50. package/src/cli/cmd/pr.ts +112 -0
  51. package/src/cli/cmd/run.ts +374 -0
  52. package/src/cli/cmd/serve.ts +16 -0
  53. package/src/cli/cmd/session.ts +135 -0
  54. package/src/cli/cmd/stats.ts +402 -0
  55. package/src/cli/cmd/tui/app.tsx +705 -0
  56. package/src/cli/cmd/tui/attach.ts +32 -0
  57. package/src/cli/cmd/tui/component/border.tsx +21 -0
  58. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  59. package/src/cli/cmd/tui/component/dialog-command.tsx +124 -0
  60. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  61. package/src/cli/cmd/tui/component/dialog-model.tsx +232 -0
  62. package/src/cli/cmd/tui/component/dialog-provider.tsx +228 -0
  63. package/src/cli/cmd/tui/component/dialog-session-list.tsx +115 -0
  64. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  65. package/src/cli/cmd/tui/component/dialog-stash.tsx +86 -0
  66. package/src/cli/cmd/tui/component/dialog-status.tsx +162 -0
  67. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  68. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  69. package/src/cli/cmd/tui/component/did-you-know.tsx +85 -0
  70. package/src/cli/cmd/tui/component/logo.tsx +43 -0
  71. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +654 -0
  72. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  73. package/src/cli/cmd/tui/component/prompt/index.tsx +1078 -0
  74. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  75. package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
  76. package/src/cli/cmd/tui/component/tips.ts +92 -0
  77. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  78. package/src/cli/cmd/tui/context/args.tsx +14 -0
  79. package/src/cli/cmd/tui/context/directory.ts +13 -0
  80. package/src/cli/cmd/tui/context/exit.tsx +23 -0
  81. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  82. package/src/cli/cmd/tui/context/keybind.tsx +101 -0
  83. package/src/cli/cmd/tui/context/kv.tsx +49 -0
  84. package/src/cli/cmd/tui/context/local.tsx +392 -0
  85. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  86. package/src/cli/cmd/tui/context/route.tsx +46 -0
  87. package/src/cli/cmd/tui/context/sdk.tsx +75 -0
  88. package/src/cli/cmd/tui/context/sync.tsx +384 -0
  89. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  90. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  91. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  92. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  93. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  94. package/src/cli/cmd/tui/context/theme/chad.json +245 -0
  95. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  96. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  97. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  98. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  99. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  100. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  101. package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
  102. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  103. package/src/cli/cmd/tui/context/theme/lucent-orng.json +227 -0
  104. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  105. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  106. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  107. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  108. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  109. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  110. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  111. package/src/cli/cmd/tui/context/theme/orng.json +245 -0
  112. package/src/cli/cmd/tui/context/theme/osaka-jade.json +93 -0
  113. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  114. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  115. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  116. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  117. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  118. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  119. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  120. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  121. package/src/cli/cmd/tui/context/theme.tsx +1137 -0
  122. package/src/cli/cmd/tui/event.ts +46 -0
  123. package/src/cli/cmd/tui/routes/home.tsx +138 -0
  124. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
  125. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
  126. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
  127. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  128. package/src/cli/cmd/tui/routes/session/footer.tsx +88 -0
  129. package/src/cli/cmd/tui/routes/session/header.tsx +125 -0
  130. package/src/cli/cmd/tui/routes/session/index.tsx +1814 -0
  131. package/src/cli/cmd/tui/routes/session/permission.tsx +416 -0
  132. package/src/cli/cmd/tui/routes/session/sidebar.tsx +318 -0
  133. package/src/cli/cmd/tui/spawn.ts +48 -0
  134. package/src/cli/cmd/tui/thread.ts +111 -0
  135. package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
  136. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
  137. package/src/cli/cmd/tui/ui/dialog-export-options.tsx +204 -0
  138. package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
  139. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
  140. package/src/cli/cmd/tui/ui/dialog-select.tsx +345 -0
  141. package/src/cli/cmd/tui/ui/dialog.tsx +171 -0
  142. package/src/cli/cmd/tui/ui/link.tsx +28 -0
  143. package/src/cli/cmd/tui/ui/spinner.ts +368 -0
  144. package/src/cli/cmd/tui/ui/toast.tsx +100 -0
  145. package/src/cli/cmd/tui/util/clipboard.ts +127 -0
  146. package/src/cli/cmd/tui/util/editor.ts +32 -0
  147. package/src/cli/cmd/tui/util/signal.ts +7 -0
  148. package/src/cli/cmd/tui/util/terminal.ts +114 -0
  149. package/src/cli/cmd/tui/util/transcript.ts +98 -0
  150. package/src/cli/cmd/tui/worker.ts +68 -0
  151. package/src/cli/cmd/uninstall.ts +344 -0
  152. package/src/cli/cmd/upgrade.ts +67 -0
  153. package/src/cli/cmd/web.ts +73 -0
  154. package/src/cli/error.ts +56 -0
  155. package/src/cli/network.ts +53 -0
  156. package/src/cli/ui.ts +87 -0
  157. package/src/cli/upgrade.ts +25 -0
  158. package/src/command/index.ts +131 -0
  159. package/src/command/template/initialize.txt +10 -0
  160. package/src/command/template/review.txt +97 -0
  161. package/src/config/config.ts +1124 -0
  162. package/src/config/markdown.ts +41 -0
  163. package/src/env/index.ts +26 -0
  164. package/src/file/ignore.ts +83 -0
  165. package/src/file/index.ts +411 -0
  166. package/src/file/ripgrep.ts +402 -0
  167. package/src/file/time.ts +64 -0
  168. package/src/file/watcher.ts +117 -0
  169. package/src/flag/flag.ts +52 -0
  170. package/src/format/formatter.ts +359 -0
  171. package/src/format/index.ts +137 -0
  172. package/src/global/index.ts +55 -0
  173. package/src/id/id.ts +73 -0
  174. package/src/ide/index.ts +77 -0
  175. package/src/index.ts +159 -0
  176. package/src/installation/index.ts +198 -0
  177. package/src/lsp/client.ts +252 -0
  178. package/src/lsp/index.ts +485 -0
  179. package/src/lsp/language.ts +119 -0
  180. package/src/lsp/server.ts +2023 -0
  181. package/src/mcp/auth.ts +135 -0
  182. package/src/mcp/index.ts +874 -0
  183. package/src/mcp/oauth-callback.ts +200 -0
  184. package/src/mcp/oauth-provider.ts +154 -0
  185. package/src/patch/index.ts +622 -0
  186. package/src/permission/arity.ts +163 -0
  187. package/src/permission/index.ts +210 -0
  188. package/src/permission/next.ts +268 -0
  189. package/src/plugin/index.ts +106 -0
  190. package/src/project/bootstrap.ts +31 -0
  191. package/src/project/instance.ts +78 -0
  192. package/src/project/project.ts +263 -0
  193. package/src/project/state.ts +65 -0
  194. package/src/project/vcs.ts +76 -0
  195. package/src/provider/auth.ts +143 -0
  196. package/src/provider/models-macro.ts +4 -0
  197. package/src/provider/models.ts +77 -0
  198. package/src/provider/provider.ts +516 -0
  199. package/src/provider/transform.ts +114 -0
  200. package/src/pty/index.ts +212 -0
  201. package/src/server/error.ts +36 -0
  202. package/src/server/mdns.ts +57 -0
  203. package/src/server/project.ts +79 -0
  204. package/src/server/server.ts +2866 -0
  205. package/src/server/tui.ts +71 -0
  206. package/src/session/compaction.ts +225 -0
  207. package/src/session/index.ts +469 -0
  208. package/src/session/llm.ts +213 -0
  209. package/src/session/message-v2.ts +742 -0
  210. package/src/session/message.ts +189 -0
  211. package/src/session/processor.ts +402 -0
  212. package/src/session/prompt/anthropic-20250930.txt +166 -0
  213. package/src/session/prompt/anthropic.txt +105 -0
  214. package/src/session/prompt/anthropic_spoof.txt +1 -0
  215. package/src/session/prompt/beast.txt +147 -0
  216. package/src/session/prompt/build-switch.txt +5 -0
  217. package/src/session/prompt/codex.txt +318 -0
  218. package/src/session/prompt/copilot-gpt-5.txt +143 -0
  219. package/src/session/prompt/gemini.txt +155 -0
  220. package/src/session/prompt/max-steps.txt +16 -0
  221. package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
  222. package/src/session/prompt/plan.txt +26 -0
  223. package/src/session/prompt/qwen.txt +109 -0
  224. package/src/session/prompt.ts +1621 -0
  225. package/src/session/retry.ts +90 -0
  226. package/src/session/revert.ts +108 -0
  227. package/src/session/status.ts +76 -0
  228. package/src/session/summary.ts +194 -0
  229. package/src/session/system.ts +108 -0
  230. package/src/session/todo.ts +37 -0
  231. package/src/share/share-next.ts +194 -0
  232. package/src/share/share.ts +23 -0
  233. package/src/shell/shell.ts +67 -0
  234. package/src/skill/index.ts +1 -0
  235. package/src/skill/skill.ts +124 -0
  236. package/src/snapshot/index.ts +197 -0
  237. package/src/storage/storage.ts +226 -0
  238. package/src/tool/bash.ts +262 -0
  239. package/src/tool/bash.txt +116 -0
  240. package/src/tool/batch.ts +175 -0
  241. package/src/tool/batch.txt +24 -0
  242. package/src/tool/codesearch.ts +132 -0
  243. package/src/tool/codesearch.txt +12 -0
  244. package/src/tool/edit.ts +655 -0
  245. package/src/tool/edit.txt +10 -0
  246. package/src/tool/glob.ts +75 -0
  247. package/src/tool/glob.txt +6 -0
  248. package/src/tool/grep.ts +132 -0
  249. package/src/tool/grep.txt +8 -0
  250. package/src/tool/invalid.ts +17 -0
  251. package/src/tool/ls.ts +119 -0
  252. package/src/tool/ls.txt +1 -0
  253. package/src/tool/lsp.ts +94 -0
  254. package/src/tool/lsp.txt +19 -0
  255. package/src/tool/multiedit.ts +46 -0
  256. package/src/tool/multiedit.txt +41 -0
  257. package/src/tool/patch.ts +210 -0
  258. package/src/tool/patch.txt +1 -0
  259. package/src/tool/read.ts +191 -0
  260. package/src/tool/read.txt +12 -0
  261. package/src/tool/registry.ts +137 -0
  262. package/src/tool/skill.ts +77 -0
  263. package/src/tool/task.ts +167 -0
  264. package/src/tool/task.txt +60 -0
  265. package/src/tool/todo.ts +53 -0
  266. package/src/tool/todoread.txt +14 -0
  267. package/src/tool/todowrite.txt +167 -0
  268. package/src/tool/tool.ts +73 -0
  269. package/src/tool/webfetch.ts +182 -0
  270. package/src/tool/webfetch.txt +13 -0
  271. package/src/tool/websearch.ts +144 -0
  272. package/src/tool/websearch.txt +11 -0
  273. package/src/tool/write.ts +84 -0
  274. package/src/tool/write.txt +8 -0
  275. package/src/util/archive.ts +16 -0
  276. package/src/util/color.ts +19 -0
  277. package/src/util/context.ts +25 -0
  278. package/src/util/defer.ts +12 -0
  279. package/src/util/eventloop.ts +20 -0
  280. package/src/util/filesystem.ts +83 -0
  281. package/src/util/fn.ts +11 -0
  282. package/src/util/iife.ts +3 -0
  283. package/src/util/keybind.ts +102 -0
  284. package/src/util/lazy.ts +18 -0
  285. package/src/util/locale.ts +81 -0
  286. package/src/util/lock.ts +98 -0
  287. package/src/util/log.ts +180 -0
  288. package/src/util/queue.ts +32 -0
  289. package/src/util/rpc.ts +42 -0
  290. package/src/util/scrap.ts +10 -0
  291. package/src/util/signal.ts +12 -0
  292. package/src/util/timeout.ts +14 -0
  293. package/src/util/token.ts +7 -0
  294. package/src/util/wildcard.ts +54 -0
  295. package/src/worktree/index.ts +217 -0
  296. package/sst-env.d.ts +9 -0
  297. package/test/agent/agent.test.ts +448 -0
  298. package/test/bun.test.ts +53 -0
  299. package/test/cli/github-action.test.ts +129 -0
  300. package/test/cli/github-remote.test.ts +80 -0
  301. package/test/cli/tui/transcript.test.ts +297 -0
  302. package/test/config/agent-color.test.ts +66 -0
  303. package/test/config/config.test.ts +870 -0
  304. package/test/config/markdown.test.ts +89 -0
  305. package/test/file/ignore.test.ts +10 -0
  306. package/test/file/path-traversal.test.ts +115 -0
  307. package/test/fixture/fixture.ts +45 -0
  308. package/test/fixture/lsp/fake-lsp-server.js +77 -0
  309. package/test/ide/ide.test.ts +82 -0
  310. package/test/keybind.test.ts +421 -0
  311. package/test/lsp/client.test.ts +95 -0
  312. package/test/mcp/headers.test.ts +153 -0
  313. package/test/patch/patch.test.ts +348 -0
  314. package/test/permission/arity.test.ts +33 -0
  315. package/test/permission/next.test.ts +652 -0
  316. package/test/preload.ts +63 -0
  317. package/test/project/project.test.ts +120 -0
  318. package/test/provider/amazon-bedrock.test.ts +236 -0
  319. package/test/provider/provider.test.ts +2127 -0
  320. package/test/provider/transform.test.ts +980 -0
  321. package/test/server/session-select.test.ts +78 -0
  322. package/test/session/compaction.test.ts +251 -0
  323. package/test/session/message-v2.test.ts +570 -0
  324. package/test/session/retry.test.ts +131 -0
  325. package/test/session/revert-compact.test.ts +285 -0
  326. package/test/session/session.test.ts +71 -0
  327. package/test/skill/skill.test.ts +185 -0
  328. package/test/snapshot/snapshot.test.ts +939 -0
  329. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  330. package/test/tool/bash.test.ts +232 -0
  331. package/test/tool/grep.test.ts +109 -0
  332. package/test/tool/patch.test.ts +261 -0
  333. package/test/tool/read.test.ts +167 -0
  334. package/test/util/iife.test.ts +36 -0
  335. package/test/util/lazy.test.ts +50 -0
  336. package/test/util/timeout.test.ts +21 -0
  337. package/test/util/wildcard.test.ts +55 -0
  338. package/tsconfig.json +16 -0
@@ -0,0 +1,132 @@
1
+ import { Auth } from "../../auth"
2
+ import { cmd } from "./cmd"
3
+ import * as prompts from "@clack/prompts"
4
+ import { UI } from "../ui"
5
+ import path from "path"
6
+ import os from "os"
7
+ import { Global } from "../../global"
8
+ import { Instance } from "../../project/instance"
9
+
10
+ export const AuthCommand = cmd({
11
+ command: "auth",
12
+ describe: "manage credentials",
13
+ builder: (yargs) =>
14
+ yargs.command(AuthLoginCommand).command(AuthLogoutCommand).command(AuthListCommand).demandCommand(),
15
+ async handler() {},
16
+ })
17
+
18
+ export const AuthListCommand = cmd({
19
+ command: "list",
20
+ aliases: ["ls"],
21
+ describe: "list providers",
22
+ async handler() {
23
+ UI.empty()
24
+ const authPath = path.join(Global.Path.data, "auth.json")
25
+ const homedir = os.homedir()
26
+ const displayPath = authPath.startsWith(homedir) ? authPath.replace(homedir, "~") : authPath
27
+ prompts.intro(`Credentials ${UI.Style.TEXT_DIM}${displayPath}`)
28
+ const results = Object.entries(await Auth.all())
29
+
30
+ for (const [providerID, result] of results) {
31
+ prompts.log.info(`${providerID} ${UI.Style.TEXT_DIM}${result.type}`)
32
+ }
33
+
34
+ prompts.outro(`${results.length} credentials`)
35
+
36
+ // Check for CORETHINK_API_KEY environment variable
37
+ if (process.env.CORETHINK_API_KEY) {
38
+ UI.empty()
39
+ prompts.intro("Environment")
40
+ prompts.log.info(`Chad ${UI.Style.TEXT_DIM}CORETHINK_API_KEY`)
41
+ prompts.outro("1 environment variable")
42
+ }
43
+ },
44
+ })
45
+
46
+ export const AuthLoginCommand = cmd({
47
+ command: "login [url]",
48
+ describe: "log in to Chad",
49
+ builder: (yargs) =>
50
+ yargs.positional("url", {
51
+ describe: "opencode auth provider",
52
+ type: "string",
53
+ }),
54
+ async handler(args) {
55
+ await Instance.provide({
56
+ directory: process.cwd(),
57
+ async fn() {
58
+ UI.empty()
59
+ prompts.intro("Add Chad credential")
60
+
61
+ if (args.url) {
62
+ const wellknown = await fetch(`${args.url}/.well-known/opencode`).then((x) => x.json() as any)
63
+ prompts.log.info(`Running \`${wellknown.auth.command.join(" ")}\``)
64
+ const proc = Bun.spawn({
65
+ cmd: wellknown.auth.command,
66
+ stdout: "pipe",
67
+ })
68
+ const exit = await proc.exited
69
+ if (exit !== 0) {
70
+ prompts.log.error("Failed")
71
+ prompts.outro("Done")
72
+ return
73
+ }
74
+ const token = await new Response(proc.stdout).text()
75
+ await Auth.set(args.url, {
76
+ type: "wellknown",
77
+ key: wellknown.auth.env,
78
+ token: token.trim(),
79
+ })
80
+ prompts.log.success("Logged into " + args.url)
81
+ prompts.outro("Done")
82
+ return
83
+ }
84
+
85
+ prompts.log.info("Get your Chadcode API key from the Chadcode dashboard")
86
+ prompts.log.info("API keys should start with 'sk_'")
87
+
88
+ const key = await prompts.password({
89
+ message: "Enter your Chadcode API key",
90
+ validate: (x) => {
91
+ if (!x || x.length === 0) return "Required"
92
+ if (!x.startsWith("sk_")) return "Chadcode API keys should start with 'sk_'"
93
+ return undefined
94
+ },
95
+ })
96
+ if (prompts.isCancel(key)) throw new UI.CancelledError()
97
+
98
+ await Auth.set("corethink", {
99
+ type: "api",
100
+ key,
101
+ })
102
+
103
+ prompts.log.success("Chadcode API key saved")
104
+ prompts.outro("Done")
105
+ },
106
+ })
107
+ },
108
+ })
109
+
110
+ export const AuthLogoutCommand = cmd({
111
+ command: "logout",
112
+ describe: "log out from Chad",
113
+ async handler() {
114
+ UI.empty()
115
+ const credentials = await Auth.all().then((x) => Object.entries(x))
116
+ prompts.intro("Remove credential")
117
+ if (credentials.length === 0) {
118
+ prompts.log.error("No credentials found")
119
+ return
120
+ }
121
+ const providerID = await prompts.select({
122
+ message: "Select provider",
123
+ options: credentials.map(([key, value]) => ({
124
+ label: key + UI.Style.TEXT_DIM + " (" + value.type + ")",
125
+ value: key,
126
+ })),
127
+ })
128
+ if (prompts.isCancel(providerID)) throw new UI.CancelledError()
129
+ await Auth.remove(providerID)
130
+ prompts.outro("Logout successful")
131
+ },
132
+ })
@@ -0,0 +1,7 @@
1
+ import type { CommandModule } from "yargs"
2
+
3
+ type WithDoubleDash<T> = T & { "--"?: string[] }
4
+
5
+ export function cmd<T, U>(input: CommandModule<T, WithDoubleDash<U>>) {
6
+ return input
7
+ }
@@ -0,0 +1,28 @@
1
+ import { EOL } from "os"
2
+ import { basename } from "path"
3
+ import { Agent } from "../../../agent/agent"
4
+ import { bootstrap } from "../../bootstrap"
5
+ import { cmd } from "../cmd"
6
+
7
+ export const AgentCommand = cmd({
8
+ command: "agent <name>",
9
+ builder: (yargs) =>
10
+ yargs.positional("name", {
11
+ type: "string",
12
+ demandOption: true,
13
+ description: "Agent name",
14
+ }),
15
+ async handler(args) {
16
+ await bootstrap(process.cwd(), async () => {
17
+ const agentName = args.name as string
18
+ const agent = await Agent.get(agentName)
19
+ if (!agent) {
20
+ process.stderr.write(
21
+ `Agent ${agentName} not found, run '${basename(process.execPath)} agent list' to get an agent list` + EOL,
22
+ )
23
+ process.exit(1)
24
+ }
25
+ process.stdout.write(JSON.stringify(agent, null, 2) + EOL)
26
+ })
27
+ },
28
+ })
@@ -0,0 +1,15 @@
1
+ import { EOL } from "os"
2
+ import { Config } from "../../../config/config"
3
+ import { bootstrap } from "../../bootstrap"
4
+ import { cmd } from "../cmd"
5
+
6
+ export const ConfigCommand = cmd({
7
+ command: "config",
8
+ builder: (yargs) => yargs,
9
+ async handler() {
10
+ await bootstrap(process.cwd(), async () => {
11
+ const config = await Config.get()
12
+ process.stdout.write(JSON.stringify(config, null, 2) + EOL)
13
+ })
14
+ },
15
+ })
@@ -0,0 +1,91 @@
1
+ import { EOL } from "os"
2
+ import { File } from "../../../file"
3
+ import { bootstrap } from "../../bootstrap"
4
+ import { cmd } from "../cmd"
5
+ import { Ripgrep } from "@/file/ripgrep"
6
+
7
+ const FileSearchCommand = cmd({
8
+ command: "search <query>",
9
+ builder: (yargs) =>
10
+ yargs.positional("query", {
11
+ type: "string",
12
+ demandOption: true,
13
+ description: "Search query",
14
+ }),
15
+ async handler(args) {
16
+ await bootstrap(process.cwd(), async () => {
17
+ const results = await File.search({ query: args.query })
18
+ process.stdout.write(results.join(EOL) + EOL)
19
+ })
20
+ },
21
+ })
22
+
23
+ const FileReadCommand = cmd({
24
+ command: "read <path>",
25
+ builder: (yargs) =>
26
+ yargs.positional("path", {
27
+ type: "string",
28
+ demandOption: true,
29
+ description: "File path to read",
30
+ }),
31
+ async handler(args) {
32
+ await bootstrap(process.cwd(), async () => {
33
+ const content = await File.read(args.path)
34
+ process.stdout.write(JSON.stringify(content, null, 2) + EOL)
35
+ })
36
+ },
37
+ })
38
+
39
+ const FileStatusCommand = cmd({
40
+ command: "status",
41
+ builder: (yargs) => yargs,
42
+ async handler() {
43
+ await bootstrap(process.cwd(), async () => {
44
+ const status = await File.status()
45
+ process.stdout.write(JSON.stringify(status, null, 2) + EOL)
46
+ })
47
+ },
48
+ })
49
+
50
+ const FileListCommand = cmd({
51
+ command: "list <path>",
52
+ builder: (yargs) =>
53
+ yargs.positional("path", {
54
+ type: "string",
55
+ demandOption: true,
56
+ description: "File path to list",
57
+ }),
58
+ async handler(args) {
59
+ await bootstrap(process.cwd(), async () => {
60
+ const files = await File.list(args.path)
61
+ process.stdout.write(JSON.stringify(files, null, 2) + EOL)
62
+ })
63
+ },
64
+ })
65
+
66
+ const FileTreeCommand = cmd({
67
+ command: "tree [dir]",
68
+ builder: (yargs) =>
69
+ yargs.positional("dir", {
70
+ type: "string",
71
+ description: "Directory to tree",
72
+ default: process.cwd(),
73
+ }),
74
+ async handler(args) {
75
+ const files = await Ripgrep.tree({ cwd: args.dir, limit: 200 })
76
+ console.log(files)
77
+ },
78
+ })
79
+
80
+ export const FileCommand = cmd({
81
+ command: "file",
82
+ builder: (yargs) =>
83
+ yargs
84
+ .command(FileReadCommand)
85
+ .command(FileStatusCommand)
86
+ .command(FileListCommand)
87
+ .command(FileSearchCommand)
88
+ .command(FileTreeCommand)
89
+ .demandCommand(),
90
+ async handler() {},
91
+ })
@@ -0,0 +1,45 @@
1
+ import { Global } from "../../../global"
2
+ import { bootstrap } from "../../bootstrap"
3
+ import { cmd } from "../cmd"
4
+ import { ConfigCommand } from "./config"
5
+ import { FileCommand } from "./file"
6
+ import { LSPCommand } from "./lsp"
7
+ import { RipgrepCommand } from "./ripgrep"
8
+ import { ScrapCommand } from "./scrap"
9
+ import { SkillCommand } from "./skill"
10
+ import { SnapshotCommand } from "./snapshot"
11
+ import { AgentCommand } from "./agent"
12
+
13
+ export const DebugCommand = cmd({
14
+ command: "debug",
15
+ builder: (yargs) =>
16
+ yargs
17
+ .command(ConfigCommand)
18
+ .command(LSPCommand)
19
+ .command(RipgrepCommand)
20
+ .command(FileCommand)
21
+ .command(ScrapCommand)
22
+ .command(SkillCommand)
23
+ .command(SnapshotCommand)
24
+ .command(AgentCommand)
25
+ .command(PathsCommand)
26
+ .command({
27
+ command: "wait",
28
+ async handler() {
29
+ await bootstrap(process.cwd(), async () => {
30
+ await new Promise((resolve) => setTimeout(resolve, 1_000 * 60 * 60 * 24))
31
+ })
32
+ },
33
+ })
34
+ .demandCommand(),
35
+ async handler() {},
36
+ })
37
+
38
+ const PathsCommand = cmd({
39
+ command: "paths",
40
+ handler() {
41
+ for (const [key, value] of Object.entries(Global.Path)) {
42
+ console.log(key.padEnd(10), value)
43
+ }
44
+ },
45
+ })
@@ -0,0 +1,48 @@
1
+ import { LSP } from "../../../lsp"
2
+ import { bootstrap } from "../../bootstrap"
3
+ import { cmd } from "../cmd"
4
+ import { Log } from "../../../util/log"
5
+ import { EOL } from "os"
6
+
7
+ export const LSPCommand = cmd({
8
+ command: "lsp",
9
+ builder: (yargs) =>
10
+ yargs.command(DiagnosticsCommand).command(SymbolsCommand).command(DocumentSymbolsCommand).demandCommand(),
11
+ async handler() {},
12
+ })
13
+
14
+ const DiagnosticsCommand = cmd({
15
+ command: "diagnostics <file>",
16
+ builder: (yargs) => yargs.positional("file", { type: "string", demandOption: true }),
17
+ async handler(args) {
18
+ await bootstrap(process.cwd(), async () => {
19
+ await LSP.touchFile(args.file, true)
20
+ await Bun.sleep(1000)
21
+ process.stdout.write(JSON.stringify(await LSP.diagnostics(), null, 2) + EOL)
22
+ })
23
+ },
24
+ })
25
+
26
+ export const SymbolsCommand = cmd({
27
+ command: "symbols <query>",
28
+ builder: (yargs) => yargs.positional("query", { type: "string", demandOption: true }),
29
+ async handler(args) {
30
+ await bootstrap(process.cwd(), async () => {
31
+ using _ = Log.Default.time("symbols")
32
+ const results = await LSP.workspaceSymbol(args.query)
33
+ process.stdout.write(JSON.stringify(results, null, 2) + EOL)
34
+ })
35
+ },
36
+ })
37
+
38
+ export const DocumentSymbolsCommand = cmd({
39
+ command: "document-symbols <uri>",
40
+ builder: (yargs) => yargs.positional("uri", { type: "string", demandOption: true }),
41
+ async handler(args) {
42
+ await bootstrap(process.cwd(), async () => {
43
+ using _ = Log.Default.time("document-symbols")
44
+ const results = await LSP.documentSymbol(args.uri)
45
+ process.stdout.write(JSON.stringify(results, null, 2) + EOL)
46
+ })
47
+ },
48
+ })
@@ -0,0 +1,83 @@
1
+ import { EOL } from "os"
2
+ import { Ripgrep } from "../../../file/ripgrep"
3
+ import { Instance } from "../../../project/instance"
4
+ import { bootstrap } from "../../bootstrap"
5
+ import { cmd } from "../cmd"
6
+
7
+ export const RipgrepCommand = cmd({
8
+ command: "rg",
9
+ builder: (yargs) => yargs.command(TreeCommand).command(FilesCommand).command(SearchCommand).demandCommand(),
10
+ async handler() {},
11
+ })
12
+
13
+ const TreeCommand = cmd({
14
+ command: "tree",
15
+ builder: (yargs) =>
16
+ yargs.option("limit", {
17
+ type: "number",
18
+ }),
19
+ async handler(args) {
20
+ await bootstrap(process.cwd(), async () => {
21
+ process.stdout.write((await Ripgrep.tree({ cwd: Instance.directory, limit: args.limit })) + EOL)
22
+ })
23
+ },
24
+ })
25
+
26
+ const FilesCommand = cmd({
27
+ command: "files",
28
+ builder: (yargs) =>
29
+ yargs
30
+ .option("query", {
31
+ type: "string",
32
+ description: "Filter files by query",
33
+ })
34
+ .option("glob", {
35
+ type: "string",
36
+ description: "Glob pattern to match files",
37
+ })
38
+ .option("limit", {
39
+ type: "number",
40
+ description: "Limit number of results",
41
+ }),
42
+ async handler(args) {
43
+ await bootstrap(process.cwd(), async () => {
44
+ const files: string[] = []
45
+ for await (const file of Ripgrep.files({
46
+ cwd: Instance.directory,
47
+ glob: args.glob ? [args.glob] : undefined,
48
+ })) {
49
+ files.push(file)
50
+ if (args.limit && files.length >= args.limit) break
51
+ }
52
+ process.stdout.write(files.join(EOL) + EOL)
53
+ })
54
+ },
55
+ })
56
+
57
+ const SearchCommand = cmd({
58
+ command: "search <pattern>",
59
+ builder: (yargs) =>
60
+ yargs
61
+ .positional("pattern", {
62
+ type: "string",
63
+ demandOption: true,
64
+ description: "Search pattern",
65
+ })
66
+ .option("glob", {
67
+ type: "array",
68
+ description: "File glob patterns",
69
+ })
70
+ .option("limit", {
71
+ type: "number",
72
+ description: "Limit number of results",
73
+ }),
74
+ async handler(args) {
75
+ const results = await Ripgrep.search({
76
+ cwd: process.cwd(),
77
+ pattern: args.pattern,
78
+ glob: args.glob as string[] | undefined,
79
+ limit: args.limit,
80
+ })
81
+ process.stdout.write(JSON.stringify(results, null, 2) + EOL)
82
+ },
83
+ })
@@ -0,0 +1,15 @@
1
+ import { EOL } from "os"
2
+ import { Project } from "../../../project/project"
3
+ import { Log } from "../../../util/log"
4
+ import { cmd } from "../cmd"
5
+
6
+ export const ScrapCommand = cmd({
7
+ command: "scrap",
8
+ builder: (yargs) => yargs,
9
+ async handler() {
10
+ const timer = Log.Default.time("scrap")
11
+ const list = await Project.list()
12
+ process.stdout.write(JSON.stringify(list, null, 2) + EOL)
13
+ timer.stop()
14
+ },
15
+ })
@@ -0,0 +1,15 @@
1
+ import { EOL } from "os"
2
+ import { Skill } from "../../../skill"
3
+ import { bootstrap } from "../../bootstrap"
4
+ import { cmd } from "../cmd"
5
+
6
+ export const SkillCommand = cmd({
7
+ command: "skill",
8
+ builder: (yargs) => yargs,
9
+ async handler() {
10
+ await bootstrap(process.cwd(), async () => {
11
+ const skills = await Skill.all()
12
+ process.stdout.write(JSON.stringify(skills, null, 2) + EOL)
13
+ })
14
+ },
15
+ })
@@ -0,0 +1,48 @@
1
+ import { Snapshot } from "../../../snapshot"
2
+ import { bootstrap } from "../../bootstrap"
3
+ import { cmd } from "../cmd"
4
+
5
+ export const SnapshotCommand = cmd({
6
+ command: "snapshot",
7
+ builder: (yargs) => yargs.command(TrackCommand).command(PatchCommand).command(DiffCommand).demandCommand(),
8
+ async handler() {},
9
+ })
10
+
11
+ const TrackCommand = cmd({
12
+ command: "track",
13
+ async handler() {
14
+ await bootstrap(process.cwd(), async () => {
15
+ console.log(await Snapshot.track())
16
+ })
17
+ },
18
+ })
19
+
20
+ const PatchCommand = cmd({
21
+ command: "patch <hash>",
22
+ builder: (yargs) =>
23
+ yargs.positional("hash", {
24
+ type: "string",
25
+ description: "hash",
26
+ demandOption: true,
27
+ }),
28
+ async handler(args) {
29
+ await bootstrap(process.cwd(), async () => {
30
+ console.log(await Snapshot.patch(args.hash))
31
+ })
32
+ },
33
+ })
34
+
35
+ const DiffCommand = cmd({
36
+ command: "diff <hash>",
37
+ builder: (yargs) =>
38
+ yargs.positional("hash", {
39
+ type: "string",
40
+ description: "hash",
41
+ demandOption: true,
42
+ }),
43
+ async handler(args) {
44
+ await bootstrap(process.cwd(), async () => {
45
+ console.log(await Snapshot.diff(args.hash))
46
+ })
47
+ },
48
+ })
@@ -0,0 +1,88 @@
1
+ import type { Argv } from "yargs"
2
+ import { Session } from "../../session"
3
+ import { cmd } from "./cmd"
4
+ import { bootstrap } from "../bootstrap"
5
+ import { UI } from "../ui"
6
+ import * as prompts from "@clack/prompts"
7
+ import { EOL } from "os"
8
+
9
+ export const ExportCommand = cmd({
10
+ command: "export [sessionID]",
11
+ describe: "export session data as JSON",
12
+ builder: (yargs: Argv) => {
13
+ return yargs.positional("sessionID", {
14
+ describe: "session id to export",
15
+ type: "string",
16
+ })
17
+ },
18
+ handler: async (args) => {
19
+ await bootstrap(process.cwd(), async () => {
20
+ let sessionID = args.sessionID
21
+ process.stderr.write(`Exporting session: ${sessionID ?? "latest"}`)
22
+
23
+ if (!sessionID) {
24
+ UI.empty()
25
+ prompts.intro("Export session", {
26
+ output: process.stderr,
27
+ })
28
+
29
+ const sessions = []
30
+ for await (const session of Session.list()) {
31
+ sessions.push(session)
32
+ }
33
+
34
+ if (sessions.length === 0) {
35
+ prompts.log.error("No sessions found", {
36
+ output: process.stderr,
37
+ })
38
+ prompts.outro("Done", {
39
+ output: process.stderr,
40
+ })
41
+ return
42
+ }
43
+
44
+ sessions.sort((a, b) => b.time.updated - a.time.updated)
45
+
46
+ const selectedSession = await prompts.autocomplete({
47
+ message: "Select session to export",
48
+ maxItems: 10,
49
+ options: sessions.map((session) => ({
50
+ label: session.title,
51
+ value: session.id,
52
+ hint: `${new Date(session.time.updated).toLocaleString()} • ${session.id.slice(-8)}`,
53
+ })),
54
+ output: process.stderr,
55
+ })
56
+
57
+ if (prompts.isCancel(selectedSession)) {
58
+ throw new UI.CancelledError()
59
+ }
60
+
61
+ sessionID = selectedSession as string
62
+
63
+ prompts.outro("Exporting session...", {
64
+ output: process.stderr,
65
+ })
66
+ }
67
+
68
+ try {
69
+ const sessionInfo = await Session.get(sessionID!)
70
+ const messages = await Session.messages({ sessionID: sessionID! })
71
+
72
+ const exportData = {
73
+ info: sessionInfo,
74
+ messages: messages.map((msg) => ({
75
+ info: msg.info,
76
+ parts: msg.parts,
77
+ })),
78
+ }
79
+
80
+ process.stdout.write(JSON.stringify(exportData, null, 2))
81
+ process.stdout.write(EOL)
82
+ } catch (error) {
83
+ UI.error(`Session not found: ${sessionID!}`)
84
+ process.exit(1)
85
+ }
86
+ })
87
+ },
88
+ })
@@ -0,0 +1,38 @@
1
+ import { Server } from "../../server/server"
2
+ import type { CommandModule } from "yargs"
3
+
4
+ export const GenerateCommand = {
5
+ command: "generate",
6
+ handler: async () => {
7
+ const specs = await Server.openapi()
8
+ for (const item of Object.values(specs.paths)) {
9
+ for (const method of ["get", "post", "put", "delete", "patch"] as const) {
10
+ const operation = item[method]
11
+ if (!operation?.operationId) continue
12
+ // @ts-expect-error
13
+ operation["x-codeSamples"] = [
14
+ {
15
+ lang: "js",
16
+ source: [
17
+ `import { createOpencodeClient } from "@opencode-ai/sdk`,
18
+ ``,
19
+ `const client = createOpencodeClient()`,
20
+ `await client.${operation.operationId}({`,
21
+ ` ...`,
22
+ `})`,
23
+ ].join("\n"),
24
+ },
25
+ ]
26
+ }
27
+ }
28
+ const json = JSON.stringify(specs, null, 2)
29
+
30
+ // Wait for stdout to finish writing before process.exit() is called
31
+ await new Promise<void>((resolve, reject) => {
32
+ process.stdout.write(json, (err) => {
33
+ if (err) reject(err)
34
+ else resolve()
35
+ })
36
+ })
37
+ },
38
+ } satisfies CommandModule