@prestyj/cli 5.30.0 → 5.30.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 (334) hide show
  1. package/README.md +54 -39
  2. package/assets/skills/bulletproof/SKILL.md +1 -1
  3. package/assets/skills/clarify/SKILL.md +1 -1
  4. package/assets/skills/code-review/SKILL.md +1 -1
  5. package/assets/skills/compliance-guard/SKILL.md +1 -1
  6. package/assets/skills/durable/SKILL.md +1 -1
  7. package/assets/skills/evidence-led-ui/SKILL.md +1 -1
  8. package/assets/skills/lean/SKILL.md +1 -1
  9. package/assets/skills/refactoring/SKILL.md +1 -1
  10. package/assets/skills/root-cause/SKILL.md +1 -1
  11. package/assets/skills/shared-language/SKILL.md +1 -1
  12. package/assets/skills/tdd/SKILL.md +1 -1
  13. package/dist/app-sidecar/app-settings.d.ts +63 -0
  14. package/dist/app-sidecar/app-settings.js +147 -0
  15. package/dist/app-sidecar/app-settings.js.map +1 -0
  16. package/dist/app-sidecar/attachments.d.ts +11 -0
  17. package/dist/app-sidecar/attachments.js +47 -0
  18. package/dist/app-sidecar/attachments.js.map +1 -0
  19. package/dist/app-sidecar/auth-routes.d.ts +3 -0
  20. package/dist/app-sidecar/auth-routes.js +293 -0
  21. package/dist/app-sidecar/auth-routes.js.map +1 -0
  22. package/dist/app-sidecar/autopilot-runner.d.ts +62 -0
  23. package/dist/app-sidecar/autopilot-runner.js +373 -0
  24. package/dist/app-sidecar/autopilot-runner.js.map +1 -0
  25. package/dist/app-sidecar/file-search.d.ts +15 -0
  26. package/dist/app-sidecar/file-search.js +103 -0
  27. package/dist/app-sidecar/file-search.js.map +1 -0
  28. package/dist/app-sidecar/hf-pull-manager.d.ts +20 -0
  29. package/dist/app-sidecar/hf-pull-manager.js +224 -0
  30. package/dist/app-sidecar/hf-pull-manager.js.map +1 -0
  31. package/dist/app-sidecar/history-routes.d.ts +3 -0
  32. package/dist/app-sidecar/history-routes.js +375 -0
  33. package/dist/app-sidecar/history-routes.js.map +1 -0
  34. package/dist/app-sidecar/history.d.ts +67 -0
  35. package/dist/app-sidecar/history.js +23 -0
  36. package/dist/app-sidecar/history.js.map +1 -0
  37. package/dist/app-sidecar/http.d.ts +5 -0
  38. package/dist/app-sidecar/http.js +27 -0
  39. package/dist/app-sidecar/http.js.map +1 -0
  40. package/dist/app-sidecar/integration-routes.d.ts +3 -0
  41. package/dist/app-sidecar/integration-routes.js +286 -0
  42. package/dist/app-sidecar/integration-routes.js.map +1 -0
  43. package/dist/app-sidecar/json-mode.d.ts +10 -0
  44. package/dist/app-sidecar/json-mode.js +73 -0
  45. package/dist/app-sidecar/json-mode.js.map +1 -0
  46. package/dist/app-sidecar/keep-awake.d.ts +4 -0
  47. package/dist/app-sidecar/keep-awake.js +5 -0
  48. package/dist/app-sidecar/keep-awake.js.map +1 -0
  49. package/dist/app-sidecar/mcp-routes.d.ts +3 -0
  50. package/dist/app-sidecar/mcp-routes.js +185 -0
  51. package/dist/app-sidecar/mcp-routes.js.map +1 -0
  52. package/dist/app-sidecar/mcp-rows.d.ts +31 -0
  53. package/dist/app-sidecar/mcp-rows.js +77 -0
  54. package/dist/app-sidecar/mcp-rows.js.map +1 -0
  55. package/dist/app-sidecar/nolan-context.d.ts +20 -0
  56. package/dist/app-sidecar/nolan-context.js +55 -0
  57. package/dist/app-sidecar/nolan-context.js.map +1 -0
  58. package/dist/app-sidecar/progress-manager.d.ts +10 -0
  59. package/dist/app-sidecar/progress-manager.js +116 -0
  60. package/dist/app-sidecar/progress-manager.js.map +1 -0
  61. package/dist/app-sidecar/prompt-routes.d.ts +3 -0
  62. package/dist/app-sidecar/prompt-routes.js +355 -0
  63. package/dist/app-sidecar/prompt-routes.js.map +1 -0
  64. package/dist/app-sidecar/repo-polls.d.ts +18 -0
  65. package/dist/app-sidecar/repo-polls.js +45 -0
  66. package/dist/app-sidecar/repo-polls.js.map +1 -0
  67. package/dist/app-sidecar/route-context.d.ts +147 -0
  68. package/dist/app-sidecar/route-context.js +2 -0
  69. package/dist/app-sidecar/route-context.js.map +1 -0
  70. package/dist/app-sidecar/run-control-routes.d.ts +3 -0
  71. package/dist/app-sidecar/run-control-routes.js +437 -0
  72. package/dist/app-sidecar/run-control-routes.js.map +1 -0
  73. package/dist/app-sidecar/session-routes.d.ts +3 -0
  74. package/dist/app-sidecar/session-routes.js +115 -0
  75. package/dist/app-sidecar/session-routes.js.map +1 -0
  76. package/dist/app-sidecar/session-types.d.ts +39 -0
  77. package/dist/app-sidecar/session-types.js +5 -0
  78. package/dist/app-sidecar/session-types.js.map +1 -0
  79. package/dist/app-sidecar/task-routes.d.ts +3 -0
  80. package/dist/app-sidecar/task-routes.js +232 -0
  81. package/dist/app-sidecar/task-routes.js.map +1 -0
  82. package/dist/app-sidecar/usage.d.ts +19 -0
  83. package/dist/app-sidecar/usage.js +153 -0
  84. package/dist/app-sidecar/usage.js.map +1 -0
  85. package/dist/app-sidecar/workspace-routes.d.ts +3 -0
  86. package/dist/app-sidecar/workspace-routes.js +374 -0
  87. package/dist/app-sidecar/workspace-routes.js.map +1 -0
  88. package/dist/app-sidecar.js +541 -3971
  89. package/dist/app-sidecar.js.map +1 -1
  90. package/dist/chat-agents/jiwa.js +2 -0
  91. package/dist/chat-agents/jiwa.js.map +1 -1
  92. package/dist/chat-agents/memory.js +2 -0
  93. package/dist/chat-agents/memory.js.map +1 -1
  94. package/dist/cli/auth.js +13 -9
  95. package/dist/cli/auth.js.map +1 -1
  96. package/dist/cli.js +10 -11
  97. package/dist/cli.js.map +1 -1
  98. package/dist/config.js +1 -1
  99. package/dist/core/acceptance-checks.js +3 -9
  100. package/dist/core/acceptance-checks.js.map +1 -1
  101. package/dist/core/agent-session/helpers.d.ts +26 -0
  102. package/dist/core/agent-session/helpers.js +47 -0
  103. package/dist/core/agent-session/helpers.js.map +1 -0
  104. package/dist/core/agent-session/mcp-tools.d.ts +68 -0
  105. package/dist/core/agent-session/mcp-tools.js +195 -0
  106. package/dist/core/agent-session/mcp-tools.js.map +1 -0
  107. package/dist/core/agent-session/run-loop-monitor.d.ts +63 -0
  108. package/dist/core/agent-session/run-loop-monitor.js +164 -0
  109. package/dist/core/agent-session/run-loop-monitor.js.map +1 -0
  110. package/dist/core/agent-session/transcript-markers.d.ts +57 -0
  111. package/dist/core/agent-session/transcript-markers.js +166 -0
  112. package/dist/core/agent-session/transcript-markers.js.map +1 -0
  113. package/dist/core/agent-session/verification-tracker.d.ts +50 -0
  114. package/dist/core/agent-session/verification-tracker.js +269 -0
  115. package/dist/core/agent-session/verification-tracker.js.map +1 -0
  116. package/dist/core/agent-session.d.ts +27 -87
  117. package/dist/core/agent-session.js +166 -713
  118. package/dist/core/agent-session.js.map +1 -1
  119. package/dist/core/auth-providers.js +3 -3
  120. package/dist/core/auth-providers.js.map +1 -1
  121. package/dist/core/autopilot-cycle.d.ts +8 -2
  122. package/dist/core/autopilot-cycle.js +22 -3
  123. package/dist/core/autopilot-cycle.js.map +1 -1
  124. package/dist/core/bundled-agents.js +6 -6
  125. package/dist/core/bundled-agents.js.map +1 -1
  126. package/dist/core/checklist-git.d.ts +19 -0
  127. package/dist/core/checklist-git.js +54 -0
  128. package/dist/core/checklist-git.js.map +1 -0
  129. package/dist/core/checklist-items.d.ts +10 -1
  130. package/dist/core/checklist-items.js +22 -0
  131. package/dist/core/checklist-items.js.map +1 -1
  132. package/dist/core/checklist-prompt.d.ts +14 -3
  133. package/dist/core/checklist-prompt.js +38 -8
  134. package/dist/core/checklist-prompt.js.map +1 -1
  135. package/dist/core/checklist-snapshot.d.ts +5 -1
  136. package/dist/core/checklist-snapshot.js +20 -3
  137. package/dist/core/checklist-snapshot.js.map +1 -1
  138. package/dist/core/checklist-store.d.ts +5 -1
  139. package/dist/core/checklist-store.js +35 -4
  140. package/dist/core/checklist-store.js.map +1 -1
  141. package/dist/core/context-limits.js +1 -1
  142. package/dist/core/context-limits.js.map +1 -1
  143. package/dist/core/event-bus.d.ts +1 -1
  144. package/dist/core/event-bus.js +39 -13
  145. package/dist/core/event-bus.js.map +1 -1
  146. package/dist/core/extensions/plugin-bundles.js +4 -2
  147. package/dist/core/extensions/plugin-bundles.js.map +1 -1
  148. package/dist/core/hashline.d.ts +10 -8
  149. package/dist/core/hashline.js.map +1 -1
  150. package/dist/core/mcp/client.js +2 -0
  151. package/dist/core/mcp/client.js.map +1 -1
  152. package/dist/core/mcp/loopback.d.ts +2 -2
  153. package/dist/core/mcp/loopback.js +2 -2
  154. package/dist/core/mcp/shared-pool.js +4 -3
  155. package/dist/core/mcp/shared-pool.js.map +1 -1
  156. package/dist/core/persistent-shell.js +2 -1
  157. package/dist/core/persistent-shell.js.map +1 -1
  158. package/dist/core/plan-handoff.d.ts +30 -0
  159. package/dist/core/plan-handoff.js +10 -0
  160. package/dist/core/plan-handoff.js.map +1 -0
  161. package/dist/core/plan-submission-gate.d.ts +28 -0
  162. package/dist/core/plan-submission-gate.js +27 -0
  163. package/dist/core/plan-submission-gate.js.map +1 -0
  164. package/dist/core/process-manager.js +9 -1
  165. package/dist/core/process-manager.js.map +1 -1
  166. package/dist/core/project-health-scan.d.ts +109 -0
  167. package/dist/core/project-health-scan.js +673 -0
  168. package/dist/core/project-health-scan.js.map +1 -0
  169. package/dist/core/project-health-score.d.ts +41 -0
  170. package/dist/core/project-health-score.js +257 -0
  171. package/dist/core/project-health-score.js.map +1 -0
  172. package/dist/core/prompt-commands.js +44 -6
  173. package/dist/core/prompt-commands.js.map +1 -1
  174. package/dist/core/session-manager.js.map +1 -1
  175. package/dist/core/session-storage.d.ts +1 -0
  176. package/dist/core/session-storage.js +1 -1
  177. package/dist/core/session-storage.js.map +1 -1
  178. package/dist/core/skills.js +6 -9
  179. package/dist/core/skills.js.map +1 -1
  180. package/dist/core/style-packs/index.js +2 -11
  181. package/dist/core/style-packs/index.js.map +1 -1
  182. package/dist/core/style-packs/packs.d.ts +3 -12
  183. package/dist/core/style-packs/packs.js +132 -173
  184. package/dist/core/style-packs/packs.js.map +1 -1
  185. package/dist/core/subagent-manager.js +11 -6
  186. package/dist/core/subagent-manager.js.map +1 -1
  187. package/dist/core/subagent-receipt.js +3 -4
  188. package/dist/core/subagent-receipt.js.map +1 -1
  189. package/dist/core/ui-adoption.js +2 -0
  190. package/dist/core/ui-adoption.js.map +1 -1
  191. package/dist/core/ui-registry.js +5 -4
  192. package/dist/core/ui-registry.js.map +1 -1
  193. package/dist/core/verification-evidence.d.ts +21 -2
  194. package/dist/core/verification-evidence.js +283 -8
  195. package/dist/core/verification-evidence.js.map +1 -1
  196. package/dist/core/verification-gate.js +4 -2
  197. package/dist/core/verification-gate.js.map +1 -1
  198. package/dist/core/verify-commands.js +2 -3
  199. package/dist/core/verify-commands.js.map +1 -1
  200. package/dist/modes/agent-home-mode.js +1 -4
  201. package/dist/modes/agent-home-mode.js.map +1 -1
  202. package/dist/modes/subagent-worker-mode.js +13 -8
  203. package/dist/modes/subagent-worker-mode.js.map +1 -1
  204. package/dist/system-prompt.js +70 -87
  205. package/dist/system-prompt.js.map +1 -1
  206. package/dist/tools/ask-user.js +13 -74
  207. package/dist/tools/ask-user.js.map +1 -1
  208. package/dist/tools/bash.d.ts +3 -1
  209. package/dist/tools/bash.js +28 -84
  210. package/dist/tools/bash.js.map +1 -1
  211. package/dist/tools/checklist.d.ts +7 -14
  212. package/dist/tools/checklist.js +22 -41
  213. package/dist/tools/checklist.js.map +1 -1
  214. package/dist/tools/code-nav.js +7 -29
  215. package/dist/tools/code-nav.js.map +1 -1
  216. package/dist/tools/edit.d.ts +4 -9
  217. package/dist/tools/edit.js +175 -65
  218. package/dist/tools/edit.js.map +1 -1
  219. package/dist/tools/enter-plan.js +2 -7
  220. package/dist/tools/enter-plan.js.map +1 -1
  221. package/dist/tools/exit-plan.js +2 -3
  222. package/dist/tools/exit-plan.js.map +1 -1
  223. package/dist/tools/find.js +3 -4
  224. package/dist/tools/find.js.map +1 -1
  225. package/dist/tools/grep.js +9 -20
  226. package/dist/tools/grep.js.map +1 -1
  227. package/dist/tools/index.js +10 -7
  228. package/dist/tools/index.js.map +1 -1
  229. package/dist/tools/ls.js +3 -3
  230. package/dist/tools/ls.js.map +1 -1
  231. package/dist/tools/prompt-hints.js +34 -47
  232. package/dist/tools/prompt-hints.js.map +1 -1
  233. package/dist/tools/read-only-bash.js +3 -0
  234. package/dist/tools/read-only-bash.js.map +1 -1
  235. package/dist/tools/read.js +8 -20
  236. package/dist/tools/read.js.map +1 -1
  237. package/dist/tools/search-code.js +4 -12
  238. package/dist/tools/search-code.js.map +1 -1
  239. package/dist/tools/skill.js +13 -7
  240. package/dist/tools/skill.js.map +1 -1
  241. package/dist/tools/subagent-control.js +7 -22
  242. package/dist/tools/subagent-control.js.map +1 -1
  243. package/dist/tools/subagent.js +1 -1
  244. package/dist/tools/subagent.js.map +1 -1
  245. package/dist/tools/task-output.js +4 -15
  246. package/dist/tools/task-output.js.map +1 -1
  247. package/dist/tools/task-send.js +5 -17
  248. package/dist/tools/task-send.js.map +1 -1
  249. package/dist/tools/task-stop.js +2 -2
  250. package/dist/tools/task-stop.js.map +1 -1
  251. package/dist/tools/tool-search.js +2 -7
  252. package/dist/tools/tool-search.js.map +1 -1
  253. package/dist/tools/tool-tiers.d.ts +21 -4
  254. package/dist/tools/tool-tiers.js +44 -17
  255. package/dist/tools/tool-tiers.js.map +1 -1
  256. package/dist/tools/web-fetch.js +7 -33
  257. package/dist/tools/web-fetch.js.map +1 -1
  258. package/dist/tools/write.js +3 -4
  259. package/dist/tools/write.js.map +1 -1
  260. package/dist/ui/App.js +20 -26
  261. package/dist/ui/App.js.map +1 -1
  262. package/dist/ui/components/Footer.js +1 -2
  263. package/dist/ui/components/Footer.js.map +1 -1
  264. package/dist/ui/components/InputArea.js +0 -2
  265. package/dist/ui/components/InputArea.js.map +1 -1
  266. package/dist/ui/components/ToolExecution.js +4 -3
  267. package/dist/ui/components/ToolExecution.js.map +1 -1
  268. package/dist/ui/hooks/useAgentLoop.js +7 -6
  269. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  270. package/dist/ui/sessions.js +1 -5
  271. package/dist/ui/sessions.js.map +1 -1
  272. package/dist/ui/utils/highlight.d.ts +0 -5
  273. package/dist/ui/utils/highlight.js +3 -49
  274. package/dist/ui/utils/highlight.js.map +1 -1
  275. package/dist/ui/utils/markdown-renderer.d.ts +6 -0
  276. package/dist/ui/utils/markdown-renderer.js +21 -5
  277. package/dist/ui/utils/markdown-renderer.js.map +1 -1
  278. package/dist/utils/process.js +3 -3
  279. package/dist/utils/process.js.map +1 -1
  280. package/dist/utils/shared-poll.d.ts +37 -0
  281. package/dist/utils/shared-poll.js +104 -0
  282. package/dist/utils/shared-poll.js.map +1 -0
  283. package/package.json +8 -8
  284. package/dist/core/api-benchmark.d.ts +0 -63
  285. package/dist/core/api-benchmark.js +0 -381
  286. package/dist/core/api-benchmark.js.map +0 -1
  287. package/dist/core/bash-spawn-benchmark.d.ts +0 -1
  288. package/dist/core/bash-spawn-benchmark.js +0 -139
  289. package/dist/core/bash-spawn-benchmark.js.map +0 -1
  290. package/dist/core/cache-warm-benchmark.d.ts +0 -21
  291. package/dist/core/cache-warm-benchmark.js +0 -170
  292. package/dist/core/cache-warm-benchmark.js.map +0 -1
  293. package/dist/core/fast-apply-benchmark.d.ts +0 -25
  294. package/dist/core/fast-apply-benchmark.js +0 -284
  295. package/dist/core/fast-apply-benchmark.js.map +0 -1
  296. package/dist/core/hashline-edit-benchmark.d.ts +0 -88
  297. package/dist/core/hashline-edit-benchmark.js +0 -518
  298. package/dist/core/hashline-edit-benchmark.js.map +0 -1
  299. package/dist/core/semantic-search-benchmark.d.ts +0 -36
  300. package/dist/core/semantic-search-benchmark.js +0 -211
  301. package/dist/core/semantic-search-benchmark.js.map +0 -1
  302. package/dist/core/speed-benchmark.d.ts +0 -132
  303. package/dist/core/speed-benchmark.js +0 -410
  304. package/dist/core/speed-benchmark.js.map +0 -1
  305. package/dist/ui/activity-phrases.d.ts +0 -10
  306. package/dist/ui/activity-phrases.js +0 -184
  307. package/dist/ui/activity-phrases.js.map +0 -1
  308. package/dist/ui/components/PlanApproval.d.ts +0 -7
  309. package/dist/ui/components/PlanApproval.js +0 -60
  310. package/dist/ui/components/PlanApproval.js.map +0 -1
  311. package/dist/ui/components/PlanBanner.d.ts +0 -5
  312. package/dist/ui/components/PlanBanner.js +0 -31
  313. package/dist/ui/components/PlanBanner.js.map +0 -1
  314. package/dist/ui/components/PlanProgress.d.ts +0 -6
  315. package/dist/ui/components/PlanProgress.js +0 -30
  316. package/dist/ui/components/PlanProgress.js.map +0 -1
  317. package/dist/ui/hooks/useMinDisplayTime.d.ts +0 -10
  318. package/dist/ui/hooks/useMinDisplayTime.js +0 -34
  319. package/dist/ui/hooks/useMinDisplayTime.js.map +0 -1
  320. package/dist/ui/hooks/useSessionManager.d.ts +0 -12
  321. package/dist/ui/hooks/useSessionManager.js +0 -43
  322. package/dist/ui/hooks/useSessionManager.js.map +0 -1
  323. package/dist/ui/hooks/useSlashCommands.d.ts +0 -6
  324. package/dist/ui/hooks/useSlashCommands.js +0 -11
  325. package/dist/ui/hooks/useSlashCommands.js.map +0 -1
  326. package/dist/ui/terminal-history-spacing.d.ts +0 -1
  327. package/dist/ui/terminal-history-spacing.js +0 -2
  328. package/dist/ui/terminal-history-spacing.js.map +0 -1
  329. package/dist/ui/utils/markdown-cache.d.ts +0 -10
  330. package/dist/ui/utils/markdown-cache.js +0 -58
  331. package/dist/ui/utils/markdown-cache.js.map +0 -1
  332. package/dist/ui/utils/token-to-ansi.d.ts +0 -8
  333. package/dist/ui/utils/token-to-ansi.js +0 -323
  334. package/dist/ui/utils/token-to-ansi.js.map +0 -1
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ![ezcoder](screenshots/ezcoder.png)
2
2
 
