@open-mercato/cezar 0.9.1 → 0.9.2-pr710.1256

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 (393) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -32
  3. package/dist/agent-config/account-identity.d.ts +44 -0
  4. package/dist/agent-config/account-identity.js +128 -0
  5. package/dist/agent-config/account-identity.js.map +1 -0
  6. package/dist/agent-config/catalog.d.ts +9 -1
  7. package/dist/agent-config/catalog.js +18 -0
  8. package/dist/agent-config/catalog.js.map +1 -1
  9. package/dist/agent-config/files.d.ts +1 -1
  10. package/dist/agent-config/model-settings/claude.d.ts +2 -0
  11. package/dist/agent-config/model-settings/claude.js +11 -0
  12. package/dist/agent-config/model-settings/claude.js.map +1 -0
  13. package/dist/agent-config/model-settings/codex.d.ts +2 -0
  14. package/dist/agent-config/model-settings/codex.js +16 -0
  15. package/dist/agent-config/model-settings/codex.js.map +1 -0
  16. package/dist/agent-config/model-settings/opencode.d.ts +2 -0
  17. package/dist/agent-config/model-settings/opencode.js +8 -0
  18. package/dist/agent-config/model-settings/opencode.js.map +1 -0
  19. package/dist/agent-config/model-settings/pi.d.ts +12 -0
  20. package/dist/agent-config/model-settings/pi.js +18 -0
  21. package/dist/agent-config/model-settings/pi.js.map +1 -0
  22. package/dist/agent-config/model-settings/shared.d.ts +9 -0
  23. package/dist/agent-config/model-settings/shared.js +93 -0
  24. package/dist/agent-config/model-settings/shared.js.map +1 -0
  25. package/dist/agent-config/model-settings/types.d.ts +9 -0
  26. package/dist/agent-config/model-settings/types.js +2 -0
  27. package/dist/agent-config/model-settings/types.js.map +1 -0
  28. package/dist/agent-config/models.d.ts +9 -0
  29. package/dist/agent-config/models.js +32 -0
  30. package/dist/agent-config/models.js.map +1 -0
  31. package/dist/agent-config/service.d.ts +1 -1
  32. package/dist/agent-config/service.js +4 -4
  33. package/dist/agent-config/service.js.map +1 -1
  34. package/dist/agent-config/validate.d.ts +1 -1
  35. package/dist/automations/coordinator.d.ts +26 -0
  36. package/dist/automations/coordinator.js +66 -0
  37. package/dist/automations/coordinator.js.map +1 -0
  38. package/dist/automations/github-poller.d.ts +74 -0
  39. package/dist/automations/github-poller.js +234 -0
  40. package/dist/automations/github-poller.js.map +1 -0
  41. package/dist/automations/scheduler.d.ts +42 -0
  42. package/dist/automations/scheduler.js +192 -0
  43. package/dist/automations/scheduler.js.map +1 -0
  44. package/dist/automations/store.d.ts +65 -0
  45. package/dist/automations/store.js +298 -0
  46. package/dist/automations/store.js.map +1 -0
  47. package/dist/automations/task-template.d.ts +18 -0
  48. package/dist/automations/task-template.js +95 -0
  49. package/dist/automations/task-template.js.map +1 -0
  50. package/dist/automations/types.d.ts +255 -0
  51. package/dist/automations/types.js +159 -0
  52. package/dist/automations/types.js.map +1 -0
  53. package/dist/config.d.ts +19 -112
  54. package/dist/config.js +48 -5
  55. package/dist/config.js.map +1 -1
  56. package/dist/contract/agent-config.d.ts +153 -0
  57. package/dist/contract/agent-profiles.d.ts +347 -0
  58. package/dist/contract/automations.d.ts +935 -0
  59. package/dist/contract/events.d.ts +104 -0
  60. package/dist/contract/github.d.ts +467 -0
  61. package/dist/contract/health.d.ts +102 -0
  62. package/dist/contract/index.d.ts +16 -0
  63. package/dist/contract/index.js +1830 -0
  64. package/dist/contract/projects.d.ts +210 -0
  65. package/dist/contract/repo.d.ts +234 -0
  66. package/dist/contract/runs.d.ts +1407 -0
  67. package/dist/contract/skills.d.ts +232 -0
  68. package/dist/contract/workflows.d.ts +218 -0
  69. package/dist/contract/workspace.d.ts +577 -0
  70. package/dist/core/agent-env.d.ts +1 -1
  71. package/dist/core/agent-env.js +41 -16
  72. package/dist/core/agent-env.js.map +1 -1
  73. package/dist/core/agent-model-policy.d.ts +10 -0
  74. package/dist/core/agent-model-policy.js +36 -0
  75. package/dist/core/agent-model-policy.js.map +1 -0
  76. package/dist/core/agent-profiles.d.ts +62 -0
  77. package/dist/core/agent-profiles.js +90 -0
  78. package/dist/core/agent-profiles.js.map +1 -0
  79. package/dist/core/agent-runner.d.ts +49 -7
  80. package/dist/core/agent-runner.js +48 -3
  81. package/dist/core/agent-runner.js.map +1 -1
  82. package/dist/core/ask.d.ts +45 -124
  83. package/dist/core/ask.js +103 -13
  84. package/dist/core/ask.js.map +1 -1
  85. package/dist/core/backend-detect.d.ts +5 -5
  86. package/dist/core/backend-detect.js +44 -7
  87. package/dist/core/backend-detect.js.map +1 -1
  88. package/dist/core/claude-cli-runner.d.ts +2 -2
  89. package/dist/core/claude-cli-runner.js +61 -13
  90. package/dist/core/claude-cli-runner.js.map +1 -1
  91. package/dist/core/claude-ui-mapper.d.ts +1 -1
  92. package/dist/core/codex-app-server-runner.d.ts +1 -1
  93. package/dist/core/codex-app-server-runner.js +65 -3
  94. package/dist/core/codex-app-server-runner.js.map +1 -1
  95. package/dist/core/codex-app-server-transport.d.ts +6 -1
  96. package/dist/core/codex-app-server-transport.js +17 -3
  97. package/dist/core/codex-app-server-transport.js.map +1 -1
  98. package/dist/core/codex-model-catalog.d.ts +1 -1
  99. package/dist/core/codex-ui-mapper.d.ts +5 -1
  100. package/dist/core/codex-ui-mapper.js +74 -17
  101. package/dist/core/codex-ui-mapper.js.map +1 -1
  102. package/dist/core/model-identity.d.ts +24 -12
  103. package/dist/core/model-identity.js +41 -24
  104. package/dist/core/model-identity.js.map +1 -1
  105. package/dist/core/model-presets.d.ts +10 -4
  106. package/dist/core/model-presets.js +52 -9
  107. package/dist/core/model-presets.js.map +1 -1
  108. package/dist/core/opencode-model-catalog.d.ts +30 -0
  109. package/dist/core/opencode-model-catalog.js +126 -0
  110. package/dist/core/opencode-model-catalog.js.map +1 -0
  111. package/dist/core/opencode-server-runner.d.ts +2 -2
  112. package/dist/core/opencode-ui-mapper.d.ts +4 -1
  113. package/dist/core/opencode-ui-mapper.js +45 -7
  114. package/dist/core/opencode-ui-mapper.js.map +1 -1
  115. package/dist/core/pi-runner.d.ts +24 -0
  116. package/dist/core/pi-runner.js +349 -0
  117. package/dist/core/pi-runner.js.map +1 -0
  118. package/dist/core/pi-ui-mapper.d.ts +34 -0
  119. package/dist/core/pi-ui-mapper.js +270 -0
  120. package/dist/core/pi-ui-mapper.js.map +1 -0
  121. package/dist/core/provider-auth.d.ts +154 -0
  122. package/dist/core/provider-auth.js +509 -0
  123. package/dist/core/provider-auth.js.map +1 -0
  124. package/dist/core/provider-availability.d.ts +3 -0
  125. package/dist/core/provider-availability.js +14 -0
  126. package/dist/core/provider-availability.js.map +1 -0
  127. package/dist/core/runner-factory.d.ts +1 -1
  128. package/dist/core/runner-factory.js +3 -0
  129. package/dist/core/runner-factory.js.map +1 -1
  130. package/dist/core/runner-model-catalog.d.ts +1 -1
  131. package/dist/core/shell-env.d.ts +28 -0
  132. package/dist/core/shell-env.js +56 -0
  133. package/dist/core/shell-env.js.map +1 -0
  134. package/dist/core/tool-display.d.ts +1 -1
  135. package/dist/core/ui-events.d.ts +2 -2
  136. package/dist/core/ui-events.js +1 -1
  137. package/dist/core/usage-limit.d.ts +42 -0
  138. package/dist/core/usage-limit.js +209 -0
  139. package/dist/core/usage-limit.js.map +1 -0
  140. package/dist/git-diff-base.d.ts +85 -0
  141. package/dist/git-diff-base.js +180 -0
  142. package/dist/git-diff-base.js.map +1 -0
  143. package/dist/git-worktree.d.ts +46 -6
  144. package/dist/git-worktree.js +46 -9
  145. package/dist/git-worktree.js.map +1 -1
  146. package/dist/handoff.d.ts +2 -2
  147. package/dist/handoff.js +1 -1
  148. package/dist/index.js +66 -8
  149. package/dist/index.js.map +1 -1
  150. package/dist/paths.d.ts +69 -6
  151. package/dist/paths.js +86 -9
  152. package/dist/paths.js.map +1 -1
  153. package/dist/planner.d.ts +2 -2
  154. package/dist/planner.js +7 -1
  155. package/dist/planner.js.map +1 -1
  156. package/dist/release/manifests.d.ts +81 -0
  157. package/dist/release/manifests.js +74 -0
  158. package/dist/release/manifests.js.map +1 -0
  159. package/dist/release/snapshot.d.ts +9 -23
  160. package/dist/release/snapshot.js +9 -22
  161. package/dist/release/snapshot.js.map +1 -1
  162. package/dist/release/stable.d.ts +15 -29
  163. package/dist/release/stable.js +14 -27
  164. package/dist/release/stable.js.map +1 -1
  165. package/dist/runs/agent-tmpdir.d.ts +41 -0
  166. package/dist/runs/agent-tmpdir.js +183 -0
  167. package/dist/runs/agent-tmpdir.js.map +1 -0
  168. package/dist/runs/auto-name.d.ts +1 -1
  169. package/dist/runs/auto-name.js +6 -1
  170. package/dist/runs/auto-name.js.map +1 -1
  171. package/dist/runs/event-history.d.ts +50 -0
  172. package/dist/runs/event-history.js +613 -0
  173. package/dist/runs/event-history.js.map +1 -0
  174. package/dist/runs/retention.d.ts +1 -1
  175. package/dist/runs/run-index.d.ts +19 -0
  176. package/dist/runs/run-index.js +43 -0
  177. package/dist/runs/run-index.js.map +1 -0
  178. package/dist/runs/store.d.ts +209 -344
  179. package/dist/runs/store.js +298 -39
  180. package/dist/runs/store.js.map +1 -1
  181. package/dist/runs/ui-event-sink.d.ts +1 -1
  182. package/dist/server/app-type.d.ts +21 -0
  183. package/dist/server/app-type.js +2 -0
  184. package/dist/server/app-type.js.map +1 -0
  185. package/dist/server/capabilities.d.ts +21 -6
  186. package/dist/server/capabilities.js +27 -1
  187. package/dist/server/capabilities.js.map +1 -1
  188. package/dist/server/forge/github.d.ts +58 -151
  189. package/dist/server/forge/github.js +530 -6
  190. package/dist/server/forge/github.js.map +1 -1
  191. package/dist/server/forge/index.d.ts +19 -3
  192. package/dist/server/forge/index.js +28 -1
  193. package/dist/server/forge/index.js.map +1 -1
  194. package/dist/server/forge/types.d.ts +86 -1
  195. package/dist/server/git-changes.d.ts +10 -8
  196. package/dist/server/git-changes.js +19 -17
  197. package/dist/server/git-changes.js.map +1 -1
  198. package/dist/server/git.d.ts +2 -0
  199. package/dist/server/git.js +9 -0
  200. package/dist/server/git.js.map +1 -1
  201. package/dist/server/github.d.ts +3 -3
  202. package/dist/server/github.js +1 -1
  203. package/dist/server/github.js.map +1 -1
  204. package/dist/server/open-in-app.d.ts +2 -1
  205. package/dist/server/open-in-app.js +3 -1
  206. package/dist/server/open-in-app.js.map +1 -1
  207. package/dist/server/open-in-terminal.d.ts +46 -1
  208. package/dist/server/open-in-terminal.js +72 -13
  209. package/dist/server/open-in-terminal.js.map +1 -1
  210. package/dist/server/pr.d.ts +2 -2
  211. package/dist/server/project-context.d.ts +20 -3
  212. package/dist/server/project-context.js +30 -1
  213. package/dist/server/project-context.js.map +1 -1
  214. package/dist/server/provider-action-gate.d.ts +8 -0
  215. package/dist/server/provider-action-gate.js +56 -0
  216. package/dist/server/provider-action-gate.js.map +1 -0
  217. package/dist/server/provider-auth-runtime.d.ts +21 -0
  218. package/dist/server/provider-auth-runtime.js +66 -0
  219. package/dist/server/provider-auth-runtime.js.map +1 -0
  220. package/dist/server/server.d.ts +12802 -47
  221. package/dist/server/server.js +2857 -949
  222. package/dist/server/server.js.map +1 -1
  223. package/dist/server/validators.d.ts +97 -0
  224. package/dist/server/validators.js +86 -0
  225. package/dist/server/validators.js.map +1 -0
  226. package/dist/server/ws.d.ts +2 -2
  227. package/dist/server/ws.js +2 -2
  228. package/dist/server/ws.js.map +1 -1
  229. package/dist/server-install/engine.d.ts +1 -1
  230. package/dist/server-install/engine.js +5 -18
  231. package/dist/server-install/engine.js.map +1 -1
  232. package/dist/server-install/platforms/macosx-ngrok.d.ts +1 -1
  233. package/dist/server-install/platforms/ubuntu-vps.d.ts +16 -1
  234. package/dist/server-install/platforms/ubuntu-vps.js +83 -1
  235. package/dist/server-install/platforms/ubuntu-vps.js.map +1 -1
  236. package/dist/server-install/state.d.ts +1 -1
  237. package/dist/server-install/steps.d.ts +2 -2
  238. package/dist/server-install/steps.js +6 -2
  239. package/dist/server-install/steps.js.map +1 -1
  240. package/dist/server-install/strategies.d.ts +1 -1
  241. package/dist/server-install/types.d.ts +38 -424
  242. package/dist/server-install/ui.d.ts +1 -1
  243. package/dist/skills-banner.d.ts +7 -6
  244. package/dist/skills-banner.js +7 -6
  245. package/dist/skills-banner.js.map +1 -1
  246. package/dist/skills-remote.d.ts +2 -2
  247. package/dist/skills-update.d.ts +88 -0
  248. package/dist/skills-update.js +392 -0
  249. package/dist/skills-update.js.map +1 -0
  250. package/dist/skills.d.ts +2 -0
  251. package/dist/skills.js +7 -2
  252. package/dist/skills.js.map +1 -1
  253. package/dist/todos.d.ts +2 -28
  254. package/dist/todos.js +1 -1
  255. package/dist/ui-state.d.ts +16 -2
  256. package/dist/ui-state.js +14 -1
  257. package/dist/ui-state.js.map +1 -1
  258. package/dist/workflows/load.d.ts +1 -1
  259. package/dist/workflows/run.d.ts +276 -15
  260. package/dist/workflows/run.js +1261 -159
  261. package/dist/workflows/run.js.map +1 -1
  262. package/dist/workflows/types.d.ts +62 -224
  263. package/dist/workflows/types.js +25 -2
  264. package/dist/workflows/types.js.map +1 -1
  265. package/dist/workspace/agent-accounts.d.ts +153 -0
  266. package/dist/workspace/agent-accounts.js +304 -0
  267. package/dist/workspace/agent-accounts.js.map +1 -0
  268. package/dist/workspace/agent-profiles.d.ts +78 -0
  269. package/dist/workspace/agent-profiles.js +115 -0
  270. package/dist/workspace/agent-profiles.js.map +1 -0
  271. package/dist/workspace/config.d.ts +94 -206
  272. package/dist/workspace/config.js +226 -14
  273. package/dist/workspace/config.js.map +1 -1
  274. package/dist/workspace/migrations.d.ts +1 -1
  275. package/dist/workspace/migrations.js +19 -4
  276. package/dist/workspace/migrations.js.map +1 -1
  277. package/dist/workspace/projects-cli.js +54 -4
  278. package/dist/workspace/projects-cli.js.map +1 -1
  279. package/dist/workspace/projects.d.ts +26 -2
  280. package/dist/workspace/projects.js +42 -3
  281. package/dist/workspace/projects.js.map +1 -1
  282. package/dist/workspace/semaphore.d.ts +51 -0
  283. package/dist/workspace/semaphore.js +53 -3
  284. package/dist/workspace/semaphore.js.map +1 -1
  285. package/dist/workspace/ui-state.d.ts +16 -5
  286. package/dist/workspace/ui-state.js +18 -7
  287. package/dist/workspace/ui-state.js.map +1 -1
  288. package/package.json +17 -39
  289. package/scripts/inline-contract.mjs +112 -0
  290. package/scripts/mock-claude.mjs +59 -1
  291. package/scripts/mock-pi-rpc.mjs +83 -0
  292. package/scripts/sync-readme.mjs +20 -0
  293. package/web/dist/assets/alert-dialog-BVs3QSmP.js +1 -0
  294. package/web/dist/assets/arrow-down-D7T7XuF6.js +1 -0
  295. package/web/dist/assets/arrow-left-B1dRFd8y.js +1 -0
  296. package/web/dist/assets/bundle-mjs-BT31bpU6.js +1 -0
  297. package/web/dist/assets/centered-state-DdRLYi9u.js +43 -0
  298. package/web/dist/assets/chevron-right-Dh0t3AL8.js +1 -0
  299. package/web/dist/assets/{chunk-BO2N2NFS-DtrdTCWa.js → chunk-BO2N2NFS-DE6qKn3r.js} +8 -8
  300. package/web/dist/assets/circle-check-4FDOlh9u.js +1 -0
  301. package/web/dist/assets/circle-x-CgTVbqX5.js +1 -0
  302. package/web/dist/assets/collapsible-BoADzTok.js +1 -0
  303. package/web/dist/assets/commit-list-BCcCkRbU.js +1 -0
  304. package/web/dist/assets/compare-variants-B7gTgGqR.js +1 -0
  305. package/web/dist/assets/{core-DePtBHcl.js → core-BCsw8oQw.js} +1 -1
  306. package/web/dist/assets/diff-ecfV3-op.js +3 -0
  307. package/web/dist/assets/diff-stat-C2KGLVnZ.js +1 -0
  308. package/web/dist/assets/{diff-view-DCeSegKk.js → diff-view-CQtonQ4L.js} +4 -4
  309. package/web/dist/assets/dropdown-menu-WcGoirf2.js +1 -0
  310. package/web/dist/assets/editable-title-SqNK-wuI.js +1 -0
  311. package/web/dist/assets/{ellipsis-vertical-CNnSLn5a.js → ellipsis-vertical-ClTFrwit.js} +1 -1
  312. package/web/dist/assets/{file-D4GBh1ao.js → file-BU0mWida.js} +1 -1
  313. package/web/dist/assets/folder-rsgCF0aw.js +1 -0
  314. package/web/dist/assets/{git-pull-request-DnR8Xh4_.js → git-pull-request-BFhIKb83.js} +1 -1
  315. package/web/dist/assets/git-toolbar-CF1_tzqz.js +1 -0
  316. package/web/dist/assets/github-CyjPz-Ks.js +1 -0
  317. package/web/dist/assets/highlighted-body-OFNGDK62-BL-MfFgl.js +1 -0
  318. package/web/dist/assets/highlighter-CdHqIwFr.js +3 -0
  319. package/web/dist/assets/image-preview-iEzCyEmz.js +1 -0
  320. package/web/dist/assets/index-BN09RpYY.css +2 -0
  321. package/web/dist/assets/index-CyG7aE1W.js +7 -0
  322. package/web/dist/assets/lib-BQXq3kEf.js +1 -0
  323. package/web/dist/assets/lib-BxQXEXDF.js +1 -0
  324. package/web/dist/assets/markdown-CNAa22LB.js +2 -0
  325. package/web/dist/assets/mermaid-GHXKKRXX-C4jxqUUb.js +1 -0
  326. package/web/dist/assets/new-task-form-CWhQZbsX.js +1 -0
  327. package/web/dist/assets/pill-BO5s2x3N.js +1 -0
  328. package/web/dist/assets/project-router-Dm4OhAPE.js +1 -0
  329. package/web/dist/assets/prompt-templates-CP__OCDQ.js +15 -0
  330. package/web/dist/assets/react-runtime-CCIEwYL0.js +9 -0
  331. package/web/dist/assets/{refresh-cw-BT8E96Tm.js → refresh-cw-DyiysCoP.js} +1 -1
  332. package/web/dist/assets/repo-git-B1WM6N8T.js +1 -0
  333. package/web/dist/assets/rolldown-runtime-QTnfLwEv.js +1 -0
  334. package/web/dist/assets/run-diff-CKx4d9Oo.js +3 -0
  335. package/web/dist/assets/run-header-DpbfOtNi.js +1 -0
  336. package/web/dist/assets/{search-x-BDjaMrzG.js → search-x-DRvk-6x4.js} +1 -1
  337. package/web/dist/assets/skill-empty-hint-D5vsHfMr.js +1 -0
  338. package/web/dist/assets/skills-BiWfHmCR.js +1 -0
  339. package/web/dist/assets/skills-XGltyIJ_.js +1 -0
  340. package/web/dist/assets/sparkles-BugkDxWO.js +1 -0
  341. package/web/dist/assets/{square-terminal-Ckjjn0vb.js → square-terminal-Drp2h-o8.js} +1 -1
  342. package/web/dist/assets/tab-link-CiRLRlnY.js +1 -0
  343. package/web/dist/assets/task-changes-C2hKkEtc.js +1 -0
  344. package/web/dist/assets/task-commits-CwGs_Opa.js +1 -0
  345. package/web/dist/assets/task-files-5KUgFzX3.js +2 -0
  346. package/web/dist/assets/task-thread-B3AFO3SS.js +9 -0
  347. package/web/dist/assets/textarea-Dn90Eun6.js +1 -0
  348. package/web/dist/assets/thread-loading-_1hPuk76.js +1 -0
  349. package/web/dist/assets/{trash-2-DAyZ0VSi.js → trash-2-BKEc5Sp2.js} +1 -1
  350. package/web/dist/assets/{triangle-alert-Uy8rokUh.js → triangle-alert-BGGPY2C2.js} +1 -1
  351. package/web/dist/assets/{upload-CDdyPPo_.js → upload-B0AQw-mO.js} +1 -1
  352. package/web/dist/assets/use-desktop-CegyTp3X.js +1 -0
  353. package/web/dist/assets/use-submit-shortcut-Mle-9uJp.js +1 -0
  354. package/web/dist/assets/utils-D9GHDNza.js +64 -0
  355. package/web/dist/assets/workflows-3PCz57Z6.js +11 -0
  356. package/web/dist/assets/zoomable-image-DTq7s8CZ.js +1 -0
  357. package/web/dist/index.html +33 -13
  358. package/scripts/dev.mjs +0 -74
  359. package/scripts/release-snapshot.mjs +0 -130
  360. package/scripts/release.mjs +0 -119
  361. package/web/dist/assets/arrow-left-CnSdp92h.js +0 -1
  362. package/web/dist/assets/bundle-mjs-BegPhL5c.js +0 -1
  363. package/web/dist/assets/centered-state-DOsTcJZF.js +0 -43
  364. package/web/dist/assets/commit-list-BrxBEzRK.js +0 -1
  365. package/web/dist/assets/compare-variants-Bv2c9ORF.js +0 -1
  366. package/web/dist/assets/dist-B6XQOhgM.js +0 -1
  367. package/web/dist/assets/git-toolbar-pIC1ubPM.js +0 -1
  368. package/web/dist/assets/github-DTTSG0ht.js +0 -1
  369. package/web/dist/assets/highlighted-body-OFNGDK62-BuFJwunK.js +0 -1
  370. package/web/dist/assets/image-preview-DEhW0TFz.js +0 -1
  371. package/web/dist/assets/index-Cijmlz7q.js +0 -30
  372. package/web/dist/assets/index-DzroxqBG.css +0 -2
  373. package/web/dist/assets/lib-DPEZDBUN.js +0 -1
  374. package/web/dist/assets/lib-uHpeUPzK.js +0 -1
  375. package/web/dist/assets/mermaid-GHXKKRXX-CN2zQue0.js +0 -1
  376. package/web/dist/assets/open-mercato-toBr6SOa.svg +0 -11
  377. package/web/dist/assets/project-router-BMx4e8m-.js +0 -1
  378. package/web/dist/assets/repo-git-BusYfa3t.js +0 -1
  379. package/web/dist/assets/run-diff-wOJ3odA-.js +0 -3
  380. package/web/dist/assets/run-header-Cg5incil.js +0 -1
  381. package/web/dist/assets/skill-empty-hint-DTUSp6Vl.js +0 -1
  382. package/web/dist/assets/skills-PpP2owbM.js +0 -1
  383. package/web/dist/assets/tab-link-F3uQrdm2.js +0 -1
  384. package/web/dist/assets/task-changes-iD9kS79I.js +0 -1
  385. package/web/dist/assets/task-commits-COkLaUri.js +0 -1
  386. package/web/dist/assets/task-files-Ckttz7XH.js +0 -2
  387. package/web/dist/assets/task-thread-CQD91VPt.js +0 -9
  388. package/web/dist/assets/textarea-Bj_LCreg.js +0 -1
  389. package/web/dist/assets/use-desktop-DUh0STzq.js +0 -3
  390. package/web/dist/assets/utils-B8s5qIcK.js +0 -1
  391. package/web/dist/assets/workflows-BFk8C0co.js +0 -11
  392. package/web/dist/assets/zoomable-image-PEDOqyLQ.js +0 -1
  393. /package/web/{open-mercato.svg → dist/open-mercato.svg} +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Patryk Lewczuk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -5,8 +5,8 @@
