chainlesschain 0.162.142 → 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 (192) hide show
  1. package/bin/chainlesschain.js +5 -3
  2. package/package.json +2 -2
  3. package/src/assets/web-panel/assets/{AIOps-Dc6fWgoa.js → AIOps-DywJ7xTv.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-DzMx25vJ.js → ActionButton-BTlqcY-q.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-eDC3KNht.js → Analytics-FdG1Mvwy.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-uA1TOtNp.js → AppLayout-CVsnbvN1.js} +3 -3
  7. package/src/assets/web-panel/assets/{Audit-Bq3QX9Cj.js → Audit-ITdpJ7vR.js} +1 -1
  8. package/src/assets/web-panel/assets/{Backup-B1V3Jfyv.js → Backup-BfXqnXo1.js} +1 -1
  9. package/src/assets/web-panel/assets/{BaseInput-DMFwddIF.js → BaseInput-C09ip3_E.js} +1 -1
  10. package/src/assets/web-panel/assets/{Chat-CKWQDH5j.js → Chat-qdkhB42l.js} +6 -6
  11. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CStSBCnk.js → ChatBubbleRenderer-D2KfETZD.js} +1 -1
  12. package/src/assets/web-panel/assets/{Checkbox-DepIzI7G.js → Checkbox-j6WZCuff.js} +1 -1
  13. package/src/assets/web-panel/assets/{Codegen-ClanWll2.js → Codegen-CGZ-K3uK.js} +1 -1
  14. package/src/assets/web-panel/assets/{Col-CFBzsL4W.js → Col-CIlPOAu6.js} +1 -1
  15. package/src/assets/web-panel/assets/{Community-CaAyZ_Pt.js → Community-sY-i-hic.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compact-3dCHRSVe.js → Compact-DcoEfyL8.js} +1 -1
  17. package/src/assets/web-panel/assets/Compliance-T8EtTecW.js +1 -0
  18. package/src/assets/web-panel/assets/{Cowork-DkJmdQaU.js → Cowork-DLY_fkLv.js} +3 -3
  19. package/src/assets/web-panel/assets/{Cron-DKfNf6J2.js → Cron-D049pZBC.js} +2 -2
  20. package/src/assets/web-panel/assets/{Crosschain-COu1aQIO.js → Crosschain-DCXdE8M9.js} +1 -1
  21. package/src/assets/web-panel/assets/{DID-CkAgFLkI.js → DID-JCvPZtjW.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dashboard-CfaKWZCU.js → Dashboard-Cg2xu3iE.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dropdown-Cjw97sdb.js → Dropdown-DjJLjbLh.js} +1 -1
  24. package/src/assets/web-panel/assets/{EmailListRenderer-DROLQgOn.js → EmailListRenderer-DugNcSLR.js} +1 -1
  25. package/src/assets/web-panel/assets/{FamilyGuardDashboard-o_cYzlLq.js → FamilyGuardDashboard-J6Nb-E30.js} +1 -1
  26. package/src/assets/web-panel/assets/{Federation-Boex3ljt.js → Federation-CQ3Ttpbl.js} +1 -1
  27. package/src/assets/web-panel/assets/{FormItemContext-BQQ05T_3.js → FormItemContext-Cz0NKag4.js} +1 -1
  28. package/src/assets/web-panel/assets/{GenericCardRenderer-CdfL8PBd.js → GenericCardRenderer-NYcMP6iz.js} +1 -1
  29. package/src/assets/web-panel/assets/{Git-CfZ07qJy.js → Git-B4hYN18N.js} +2 -2
  30. package/src/assets/web-panel/assets/{Governance-B21ISudq.js → Governance-DOQPCcC0.js} +1 -1
  31. package/src/assets/web-panel/assets/{Inference-CGIK4Im1.js → Inference-HtLF746W.js} +1 -1
  32. package/src/assets/web-panel/assets/{KnowledgeGraph-CI1kmfdT.js → KnowledgeGraph-BXrk8rMm.js} +1 -1
  33. package/src/assets/web-panel/assets/{Logs-Dpc1-__h.js → Logs-DS0JnD3-.js} +2 -2
  34. package/src/assets/web-panel/assets/{Marketplace-BpMtMWyK.js → Marketplace-Cqnjihrz.js} +1 -1
  35. package/src/assets/web-panel/assets/{McpTools-B94WvOOS.js → McpTools-Cx3Psk-U.js} +5 -5
  36. package/src/assets/web-panel/assets/{Memory-DODsAxZf.js → Memory-BjyysPtj.js} +2 -2
  37. package/src/assets/web-panel/assets/{MobileBridge-C3Bjshem.js → MobileBridge-CYaITZ7w.js} +1 -1
  38. package/src/assets/web-panel/assets/{MobileProjects-Bi8IHDv_.js → MobileProjects-Xwf-fdOQ.js} +1 -1
  39. package/src/assets/web-panel/assets/{Mtc-CH5BSuWG.js → Mtc-Djkql5m5.js} +2 -2
  40. package/src/assets/web-panel/assets/{MtcAudit-DN3MzNtL.js → MtcAudit-D2BAZlu0.js} +2 -2
  41. package/src/assets/web-panel/assets/{Multisig-CO6GWQOh.js → Multisig-ByqP1ZzH.js} +3 -3
  42. package/src/assets/web-panel/assets/{NLProgramming-DhIr3V_u.js → NLProgramming-C_kn0nE2.js} +1 -1
  43. package/src/assets/web-panel/assets/{Notes-CNgrvZCJ.js → Notes-7l7eXHPq.js} +3 -3
  44. package/src/assets/web-panel/assets/{NotificationSettings-Crr4LPjQ.js → NotificationSettings-BrCDoitw.js} +1 -1
  45. package/src/assets/web-panel/assets/{OrderTableRenderer-C8q-kK2z.js → OrderTableRenderer-CmtqIdwr.js} +1 -1
  46. package/src/assets/web-panel/assets/{Organization-hWhCmeUn.js → Organization-DdoNAxsM.js} +4 -4
  47. package/src/assets/web-panel/assets/{Overflow-t_EBxns-.js → Overflow-Bw7R6dE3.js} +1 -1
  48. package/src/assets/web-panel/assets/{P2P-B8fqfwis.js → P2P-DJNtBugA.js} +2 -2
  49. package/src/assets/web-panel/assets/{PdhVaultBrowser-d-wlJw3R.js → PdhVaultBrowser-Dwhd5_ue.js} +3 -3
  50. package/src/assets/web-panel/assets/{Permissions-Ch13YpBo.js → Permissions-BYoSfhPR.js} +4 -4
  51. package/src/assets/web-panel/assets/{PersonalDataHub-DW7LlLbS.js → PersonalDataHub-aYCYJbnH.js} +2 -2
  52. package/src/assets/web-panel/assets/{Pipeline-BHh3HqOQ.js → Pipeline-DJp6CprF.js} +1 -1
  53. package/src/assets/web-panel/assets/{Privacy-DAhlJDSC.js → Privacy-Cq9HZweR.js} +1 -1
  54. package/src/assets/web-panel/assets/{ProjectInit-BRtddAM_.js → ProjectInit-CmF0HsSt.js} +2 -2
  55. package/src/assets/web-panel/assets/{ProjectSettings-CzR1EC7b.js → ProjectSettings-P8V5Aea2.js} +2 -2
  56. package/src/assets/web-panel/assets/{Projects-DSavX602.js → Projects-DPd5-lNS.js} +1 -1
  57. package/src/assets/web-panel/assets/{Providers-D55_kGZs.js → Providers-D589v0q2.js} +1 -1
  58. package/src/assets/web-panel/assets/{QuickAsk-BR5qDIaT.js → QuickAsk-lvRV2osB.js} +1 -1
  59. package/src/assets/web-panel/assets/{Recommend-CTFAM97K.js → Recommend-sb84MTpY.js} +1 -1
  60. package/src/assets/web-panel/assets/{Reputation-Z7pvEha9.js → Reputation-d9Y3vy-W.js} +1 -1
  61. package/src/assets/web-panel/assets/{Row-MqKcIsjP.js → Row-DMdhLUTp.js} +1 -1
  62. package/src/assets/web-panel/assets/{RssFeed-DdLDjRpk.js → RssFeed-OL-SMDkz.js} +3 -3
  63. package/src/assets/web-panel/assets/{Search-CeOzh2hz.js → Search-BjStLKq1.js} +1 -1
  64. package/src/assets/web-panel/assets/{Security-gHrXaf4o.js → Security-MeI411qr.js} +3 -3
  65. package/src/assets/web-panel/assets/{Services-B8Y7pmY1.js → Services-UajosuhT.js} +2 -2
  66. package/src/assets/web-panel/assets/{Skeleton-CRS0WNut.js → Skeleton-CGpG-QJ1.js} +1 -1
  67. package/src/assets/web-panel/assets/{Skills--a5_Pdxx.js → Skills-C6P2RPY-.js} +1 -1
  68. package/src/assets/web-panel/assets/{Sla-EcTyL6EM.js → Sla-B_fPprgw.js} +1 -1
  69. package/src/assets/web-panel/assets/{SpeechSettings-QpfvOiJr.js → SpeechSettings-CqxLjSlQ.js} +1 -1
  70. package/src/assets/web-panel/assets/{SyncSettings-DaLBBzlE.js → SyncSettings-DixSfFOQ.js} +2 -2
  71. package/src/assets/web-panel/assets/{Tasks-Ca6xvO-I.js → Tasks-PavzPBxc.js} +1 -1
  72. package/src/assets/web-panel/assets/{Templates-CWguiCoE.js → Templates-BYdGRnfX.js} +1 -1
  73. package/src/assets/web-panel/assets/{Tenant-BGLLZulu.js → Tenant-BQLgnarD.js} +1 -1
  74. package/src/assets/web-panel/assets/Terminal-BzOHpq-B.js +3 -0
  75. package/src/assets/web-panel/assets/{TimelineRenderer-CLjvjbmr.js → TimelineRenderer-Bv7uZRM7.js} +1 -1
  76. package/src/assets/web-panel/assets/{Tokens-De5mmw_a.js → Tokens-DxhgszRJ.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trigger-Chbq6U0N.js → Trigger-nQYHayuc.js} +1 -1
  78. package/src/assets/web-panel/assets/{Trust-CYxUO2lv.js → Trust-CvqZDuZ4.js} +1 -1
  79. package/src/assets/web-panel/assets/{UkeySign-iyoZXXF6.js → UkeySign-DaR8GV2I.js} +1 -1
  80. package/src/assets/web-panel/assets/{VideoEditing-CHg3ifJs.js → VideoEditing-C6Mpsokw.js} +1 -1
  81. package/src/assets/web-panel/assets/{Wallet-DfjqObsO.js → Wallet-B57VRrWc.js} +4 -4
  82. package/src/assets/web-panel/assets/{WebAuthn-0FI6xfud.js → WebAuthn-BbtEEtpq.js} +4 -4
  83. package/src/assets/web-panel/assets/{WorkflowEditor-CJgGcctS.js → WorkflowEditor-C5LwvKmH.js} +1 -1
  84. package/src/assets/web-panel/assets/{chat-fH-E4vhY.js → chat-MzuPR5jh.js} +1 -1
  85. package/src/assets/web-panel/assets/{colors-CuxsOD6d.js → colors-HyW8mi_y.js} +1 -1
  86. package/src/assets/web-panel/assets/{compact-item-AfVcFrFU.js → compact-item-DvUSzWAp.js} +1 -1
  87. package/src/assets/web-panel/assets/{createContext-DTsD7sPO.js → createContext-4MppZl7X.js} +1 -1
  88. package/src/assets/web-panel/assets/devWarning-6YJJMjSH.js +1 -0
  89. package/src/assets/web-panel/assets/{hasIn-DJR763M6.js → hasIn-D9q3CJ-u.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-DhM9FZUH.js → index--Bm6OqmU.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-OZwLoscJ.js → index-B5E4DhVc.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-CF8OSTin.js → index-B994UQfE.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-9cryBBzh.js → index-BF2JsbiX.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-BMVULNUC.js → index-BFGfC5RS.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-Dj1_lz3M.js → index-BGQtFso0.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DBPAH7rp.js → index-BcunsBIx.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-mLAfJXAf.js → index-Bl-E4W4q.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Cfppli6E.js → index-BmCo2Xdp.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-_hP8-Y2F.js → index-Btz8pU68.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DvlzcX3Q.js → index-C0DiL97c.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CBBStCbO.js → index-C9I5MuJ0.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-SuJ2_OzM.js → index-CLAZs1Vd.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-B8DLT-F4.js → index-Caqtu6Et.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Cm4cHE5_.js → index-CgIfXOD9.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DbQX0Zbf.js → index-Ci6adKh8.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BEGMojUg.js → index-CifKUNtV.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CdV7a6-K.js → index-Cs-RKRUM.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Dswd93W4.js → index-CucRo4Vz.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-D2KdGSMa.js → index-CvAqCAo9.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BqflTl_b.js → index-D2jrnaq3.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Cl7chKuM.js → index-D7TDMMfu.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CAbZ3dW9.js → index-DDZ6fP5Z.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BD4-kWQY.js → index-DFqvWeGc.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DejUsZOw.js → index-DNYqw0MO.js} +1 -1
  115. package/src/assets/web-panel/assets/index-D_oeGLr6.js +1 -0
  116. package/src/assets/web-panel/assets/{index-DH-dA4pG.js → index-DcMkjb92.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CMcYdHhK.js → index-DmZ6-suL.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-85iIi3qF.js → index-Dv7ffI2g.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DJIFQ-Ay.js → index-Dvg5xYuP.js} +1 -1
  120. package/src/assets/web-panel/assets/index-Qa57YG19.js +1 -0
  121. package/src/assets/web-panel/assets/{index-DxD03TL7.js → index-SDblbKj6.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CmUxSTNy.js → index-UUMCA2Sq.js} +3 -3
  123. package/src/assets/web-panel/assets/{index-BJl6Ob-o.js → index-Zvtru2oE.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DPHYW3IK.js → index-eOQO6KnV.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B-rcowKd.js → index-m0b6Fj9q.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BTtL2Qkb.js → index-ryFLxB1p.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-fj3ZXgiy.js → index-xvUVuFnA.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BbpuFc8C.js → index-zLwYpvX0.js} +1 -1
  129. package/src/assets/web-panel/assets/{initDefaultProps-BGoLJP6T.js → initDefaultProps-CC--PMsC.js} +1 -1
  130. package/src/assets/web-panel/assets/{motion-23xdoVi0.js → motion-DdrBjRF1.js} +1 -1
  131. package/src/assets/web-panel/assets/{move-C3Bnnft-.js → move-D712Gwl2.js} +1 -1
  132. package/src/assets/web-panel/assets/{mtc-parser-Dv0C3a90.js → mtc-parser-39y-keKO.js} +1 -1
  133. package/src/assets/web-panel/assets/{omit-C3r9qzDO.js → omit-6Y51gDB9.js} +1 -1
  134. package/src/assets/web-panel/assets/{pickAttrs-B4bJOcNp.js → pickAttrs-Cy6EHbq9.js} +1 -1
  135. package/src/assets/web-panel/assets/{placementArrow-Dxf48wcO.js → placementArrow-BYxdAm0p.js} +1 -1
  136. package/src/assets/web-panel/assets/{responsiveObserve-Rq9U2hbz.js → responsiveObserve-C9R6q_cr.js} +1 -1
  137. package/src/assets/web-panel/assets/{slide-BeWiqbdF.js → slide-CXUJlilB.js} +1 -1
  138. package/src/assets/web-panel/assets/{statusUtils-yX9N1cEc.js → statusUtils-DOtrOeql.js} +1 -1
  139. package/src/assets/web-panel/assets/{styleChecker-5Ko9NorO.js → styleChecker-D5r39o92.js} +1 -1
  140. package/src/assets/web-panel/assets/{useFlexGapSupport-WKpkTLok.js → useFlexGapSupport-DfAD5U4Z.js} +1 -1
  141. package/src/assets/web-panel/assets/{useFs-BV4X0JOG.js → useFs-BkrT-Zbc.js} +1 -1
  142. package/src/assets/web-panel/assets/{usePersonalDataHub-g41wq_2p.js → usePersonalDataHub-BwnnnZjU.js} +1 -1
  143. package/src/assets/web-panel/assets/{vnode-BAurbOH8.js → vnode-SU-N4pum.js} +1 -1
  144. package/src/assets/web-panel/assets/{zoom-Cl5XniRg.js → zoom-DHScfpTP.js} +1 -1
  145. package/src/assets/web-panel/index.html +1 -1
  146. package/src/auth/npm-auth.js +65 -0
  147. package/src/command-manifest.json +1126 -0
  148. package/src/commands/agent.js +92 -0
  149. package/src/commands/agents.js +68 -0
  150. package/src/commands/note.js +2 -1
  151. package/src/commands/permissions.js +66 -10
  152. package/src/commands/plugin.js +50 -3
  153. package/src/commands/search.js +2 -1
  154. package/src/harness/worktree-isolator.js +14 -7
  155. package/src/index.js +4 -12
  156. package/src/lazy-dispatch.js +107 -0
  157. package/src/lib/agent-sandbox.js +72 -0
  158. package/src/lib/background-agent-supervisor.js +197 -0
  159. package/src/lib/code-review.js +72 -0
  160. package/src/lib/ensure-utf8.js +25 -7
  161. package/src/lib/knowledge-exporter.js +3 -2
  162. package/src/lib/permission-engine.js +1 -1
  163. package/src/lib/plugin-security.js +128 -0
  164. package/src/lib/pr-create.js +108 -0
  165. package/src/lib/publish-workspace.js +107 -0
  166. package/src/lib/resume-session.js +111 -0
  167. package/src/lib/session-manager.js +2 -1
  168. package/src/lib/settings-hooks.cjs +68 -25
  169. package/src/lib/settings-loader.cjs +115 -2
  170. package/src/lib/task-list.js +53 -0
  171. package/src/program-base.js +24 -0
  172. package/src/repl/agent-repl.js +108 -3
  173. package/src/repl/agents-status.js +8 -2
  174. package/src/repl/btw-command.js +56 -0
  175. package/src/repl/chat-repl.js +52 -1
  176. package/src/repl/hooks-status.js +1 -2
  177. package/src/repl/slash-command-registry.js +197 -0
  178. package/src/repl/think-command.js +31 -0
  179. package/src/runtime/agent-core.js +137 -1
  180. package/src/runtime/coding-agent-contract-shared.cjs +37 -0
  181. package/src/runtime/coding-agent-policy.cjs +14 -0
  182. package/src/runtime/file-ref-expander.js +100 -14
  183. package/src/runtime/headless-runner.js +26 -6
  184. package/src/runtime/headless-stream.js +25 -6
  185. package/src/runtime/mcp-config.js +46 -2
  186. package/src/runtime/policies/agent-policy.js +1 -0
  187. package/src/workers/background-agent-worker.js +60 -0
  188. package/src/assets/web-panel/assets/Compliance-BKYHHTdq.js +0 -1
  189. package/src/assets/web-panel/assets/Terminal-Bryzb1Rm.js +0 -3
  190. package/src/assets/web-panel/assets/devWarning-DffbPlEe.js +0 -1
  191. package/src/assets/web-panel/assets/index-BAHgOh3h.js +0 -1
  192. package/src/assets/web-panel/assets/index-zfkDb9FC.js +0 -1
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Publish workspace packages to npm (ESM)
3
+ * Mirrors Claude Code /publish behavior
4
+ * @module lib/publish-workspace
5
+ */
6
+
7
+ import { execSync } from "child_process";
8
+ import { logger } from "./logger.js";
9
+ import path from "path";
10
+ import fs from "fs";
11
+
12
+ /**
13
+ * Get all workspace packages
14
+ * @returns {Array<{name: string, path: string, version: string}>}
15
+ */
16
+ export function getWorkspacePackages() {
17
+ try {
18
+ const rootPkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
19
+ const packages = [];
20
+
21
+ // Handle workspaces config
22
+ const workspaces = rootPkg.workspaces?.packages || rootPkg.workspaces || [];
23
+ for (const pattern of workspaces) {
24
+ // Simple glob handling for basic patterns
25
+ const dir = pattern.replace(/\*+/g, "");
26
+ if (fs.existsSync(dir)) {
27
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
28
+ for (const entry of entries) {
29
+ if (entry.isDirectory()) {
30
+ const pkgPath = path.join(dir, entry.name);
31
+ const pkgFile = path.join(pkgPath, "package.json");
32
+ if (fs.existsSync(pkgFile)) {
33
+ const pkg = JSON.parse(fs.readFileSync(pkgFile, "utf8"));
34
+ if (pkg.name && !pkg.private) {
35
+ packages.push({
36
+ name: pkg.name,
37
+ path: pkgPath,
38
+ version: pkg.version,
39
+ });
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+
47
+ return packages;
48
+ } catch (err) {
49
+ logger.error(`Failed to get workspace packages: ${err.message}`);
50
+ return [];
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Publish a single package
56
+ * @param {Object} pkg Package info
57
+ * @param {Object} options Publish options
58
+ * @returns {boolean} success
59
+ */
60
+ export function publishPackage(pkg, options = {}) {
61
+ try {
62
+ logger.info(`Publishing ${pkg.name}@${pkg.version}...`);
63
+ let cmd = "npm publish";
64
+ if (options.tag) cmd += ` --tag ${options.tag}`;
65
+ if (options.access) cmd += ` --access ${options.access}`;
66
+
67
+ execSync(cmd, {
68
+ cwd: pkg.path,
69
+ stdio: "inherit",
70
+ encoding: "utf8",
71
+ });
72
+ logger.succeed(`Published ${pkg.name}@${pkg.version}`);
73
+ return true;
74
+ } catch (err) {
75
+ logger.error(`Failed to publish ${pkg.name}: ${err.message}`);
76
+ return false;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Publish all changed workspace packages
82
+ * @param {Object} options Options
83
+ * @returns {Promise<boolean>} success
84
+ */
85
+ export async function publishWorkspace(options = {}) {
86
+ const packages = getWorkspacePackages();
87
+ if (packages.length === 0) {
88
+ logger.info("No publishable packages found");
89
+ return true;
90
+ }
91
+
92
+ logger.info(`Found ${packages.length} publishable packages`);
93
+ let allSucceeded = true;
94
+
95
+ for (const pkg of packages) {
96
+ if (options.dryRun) {
97
+ logger.info(`[dry-run] Would publish ${pkg.name}@${pkg.version}`);
98
+ continue;
99
+ }
100
+ const ok = publishPackage(pkg, options);
101
+ if (!ok) allSucceeded = false;
102
+ }
103
+
104
+ return allSucceeded;
105
+ }
106
+
107
+ export default { getWorkspacePackages, publishPackage, publishWorkspace };
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Session resume utilities (ESM)
3
+ * Mirrors Claude Code /resume behavior
4
+ * @module lib/resume-session
5
+ */
6
+
7
+ import fs from "fs";
8
+ import path from "path";
9
+ import os from "os";
10
+ import { logger } from "./logger.js";
11
+
12
+ const SESSION_DIR = path.join(os.homedir(), ".chainlesschain", "sessions");
13
+
14
+ /**
15
+ * List recent chat sessions
16
+ * @param {number} limit Maximum sessions to return
17
+ * @returns {Array<Object>} list of sessions
18
+ */
19
+ export function listSessions(limit = 10) {
20
+ try {
21
+ if (!fs.existsSync(SESSION_DIR)) {
22
+ return [];
23
+ }
24
+
25
+ const files = fs
26
+ .readdirSync(SESSION_DIR)
27
+ .filter((f) => f.endsWith(".json"))
28
+ .map((f) => {
29
+ const filePath = path.join(SESSION_DIR, f);
30
+ const stat = fs.statSync(filePath);
31
+ let summary = "";
32
+ try {
33
+ const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
34
+ summary = data.summary || data.title || f.replace(".json", "");
35
+ } catch {
36
+ summary = f.replace(".json", "");
37
+ }
38
+ return {
39
+ id: f.replace(".json", ""),
40
+ file: filePath,
41
+ mtime: stat.mtimeMs,
42
+ summary,
43
+ };
44
+ })
45
+ .sort((a, b) => b.mtime - a.mtime)
46
+ .slice(0, limit);
47
+
48
+ return files;
49
+ } catch (err) {
50
+ logger.debug(`Error listing sessions: ${err.message}`);
51
+ return [];
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Load a session by ID
57
+ * @param {string} sessionId
58
+ * @returns {Object|null} session data
59
+ */
60
+ export function loadSession(sessionId) {
61
+ try {
62
+ const filePath = path.join(SESSION_DIR, `${sessionId}.json`);
63
+ if (!fs.existsSync(filePath)) {
64
+ return null;
65
+ }
66
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
67
+ } catch (err) {
68
+ logger.error(`Error loading session ${sessionId}: ${err.message}`);
69
+ return null;
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Get the most recent session
75
+ * @returns {Object|null}
76
+ */
77
+ export function getLatestSession() {
78
+ const sessions = listSessions(1);
79
+ return sessions.length > 0 ? loadSession(sessions[0].id) : null;
80
+ }
81
+
82
+ /**
83
+ * Resume a chat session
84
+ * @param {string} [sessionId] Optional session ID (resumes latest if not provided)
85
+ * @returns {Promise<Object>} resume result
86
+ */
87
+ export async function resumeSession(sessionId) {
88
+ let session;
89
+ if (sessionId) {
90
+ session = loadSession(sessionId);
91
+ if (!session) {
92
+ return { success: false, message: `Session ${sessionId} not found` };
93
+ }
94
+ } else {
95
+ session = getLatestSession();
96
+ if (!session) {
97
+ return { success: false, message: "No previous sessions found" };
98
+ }
99
+ }
100
+
101
+ return {
102
+ success: true,
103
+ sessionId: session.id || sessionId,
104
+ messageCount: session.messages?.length || 0,
105
+ summary: session.summary,
106
+ session,
107
+ message: "Session loaded. Continue chatting to resume the conversation.",
108
+ };
109
+ }
110
+
111
+ export default { listSessions, loadSession, getLatestSession, resumeSession };
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  import { createHash } from "crypto";
9
+ import { safeJsonParse } from "./safe-json.js";
9
10
 
10
11
  function ensureSessionsTable(db) {
11
12
  db.exec(`
@@ -153,7 +154,7 @@ export function listSessions(db, options = {}) {
153
154
  ...session,
154
155
  metadata:
155
156
  typeof session.metadata === "string"
156
- ? JSON.parse(session.metadata || "{}")
157
+ ? safeJsonParse(session.metadata, {})
157
158
  : session.metadata || {},
158
159
  }));
159
160
  }
@@ -82,20 +82,66 @@ function readJson(file, onWarn) {
82
82
  }
83
83
  }
84
84
 
85
+ function managedSettingsFile(env = process.env) {
86
+ if (env.CC_MANAGED_SETTINGS) return path.resolve(env.CC_MANAGED_SETTINGS);
87
+ if (process.platform === "win32") {
88
+ const base = env.ProgramData || env.PROGRAMDATA || "C:\\ProgramData";
89
+ return path.join(base, "ChainlessChain", "managed-settings.json");
90
+ }
91
+ return "/etc/chainlesschain/managed-settings.json";
92
+ }
93
+
94
+ function appendHookBlock(merged, data) {
95
+ const block =
96
+ data && data.hooks && typeof data.hooks === "object" ? data.hooks : null;
97
+ if (!block) return false;
98
+ let contributed = false;
99
+ for (const [event, groups] of Object.entries(block)) {
100
+ if (!Array.isArray(groups)) continue;
101
+ for (const g of groups) {
102
+ if (!g || typeof g !== "object" || !Array.isArray(g.hooks)) continue;
103
+ const cmds = g.hooks.filter(
104
+ (h) => h && h.type === "command" && h.command,
105
+ );
106
+ if (cmds.length === 0) continue;
107
+ if (!merged[event]) merged[event] = [];
108
+ merged[event].push({ matcher: g.matcher ?? null, hooks: cmds });
109
+ contributed = true;
110
+ }
111
+ }
112
+ return contributed;
113
+ }
114
+
85
115
  /**
86
116
  * Load + concatenate the `hooks` blocks across the hierarchy.
87
117
  * @returns {{ hooks: Record<string, Array<{matcher:string|null, hooks:Array<{type,command,timeout}>}>>, files:string[] }}
88
118
  */
89
- function loadHooks({ cwd = process.cwd(), settingsFile, onWarn } = {}) {
119
+ function loadHooks({
120
+ cwd = process.cwd(),
121
+ settingsFile,
122
+ onWarn,
123
+ env = process.env,
124
+ } = {}) {
90
125
  const merged = {};
91
126
  const files = [];
92
- // Safe-mode kill switch (`cc agent --safe-mode` sets CC_SETTINGS_HOOKS=0):
93
- // run with NO settings hooks so a broken hook can be diagnosed.
94
- if (process.env.CC_SETTINGS_HOOKS === "0") {
95
- return { hooks: merged, files };
127
+ const managedFile = managedSettingsFile(env);
128
+ let managed = null;
129
+ if (_deps.fs.existsSync(managedFile)) {
130
+ managed = readJson(managedFile, onWarn);
131
+ if (!managed) {
132
+ const error = new Error(
133
+ `managed settings are unreadable or malformed: ${managedFile}`,
134
+ );
135
+ error.code = "CC_MANAGED_SETTINGS_INVALID";
136
+ throw error;
137
+ }
96
138
  }
139
+ // Safe-mode kill switch (`cc agent --safe-mode` sets CC_SETTINGS_HOOKS=0):
140
+ // user/project hooks are disabled, but administrator hooks remain active.
141
+ const managedOnly = managed?.allowManagedHooksOnly === true;
142
+ const skipUnmanaged = env.CC_SETTINGS_HOOKS === "0" || managedOnly;
97
143
  const seenPaths = new Set();
98
- for (const file of settingsFiles(cwd, settingsFile)) {
144
+ for (const file of skipUnmanaged ? [] : settingsFiles(cwd, settingsFile)) {
99
145
  // Dedup by RESOLVED path so the SAME physical file is never read twice — e.g.
100
146
  // `--settings .claude/settings.json` from the project root aliases the
101
147
  // auto-loaded cwd file, which would otherwise CONCATENATE its hook groups a
@@ -106,26 +152,16 @@ function loadHooks({ cwd = process.cwd(), settingsFile, onWarn } = {}) {
106
152
  if (seenPaths.has(resolved)) continue;
107
153
  seenPaths.add(resolved);
108
154
  const data = readJson(file, onWarn);
109
- const block =
110
- data && data.hooks && typeof data.hooks === "object" ? data.hooks : null;
111
- if (!block) continue;
112
- let contributed = false;
113
- for (const [event, groups] of Object.entries(block)) {
114
- if (!Array.isArray(groups)) continue;
115
- for (const g of groups) {
116
- if (!g || typeof g !== "object" || !Array.isArray(g.hooks)) continue;
117
- const cmds = g.hooks.filter(
118
- (h) => h && h.type === "command" && h.command,
119
- );
120
- if (cmds.length === 0) continue;
121
- if (!merged[event]) merged[event] = [];
122
- merged[event].push({ matcher: g.matcher ?? null, hooks: cmds });
123
- contributed = true;
124
- }
125
- }
155
+ const contributed = appendHookBlock(merged, data);
126
156
  if (contributed) files.push(file);
127
157
  }
128
- return { hooks: merged, files };
158
+ if (managed && appendHookBlock(merged, managed)) files.push(managedFile);
159
+ const result = { hooks: merged, files };
160
+ if (managed) {
161
+ result.managed = managed;
162
+ result.managedFile = managedFile;
163
+ }
164
+ return result;
129
165
  }
130
166
 
131
167
  /**
@@ -184,7 +220,8 @@ function collectHooks(hooksBlock, event, toolName) {
184
220
  for (const g of groups) {
185
221
  const fn = compileMatcher(g.matcher);
186
222
  if (fn(umbrella) || (raw && fn(raw))) {
187
- for (const h of g.hooks) out.push({ command: h.command, timeout: h.timeout });
223
+ for (const h of g.hooks)
224
+ out.push({ command: h.command, timeout: h.timeout });
188
225
  }
189
226
  }
190
227
  return out;
@@ -265,6 +302,11 @@ function writeHookTrustStore(store) {
265
302
  function projectHookTrustNotice({ cwd = process.cwd(), settingsFile } = {}) {
266
303
  if (process.env.CC_HOOK_TRUST_NOTICE === "0") return null;
267
304
  if (process.env.CC_SETTINGS_HOOKS === "0") return null; // hooks won't run anyway
305
+ const managedFile = managedSettingsFile(process.env);
306
+ if (_deps.fs.existsSync(managedFile)) {
307
+ const managed = readJson(managedFile);
308
+ if (managed?.allowManagedHooksOnly === true) return null;
309
+ }
268
310
  const home = path.join(_deps.homedir(), ".claude", "settings.json");
269
311
  const explicit = settingsFile ? path.resolve(cwd, settingsFile) : null;
270
312
  const trusted = new Set([home, explicit].filter(Boolean));
@@ -328,6 +370,7 @@ module.exports = {
328
370
  compileMatcher,
329
371
  umbrellaFor,
330
372
  settingsFiles,
373
+ managedSettingsFile,
331
374
  HOOK_EVENTS,
332
375
  _deps,
333
376
  };
@@ -88,6 +88,69 @@ function settingsPaths(cwd, explicitFile) {
88
88
  return list;
89
89
  }
90
90
 
91
+ /** Organization-controlled settings file. This layer is always highest. */
92
+ function managedSettingsPath(opts = {}) {
93
+ if (opts.managedSettingsFile) return path.resolve(opts.managedSettingsFile);
94
+ const env = opts.env || process.env;
95
+ if (env.CC_MANAGED_SETTINGS) return path.resolve(env.CC_MANAGED_SETTINGS);
96
+ if (process.platform === "win32") {
97
+ const base = env.ProgramData || env.PROGRAMDATA || "C:\\ProgramData";
98
+ return path.join(base, "ChainlessChain", "managed-settings.json");
99
+ }
100
+ return "/etc/chainlesschain/managed-settings.json";
101
+ }
102
+
103
+ function loadManagedSettings(opts = {}) {
104
+ const file = managedSettingsPath(opts);
105
+ if (!_deps.fs.existsSync(file)) return { file, settings: null };
106
+ const data = readSettingsFile(file, { onWarn: opts.onWarn });
107
+ if (!data) {
108
+ const error = new Error(
109
+ `managed settings are unreadable or malformed: ${file}`,
110
+ );
111
+ error.code = "CC_MANAGED_SETTINGS_INVALID";
112
+ throw error;
113
+ }
114
+ return { file, settings: data };
115
+ }
116
+
117
+ function emptyRules() {
118
+ return { allow: [], ask: [], deny: [] };
119
+ }
120
+
121
+ /** Apply the non-bypassable permission portion of managed settings. */
122
+ function applyManagedPermissionPolicy(baseRules, managed, sources = {}) {
123
+ const policy = managed && typeof managed === "object" ? managed : {};
124
+ const rules = policy.allowManagedPermissionRulesOnly
125
+ ? emptyRules()
126
+ : {
127
+ allow: [...(baseRules?.allow || [])],
128
+ ask: [...(baseRules?.ask || [])],
129
+ deny: [...(baseRules?.deny || [])],
130
+ };
131
+ const perms =
132
+ policy.permissions && typeof policy.permissions === "object"
133
+ ? policy.permissions
134
+ : {};
135
+ for (const kind of KINDS) {
136
+ accrete(rules[kind], sources, perms[kind], "<managed>", kind);
137
+ }
138
+ return rules;
139
+ }
140
+
141
+ function assertManagedPermissionMode(mode, managed) {
142
+ if (
143
+ mode === "bypassPermissions" &&
144
+ (managed?.disableBypassPermissionsMode === true ||
145
+ managed?.disableBypassPermissionsMode === "disable")
146
+ ) {
147
+ throw new Error(
148
+ 'permission mode "bypassPermissions" is disabled by managed settings',
149
+ );
150
+ }
151
+ return mode;
152
+ }
153
+
91
154
  /** Parse a comma/space separated env override into a string[]. */
92
155
  function parseEnvList(value) {
93
156
  if (!value) return [];
@@ -116,7 +179,7 @@ function loadSettings(opts = {}) {
116
179
  const env = opts.env || process.env;
117
180
  const onWarn = opts.onWarn;
118
181
 
119
- const rules = { allow: [], ask: [], deny: [] };
182
+ let rules = emptyRules();
120
183
  const sources = {};
121
184
  const files = [];
122
185
 
@@ -150,7 +213,27 @@ function loadSettings(opts = {}) {
150
213
  }
151
214
  if (envContributed) files.push("<env>");
152
215
 
153
- return { rules, sources, files };
216
+ const managedLoaded = loadManagedSettings({
217
+ env,
218
+ managedSettingsFile: opts.managedSettingsFile,
219
+ onWarn,
220
+ });
221
+ if (managedLoaded.settings) {
222
+ rules = applyManagedPermissionPolicy(
223
+ rules,
224
+ managedLoaded.settings,
225
+ sources,
226
+ );
227
+ files.push(managedLoaded.file);
228
+ }
229
+
230
+ return {
231
+ rules,
232
+ sources,
233
+ files,
234
+ managed: managedLoaded.settings,
235
+ managedFile: managedLoaded.settings ? managedLoaded.file : null,
236
+ };
154
237
  }
155
238
 
156
239
  /** Look up the source file a matched `{ kind, rule }` came from. */
@@ -236,6 +319,24 @@ function loadSettingsConfig(opts = {}) {
236
319
  }
237
320
  if (contributed) files.push(file);
238
321
  }
322
+ const managed = loadManagedSettings(opts);
323
+ if (managed.settings) {
324
+ const data = managed.settings;
325
+ let contributed = false;
326
+ if (typeof data.model === "string" && data.model.trim()) {
327
+ model = data.model.trim();
328
+ contributed = true;
329
+ }
330
+ if (data.env && typeof data.env === "object" && !Array.isArray(data.env)) {
331
+ for (const [k, v] of Object.entries(data.env)) {
332
+ if (typeof v === "string") {
333
+ env[k] = v;
334
+ contributed = true;
335
+ }
336
+ }
337
+ }
338
+ if (contributed) files.push(managed.file);
339
+ }
239
340
  return { model, env, files };
240
341
  }
241
342
 
@@ -270,6 +371,14 @@ function readBooleanSetting(key, opts = {}) {
270
371
  value = node; // last (closest) layer wins
271
372
  }
272
373
  }
374
+ const managed = loadManagedSettings(opts);
375
+ if (managed.settings) {
376
+ let node = managed.settings;
377
+ for (const p of parts) {
378
+ node = node && typeof node === "object" ? node[p] : undefined;
379
+ }
380
+ if (typeof node === "boolean") value = node;
381
+ }
273
382
  return value;
274
383
  }
275
384
 
@@ -279,6 +388,10 @@ module.exports = {
279
388
  readSettingsFile,
280
389
  readBooleanSetting,
281
390
  settingsPaths,
391
+ managedSettingsPath,
392
+ loadManagedSettings,
393
+ applyManagedPermissionPolicy,
394
+ assertManagedPermissionMode,
282
395
  parseEnvList,
283
396
  ruleSource,
284
397
  addRule,
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Background task listing utilities (ESM)
3
+ * Mirrors Claude Code /tasks behavior
4
+ * @module lib/task-list
5
+ */
6
+
7
+ import { listBackgroundShellTasks } from "../runtime/agent-core.js";
8
+ import { formatBackgroundTasks } from "../repl/tasks-status.js";
9
+ import { logger } from "./logger.js";
10
+
11
+ /**
12
+ * List all background tasks
13
+ * @param {Object} options List options
14
+ * @returns {Promise<Object>} task list result
15
+ */
16
+ export async function listTasks(options = {}) {
17
+ const tasks = listBackgroundShellTasks();
18
+ const active = tasks.filter((t) => t.status === "running");
19
+ const completed = tasks.filter((t) => t.status !== "running");
20
+
21
+ if (tasks.length === 0) {
22
+ logger.info("No background tasks");
23
+ return { count: 0, active: 0, completed: 0, tasks: [] };
24
+ }
25
+
26
+ if (!options.quiet) {
27
+ logger.info(formatBackgroundTasks(tasks));
28
+ }
29
+
30
+ logger.info(
31
+ ` ${active.length} active, ${completed.length} completed (total: ${tasks.length})`,
32
+ );
33
+
34
+ return {
35
+ count: tasks.length,
36
+ active: active.length,
37
+ completed: completed.length,
38
+ tasks,
39
+ formatted: formatBackgroundTasks(tasks),
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Get a specific task by ID
45
+ * @param {string} taskId
46
+ * @returns {Object|null}
47
+ */
48
+ export function getTask(taskId) {
49
+ const tasks = listBackgroundShellTasks();
50
+ return tasks.find((t) => t.id === taskId) || null;
51
+ }
52
+
53
+ export default { listTasks, getTask };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Shared base Commander program factory.
3
+ *
4
+ * Both the eager path (src/index.js `createProgram`, used by tests, help, and
5
+ * the unknown-command fallback) and the lazy fast path (src/lazy-dispatch.js,
6
+ * used by the bin for a resolved `cc <cmd>`) build their program from this so
7
+ * the program name, version flag, and global options can never drift between
8
+ * the two code paths.
9
+ */
10
+ import { Command } from "commander";
11
+ import { VERSION } from "./constants.js";
12
+
13
+ export function createBaseProgram() {
14
+ const program = new Command();
15
+ program
16
+ .name("chainlesschain")
17
+ .description(
18
+ "CLI for ChainlessChain - install, configure, and manage your personal AI management system",
19
+ )
20
+ .version(VERSION, "-v, --version")
21
+ .option("--verbose", "Enable verbose output")
22
+ .option("--quiet", "Suppress non-essential output");
23
+ return program;
24
+ }