3
3
  <p align="center">
4
- <strong>The fast, lean coding agent. Eight providers. Zero bloat.</strong>
4
+ <strong>The fast, lean coding agent. Twelve providers plus local models. Zero bloat.</strong>
5
5
  </p>
6
6
 
7
7
  <p align="center">
@@ -12,13 +12,13 @@
12
12
  <a href="https://github.com/Gahroot"><img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white" alt="GitHub"></a>
13
13
  </p>
14
14
 
15
- A coding agent that ships only what the model needs to work — a tiny system prompt, one carefully-chosen MCP, and a focused tool set. Switch between Anthropic, OpenAI, GLM, Moonshot, MiniMax, Xiaomi, DeepSeek, and OpenRouter mid-conversation. Run it on its own, or let [`@prestyj/boss`](../ezboss/README.md) drive a fleet of `ezcoder` workers across many projects from a single chat.
15
+ A coding agent that ships only what the model needs to work — a tiny system prompt, no bundled MCPs, and a focused tool set. Switch between Anthropic, OpenAI, Gemini, xAI, Moonshot, GLM, MiniMax, Xiaomi, DeepSeek, Sakana, OpenRouter, Hugging Face, and your own local models mid-conversation. Run it on its own, or let [`@prestyj/boss`](../ezboss/README.md) drive a fleet of `ezcoder` workers across many projects from a single chat.
16
16
 
