chainlesschain 0.162.35 → 0.162.36

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 (187) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-CJn02U42.js → AIOps-vAVAFNJ4.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-ewURAAoy.js → ActionButton-BnRHFCKM.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-BiSadESb.js → Analytics-BOjwqWqG.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-BR0WOEug.js → AppLayout-Dc0D1Txn.js} +5 -5
  6. package/src/assets/web-panel/assets/{Audit-CrqcYx0e.js → Audit-dd_2efaZ.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-DtbSBn4e.js → Backup-HF1jgm8G.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-BjSc9j0o.js → BaseInput-CCtzmoKe.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-ixzrlCJE.js → Chat-BNfH1c3p.js} +6 -6
  10. package/src/assets/web-panel/assets/{ChatBubbleRenderer-B78nEq05.js → ChatBubbleRenderer-DCWFqmI4.js} +1 -1
  11. package/src/assets/web-panel/assets/{Checkbox-UGYeSsgr.js → Checkbox-BOr-NscK.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen-B97OOAg4.js → Codegen-DE058N7-.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-D9aGkaZ6.js → Col-SOREo1XE.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-Dc2v2RGS.js → Community-sOvNZo9f.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-B_FYlUQR.js → Compact-DnBe558D.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-C4FiTHyC.js → Compliance-o-r6CUbg.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-CQ8j3LIg.js → Cowork-D6_k9mHP.js} +3 -3
  18. package/src/assets/web-panel/assets/{Cron-Dzjs9Z9Z.js → Cron-CEV3Xkrm.js} +2 -2
  19. package/src/assets/web-panel/assets/{Crosschain-BXI24uzI.js → Crosschain-eJ1lQWKU.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-C-I4_d07.js → DID-B-WqM9Hp.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dashboard-BzzGh5mo.js → Dashboard-ZnKPcsHN.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-Bh8H70De.js → Dropdown-B8uLWDIP.js} +1 -1
  23. package/src/assets/web-panel/assets/{EmailListRenderer-DI_qybJP.js → EmailListRenderer-Jmj2Y7aH.js} +1 -1
  24. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DkKTsfc4.js → FamilyGuardDashboard-Cb2xetG-.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-DS7CmvVG.js → Federation-C_07GXoq.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-CI97WsB5.js → FormItemContext-D3kbYrMU.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-Da27EdR4.js → GenericCardRenderer-9xgqvGPg.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-CEh0gR2W.js → Git-BlwWlMMB.js} +2 -2
  29. package/src/assets/web-panel/assets/{Governance-kIr3tls2.js → Governance-DxN3wQZ_.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-CC1GzyC1.js → Inference-ls7pSw_D.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph-BNgTiWOB.js → KnowledgeGraph-_n9hYuPI.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-B2P10gB1.js → Logs-CvEVY5TK.js} +2 -2
  33. package/src/assets/web-panel/assets/{Marketplace-HPfBvbFZ.js → Marketplace-C3qvQJT7.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-ByYotSKb.js → McpTools-DiwKpnKx.js} +3 -3
  35. package/src/assets/web-panel/assets/{Memory-BGIAzFVS.js → Memory-CIBPi_da.js} +2 -2
  36. package/src/assets/web-panel/assets/{MobileBridge-CroNYTAH.js → MobileBridge-D-v0Se8y.js} +2 -2
  37. package/src/assets/web-panel/assets/MobileProjects-cP1apTQD.js +1 -0
  38. package/src/assets/web-panel/assets/{Mtc-BqhyIwo9.js → Mtc-BMFWrI65.js} +4 -4
  39. package/src/assets/web-panel/assets/{MtcAudit-BpEKOvx9.js → MtcAudit-2s8LaHtR.js} +2 -2
  40. package/src/assets/web-panel/assets/{Multisig-DST1d_Qo.js → Multisig-dL_nvj7d.js} +3 -3
  41. package/src/assets/web-panel/assets/{NLProgramming-DlMsZcK_.js → NLProgramming-BbrJp06R.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-C734UJvD.js → Notes-jR9irwy3.js} +3 -3
  43. package/src/assets/web-panel/assets/{NotificationSettings-C0-pPxvk.js → NotificationSettings-Dk-STCIX.js} +1 -1
  44. package/src/assets/web-panel/assets/{OrderTableRenderer-C7zT9eFc.js → OrderTableRenderer-CqqfY6zq.js} +1 -1
  45. package/src/assets/web-panel/assets/{Organization-C5iHC_yW.js → Organization-BCK5jylo.js} +4 -4
  46. package/src/assets/web-panel/assets/{Overflow-CovuHHVR.js → Overflow-BRAY7Smt.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-Dx9QL-Gy.js → P2P-BltVRGjb.js} +2 -2
  48. package/src/assets/web-panel/assets/{PdhVaultBrowser-IP1dEt6-.js → PdhVaultBrowser-CV8UbXHe.js} +4 -4
  49. package/src/assets/web-panel/assets/{Permissions-BrR1XZG5.js → Permissions-_tNl47Qh.js} +4 -4
  50. package/src/assets/web-panel/assets/{PersonalDataHub-BgqxVE5m.js → PersonalDataHub-Cgc4HjpX.js} +2 -2
  51. package/src/assets/web-panel/assets/{Pipeline-DzMk5HAz.js → Pipeline-Bn_QU4mu.js} +1 -1
  52. package/src/assets/web-panel/assets/{Privacy-CDoLa6tk.js → Privacy-jzJowp5P.js} +1 -1
  53. package/src/assets/web-panel/assets/{ProjectInit-Dy5gc6ve.js → ProjectInit-B_1pJ8qd.js} +2 -2
  54. package/src/assets/web-panel/assets/{ProjectSettings-DXy-k4hG.js → ProjectSettings-CPVZpXzs.js} +2 -2
  55. package/src/assets/web-panel/assets/Projects-CQsHOWnT.js +1 -0
  56. package/src/assets/web-panel/assets/Providers-CzzMiLC0.js +1 -0
  57. package/src/assets/web-panel/assets/{QuickAsk-B8KEHCnd.js → QuickAsk-MxBKIn9o.js} +1 -1
  58. package/src/assets/web-panel/assets/{Recommend-DNVHGYYZ.js → Recommend-D8lN6Lis.js} +1 -1
  59. package/src/assets/web-panel/assets/{Reputation-CaDhWP03.js → Reputation-CfYK-IrV.js} +1 -1
  60. package/src/assets/web-panel/assets/{Row-CrGLI02x.js → Row-Bg7NZDP9.js} +1 -1
  61. package/src/assets/web-panel/assets/{RssFeed-BX7P8I6i.js → RssFeed-BOVNJhj0.js} +3 -3
  62. package/src/assets/web-panel/assets/Search-B38qzmhY.js +1 -0
  63. package/src/assets/web-panel/assets/{Security-B6J7IFc1.js → Security-CjqleZpe.js} +4 -4
  64. package/src/assets/web-panel/assets/{Services-vvdcO3mM.js → Services-Bu9JSJap.js} +2 -2
  65. package/src/assets/web-panel/assets/{Skeleton-BoAoPTzZ.js → Skeleton-B2RvRkaX.js} +1 -1
  66. package/src/assets/web-panel/assets/{Skills-CyIQV5b3.js → Skills-_h42mxMN.js} +1 -1
  67. package/src/assets/web-panel/assets/{Sla-BAQVgdZV.js → Sla-BssLs56D.js} +1 -1
  68. package/src/assets/web-panel/assets/{SpeechSettings-Bxcn1Jkj.js → SpeechSettings-DCxFYHsd.js} +1 -1
  69. package/src/assets/web-panel/assets/{SyncSettings-Dpaj3hDM.js → SyncSettings-D2xQuNLE.js} +2 -2
  70. package/src/assets/web-panel/assets/{Tasks-Bwqo89En.js → Tasks-DhpOGOlo.js} +1 -1
  71. package/src/assets/web-panel/assets/{Templates-Bowcqifn.js → Templates-CYG-R-aS.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tenant-DOkf85uG.js → Tenant-BQRYLsvP.js} +1 -1
  73. package/src/assets/web-panel/assets/{Terminal-v4MM9dCj.js → Terminal-imKU7N5j.js} +2 -2
  74. package/src/assets/web-panel/assets/{TimelineRenderer-B9A3zDXA.js → TimelineRenderer-BIZzBftk.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tokens-jtVVqKFr.js → Tokens-uMLH5p_a.js} +1 -1
  76. package/src/assets/web-panel/assets/{Trigger-26Iw-iIl.js → Trigger-BzS6XPqx.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trust-DqY5ORrH.js → Trust-R4zhHufZ.js} +1 -1
  78. package/src/assets/web-panel/assets/{UkeySign-BFsbr3y7.js → UkeySign-DATQCoGe.js} +1 -1
  79. package/src/assets/web-panel/assets/{VideoEditing-BtDbj3oa.js → VideoEditing-ClUmKOtS.js} +1 -1
  80. package/src/assets/web-panel/assets/{Wallet-BAwmwHbk.js → Wallet-DzJTbQzD.js} +4 -4
  81. package/src/assets/web-panel/assets/{WebAuthn-DINJTsfq.js → WebAuthn-CrXrLmzQ.js} +5 -5
  82. package/src/assets/web-panel/assets/{WorkflowEditor-BEorm8SK.js → WorkflowEditor-CpvZ0Tma.js} +1 -1
  83. package/src/assets/web-panel/assets/{chat-CE39-Dxg.js → chat-a6wpYmVL.js} +1 -1
  84. package/src/assets/web-panel/assets/{colors-C_cLZ93a.js → colors-CXJADb1t.js} +1 -1
  85. package/src/assets/web-panel/assets/{compact-item-BSioWA2c.js → compact-item-CL2pohS_.js} +1 -1
  86. package/src/assets/web-panel/assets/{createContext-CGTk4mhN.js → createContext-xFi_1G5_.js} +1 -1
  87. package/src/assets/web-panel/assets/devWarning-BtmELbtB.js +1 -0
  88. package/src/assets/web-panel/assets/{hasIn-Dl1fRwS_.js → hasIn-Bchh1rAi.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-BAhinBPR.js → index-B3Tpv7-d.js} +1 -1
  90. package/src/assets/web-panel/assets/index-B4l4vLTB.js +1 -0
  91. package/src/assets/web-panel/assets/{index-BWpfxzVm.js → index-B4zNisy9.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-CA6K7lZB.js → index-B6NehWty.js} +1 -1
  93. package/src/assets/web-panel/assets/index-B7Ek5iiY.js +1 -0
  94. package/src/assets/web-panel/assets/{index-DJyeeygd.js → index-B7knYOpm.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-hv4jUdG3.js → index-B7wT5VRi.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-9_mmaR42.js → index-BF4xx1_b.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-Cxw3p73X.js → index-BH9t10pe.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B016Fsqr.js → index-BPH5ESqs.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-BmbVyhk1.js → index-BmsIKzyu.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CST381Qf.js → index-BoaRB-4a.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-D9D4q-qI.js → index-BrbJBnT-.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-pngH1and.js → index-C2eMYASq.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DKEipmR8.js → index-C4yBRKT4.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-B2QiUEgK.js → index-CGq4HQno.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C4JXchTG.js → index-CMybtJY6.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-iiZfONfx.js → index-CR3kFPuC.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DTKEXyaW.js → index-CTRd7vkq.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C2ly7sCw.js → index-CdU8BwRW.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Di6nvW1N.js → index-Cua_P8St.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BnEPB1Mz.js → index-CuehgDOp.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DrWERr8C.js → index-D-TT9Swq.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-II3JhQu2.js → index-DEYcLAl7.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CbXnyoSO.js → index-DQ_hw_5P.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Ceo9P9tQ.js → index-DTEu7TSF.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DDQx2YFc.js → index-DVo1GJoj.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-C-VVk1Jg.js → index-DjdOL159.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CAwVwBOL.js → index-DsbMVBj1.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Bvi14vJ7.js → index-DxahxRP7.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BhqOTuMW.js → index-EPERz4Pu.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Ds2RzRG0.js → index-IkvkNxbc.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-ChwpS1f0.js → index-KCib1PTw.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-OCxo0X6J.js → index-M8SZI11a.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Qj2x55mz.js → index-TxbHusq2.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CisXVbSt.js → index-dsLc7t6W.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C9tq8Da8.js → index-jMcv1u5o.js} +1 -1
  126. package/src/assets/web-panel/assets/{index--SWvw6yW.js → index-majCS3s2.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DTpCUi0m.js → index-u8K1y_lh.js} +1 -1
  128. package/src/assets/web-panel/assets/{initDefaultProps-GOhLA2-f.js → initDefaultProps-DYn3Gc09.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-jqxFzHTx.js → motion-ZS3eolb9.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-CSLsp6TA.js → move-CEw4uqr3.js} +1 -1
  131. package/src/assets/web-panel/assets/{omit-Cnlrb25c.js → omit-DlHFZnPp.js} +1 -1
  132. package/src/assets/web-panel/assets/{pickAttrs-CLqlxWWD.js → pickAttrs-eZQvV5fA.js} +1 -1
  133. package/src/assets/web-panel/assets/{placementArrow-BAWIWtul.js → placementArrow-B31jQwa-.js} +1 -1
  134. package/src/assets/web-panel/assets/{responsiveObserve-CSR1DayS.js → responsiveObserve-DAsNmVto.js} +1 -1
  135. package/src/assets/web-panel/assets/{slide-CNhoPJOp.js → slide-gPQPrYZC.js} +1 -1
  136. package/src/assets/web-panel/assets/{statusUtils-BZiYHRHW.js → statusUtils-DwWKX5co.js} +1 -1
  137. package/src/assets/web-panel/assets/{styleChecker-BMoY-Fm5.js → styleChecker-B3VOtXuH.js} +1 -1
  138. package/src/assets/web-panel/assets/{useFlexGapSupport-DhtNdlaS.js → useFlexGapSupport-6ADctM2r.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFs-DNPtDOZ4.js → useFs-6Zx1SSKs.js} +1 -1
  140. package/src/assets/web-panel/assets/{usePersonalDataHub-DTdjNvAI.js → usePersonalDataHub-BzReowln.js} +1 -1
  141. package/src/assets/web-panel/assets/{vnode-C9zW9IJ2.js → vnode-C8IpEQbD.js} +1 -1
  142. package/src/assets/web-panel/assets/{zoom-D-6RYJJr.js → zoom-ruc9vHr0.js} +1 -1
  143. package/src/assets/web-panel/index.html +1 -1
  144. package/src/commands/agent.js +161 -6
  145. package/src/commands/agents.js +8 -2
  146. package/src/commands/command.js +7 -2
  147. package/src/commands/hook.js +136 -28
  148. package/src/commands/ide.js +168 -0
  149. package/src/commands/mcp.js +92 -0
  150. package/src/commands/output-style.js +127 -0
  151. package/src/commands/permissions.js +211 -0
  152. package/src/commands/statusline.js +93 -0
  153. package/src/index.js +8 -2
  154. package/src/lib/agent-core.js +7 -0
  155. package/src/lib/agents.js +5 -0
  156. package/src/lib/hook-manager.js +1 -0
  157. package/src/lib/hook-runner.cjs +183 -0
  158. package/src/lib/ide-bridge.js +310 -0
  159. package/src/lib/image-input.js +156 -0
  160. package/src/lib/mcp-oauth.js +415 -0
  161. package/src/lib/output-styles.js +179 -0
  162. package/src/lib/permission-rules.cjs +325 -0
  163. package/src/lib/provider-options.js +11 -7
  164. package/src/lib/settings-hook-events.cjs +102 -0
  165. package/src/lib/settings-hooks.cjs +163 -0
  166. package/src/lib/settings-loader.cjs +244 -0
  167. package/src/lib/slash-commands.js +4 -0
  168. package/src/lib/status-line.cjs +204 -0
  169. package/src/lib/sub-agent-profiles.js +3 -0
  170. package/src/lib/web-search.js +487 -0
  171. package/src/repl/agent-repl.js +445 -35
  172. package/src/repl/slash-macro.js +45 -0
  173. package/src/runtime/agent-core.js +799 -21
  174. package/src/runtime/coding-agent-contract-shared.cjs +94 -4
  175. package/src/runtime/coding-agent-policy.cjs +24 -0
  176. package/src/runtime/headless-runner.js +162 -6
  177. package/src/runtime/headless-stream.js +133 -7
  178. package/src/runtime/mcp-config.js +161 -15
  179. package/src/runtime/policies/agent-policy.js +1 -0
  180. package/src/runtime/system-prompt.js +6 -1
  181. package/src/assets/web-panel/assets/MobileProjects-CH-qnGEV.js +0 -1
  182. package/src/assets/web-panel/assets/Projects-DvsaEbZR.js +0 -1
  183. package/src/assets/web-panel/assets/Providers-Demck9PO.js +0 -1
  184. package/src/assets/web-panel/assets/Search-laS6rz8M.js +0 -1
  185. package/src/assets/web-panel/assets/devWarning-PObcVnJR.js +0 -1
  186. package/src/assets/web-panel/assets/index-BNwIzLyX.js +0 -1
  187. package/src/assets/web-panel/assets/index-Dh6FxR9B.js +0 -1