5
5
  **Parallel coding agents orchestrator** — a local cockpit for running and
6
6
  tracking AI coding-agent tasks in your repo.
7
7
 
8
- Type a task, pick a workflow and an agent — **Claude Code, Codex or OpenCode
9
- (experimental), or a mix of them per step** — and watch it work live: steps, tool calls,
8
+ Type a task, pick a workflow and an agent — **Claude Code, Codex, OpenCode or pi
9
+ (the latter two experimental), or a mix of them per step** — and watch it work live: steps, tool calls,
10
10
  tokens, diffs, in a browser cockpit that runs entirely on your machine.
11
11
  Your CLI logins, your `gh`, your files. No accounts, no database, no cloud.
12
12
 
@@ -19,7 +19,7 @@ your phone, working your backlog while you're away.
19
19
 
20
20
  [A look inside](#a-look-inside) · [What cezar does best](#what-cezar-does-best) · [What it solves](#what-it-solves) · [Who it's for](#who-its-for) · [Quick start](#quick-start) · [How it works](#how-it-works) · [Core concepts](#core-concepts) · [Cockpit tour](#cockpit-tour) · [Agent backends](#coding-agent-backends) · [Remote access](#remote-access-host-cezar-on-a-server)
21
21
 
22
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](#license)
22
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
23
23
  ![Node 20+](https://img.shields.io/badge/Node-20%2B-339933)
24
24
  ![TypeScript 7.x](https://img.shields.io/badge/TypeScript-7.x-3178c6)
25
25
  ![Zero config](https://img.shields.io/badge/config-zero-success)
@@ -60,7 +60,7 @@ it does better than any of them:
60
60
 
61
61
  - 🪶 **Genuinely zero config.** `npx cezar-cli` in your repo and you're running —
62
62
  no wizard, no API keys, no env vars, no schema, no database. It rides the
63
- `claude` / `codex` / `opencode` logins and the `gh` you already have, and every
63
+ `claude` / `codex` / `opencode` / `pi` logins and the `gh` you already have, and every
64
64
  missing piece degrades gracefully instead of blocking you.
65
65
  - 🖥️ **Built for a server (VPS mode).** cezar is made to live on a **VPS, cloud,
66
66
  or dedicated box** as an always-on janitor for your repo — headless-first, with
@@ -207,7 +207,7 @@ event live and parks the run at a review gate when there's a diff to inspect.
207
207
 
208
208
  ┌──────────────────────────────┐ ┌───────────────────────────────┐
209
209
  │ git worktree per task │ │ agent CLI (your login) │
210
- │ (isolated branch, parallel) │◄───►│ claude · codex · opencode
210
+ │ (isolated branch, parallel) │◄───►│ claude · codex · opencode · pi
211
211
  └──────────────────────────────┘ │ Bash open · no prompts │
212
212
  │ └───────────────────────────────┘
213
213
  │ agent text · tool calls · tool results · tokens · cost
@@ -285,11 +285,12 @@ Five moves that make the cockpit worth the browser tab:
285
285
 
286
286
  ## Cockpit tour
287
287
 
288
- Seven views, one browser window, all live over Server-Sent Events (six until you opt into the Inbox):
288
+ Eight views, one browser window, all live over Server-Sent Events (seven until you opt into the Inbox):
289
289
 
290
290
  | View | What's in it |
291
291
  |---|---|
292
292
  | **Tasks** | Every task with its status, live event stream (agent text · tool calls · tool results · pasted/generated screenshots), tokens and cost. Continue, cancel, open in terminal (`claude --resume`), review the diff, or push a draft PR. |
293
+ | **All tasks** | Every *registered project's* tasks in one table, filtered and grouped by tag, project, status or workflow — see [Grouping connected repositories](#grouping-connected-repositories-tags-and-the-all-tasks-page). Appears once a second project is registered. |
293
294
  | **Inbox** | **Opt-in** (`CEZ_FOLLOWUPS=1`; hidden by default). Follow-ups an agent left behind (`todos.json`) — one click turns a suggestion into the next task, pre-wired to its suggested skill. Off, agents are never asked to leave follow-ups; each task's own **Notes** handoff journal is unaffected. |
294
295
  | **Git** | Branch, working-tree status, diff vs HEAD, recent commits (click one for its inline patch + GitHub link), and the configurable base branch that worktrees fork from and PRs target. |
295
296
  | **GitHub** | Open issues and PRs of the repo's origin, read through your logged-in `gh`. Hand an issue straight to the agent — pick a workflow and skills, one click runs it. |
@@ -342,25 +343,86 @@ re-registers itself at the next start.
342
343
  **From the terminal** — the same registry, no cockpit required (handy over ssh):
343
344
 
344
345
  ```bash
345
- cezar projects # list: id, branch or status, path
346
+ cezar projects # list: id, branch or status, path, tags
346
347
  cezar projects add ~/code/api # register a folder (defaults to the current repo)
347
348
  cezar projects remove api # drop the registry entry; the repo is untouched
349
+ cezar projects tag api storefront backend # set the grouping tags (no tags clears them)
348
350
  ```
349
351
 
350
352
  These read and write `~/.cezar/config.json` directly, so they work with the
351
353
  server stopped, and `CEZ_HOME` selects which workspace they operate on.
352
354
 
353
- Settings split along the same line: **Agents**, **Worktrees**, **Bookmarklets**,
354
- **Prompt templates** and **MCP** describe one repo and live under
355
- `/p/<projectId>/settings`; **Appearance**, **Notifications**, **Resources**,
356
- **Projects** and **Keyboard** are yours or the machine's and live at
357
- `/settings/global`.
358
-
359
- **Old URLs keep working.** Every unprefixed path — `/`, `/tasks/<id>`,
360
- `/settings`, and the whole `/api/…` surface still answers exactly as before,
361
- bound to the project cezar was started in; the cockpit redirects flat paths to
362
- their `/p/<boot>/…` twin. Existing bookmarks, bookmarklets and scripts need no
363
- change.
355
+ Settings split along the same line: **General** (the project's folder, its
356
+ registry facts, its parallel-task ceiling, and Remove), **Agents**,
357
+ **Worktrees**, **Bookmarklets**, **Prompt templates** and **MCP** describe one
358
+ repo and live under `/p/<projectId>/settings`; **Appearance**,
359
+ **Notifications**, **Resources**, **Projects** and **Keyboard** are yours or the
360
+ machine's and live at `/settings/global`.
361
+
362
+ ### Grouping connected repositories: tags and the All tasks page
363
+
364
+ Work rarely stops at a repo boundary. A storefront is an API, a web app and a
365
+ design system; a platform is a handful of services plus the infra that runs
366
+ them. **Tags** are how you say so, and **All tasks** is where saying so pays off.
367
+
368
+ **Tag a repo** in **Settings → Projects**: type into the *Tags* cell on its row
369
+ and press Enter (comma works too; the × on a chip, or Backspace in an empty
370
+ field, removes one). The field **autocompletes from the tags already used in the
371
+ workspace** — click the field to see them all, arrow keys and Enter to pick —
372
+ which is what keeps the second repo landing on the first one's spelling instead
373
+ of inventing `store-front` next to `storefront`. Anything not on the list is
374
+ just typed. A tag is a free-form label — `storefront`, `infra`, `client-acme` —
375
+ and a project can carry several, because a repo can belong to more than one
376
+ piece of work. Tags are trimmed, deduplicated case-insensitively (`API` and
377
+ `api` are one tag) and stored in `~/.cezar/config.json` beside the rest of the
378
+ registry, so they are yours and this machine's, never something added to the
379
+ repo.
380
+
381
+ **All tasks** — the top item in the sidebar, `/tasks`, or `⌘K → All tasks` —
382
+ then shows every registered project's work in one table:
383
+
384
+ - **Filter** by tag, status and workflow. Tags are one-click chips; status and
385
+ workflow are searchable multi-selects. Every facet ORs inside itself and ANDs
386
+ across, so *"anything running or waiting in storefront or infra"* is one set
387
+ of clicks. Each option carries how many tasks it would leave, so a filter that
388
+ would empty the table says so before you click it. The search box matches
389
+ title, project, workflow, branch and tags.
390
+ - **Group by** tag, project, status or workflow — click the pressed one again to
391
+ ungroup. Grouping by tag is the reason tags exist: three repos tagged
392
+ `storefront` become one section, and a repo tagged twice appears under both —
393
+ it genuinely belongs to both.
394
+
395
+ The filters, the grouping and the Active/Archived tab live in the **URL**, so a
396
+ filtered view survives a refresh, pastes into a chat, and sits in a bookmark —
397
+ `/tasks?tag=storefront&status=running&group=tag` is a link to exactly what you
398
+ were looking at. Only what you changed shows up: Active is the default, so the
399
+ Archived view is `?archived=1` and a normal link carries no key for it.
400
+
401
+ Each row shows **every** PR and issue it references — a task opened on an issue
402
+ that landed a PR shows both — plus its cost and live CPU/memory, and can be
403
+ marked **read/unread** (the eye) or **archived** (or restored) right there. Every task title, project name and project group heading links into that
404
+ project, so the thread, its diff and its worktree are one click away and stay
405
+ exactly where they were.
406
+
407
+ There is deliberately **no project filter**: narrowing this page to one project
408
+ is that project's own Tasks page, which is a better version of the same answer
409
+ (live updates, the full column set, the composer). So picking a project *leaves*
410
+ for it rather than turning the global view into a worse local one.
411
+
412
+ Nothing else in cezar reads tags, on purpose: a tag is a lens, not a permission,
413
+ a queue or a routing rule. Removing one changes what you see and nothing else.
414
+
415
+ > The page reads a workspace-wide index capped at the newest 200 tasks per
416
+ > project — it says so, and names the projects it capped, rather than showing a
417
+ > short list as if it were complete. Older tasks are always in that project's own
418
+ > Tasks page.
419
+
420
+ **Old page URLs keep working.** Every unprefixed page path — `/`, `/tasks/<id>`,
421
+ `/settings` — still answers, bound to the project cezar was started in; the
422
+ cockpit redirects flat paths to their `/p/<boot>/…` twin, so existing bookmarks
423
+ and bookmarklets need no change. The HTTP API is the exception: it moved to
424
+ `/api/v1/…` (see the CHANGELOG), so a script that calls it needs the extra
425
+ segment.
364
426
 
365
427
  > **Hosted cockpit?** The folder picker is confined to the independent browse
366
428
  > root. Set `CEZ_BROWSE_ROOT` narrowly before first boot (or save it in
@@ -382,7 +444,7 @@ steps:
382
444
  prompt: "{{task}}"
383
445
  skill: project-conventions # optional — from .ai/skills or .ai/cezar/skills
384
446
  # model: opus # optional per-step model override
385
- # runner: codex # optional per-step backend: claude · codex · opencode
447
+ # runner: codex # optional per-step backend: claude · codex · opencode · pi
386
448
  # allowedTools: [Read, Edit, Write, Grep, Glob, Bash]
387
449
  - id: verify
388
450
  name: Verify
@@ -426,43 +488,87 @@ Useful environment variables:
426
488
  | Var | Effect |
427
489
  |---|---|
428
490
  | `CEZ_DRY_RUN=1` | Use the bundled mock instead of the real `claude` CLI — the entire cockpit works offline, for demos and development. |
491
+ | `CEZ_AGENT_MODELS_LOCKED=1` | Globally lock each runner to the model configured in its native Claude/Codex/OpenCode settings while keeping runner selection available. Exact `1` also delegates authentication and provider enablement to those native agents, so Cezar skips its credential probes and provider-disable preferences. Existing Cezar presets are preserved but ignored, and an environment change requires a restart. The config-file equivalent is `"modelsLocked": true` in global `~/.cezar/config.json` or one repository's `.ai/cezar/config.json`; config-file locks do not disable provider checks. |
429
492
  | `CEZ_APPROVAL_GATE=1` | Opt into Claude's interactive approval UI; by default, unapproved tools are denied without interrupting the run. |
430
493
  | `CEZ_FOLLOWUPS=1` | Turn on the global follow-up **Inbox**: agents are asked to leave follow-ups in `todos.json` when they finish, and the Inbox view appears. Off by default — each task's own **Notes** handoff journal runs either way. |
494
+ | `CEZ_AUTOMATIONS=1` | Turn on **GitHub automations**: the Automations view appears and cezar polls GitHub on each enabled automation's interval, launching tasks from what it finds. Off by default, and only the exact value `1` enables it — without it nothing polls GitHub, the automations endpoints answer `409`, and the nav item is absent. Read at boot, so restart after changing it; definitions, receipts and high-watermarks are retained, so unsetting it and restarting restores the feature without migration or data loss. |
431
495
  | `CEZ_AUTOSAVE=1` | Re-enable the periodic (90 s) autosave commit in task worktrees. Off by default (#471) — turn-end and pre-PR flushes always run, so branches still end complete. Every autosave names its trigger in the commit subject (`cezar autosave (periodic)` vs `(turn end)` / `(run finalize)` / `(pre-PR)`), so the flushes you keep are distinguishable from the timer you disabled. |
432
496
  | `CEZ_CLAUDE_BIN=/path/to/claude` | Override which `claude` binary is used. |
433
497
  | `CEZ_CODEX_BIN=/path/to/codex` | Override which `codex` binary is used. |
434
498
  | `CEZ_OPENCODE_BIN=/path/to/opencode` | Override which `opencode` binary is used. |
499
+ | `CEZ_PI_BIN=/path/to/pi` | Override which `pi` binary is used. |
500
+ | `CLAUDE_CONFIG_DIR`, `CODEX_HOME` | The agents' **own** variables, honoured where the vendor documents one. Setting one moves that agent's **default account** — the config folder cezar discovers. A *second* login of the same CLI is deliberately not an environment setting, since one process-wide value cannot differ per project: add it under **Settings → Agent accounts** and pick it per project. |
435
501
  | `CEZ_BROWSE_ROOT=~/` | Default root for **Add project → Open local folder…**. The picker cannot navigate above it; a saved workspace value overrides the environment default and must name an existing folder. |
436
502
  | `CEZ_PROJECTS_DIR=~/cezar/projects` | Default destination for **Clone from GitHub**. Saved workspace settings override it, and missing directories are created recursively. |
503
+ | `CEZ_SKILLS_AUTO_UPDATE=0` | Disable automatic checks and updates for upstream-CLI-tracked Open Mercato skill installations. On by default; a saved global Skills setting overrides this environment default. Checks are delayed, bounded, cached, and non-blocking. |
504
+ | `CEZ_AUTONOMOUS_DEFAULT=0` | Seed the New Task Autonomous default (`0` or `1`). Without a seed, skills default on and workflows off; a saved global Resources setting overrides it. |
505
+ | `CEZ_WORKTREE_DEFAULT=1` | Seed the New Task Worktree default (`0` or `1`). Without a seed, eligible runs default on; a saved global Resources setting overrides it. |
506
+ | `CEZ_DISABLE_REPO_LOCK=1` | **Dangerous escape hatch:** allow any run executing in the repository root — an explicit `worktree=false` run, non-Git degradation, or a continuation whose worktree cannot be restored — to proceed without Cezar’s repository-root lease. Agents can overwrite each other’s files or Git state; isolated worktree runs are unaffected. Off by default; only the exact value `1` enables it. |
437
507
  | `CEZ_SINGLE_PROJECT=1` | Opt into a launch-project-only cockpit: only the exact value `1` enables it. Project add, edit, checkout, folder browsing, and removal are refused and only the launch project is shown. Off by default; stored registry rows are retained, so unsetting it and restarting restores the full multi-project workspace without migration or data loss. |
508
+ | `CEZ_HIDE_TOKEN_USAGE=1` | Hide raw input/output token counts throughout the browser cockpit while leaving backend-reported cost visible. Only the exact value `1` enables it; telemetry and API payloads are unchanged, and a restart is required after changing it. |
509
+ | `CEZ_HIDE_COST=1` | Hide backend-reported monetary cost throughout the browser cockpit while leaving raw input/output token counts visible. Only the exact value `1` enables it; telemetry and API payloads are unchanged, and a restart is required after changing it. |
510
+ | `CEZ_HIDE_TOKEN_METRICS=1` | Legacy master switch that hides both token usage and cost. It takes precedence over the two independent flags; only the exact value `1` enables it, payloads are unchanged, and a restart is required. |
438
511
  | `GITHUB_TOKEN` | Fallback for GitHub reads/PRs when `gh` isn't authenticated. |
439
512
  | `CEZ_ENV_PASSTHROUGH=A,B` | Forward these extra host env vars to spawned agents. By default agents get a least-privilege env (safe shell/toolchain vars + the backend's own auth + `GITHUB_TOKEN` + `CEZ_*`), not your full environment — use this to add a var an agent needs. |
440
513
  | `CEZ_AGENT_ENV_FULL=1` | Escape hatch: give spawned agents the full host environment (pre-hardening behavior). Off by default; only set it if you understand that this hands every host secret to the agent process. |
514
+ | `CEZ_AGENT_TMPDIR=0` | Stop giving each task its own temp directory and hand agents the host `TMPDIR` again (pre-#785 behavior). On by default: every run gets `TMPDIR`/`TEMP`/`TMP` pointing at `.ai/cezar/tmp/<task-id>`, created and write-probed before the agent spawns and reaped when the run ends, so concurrent tasks stop sharing one directory and a task refuses to start rather than run against a temp directory that silently swallows its shell output (see Troubleshooting below). Only an exact `0` disables it, and it disables the whole thing — the pre-spawn check included, so this stays an escape hatch you can actually take. |
441
515
  | `CEZ_REDACT_SECRETS=0` | Disable scrubbing of credential values/token shapes from the on-disk state (the NDJSON transcript and the free-text fields of `runs.json`). On by default; leave it on. Best-effort defense-in-depth, not a guarantee: it catches known token shapes and the values of your own secret-named env vars, so a credential in neither category can still get through. |
442
516
  | `CEZ_TITLE_UPDATES=0` | Turn off the live task-title refresh (namer re-runs on each turn end). The Settings → Agents toggle overrides this default. |
443
517
  | `CEZ_AUTONAME=0` | Disable ALL LLM task naming (creation + live) — titles stay heuristic (`437: /om-auto-review-pr`). Under `CEZ_DRY_RUN=1` naming is already off unless forced with `CEZ_AUTONAME=1`. |
444
518
  | `CEZ_REVIEW_GATE=1` | Turn ON the optional diff-first review gate (#489): a successful, non-autonomous run with changes parks at `review` (Accept / Send back / Draft PR) instead of finishing. Off by default — changed runs settle to `done` with the diff left in the worktree. Only `1` enables. The Settings → Agents toggle overrides this; autonomous runs always skip it. |
445
519
  | `CEZ_NO_BANNER=1` | Skip the `open-mercato/skills` banner on `cezar serve` startup. (The cockpit no longer shows a banner — its skills now live on the Skills page's Manage panel — so this env var is the terminal banner's only switch.) |
520
+ | `VITE_CEZ_API_BASE=http://localhost:4321` | **Build time only**, and only when the cockpit bundle is deployed apart from the service it talks to. Empty (the default) means "the origin that served this page", which is right for both normal cases: the CLI serves the bundle itself, and `npm run dev` proxies `/api` to the local service. A deployment that must be configured without a rebuild can put `<meta name="cez-api-base" content="…">` in the served HTML instead, which wins over this. |
521
+
522
+ ### Troubleshooting: the agent's shell returns nothing
523
+
524
+ **Symptom.** A task on the Claude backend keeps working, but every shell command
525
+ comes back with no output and a spurious non-zero exit status — `echo hello`
526
+ included. Redirecting into a file inside the worktree still produces the right
527
+ content, so the commands genuinely run; only the *capture* is lost. Codex tasks
528
+ on the same machine are unaffected, because that backend streams over stdio
529
+ pipes instead of round-tripping a command's output through a temp file.
530
+
531
+ **Diagnosis.** The temp directory the agent was given is out of space or out of
532
+ quota. One line tells you:
533
+
534
+ ```bash
535
+ echo probe > "${TMPDIR:-/tmp}/probe" # "Disk quota exceeded" / "No space left on device"
536
+ df -i "${TMPDIR:-/tmp}" # a tmpfs can exhaust inodes long before bytes
537
+ ```
538
+
539
+ Under quota the file is *created* and the write then fails, so the backend reads
540
+ back a zero-byte capture file and hands the agent an empty result.
541
+
542
+ **Fix.** Since #785 cezar gives each task its own `TMPDIR` under
543
+ `.ai/cezar/tmp/<task-id>` and write-probes it before spawning, so a broken temp
544
+ directory fails the task with `agent temp directory is not writable: …` on the
545
+ task thread instead of corrupting its work. If you see that error, free space on
546
+ the disk holding the repo. `CEZ_AGENT_TMPDIR=0` turns the whole mechanism off —
547
+ per-task directory and pre-spawn check alike — and hands agents the host
548
+ `TMPDIR` again, which is the way out if the check itself is wrong on your
549
+ platform.
446
550
 
447
551
  ---
448
552
 
449
553
  ## Coding agent backends
450
554
 
451
555
  cezar is not married to one vendor. Every agent step runs through a single
452
- `AgentRunner` seam with three built-in backends:
556
+ `AgentRunner` seam with four built-in backends:
453
557
 
454
558
  | Backend | CLI | How cezar drives it | Tool access |
455
559
  |---|---|---|---|
456
560
  | **Claude Code** (default) | [`claude`](https://github.com/anthropics/claude-code) | Headless `stream-json` mode. | Per-tool `--allowedTools` (`bashAllowlist` scopes `Bash`); `dontAsk` denies unapproved tools without prompting (`CEZ_APPROVAL_GATE=1` → `acceptEdits` + approval UI). |
457
561
  | **Codex** | [`codex`](https://github.com/openai/codex) | `codex app-server` — JSON-RPC over stdio, the same transport the Codex IDE extensions use. | Ignores `allowedTools`; the default auto mode uses `danger-full-access` with `approvalPolicy: never` (`CEZ_CODEX_NETWORK=0` opts into the network-blocked `workspace-write` sandbox). |
458
562
  | **OpenCode** _(experimental)_ | [`opencode`](https://opencode.ai) | `opencode serve` — a local HTTP server with an SSE event stream. | Ignores `allowedTools` entirely; every permission is auto-approved. |
563
+ | **pi** _(experimental)_ | [`pi`](https://github.com/badlogic/pi-mono) | Persistent `--mode rpc` over JSONL; models are picked with the `provider/model` convention. | Maps `allowedTools` onto pi's `--tools` allowlist; a configured `bashAllowlist` disables Bash because pi cannot express command-prefix rules. |
459
564
 
460
- > ⚠️ **OpenCode support is experimental.** The runner works but is less battle-tested
461
- > than the Claude Code and Codex backends, and OpenCode auto-approves every permission
462
- > (it ignores `allowedTools`). Treat it as a preview and expect rough edges.
565
+ > ⚠️ **OpenCode and pi support are experimental.** Both runners work but are less
566
+ > battle-tested than the Claude Code and Codex backends, and OpenCode auto-approves
567
+ > every permission (it ignores `allowedTools`). Treat them as previews and expect
568
+ > rough edges.
463
569
 
464
570
  On startup cezar probes which CLIs are installed and the cockpit only offers
465
- the backends it found — install any one of the three and you're operational.
571
+ the backends it found — install any one of the four and you're operational.
466
572
 
467
573
  **Pick a backend at three levels** (most specific wins):
468
574
 
@@ -493,8 +599,19 @@ steps:
493
599
  Parallel variants (×2/×3) of one task share that task's backend — mixing
494
600
  happens per task and per step, not inside a variant group.
495
601
 
602
+ **Models come from your own machine.** For Codex and OpenCode, the model picker
603
+ is not a list cezar ships — it asks the installed CLI what it can actually run
604
+ (`codex app-server`'s `model/list`, and `opencode models`), caches the answer in
605
+ memory for five minutes, and shows it. A model your provider rolled out
606
+ yesterday is selectable without a cezar release, and one it retired stops being
607
+ offered. Claude Code has no equivalent local catalog, so it keeps a short list
608
+ of tier aliases and pinned versions. `auto` (let the agent decide) is always
609
+ available, including when the CLI is missing, logged out, or slow — discovery
610
+ never blocks the cockpit, and a model you pinned yourself stays selectable even
611
+ if it is absent from the discovered list.
612
+
496
613
  The seam is deliberately small: a backend is one class implementing the
497
- `AgentRunner` interface (`src/core/agent-runner.ts`) that turns a prompt into
614
+ `AgentRunner` interface (`packages/cezar/src/core/agent-runner.ts`) that turns a prompt into
498
615
  a stream of normalized events. Other CLIs — pi, aider, whatever ships next —
499
616
  can slot in the same way.
500
617
 
@@ -562,12 +679,20 @@ never blocks startup):
562
679
  // the source against a moving branch head — cezar verifies it resolves to
563
680
  // exactly that commit, and reports it as `team.commit`.
564
681
  "worktreeRetention": 10, // keep the last N finished worktrees on disk; 0 = unlimited (branch always kept)
565
- "defaultRunner": "claude", // agent backend: "claude" (default) · "codex" · "opencode"
682
+ "defaultRunner": "claude", // agent backend: "claude" (default) · "codex" · "opencode" · "pi"
683
+ "modelsLocked": true, // optional: native per-runner model is fixed/read-only; runner stays selectable
566
684
  "plannerModel": "sonnet", // model the "Plan first" button uses to draft chains
567
685
  "baseBranch": "develop" // branch worktrees fork from + PRs target (also settable in the Git tab)
568
686
  }
569
687
  ```
570
688
 
689
+ Put the same `"modelsLocked": true` key in `~/.cezar/config.json` to apply it
690
+ to every registered project. When the key is absent or `false` in both config
691
+ files (and `CEZ_AGENT_MODELS_LOCKED` is not `1`), each runner's normal model
692
+ selector uses that runner's discovered model list. While locked, the model is
693
+ shown read-only and follows the selected runner's native settings; the runner
694
+ itself remains selectable.
695
+
571
696
  Run data (`runs.json`, NDJSON event logs, worktrees, `todos.json`) is
572
697
  git-ignored automatically; your workflows and skills stay committable.
573
698
 
@@ -610,8 +735,8 @@ cd cezar
610
735
  npm install
611
736
  ```
612
737
 
613
- **3. Build** — compiles the server (`tsc → dist/`) and the cockpit
614
- (`vite build → web/dist/`), then runs the pack gate:
738
+ **3. Build** — compiles the api-client and the server (`tsc → packages/cezar/dist/`) and the cockpit
739
+ (`vite build → packages/cezar/web/dist/`), then runs the pack gate:
615
740
 
616
741
  ```bash
617
742
  npm run build
@@ -663,9 +788,9 @@ npm run uninstall-as-command # removes cezar / cez / cezar-cli (either flavor
663
788
 
664
789
  ```bash
665
790
  npm run dev # server (API :4321) + Vite dev server, opens the cockpit in the browser
666
- npm run dev:server # tsx src/index.ts — the API server alone
791
+ npm run dev:server # tsx packages/cezar/src/index.ts — the API server alone
667
792
  npm run dev:web # Vite dev server alone (proxies /api to :4321)
668
- npm run build # tsc → dist/, vite build → web/dist/, then the pack gate
793
+ npm run build # tsc → packages/cezar/dist/, vite build → packages/cezar/web/dist/, then the pack gate
669
794
  npm run typecheck # server + web (tsc --noEmit)
670
795
  npm test # vitest — server + cockpit unit suites
671
796
  npm run test:unit # node:test — fast core-module tests
@@ -675,7 +800,7 @@ npm run test:e2e # real-browser cockpit suite (agent-browser)
675
800
 
676
801
  The stack is deliberately small: **TypeScript** (strict, ESM), **Hono** + SSE for
677
802
  the server, **Zod** at every boundary, **YAML** for workflows, and a **React 19 +
678
- Vite + Tailwind v4 + shadcn/ui** cockpit shipped pre-built in `web/dist/` — the
803
+ Vite + Tailwind v4 + shadcn/ui** cockpit shipped pre-built in `packages/cezar/web/dist/` — the
679
804
  published package carries the built app, so `npx` users never run a bundler.
680
805
  Every module is meant to be read in one sitting.
681
806
 
@@ -694,4 +819,4 @@ Start here; graduate to cezar when a team needs shared visibility.
694
819
 
695
820
  ## License
696
821
 
697
- **MIT** © Patryk Lewczuk
822
+ **MIT** © Patryk Lewczuk — full text in [LICENSE](LICENSE).
@@ -0,0 +1,44 @@
1
+ import type { ProviderId } from '../core/provider-auth.ts';
2
+ /**
3
+ * Who an agent account is logged in AS — the "Show details" read (spec
4
+ * `2026-07-29-agent-profiles.md`).
5
+ *
6
+ * This is the second place vendor knowledge lives about an agent's home, beside
7
+ * `catalog.ts` (which config FILES exist) and `core/agent-profiles.ts` (which env var relocates
8
+ * the home). This one knows where each agent writes its own identity. Facts verified against the
9
+ * files on disk 2026-07-29; re-verify before changing them.
10
+ *
11
+ * ## Two rules that are not negotiable
12
+ *
13
+ * 1. **Named fields only, never pass-through.** `~/.codex/auth.json` holds `OPENAI_API_KEY`,
14
+ * `access_token` and `refresh_token` right beside the identity claims. Every reader below picks
15
+ * fields by name and builds a fresh object; nothing here spreads, forwards or stringifies a
16
+ * parsed vendor object, so a key the vendor adds tomorrow cannot leak through. The JWT is read
17
+ * for its CLAIMS and its signature is never a credential we hold onto.
18
+ * 2. **Read on demand, answered to exactly one route.** This never joins the accounts listing,
19
+ * never enters `runs.json` or the NDJSON, and is never logged. `provider-auth.ts` keeps account
20
+ * identity out of its own boundary on purpose; this is the deliberate, opt-in exception —
21
+ * localHandoff-gated, and only when the user asks for it — not a widening of that rule.
22
+ */
23
+ /** One labelled row, as the pane renders it. Deliberately not a fixed per-provider shape: what an
24
+ * agent knows about its own login differs, and inventing an empty "Organization" for one that has
25
+ * no concept of it would be a worse answer than omitting the row. */
26
+ export interface AccountIdentityField {
27
+ label: string;
28
+ value: string;
29
+ }
30
+ export interface AccountIdentity {
31
+ /** False when there is nothing to show — not signed in, no file, or a file we cannot parse. */
32
+ available: boolean;
33
+ /** Why, in the user's terms, when `available` is false. */
34
+ reason?: string;
35
+ fields: AccountIdentityField[];
36
+ }
37
+ /**
38
+ * What this account is logged in as, or an honest reason there is nothing to show.
39
+ *
40
+ * Never throws. OpenCode answers "unsupported": its credentials live in a SQLite DB outside the
41
+ * config dir (see `core/agent-profiles.ts`), so there is nothing in a config folder to read — and
42
+ * guessing from the default login would attribute one account's identity to another.
43
+ */
44
+ export declare function readAccountIdentity(provider: ProviderId, configDir: string): Promise<AccountIdentity>;
@@ -0,0 +1,128 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { claudeStateFilePath } from '../paths.js';
4
+ /** `.claude.json` can carry per-project history; cap the read like `readUserMcpServers` does. */
5
+ const READ_CAP = 2 * 1024 * 1024;
6
+ const NOT_SIGNED_IN = 'Not signed in on this account yet — use Connect.';
7
+ const UNREADABLE = 'Could not read this account’s details.';
8
+ /** Read a JSON file under the cap. `null` for absent, unreadable, oversized or malformed. */
9
+ async function readJsonCapped(path) {
10
+ try {
11
+ const raw = await readFile(path, 'utf8');
12
+ if (raw.length > READ_CAP)
13
+ return null;
14
+ const parsed = JSON.parse(raw);
15
+ return parsed && typeof parsed === 'object' ? parsed : null;
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ /** A non-empty display string, or undefined — so a blank vendor value never renders as an empty row. */
22
+ function text(value) {
23
+ if (typeof value === 'string' && value.trim() !== '')
24
+ return value.trim();
25
+ if (typeof value === 'number' && Number.isFinite(value))
26
+ return String(value);
27
+ return undefined;
28
+ }
29
+ /** Push a row only when the value is really there. */
30
+ function push(fields, label, value) {
31
+ const shown = text(value);
32
+ if (shown !== undefined)
33
+ fields.push({ label, value: shown });
34
+ }
35
+ /**
36
+ * Claude Code keeps its login in `.claude.json`'s `oauthAccount` — a *sibling* of `~/.claude` by
37
+ * default, but INSIDE an overridden config dir (`claudeStateFilePath` owns that rule, and getting
38
+ * it wrong is how one account reports another's email).
39
+ */
40
+ async function readClaudeIdentity(configDir) {
41
+ const state = await readJsonCapped(claudeStateFilePath(configDir));
42
+ if (state === null)
43
+ return { available: false, reason: NOT_SIGNED_IN, fields: [] };
44
+ const account = state.oauthAccount;
45
+ if (!account || typeof account !== 'object') {
46
+ return { available: false, reason: NOT_SIGNED_IN, fields: [] };
47
+ }
48
+ const a = account;
49
+ const fields = [];
50
+ push(fields, 'Email', a.emailAddress);
51
+ push(fields, 'Name', a.displayName);
52
+ push(fields, 'Organization', a.organizationName);
53
+ push(fields, 'Role', a.organizationRole);
54
+ // `seatTier`/`billingType` are the closest thing to a plan the file states; neither is
55
+ // documented, so they are shown under a label that promises no more than they are.
56
+ push(fields, 'Seat', a.seatTier);
57
+ push(fields, 'Billing', a.billingType);
58
+ return fields.length > 0
59
+ ? { available: true, fields }
60
+ : { available: false, reason: UNREADABLE, fields: [] };
61
+ }
62
+ /**
63
+ * Codex keeps its login in `auth.json`'s `id_token` — a JWT whose payload carries the identity
64
+ * claims. Read for its claims only: the same file holds `OPENAI_API_KEY`, `access_token` and
65
+ * `refresh_token`, none of which this function so much as names.
66
+ *
67
+ * The signature is NOT verified, and that is correct here: this is a local file the user's own CLI
68
+ * wrote, read to display who they are — not a token cezar is accepting as proof of anything.
69
+ */
70
+ async function readCodexIdentity(configDir) {
71
+ const auth = await readJsonCapped(join(configDir, 'auth.json'));
72
+ if (auth === null)
73
+ return { available: false, reason: NOT_SIGNED_IN, fields: [] };
74
+ const tokens = auth.tokens;
75
+ const idToken = tokens && typeof tokens === 'object'
76
+ ? tokens.id_token
77
+ : undefined;
78
+ const fields = [];
79
+ const claims = typeof idToken === 'string' ? decodeJwtClaims(idToken) : null;
80
+ if (claims !== null) {
81
+ push(fields, 'Email', claims.email);
82
+ push(fields, 'Name', claims.name);
83
+ const openai = claims['https://api.openai.com/auth'];
84
+ if (openai && typeof openai === 'object') {
85
+ push(fields, 'Plan', openai.chatgpt_plan_type);
86
+ }
87
+ }
88
+ // An API-key login has no id_token at all — say which kind of login this is rather than
89
+ // reporting "not signed in" for an account that is perfectly usable.
90
+ if (fields.length === 0 && typeof auth.OPENAI_API_KEY === 'string' && auth.OPENAI_API_KEY !== '') {
91
+ return { available: true, fields: [{ label: 'Login', value: 'API key' }] };
92
+ }
93
+ return fields.length > 0
94
+ ? { available: true, fields }
95
+ : { available: false, reason: NOT_SIGNED_IN, fields: [] };
96
+ }
97
+ /** A JWT's payload claims, or null when it is not a readable three-part token. */
98
+ function decodeJwtClaims(token) {
99
+ const parts = token.split('.');
100
+ if (parts.length !== 3 || !parts[1])
101
+ return null;
102
+ try {
103
+ const parsed = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf8'));
104
+ return parsed && typeof parsed === 'object' ? parsed : null;
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ /**
111
+ * What this account is logged in as, or an honest reason there is nothing to show.
112
+ *
113
+ * Never throws. OpenCode answers "unsupported": its credentials live in a SQLite DB outside the
114
+ * config dir (see `core/agent-profiles.ts`), so there is nothing in a config folder to read — and
115
+ * guessing from the default login would attribute one account's identity to another.
116
+ */
117
+ export async function readAccountIdentity(provider, configDir) {
118
+ if (provider === 'claude')
119
+ return readClaudeIdentity(configDir);
120
+ if (provider === 'codex')
121
+ return readCodexIdentity(configDir);
122
+ return {
123
+ available: false,
124
+ reason: 'OpenCode keeps its login outside its config folder, so cezar cannot read it.',
125
+ fields: [],
126
+ };
127
+ }
128
+ //# sourceMappingURL=account-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-identity.js","sourceRoot":"","sources":["../../src/agent-config/account-identity.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { RunnerId } from '../core/agent-runner.js';
1
+ import type { RunnerId } from '../core/agent-runner.ts';
2
2
  /**
3
3
  * The catalog of coding-agent config files cezar can surface and edit (spec
4
4
  * `.ai/specs/2026-07-16-agent-config-files.md`). This file is the ONLY place
@@ -47,6 +47,14 @@ export interface ConfigFileDef {
47
47
  seeded?: boolean;
48
48
  /** True when this file holds MCP server definitions (drives the MCP section's filter). */
49
49
  holdsMcp?: boolean;
50
+ /** Top-level native setting that supplies the agent's new-session model, when present. */
51
+ modelKey?: string;
52
+ /** Native model keys checked in precedence order, including nested `env.*` settings. */
53
+ modelKeys?: readonly string[];
54
+ /** Native provider key paired with the model, when the vendor separates the two. */
55
+ modelProviderKey?: string;
56
+ /** Higher values win when resolving a native default model across config scopes. */
57
+ modelPriority?: number;
50
58
  /** VERBATIM from the vendor docs. Never computed, never generic. */
51
59
  precedence: string;
52
60
  /** Documented mid-run reload behaviour, or undefined when the vendor is silent. */
@@ -21,6 +21,9 @@ export const CONFIG_FILES = [
21
21
  label: '~/.claude/settings.json',
22
22
  format: 'json',
23
23
  tracked: 'outside-repo',
24
+ modelKey: 'model',
25
+ modelKeys: ['env.ANTHROPIC_MODEL', 'model'],
26
+ modelPriority: 1,
24
27
  precedence: 'Lowest priority. Project and local settings override it key by key — except permission rules, which merge across all scopes.',
25
28
  hotReload: 'Edits to most keys — including permissions and hooks — apply to a running session without a restart.',
26
29
  docsUrl: CLAUDE_SETTINGS_DOCS,
@@ -34,6 +37,9 @@ export const CONFIG_FILES = [
34
37
  label: '.claude/settings.json',
35
38
  format: 'json',
36
39
  tracked: 'tracked',
40
+ modelKey: 'model',
41
+ modelKeys: ['env.ANTHROPIC_MODEL', 'model'],
42
+ modelPriority: 2,
37
43
  precedence: 'Overrides user settings key by key (permission rules merge). Local settings override this.',
38
44
  hotReload: 'Edits to most keys — including permissions and hooks — apply to a running session without a restart.',
39
45
  docsUrl: CLAUDE_SETTINGS_DOCS,
@@ -48,6 +54,9 @@ export const CONFIG_FILES = [
48
54
  format: 'json',
49
55
  tracked: 'gitignored',
50
56
  seeded: true,
57
+ modelKey: 'model',
58
+ modelKeys: ['env.ANTHROPIC_MODEL', 'model'],
59
+ modelPriority: 3,
51
60
  precedence: 'Highest of the file scopes — overrides project and user (permission rules merge). Git-ignored; copied into each run’s worktree so it takes effect immediately.',
52
61
  hotReload: 'Edits to most keys — including permissions and hooks — apply to a running session without a restart.',
53
62
  docsUrl: CLAUDE_SETTINGS_DOCS,
@@ -113,6 +122,9 @@ export const CONFIG_FILES = [
113
122
  format: 'toml',
114
123
  tracked: 'outside-repo',
115
124
  holdsMcp: true,
125
+ modelKey: 'model',
126
+ modelProviderKey: 'model_provider',
127
+ modelPriority: 1,
116
128
  precedence: 'User-level defaults. A trusted project’s .codex/config.toml overrides these; some keys (provider, auth, telemetry) cannot be overridden at project scope. MCP servers live here under [mcp_servers.<id>].',
117
129
  docsUrl: CODEX_CONFIG_DOCS,
118
130
  },
@@ -125,6 +137,8 @@ export const CONFIG_FILES = [
125
137
  label: '.codex/config.toml',
126
138
  format: 'toml',
127
139
  tracked: 'tracked',
140
+ modelKey: 'model',
141
+ modelPriority: 2,
128
142
  holdsMcp: true,
129
143
  precedence: 'Applies only in projects you have trusted. Some keys (provider, auth, telemetry) cannot be overridden here. MCP servers go under [mcp_servers.<id>]. Runs read the committed copy.',
130
144
  docsUrl: CODEX_CONFIG_DOCS,
@@ -152,6 +166,8 @@ export const CONFIG_FILES = [
152
166
  format: 'jsonc',
153
167
  tracked: 'outside-repo',
154
168
  holdsMcp: true,
169
+ modelKey: 'model',
170
+ modelPriority: 1,
155
171
  precedence: 'Global config. Merged with the project config, not replaced — later configs override earlier ones only for conflicting keys. MCP servers live under the "mcp" key.',
156
172
  docsUrl: OPENCODE_CONFIG_DOCS,
157
173
  },
@@ -165,6 +181,8 @@ export const CONFIG_FILES = [
165
181
  format: 'jsonc',
166
182
  tracked: 'tracked',
167
183
  holdsMcp: true,
184
+ modelKey: 'model',
185
+ modelPriority: 2,
168
186
  precedence: 'Merged over the global config per conflicting key (not a wholesale replace). MCP servers live under the "mcp" key. Runs read the committed copy.',
169
187
  docsUrl: OPENCODE_CONFIG_DOCS,
170
188
  },