17
17
  Built on [`@prestyj/ai`](../ai/README.md) and [`@prestyj/agent`](../agent/README.md). Part of the [EZCoder Framework](../../README.md) monorepo.
18
18
 
19
19
  ---
20
20
 
21
- ## 🚀 Run It
21
+ ## Run It
22
22
 
23
23
  ```bash
24
24
  npm i -g @prestyj/cli
@@ -27,11 +27,11 @@ ezcoder login # Pick provider, authenticate
27
27
  ezcoder # Start coding
28
28
  ```
29
29
 
30
- OAuth for Anthropic and OpenAI (log in once, auto-refresh, no key to leak). API keys for the rest. Up and running in seconds either way. Auth lives in `~/.ezcoder/auth.json` and is shared with `ezboss`.
30
+ OAuth for Anthropic, OpenAI, and Gemini; OAuth or an API key for xAI and Moonshot (log in once, auto-refresh, no key to leak). API keys for the rest. Up and running in seconds either way. Auth lives in `~/.ezcoder/auth.json` and is shared with `ezboss`.
31
31
 
32
32
  ---
33
33
 
34
- ## 🪶 The system prompt problem
34
+ ## The system prompt problem
35
35
 
36
36
  Every token in the system prompt gets processed on **every single turn**. It's not a one-time cost. It's a tax on every request.
