chainlesschain 0.162.158 → 0.162.160

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 (219) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-BwpTJTN_.js → AIOps-CkRHjW8e.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BtQOoo3l.js → ActionButton-BP3MeNi2.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-Duf_rXZa.js → Analytics-CjbjQsOr.js} +2 -2
  6. package/src/assets/web-panel/assets/{AppLayout-XQK3wjvB.js → AppLayout-i0adH1M8.js} +5 -5
  7. package/src/assets/web-panel/assets/Artifacts-CCCG2GOU.js +1 -0
  8. package/src/assets/web-panel/assets/{Audit-DNjOGQLh.js → Audit-DrsgvwHC.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-FH9RAfB5.js → BackgroundAgents-DkXNkbZM.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-ZIbrR4-U.js → Backup-DarTWCex.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-DSt3NaND.js → BaseInput-DaDzhcto.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-CY-wvbjv.js → Chat-C4EzGw6V.js} +5 -5
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-lkavIWMS.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-8JVadE_B.js → Checkbox-gddNgaQi.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CN83nPYI.js → Codegen-BKldFWf9.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-xPSvqdN8.js → Col-ChR-brDs.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-D78cnIjG.js → Community-DlHtZX86.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-CSw6Csbp.js → Compact-BAhfcBpC.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-E_HhjcYR.js → Compliance-gIrKkm6m.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DybeQjmm.js → Cowork-BYnzLBO3.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-DS0BJeLY.js → Cron-ByUDIljI.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-BOwVgkbs.js → Crosschain-DOdNbHFp.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DRUr9YuX.js → DID-BJHaNWD2.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-Cht-yUKW.js → Dashboard-Drm_tClz.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BLr_EJ9X.js → Dropdown-CA1WLzGN.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-Drexuh5W.js → EmailListRenderer-Di1SKjNO.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D9Q2Kq63.js → FamilyGuardDashboard-44Ve7ZFe.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-C-Z1xI-T.js → Federation-CubPwv_N.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-DLHPMkQF.js → FormItemContext-CsUFe5bU.js} +1 -1
  30. package/src/assets/web-panel/assets/GenericCardRenderer-D7xRjPjZ.js +1 -0
  31. package/src/assets/web-panel/assets/{Git-syATcaBt.js → Git-D-Qx9dhO.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CYe_r8Zf.js → Governance-_YMYaU4n.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-GWxErB7k.js → Inference-J7Yzh-K_.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-qQvVCZoi.js → KnowledgeGraph-D37iI_Mo.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-BenAU2W8.js → Logs-oMTSYfGY.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-7agE3Or1.js → MarkdownRenderer-BqaPmC0W.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-D4Jn5fpD.js → Marketplace-DKUqYDaF.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-DtAwoqiQ.js → McpTools-BEv3Gx61.js} +4 -4
  39. package/src/assets/web-panel/assets/{Memory-BI_O50I8.js → Memory-CtA8XD2y.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-CQWE2lqx.js → MobileBridge-ug7c1mMj.js} +1 -1
  41. package/src/assets/web-panel/assets/MobileProjects-BpX5g9It.js +1 -0
  42. package/src/assets/web-panel/assets/{Mtc-Dnr16qsn.js → Mtc-WJaMs4i2.js} +2 -2
  43. package/src/assets/web-panel/assets/{MtcAudit-CQ5Xe4-a.js → MtcAudit-DXnK_-ru.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-Bjr8O-wy.js → Multisig-C4Ev7726.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-CEe-KirU.js → NLProgramming-BMFb9_zk.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-spKJIKF9.js → Notes-Bl93nvBX.js} +4 -4
  47. package/src/assets/web-panel/assets/{NotificationSettings-DRp83LFG.js → NotificationSettings-BN2W5cl6.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-h1A0XB2a.js → OrderTableRenderer-Dxc9oN4o.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-BlgB0IYg.js → Organization-CAs48637.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-a_35HqZI.js → Overflow-Bhq27Zoc.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CSNHCNPC.js → P2P-D61-2542.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-C8M1JH-1.js → PdhVaultBrowser-C1j4iUxz.js} +5 -5
  53. package/src/assets/web-panel/assets/{Permissions-DmjJi9Ms.js → Permissions-rJ2-fScM.js} +3 -3
  54. package/src/assets/web-panel/assets/{PersonalDataHub-DfuwRyf4.js → PersonalDataHub-DFIlTok6.js} +2 -2
  55. package/src/assets/web-panel/assets/{Pipeline-B2-S4ekE.js → Pipeline-BjIgEWoZ.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-B1dOiBLC.js → Privacy-BQoH5wcX.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-_pNmc-DX.js → ProjectInit-CYR_-_Ub.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-DmwG2Ii1.js → ProjectSettings-nkatCq-9.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-SS9uZKCl.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-C6HSjg1d.js → Providers-BnKM9fsF.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-CrDmS7l1.js → QrScannerModal-Cfe82dbz.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-CfKvWt-x.js → QuickAsk-r1RbPufV.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-DMa6Kuzv.js → Recommend-CjCbM2WE.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DrktUo5x.js → RemoteSession-BuMGPH6V.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-BTPQ1vjL.js → Reputation-Bmj3NY1F.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-B6Q7QkMG.js → Row-BIsNcE_1.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-B1IJhAmX.js → RssFeed-BObmojD2.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-xbea1kGD.js → Search-BRmbkQNS.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-7rs0cO3F.js → Security-_rF3DRpY.js} +2 -2
  70. package/src/assets/web-panel/assets/{Services-0fjixK0S.js → Services-D0If9ZV4.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-B_rVq9Cu.js → Skeleton-o7zIksUg.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-C5uM90b9.js → Skills-oUR7zi9u.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-U4pYCIZH.js → Sla-fqKyGi03.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-Cdz4yTWx.js → SpeechSettings-B1wZ_gxx.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-Me3aetHv.js → SyncSettings-B3qJWYXq.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-Cf6aNkL_.js → Tasks-BH5_dUfr.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CYatk4tU.js → Templates-CCIVpjRP.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-DIMKLw7o.js → Tenant-2GZtTGnB.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-C_cp-uSJ.js → Terminal-BlMkfs_u.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-cUPVNADp.js → TimelineRenderer-U6hi5OMc.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-CiaEIXVf.js → Tokens-C-_BerGJ.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-DB1WU5lQ.js → Trigger-DaKzBgN3.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-Cfht9Ijy.js → Trust-CLvcsco3.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-K3P4Vt9S.js → UkeySign-BFn_Y1zZ.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-DWjhjXRh.js → VideoEditing-B0V18dLT.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-D9-Q1Kan.js → Wallet-BbmP7Imu.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-BDszy-oV.js → WebAuthn-Dewj_0kt.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-DIhij4rA.js → WorkflowEditor-DOxz3Lwa.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-D7VCiKbh.js → chat-B1OIpZnh.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BvOd9pVn.js → colors-CSGNVdri.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-DoqXBiAO.js → compact-item-8S0vcg0u.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-CrKRzUtp.js → createContext-vZyc27TN.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DYEZcY55.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-BWAev4WC.js → hasIn-DWw3-UhA.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DvDOpsJB.js → index-B4pP2ycr.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-oY45XrkG.js → index-BDHyovnK.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CmJ6xKBO.js → index-BKEmQQvR.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BoYrS_L2.js → index-BQssf0EQ.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-ww1QtLnX.js → index-BZnauCqN.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BWWsaimP.js → index-BdyokEau.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CoD31Ndm.js → index-BeBv896m.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DlGu7As6.js → index-BjC-TrOb.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-zH-tuuGZ.js → index-BkWd6YL7.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CEXfKSiI.js → index-BoIPHP4R.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CEPHMSih.js → index-BuB5P0TR.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-PDxGjKRu.js → index-BwKrTVV0.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BkgnGX7v.js → index-C6r27A-o.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DV-Rfmfx.js → index-CB2MOS_8.js} +3 -3
  109. package/src/assets/web-panel/assets/{index-KR1-Em9C.js → index-CFQWZvak.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-8g5TJCZ3.js → index-CI3slBKI.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BCyP071m.js → index-CJgKP2cm.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CSb-tnIo.js → index-CLPr2vC_.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-1poMpMU0.js → index-CbZqw7pg.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BZGk8AbZ.js → index-CfEvacz7.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BXyl8O23.js → index-CwXBblm-.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BHOcVYrx.js → index-D1i_8oop.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Bq_ctRpz.js → index-D8qXVfoV.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-gmxqu5Kk.js → index-DKwl1AkQ.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-D23L1V76.js → index-DLAvUtOH.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CDGLdn12.js → index-DLgkAhEE.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-YGDy7nNq.js → index-DPgY5GLy.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Cx7M7PSF.js → index-Dc40pX3F.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-JzUmJMvn.js → index-DcfLXAW7.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-HwHdTusY.js → index-DeCS12Mh.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B30NvR21.js → index-Dg0Izipr.js} +1 -1
  126. package/src/assets/web-panel/assets/index-DmVFfcNR.js +1 -0
  127. package/src/assets/web-panel/assets/{index-B0vGEbJT.js → index-DtHWHJnj.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Bf9YlbDn.js → index-Q6oyLnKC.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Bj7EgmOp.js → index-dxocDVD_.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-ISvPZ05r.js → index-t-q3rkVm.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-C5kRmj3P.js → index-tr1x96W9.js} +1 -1
  132. package/src/assets/web-panel/assets/index-x7YyhMUa.js +1 -0
  133. package/src/assets/web-panel/assets/{index-BN9m4Ux2.js → index-xx5M5Rbj.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-XW-OR3mL.js → initDefaultProps-Di5YFId0.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-CeuEHh20.js → motion-BVSN0aeL.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-Dva79Keg.js → move-DHNiaP2l.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-C0B6bD2j.js → mtc-parser-xJPf3gQD.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-AkZvO-a2.js → omit-C7qzUdkN.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-B4r55qGc.js → pickAttrs-pSpjg3Le.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-BLH-z7YE.js → placementArrow-cs_jL_UC.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-ksEGZ2Wf.js → responsiveObserve-DkS_Zs4r.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-Cth4OD1Z.js → slide-B5O1Kpxo.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-9S83ezxw.js → statusUtils-BX02GnZp.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-7yQmQGZ4.js → styleChecker-EmBYRftd.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-DpGnMmPc.js → useFlexGapSupport-ZGzN1cU8.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-C4zDZIXH.js → useFs-CfP7M1m7.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-CoLICdUZ.js → usePersonalDataHub-CbIPHgNh.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-CKyH-35X.js → vnode-7xh0If_O.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-DRDGit17.js → zoom-DmitvTR2.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-manifest.json +17 -3
  152. package/src/commands/agent.js +72 -6
  153. package/src/commands/background-session.js +173 -3
  154. package/src/commands/browse.js +86 -0
  155. package/src/commands/cloud.js +232 -0
  156. package/src/commands/doctor.js +61 -6
  157. package/src/commands/mcp.js +107 -0
  158. package/src/commands/plugin.js +63 -1
  159. package/src/commands/routine.js +367 -0
  160. package/src/commands/session.js +396 -0
  161. package/src/data/changelog.json +12 -2
  162. package/src/harness/jsonl-session-store.js +152 -3
  163. package/src/harness/mcp-client.js +50 -0
  164. package/src/harness/session-index.js +295 -0
  165. package/src/harness/session-mirror.js +142 -0
  166. package/src/harness/transcript-integrity.js +182 -0
  167. package/src/index.js +8 -0
  168. package/src/lib/agent-sandbox.js +68 -0
  169. package/src/lib/agents.js +12 -4
  170. package/src/lib/api-key-helper.js +62 -0
  171. package/src/lib/background-agent-supervisor.js +158 -2
  172. package/src/lib/channels/channel-manager.js +126 -0
  173. package/src/lib/channels/telegram-channel.js +112 -0
  174. package/src/lib/channels/webhook-channel.js +140 -0
  175. package/src/lib/chrome-connector.js +386 -0
  176. package/src/lib/cloud/bundle.js +110 -0
  177. package/src/lib/cloud/cloud-client.js +152 -0
  178. package/src/lib/computer-use/authorization.js +173 -0
  179. package/src/lib/computer-use/computer-use-server.js +276 -0
  180. package/src/lib/computer-use/control-backend.js +150 -0
  181. package/src/lib/dependency-install-policy.js +130 -0
  182. package/src/lib/doctor-checkup.js +652 -0
  183. package/src/lib/exit-codes.cjs +77 -0
  184. package/src/lib/headless-manifest.js +175 -0
  185. package/src/lib/hook-runner.cjs +70 -4
  186. package/src/lib/ide-context-redaction.js +130 -0
  187. package/src/lib/ide-context.js +89 -13
  188. package/src/lib/jsonl-session-store.js +6 -0
  189. package/src/lib/llm-config-defaults.js +24 -8
  190. package/src/lib/lsp/lsp-server-registry.js +48 -21
  191. package/src/lib/plugin-runtime/governance.js +174 -0
  192. package/src/lib/pr-link-ledger.js +221 -0
  193. package/src/lib/project-mcp-trust.js +87 -0
  194. package/src/lib/routine-store.js +352 -0
  195. package/src/lib/sensitive-file-guard.js +51 -0
  196. package/src/lib/session-store-guard.js +40 -0
  197. package/src/lib/session-usage.js +318 -2
  198. package/src/lib/sub-agent-context.js +30 -3
  199. package/src/repl/agent-repl.js +361 -3
  200. package/src/repl/bg-dashboard.js +355 -0
  201. package/src/repl/fast-mode.js +103 -0
  202. package/src/repl/fullscreen-tui.js +197 -0
  203. package/src/repl/slash-command-registry.js +11 -3
  204. package/src/repl/voice-dictation.js +132 -0
  205. package/src/runtime/agent-core.js +344 -7
  206. package/src/runtime/coding-agent-contract-shared.cjs +107 -2
  207. package/src/runtime/coding-agent-policy.cjs +17 -0
  208. package/src/runtime/headless-runner.js +137 -14
  209. package/src/runtime/headless-stream.js +43 -9
  210. package/src/runtime/mcp-config.js +32 -1
  211. package/src/runtime/policies/agent-policy.js +3 -0
  212. package/src/assets/web-panel/assets/Artifacts-DQvJoQ6E.js +0 -1
  213. package/src/assets/web-panel/assets/ChatBubbleRenderer-BAV9V-t-.js +0 -1
  214. package/src/assets/web-panel/assets/GenericCardRenderer-DxxEdn2r.js +0 -1
  215. package/src/assets/web-panel/assets/MobileProjects-CVtTqgtg.js +0 -1
  216. package/src/assets/web-panel/assets/Projects-COATmHxF.js +0 -1
  217. package/src/assets/web-panel/assets/devWarning-nDB--2xr.js +0 -1
  218. package/src/assets/web-panel/assets/index-B1_pRTtB.js +0 -1
  219. package/src/assets/web-panel/assets/index-TMM9FuW-.js +0 -1
@@ -0,0 +1,367 @@
1
+ /**
2
+ * `cc routine` — named scheduled/triggered agent tasks with run history
3
+ * (gap-2026-07-11 P1#8; Claude-Code Routines parity, self-hosted).
4
+ *
5
+ * cc routine create "nightly report" --prompt "..." --cron "0 3 * * *"
6
+ * cc routine create "deploy watch" --prompt "..." --github acme/app --events PushEvent
7
+ * cc routine create "one shot" --prompt "..." --at 2026-07-12T09:00:00Z
8
+ * cc routine create "ci hook" --prompt "..." --webhook
9
+ * cc routine list · enable/disable · trigger <id> · run · runs [id] · logs <runId> · remove <id>
10
+ *
11
+ * `cc routine run` is the driver (fire due cron/once + poll github) — run it
12
+ * periodically (`cc loop --every 1m -- cc routine run`, system cron, or an
13
+ * agenda wakeup), exactly like `cc agenda run`.
14
+ */
15
+
16
+ import { spawn, execFile } from "node:child_process";
17
+ import { readFileSync, existsSync } from "node:fs";
18
+ import { fileURLToPath } from "node:url";
19
+ import chalk from "chalk";
20
+ import { logger } from "../lib/logger.js";
21
+
22
+ const BIN_PATH = fileURLToPath(
23
+ new URL("../../bin/chainlesschain.js", import.meta.url),
24
+ );
25
+
26
+ async function loadStore() {
27
+ const { RoutineStore } = await import("../lib/routine-store.js");
28
+ return new RoutineStore();
29
+ }
30
+
31
+ /** Production runner: `cc agent -p <prompt> --output-format json`. */
32
+ function defaultRunAgent({ prompt }) {
33
+ return new Promise((resolve) => {
34
+ const child = spawn(
35
+ process.execPath,
36
+ [BIN_PATH, "agent", "-p", prompt, "--output-format", "json"],
37
+ { windowsHide: true },
38
+ );
39
+ let out = "";
40
+ let err = "";
41
+ child.stdout?.setEncoding("utf8");
42
+ child.stderr?.setEncoding("utf8");
43
+ child.stdout?.on("data", (d) => (out += d));
44
+ child.stderr?.on("data", (d) => (err += d));
45
+ child.on("error", (error) =>
46
+ resolve({ exitCode: -1, output: `spawn error: ${error.message}` }),
47
+ );
48
+ child.on("close", (code) => {
49
+ let usage = null;
50
+ let costUsd;
51
+ let resultText = "";
52
+ try {
53
+ // result envelope is the last JSON line on stdout
54
+ const lines = out.split("\n").filter((l) => l.trim());
55
+ const envelope = JSON.parse(lines[lines.length - 1]);
56
+ usage = envelope.usage || null;
57
+ costUsd = Number(envelope.total_cost_usd ?? envelope.costUsd);
58
+ resultText = envelope.result || "";
59
+ } catch {
60
+ /* non-JSON output still recorded verbatim */
61
+ }
62
+ resolve({
63
+ exitCode: code ?? -1,
64
+ output: resultText || out || err,
65
+ usage,
66
+ costUsd: Number.isFinite(costUsd) ? costUsd : undefined,
67
+ });
68
+ });
69
+ });
70
+ }
71
+
72
+ /** Production github events fetch via gh CLI. */
73
+ function defaultFetchEvents(repo) {
74
+ return new Promise((resolve) => {
75
+ execFile(
76
+ "gh",
77
+ ["api", `repos/${repo}/events`, "--paginate=false"],
78
+ { encoding: "utf8", timeout: 8000, windowsHide: true },
79
+ (err, stdout) => {
80
+ if (err) return resolve([]);
81
+ try {
82
+ const rows = JSON.parse(stdout);
83
+ resolve(
84
+ (Array.isArray(rows) ? rows : []).map((r) => ({
85
+ id: r.id,
86
+ type: r.type,
87
+ })),
88
+ );
89
+ } catch {
90
+ resolve([]);
91
+ }
92
+ },
93
+ );
94
+ });
95
+ }
96
+
97
+ function describeTrigger(routine) {
98
+ const t = routine.trigger || {};
99
+ if (t.kind === "cron") return `cron ${t.cron}`;
100
+ if (t.kind === "once") return `once ${new Date(t.at).toISOString()}`;
101
+ if (t.kind === "github")
102
+ return `github ${t.repo}${t.events?.length ? ` (${t.events.join(",")})` : ""}`;
103
+ return "webhook (cc routine trigger)";
104
+ }
105
+
106
+ export function registerRoutineCommand(program) {
107
+ const routine = program
108
+ .command("routine")
109
+ .description(
110
+ "Named scheduled/triggered agent tasks with run history (cron/once/webhook/github)",
111
+ );
112
+
113
+ routine
114
+ .command("create <name>")
115
+ .description(
116
+ "Create a routine (exactly one of --cron/--at/--webhook/--github)",
117
+ )
118
+ .requiredOption("--prompt <text>", "Agent prompt to run")
119
+ .option("--cron <expr>", "5-field cron schedule (driver-fired)")
120
+ .option("--at <time>", "One-off ISO time / epoch ms (driver-fired)")
121
+ .option("--webhook", "Fire externally via `cc routine trigger <id>`")
122
+ .option(
123
+ "--github <repo>",
124
+ "Fire on new GitHub events for owner/name (driver-polled via gh)",
125
+ )
126
+ .option(
127
+ "--events <list>",
128
+ "GitHub event types filter (e.g. PushEvent,PullRequestEvent)",
129
+ )
130
+ .option("--json", "Output as JSON")
131
+ .action(async (name, options) => {
132
+ try {
133
+ const picked = [
134
+ options.cron && "cron",
135
+ options.at && "once",
136
+ options.webhook && "webhook",
137
+ options.github && "github",
138
+ ].filter(Boolean);
139
+ if (picked.length !== 1) {
140
+ throw new Error(
141
+ "pick exactly one trigger: --cron <expr> | --at <time> | --webhook | --github <repo>",
142
+ );
143
+ }
144
+ const trigger =
145
+ picked[0] === "cron"
146
+ ? { kind: "cron", cron: options.cron }
147
+ : picked[0] === "once"
148
+ ? { kind: "once", at: options.at }
149
+ : picked[0] === "github"
150
+ ? {
151
+ kind: "github",
152
+ repo: options.github,
153
+ events: options.events
154
+ ? options.events.split(",").map((s) => s.trim())
155
+ : [],
156
+ }
157
+ : { kind: "webhook" };
158
+ const store = await loadStore();
159
+ const created = store.create({ name, prompt: options.prompt, trigger });
160
+ if (options.json) return console.log(JSON.stringify(created, null, 2));
161
+ logger.success(
162
+ `Created routine ${created.id} (${describeTrigger(created)})`,
163
+ );
164
+ if (trigger.kind === "webhook") {
165
+ logger.log(
166
+ chalk.gray(` fire it with: cc routine trigger ${created.id}`),
167
+ );
168
+ } else {
169
+ logger.log(chalk.gray(" driver: run `cc routine run` periodically"));
170
+ }
171
+ } catch (err) {
172
+ logger.error(err.message);
173
+ process.exitCode = 1;
174
+ }
175
+ });
176
+
177
+ routine
178
+ .command("list", { isDefault: true })
179
+ .description("List routines with run/cost summaries")
180
+ .option("--json", "Output as JSON")
181
+ .action(async (options) => {
182
+ try {
183
+ const store = await loadStore();
184
+ const routines = store.list().map((r) => ({
185
+ ...r,
186
+ summary: store.summarize(r.id),
187
+ }));
188
+ if (options.json) return console.log(JSON.stringify(routines, null, 2));
189
+ if (routines.length === 0) {
190
+ logger.log(
191
+ chalk.gray("No routines. Create one with `cc routine create`."),
192
+ );
193
+ return;
194
+ }
195
+ for (const r of routines) {
196
+ const state = r.enabled ? chalk.green("on ") : chalk.gray("off");
197
+ const s = r.summary;
198
+ const cost = s.costUsd ? ` $${s.costUsd.toFixed(4)}` : "";
199
+ logger.log(
200
+ `${state} ${r.id} ${chalk.bold(r.name)} ${chalk.gray(describeTrigger(r))}`,
201
+ );
202
+ logger.log(
203
+ chalk.gray(
204
+ ` runs ${s.totalRuns} (${s.ok} ok, ${s.failed} failed${s.running ? `, ${s.running} running` : ""})${cost}`,
205
+ ),
206
+ );
207
+ }
208
+ } catch (err) {
209
+ logger.error(err.message);
210
+ process.exitCode = 1;
211
+ }
212
+ });
213
+
214
+ routine
215
+ .command("enable <id>")
216
+ .description("Enable a routine")
217
+ .action(async (id) => {
218
+ try {
219
+ const store = await loadStore();
220
+ const r = store.setEnabled(id, true);
221
+ logger.success(`Enabled ${r.id} (${r.name})`);
222
+ } catch (err) {
223
+ logger.error(err.message);
224
+ process.exitCode = 1;
225
+ }
226
+ });
227
+
228
+ routine
229
+ .command("disable <id>")
230
+ .description("Disable a routine (kept, never fires)")
231
+ .action(async (id) => {
232
+ try {
233
+ const store = await loadStore();
234
+ const r = store.setEnabled(id, false);
235
+ logger.success(`Disabled ${r.id} (${r.name})`);
236
+ } catch (err) {
237
+ logger.error(err.message);
238
+ process.exitCode = 1;
239
+ }
240
+ });
241
+
242
+ routine
243
+ .command("remove <id>")
244
+ .description("Delete a routine (run history is kept)")
245
+ .action(async (id) => {
246
+ try {
247
+ const store = await loadStore();
248
+ const r = store.remove(id);
249
+ logger.success(`Removed ${r.id} (${r.name})`);
250
+ } catch (err) {
251
+ logger.error(err.message);
252
+ process.exitCode = 1;
253
+ }
254
+ });
255
+
256
+ routine
257
+ .command("trigger <id>")
258
+ .description("Fire a routine NOW (the webhook/API entry point)")
259
+ .option("--json", "Output as JSON")
260
+ .action(async (id, options) => {
261
+ try {
262
+ const store = await loadStore();
263
+ const r = store.get(id);
264
+ if (!r) throw new Error(`routine not found: ${id}`);
265
+ const { fireRoutine } = await import("../lib/routine-store.js");
266
+ const runId = await fireRoutine(store, r, defaultRunAgent, {
267
+ trigger: "manual",
268
+ });
269
+ const run = store.listRuns({ routineId: r.id, limit: 1 })[0];
270
+ if (options.json) return console.log(JSON.stringify(run, null, 2));
271
+ logger.success(`Fired ${r.id} → ${runId} (${run?.status})`);
272
+ logger.log(chalk.gray(` log: cc routine logs ${runId}`));
273
+ } catch (err) {
274
+ logger.error(err.message);
275
+ process.exitCode = 1;
276
+ }
277
+ });
278
+
279
+ routine
280
+ .command("run")
281
+ .description("Driver: fire due cron/once routines and poll github triggers")
282
+ .option("--json", "Output as JSON")
283
+ .action(async (options) => {
284
+ try {
285
+ const store = await loadStore();
286
+ const { fireRoutine, pollGithubRoutine } =
287
+ await import("../lib/routine-store.js");
288
+ const fired = [];
289
+ for (const r of store.due()) {
290
+ fired.push({
291
+ routine: r.id,
292
+ runId: await fireRoutine(store, r, defaultRunAgent, {
293
+ trigger: r.trigger.kind,
294
+ }),
295
+ });
296
+ }
297
+ for (const r of store.githubRoutines()) {
298
+ const runs = await pollGithubRoutine(store, r, {
299
+ fetchEvents: defaultFetchEvents,
300
+ runAgent: defaultRunAgent,
301
+ });
302
+ for (const runId of runs) fired.push({ routine: r.id, runId });
303
+ }
304
+ if (options.json)
305
+ return console.log(JSON.stringify({ fired }, null, 2));
306
+ if (fired.length === 0) {
307
+ logger.log(chalk.gray("Nothing due."));
308
+ } else {
309
+ for (const f of fired) logger.log(`fired ${f.routine} → ${f.runId}`);
310
+ }
311
+ } catch (err) {
312
+ logger.error(err.message);
313
+ process.exitCode = 1;
314
+ }
315
+ });
316
+
317
+ routine
318
+ .command("runs [id]")
319
+ .description("Run history (all routines, or one)")
320
+ .option("-n, --limit <n>", "Max rows", "20")
321
+ .option("--json", "Output as JSON")
322
+ .action(async (id, options) => {
323
+ try {
324
+ const store = await loadStore();
325
+ const routineId = id ? (store.get(id)?.id ?? id) : null;
326
+ const runs = store.listRuns({
327
+ routineId,
328
+ limit: Math.max(1, Number(options.limit) || 20),
329
+ });
330
+ if (options.json) return console.log(JSON.stringify(runs, null, 2));
331
+ if (runs.length === 0) return logger.log(chalk.gray("No runs."));
332
+ for (const run of runs) {
333
+ const color =
334
+ run.status === "ok"
335
+ ? chalk.green
336
+ : run.status === "running"
337
+ ? chalk.cyan
338
+ : chalk.red;
339
+ const cost = Number.isFinite(run.costUsd)
340
+ ? ` $${run.costUsd.toFixed(4)}`
341
+ : "";
342
+ logger.log(
343
+ `${color((run.status || "?").padEnd(8))} ${run.runId} ${run.routineId} ${new Date(run.startedAt).toISOString()}${cost}`,
344
+ );
345
+ if (run.summary) logger.log(chalk.gray(` ${run.summary}`));
346
+ }
347
+ } catch (err) {
348
+ logger.error(err.message);
349
+ process.exitCode = 1;
350
+ }
351
+ });
352
+
353
+ routine
354
+ .command("logs <runId>")
355
+ .description("Print a run's full agent output")
356
+ .action(async (runId) => {
357
+ try {
358
+ const store = await loadStore();
359
+ const file = store.logFile(runId);
360
+ if (!existsSync(file)) throw new Error(`no log for run: ${runId}`);
361
+ process.stdout.write(readFileSync(file, "utf-8"));
362
+ } catch (err) {
363
+ logger.error(err.message);
364
+ process.exitCode = 1;
365
+ }
366
+ });
367
+ }