@@ -65,6 +65,98 @@ export function registerMcpCommand(program) {
65
65
  .command("mcp")
66
66
  .description("MCP server management and tool execution");
67
67
 
68
+ // mcp login — OAuth 2.0 (Auth Code + PKCE) for a remote MCP server.
69
+ mcp
70
+ .command("login <url>")
71
+ .description("Authorize a remote MCP server via OAuth (opens a browser); stores the token")
72
+ .option("--scope <scope>", "OAuth scope(s) to request")
73
+ .option("--client-id <id>", "Use a pre-registered client_id instead of dynamic registration")
74
+ .option("--port <n>", "Localhost callback port", (v) => parseInt(v, 10), 53682)
75
+ .option("--no-open", "Print the authorize URL instead of opening a browser")
76
+ .action(async (url, options) => {
77
+ try {
78
+ const oauth = await import("../lib/mcp-oauth.js");
79
+ if (options.open === false) {
80
+ oauth._deps.openBrowser = () => false; // commander maps --no-open → open:false
81
+ }
82
+ logger.log(chalk.gray(`Authorizing ${url} …`));
83
+ const rec = await oauth.authorizeInteractive(url, {
84
+ scope: options.scope,
85
+ clientId: options.clientId,
86
+ port: options.port,
87
+ writeOut: (s) => process.stdout.write(s),
88
+ });
89
+ logger.log(
90
+ chalk.green(`✓ authorized ${rec.server}`) +
91
+ chalk.gray(
92
+ rec.expires_at
93
+ ? ` (expires ${new Date(rec.expires_at).toISOString()})`
94
+ : "",
95
+ ),
96
+ );
97
+ logger.log(
98
+ chalk.gray("The token is injected as a Bearer header on connect."),
99
+ );
100
+ } catch (err) {
101
+ logger.error(chalk.red(`mcp login failed: ${err.message}`));
102
+ process.exitCode = 1;
103
+ }
104
+ });
105
+
106
+ // mcp logout — forget a stored OAuth token.
107
+ mcp
108
+ .command("logout <url>")
109
+ .description("Delete the stored OAuth token for a remote MCP server")
110
+ .action(async (url) => {
111
+ try {
112
+ const { deleteStoredToken, serverKey } = await import("../lib/mcp-oauth.js");
113
+ const ok = deleteStoredToken(url);
114
+ logger.log(
115
+ ok
116
+ ? chalk.green(`✓ removed token for ${serverKey(url)}`)
117
+ : chalk.gray(`no stored token for ${serverKey(url)}`),
118
+ );
119
+ } catch (err) {
120
+ logger.error(chalk.red(`mcp logout failed: ${err.message}`));
121
+ process.exitCode = 1;
122
+ }
123
+ });
124
+
125
+ // mcp auth — list stored OAuth tokens.
126
+ mcp
127
+ .command("auth")
128
+ .description("List stored MCP OAuth tokens")
129
+ .option("--json", "Output as JSON")
130
+ .action(async (options) => {
131
+ try {
132
+ const { loadTokenStore, isTokenExpired } = await import("../lib/mcp-oauth.js");
133
+ const store = loadTokenStore();
134
+ const rows = Object.values(store).map((r) => ({
135
+ server: r.server,
136
+ expired: isTokenExpired(r),
137
+ expires_at: r.expires_at || null,
138
+ refresh: Boolean(r.refresh_token),
139
+ }));
140
+ if (options.json) {
141
+ console.log(JSON.stringify(rows, null, 2));
142
+ return;
143
+ }
144
+ if (rows.length === 0) {
145
+ logger.log(chalk.gray("No MCP OAuth tokens. Run: cc mcp login <url>"));
146
+ return;
147
+ }
148
+ for (const r of rows) {
149
+ const state = r.expired ? chalk.red("expired") : chalk.green("valid");
150
+ logger.log(
151
+ ` ${chalk.cyan(r.server)} [${state}]${r.refresh ? chalk.gray(" +refresh") : ""}`,
152
+ );
153
+ }
154
+ } catch (err) {
155
+ logger.error(chalk.red(`mcp auth failed: ${err.message}`));
156
+ process.exitCode = 1;
157
+ }
158
+ });
159
+
68
160
  // mcp servers — list configured servers
69
161
  mcp
70
162
  .command("servers")
@@ -0,0 +1,127 @@
1
+ /**
2
+ * cc output-style — list / show output-style personas (Claude-Code parity).
3
+ *
4
+ * cc output-style list [--json] list built-ins + .claude/output-styles/*.md
5
+ * cc output-style show <name> show a style's metadata + body
6
+ * cc output-style new <name> scaffold a new style file
7
+ *
8
+ * Apply one with `cc agent --output-style <name>` or the REPL `/output-style`,
9
+ * or set a default via `outputStyle` in .claude/settings.json.
10
+ */
11
+
12
+ import chalk from "chalk";
13
+ import { logger } from "../lib/logger.js";
14
+
15
+ export function registerOutputStyleCommand(program) {
16
+ const cmd = program
17
+ .command("output-style")
18
+ .alias("output-styles")
19
+ .description("List / show agent output-style personas");
20
+
21
+ cmd
22
+ .command("list", { isDefault: true })
23
+ .alias("ls")
24
+ .description("List built-in + .claude/output-styles/*.md personas")
25
+ .option("--json", "Output as JSON")
26
+ .action(async (options) => {
27
+ try {
28
+ const { discoverOutputStyles, settingsDefaultOutputStyle } =
29
+ await import("../lib/output-styles.js");
30
+ const all = discoverOutputStyles(process.cwd());
31
+ const dflt = settingsDefaultOutputStyle(process.cwd());
32
+ if (options.json) {
33
+ console.log(JSON.stringify({ default: dflt, styles: all }, null, 2));
34
+ return;
35
+ }
36
+ for (const s of all) {
37
+ const tag = s.builtin
38
+ ? chalk.gray("[builtin]")
39
+ : s.scope === "project"
40
+ ? chalk.cyan("[proj]")
41
+ : chalk.gray("[pers]");
42
+ const star = s.name === dflt ? chalk.green(" *") : "";
43
+ logger.log(
44
+ `${chalk.bold(s.name.padEnd(16))} ${tag}${star} ${chalk.gray(s.description || "")}`,
45
+ );
46
+ }
47
+ if (dflt) logger.log(chalk.dim(`\ndefault (settings.json): ${dflt}`));
48
+ } catch (err) {
49
+ logger.error(chalk.red(`output-style list failed: ${err.message}`));
50
+ process.exitCode = 1;
51
+ }
52
+ });
53
+
54
+ cmd
55
+ .command("show <name>")
56
+ .description("Show a style's metadata and body")
57
+ .option("--json", "Output as JSON")
58
+ .action(async (name, options) => {
59
+ try {
60
+ const { getOutputStyle } = await import("../lib/output-styles.js");
61
+ const s = getOutputStyle(name, process.cwd());
62
+ if (!s) {
63
+ logger.error(chalk.red(`no such output style: ${name}`));
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+ if (options.json) {
68
+ console.log(JSON.stringify(s, null, 2));
69
+ return;
70
+ }
71
+ logger.log(
72
+ chalk.bold(s.name) +
73
+ (s.builtin ? chalk.gray(" [builtin]") : chalk.gray(` [${s.scope}]`)),
74
+ );
75
+ if (s.description) logger.log(chalk.gray(` ${s.description}`));
76
+ if (s.file) logger.log(chalk.gray(` file: ${s.file}`));
77
+ logger.log(chalk.dim(" ───"));
78
+ logger.log(s.body || chalk.gray("(empty — no persona overlay)"));
79
+ } catch (err) {
80
+ logger.error(chalk.red(`output-style show failed: ${err.message}`));
81
+ process.exitCode = 1;
82
+ }
83
+ });
84
+
85
+ cmd
86
+ .command("new <name>")
87
+ .description("Scaffold a new style under .claude/output-styles/")
88
+ .option("--description <d>", "Frontmatter description")
89
+ .option("--personal", "Create under ~/.claude/output-styles instead of project")
90
+ .action(async (name, options) => {
91
+ try {
92
+ const fs = await import("node:fs");
93
+ const path = await import("node:path");
94
+ const { homedir } = await import("node:os");
95
+ const safe = String(name).replace(/[^\w.-]/g, "-");
96
+ const root = options.personal
97
+ ? path.join(homedir(), ".claude", "output-styles")
98
+ : path.join(process.cwd(), ".claude", "output-styles");
99
+ const file = path.join(root, `${safe}.md`);
100
+ if (fs.existsSync(file)) {
101
+ logger.error(chalk.red(`already exists: ${file}`));
102
+ process.exitCode = 1;
103
+ return;
104
+ }
105
+ fs.mkdirSync(path.dirname(file), { recursive: true });
106
+ const tpl = `---
107
+ name: ${safe}
108
+ description: ${options.description || name}
109
+ ---
110
+
111
+ ## Output style: ${safe}
112
+
113
+ Describe how the agent should behave in this style. This text is appended to
114
+ the system prompt (after the base coding instructions), so keep it focused on
115
+ *behaviour / tone*, not tool mechanics.
116
+ `;
117
+ fs.writeFileSync(file, tpl, "utf-8");
118
+ logger.log(chalk.green(`✓ created ${file}`));
119
+ logger.log(
120
+ chalk.gray(` use it: cc agent --output-style ${safe} -p "..."`),
121
+ );
122
+ } catch (err) {
123
+ logger.error(chalk.red(`output-style new failed: ${err.message}`));
124
+ process.exitCode = 1;
125
+ }
126
+ });
127
+ }
@@ -0,0 +1,211 @@
1
+ /**
2
+ * cc permissions — inspect, dry-run, and edit the `.claude/settings.json`
3
+ * permission ruleset (Claude-Code `permissions.{allow,ask,deny}` parity).
4
+ *
5
+ * cc permissions list [--json] merged ruleset + source file
6
+ * cc permissions test <tool> <args...> dry-run: which rule decides?
7
+ * cc permissions add <allow|ask|deny> <rule> append a rule to a settings file
8
+ * [--local | --user] (default target: project)
9
+ *
10
+ * The ruleset is loaded by settings-loader (user < project < local < env) and
11
+ * evaluated by permission-rules (deny > ask > allow). This command only reads
12
+ * and edits the files / runs the engine — it does not yet gate the agent tool
13
+ * loop (that wiring is a separate, riskier step).
14
+ */
15
+
16
+ import chalk from "chalk";
17
+ import { logger } from "../lib/logger.js";
18
+
19
+ const KIND_COLOR = {
20
+ allow: chalk.green,
21
+ ask: chalk.yellow,
22
+ deny: chalk.red,
23
+ };
24
+
25
+ /** Resolve an umbrella token (Bash) to a concrete tool name for dry-run. */
26
+ function resolveConcreteTool(token, groups) {
27
+ const t = String(token || "");
28
+ const lower = t.toLowerCase();
29
+ if (Object.prototype.hasOwnProperty.call(groups, lower)) {
30
+ return groups[lower][0];
31
+ }
32
+ return t;
33
+ }
34
+
35
+ /** Build the tool args object a dry-run target needs from positional args. */
36
+ function buildArgs(tool, positional, rulesMod) {
37
+ const joined = positional.join(" ").trim();
38
+ if (rulesMod.COMMAND_TOOLS.has(tool)) return { command: joined };
39
+ if (rulesMod.PATH_TOOLS.has(tool)) return { path: positional[0] || "" };
40
+ if (rulesMod.URL_TOOLS.has(tool)) return { url: positional[0] || "" };
41
+ return {};
42
+ }
43
+
44
+ export function registerPermissionsCommand(program) {
45
+ const cmd = program
46
+ .command("permissions")
47
+ .alias("perms")
48
+ .description(
49
+ "Inspect / dry-run / edit .claude/settings.json permission rules",
50
+ );
51
+
52
+ // ── list ──────────────────────────────────────────────────────────────
53
+ cmd
54
+ .command("list")
55
+ .alias("ls")
56
+ .description("Show the merged permission ruleset and where each rule came from")
57
+ .option("--json", "Output as JSON")
58
+ .option("--settings <file>", "Also merge an explicit settings file")
59
+ .action(async (options) => {
60
+ try {
61
+ const { loadSettings } = await import("../lib/settings-loader.cjs");
62
+ const { rules, sources, files } = loadSettings({
63
+ cwd: process.cwd(),
64
+ settingsFile: options.settings,
65
+ });
66
+ if (options.json) {
67
+ console.log(JSON.stringify({ rules, sources, files }, null, 2));
68
+ return;
69
+ }
70
+ const total =
71
+ rules.allow.length + rules.ask.length + rules.deny.length;
72
+ if (total === 0) {
73
+ logger.log(
74
+ chalk.gray(
75
+ "No permission rules. Add one: cc permissions add deny \"Bash(rm:*)\"\n" +
76
+ "(or create .claude/settings.json with a permissions block)",
77
+ ),
78
+ );
79
+ return;
80
+ }
81
+ for (const kind of ["deny", "ask", "allow"]) {
82
+ if (rules[kind].length === 0) continue;
83
+ logger.log(KIND_COLOR[kind].bold(`${kind} (${rules[kind].length})`));
84
+ for (const rule of rules[kind]) {
85
+ const src = sources[`${kind}:${rule}`] || "?";
86
+ logger.log(` ${rule.padEnd(34)} ${chalk.gray(src)}`);
87
+ }
88
+ }
89
+ if (files.length) {
90
+ logger.log(chalk.dim(`\nsources: ${files.join(", ")}`));
91
+ }
92
+ } catch (err) {
93
+ logger.error(chalk.red(`permissions list failed: ${err.message}`));
94
+ process.exitCode = 1;
95
+ }
96
+ });
97
+
98
+ // ── test (dry-run) ─────────────────────────────────────────────────────
99
+ cmd
100
+ .command("test <tool> [args...]")
101
+ .description(
102
+ 'Dry-run a tool call against the ruleset, e.g. permissions test run_shell "git push"',
103
+ )
104
+ .option("--json", "Output as JSON")
105
+ .option("--settings <file>", "Also merge an explicit settings file")
106
+ .action(async (tool, args, options) => {
107
+ try {
108
+ const { loadSettings, ruleSource } =
109
+ await import("../lib/settings-loader.cjs");
110
+ // .cjs default-export interop: module.exports surfaces as `.default`.
111
+ const rulesMod = await import("../lib/permission-rules.cjs");
112
+ const mod = rulesMod.default || rulesMod;
113
+
114
+ const { rules, sources } = loadSettings({
115
+ cwd: process.cwd(),
116
+ settingsFile: options.settings,
117
+ });
118
+ const concrete = resolveConcreteTool(tool, mod.TOOL_GROUPS);
119
+ const toolArgs = buildArgs(concrete, args || [], mod);
120
+ const result = mod.evaluatePermissionRules({
121
+ tool: concrete,
122
+ args: toolArgs,
123
+ cwd: process.cwd(),
124
+ rules,
125
+ });
126
+ const decision = result.decision || "fallthrough";
127
+ const source = result.rule
128
+ ? ruleSource(sources, result.decision, result.rule)
129
+ : null;
130
+
131
+ if (options.json) {
132
+ console.log(
133
+ JSON.stringify(
134
+ { tool: concrete, args: toolArgs, decision, rule: result.rule, source },
135
+ null,
136
+ 2,
137
+ ),
138
+ );
139
+ return;
140
+ }
141
+
142
+ const color = KIND_COLOR[result.decision] || chalk.gray;
143
+ logger.log(
144
+ `${chalk.bold(concrete)} ${chalk.gray(JSON.stringify(toolArgs))}`,
145
+ );
146
+ logger.log(` decision: ${color.bold(decision)}`);
147
+ if (result.rule) {
148
+ logger.log(` rule: ${result.rule}`);
149
+ if (source) logger.log(` source: ${chalk.gray(source)}`);
150
+ } else {
151
+ logger.log(
152
+ chalk.gray(
153
+ " no rule matched → falls back to risk-tier / --permission-mode logic",
154
+ ),
155
+ );
156
+ }
157
+ } catch (err) {
158
+ logger.error(chalk.red(`permissions test failed: ${err.message}`));
159
+ process.exitCode = 1;
160
+ }
161
+ });
162
+
163
+ // ── add ────────────────────────────────────────────────────────────────
164
+ cmd
165
+ .command("add <decision> <rule>")
166
+ .description("Append a rule (allow|ask|deny) to a settings file")
167
+ .option("--local", "Write to .claude/settings.local.json (personal, gitignored)")
168
+ .option("--user", "Write to ~/.claude/settings.json (all projects)")
169
+ .action(async (decision, rule, options) => {
170
+ try {
171
+ const kind = String(decision || "").toLowerCase();
172
+ if (!["allow", "ask", "deny"].includes(kind)) {
173
+ logger.error(
174
+ chalk.red(`decision must be allow | ask | deny (got "${decision}")`),
175
+ );
176
+ process.exitCode = 1;
177
+ return;
178
+ }
179
+ const rulesMod = await import("../lib/permission-rules.cjs");
180
+ const mod = rulesMod.default || rulesMod;
181
+ if (!mod.parseRule(rule)) {
182
+ logger.error(
183
+ chalk.red(
184
+ `not a valid rule: "${rule}" (expected Tool or Tool(pattern), e.g. Bash(rm:*))`,
185
+ ),
186
+ );
187
+ process.exitCode = 1;
188
+ return;
189
+ }
190
+
191
+ const scope = options.user ? "user" : options.local ? "local" : "project";
192
+ const { addRule } = await import("../lib/settings-loader.cjs");
193
+ const { file, added } = addRule({
194
+ cwd: process.cwd(),
195
+ kind,
196
+ rule,
197
+ scope,
198
+ });
199
+ if (!added) {
200
+ logger.log(chalk.gray(`already present in ${file}: ${kind} ${rule}`));
201
+ return;
202
+ }
203
+ logger.log(
204
+ `${KIND_COLOR[kind].bold("✓ " + kind)} ${rule} ${chalk.gray("→ " + file)}`,
205
+ );
206
+ } catch (err) {
207
+ logger.error(chalk.red(`permissions add failed: ${err.message}`));
208
+ process.exitCode = 1;
209
+ }
210
+ });
211
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * cc statusline — preview the configured `statusLine` (Claude-Code parity).
3
+ *
4
+ * cc statusline preview the rendered status line
5
+ * cc statusline show show the resolved config (+ source)
6
+ *
7
+ * Configure in .claude/settings.json:
8
+ * { "statusLine": { "type": "command", "command": "~/.claude/status.sh" } }
9
+ * The command receives a JSON context on stdin and its first stdout line is the
10
+ * status line (shown above the REPL prompt each turn).
11
+ */
12
+
13
+ import chalk from "chalk";
14
+ import { logger } from "../lib/logger.js";
15
+
16
+ export function registerStatuslineCommand(program) {
17
+ const cmd = program
18
+ .command("statusline")
19
+ .alias("status-line")
20
+ .description("Preview / show the .claude/settings.json statusLine");
21
+
22
+ cmd
23
+ .command("preview", { isDefault: true })
24
+ .description("Render the configured status line once")
25
+ .option("--model <m>", "Model to pass in the context", "opus")
26
+ .option("--json", "Output as JSON")
27
+ .action(async (options) => {
28
+ try {
29
+ const { loadStatusLineConfig, buildContext, renderStatusLine } =
30
+ await import("../lib/status-line.cjs");
31
+ const cfg = loadStatusLineConfig({ cwd: process.cwd() });
32
+ if (!cfg) {
33
+ logger.log(
34
+ chalk.gray(
35
+ 'No statusLine configured. Add to .claude/settings.json:\n' +
36
+ ' { "statusLine": { "type": "command", "command": "./status.sh" } }',
37
+ ),
38
+ );
39
+ return;
40
+ }
41
+ const line = renderStatusLine(
42
+ cfg,
43
+ buildContext({
44
+ sessionId: "preview",
45
+ model: options.model,
46
+ cwd: process.cwd(),
47
+ }),
48
+ { cwd: process.cwd() },
49
+ );
50
+ if (options.json) {
51
+ console.log(JSON.stringify({ config: cfg, line }, null, 2));
52
+ return;
53
+ }
54
+ if (line == null) {
55
+ logger.error(
56
+ chalk.red(
57
+ `statusLine command produced no output (or failed): ${cfg.command}`,
58
+ ),
59
+ );
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+ process.stdout.write(line + "\n");
64
+ } catch (err) {
65
+ logger.error(chalk.red(`statusline preview failed: ${err.message}`));
66
+ process.exitCode = 1;
67
+ }
68
+ });
69
+
70
+ cmd
71
+ .command("show")
72
+ .description("Show the resolved statusLine config")
73
+ .option("--json", "Output as JSON")
74
+ .action(async (options) => {
75
+ try {
76
+ const { loadStatusLineConfig } = await import("../lib/status-line.cjs");
77
+ const cfg = loadStatusLineConfig({ cwd: process.cwd() });
78
+ if (options.json) {
79
+ console.log(JSON.stringify(cfg, null, 2));
80
+ return;
81
+ }
82
+ if (!cfg) {
83
+ logger.log(chalk.gray("No statusLine configured."));
84
+ return;
85
+ }
86
+ logger.log(`command: ${chalk.cyan(cfg.command)}`);
87
+ logger.log(chalk.gray(`type: ${cfg.type} padding: ${cfg.padding}`));
88
+ } catch (err) {
89
+ logger.error(chalk.red(`statusline show failed: ${err.message}`));
90
+ process.exitCode = 1;
91
+ }
92
+ });
93
+ }
package/src/index.js CHANGED
@@ -58,11 +58,14 @@ import { registerRCacheCommand } from "./commands/rcache.js";
58
58
  import { registerSessionCommand } from "./commands/session.js";
59
59
  import { registerCostCommand } from "./commands/cost.js";
60
60
  import { registerContextCommand } from "./commands/context.js";
61
- import { registerAgentsCommand } from "./commands/agents.js";
62
61
  import { registerCheckpointCommand } from "./commands/checkpoint.js";
63
62
  import { registerGoalCommand } from "./commands/goal.js";
64
63
  import { registerCommandCommand } from "./commands/command.js";
65
64
  import { registerCompactCommand } from "./commands/compact.js";
65
+ import { registerPermissionsCommand } from "./commands/permissions.js";
66
+ import { registerOutputStyleCommand } from "./commands/output-style.js";
67
+ import { registerStatuslineCommand } from "./commands/statusline.js";
68
+ import { registerIdeCommand } from "./commands/ide.js";
66
69
  import { registerConsolCommand } from "./commands/consol.js";
67
70
  import { registerImportCommand } from "./commands/import.js";
68
71
  import { registerExportCommand } from "./commands/export.js";
@@ -457,11 +460,14 @@ export function createProgram(opts = {}) {
457
460
  registerSessionCommand(program);
458
461
  registerCostCommand(program);
459
462
  registerContextCommand(program);
460
- registerAgentsCommand(program);
461
463
  registerCheckpointCommand(program);
462
464
  registerGoalCommand(program);
463
465
  registerCommandCommand(program);
464
466
  registerCompactCommand(program);
467
+ registerPermissionsCommand(program);
468
+ registerOutputStyleCommand(program);
469
+ registerStatuslineCommand(program);
470
+ registerIdeCommand(program);
465
471
  registerConsolCommand(program);
466
472
 
467
473
  // Phase 2: Knowledge & content management
@@ -24,5 +24,12 @@ export {
24
24
  agentLoop,
25
25
  formatToolArgs,
26
26
  getActiveMcpServers,
27
+ listBackgroundShellTasks,
28
+ killAllBackgroundShellTasks,
27
29
  _accumulateOllamaStream,
30
+ _accumulateOpenAIStream,
31
+ _accumulateAnthropicStream,
32
+ _toAnthropicMessages,
33
+ _anthropicThinkingParams,
34
+ _normalizeAnthropicResponse,
28
35
  } from "../runtime/agent-core.js";
package/src/lib/agents.js CHANGED
@@ -57,7 +57,12 @@ export function normalizeTools(tools) {
57
57
  export function agentDirs(cwd = process.cwd(), opts = {}) {
58
58
  const path = opts.deps?.path || _deps.path;
59
59
  const home = opts.home || homedir();
60
+ // Project-native first (highest precedence), then the Claude-Code-portable
61
+ // location (so existing `.claude/agents/*.md` work unchanged), then personal.
62
+ // discoverAgents reverses + last-write-wins, so `.chainlesschain/agents/`
63
+ // shadows `.claude/agents/` shadows `~/.claude/agents/` on a name clash.
60
64
  return [
65
+ { dir: path.join(cwd, ".chainlesschain", "agents"), scope: "project" },
61
66
  { dir: path.join(cwd, ".claude", "agents"), scope: "project" },
62
67
  { dir: path.join(home, ".claude", "agents"), scope: "personal" },
63
68
  ];
@@ -40,6 +40,7 @@ export const HookEvents = {
40
40
  SessionEnd: "SessionEnd",
41
41
  PreCompact: "PreCompact",
42
42
  PostCompact: "PostCompact",
43
+ Notification: "Notification",
43
44
  UserPromptSubmit: "UserPromptSubmit",
44
45
  AssistantResponse: "AssistantResponse",
45
46
  AgentStart: "AgentStart",