37
37
 
@@ -51,38 +51,43 @@ EZ Coder sends only what the model needs: how to work, what tools it has, and yo
51
51
 
52
52
  ---
53
53
 
54
- ## 🧩 The MCP problem
54
+ ## The MCP problem
55
55
 
56
56
  Same philosophy applies to tools. People collect MCPs like Pokemon. Slack MCP, GitHub MCP, Notion MCP, five different file system MCPs. Every single one injects its tool descriptions into the context. The model now has to figure out which of 40+ tools to use for any given task.
57
57
 
58
58
  This doesn't help. It confuses the agent. More tool descriptions = more noise = worse tool selection. The model spends tokens reasoning about tools it will never call.
59
59
 
60
- EZ Coder ships with one MCP: [Grep](https://grep.dev). That's it. It lets the agent search across 1M+ public GitHub repos to verify implementations against real-world code. Correct API usage, library idioms, production patterns. One tool that actually makes the output better.
60
+ EZ Coder ships with no MCPs by default. Checking work against real-world code is a native tool instead: `steroids` finds production repos similar to yours so the agent can confirm API usage, library idioms, and patterns. It loads only when the agent asks for it, so it costs nothing until it's used. (On GLM, the Z.AI MCP servers that come with your key are connected automatically.)
61
61
 
62
- You can still add your own MCPs if you need them. But start with less. You'll get better results.
62
+ You can still add your own MCPs in `~/.ezcoder/mcp.json` or `.ezcoder/mcp.json`. But start with less. You'll get better results.
63
63
 
64
64
  ---
65
65
 
66
- ## 🎛 Eight providers, one agent
66
+ ## Twelve providers, one agent
67
67
 
68
68
  Switch mid-conversation with `/model`. Not locked to anyone.
69
69
 
70
-
71
- | Provider | Models | Auth |
72
- | ----------------- | ---------------------------------------------------------------------------- | ---------------- |
73
- | **Anthropic** | Claude Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 4.5 | OAuth |
74
- | **OpenAI** | GPT-6 Astra, GPT-6.1 Sol, GPT-6 Luna | OAuth |
75
- | **Moonshot** | Kimi K3, Kimi K2.8 Preview, Kimi K2.7 Code | OAuth or API key |
76
- | **Z.AI (GLM)** | GLM-5.3, GLM-5.3-Flash (image) | API key |
77
- | **MiniMax** | MiniMax M3 (image + video) | API key |
78
- | **Xiaomi (MiMo)** | MiMo-V2.6-Pro + V2.6-Flash (image + video), V2.6-Pro-UltraSpeed | API key |
79
- | **DeepSeek** | DeepSeek V4 Pro, V4.1 Flash (image) | API key |
80
- | **Sakana (Fugu)** | Fugu, Fugu Max, Fugu Ultra (image) | API key |
81
- | **OpenRouter** | Qwen3.8 Max (image + video) + multi-provider gateway | API key |
70
+ | Provider | Models | Auth |
71
+ | ----------------- | ------------------------------------------------------------------------------------------- | ---------------- |
72
+ | **Anthropic** | Claude Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5 | OAuth |
73
+ | **OpenAI** | GPT-6 Astra, GPT-6.1 Sol, GPT-6 Luna | OAuth |
74
+ | **Gemini** | Gemini 3.1 Pro (Preview), 3.8 Flash, 3.7 Flash, 3.5 Flash, 3.5 Flash Lite, 3.1 Flash Lite | OAuth |
75
+ | **xAI (Grok)** | Grok 4.7 | OAuth or API key |
76
+ | **Moonshot** | Kimi K3, K2.8 Preview (Kimi sign-in), K2.7 Code, K2.7 Code HighSpeed | OAuth or API key |
77
+ | **Z.AI (GLM)** | GLM-5.3, GLM-5.3-Flash | API key |
78
+ | **MiniMax** | MiniMax M3 | API key |
79
+ | **Xiaomi (MiMo)** | MiMo-V2.6-Pro, MiMo-V2.6-Flash, MiMo-V2.6-Pro-UltraSpeed | API key |
80
+ | **DeepSeek** | DeepSeek V4 Pro, V4.1 Flash | API key |
81
+ | **Sakana (Fugu)** | Fugu, Fugu Max, Fugu Ultra | API key |
82
+ | **OpenRouter** | Qwen3.8 Max | API key |
83
+ | **Hugging Face** | Kimi K2.7 Code, DeepSeek V4.1 Flash, GPT-OSS 120B (Inference Providers router) | API key |
84
+ | **Local** | Any model on an OpenAI-compatible server: Ollama, LM Studio, llama.cpp, vLLM | None |
85
+
86
+ Every hosted model above except GLM-5.3, DeepSeek V4 Pro, and GPT-OSS 120B accepts images.
82
87
 
83
88
  The same conversation, the same tools, the same project context — only the model changes. Use a strong reasoning model when you need it, swap to a fast cheap one for grunt work, never restart your session.
84
89
 
85
- **Attachments.** Drag, paste, or type a path to attach images and video in the chat input. Video is sent natively to models that support it (Gemini 3.x, Kimi K3/K2.8 Preview/K2.7 Code, MiniMax M3, MiMo-V2.6, Qwen3.8 Max); for other models the video is saved to a temp file and the model is told to inspect it with ffmpeg or its own tools.
90
+ **Attachments.** Drag, paste, or type a path to attach images and video in the chat input. Video is sent natively to models that support it (Gemini 3.x, every Moonshot Kimi model, MiniMax M3, MiMo-V2.6, Qwen3.8 Max); for other models the video is saved to a temp file and the model is told to inspect it with ffmpeg or its own tools.
86
91
 
87
92
  ---
88
93
 
@@ -118,7 +123,7 @@ Run `ezcoder` directly when you're heads-down on one project. Switch to `ezboss`
118
123
 
119
124
  ---
120
125
 
121
- ## 💬 Slash commands
126
+ ## Slash commands
122
127
 
123
128
  Everything runs through slash commands inside the session. Not CLI flags.
124
129
 
@@ -131,7 +136,8 @@ Everything runs through slash commands inside the session. Not CLI flags.
131
136
  | `/branch` (`/b`) | Branch the current conversation |
132
137
  | `/branches` | List branches of the current session |
133
138
  | `/rewind` | Restore files and/or conversation to an earlier checkpoint |
134
- | `/buddy` | Spin up a second model to review the current chat |
139
+ | `/add-dir` | Add another project folder to this workspace |
140
+ | `/remove-dir` | Remove an added project folder from this workspace |
135
141
  | `/settings` (`/config`) | Open settings |
136
142
  | `/help` (`/h`, `/?`) | Show all commands |
137
143
  | `/quit` (`/q`, `/exit`) | Exit |
@@ -142,28 +148,37 @@ Plus built-in workflows that ship with the binary:
142
148
  /expand # Compare against current alternatives and report gaps
143
149
  /raise-floor # Audit existing features and make them just work
144
150
  /bullet-proof # Run a defensive security review
145
- /init # Generate CLAUDE.md for your project
151
+ /init # Generate or update AGENTS.md / CLAUDE.md for your project
146
152
  /setup-commit # Generate a /commit command with quality checks
153
+ /setup-ci # Set up or harden CI for any stack
147
154
  /setup-skills # Audit and recommend reusable skills
155
+ /compare # Compare your code against real-world code
156
+ /steroids # Index real repos like this project
148
157
  ```
149
158
 
150
159
  ---
151
160
 
152
- ## 🛠 Tools
161
+ ## Tools
153
162
 
154
- EZ Coder comes with a focused set of tools. Each one is small, well-described, and earns its place in the prompt.
163
+ EZ Coder comes with a focused set of tools. Only six core tools — `read`, `write`, `edit`, `bash`, `grep`, and `skill` — plus `tool_search` send their full schemas on every request. Everything else is listed as a one-line hint and loads the first time the agent needs it, so rarely used tools cost almost nothing.
155
164
 
156
165
  | Tool | What it does |
157
166
  | --------------------------------- | ------------------------------------------------------------------------------------------------------ |
158
- | `bash` | Run shell commands |
167
+ | `bash` | Run shell commands, in the foreground or background (`task_output` / `task_send` / `task_stop`) |
159
168
  | `read` | Read file contents |
160
169
  | `write` | Write files |
161
170
  | `edit` | Surgical string replacements |
162
171
  | `grep` | Search file contents (regex) |
163
- | `find` | Find files by glob pattern |
164
- | `ls` | List directory contents |
165
- | `web_fetch` | Fetch URL content |
172
+ | `skill` | Load a skill's instructions |
173
+ | `tool_search` | Load an on-demand tool by capability |
174
+ | `find` / `ls` | Find files by glob pattern / list a directory |
175
+ | `code_search` / `code_nav` | Find code by meaning / jump to exact definitions and callers |
176
+ | `web_fetch` / `web_search` | Fetch a URL / search the web |
177
+ | `steroids` | Find real production repos similar to yours and read how they do it |
178
+ | `source_path` | Locate an installed dependency's source |
166
179
  | `screenshot` | Open a URL / dev server in a headless browser and capture a PNG so the agent can see the rendered page |
180
+ | `debug` | Drive the Node debugger |
181
+ | `enter_plan` / `exit_plan` | Plan before editing, then hand the plan back for approval |
167
182
  | `subagent` | Run one blocking, isolated child task (backward-compatible) |
168
183
  | `spawn_agent` / `wait_agent` | Launch persistent child turns concurrently and collect results |
169
184
  | `send_message` / `followup_task` | Steer a running child or reuse an idle child's context |
@@ -171,7 +186,7 @@ EZ Coder comes with a focused set of tools. Each one is small, well-described, a
171
186
 
172
187
  The `screenshot` tool needs the optional `playwright` dependency plus a one-time `npx playwright install chromium`. Without it the tool returns an install hint instead of failing the turn. Captured images render inline in graphics-capable terminals (kitty, Ghostty, WezTerm, iTerm2); other terminals show a text line.
173
188
 
174
- Plus the [Grep MCP](https://grep.dev) for searching across 1M+ public GitHub repos. Add your own MCPs in settings if you need more — but start lean.
189
+ Add your own MCPs in `~/.ezcoder/mcp.json` or `.ezcoder/mcp.json` if you need more — but start lean.
175
190
 
176
191
  ### Async subagent lifecycle
177
192
 
@@ -185,13 +200,13 @@ Parent cancellation interrupts active children. Session disposal shuts down ever
185
200
 
186
201
  ---
187
202
 
188
- ## 🪄 Custom commands
203
+ ## Custom commands
189
204
 
190
205
  Drop a markdown file in `.ezcoder/commands/` and it becomes a slash command. Your React app gets `/deploy` and `/storybook`. Your API gets `/migrate` and `/seed`. Different projects, different commands.
191
206
 
192
207
  ---
193
208
 
194
- ## ⏪ Checkpoints & `/rewind`
209
+ ## Checkpoints & `/rewind`
195
210
 
196
211
  Before every file the agent writes or edits, EZ Coder snapshots the prior on-disk content into a per-session checkpoint (stored under `~/.ezcoder/checkpoints/`, never in your repo). Run `/rewind` to pick an earlier checkpoint and restore **code only**, **conversation only**, or **both**.
197
212
 
@@ -199,7 +214,7 @@ Only edits made through ezcoder's `write`/`edit` tools are tracked — changes m
199
214
 
200
215
  ---
201
216
 
202
- ## 🎒 Skills
217
+ ## Skills
203
218
 
204
219
  Reusable behaviors across projects. Drop `.md` files in:
205
220
 
@@ -226,22 +241,22 @@ Eleven ship built in, and route themselves when the work matches:
226
241
 
227
242
  ---
228
243
 
229
- ## 📋 Project guidelines
244
+ ## Project guidelines
230
245
 
231
- Drop a `CLAUDE.md` or `AGENTS.md` in your repo root (or any parent directory). EZ Coder picks it up automatically.
246
+ Drop an `AGENTS.md` or `CLAUDE.md` in your repo root (or any parent directory). EZ Coder picks it up automatically. One file per directory is loaded, first match wins: `AGENTS.override.md` > `AGENTS.md` > `CLAUDE.md` > `.cursorrules` > `CONVENTIONS.md`.
232
247
 
233
248
  Your rules. Your conventions. The agent follows them.
234
249
 
235
250
  ---
236
251
 
237
- ## 👥 Community
252
+ ## Community
238
253
 
239
254
  - [Prestyj website](https://prestyj.com) — tutorials and updates
240
255
  - [GitHub @Gahroot](https://github.com/Gahroot)
241
256
 
242
257
  ---
243
258
 
244
- ## 📄 License
259
+ ## License
245
260
 
246
261
  MIT
247
262
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bulletproof
3
- description: Use when writing or reviewing code an attacker can reach — auth, sessions, tokens, crypto; untrusted input (requests, files, archives, repo content, model/tool output); secrets; per-user or multi-tenant data access (incl. Supabase/Firebase RLS); dependencies, install scripts, CI/CD, publishing, signing, updates; shelling out, deserialization, dynamic loading; LLM/agent/MCP tools; and pre-ship "can this be hacked" reviews, hardening, or suspected compromise. Fires mid-build on adding a login, upload, webhook, dependency, or tool. Do NOT use for local CLIs/libraries/scripts with no auth, network, secrets or multi-user data, styling/copy/docs, or legal/privacy questions (compliance-guard).
3
+ description: "Use for attacker-reachable code: auth, tokens, crypto, untrusted input, secrets, tenant data, CI, agent tools. Do NOT use for local scripts without auth or network."
4
4
  license: Apache-2.0. Content is defensive engineering guidance, not a security certification or a penetration test. See references/provenance.md.
5
5
  compatibility: Works offline from the bundled references, which are a snapshot dated 3 October 2026. Version numbers, CVEs, and incident details decay fast; re-verify date-sensitive claims with web access before stating them as current. Never certifies that software is secure.
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: clarify
3
- description: Use when requirements or a design are genuinely unsettled — the user asks to interrogate, sharpen, or stress-test a plan or spec before building, a new app or feature request leaves costly-to-reverse product decisions open, or mid-build discovery hits a decision that materially changes the result (scope, data model, UX, tradeoff). Settled terms and hard-to-reverse calls hand off to shared-language. Do NOT use for routine changes, clear bug reports (root-cause), reviewing finished work (code-review), or work whose requirements are already settled — bias to action there.
3
+ description: Use when requirements are genuinely unsettled. Do NOT use for routine work.
4
4
  ---
5
5
 
6
6
  # Clarify
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: code-review
3
- description: Use when the user asks to review written work — a diff, PR, branch, commit range, or agent-generated change — or says "review before merge", "is this really done?", "check what the agent did". Checks spec compliance and build quality separately, verifies PR/"done" claims against the diff, and reports file:line findings by severity. Do NOT use while still mid-build (finish and run checks instead), for a plain diff summary, or for security review (bulletproof), performance (lean), migrations/data loss (durable), or UI review (evidence-led-ui).
3
+ description: Use when asked to review a diff, PR or finished work. Do NOT use mid-build.
4
4
  ---
5
5
 
6
6
  # Code Review
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: compliance-guard
3
- description: Use when shipping something real users reach and the work carries legal exposure — pre-launch or "is this safe to ship" reviews; mid-build features adding personal data, pixels/cookies, payments or auto-renewal, uploads/UGC, email/SMS/push, AI chatbots, minors, biometrics, scraping; drafting privacy policies, terms, disclosures. Also when a feature may need a licence or be illegal: health, finance, money movement, crypto, gambling, adult content, background checks, automated hiring/lending/housing decisions. Do NOT use for local-only scripts, prototypes with no real users or data, or changes touching no data, money, users or public surface; security hardening is bulletproof's lane.
3
+ description: Use when shipping to real users risks legal exposure (personal data, payments, minors). Do NOT use for local work.
4
4
  license: Apache-2.0. Content is engineering guidance, not legal advice. See references/provenance.md.
5
5
  compatibility: Static review works offline from the bundled references. Legal status changes constantly; date-sensitive claims must be re-verified with web access before being stated as current. Never certifies compliance.
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: durable
3
- description: Use when user data must not be lost or corrupted — creating the first table/schema, writing or running migrations, backfills/imports, any destructive op (delete, drop, truncate, reset, overwrite), before the agent itself runs a command against a database that may hold real data, setting up backups/recovery, or moving data between systems; plus "is my data safe / back up my app" checks. Any store — SQL, document, serverless, files, queues. Do NOT use for query speed or pool sizing (that is lean), access control over data (that is bulletproof), or privacy/legal deletion regimes (that is compliance-guard).
3
+ description: "Use when data could be lost: migrations, destructive ops, real databases. Do NOT use for query speed."
4
4
  license: Data-durability engineering guidance, not a DBA certification. Sources and snapshot date are recorded at the foot of each reference file.
5
5
  compatibility: Snapshot dated 3 October 2026. Version behaviours, provider retention defaults and tool flags decay — re-verify with web access before asserting them as current.
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: evidence-led-ui
3
- description: Use when building or changing web/mobile UI: net-new screens or pages, redesigns, design systems, visual polish, UI review, and mid-build edits touching colour, type, spacing, icons, focus/hover/selected states, borders, dropdown icons, motion, or UI copy layout. Also use when output looks generic or AI-made. Small styling fixes take the small-edit path. Do NOT use for behavior-only wiring with no visual state, copy-only text changes, database/API schemas, CLI output, or standalone image generation; speed/bundle work is lean, legal/privacy review of public pages is compliance-guard.
3
+ description: Use when building or reviewing UI visuals. Do NOT use for behaviour-only changes.
4
4
  license: See LICENSES.md
5
5
  compatibility: Full review requires filesystem inspection and rendered screenshots (deferred `screenshot` tool); web research and device tooling are optional and unavailable checks must be reported as unverified.
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lean
3
- description: Use when speed or resource use matters — while writing features that load, render lists, fetch, poll, spawn processes or cache (inline gate); on "slow / laggy / eating RAM / fans spinning", leaks, zombie or orphan processes, bundle bloat, dead code, Core Web Vitals; for a performance pass or pre-ship "will this run smoothly" check. Any stack — web, backend/API/CLI, desktop (Electron, Tauri), mobile, native, game, ML. Do NOT use for correctness bugs where speed is not the complaint, copy/docs-only changes, design or visual polish (evidence-led-ui), data-loss or migration safety (durable), or when the user explicitly deprioritizes performance.
3
+ description: Use when speed or resource use matters. Do NOT use for correctness bugs.
4
4
  license: Performance engineering guidance, not a benchmark certification. Sources and snapshot date are recorded at the foot of each reference file.
5
5
  compatibility: Snapshot dated 3 October 2026. Thresholds, tool names, and defaults decay — re-verify with web access before asserting them as current. Claims sourced to that date carry a SNAPSHOT marker.
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: refactoring
3
- description: Use for behavior-preserving restructuring: extract, move, split, deduplicate, plan a refactor, or migrate an implementation behind an unchanged contract. Baseline tests, small steps, revert-on-red. Do NOT use for requested behavior or API-contract changes (including new return/error semantics), even when called a "refactor"; use the normal implementation workflow with regression tests and update affected callers together. Also exclude bug fixes (root-cause when stubborn), performance work (lean), data migrations (durable), styling/copy, TDD's refactor step (tdd), and rewrites.
3
+ description: Use for behaviour-preserving restructuring behind an unchanged contract. Do NOT use for renames, bug fixes or behaviour changes.
4
4
  license: Behavior-preservation methodology synthesized from public sources (Fowler's Refactoring catalog, Tidy First?, and community agent skills by bienhoang, wondelai, mattpocock, jeffallan, vasilyu1983), audited 2026-09-12.
5
5
  ---
6
6
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: root-cause
3
- description: Use when a bug resists the obvious fix, behaviour makes no sense, a symptom keeps coming back, a test is flaky, something "worked last week", or the user asks why something happens and the answer is not on the surface — including mid-build when a second fix attempt fails. Do NOT use for bugs with a clear repro and an obvious cause (reproduce, fix, re-run directly), security incident triage (bulletproof), or reviewing a diff (code-review).
3
+ description: Use when a bug resists the obvious fix or is flaky. Do NOT use when the cause is obvious.
4
4
  ---
5
5
 
6
6
  # Root-Cause
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: shared-language
3
- description: Use when a project's domain vocabulary is fuzzy or drifting (two names for one thing, one name for two), naming decisions keep recurring, or a hard-to-reverse architectural decision needs recording so it is not re-litigated or re-suggested — including mid-build when a term settles or a change contradicts an ADR. Do NOT use for throwaway scripts, projects too small to have recurring vocabulary, interviewing for requirements (clarify), or renames with no vocabulary decision (refactoring).
3
+ description: Use when domain terms drift or a decision needs an ADR. Do NOT use for renames.
4
4
  ---
5
5
 
6
6
  # Shared Language
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: tdd
3
- description: Use when the user asks for test-driven development, red-green-refactor, "write the test first", or wants a feature or bug fix built test-first — including mid-build when they ask to switch to test-first. Do NOT use when tests are a verification step after the build, the project has no suite and the user has not asked for one, the change is throwaway probe code, or the goal is restructuring without behaviour change (refactoring) or finding an unknown cause (root-cause).
3
+ description: Use when asked for test-first development. Do NOT use for post-build tests.
4
4
  ---
5
5
 
6
6
  # TDD
@@ -0,0 +1,63 @@
1
+ import type { Provider, ThinkingLevel } from "@prestyj/ai";
2
+ import type { NolanModelPref } from "../core/nolan-model.js";
3
+ export declare const ALL_PROVIDERS: Provider[];
4
+ /** Per-project model + thinking preferences. Persisted so each window (one
5
+ * project cwd) restores its OWN model across app restarts — instead of every
6
+ * window reading the same single global slot that the last writer clobbered. */
7
+ export interface ProjectModelPrefs {
8
+ provider: Provider;
9
+ model: string;
10
+ thinkingEnabled?: boolean;
11
+ thinkingLevel?: ThinkingLevel;
12
+ }
13
+ export interface AppSettings {
14
+ /** Folder new projects are created inside. Defaults to ~/ez-projects. */
15
+ projectsRoot: string;
16
+ /** Model + thinking prefs keyed by normalized project cwd. A window restores
17
+ * its own entry on boot; absent → global settings.json → provider default. */
18
+ projectModels?: Record<string, ProjectModelPrefs>;
19
+ /** Autopilot (auto-review) on/off keyed by normalized project cwd. Per-window
20
+ * (one window = one cwd); absent/false → off. Restored on boot. */
21
+ autopilot?: Record<string, boolean>;
22
+ /** Nolan model override keyed by normalized project cwd. */
23
+ nolanModels?: Record<string, NolanModelPref>;
24
+ /** Extra folders scanned for projects alongside `projectsRoot`. */
25
+ projectRoots?: string[];
26
+ /** Project paths dismissed from the picker, as normalized cwds. */
27
+ hiddenProjects?: string[];
28
+ }
29
+ export declare function stringArray(value: unknown): string[] | undefined;
30
+ export declare function appSettingsFile(): string;
31
+ export declare function defaultProjectsRoot(): string;
32
+ /** Normalize a project cwd to a stable settings key so trailing slashes /
33
+ * relative segments collapse — the same project always maps to one entry. */
34
+ export declare function projectModelKey(cwd: string): string;
35
+ export declare function loadAppSettings(): Promise<AppSettings>;
36
+ export declare function saveAppSettings(settings: AppSettings): Promise<void>;
37
+ /** Read this project's persisted model/thinking prefs, if any. */
38
+ export declare function loadProjectModelPrefs(cwd: string): Promise<ProjectModelPrefs | undefined>;
39
+ /** Persist this project's model/thinking prefs via read-modify-write so the rest
40
+ * of the settings file (projectsRoot, other projects' entries) is preserved. */
41
+ export declare function saveProjectModelPrefs(cwd: string, prefs: ProjectModelPrefs): Promise<void>;
42
+ /** Read this project's persisted Nolan model override, if any. */
43
+ export declare function loadNolanModelPref(cwd: string): Promise<NolanModelPref | undefined>;
44
+ /** Persist (or with null, clear) this project's Nolan model override via
45
+ * read-modify-write so the rest of the settings file is preserved. */
46
+ export declare function saveNolanModelPref(cwd: string, pref: NolanModelPref | null): Promise<void>;
47
+ /** Read this project's persisted autopilot flag (default off). */
48
+ export declare function loadAutopilot(cwd: string): Promise<boolean>;
49
+ /** Persist this project's autopilot flag via read-modify-write so the rest of
50
+ * the settings file (projectsRoot, model map, other projects) is preserved. */
51
+ export declare function saveAutopilot(cwd: string, enabled: boolean): Promise<void>;
52
+ /**
53
+ * Persist the active model selection to ~/.ezcoder/settings.json so it survives app
54
+ * restarts. Mirrors the CLI's handleModelSelect persistence (App.tsx).
55
+ */
56
+ export declare function persistModelSelection(settingsFile: string, provider: Provider, model: string): Promise<void>;
57
+ /**
58
+ * Persist the thinking level to ~/.ezcoder/settings.json so it survives app restarts.
59
+ * Mirrors the CLI's handleToggleThinking persistence (App.tsx).
60
+ */
61
+ export declare function persistThinkingLevel(settingsFile: string, level: ThinkingLevel | undefined): Promise<void>;
62
+ /** Validate a project folder name: lowercase letters, digits, dashes only. */
63
+ export declare function isValidProjectName(name: string): boolean;
@@ -0,0 +1,147 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { SettingsManager } from "../core/settings-manager.js";
5
+ import { log } from "../core/logger.js";
6
+ export const ALL_PROVIDERS = [
7
+ // US
8
+ "anthropic",
9
+ "openai",
10
+ "gemini",
11
+ "xai",
12
+ // China
13
+ "moonshot",
14
+ "glm",
15
+ "minimax",
16
+ "xiaomi",
17
+ "deepseek",
18
+ // Open-community gateway, before the provider-agnostic one
19
+ "huggingface",
20
+ // Japan, then provider-agnostic gateway last
21
+ "sakana",
22
+ "openrouter",
23
+ ];
24
+ export function stringArray(value) {
25
+ if (!Array.isArray(value))
26
+ return undefined;
27
+ const out = value.filter((v) => typeof v === "string" && v.trim().length > 0);
28
+ return out.length > 0 ? out : undefined;
29
+ }
30
+ export function appSettingsFile() {
31
+ return path.join(os.homedir(), ".ezcoder", "ezcoder-app.json");
32
+ }
33
+ export function defaultProjectsRoot() {
34
+ return path.join(os.homedir(), "ez-projects");
35
+ }
36
+ /** Normalize a project cwd to a stable settings key so trailing slashes /
37
+ * relative segments collapse — the same project always maps to one entry. */
38
+ export function projectModelKey(cwd) {
39
+ return path.resolve(cwd);
40
+ }
41
+ export async function loadAppSettings() {
42
+ try {
43
+ const raw = JSON.parse(await fs.readFile(appSettingsFile(), "utf-8"));
44
+ return {
45
+ projectsRoot: typeof raw.projectsRoot === "string" && raw.projectsRoot.trim()
46
+ ? raw.projectsRoot
47
+ : defaultProjectsRoot(),
48
+ // Preserve the per-project map verbatim (validated + written by the
49
+ // model/thinking handlers below).
50
+ projectModels: raw.projectModels && typeof raw.projectModels === "object" ? raw.projectModels : undefined,
51
+ autopilot: raw.autopilot && typeof raw.autopilot === "object" ? raw.autopilot : undefined,
52
+ nolanModels: raw.nolanModels && typeof raw.nolanModels === "object" ? raw.nolanModels : undefined,
53
+ projectRoots: stringArray(raw.projectRoots),
54
+ hiddenProjects: stringArray(raw.hiddenProjects),
55
+ };
56
+ }
57
+ catch {
58
+ return { projectsRoot: defaultProjectsRoot() };
59
+ }
60
+ }
61
+ export async function saveAppSettings(settings) {
62
+ await fs.mkdir(path.dirname(appSettingsFile()), { recursive: true });
63
+ await fs.writeFile(appSettingsFile(), JSON.stringify(settings, null, 2), "utf-8");
64
+ }
65
+ /** Read this project's persisted model/thinking prefs, if any. */
66
+ export async function loadProjectModelPrefs(cwd) {
67
+ const s = await loadAppSettings();
68
+ return s.projectModels?.[projectModelKey(cwd)];
69
+ }
70
+ /** Persist this project's model/thinking prefs via read-modify-write so the rest
71
+ * of the settings file (projectsRoot, other projects' entries) is preserved. */
72
+ export async function saveProjectModelPrefs(cwd, prefs) {
73
+ const s = await loadAppSettings();
74
+ const key = projectModelKey(cwd);
75
+ s.projectModels = { ...(s.projectModels ?? {}), [key]: prefs };
76
+ await saveAppSettings(s);
77
+ }
78
+ /** Read this project's persisted Nolan model override, if any. */
79
+ export async function loadNolanModelPref(cwd) {
80
+ const s = await loadAppSettings();
81
+ return s.nolanModels?.[projectModelKey(cwd)];
82
+ }
83
+ /** Persist (or with null, clear) this project's Nolan model override via
84
+ * read-modify-write so the rest of the settings file is preserved. */
85
+ export async function saveNolanModelPref(cwd, pref) {
86
+ const s = await loadAppSettings();
87
+ const key = projectModelKey(cwd);
88
+ const next = { ...(s.nolanModels ?? {}) };
89
+ if (pref)
90
+ next[key] = pref;
91
+ else
92
+ delete next[key];
93
+ s.nolanModels = next;
94
+ await saveAppSettings(s);
95
+ }
96
+ /** Read this project's persisted autopilot flag (default off). */
97
+ export async function loadAutopilot(cwd) {
98
+ const s = await loadAppSettings();
99
+ return s.autopilot?.[projectModelKey(cwd)] ?? false;
100
+ }
101
+ /** Persist this project's autopilot flag via read-modify-write so the rest of
102
+ * the settings file (projectsRoot, model map, other projects) is preserved. */
103
+ export async function saveAutopilot(cwd, enabled) {
104
+ const s = await loadAppSettings();
105
+ const key = projectModelKey(cwd);
106
+ s.autopilot = { ...(s.autopilot ?? {}), [key]: enabled };
107
+ await saveAppSettings(s);
108
+ }
109
+ /**
110
+ * Persist the active model selection to ~/.ezcoder/settings.json so it survives app
111
+ * restarts. Mirrors the CLI's handleModelSelect persistence (App.tsx).
112
+ */
113
+ export async function persistModelSelection(settingsFile, provider, model) {
114
+ try {
115
+ const sm = new SettingsManager(settingsFile);
116
+ await sm.load();
117
+ await sm.set("defaultProvider", provider);
118
+ await sm.set("defaultModel", model);
119
+ }
120
+ catch (err) {
121
+ log("WARN", "app-sidecar", "failed to persist model selection", { err: String(err) });
122
+ }
123
+ }
124
+ /**
125
+ * Persist the thinking level to ~/.ezcoder/settings.json so it survives app restarts.
126
+ * Mirrors the CLI's handleToggleThinking persistence (App.tsx).
127
+ */
128
+ export async function persistThinkingLevel(settingsFile, level) {
129
+ try {
130
+ const sm = new SettingsManager(settingsFile);
131
+ await sm.load();
132
+ await sm.set("thinkingEnabled", !!level);
133
+ if (level)
134
+ await sm.set("thinkingLevel", level);
135
+ }
136
+ catch (err) {
137
+ log("WARN", "app-sidecar", "failed to persist thinking level", { err: String(err) });
138
+ }
139
+ }
140
+ /** Validate a project folder name: lowercase letters, digits, dashes only. */
141
+ export function isValidProjectName(name) {
142
+ return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
143
+ }
144
+ // ── History reconstruction types ──────────────────────────
145
+ // Mirrors HistoryEntry in ezcoder-app/src/agent.ts — the wire shape the webview
146
+ // receives from GET /history. Fields beyond role/text carry the transcript
147
+ //# sourceMappingURL=app-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-settings.js","sourceRoot":"","sources":["../../src/app-sidecar/app-settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface AppAttachment {
2
+ kind: "image" | "video" | "file";
3
+ name: string;
4
+ mediaType: string;
5
+ /** base64 (no data: prefix). */
6
+ data: string;
7
+ }
8
+ export interface PreparedAttachment extends AppAttachment {
9
+ path?: string;
10
+ }
11
+ export declare function prepareAttachments(cwd: string, attachments: AppAttachment[]): Promise<PreparedAttachment[]>;
@@ -0,0 +1,47 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { shrinkToFit, validateVisionImage } from "../utils/image.js";
4
+ export async function prepareAttachments(cwd, attachments) {
5
+ const dir = path.join(cwd, ".ezcoder", "uploads");
6
+ await fs.mkdir(dir, { recursive: true }).catch(() => { });
7
+ const out = [];
8
+ for (const a of attachments) {
9
+ // Sanitize the filename and prefix with a short timestamp to avoid clobber.
10
+ const safe = a.name.replace(/[^\w.-]+/g, "_").slice(-80) || "file";
11
+ const fileName = `${Date.now().toString(36)}-${safe}`;
12
+ const filePath = path.join(dir, fileName);
13
+ const buf = Buffer.from(a.data, "base64");
14
+ // Validate and cap image attachments before they become native image content
15
+ // blocks. Anthropic applies a 2000 px per-dimension cap once conversation
16
+ // history contains more than 20 images, so every attachment must be safe for
17
+ // later turns too. Keep the original on disk, but send the resized bytes.
18
+ // Corrupt or unsupported images become plain files so they cannot reject the
19
+ // entire provider request.
20
+ let prepared = { ...a };
21
+ if (a.kind === "image") {
22
+ try {
23
+ const resized = await shrinkToFit(buf, a.mediaType);
24
+ const validatedType = await validateVisionImage(resized.buffer);
25
+ prepared = validatedType
26
+ ? {
27
+ ...a,
28
+ mediaType: validatedType,
29
+ data: resized.buffer.toString("base64"),
30
+ }
31
+ : { ...a, kind: "file" };
32
+ }
33
+ catch {
34
+ prepared = { ...a, kind: "file" };
35
+ }
36
+ }
37
+ try {
38
+ await fs.writeFile(filePath, buf);
39
+ out.push({ ...prepared, path: filePath });
40
+ }
41
+ catch {
42
+ out.push({ ...prepared });
43
+ }
44
+ }
45
+ return out;
46
+ }
47
+ //# sourceMappingURL=attachments.js.map