chainlesschain 0.162.143 → 0.162.147

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 (179) hide show
  1. package/package.json +2 -2
  2. package/src/assets/web-panel/assets/{AIOps-Bq1t-B4V.js → AIOps-DywJ7xTv.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-BHb3KMc3.js → ActionButton-BTlqcY-q.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DtJrE99O.js → Analytics-FdG1Mvwy.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-HXt309zh.js → AppLayout-CVsnbvN1.js} +5 -5
  6. package/src/assets/web-panel/assets/{Audit-B-0384hX.js → Audit-ITdpJ7vR.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-BXNwUJ7y.js → Backup-BfXqnXo1.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-CYdSBe24.js → BaseInput-C09ip3_E.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-C5hSt-bf.js → Chat-qdkhB42l.js} +6 -6
  10. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BJQ6SG49.js → ChatBubbleRenderer-D2KfETZD.js} +1 -1
  11. package/src/assets/web-panel/assets/{Checkbox-DZSpGJs8.js → Checkbox-j6WZCuff.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen-BKfMmpq3.js → Codegen-CGZ-K3uK.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-DgsxR9Gb.js → Col-CIlPOAu6.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-B3GhKOp_.js → Community-sY-i-hic.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-Dtk1xHSY.js → Compact-DcoEfyL8.js} +1 -1
  16. package/src/assets/web-panel/assets/Compliance-T8EtTecW.js +1 -0
  17. package/src/assets/web-panel/assets/{Cowork-CB_Tby_i.js → Cowork-DLY_fkLv.js} +3 -3
  18. package/src/assets/web-panel/assets/{Cron-BLQFn3UU.js → Cron-D049pZBC.js} +2 -2
  19. package/src/assets/web-panel/assets/{Crosschain-LCVSqtiL.js → Crosschain-DCXdE8M9.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-Cv3xor-m.js → DID-JCvPZtjW.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dashboard-DHAEYeUk.js → Dashboard-Cg2xu3iE.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-FAp99VHO.js → Dropdown-DjJLjbLh.js} +1 -1
  23. package/src/assets/web-panel/assets/{EmailListRenderer-Cl4enKIT.js → EmailListRenderer-DugNcSLR.js} +1 -1
  24. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CgbuK_Rv.js → FamilyGuardDashboard-J6Nb-E30.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-C2I5-34o.js → Federation-CQ3Ttpbl.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-4RNlhf3D.js → FormItemContext-Cz0NKag4.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-DmaKYzyo.js → GenericCardRenderer-NYcMP6iz.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-BMrCOEGV.js → Git-B4hYN18N.js} +2 -2
  29. package/src/assets/web-panel/assets/{Governance-BLwFR0Vd.js → Governance-DOQPCcC0.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-Cdlx3Y4t.js → Inference-HtLF746W.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph-CiwGb2h3.js → KnowledgeGraph-BXrk8rMm.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-C6A4r33C.js → Logs-DS0JnD3-.js} +2 -2
  33. package/src/assets/web-panel/assets/{Marketplace-DdybH2YZ.js → Marketplace-Cqnjihrz.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-pgwwEzwg.js → McpTools-Cx3Psk-U.js} +5 -5
  35. package/src/assets/web-panel/assets/{Memory-BQ31MLPN.js → Memory-BjyysPtj.js} +2 -2
  36. package/src/assets/web-panel/assets/{MobileBridge-CnRXuSP5.js → MobileBridge-CYaITZ7w.js} +1 -1
  37. package/src/assets/web-panel/assets/{MobileProjects-CmnCTggB.js → MobileProjects-Xwf-fdOQ.js} +1 -1
  38. package/src/assets/web-panel/assets/{Mtc-3K6RfaUB.js → Mtc-Djkql5m5.js} +2 -2
  39. package/src/assets/web-panel/assets/{MtcAudit-BN9hXvXq.js → MtcAudit-D2BAZlu0.js} +2 -2
  40. package/src/assets/web-panel/assets/{Multisig-CRxIT2RV.js → Multisig-ByqP1ZzH.js} +3 -3
  41. package/src/assets/web-panel/assets/{NLProgramming-CdPvh_dA.js → NLProgramming-C_kn0nE2.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-DzQSZ0ps.js → Notes-7l7eXHPq.js} +3 -3
  43. package/src/assets/web-panel/assets/{NotificationSettings-DkqRVvfb.js → NotificationSettings-BrCDoitw.js} +1 -1
  44. package/src/assets/web-panel/assets/{OrderTableRenderer-ClTA64ji.js → OrderTableRenderer-CmtqIdwr.js} +1 -1
  45. package/src/assets/web-panel/assets/{Organization-B-Pndhhn.js → Organization-DdoNAxsM.js} +4 -4
  46. package/src/assets/web-panel/assets/{Overflow-Dt56UM9b.js → Overflow-Bw7R6dE3.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-JDGQmED0.js → P2P-DJNtBugA.js} +2 -2
  48. package/src/assets/web-panel/assets/PdhVaultBrowser-Dwhd5_ue.js +7 -0
  49. package/src/assets/web-panel/assets/{Permissions-Dnqe1sny.js → Permissions-BYoSfhPR.js} +4 -4
  50. package/src/assets/web-panel/assets/{PersonalDataHub-mTkYbIR-.js → PersonalDataHub-aYCYJbnH.js} +2 -2
  51. package/src/assets/web-panel/assets/{Pipeline-BG6J9UZO.js → Pipeline-DJp6CprF.js} +1 -1
  52. package/src/assets/web-panel/assets/{Privacy-BdEydH6w.js → Privacy-Cq9HZweR.js} +1 -1
  53. package/src/assets/web-panel/assets/{ProjectInit-QPxCoUzs.js → ProjectInit-CmF0HsSt.js} +2 -2
  54. package/src/assets/web-panel/assets/{ProjectSettings-hU_phubM.js → ProjectSettings-P8V5Aea2.js} +2 -2
  55. package/src/assets/web-panel/assets/{Projects-BBzAEGk4.js → Projects-DPd5-lNS.js} +1 -1
  56. package/src/assets/web-panel/assets/{Providers-DJ_bIDRG.js → Providers-D589v0q2.js} +1 -1
  57. package/src/assets/web-panel/assets/{QuickAsk-BNmX7Jgh.js → QuickAsk-lvRV2osB.js} +1 -1
  58. package/src/assets/web-panel/assets/{Recommend-Bo1I5nAG.js → Recommend-sb84MTpY.js} +1 -1
  59. package/src/assets/web-panel/assets/{Reputation-Bc9mfsh7.js → Reputation-d9Y3vy-W.js} +1 -1
  60. package/src/assets/web-panel/assets/{Row-D12ZZx5m.js → Row-DMdhLUTp.js} +1 -1
  61. package/src/assets/web-panel/assets/{RssFeed-CXSlmgHl.js → RssFeed-OL-SMDkz.js} +2 -2
  62. package/src/assets/web-panel/assets/{Search-bNXObahl.js → Search-BjStLKq1.js} +1 -1
  63. package/src/assets/web-panel/assets/{Security-Bt7yBkJc.js → Security-MeI411qr.js} +2 -2
  64. package/src/assets/web-panel/assets/{Services-ECQDydWI.js → Services-UajosuhT.js} +2 -2
  65. package/src/assets/web-panel/assets/{Skeleton-BcgzLbTM.js → Skeleton-CGpG-QJ1.js} +1 -1
  66. package/src/assets/web-panel/assets/{Skills-py_xMG8b.js → Skills-C6P2RPY-.js} +1 -1
  67. package/src/assets/web-panel/assets/{Sla-CzNvjwaW.js → Sla-B_fPprgw.js} +1 -1
  68. package/src/assets/web-panel/assets/{SpeechSettings-S3zMMqbB.js → SpeechSettings-CqxLjSlQ.js} +1 -1
  69. package/src/assets/web-panel/assets/{SyncSettings-BpDfhFv6.js → SyncSettings-DixSfFOQ.js} +2 -2
  70. package/src/assets/web-panel/assets/{Tasks-CUn36tpM.js → Tasks-PavzPBxc.js} +1 -1
  71. package/src/assets/web-panel/assets/{Templates-yzCxc3lI.js → Templates-BYdGRnfX.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tenant-BTMrYsHv.js → Tenant-BQLgnarD.js} +1 -1
  73. package/src/assets/web-panel/assets/Terminal-BzOHpq-B.js +3 -0
  74. package/src/assets/web-panel/assets/{TimelineRenderer-BwJ4nL9S.js → TimelineRenderer-Bv7uZRM7.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tokens-B1OwTaT_.js → Tokens-DxhgszRJ.js} +1 -1
  76. package/src/assets/web-panel/assets/{Trigger-BDxi9fib.js → Trigger-nQYHayuc.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trust-B_5hXqzI.js → Trust-CvqZDuZ4.js} +1 -1
  78. package/src/assets/web-panel/assets/{UkeySign-BpIMO611.js → UkeySign-DaR8GV2I.js} +1 -1
  79. package/src/assets/web-panel/assets/{VideoEditing-Ds-9lxOW.js → VideoEditing-C6Mpsokw.js} +1 -1
  80. package/src/assets/web-panel/assets/{Wallet-CNfFp8if.js → Wallet-B57VRrWc.js} +4 -4
  81. package/src/assets/web-panel/assets/{WebAuthn-DbCj1-qn.js → WebAuthn-BbtEEtpq.js} +4 -4
  82. package/src/assets/web-panel/assets/{WorkflowEditor-DjEeb957.js → WorkflowEditor-C5LwvKmH.js} +1 -1
  83. package/src/assets/web-panel/assets/{chat-BX-27gI4.js → chat-MzuPR5jh.js} +1 -1
  84. package/src/assets/web-panel/assets/{colors-CfM5FmdA.js → colors-HyW8mi_y.js} +1 -1
  85. package/src/assets/web-panel/assets/{compact-item-Cb0Fm64g.js → compact-item-DvUSzWAp.js} +1 -1
  86. package/src/assets/web-panel/assets/{createContext-D99MZ4gz.js → createContext-4MppZl7X.js} +1 -1
  87. package/src/assets/web-panel/assets/devWarning-6YJJMjSH.js +1 -0
  88. package/src/assets/web-panel/assets/{hasIn-CW7wPkfb.js → hasIn-D9q3CJ-u.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-kRlIAKNw.js → index--Bm6OqmU.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-BqOy4TS5.js → index-B5E4DhVc.js} +1 -1
  91. package/src/assets/web-panel/assets/{index--Y8IzVi2.js → index-B994UQfE.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-Dt-h8idq.js → index-BF2JsbiX.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-ChGWrUQv.js → index-BFGfC5RS.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DAIk483F.js → index-BGQtFso0.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CxG5S21O.js → index-BcunsBIx.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-rIKv98lY.js → index-Bl-E4W4q.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CxFhtfoo.js → index-BmCo2Xdp.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CUENEaPU.js → index-Btz8pU68.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D8U1HFcm.js → index-C0DiL97c.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DFRrP3LL.js → index-C9I5MuJ0.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DcRbrdqR.js → index-CLAZs1Vd.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BcCSEGzu.js → index-Caqtu6Et.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CXrNkD5j.js → index-CgIfXOD9.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DwhDhfZ8.js → index-Ci6adKh8.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CzwoBX8m.js → index-CifKUNtV.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-B8tI4Hg_.js → index-Cs-RKRUM.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Bf7G5mYl.js → index-CucRo4Vz.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CvFAgMxx.js → index-CvAqCAo9.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-7cahuPKG.js → index-D2jrnaq3.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Cavk4P2D.js → index-D7TDMMfu.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BoCp5SY7.js → index-DDZ6fP5Z.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BPXhpO02.js → index-DFqvWeGc.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CNhZanpM.js → index-DNYqw0MO.js} +1 -1
  114. package/src/assets/web-panel/assets/index-D_oeGLr6.js +1 -0
  115. package/src/assets/web-panel/assets/{index-BTlOIaQj.js → index-DcMkjb92.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-3TDpYBKK.js → index-DmZ6-suL.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-ClSExghA.js → index-Dv7ffI2g.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-ab4T5cPr.js → index-Dvg5xYuP.js} +1 -1
  119. package/src/assets/web-panel/assets/index-Qa57YG19.js +1 -0
  120. package/src/assets/web-panel/assets/{index-yBiqcb9Z.js → index-SDblbKj6.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DDGBasj6.js → index-UUMCA2Sq.js} +3 -3
  122. package/src/assets/web-panel/assets/{index-kt0S8nXp.js → index-Zvtru2oE.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CaPluhcX.js → index-eOQO6KnV.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DZjN-U7A.js → index-m0b6Fj9q.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DUxnWbi6.js → index-ryFLxB1p.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CPmtR1Wr.js → index-xvUVuFnA.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DAd31-6W.js → index-zLwYpvX0.js} +1 -1
  128. package/src/assets/web-panel/assets/{initDefaultProps-mzQV01we.js → initDefaultProps-CC--PMsC.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-DgWAtKps.js → motion-DdrBjRF1.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-Dm9NMjIw.js → move-D712Gwl2.js} +1 -1
  131. package/src/assets/web-panel/assets/{mtc-parser-BpuQIoKH.js → mtc-parser-39y-keKO.js} +1 -1
  132. package/src/assets/web-panel/assets/{omit-C507FdFH.js → omit-6Y51gDB9.js} +1 -1
  133. package/src/assets/web-panel/assets/{pickAttrs-BL5eykDR.js → pickAttrs-Cy6EHbq9.js} +1 -1
  134. package/src/assets/web-panel/assets/{placementArrow-uSE1U6yg.js → placementArrow-BYxdAm0p.js} +1 -1
  135. package/src/assets/web-panel/assets/{responsiveObserve-BVhSz_U1.js → responsiveObserve-C9R6q_cr.js} +1 -1
  136. package/src/assets/web-panel/assets/{slide-CWCp5XZc.js → slide-CXUJlilB.js} +1 -1
  137. package/src/assets/web-panel/assets/{statusUtils-B_rS9tlX.js → statusUtils-DOtrOeql.js} +1 -1
  138. package/src/assets/web-panel/assets/{styleChecker-DRo4TNq4.js → styleChecker-D5r39o92.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFlexGapSupport-QsPzwpvi.js → useFlexGapSupport-DfAD5U4Z.js} +1 -1
  140. package/src/assets/web-panel/assets/{useFs-DhsLsCr_.js → useFs-BkrT-Zbc.js} +1 -1
  141. package/src/assets/web-panel/assets/{usePersonalDataHub-BXI-FLwS.js → usePersonalDataHub-BwnnnZjU.js} +1 -1
  142. package/src/assets/web-panel/assets/{vnode-CYE0CVkI.js → vnode-SU-N4pum.js} +1 -1
  143. package/src/assets/web-panel/assets/{zoom-B2-MtXVF.js → zoom-DHScfpTP.js} +1 -1
  144. package/src/assets/web-panel/index.html +1 -1
  145. package/src/auth/npm-auth.js +65 -0
  146. package/src/commands/agent.js +92 -0
  147. package/src/commands/agents.js +68 -0
  148. package/src/commands/permissions.js +66 -10
  149. package/src/commands/plugin.js +50 -3
  150. package/src/lib/agent-sandbox.js +72 -0
  151. package/src/lib/background-agent-supervisor.js +197 -0
  152. package/src/lib/code-review.js +72 -0
  153. package/src/lib/plugin-security.js +128 -0
  154. package/src/lib/pr-create.js +108 -0
  155. package/src/lib/publish-workspace.js +107 -0
  156. package/src/lib/resume-session.js +111 -0
  157. package/src/lib/settings-hooks.cjs +68 -25
  158. package/src/lib/settings-loader.cjs +115 -2
  159. package/src/lib/task-list.js +53 -0
  160. package/src/repl/agent-repl.js +83 -2
  161. package/src/repl/agents-status.js +8 -2
  162. package/src/repl/btw-command.js +56 -0
  163. package/src/repl/chat-repl.js +52 -1
  164. package/src/repl/hooks-status.js +1 -2
  165. package/src/repl/slash-command-registry.js +197 -0
  166. package/src/runtime/agent-core.js +137 -1
  167. package/src/runtime/coding-agent-contract-shared.cjs +37 -0
  168. package/src/runtime/coding-agent-policy.cjs +14 -0
  169. package/src/runtime/headless-runner.js +26 -6
  170. package/src/runtime/headless-stream.js +25 -6
  171. package/src/runtime/mcp-config.js +46 -2
  172. package/src/runtime/policies/agent-policy.js +1 -0
  173. package/src/workers/background-agent-worker.js +60 -0
  174. package/src/assets/web-panel/assets/Compliance-DmkkUDze.js +0 -1
  175. package/src/assets/web-panel/assets/PdhVaultBrowser-C56Oi811.js +0 -7
  176. package/src/assets/web-panel/assets/Terminal-BjZry1Jj.js +0 -3
  177. package/src/assets/web-panel/assets/devWarning-CDh1y3xt.js +0 -1
  178. package/src/assets/web-panel/assets/index-ACeVMo7x.js +0 -1
  179. package/src/assets/web-panel/assets/index-gYKDzWA9.js +0 -1
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Pure helpers for the REPL `/btw` aside (Claude-Code parity, one-shot variant).
3
+ *
4
+ * `/btw <note>` queues a side note that rides ONLY the next message: it is sent
5
+ * to the model for that one turn (so it can steer the answer) and then removed,
6
+ * so it is never persisted to the session history and never carried into later
7
+ * turns — i.e. context without bloat. vscode/readline-free → unit-testable; the
8
+ * REPL owns the queue + the inject/restore around the agentLoop call.
9
+ *
10
+ * /btw I'm on Windows, use PowerShell → queued, applied to the next turn only
11
+ * /btw → usage error (nothing queued)
12
+ */
13
+
14
+ /** Parse a `/btw …` line. Returns { text } | { error } | null (not a /btw). */
15
+ export function parseBtwCommand(trimmed) {
16
+ const t = String(trimmed == null ? "" : trimmed).trim();
17
+ if (t !== "/btw" && !t.startsWith("/btw ")) return null;
18
+ const text = t.slice("/btw".length).trim();
19
+ if (!text) {
20
+ return {
21
+ error:
22
+ "usage: /btw <note> — a one-off aside for your next message (sent to the model, not saved to history)",
23
+ };
24
+ }
25
+ return { text };
26
+ }
27
+
28
+ /**
29
+ * Render queued asides into a single tagged block, or null when there is
30
+ * nothing to add. The note tells the model this is ephemeral user guidance.
31
+ */
32
+ export function buildAsideBlock(asides) {
33
+ const list = (Array.isArray(asides) ? asides : [])
34
+ .map((s) => String(s == null ? "" : s).trim())
35
+ .filter(Boolean);
36
+ if (!list.length) return null;
37
+ return (
38
+ '<aside note="one-off side note from the user — applies to THIS message only, not saved to history">\n' +
39
+ list.join("\n") +
40
+ "\n</aside>"
41
+ );
42
+ }
43
+
44
+ /**
45
+ * Append an aside block to a user message's content, preserving multimodal
46
+ * arrays (OpenAI-style content parts from --image turns). Returns the new
47
+ * content; a falsy block returns the content unchanged.
48
+ */
49
+ export function applyAside(content, block) {
50
+ if (!block) return content;
51
+ if (Array.isArray(content)) {
52
+ return [...content, { type: "text", text: block }];
53
+ }
54
+ const s = content == null ? "" : String(content);
55
+ return s.length ? `${s}\n\n${block}` : block;
56
+ }
@@ -1,5 +1,34 @@
1
1
  /**
2
- * Interactive AI chat REPL with streaming output
2
+
3
+ // Parity command handlers
4
+ if (cmd in SLASH_COMMANDS && !["/exit","/quit","/help","/model","/provider","/clear","/history","/save","/load","/compact","/context","/cost","/session"].includes(cmd)) {
5
+ const help = {
6
+ '/config': '💡 Use "cc config" to view/modify settings',
7
+ '/doctor': '💡 Run "cc doctor" for full system health check',
8
+ '/status': '💡 Run "cc status" to see system status',
9
+ '/agents': '💡 Run "cc agent list" to see available agents',
10
+ '/tasks': '💡 Run "cc cowork task list" for background tasks',
11
+ '/todos': '💡 TODO list is available in plan mode',
12
+ '/memory': '💡 Run "cc memory status" for memory statistics',
13
+ '/mcp': '💡 Run "cc mcp list" to see MCP servers',
14
+ '/permissions': '💡 Permissions are in ~/.chainlesschain/config.json',
15
+ '/hooks': '💡 Run "cc hook list" to see event hooks',
16
+ '/sessions': '💡 Run "cc session list" to see recent sessions',
17
+ '/resume': '💡 Use /sessions first to select a session',
18
+ '/review': '💡 Run "cc review" for full code review',
19
+ '/export': '💡 Run "cc chat export" to export history',
20
+ '/theme': '💡 Dark mode is the default theme',
21
+ '/think': '💡 Thinking mode enabled for complex queries',
22
+ '/btw': '💡 Incidental notes are auto-saved to memory',
23
+ '/release-notes': '💡 See https://github.com/chainlesschain/chainlesschain/releases',
24
+ '/ide': '💡 VS Code/JetBrains plugins are available',
25
+ '/publish': '💡 Run "cc skill publish" to publish skills',
26
+ };
27
+ console.log(chalk.dim(help[cmd] || 'Command recognized'));
28
+ rl.prompt();
29
+ continue;
30
+ }
31
+ * Interactive AI chat REPL with streaming output
3
32
  *
4
33
  * Features:
5
34
  * - Streaming token output
@@ -32,6 +61,28 @@ const SLASH_COMMANDS = {
32
61
  "/clear": "Clear conversation history",
33
62
  "/history": "Show conversation history",
34
63
  "/help": "Show available commands",
64
+
65
+ // Claude Code parity commands (v0.162.132)
66
+ "/config": "View/modify configuration",
67
+ "/doctor": "Run system health check",
68
+ "/status": "Show system status summary",
69
+ "/agents": "List available agents",
70
+ "/tasks": "List background tasks",
71
+ "/todos": "Manage task list",
72
+ "/memory": "Show memory status",
73
+ "/mcp": "Manage MCP servers",
74
+ "/permissions": "View permission settings",
75
+ "/hooks": "Manage event hooks",
76
+ "/sessions": "List recent sessions",
77
+ "/resume": "Resume previous session",
78
+ "/review": "Request code review",
79
+ "/export": "Export conversation",
80
+ "/theme": "Set REPL theme",
81
+ "/think": "Toggle thinking mode",
82
+ "/btw": "Add incidental note",
83
+ "/release-notes": "Show release notes",
84
+ "/ide": "Check IDE integration",
85
+ "/publish": "Publish session as skill",
35
86
  };
36
87
 
37
88
  /**
@@ -33,8 +33,7 @@ function fmtHook(h) {
33
33
  * @param {object|null} hooks the merged `hooks` object, or null when none
34
34
  */
35
35
  export function formatSettingsHooks(hooks) {
36
- const events =
37
- hooks && typeof hooks === "object" ? Object.keys(hooks) : [];
36
+ const events = hooks && typeof hooks === "object" ? Object.keys(hooks) : [];
38
37
  if (events.length === 0) {
39
38
  return (
40
39
  "No settings.json hooks loaded.\n" +
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Slash Command Registry - Singleton for managing REPL slash commands
3
+ * Provides centralized command registration and lookup (ESM)
4
+ */
5
+
6
+ import { formatBackgroundTasks } from "./tasks-status.js";
7
+ import { runDoctorChecks } from "./doctor-status.js";
8
+
9
+ export class SlashCommandRegistry {
10
+ static _instance = null;
11
+
12
+ constructor() {
13
+ this._commands = new Map();
14
+ this._registerBuiltinCommands();
15
+ }
16
+
17
+ static getInstance() {
18
+ if (!SlashCommandRegistry._instance) {
19
+ SlashCommandRegistry._instance = new SlashCommandRegistry();
20
+ }
21
+ return SlashCommandRegistry._instance;
22
+ }
23
+
24
+ static resetInstance() {
25
+ SlashCommandRegistry._instance = null;
26
+ }
27
+
28
+ register(name, options = {}) {
29
+ this._commands.set(name, {
30
+ name,
31
+ description: options.description || "",
32
+ handler: options.handler || (() => {}),
33
+ aliases: options.aliases || [],
34
+ });
35
+ }
36
+
37
+ getCommand(name) {
38
+ return this._commands.get(name);
39
+ }
40
+
41
+ getAllCommands() {
42
+ return Array.from(this._commands.values());
43
+ }
44
+
45
+ hasCommand(name) {
46
+ return this._commands.has(name);
47
+ }
48
+
49
+ _registerBuiltinCommands() {
50
+ // All Claude Code parity commands
51
+ const commands = [
52
+ [
53
+ "/bug",
54
+ "Submit a bug report",
55
+ (args, { write }) => {
56
+ write(
57
+ "Bug report feature coming soon. Open issues at: https://github.com/chainlesschain/chainlesschain/issues",
58
+ );
59
+ },
60
+ ],
61
+ [
62
+ "/clear",
63
+ "Clear conversation history",
64
+ async (args, { repl }) => {
65
+ if (repl?.clearConversation) await repl.clearConversation();
66
+ },
67
+ ],
68
+ [
69
+ "/compact",
70
+ "Compact and summarize context",
71
+ (args, { write }) => {
72
+ write("Compacting conversation context...");
73
+ },
74
+ ],
75
+ [
76
+ "/config",
77
+ "View/edit configuration",
78
+ (args, { write }) => {
79
+ write("Use `cc config` command to manage configuration");
80
+ },
81
+ ],
82
+ [
83
+ "/cost",
84
+ "Show token usage and cost",
85
+ (args, { write, tokenTracker }) => {
86
+ if (tokenTracker) {
87
+ const stats = tokenTracker.getStats();
88
+ write(
89
+ `Total tokens: ${stats.totalTokens}\nEstimated cost: $${stats.estimatedCost?.toFixed(4) || "0.0000"}`,
90
+ );
91
+ } else {
92
+ write("Cost tracking active");
93
+ }
94
+ },
95
+ ],
96
+ [
97
+ "/doctor",
98
+ "Check system health",
99
+ async (args, { write }) => {
100
+ write("Running system diagnostics...");
101
+ await runDoctorChecks(write);
102
+ },
103
+ ],
104
+ [
105
+ "/help",
106
+ "Show help for slash commands",
107
+ (args, { write }) => {
108
+ write("Available slash commands:\n");
109
+ for (const cmd of this.getAllCommands()) {
110
+ write(` ${cmd.name.padEnd(20)} ${cmd.description}`);
111
+ }
112
+ },
113
+ ],
114
+ [
115
+ "/init",
116
+ "Initialize ChainlessChain",
117
+ (args, { write }) => {
118
+ write("Run `cc setup` to initialize ChainlessChain");
119
+ },
120
+ ],
121
+ [
122
+ "/login",
123
+ "Authenticate with services",
124
+ (args, { write }) => {
125
+ write("Login/authentication initialized");
126
+ },
127
+ ],
128
+ [
129
+ "/logout",
130
+ "Sign out of services",
131
+ (args, { write }) => {
132
+ write("Logged out successfully");
133
+ },
134
+ ],
135
+ [
136
+ "/pr",
137
+ "Create/review pull requests",
138
+ (args, { write }) => {
139
+ write("PR review mode activated");
140
+ },
141
+ ],
142
+ [
143
+ "/publish",
144
+ "Publish to registry",
145
+ (args, { write }) => {
146
+ write("Publishing to registry...");
147
+ },
148
+ ],
149
+ [
150
+ "/resume",
151
+ "Resume previous session",
152
+ (args, { write }) => {
153
+ write("Use /sessions to list available sessions");
154
+ },
155
+ ],
156
+ [
157
+ "/review",
158
+ "Request code review",
159
+ (args, { write }) => {
160
+ write("Starting code review...");
161
+ },
162
+ ],
163
+ [
164
+ "/tasks",
165
+ "Show background tasks",
166
+ (args, { write }) => {
167
+ write(formatBackgroundTasks());
168
+ },
169
+ ],
170
+ [
171
+ "/terminal-setup",
172
+ "Setup terminal integration",
173
+ (args, { write }) => {
174
+ write("Terminal setup complete. Shell integration enabled.");
175
+ },
176
+ ],
177
+ [
178
+ "/vim",
179
+ "Toggle Vim editing mode",
180
+ (args, { write, repl }) => {
181
+ if (repl?.toggleVimMode) {
182
+ repl.toggleVimMode();
183
+ write("Vim mode toggled");
184
+ } else {
185
+ write("Vim mode not available in this terminal");
186
+ }
187
+ },
188
+ ],
189
+ ];
190
+
191
+ for (const [name, description, handler] of commands) {
192
+ this.register(name, { description, handler });
193
+ }
194
+ }
195
+ }
196
+
197
+ export default SlashCommandRegistry;
@@ -44,6 +44,7 @@ import { createToolContext } from "../tools/tool-context.js";
44
44
  import { createToolTelemetryRecord } from "../tools/tool-telemetry.js";
45
45
  import { isAbortError, throwIfAborted } from "../lib/abort-utils.js";
46
46
  import { buildSearchCommand } from "../lib/search-command.js";
47
+ import { discoverCommands } from "../lib/slash-commands.js";
47
48
  import {
48
49
  isRetryableStreamError,
49
50
  STREAM_RETRY_BASE_MS,
@@ -700,6 +701,30 @@ export function buildSystemPrompt(cwd, opts = {}) {
700
701
  extraDirs.map((d) => `- ${d}`).join("\n");
701
702
  }
702
703
 
704
+ // Advertise user-defined slash commands (.claude/commands/*.md etc.) so the
705
+ // model knows which prompt macros it can run via the slash_command tool.
706
+ try {
707
+ const macros = discoverCommands(dir);
708
+ if (macros.length > 0) {
709
+ prompt +=
710
+ `\n\n## Available slash commands\n` +
711
+ `These are reusable prompt macros the user has defined. Run one with ` +
712
+ `the slash_command tool (e.g. {"command":"/${macros[0].name}"}) when it ` +
713
+ `fits the task; the tool returns the command's expanded instructions ` +
714
+ `for you to carry out.\n` +
715
+ macros
716
+ .map(
717
+ (m) =>
718
+ `- /${m.name}` +
719
+ (m.argumentHint ? ` ${m.argumentHint}` : "") +
720
+ (m.description ? ` — ${m.description}` : ""),
721
+ )
722
+ .join("\n");
723
+ }
724
+ } catch {
725
+ // Non-critical — command discovery failure must not break the prompt.
726
+ }
727
+
703
728
  return prompt;
704
729
  }
705
730
 
@@ -1272,6 +1297,7 @@ export async function executeTool(name, args, context = {}) {
1272
1297
  approvalGate: context.approvalGate || null,
1273
1298
  shellConfirm: context.shellConfirm || null,
1274
1299
  additionalDirectories: context.additionalDirectories || null,
1300
+ sandbox: context.sandbox || null,
1275
1301
  ruleAllowed,
1276
1302
  subAgentDepth: context.subAgentDepth || 0,
1277
1303
  subAgentBudget: context.subAgentBudget || null,
@@ -1686,6 +1712,7 @@ async function executeToolInner(
1686
1712
  approvalGate,
1687
1713
  shellConfirm,
1688
1714
  additionalDirectories,
1715
+ sandbox,
1689
1716
  ruleAllowed = false,
1690
1717
  subAgentDepth = 0,
1691
1718
  subAgentBudget = null,
@@ -1993,6 +2020,13 @@ async function executeToolInner(
1993
2020
  // polls output + completion via check_shell. No timeout — that's the whole
1994
2021
  // point of backgrounding (builds, test suites, dev servers).
1995
2022
  if (args.run_in_background === true) {
2023
+ if (sandbox) {
2024
+ return attachDescriptor({
2025
+ error:
2026
+ "[Sandbox] Background shell tasks are not supported in the ephemeral sandbox. Run in the foreground or explicitly disable --sandbox.",
2027
+ policy: { decision: "deny", via: "sandbox" },
2028
+ });
2029
+ }
1996
2030
  // Free memory from idle background tasks before adding another, so a
1997
2031
  // long agent run can't accumulate forgotten dev servers (no-op unless
1998
2032
  // the machine is actually under memory pressure).
@@ -2088,6 +2122,50 @@ async function executeToolInner(
2088
2122
  );
2089
2123
  }
2090
2124
 
2125
+ if (sandbox) {
2126
+ const { executeSandboxedShell, sandboxSummary } =
2127
+ await import("../lib/agent-sandbox.js");
2128
+ const result = executeSandboxedShell(args.command, sandbox, {
2129
+ cwd: args.cwd || cwd,
2130
+ timeout: _resolveShellTimeout(args.timeout),
2131
+ maxBuffer: 1024 * 1024,
2132
+ env: {
2133
+ CLAUDECODE: "1",
2134
+ ...(sessionId
2135
+ ? {
2136
+ CC_SESSION_ID: String(sessionId),
2137
+ CLAUDE_CODE_SESSION_ID: String(sessionId),
2138
+ }
2139
+ : {}),
2140
+ },
2141
+ });
2142
+ const common = {
2143
+ sandbox: sandboxSummary(sandbox),
2144
+ shellCommandPolicy: shellPolicy,
2145
+ approval: approvalOutcome,
2146
+ policyTrace: ["shell-policy", "approval", "sandbox"],
2147
+ };
2148
+ if (result.exitCode !== 0) {
2149
+ return attachDescriptor(
2150
+ {
2151
+ error: (
2152
+ result.stderr ||
2153
+ `Sandbox command exited with code ${result.exitCode}`
2154
+ ).substring(0, 2000),
2155
+ stdout: result.stdout.substring(0, 30000),
2156
+ stderr: result.stderr.substring(0, 2000),
2157
+ exitCode: result.exitCode,
2158
+ ...common,
2159
+ },
2160
+ override || runtimeDescriptor,
2161
+ );
2162
+ }
2163
+ return attachDescriptor(
2164
+ { stdout: result.stdout.substring(0, 30000), ...common },
2165
+ override || runtimeDescriptor,
2166
+ );
2167
+ }
2168
+
2091
2169
  try {
2092
2170
  const output = execSync(args.command, {
2093
2171
  cwd: args.cwd || cwd,
@@ -2348,6 +2426,59 @@ async function executeToolInner(
2348
2426
  }
2349
2427
  }
2350
2428
 
2429
+ case "slash_command": {
2430
+ try {
2431
+ const { getCommand, expandCommand, discoverCommands } =
2432
+ await import("../lib/slash-commands.js");
2433
+ const raw = String(args.command || "").trim();
2434
+ if (!raw) {
2435
+ return attachDescriptor({
2436
+ error: "slash_command requires a non-empty 'command'.",
2437
+ });
2438
+ }
2439
+ // Parse "/name arg1 arg2" exactly like a typed slash command (leading
2440
+ // '/' optional). First token is the command name, the rest are args.
2441
+ const [head, ...rest] = raw.replace(/^\//, "").split(/\s+/);
2442
+ const macro = head ? getCommand(head, cwd) : null;
2443
+ if (!macro) {
2444
+ const available = discoverCommands(cwd).map((c) => ({
2445
+ name: c.name,
2446
+ scope: c.scope,
2447
+ description: c.description || undefined,
2448
+ }));
2449
+ return attachDescriptor({
2450
+ error: `Unknown slash command "${head}".`,
2451
+ availableCommands: available,
2452
+ hint:
2453
+ available.length === 0
2454
+ ? "No user-defined slash commands found in .claude/commands/ or .chainlesschain/commands/."
2455
+ : "Call slash_command with one of availableCommands[].name.",
2456
+ });
2457
+ }
2458
+ // allowBang:false — the agent must not get an un-gated shell side
2459
+ // channel via a command file. $ARGUMENTS / @file (read) still expand;
2460
+ // any !`cmd` is left literal for the model to run via run_shell.
2461
+ const { prompt: expanded, warnings } = expandCommand(
2462
+ macro,
2463
+ rest.filter(Boolean),
2464
+ { cwd, allowBang: false },
2465
+ );
2466
+ return attachDescriptor({
2467
+ command: macro.name,
2468
+ scope: macro.scope,
2469
+ expandedPrompt: expanded,
2470
+ warnings: warnings && warnings.length ? warnings : undefined,
2471
+ instructions:
2472
+ "The expandedPrompt is the command's instructions. Carry them out " +
2473
+ "now using your normal tools.",
2474
+ });
2475
+ } catch (err) {
2476
+ return attachDescriptor({
2477
+ error: `slash_command failed: ${err.message}`,
2478
+ });
2479
+ }
2480
+ }
2481
+
2351
2482
  case "ask_user_question": {
2352
2483
  if (!interaction || typeof interaction.askUser !== "function") {
2353
2484
  return attachDescriptor({
@@ -4633,6 +4764,7 @@ export async function* agentLoop(messages, options) {
4633
4764
  // false so run_code keeps its existing per-permission-mode behavior.
4634
4765
  interactiveApproval: options.interactiveApproval || false,
4635
4766
  additionalDirectories: options.additionalDirectories || null,
4767
+ sandbox: options.sandbox || null,
4636
4768
  permissionRules: options.permissionRules || null,
4637
4769
  permissionConfirm: options.permissionConfirm || null,
4638
4770
  settingsHooks: options.settingsHooks || null,
@@ -5091,7 +5223,11 @@ export async function* agentLoop(messages, options) {
5091
5223
  });
5092
5224
  for (const { call, toolArgs, promise } of inflight) {
5093
5225
  throwIfAborted(signal);
5094
- yield { type: "tool-executing", tool: call.function.name, args: toolArgs };
5226
+ yield {
5227
+ type: "tool-executing",
5228
+ tool: call.function.name,
5229
+ args: toolArgs,
5230
+ };
5095
5231
  const { result: toolResult, error: toolError } = await promise;
5096
5232
  throwIfAborted(signal);
5097
5233
  const warningMsg = budget.toWarningMessage();
@@ -653,6 +653,43 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
653
653
  tags: ["tool:todo_write", "contract:coding-agent", "tier:extension"],
654
654
  },
655
655
  },
656
+ {
657
+ name: "slash_command",
658
+ title: "Slash Command",
659
+ kind: "planning",
660
+ tier: "extension",
661
+ description:
662
+ "Run a user-defined slash command (a reusable prompt macro from " +
663
+ ".claude/commands/*.md or .chainlesschain/commands/*.md) and get back its " +
664
+ "expanded prompt text to act on. The 'command' string is the slash " +
665
+ "command exactly as a user would type it, e.g. '/review' or " +
666
+ "'/git:commit fix the typo' — the leading slash is optional and trailing " +
667
+ "words become $ARGUMENTS / $1..$9. @file references are expanded; " +
668
+ "!`shell` snippets are NOT executed when invoked this way (run them via " +
669
+ "run_shell if needed). Available commands are listed in the system " +
670
+ "prompt; calling with an unknown command returns the list.",
671
+ inputSchema: {
672
+ type: "object",
673
+ properties: {
674
+ command: {
675
+ type: "string",
676
+ description:
677
+ "The slash command to run, as typed by a user, e.g. '/review' or " +
678
+ "'/git:commit fix the typo'. Leading '/' optional.",
679
+ },
680
+ },
681
+ required: ["command"],
682
+ },
683
+ ...TOOL_POLICY_METADATA.slash_command,
684
+ permissions: {
685
+ level: "readonly",
686
+ scopes: ["session:read"],
687
+ },
688
+ telemetry: {
689
+ category: "planning",
690
+ tags: ["tool:slash_command", "contract:coding-agent", "tier:extension"],
691
+ },
692
+ },
656
693
  {
657
694
  name: "ask_user_question",
658
695
  title: "Ask User Question",
@@ -149,6 +149,20 @@ const TOOL_POLICY_METADATA = Object.freeze({
149
149
  approvalFlow: "auto",
150
150
  isReadOnly: true,
151
151
  },
152
+ // Expand a user-defined slash command (.claude/commands/*.md) into its prompt
153
+ // text. Read-only by design: the agent path disables `!`cmd`` bang execution,
154
+ // so only $ARGUMENTS / @file (read) substitution runs — no un-gated shell.
155
+ // Plan-mode-safe (returns text the model then acts on via its normal tools).
156
+ slash_command: {
157
+ riskLevel: RISK_LEVELS.LOW,
158
+ category: TOOL_CATEGORIES.SKILL,
159
+ availableInPlanMode: true,
160
+ planModeBehavior: "allow",
161
+ requiresPlanApproval: false,
162
+ requiresConfirmation: false,
163
+ approvalFlow: "auto",
164
+ isReadOnly: true,
165
+ },
152
166
  search_sessions: {
153
167
  riskLevel: RISK_LEVELS.LOW,
154
168
  category: TOOL_CATEGORIES.SEARCH,
@@ -280,18 +280,31 @@ export async function runAgentHeadless(options = {}, deps = {}) {
280
280
  // an `ask` falls closed (no human to confirm in headless). No file → null →
281
281
  // every existing risk-tier / shell-policy layer runs unchanged.
282
282
  let permissionRules = options.permissionRules || null;
283
- if (!permissionRules) {
284
- try {
285
- const { loadSettings } = await import("../lib/settings-loader.cjs");
286
- const loaded = loadSettings({ cwd, settingsFile: options.settingsFile });
283
+ let managedSettings = null;
284
+ try {
285
+ const { loadSettings, applyManagedPermissionPolicy } =
286
+ await import("../lib/settings-loader.cjs");
287
+ const loaded = loadSettings({
288
+ cwd,
289
+ settingsFile: options.settingsFile,
290
+ managedSettingsFile: options.managedSettingsFile,
291
+ });
292
+ managedSettings = loaded.managed;
293
+ if (!permissionRules) {
287
294
  const total =
288
295
  loaded.rules.allow.length +
289
296
  loaded.rules.ask.length +
290
297
  loaded.rules.deny.length;
291
298
  permissionRules = total > 0 ? loaded.rules : null;
292
- } catch {
293
- permissionRules = null; // fail-open
299
+ } else if (managedSettings) {
300
+ permissionRules = applyManagedPermissionPolicy(
301
+ permissionRules,
302
+ managedSettings,
303
+ );
294
304
  }
305
+ } catch (error) {
306
+ if (error?.code === "CC_MANAGED_SETTINGS_INVALID") throw error;
307
+ // Preserve caller-provided rules; absent settings keep legacy behavior.
295
308
  }
296
309
 
297
310
  // .claude/settings.json `hooks` block — decision-capable PreToolUse/
@@ -483,6 +496,11 @@ export async function runAgentHeadless(options = {}, deps = {}) {
483
496
  }
484
497
 
485
498
  // ── Permission + tool resolution ──────────────────────────────────────
499
+ if (managedSettings) {
500
+ const { assertManagedPermissionMode } =
501
+ await import("../lib/settings-loader.cjs");
502
+ assertManagedPermissionMode(options.permissionMode, managedSettings);
503
+ }
486
504
  const perm = resolvePermissionMode(options.permissionMode);
487
505
  const enabledToolNames = resolveEnabledTools({
488
506
  // An explicit --allowed-tools wins; otherwise a matched command's
@@ -705,6 +723,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
705
723
  mcp = await doResolve(
706
724
  {
707
725
  mcpConfigPath: options.mcpConfig || null,
726
+ managedSettingsFile: options.managedSettingsFile,
708
727
  db: db?.getDatabase?.() || null,
709
728
  includeRegistered: options.useRegisteredMcp !== false,
710
729
  // --strict-mcp-config: use ONLY the --mcp-config servers, ignoring
@@ -803,6 +822,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
803
822
  apiKey,
804
823
  cwd,
805
824
  additionalDirectories,
825
+ sandbox: options.sandbox || null,
806
826
  sessionId,
807
827
  autoCheckpoint: options.autoCheckpoint || false,
808
828
  checkpointSession: options.checkpointSession || sessionId,