shadow-claw 1.27.0 → 1.28.0

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 (240) hide show
  1. package/.well-known/ai-catalog.json +11 -0
  2. package/.well-known/mcp/index.html +19 -0
  3. package/.well-known/mcp/server-card.json +52 -0
  4. package/.well-known/mcp/servers.json +15 -0
  5. package/.well-known/mcp.json +52 -0
  6. package/.well-known/oauth-protected-resource +10 -0
  7. package/.well-known/oauth-protected-resource.json +10 -0
  8. package/bin/assert-version-bump.mjs +61 -3
  9. package/bin/assert-version-bump.test.mjs +77 -1
  10. package/bin/build/build.mjs +116 -49
  11. package/bin/build/build.test.mjs +103 -0
  12. package/bin/cli.mjs +299 -237
  13. package/bin/cli.test.mjs +27 -0
  14. package/bin/commands/mcp.mjs +132 -2
  15. package/bin/commands/mcp.test.mjs +166 -0
  16. package/bin/commands/skills-index.mjs +139 -20
  17. package/bin/commands/skills-index.test.mjs +82 -0
  18. package/bin/utils/control-client.mjs +17 -0
  19. package/bin/utils/control-client.test.mjs +46 -0
  20. package/bin/version.mjs +208 -0
  21. package/bin/version.test.mjs +138 -0
  22. package/dist/electron/main.cjs +195 -185
  23. package/dist/lib/components/index.js +21 -21
  24. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  25. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  26. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  27. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  28. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  29. package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
  30. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  31. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  32. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  33. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  34. package/dist/lib/components/shadow-claw/shadow-claw.d.ts +1 -0
  35. package/dist/lib/components/shadow-claw/utils/setupAppLifecycle.d.ts +23 -0
  36. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  37. package/dist/lib/components/shadow-claw-channels.js +1 -1
  38. package/dist/lib/components/shadow-claw-chat.js +1 -1
  39. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  40. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  41. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  42. package/dist/lib/components/shadow-claw-files.js +1 -1
  43. package/dist/lib/components/shadow-claw-git.js +1 -1
  44. package/dist/lib/components/shadow-claw-llm.js +1 -1
  45. package/dist/lib/components/shadow-claw-networking.js +1 -1
  46. package/dist/lib/components/shadow-claw-notifications.js +1 -1
  47. package/dist/lib/components/shadow-claw-pages.js +1 -1
  48. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  49. package/dist/lib/components/shadow-claw-settings.js +1 -1
  50. package/dist/lib/components/shadow-claw-storage.js +1 -1
  51. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  52. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  53. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  54. package/dist/lib/components/shadow-claw-tools.js +1 -1
  55. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  56. package/dist/lib/components/shadow-claw.js +1 -1
  57. package/dist/lib/{configurePeerJs-oODzltaC.js → configurePeerJs-D8Ph0-A9.js} +2 -2
  58. package/dist/lib/{configurePeerJs-oODzltaC.js.map → configurePeerJs-D8Ph0-A9.js.map} +1 -1
  59. package/dist/lib/core/control-plane-client.d.ts +2 -0
  60. package/dist/lib/core/orchestrator/orchestrator.d.ts +10 -0
  61. package/dist/lib/core/orchestrator/utils/operations/channel.d.ts +2 -2
  62. package/dist/lib/core/utils/initControlPlane.d.ts +6 -0
  63. package/dist/lib/index.js +21 -21
  64. package/dist/lib/{initControlPlane-C2zURVIS.js → initControlPlane-BIrWmpzc.js} +76 -9
  65. package/dist/lib/initControlPlane-BIrWmpzc.js.map +1 -0
  66. package/dist/lib/{markdown-C6EHl9zs.js → markdown-DEUoM1c6.js} +2 -2
  67. package/dist/lib/{markdown-C6EHl9zs.js.map → markdown-DEUoM1c6.js.map} +1 -1
  68. package/dist/lib/{orchestrator-KRjx0eba.js → orchestrator-BtVj9bBB.js} +11 -10
  69. package/dist/lib/{orchestrator-KRjx0eba.js.map → orchestrator-BtVj9bBB.js.map} +1 -1
  70. package/dist/lib/{orchestrator-CACLa_Ro.js → orchestrator-CFCW-l1O.js} +52 -4
  71. package/dist/lib/orchestrator-CFCW-l1O.js.map +1 -0
  72. package/dist/lib/{peerjs-DFWOBcXf.js → peerjs-BoBkx9DJ.js} +23 -3
  73. package/dist/lib/peerjs-BoBkx9DJ.js.map +1 -0
  74. package/dist/lib/{push-client-_tiWQsCT.js → push-client-D6hbzDNV.js} +10 -4
  75. package/dist/lib/push-client-D6hbzDNV.js.map +1 -0
  76. package/dist/lib/{shadow-claw-6UHdiy4a.js → shadow-claw-Cuf2O5bZ.js} +71 -4
  77. package/dist/lib/shadow-claw-Cuf2O5bZ.js.map +1 -0
  78. package/dist/lib/{shadow-claw-channel-config-DmfwJc6G.js → shadow-claw-channel-config-BDPKt6Bd.js} +3 -3
  79. package/dist/lib/{shadow-claw-channel-config-DmfwJc6G.js.map → shadow-claw-channel-config-BDPKt6Bd.js.map} +1 -1
  80. package/dist/lib/{shadow-claw-channels-1N6Jl-By.js → shadow-claw-channels-BsP5JABM.js} +2 -2
  81. package/dist/lib/{shadow-claw-channels-1N6Jl-By.js.map → shadow-claw-channels-BsP5JABM.js.map} +1 -1
  82. package/dist/lib/{shadow-claw-chat-BMoqQJRK.js → shadow-claw-chat-Cam2lX4k.js} +4 -4
  83. package/dist/lib/{shadow-claw-chat-BMoqQJRK.js.map → shadow-claw-chat-Cam2lX4k.js.map} +1 -1
  84. package/dist/lib/{shadow-claw-control-plane-UG0o7pCz.js → shadow-claw-control-plane-DB2qcCFs.js} +20 -10
  85. package/dist/lib/shadow-claw-control-plane-DB2qcCFs.js.map +1 -0
  86. package/dist/lib/{shadow-claw-conversations-BwXep3iu.js → shadow-claw-conversations-C9Vf4XGx.js} +2 -2
  87. package/dist/lib/{shadow-claw-conversations-BwXep3iu.js.map → shadow-claw-conversations-C9Vf4XGx.js.map} +1 -1
  88. package/dist/lib/{shadow-claw-file-viewer-DUxzVxDT.js → shadow-claw-file-viewer-B4HYiI0v.js} +3 -3
  89. package/dist/lib/{shadow-claw-file-viewer-DUxzVxDT.js.map → shadow-claw-file-viewer-B4HYiI0v.js.map} +1 -1
  90. package/dist/lib/{shadow-claw-files-DIREEnT2.js → shadow-claw-files-DVROUESO.js} +2 -2
  91. package/dist/lib/{shadow-claw-files-DIREEnT2.js.map → shadow-claw-files-DVROUESO.js.map} +1 -1
  92. package/dist/lib/{shadow-claw-git-Bg1SWgsF.js → shadow-claw-git-BqrO7cHJ.js} +3 -3
  93. package/dist/lib/{shadow-claw-git-Bg1SWgsF.js.map → shadow-claw-git-BqrO7cHJ.js.map} +1 -1
  94. package/dist/lib/{shadow-claw-llm-CazBrVpM.js → shadow-claw-llm-BexUQdYo.js} +2 -2
  95. package/dist/lib/{shadow-claw-llm-CazBrVpM.js.map → shadow-claw-llm-BexUQdYo.js.map} +1 -1
  96. package/dist/lib/{shadow-claw-networking-Df85tCbO.js → shadow-claw-networking-CfXRGpUD.js} +2 -2
  97. package/dist/lib/{shadow-claw-networking-Df85tCbO.js.map → shadow-claw-networking-CfXRGpUD.js.map} +1 -1
  98. package/dist/lib/{shadow-claw-notifications-v62FryTc.js → shadow-claw-notifications-C9KPMgx_.js} +2 -2
  99. package/dist/lib/{shadow-claw-notifications-v62FryTc.js.map → shadow-claw-notifications-C9KPMgx_.js.map} +1 -1
  100. package/dist/lib/{shadow-claw-pages-BgPyIEZO.js → shadow-claw-pages-CGzGXmrI.js} +3 -3
  101. package/dist/lib/{shadow-claw-pages-BgPyIEZO.js.map → shadow-claw-pages-CGzGXmrI.js.map} +1 -1
  102. package/dist/lib/{shadow-claw-peerjs-xkBXILed.js → shadow-claw-peerjs-B0ZB7yhB.js} +3 -3
  103. package/dist/lib/{shadow-claw-peerjs-xkBXILed.js.map → shadow-claw-peerjs-B0ZB7yhB.js.map} +1 -1
  104. package/dist/lib/{shadow-claw-settings-CN89xRVU.js → shadow-claw-settings-DBfMZdDS.js} +2 -2
  105. package/dist/lib/{shadow-claw-settings-CN89xRVU.js.map → shadow-claw-settings-DBfMZdDS.js.map} +1 -1
  106. package/dist/lib/{shadow-claw-storage-VnhcObCe.js → shadow-claw-storage-CM-w6mgG.js} +2 -2
  107. package/dist/lib/{shadow-claw-storage-VnhcObCe.js.map → shadow-claw-storage-CM-w6mgG.js.map} +1 -1
  108. package/dist/lib/{shadow-claw-task-server-jgEC2hHB.js → shadow-claw-task-server-DV4b1g2-.js} +4 -2
  109. package/dist/lib/{shadow-claw-task-server-jgEC2hHB.js.map → shadow-claw-task-server-DV4b1g2-.js.map} +1 -1
  110. package/dist/lib/{shadow-claw-tasks-i_evIufy.js → shadow-claw-tasks-K-foOHSE.js} +3 -3
  111. package/dist/lib/{shadow-claw-tasks-i_evIufy.js.map → shadow-claw-tasks-K-foOHSE.js.map} +1 -1
  112. package/dist/lib/{shadow-claw-terminal-CwScROlu.js → shadow-claw-terminal-CpAknKyA.js} +2 -2
  113. package/dist/lib/{shadow-claw-terminal-CwScROlu.js.map → shadow-claw-terminal-CpAknKyA.js.map} +1 -1
  114. package/dist/lib/{shadow-claw-tools-DD3fyXP4.js → shadow-claw-tools-D98XZ0Ep.js} +3 -3
  115. package/dist/lib/{shadow-claw-tools-DD3fyXP4.js.map → shadow-claw-tools-D98XZ0Ep.js.map} +1 -1
  116. package/dist/lib/{shadow-claw-webvm-DbJq4I3-.js → shadow-claw-webvm-DLOb8dMI.js} +2 -2
  117. package/dist/lib/{shadow-claw-webvm-DbJq4I3-.js.map → shadow-claw-webvm-DLOb8dMI.js.map} +1 -1
  118. package/dist/lib/subsystems/channels/imessage.d.ts +1 -0
  119. package/dist/lib/subsystems/channels/peerjs.d.ts +1 -0
  120. package/dist/lib/subsystems/channels/telegram.d.ts +1 -0
  121. package/dist/lib/subsystems/channels/types.d.ts +2 -0
  122. package/dist/lib/subsystems/notifications/push-client.d.ts +1 -1
  123. package/dist/lib/{syncWebMcpRegistration-DNLnQ-jz.js → syncWebMcpRegistration-NspKefOI.js} +2 -2
  124. package/dist/lib/{syncWebMcpRegistration-DNLnQ-jz.js.map → syncWebMcpRegistration-NspKefOI.js.map} +1 -1
  125. package/dist/public/.well-known/ai-catalog.json +11 -0
  126. package/dist/public/.well-known/mcp/index.html +19 -0
  127. package/dist/public/.well-known/mcp/server-card.json +52 -0
  128. package/dist/public/.well-known/mcp/servers.json +15 -0
  129. package/dist/public/.well-known/mcp.json +52 -0
  130. package/dist/public/.well-known/oauth-protected-resource +10 -0
  131. package/dist/public/.well-known/oauth-protected-resource.json +10 -0
  132. package/dist/public/404.html +28 -1
  133. package/dist/public/AGENTS.md +1 -1
  134. package/dist/public/agent.worker.js +1 -1
  135. package/dist/public/{configurePeerJs-BqgeBjP7.js → configurePeerJs-BhBokQlC.js} +1 -1
  136. package/dist/public/docs/example/article/index.html +3 -3
  137. package/dist/public/docs/publishing/index.html +3 -3
  138. package/dist/public/docs/skill-creator/index.html +3 -3
  139. package/dist/public/docs/subsystems/cli.md +11 -8
  140. package/dist/public/docs/subsystems/mcp-server.md +1 -0
  141. package/dist/public/docs/subsystems/notifications.md +10 -0
  142. package/dist/public/{e2e-bridge-Ceqr5kGc.js → e2e-bridge-DcBoeFvd.js} +1 -1
  143. package/dist/public/{file-viewer-C-6Jc_tb.js → file-viewer-CKtVC9Ix.js} +1 -1
  144. package/dist/public/index.css +1 -1
  145. package/dist/public/index.html +3 -3
  146. package/dist/public/index.js +1 -1
  147. package/dist/public/initControlPlane-Bi8ouFEb.js +1 -0
  148. package/dist/public/llms.txt +36 -1
  149. package/dist/public/main/index.html +3 -3
  150. package/dist/public/main/memory/index.html +3 -3
  151. package/dist/public/{markdown-C3M4OW_A.js → markdown-C-hCVJtc.js} +1 -1
  152. package/dist/public/orchestrator-8qNGfw8r.js +15 -0
  153. package/dist/public/{orchestrator-DHjdLtqa.js → orchestrator-BT3Ks5ip.js} +2 -2
  154. package/dist/public/peerjs-DfhwEiiq.js +1 -0
  155. package/dist/public/push-client-BVLrE9pK.js +1 -0
  156. package/dist/public/service-worker/fetch-proxy.js +1 -1
  157. package/dist/public/service-worker.js +1 -1
  158. package/dist/public/{shadow-claw-EAt2ml5Y.js → shadow-claw-DCjxNDCX.js} +3 -3
  159. package/dist/public/{shadow-claw-channels-XsfuWFF8.js → shadow-claw-channels-CITDrqMl.js} +1 -1
  160. package/dist/public/{shadow-claw-chat-CbSaOZ4q.js → shadow-claw-chat-BQrSgSKF.js} +1 -1
  161. package/dist/public/{shadow-claw-control-plane-DHvN3Ukg.js → shadow-claw-control-plane-Cp001OY0.js} +2 -2
  162. package/dist/public/{shadow-claw-conversations-BWs5VVfs.js → shadow-claw-conversations-EhX4RvIj.js} +1 -1
  163. package/dist/public/{shadow-claw-file-viewer-BWsoW5QS.js → shadow-claw-file-viewer-DiQXIjZD.js} +1 -1
  164. package/dist/public/{shadow-claw-files-CG7MqWiV.js → shadow-claw-files-lkTnSJsn.js} +1 -1
  165. package/dist/public/{shadow-claw-git-DBRPZNav.js → shadow-claw-git-BlcA_z8x.js} +2 -2
  166. package/dist/public/{shadow-claw-llm-DMvLgKXo.js → shadow-claw-llm-CW16X9Rg.js} +1 -1
  167. package/dist/public/{shadow-claw-networking-Dd8Rw31D.js → shadow-claw-networking-ySsMBY_i.js} +1 -1
  168. package/dist/public/{shadow-claw-notifications-Dbevj-lq.js → shadow-claw-notifications-CyV2zCQ8.js} +1 -1
  169. package/dist/public/{shadow-claw-pages-3_lQAv0t.js → shadow-claw-pages-Cx7cF9ah.js} +1 -1
  170. package/dist/public/{shadow-claw-settings-t8TIlgrM.js → shadow-claw-settings-zm4PHHGi.js} +2 -2
  171. package/dist/public/{shadow-claw-storage-CfEXoSIE.js → shadow-claw-storage-dy9JAEGd.js} +1 -1
  172. package/dist/public/{shadow-claw-task-server-DxQSsgRZ.js → shadow-claw-task-server-Bleww48s.js} +2 -2
  173. package/dist/public/{shadow-claw-tasks-DNpicQwz.js → shadow-claw-tasks-CTI5oaLN.js} +1 -1
  174. package/dist/public/{shadow-claw-terminal-DpY6zU_r.js → shadow-claw-terminal-mZ3i4HaQ.js} +1 -1
  175. package/dist/public/{shadow-claw-tools-WSwWohnk.js → shadow-claw-tools-B_nuk8Zl.js} +1 -1
  176. package/dist/public/{shadow-claw-webvm-CP6oFjg5.js → shadow-claw-webvm-Vl_jH5YL.js} +1 -1
  177. package/dist/public/{syncWebMcpRegistration-DOn9gLnD.js → syncWebMcpRegistration-n2vAMJ4w.js} +1 -1
  178. package/dist/server.js +197 -187
  179. package/package.json +2 -1
  180. package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.test.ts +6 -0
  181. package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.ts +19 -9
  182. package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.test.ts +14 -0
  183. package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.ts +12 -0
  184. package/src/components/shadow-claw/shadow-claw.ts +6 -0
  185. package/src/components/shadow-claw/utils/bindEventListeners.test.ts +57 -0
  186. package/src/components/shadow-claw/utils/bindEventListeners.ts +14 -0
  187. package/src/components/shadow-claw/utils/setupAppLifecycle.test.ts +201 -0
  188. package/src/components/shadow-claw/utils/setupAppLifecycle.ts +101 -0
  189. package/src/core/control-plane-client.test.ts +82 -1
  190. package/src/core/control-plane-client.ts +35 -1
  191. package/src/core/orchestrator/orchestrator.test.ts +49 -0
  192. package/src/core/orchestrator/orchestrator.ts +43 -0
  193. package/src/core/orchestrator/utils/operations/channel.test.ts +17 -0
  194. package/src/core/orchestrator/utils/operations/channel.ts +11 -5
  195. package/src/core/orchestrator/utils/operations/task.test.ts +26 -0
  196. package/src/core/orchestrator/utils/operations/task.ts +8 -1
  197. package/src/core/utils/initControlPlane.test.ts +138 -0
  198. package/src/core/utils/initControlPlane.ts +82 -0
  199. package/src/core/utils/initializeApp.test.ts +27 -1
  200. package/src/core/utils/initializeApp.ts +6 -13
  201. package/src/server/mcp/mcp-server.test.ts +6 -0
  202. package/src/server/mcp/mcp-server.ts +2 -1
  203. package/src/server/mcp/tools/built-in-tools.ts +88 -1
  204. package/src/server/mcp/tools/client-tool-relay.ts +6 -0
  205. package/src/server/mcp/tools/mcp-tools.test.ts +128 -0
  206. package/src/server/openapi/openapi-coverage.test.ts +2 -1
  207. package/src/server/openapi/openapi-spec.ts +2 -1
  208. package/src/server/openapi/paths/mcp.ts +104 -0
  209. package/src/server/openapi/paths/push.ts +3 -0
  210. package/src/server/routes/mcp.test.ts +92 -0
  211. package/src/server/routes/mcp.ts +138 -2
  212. package/src/server/utils/packageVersion.test.ts +10 -0
  213. package/src/server/utils/packageVersion.ts +32 -0
  214. package/src/service-worker/fetch-proxy-rules.test.ts +73 -0
  215. package/src/service-worker/fetch-proxy-rules.ts +44 -0
  216. package/src/service-worker/fetch-proxy.ts +1 -1
  217. package/src/subsystems/channels/imessage.test.ts +36 -0
  218. package/src/subsystems/channels/imessage.ts +11 -0
  219. package/src/subsystems/channels/peerjs.test.ts +56 -0
  220. package/src/subsystems/channels/peerjs.ts +29 -0
  221. package/src/subsystems/channels/telegram.test.ts +38 -0
  222. package/src/subsystems/channels/telegram.ts +13 -0
  223. package/src/subsystems/channels/types.ts +2 -0
  224. package/src/subsystems/notifications/push-client.test.ts +70 -0
  225. package/src/subsystems/notifications/push-client.ts +28 -3
  226. package/src/subsystems/notifications/push-routes.test.ts +82 -0
  227. package/src/subsystems/notifications/push-routes.ts +70 -16
  228. package/src/subsystems/notifications/push-store.test.ts +59 -0
  229. package/src/subsystems/notifications/push-store.ts +113 -19
  230. package/src/testing/jest-setup.ts +15 -0
  231. package/dist/lib/initControlPlane-C2zURVIS.js.map +0 -1
  232. package/dist/lib/orchestrator-CACLa_Ro.js.map +0 -1
  233. package/dist/lib/peerjs-DFWOBcXf.js.map +0 -1
  234. package/dist/lib/push-client-_tiWQsCT.js.map +0 -1
  235. package/dist/lib/shadow-claw-6UHdiy4a.js.map +0 -1
  236. package/dist/lib/shadow-claw-control-plane-UG0o7pCz.js.map +0 -1
  237. package/dist/public/initControlPlane-BN9cWyO0.js +0 -1
  238. package/dist/public/orchestrator-CMbCTjBf.js +0 -15
  239. package/dist/public/peerjs-DUCKH-m9.js +0 -1
  240. package/dist/public/push-client-D0lkwrK0.js +0 -1
@@ -1,9 +1,9 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="738087ac1e3211e265e3f6e008e6ee71c97739a0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/"><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="19ae0bb4c7c6a8640bebeb5c18f31bda04741ae3" /><meta name="version" content="1.28.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - Browser-native AI agent." /><link rel="canonical" href="https://xt-ml.github.io/shadow-claw/"><meta property="og:title" content="ShadowClaw"><meta property="og:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta property="og:type" content="website"><meta property="og:url" content="https://xt-ml.github.io/shadow-claw/"><meta property="og:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ShadowClaw"><meta name="twitter:description" content="Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution."><meta name="twitter:image" content="https://xt-ml.github.io/shadow-claw/assets/icons/512.png"><script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareApplication","@id":"https://xt-ml.github.io/shadow-claw/#software","name":"ShadowClaw","description":"Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.","url":"https://xt-ml.github.io/shadow-claw/","applicationCategory":"DeveloperApplication","operatingSystem":"Web, Browser, Desktop","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"},"codeRepository":"https://github.com/xt-ml/shadow-claw","license":"https://github.com/xt-ml/shadow-claw/blob/main/LICENSE"},{"@type":"WebSite","@id":"https://xt-ml.github.io/shadow-claw/#website","url":"https://xt-ml.github.io/shadow-claw/","name":"ShadowClaw","description":"Official website and live deployment of ShadowClaw browser-native AI assistant.","publisher":{"@type":"Organization","name":"xt-ml","url":"https://github.com/xt-ml"}},{"@type":"Organization","@id":"https://xt-ml.github.io/shadow-claw/#organization","name":"xt-ml","url":"https://github.com/xt-ml","sameAs":["https://github.com/xt-ml"]}]}</script><meta name="theme-color" content="#fff" /><meta http-equiv="origin-trial" content="A88uTgESYWcVgREKVReKB6jom41uP8TzW6ei3jNdidf+Xl6ONqKRjKNBphsxhrZmdkakLK3oXDgkGq53rtZYSAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3h0LW1sLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiV2ViTUNQIiwiZXhwaXJ5IjoxNzk0ODczNjAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ=="><base href="/shadow-claw/"><script id="shadow-claw-site-config" type="application/json">{"$schema":"https:\u002f\u002fjson-schema.org\u002fdraft\u002f2020-12\u002fschema","site":{"title":"ShadowClaw","description":"ShadowClaw - Browser-native AI agent.","themeColor":"#fff"},"branding":{"faviconPath":"assets\u002ficons\u002ffavicon.ico","appleTouchIconPath":"assets\u002ficons\u002f180.png","notFoundPath":"404.html"},"pwa":{"manifestPath":"manifest.json","themeColor":"#000000"},"sitemapPath":"sitemap.xml","assets":["assets"],"sidebar":{"pagesHidden":false,"chatHidden":false,"tasksHidden":false,"filesHidden":false,"defaultPage":"pages"},"settings":{"defaultToolsProfile":"__builtin_default"}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(){if(globalThis.trustedTypes)return;let e=new Map;globalThis.trustedTypes={createPolicy:(t,n)=>{if(e.has(t))throw TypeError(`Policy with name "${t}" already exists.`);let r={createHTML:n.createHTML?e=>n.createHTML(e):void 0,createScriptURL:n.createScriptURL?e=>n.createScriptURL(e):void 0,createScript:n.createScript?e=>n.createScript(e):void 0};return e.set(t,r),r},getPolicy:t=>e.get(t)??null,isHTML:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScriptURL:e=>typeof e==`string`||e instanceof Object&&`toString`in e,isScript:e=>typeof e==`string`||e instanceof Object&&`toString`in e}}let n=`__shadowClawDefaultTrustedTypesPolicyState`,r=`default`,i=`shadowclaw-sandbox`;function a(){let e=globalThis;return e[n]||(e[n]={initialized:!1,policy:null}),e[n]}function o(){let e=a();if(e.initialized)return;let t=Reflect.get(globalThis,`trustedTypes`);if(!(!t||typeof t.createPolicy!=`function`)){e.initialized=!0;try{if(typeof t.getPolicy==`function`){let n=t.getPolicy(r);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(r)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(i);if(n){e.policy=n;return}}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(r)??t.getPolicy(i)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){return this.models.get(e.toLowerCase())??null}registerModelInfo(e,t){this.models.set(e.toLowerCase(),t)}clear(){this.models.clear()}async fetchModelInfo(e,t,n){if(e.modelsUrl){this.loading=!0;try{let r=new Headers;if(r.set(`Content-Type`,`application/json`),e.headers)for(let[t,n]of Object.entries(e.headers))r.set(t,n);if(n)for(let[e,t]of Object.entries(n))r.set(e,t);if(t&&e.apiKeyHeader){let n=e.apiKeyHeaderFormat;r.set(e.apiKeyHeader,n?n.replace(`{key}`,t):t)}let i=await fetch(e.modelsUrl,{headers:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText}`);let a=await i.json(),o=Array.isArray(a.data)?a.data:Array.isArray(a.models)?a.models:[];for(let e of o){if(!e.id)continue;let t=e.context_length??e.context_window??0,n=e.max_completion_tokens||e.per_request_limits?.completion_tokens||e.top_provider?.max_completion_tokens||null,r=typeof e.supports_tools==`boolean`?e.supports_tools:typeof e.supportsTools==`boolean`?e.supportsTools:void 0,i=this.extractModalities(e,`input`),a=this.extractModalities(e,`output`),o=this.modalitiesInclude(i,`image`,`vision`),s=this.modalitiesInclude(i,`audio`,`voice`,`hearing`),c=this.modalitiesInclude(i,`video`),l=e.id===`openrouter/free`||this.supportedParametersInclude(e,`image`,`vision`,`audio`,`tool`,`structured`),u=this.extractReasoning(e);!t&&Array.isArray(e.providers)&&e.providers.length>0&&(t=e.providers[0]?.context_length||0),this.registerModelInfo(e.id,{contextWindow:t,maxOutput:n,...r!==void 0&&{supportsTools:r},...i.length>0&&{inputModalities:i},...a.length>0&&{outputModalities:a},...o!==void 0&&{supportsImageInput:o},...s!==void 0&&{supportsAudioInput:s},...c!==void 0&&{supportsVideoInput:c},...u&&{reasoning:u},...l&&{routesByRequestFeatures:l}})}o.length>0&&console.log(`[ModelRegistry] Registered ${o.length} models for provider "${e.id}"`)}catch(t){console.error(`[ModelRegistry] Error fetching models for ${e.id}:`,t)}finally{this.loading=!1}}}extractModalities(e,t){let n=t===`input`?e.input_modalities||e.inputModalities:e.output_modalities||e.outputModalities,r=e.architecture||{},i=t===`input`?r.input_modalities||r.inputModalities:r.output_modalities||r.outputModalities,a=typeof r.modality==`string`?r.modality:``,o=this.parseArchitectureModality(a,t),s=[...this.normalizeStringArray(n),...this.normalizeStringArray(i),...o];return Array.from(new Set(s))}extractReasoning(e){let t=e?.reasoning;if(!t||typeof t!=`object`)return;let n=this.normalizeStringArray(t.supported_efforts),r=typeof t.default_effort==`string`?t.default_effort.toLowerCase():void 0,i=typeof t.default_enabled==`boolean`?t.default_enabled:void 0,a=typeof t.supports_max_tokens==`boolean`?t.supports_max_tokens:void 0,o=typeof t.mandatory==`boolean`?t.mandatory:void 0;if(!(n.length===0&&r===void 0&&i===void 0&&a===void 0&&o===void 0))return{...n.length>0&&{supportedEfforts:n},...r!==void 0&&{defaultEffort:r},...i!==void 0&&{defaultEnabled:i},...a!==void 0&&{supportsMaxTokens:a},...o!==void 0&&{mandatory:o}}}modalitiesInclude(e,...t){if(e.length!==0)return t.some(t=>e.some(e=>e.includes(t)))}normalizeStringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`).map(e=>e.toLowerCase()):[]}parseArchitectureModality(e,t){if(!e)return[];let[n=``,r=``]=e.toLowerCase().split(`->`).map(e=>e.trim());return(t===`input`?n:r).split(/[+,/\s]+/).map(e=>e.trim()).filter(Boolean)}supportedParametersInclude(e,...t){let n=this.normalizeStringArray(e.supported_parameters||e.supportedParameters);return t.some(e=>n.some(t=>t.includes(e)))}};function s(e){return e.replace(/^\/+|\/+$/g,``)}function c(e){let t=s(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),s(t)}function l(e){let t=s(e),n=t.split(`/`).filter(Boolean);if(n.length===0)return null;let r=n[0].toLowerCase();if(r===`pages`){if(n.length>=3){let e=n[1];return{page:`pages`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)}}return{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}}if(r===`files`){let e=n[1]||`main`;return{page:`files`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e,path:n.slice(2).join(`/`)||void 0}}if(r===`chat`){let e=n[1]||`main`;return{page:`chat`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}if(r===`tasks`){let e=n[1]||`main`;return{page:`tasks`,groupId:e===`main`?`br:main`:e.startsWith(`br-`)?`br:${e.slice(3)}`:e}}return r===`main`?{page:`pages`,groupId:`br:main`,path:n.slice(1).join(`/`)}:{page:`pages`,groupId:`br:main`,path:t}}function u(){if(typeof document<`u`){let e=document.getElementById(`shadow-claw-static-routing`);if(e&&e.textContent)try{let t=JSON.parse(e.textContent);if(t&&typeof t==`object`&&t.routes)return t}catch(e){console.warn(`Failed to parse embedded static routing manifest:`,e)}}return null}function d(e,t){let n=t||u();if(!n||!n.routes)return null;let r=c(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&c(t.prettyPath)===r)return l(e);return null}let f=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function te(){f=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=te);function p(){let e=typeof window<`u`?window:typeof self<`u`?self:globalThis;if(e&&e.__SHADOWCLAW_DEPLOY_ID__){let t=String(e.__SHADOWCLAW_DEPLOY_ID__).trim();if(t)return t.replace(/[^a-zA-Z0-9_-]/g,`-`)}let t=globalThis.process;if(t&&t.env&&t.env.SHADOWCLAW_DEPLOY_ID){let e=String(t.env.SHADOWCLAW_DEPLOY_ID).trim();if(e)return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}let n=m();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function m(){if(f!==null)return f;if((typeof window>`u`||globalThis.WorkerGlobalScope!==void 0&&typeof self<`u`&&self instanceof globalThis.WorkerGlobalScope)&&typeof self<`u`&&self.location){let e=(self.location.pathname||`/`).split(`/`).filter(Boolean);if(e.length<=1)return f=`/`,f;let t=e[0].toLowerCase(),n=t===`service-worker.js`||t===`sw.js`||t===`manifest.json`||t===`sitemap.xml`||t===`favicon.ico`||t===`index.html`||t===`service-worker`||t===`assets`||t===`dist`||t===`public`;if(n&&e.length===2)return f=`/`,f;if(!n)return f=`/`+e[0]+`/`,f}let e=typeof window<`u`&&window.location?window.location:typeof self<`u`&&self.location?self.location:null;if(!e)return`/`;if(typeof document<`u`&&typeof document.querySelector==`function`){let t=document.querySelector(`base[href]`);if(t){let n=t.getAttribute(`href`);if(n)try{let t=new URL(n,e.origin).pathname;return t.endsWith(`/`)||(t+=`/`),f=t,f}catch{}}}let t=e.pathname||`/`;if(t===`/`)return f=`/`,f;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(f=`/`,f):(f=`/`+n.slice(0,r).join(`/`)+`/`,f):d(t)?(f=`/`,f):n.length===1&&!t.includes(`.`)?(f=`/`+n[0]+`/`,f):(f=`/`,f)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function re(){let e=p();return e?`shadowclaw-${e}`:`shadowclaw`}re();let h={github:{providerId:`github`,name:`GitHub`,aliases:[`github`,`api.github.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`token `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://github.com/login/oauth/authorize`,tokenUrl:`https://github.com/login/oauth/access_token`,defaultScopes:[`repo`,`read:user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},gitlab:{providerId:`gitlab`,name:`GitLab`,aliases:[`gitlab`,`gitlab.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`PRIVATE-TOKEN`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}}},oauth:{authorizeUrl:`https://gitlab.com/oauth/authorize`,tokenUrl:`https://gitlab.com/oauth/token`,defaultScopes:[`read_api`,`read_user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},figma:{providerId:`figma`,name:`Figma`,aliases:[`figma`,`api.figma.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`X-Figma-Token`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://www.figma.com/oauth`,tokenUrl:`https://api.figma.com/v1/oauth/token`,refreshUrl:`https://api.figma.com/v1/oauth/refresh`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},notion:{providerId:`notion`,name:`Notion`,aliases:[`notion`,`api.notion.com`,`notion.so`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.notion.com/v1/oauth/authorize`,tokenUrl:`https://api.notion.com/v1/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},microsoft_graph:{providerId:`microsoft_graph`,name:`Microsoft Graph`,aliases:[`microsoft`,`graph.microsoft.com`,`microsoft_graph`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/authorize`,tokenUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/token`,defaultScopes:[`openid`,`profile`,`offline_access`,`User.Read`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},yahoo_mail:{providerId:`yahoo_mail`,name:`Yahoo Mail`,aliases:[`yahoo`,`yahoo_mail`,`mail.yahoo.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.login.yahoo.com/oauth2/request_auth`,tokenUrl:`https://api.login.yahoo.com/oauth2/get_token`,defaultScopes:[`mail-r`,`mail-w`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},google:{providerId:`google`,name:`Google`,aliases:[`google`,`googleapis.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://accounts.google.com/o/oauth2/v2/auth`,tokenUrl:`https://oauth2.googleapis.com/token`,defaultScopes:[`openid`,`profile`,`email`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},atlassian:{providerId:`atlassian`,name:`Atlassian`,aliases:[`atlassian`,`api.atlassian.com`],modes:[`oauth`,`token`,`basic`],defaultMode:`basic`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `},basic:{headerName:`Authorization`,headerPrefix:`Basic `}},oauth:{authorizeUrl:`https://auth.atlassian.com/authorize`,tokenUrl:`https://auth.atlassian.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},slack:{providerId:`slack`,name:`Slack`,aliases:[`slack`,`slack.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://slack.com/oauth/v2/authorize`,tokenUrl:`https://slack.com/api/oauth.v2.access`,defaultScopes:[],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`comma`}},linear:{providerId:`linear`,name:`Linear`,aliases:[`linear`,`api.linear.app`,`linear.app`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://linear.app/oauth/authorize`,tokenUrl:`https://api.linear.app/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},azure_devops:{providerId:`azure_devops`,name:`Azure DevOps`,aliases:[`azure_devops`,`dev.azure.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Basic `},oauth:{headerName:`Authorization`,headerPrefix:`Basic `}}},oauth:{authorizeUrl:`https://app.vssps.visualstudio.com/oauth2/authorize`,tokenUrl:`https://app.vssps.visualstudio.com/oauth2/token`,defaultScopes:[`vso.code`,`vso.profile`,`offline_access`],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`space`}},custom_mcp:{providerId:`custom_mcp`,name:`Custom MCP`,aliases:[`custom_mcp`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`mcp_remote`,`webmcp_local`],authTypes:[`none`,`token`,`oauth`,`custom_header`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://example.com/oauth/authorize`,tokenUrl:`https://example.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}}};Object.fromEntries(Object.values(h).filter(e=>!!e.oauth).map(e=>{let t=e.oauth;return[e.providerId,{id:e.providerId,name:e.name,authorizeUrl:t.authorizeUrl,tokenUrl:t.tokenUrl,redirectUri:t.redirectUri,defaultScopes:t.defaultScopes,usePkce:t.usePkce,clientAuthMethod:t.clientAuthMethod,scopeSeparator:t.scopeSeparator}]})),Object.fromEntries(Object.values(h).map(e=>[e.providerId,{providerId:e.providerId,modes:e.modes,defaultMode:e.defaultMode}])),new Promise(e=>{});
3
3
  /*! @license DOMPurify 3.4.13 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.13/LICENSE */
4
4
  function g(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function ie(e){if(Array.isArray(e))return e}function _(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t!==0)for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function v(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
5
5
  In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function ae(e,t){return ie(e)||_(e,t)||oe(e,t)||v()}function oe(e,t){if(e){if(typeof e==`string`)return g(e,t);var n={}.toString.call(e).slice(8,-1);return n===`Object`&&e.constructor&&(n=e.constructor.name),n===`Map`||n===`Set`?Array.from(e):n===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?g(e,t):void 0}}let se=Object.entries,y=Object.setPrototypeOf,ce=Object.isFrozen,b=Object.getPrototypeOf,le=Object.getOwnPropertyDescriptor,x=Object.freeze,S=Object.seal,C=Object.create,ue=typeof Reflect<`u`&&Reflect,w=ue.apply,de=ue.construct;x||=function(e){return e},S||=function(e){return e},w||=function(e,t){for(var n=arguments.length,r=Array(n>2?n-2:0),i=2;i<n;i++)r[i-2]=arguments[i];return e.apply(t,r)},de||=function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return new e(...n)};let fe=A(Array.prototype.forEach),pe=A(Array.prototype.lastIndexOf),me=A(Array.prototype.pop),he=A(Array.prototype.push),ge=A(Array.prototype.splice),T=Array.isArray,_e=A(String.prototype.toLowerCase),ve=A(String.prototype.toString),ye=A(String.prototype.match),be=A(String.prototype.replace),xe=A(String.prototype.indexOf),Se=A(String.prototype.trim),Ce=A(Number.prototype.toString),we=A(Boolean.prototype.toString),Te=typeof BigInt>`u`?null:A(BigInt.prototype.toString),Ee=typeof Symbol>`u`?null:A(Symbol.prototype.toString),E=A(Object.prototype.hasOwnProperty),D=A(Object.prototype.toString),O=A(RegExp.prototype.test),k=De(TypeError);function A(e){return function(t){t instanceof RegExp&&(t.lastIndex=0);for(var n=arguments.length,r=Array(n>1?n-1:0),i=1;i<n;i++)r[i-1]=arguments[i];return w(e,t,r)}}function De(e){return function(){for(var t=arguments.length,n=Array(t),r=0;r<t;r++)n[r]=arguments[r];return de(e,n)}}function j(e,t){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:_e;if(y&&y(e,null),!T(t))return e;let r=t.length;for(;r--;){let i=t[r];if(typeof i==`string`){let e=n(i);e!==i&&(ce(t)||(t[r]=e),i=e)}e[i]=!0}return e}function Oe(e){for(let t=0;t<e.length;t++)E(e,t)||(e[t]=null);return e}function M(e){let t=C(null);for(let r of se(e)){var n=ae(r,2);let i=n[0],a=n[1];E(e,i)&&(T(a)?t[i]=Oe(a):a&&typeof a==`object`&&a.constructor===Object?t[i]=M(a):t[i]=a)}return t}function ke(e){switch(typeof e){case`string`:return e;case`number`:return Ce(e);case`boolean`:return we(e);case`bigint`:return Te?Te(e):`0`;case`symbol`:return Ee?Ee(e):`Symbol()`;case`undefined`:return D(e);case`function`:case`object`:{if(e===null)return D(e);let t=e,n=N(t,`toString`);if(typeof n==`function`){let e=n(t);return typeof e==`string`?e:D(e)}return D(e)}default:return D(e)}}function N(e,t){for(;e!==null;){let n=le(e,t);if(n){if(n.get)return A(n.get);if(typeof n.value==`function`)return A(n.value)}e=b(e)}function n(){return null}return n}function Ae(e){try{return O(e,``),!0}catch{return!1}}let je=x(`a.abbr.acronym.address.area.article.aside.audio.b.bdi.bdo.big.blink.blockquote.body.br.button.canvas.caption.center.cite.code.col.colgroup.content.data.datalist.dd.decorator.del.details.dfn.dialog.dir.div.dl.dt.element.em.fieldset.figcaption.figure.font.footer.form.h1.h2.h3.h4.h5.h6.head.header.hgroup.hr.html.i.img.input.ins.kbd.label.legend.li.main.map.mark.marquee.menu.menuitem.meter.nav.nobr.ol.optgroup.option.output.p.picture.pre.progress.q.rp.rt.ruby.s.samp.search.section.select.shadow.slot.small.source.spacer.span.strike.strong.style.sub.summary.sup.table.tbody.td.template.textarea.tfoot.th.thead.time.tr.track.tt.u.ul.var.video.wbr`.split(`.`)),Me=x(`svg.a.altglyph.altglyphdef.altglyphitem.animatecolor.animatemotion.animatetransform.circle.clippath.defs.desc.ellipse.enterkeyhint.exportparts.filter.font.g.glyph.glyphref.hkern.image.inputmode.line.lineargradient.marker.mask.metadata.mpath.part.path.pattern.polygon.polyline.radialgradient.rect.stop.style.switch.symbol.text.textpath.title.tref.tspan.view.vkern`.split(`.`)),Ne=x([`feBlend`,`feColorMatrix`,`feComponentTransfer`,`feComposite`,`feConvolveMatrix`,`feDiffuseLighting`,`feDisplacementMap`,`feDistantLight`,`feDropShadow`,`feFlood`,`feFuncA`,`feFuncB`,`feFuncG`,`feFuncR`,`feGaussianBlur`,`feImage`,`feMerge`,`feMergeNode`,`feMorphology`,`feOffset`,`fePointLight`,`feSpecularLighting`,`feSpotLight`,`feTile`,`feTurbulence`]),Pe=x([`animate`,`color-profile`,`cursor`,`discard`,`font-face`,`font-face-format`,`font-face-name`,`font-face-src`,`font-face-uri`,`foreignobject`,`hatch`,`hatchpath`,`mesh`,`meshgradient`,`meshpatch`,`meshrow`,`missing-glyph`,`script`,`set`,`solidcolor`,`unknown`,`use`]),Fe=x(`math.menclose.merror.mfenced.mfrac.mglyph.mi.mlabeledtr.mmultiscripts.mn.mo.mover.mpadded.mphantom.mroot.mrow.ms.mspace.msqrt.mstyle.msub.msup.msubsup.mtable.mtd.mtext.mtr.munder.munderover.mprescripts`.split(`.`)),Ie=x([`maction`,`maligngroup`,`malignmark`,`mlongdiv`,`mscarries`,`mscarry`,`msgroup`,`mstack`,`msline`,`msrow`,`semantics`,`annotation`,`annotation-xml`,`mprescripts`,`none`]),Le=x([`#text`]),Re=x(`accept.action.align.alt.autocapitalize.autocomplete.autopictureinpicture.autoplay.background.bgcolor.border.capture.cellpadding.cellspacing.checked.cite.class.clear.color.cols.colspan.command.commandfor.controls.controlslist.coords.crossorigin.datetime.decoding.default.dir.disabled.disablepictureinpicture.disableremoteplayback.download.draggable.enctype.enterkeyhint.exportparts.face.for.headers.height.hidden.high.href.hreflang.id.inert.inputmode.integrity.ismap.kind.label.lang.list.loading.loop.low.max.maxlength.media.method.min.minlength.multiple.muted.name.nonce.noshade.novalidate.nowrap.open.optimum.part.pattern.placeholder.playsinline.popover.popovertarget.popovertargetaction.poster.preload.pubdate.radiogroup.readonly.rel.required.rev.reversed.role.rows.rowspan.spellcheck.scope.selected.shape.size.sizes.slot.span.srclang.start.src.srcset.step.style.summary.tabindex.title.translate.type.usemap.valign.value.width.wrap.xmlns`.split(`.`)),ze=x(`accent-height.accumulate.additive.alignment-baseline.amplitude.ascent.attributename.attributetype.azimuth.basefrequency.baseline-shift.begin.bias.by.class.clip.clippathunits.clip-path.clip-rule.color.color-interpolation.color-interpolation-filters.color-profile.color-rendering.cx.cy.d.dx.dy.diffuseconstant.direction.display.divisor.dominant-baseline.dur.edgemode.elevation.end.exponent.fill.fill-opacity.fill-rule.filter.filterunits.flood-color.flood-opacity.font-family.font-size.font-size-adjust.font-stretch.font-style.font-variant.font-weight.fx.fy.g1.g2.glyph-name.glyphref.gradientunits.gradienttransform.height.href.id.image-rendering.in.in2.intercept.k.k1.k2.k3.k4.kerning.keypoints.keysplines.keytimes.lang.lengthadjust.letter-spacing.kernelmatrix.kernelunitlength.lighting-color.local.marker-end.marker-mid.marker-start.markerheight.markerunits.markerwidth.maskcontentunits.maskunits.max.mask.mask-type.media.method.mode.min.name.numoctaves.offset.operator.opacity.order.orient.orientation.origin.overflow.paint-order.path.pathlength.patterncontentunits.patterntransform.patternunits.points.preservealpha.preserveaspectratio.primitiveunits.r.rx.ry.radius.refx.refy.repeatcount.repeatdur.restart.result.rotate.scale.seed.shape-rendering.slope.specularconstant.specularexponent.spreadmethod.startoffset.stddeviation.stitchtiles.stop-color.stop-opacity.stroke-dasharray.stroke-dashoffset.stroke-linecap.stroke-linejoin.stroke-miterlimit.stroke-opacity.stroke.stroke-width.style.surfacescale.systemlanguage.tabindex.tablevalues.targetx.targety.transform.transform-origin.text-anchor.text-decoration.text-orientation.text-rendering.textlength.type.u1.u2.unicode.values.viewbox.visibility.version.vert-adv-y.vert-origin-x.vert-origin-y.width.word-spacing.wrap.writing-mode.xchannelselector.ychannelselector.x.x1.x2.xmlns.y.y1.y2.z.zoomandpan`.split(`.`)),Be=x(`accent.accentunder.align.bevelled.close.columnalign.columnlines.columnspacing.columnspan.denomalign.depth.dir.display.displaystyle.encoding.fence.frame.height.href.id.largeop.length.linethickness.lquote.lspace.mathbackground.mathcolor.mathsize.mathvariant.maxsize.minsize.movablelimits.notation.numalign.open.rowalign.rowlines.rowspacing.rowspan.rspace.rquote.scriptlevel.scriptminsize.scriptsizemultiplier.selection.separator.separators.stretchy.subscriptshift.supscriptshift.symmetric.voffset.width.xmlns`.split(`.`)),Ve=x([`xlink:href`,`xml:id`,`xlink:title`,`xml:space`,`xmlns:xlink`]),He=S(/{{[\w\W]*|^[\w\W]*}}/g),Ue=S(/<%[\w\W]*|^[\w\W]*%>/g),We=S(/\${[\w\W]*/g),Ge=S(/^data-[\-\w.\u00B7-\uFFFF]+$/),Ke=S(/^aria-[\-\w]+$/),qe=S(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Je=S(/^(?:\w+script|data):/i),Ye=S(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),Xe=S(/^html$/i),Ze=S(/^[a-z][.\w]*(-[.\w]+)+$/i),Qe=S(/<[/\w!]/g),$e=S(/<[/\w]/g),et=S(/<\/no(script|embed|frames)/i),tt=S(/\/>/i),P={element:1,attribute:2,text:3,cdataSection:4,entityReference:5,entityNode:6,processingInstruction:7,comment:8,document:9,documentType:10,documentFragment:11,notation:12},nt=function(){return typeof window>`u`?null:window},rt=function(e,t){if(typeof e!=`object`||typeof e.createPolicy!=`function`)return null;let n=null,r=`data-tt-policy-suffix`;t&&t.hasAttribute(r)&&(n=t.getAttribute(r));let i=`dompurify`+(n?`#`+n:``);try{return e.createPolicy(i,{createHTML(e){return e},createScriptURL(e){return e}})}catch{return console.warn(`TrustedTypes policy `+i+` could not be created.`),null}},it=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},F=function(e,t,n,r){return E(e,t)&&T(e[t])?j(r.base?M(r.base):{},e[t],r.transform):n};function at(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:nt(),t=e=>at(e);if(t.version=`3.4.13`,t.removed=[],!e||!e.document||e.document.nodeType!==P.document||!e.Element)return t.isSupported=!1,t;let n=e.document,r=n,i=r.currentScript;e.DocumentFragment;let a=e.HTMLTemplateElement,o=e.Node,s=e.Element,c=e.NodeFilter;e.NamedNodeMap===void 0&&(e.NamedNodeMap||e.MozNamedAttrMap),e.HTMLFormElement;let l=e.DOMParser,u=e.trustedTypes,d=s.prototype,f=N(d,`cloneNode`),ee=N(d,`remove`),te=N(d,`nextSibling`),p=N(d,`childNodes`),m=N(d,`parentNode`),ne=N(d,`shadowRoot`),re=N(d,`attributes`),h=o&&o.prototype?N(o.prototype,`nodeType`):null,g=o&&o.prototype?N(o.prototype,`nodeName`):null,ie=o&&o.prototype?N(o.prototype,`ownerDocument`):null;if(typeof a==`function`){let e=n.createElement(`template`);e.content&&e.content.ownerDocument&&(n=e.content.ownerDocument)}let _,v=``,ae,oe=!1,y=0,ce=function(){if(y>0)throw k(`A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.`)},b=function(e){ce(),y++;try{return _.createHTML(e)}finally{y--}},le=function(e){ce(),y++;try{return _.createScriptURL(e)}finally{y--}},ue=function(){return oe||=(ae=rt(u,i),!0),ae},w=n,de=w.implementation,Ce=w.createNodeIterator,we=w.createDocumentFragment,Te=w.getElementsByTagName,Ee=r.importNode,D=it();t.isSupported=typeof se==`function`&&typeof m==`function`&&de&&de.createHTMLDocument!==void 0;let A=He,De=Ue,Oe=We,ot=Ge,st=Ke,ct=Je,lt=Ye,ut=Ze,dt=qe,I=null,ft=j({},[...je,...Me,...Ne,...Fe,...Le]),L=null,R=j({},[...Re,...ze,...Be,...Ve]),z=Object.seal(C(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),B=null,pt=null,V=Object.seal(C(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}})),mt=!0,ht=!0,gt=!1,_t=!0,H=!1,U=!0,W=!1,vt=!1,G=null,K=null,yt=!1,q=!1,bt=!1,xt=!1,St=!0,Ct=!1,wt=`user-content-`,Tt=!0,Et=!1,Dt={},J=null,Ot=j({},`annotation-xml.audio.colgroup.desc.foreignobject.head.iframe.math.mi.mn.mo.ms.mtext.noembed.noframes.noscript.plaintext.script.selectedcontent.style.svg.template.thead.title.video.xmp`.split(`.`)),kt=null,At=j({},[`audio`,`video`,`img`,`source`,`image`,`track`]),jt=null,Mt=j({},[`alt`,`class`,`for`,`id`,`label`,`name`,`pattern`,`placeholder`,`role`,`summary`,`title`,`value`,`style`,`xmlns`]),Nt=`http://www.w3.org/1998/Math/MathML`,Pt=`http://www.w3.org/2000/svg`,Y=`http://www.w3.org/1999/xhtml`,Ft=Y,It=!1,Lt=null,Rt=j({},[Nt,Pt,Y],ve),zt=x([`mi`,`mo`,`mn`,`ms`,`mtext`]),Bt=j({},zt),Vt=x([`annotation-xml`]),Ht=j({},Vt),Ut=j({},[`title`,`style`,`font`,`a`,`script`]),Wt=null,Gt=[`application/xhtml+xml`,`text/html`],X=null,Kt=null,qt=n.createElement(`form`),Jt=function(e){return e instanceof RegExp||e instanceof Function},Yt=function(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(Kt&&Kt===e)return;(!e||typeof e!=`object`)&&(e={}),e=M(e),Wt=Gt.indexOf(e.PARSER_MEDIA_TYPE)===-1?`text/html`:e.PARSER_MEDIA_TYPE,X=Wt===`application/xhtml+xml`?ve:_e,I=F(e,`ALLOWED_TAGS`,ft,{transform:X}),L=F(e,`ALLOWED_ATTR`,R,{transform:X}),Lt=F(e,`ALLOWED_NAMESPACES`,Rt,{transform:ve}),jt=F(e,`ADD_URI_SAFE_ATTR`,Mt,{transform:X,base:Mt}),kt=F(e,`ADD_DATA_URI_TAGS`,At,{transform:X,base:At}),J=F(e,`FORBID_CONTENTS`,Ot,{transform:X}),B=F(e,`FORBID_TAGS`,M({}),{transform:X}),pt=F(e,`FORBID_ATTR`,M({}),{transform:X}),Dt=E(e,`USE_PROFILES`)?e.USE_PROFILES&&typeof e.USE_PROFILES==`object`?M(e.USE_PROFILES):e.USE_PROFILES:!1,mt=e.ALLOW_ARIA_ATTR!==!1,ht=e.ALLOW_DATA_ATTR!==!1,gt=e.ALLOW_UNKNOWN_PROTOCOLS||!1,_t=e.ALLOW_SELF_CLOSE_IN_ATTR!==!1,H=e.SAFE_FOR_TEMPLATES||!1,U=e.SAFE_FOR_XML!==!1,W=e.WHOLE_DOCUMENT||!1,q=e.RETURN_DOM||!1,bt=e.RETURN_DOM_FRAGMENT||!1,xt=e.RETURN_TRUSTED_TYPE||!1,yt=e.FORCE_BODY||!1,St=e.SANITIZE_DOM!==!1,Ct=e.SANITIZE_NAMED_PROPS||!1,Tt=e.KEEP_CONTENT!==!1,Et=e.IN_PLACE||!1,dt=Ae(e.ALLOWED_URI_REGEXP)?e.ALLOWED_URI_REGEXP:qe,Ft=typeof e.NAMESPACE==`string`?e.NAMESPACE:Y,Bt=E(e,`MATHML_TEXT_INTEGRATION_POINTS`)&&e.MATHML_TEXT_INTEGRATION_POINTS&&typeof e.MATHML_TEXT_INTEGRATION_POINTS==`object`?M(e.MATHML_TEXT_INTEGRATION_POINTS):j({},zt),Ht=E(e,`HTML_INTEGRATION_POINTS`)&&e.HTML_INTEGRATION_POINTS&&typeof e.HTML_INTEGRATION_POINTS==`object`?M(e.HTML_INTEGRATION_POINTS):j({},Vt);let t=E(e,`CUSTOM_ELEMENT_HANDLING`)&&e.CUSTOM_ELEMENT_HANDLING&&typeof e.CUSTOM_ELEMENT_HANDLING==`object`?M(e.CUSTOM_ELEMENT_HANDLING):C(null);if(z=C(null),E(t,`tagNameCheck`)&&Jt(t.tagNameCheck)&&(z.tagNameCheck=t.tagNameCheck),E(t,`attributeNameCheck`)&&Jt(t.attributeNameCheck)&&(z.attributeNameCheck=t.attributeNameCheck),E(t,`allowCustomizedBuiltInElements`)&&typeof t.allowCustomizedBuiltInElements==`boolean`&&(z.allowCustomizedBuiltInElements=t.allowCustomizedBuiltInElements),S(z),H&&(ht=!1),bt&&(q=!0),Dt&&(I=j({},Le),L=C(null),Dt.html===!0&&(j(I,je),j(L,Re)),Dt.svg===!0&&(j(I,Me),j(L,ze),j(L,Ve)),Dt.svgFilters===!0&&(j(I,Ne),j(L,ze),j(L,Ve)),Dt.mathMl===!0&&(j(I,Fe),j(L,Be),j(L,Ve))),V.tagCheck=null,V.attributeCheck=null,E(e,`ADD_TAGS`)&&(typeof e.ADD_TAGS==`function`?V.tagCheck=e.ADD_TAGS:T(e.ADD_TAGS)&&(I===ft&&(I=M(I)),j(I,e.ADD_TAGS,X))),E(e,`ADD_ATTR`)&&(typeof e.ADD_ATTR==`function`?V.attributeCheck=e.ADD_ATTR:T(e.ADD_ATTR)&&(L===R&&(L=M(L)),j(L,e.ADD_ATTR,X))),E(e,`ADD_URI_SAFE_ATTR`)&&T(e.ADD_URI_SAFE_ATTR)&&j(jt,e.ADD_URI_SAFE_ATTR,X),E(e,`FORBID_CONTENTS`)&&T(e.FORBID_CONTENTS)&&(J===Ot&&(J=M(J)),j(J,e.FORBID_CONTENTS,X)),E(e,`ADD_FORBID_CONTENTS`)&&T(e.ADD_FORBID_CONTENTS)&&(J===Ot&&(J=M(J)),j(J,e.ADD_FORBID_CONTENTS,X)),Tt&&(I[`#text`]=!0),W&&j(I,[`html`,`head`,`body`]),I.table&&(j(I,[`tbody`]),delete B.tbody),e.TRUSTED_TYPES_POLICY){if(typeof e.TRUSTED_TYPES_POLICY.createHTML!=`function`)throw k(`TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.`);if(typeof e.TRUSTED_TYPES_POLICY.createScriptURL!=`function`)throw k(`TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.`);let t=_;_=e.TRUSTED_TYPES_POLICY;try{v=b(``)}catch(e){throw _=t,e}}else e.TRUSTED_TYPES_POLICY===null?(_=void 0,v=``):(_===void 0&&(_=ue()),_&&typeof v==`string`&&(v=b(``)));x&&x(e),Kt=e},Xt=j({},[...Me,...Ne,...Pe]),Zt=j({},[...Fe,...Ie]),Qt=function(e,t,n){return t.namespaceURI===Y?e===`svg`:t.namespaceURI===Nt?e===`svg`&&(n===`annotation-xml`||Bt[n]):!!Xt[e]},$t=function(e,t,n){return t.namespaceURI===Y?e===`math`:t.namespaceURI===Pt?e===`math`&&Ht[n]:!!Zt[e]},en=function(e,t,n){return t.namespaceURI===Pt&&!Ht[n]||t.namespaceURI===Nt&&!Bt[n]?!1:!Zt[e]&&(Ut[e]||!Xt[e])},tn=function(e){let t=m(e);(!t||!t.tagName)&&(t={namespaceURI:Ft,tagName:`template`});let n=_e(e.tagName),r=_e(t.tagName);return Lt[e.namespaceURI]?e.namespaceURI===Pt?Qt(n,t,r):e.namespaceURI===Nt?$t(n,t,r):e.namespaceURI===Y?en(n,t,r):!!(Wt===`application/xhtml+xml`&&Lt[e.namespaceURI]):!1},Z=function(e){he(t.removed,{element:e});try{m(e).removeChild(e)}catch{if(ee(e),!m(e))throw k(`a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place`)}},nn=function(e){an(e);let t=p(e);if(t){let e=[];fe(t,t=>{he(e,t)}),fe(e,e=>{try{ee(e)}catch{}})}let n=re(e);if(n)for(let t=n.length-1;t>=0;--t){let r=n[t],i=r&&r.name;if(typeof i==`string`)try{e.removeAttribute(i)}catch{}}},Q=function(e,n){try{he(t.removed,{attribute:n.getAttributeNode(e),from:n})}catch{he(t.removed,{attribute:null,from:n})}if(n.removeAttribute(e),e===`is`)if(q||bt)try{Z(n)}catch{}else try{n.setAttribute(e,``)}catch{}},rn=function(e){let t=re(e);if(t)for(let n=t.length-1;n>=0;--n){let r=t[n],i=r&&r.name;if(!(typeof i!=`string`||L[X(i)]))try{e.removeAttribute(i)}catch{}}},an=function(e){let t=[e];for(;t.length>0;){let e=t.pop();(h?h(e):e.nodeType)===P.element&&rn(e);let n=p(e);if(n)for(let e=n.length-1;e>=0;--e)t.push(n[e])}},on=function(e){if(!U)return;let t=[e];for(;t.length>0;){let e=t.pop(),n=h?h(e):e.nodeType;if(n===P.processingInstruction||n===P.comment&&O($e,e.data)){try{ee(e)}catch{}continue}if(n===P.element){let t=e,n=X(g?g(e):e.nodeName);try{t.hasAttribute&&t.hasAttribute(`patchsrc`)&&t.removeAttribute(`patchsrc`),t.hasAttribute&&t.hasAttribute(`for`)&&n!==`label`&&n!==`output`&&t.removeAttribute(`for`)}catch{}}let r=p(e);if(r)for(let e=r.length-1;e>=0;--e)t.push(r[e])}},sn=function(e){let t=null,r=null;if(yt)e=`<remove></remove>`+e;else{let t=ye(e,/^[\r\n\t ]+/);r=t&&t[0]}Wt===`application/xhtml+xml`&&Ft===Y&&(e=`<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>`+e+`</body></html>`);let i=_?b(e):e;if(Ft===Y)try{t=new l().parseFromString(i,Wt)}catch{}if(!t||!t.documentElement){t=de.createDocument(Ft,`template`,null);try{t.documentElement.innerHTML=It?v:i}catch{}}let a=t.body||t.documentElement;return e&&r&&a.insertBefore(n.createTextNode(r),a.childNodes[0]||null),Ft===Y?Te.call(t,W?`html`:`body`)[0]:W?t.documentElement:a},cn=function(e){let t=ie?ie(e):e.ownerDocument;return Ce.call(t||e,e,c.SHOW_ELEMENT|c.SHOW_COMMENT|c.SHOW_TEXT|c.SHOW_PROCESSING_INSTRUCTION|c.SHOW_CDATA_SECTION,null)},ln=function(e){return e=be(e,A,` `),e=be(e,De,` `),e=be(e,Oe,` `),e},un=function(e){e.normalize();let t=ie?ie(e):e.ownerDocument,n=Ce.call(t||e,e,c.SHOW_TEXT|c.SHOW_COMMENT|c.SHOW_CDATA_SECTION|c.SHOW_PROCESSING_INSTRUCTION,null),r=n.nextNode();for(;r;)r.data=ln(r.data),r=n.nextNode();let i=e.querySelectorAll?.call(e,`template`);i&&fe(i,e=>{fn(e.content)&&un(e.content)})},dn=function(e){let t=g?g(e):null;return typeof t!=`string`||X(t)!==`form`?!1:typeof e.nodeName!=`string`||typeof e.textContent!=`string`||typeof e.removeChild!=`function`||e.attributes!==re(e)||typeof e.removeAttribute!=`function`||typeof e.setAttribute!=`function`||typeof e.namespaceURI!=`string`||typeof e.insertBefore!=`function`||typeof e.hasChildNodes!=`function`||e.nodeType!==h(e)||e.childNodes!==p(e)},fn=function(e){if(!h||typeof e!=`object`||!e)return!1;try{return h(e)===P.documentFragment}catch{return!1}},pn=function(e){if(!h||typeof e!=`object`||!e)return!1;try{return typeof h(e)==`number`}catch{return!1}};function $(e,n,r){e.length!==0&&fe(e,e=>{e.call(t,n,r,Kt)})}let mn=function(e,t){return!!(U&&e.hasChildNodes()&&!pn(e.firstElementChild)&&O(Qe,e.textContent)&&O(Qe,e.innerHTML)||U&&e.namespaceURI===Y&&t===`style`&&pn(e.firstElementChild)||e.nodeType===P.processingInstruction||U&&e.nodeType===P.comment&&O($e,e.data))},hn=function(e,t,n){if(!B[t]&&bn(t)&&(z.tagNameCheck instanceof RegExp&&O(z.tagNameCheck,t)||z.tagNameCheck instanceof Function&&z.tagNameCheck(t)))return!1;if(Tt&&!J[t]){let t=m(e),r=p(e);if(r&&t){let i=r.length;for(let a=i-1;a>=0;--a){let i=e===n?f(r[a],!0):r[a];t.insertBefore(i,te(e))}}}return Z(e),!0},gn=function(e,t,n,r){return e.length===0?t:t===n||t===r?M(t):t},_n=function(e,n){if($(D.beforeSanitizeElements,e,null),e!==n&&m(e)===null)return Et&&an(e),!0;if(dn(e))return Z(e),!0;let r=X(g?g(e):e.nodeName);if(I=gn(D.uponSanitizeElement,I,ft,G),$(D.uponSanitizeElement,e,{tagName:r,allowedTags:I}),e!==n&&m(e)===null)return Et&&an(e),!0;if(mn(e,r))return Z(e),!0;if(B[r]||!(V.tagCheck instanceof Function&&V.tagCheck(r))&&!I[r]){let t=hn(e,r,n);return t===!1&&$(D.afterSanitizeElements,e,null),t}if((h?h(e):e.nodeType)===P.element&&!tn(e)||(r===`noscript`||r===`noembed`||r===`noframes`)&&O(et,e.innerHTML))return Z(e),!0;if(H&&e.nodeType===P.text){let n=ln(e.textContent);e.textContent!==n&&(he(t.removed,{element:e.cloneNode()}),e.textContent=n)}return $(D.afterSanitizeElements,e,null),!1},vn=function(e,t,r){if(pt[t]||U&&t===`patchsrc`||U&&t===`for`&&e!==`label`&&e!==`output`||St&&(t===`id`||t===`name`)&&(r in n||r in qt))return!1;let i=L[t]||V.attributeCheck instanceof Function&&V.attributeCheck(t,e);if(!(ht&&O(ot,t))&&!(mt&&O(st,t))){if(!i){if(!(bn(e)&&(z.tagNameCheck instanceof RegExp&&O(z.tagNameCheck,e)||z.tagNameCheck instanceof Function&&z.tagNameCheck(e))&&(z.attributeNameCheck instanceof RegExp&&O(z.attributeNameCheck,t)||z.attributeNameCheck instanceof Function&&z.attributeNameCheck(t,e))||t===`is`&&z.allowCustomizedBuiltInElements&&(z.tagNameCheck instanceof RegExp&&O(z.tagNameCheck,r)||z.tagNameCheck instanceof Function&&z.tagNameCheck(r))))return!1}else if(!jt[t]&&!O(dt,be(r,lt,``))&&!((t===`src`||t===`xlink:href`||t===`href`)&&e!==`script`&&xe(r,`data:`)===0&&kt[e])&&!(gt&&!O(ct,be(r,lt,``)))&&r)return!1}return!0},yn=j({},[`annotation-xml`,`color-profile`,`font-face`,`font-face-format`,`font-face-name`,`font-face-src`,`font-face-uri`,`missing-glyph`]),bn=function(e){return!yn[_e(e)]&&O(ut,e)},xn=function(e,t,n,r){if(_&&typeof u==`object`&&typeof u.getAttributeType==`function`&&!n)switch(u.getAttributeType(e,t)){case`TrustedHTML`:return b(r);case`TrustedScriptURL`:return le(r)}return r},Sn=function(e,n,r,i){try{r?e.setAttributeNS(r,n,i):e.setAttribute(n,i),dn(e)?Z(e):me(t.removed)}catch{Q(n,e)}},Cn=function(e){$(D.beforeSanitizeAttributes,e,null);let t=e.attributes;if(!t||dn(e))return;L=gn(D.uponSanitizeAttribute,L,R,K);let n={attrName:``,attrValue:``,keepAttr:!0,allowedAttributes:L,forceKeepAttr:void 0},r=t.length,i=X(e.nodeName);for(;r--;){let a=t[r],o=a.name,s=a.namespaceURI,c=a.value,l=X(o),u=c,d=o===`value`?u:Se(u);if(n.attrName=l,n.attrValue=d,n.keepAttr=!0,n.forceKeepAttr=void 0,$(D.uponSanitizeAttribute,e,n),d=n.attrValue,Ct&&(l===`id`||l===`name`)&&xe(d,wt)!==0&&(Q(o,e),d=wt+d),U&&O(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,d)){Q(o,e);continue}if(l===`attributename`&&ye(d,`href`)){Q(o,e);continue}if(!n.forceKeepAttr){if(!n.keepAttr){Q(o,e);continue}if(!_t&&O(tt,d)){Q(o,e);continue}if(H&&(d=ln(d)),!vn(i,l,d)){Q(o,e);continue}d=xn(i,l,s,d),d!==u&&Sn(e,o,s,d)}}$(D.afterSanitizeAttributes,e,null)},wn=function(e){let t=null,n=cn(e);for($(D.beforeSanitizeShadowDOM,e,null);t=n.nextNode();)if($(D.uponSanitizeShadowNode,t,null),_n(t,e),Cn(t),fn(t.content)&&wn(t.content),(h?h(t):t.nodeType)===P.element){let e=ne(t);fn(e)&&(Tn(e),wn(e))}$(D.afterSanitizeShadowDOM,e,null)},Tn=function(e){let t=[{node:e,shadow:null}];for(;t.length>0;){let e=t.pop();if(e.shadow){wn(e.shadow);continue}let n=e.node,r=(h?h(n):n.nodeType)===P.element,i=p(n);if(i)for(let e=i.length-1;e>=0;--e)t.push({node:i[e],shadow:null});if(r){let e=g?g(n):null;if(typeof e==`string`&&X(e)===`template`){let e=n.content;fn(e)&&t.push({node:e,shadow:null})}}if(r){let e=ne(n);fn(e)&&t.push({node:null,shadow:e},{node:e,shadow:null})}}};return t.sanitize=function(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},i=null,a=null,o=null,s=null;if(It=!e,It&&(e=`<!-->`),typeof e!=`string`&&!pn(e)&&(e=ke(e),typeof e!=`string`))throw k(`dirty is not a string, aborting`);if(!t.isSupported)return e;vt?(I=G,L=K):Yt(n),(D.uponSanitizeElement.length>0||D.uponSanitizeAttribute.length>0)&&(I=M(I)),D.uponSanitizeAttribute.length>0&&(L=M(L)),t.removed=[];let c=Et&&typeof e!=`string`&&pn(e);if(c){on(e);let t=g?g(e):e.nodeName;if(typeof t==`string`){let n=X(t);if(!I[n]||B[n])throw nn(e),k(`root node is forbidden and cannot be sanitized in-place`)}if(dn(e))throw nn(e),k(`root node is clobbered and cannot be sanitized in-place`);try{Tn(e)}catch(t){throw nn(e),t}}else if(pn(e))i=sn(`<!---->`),a=i.ownerDocument.importNode(e,!0),a.nodeType===P.element&&a.nodeName===`BODY`||a.nodeName===`HTML`?i=a:i.appendChild(a),Tn(a);else{if(!q&&!H&&!W&&e.indexOf(`<`)===-1)return _&&xt?b(e):e;if(i=sn(e),!i)return q?null:xt?v:``}i&&yt&&Z(i.firstChild);let l=c?e:i;try{let e=cn(l);for(;o=e.nextNode();)_n(o,l),Cn(o),fn(o.content)&&wn(o.content)}catch(n){throw c&&(nn(e),fe(t.removed,e=>{e.element&&an(e.element)})),n}if(c)return fe(t.removed,e=>{e.element&&an(e.element)}),H&&un(e),e;if(q){if(H&&un(i),bt)for(s=we.call(i.ownerDocument);i.firstChild;)s.appendChild(i.firstChild);else s=i;return(L.shadowroot||L.shadowrootmode)&&(s=Ee.call(r,s,!0)),s}let u=W?i.outerHTML:i.innerHTML;return W&&I[`!doctype`]&&i.ownerDocument&&i.ownerDocument.doctype&&i.ownerDocument.doctype.name&&O(Xe,i.ownerDocument.doctype.name)&&(u=`<!DOCTYPE `+i.ownerDocument.doctype.name+`>
6
- `+u),H&&(u=ln(u)),_&&xt?b(u):u},t.setConfig=function(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};Yt(e),vt=!0,G=I,K=L},t.clearConfig=function(){Kt=null,vt=!1,G=null,K=null,_=ae,v=``},t.isValidAttribute=function(e,t,n){Kt||Yt({});let r=X(e),i=X(t);return vn(r,i,n)},t.addHook=function(e,t){typeof t==`function`&&E(D,e)&&he(D[e],t)},t.removeHook=function(e,t){if(E(D,e)){if(t!==void 0){let n=pe(D[e],t);return n===-1?void 0:ge(D[e],n,1)[0]}return me(D[e])}},t.removeHooks=function(e){E(D,e)&&(D[e]=[])},t.removeAllHooks=function(){D=it()},t}at();let ot=[`youtube.com`,`youtube-nocookie.com`,`youtu.be`,`xt-ml.github.io`,`kherrick.github.io`];function st(e){e.map(e=>ct(e)).filter(Boolean)}st(ot);function ct(e){let t=e.trim();if(!t)return()=>!1;if(t.startsWith(`/`)&&(t.endsWith(`/`)||/\/[gimuy]*$/.test(t)))try{let e=t.lastIndexOf(`/`),n=t.slice(1,e),r=t.slice(e+1),i=new RegExp(n,r||`i`);return e=>i.test(e)}catch{}if(t.includes(`^`)||t.includes(`$`)||t.includes(`(`)&&t.includes(`)`))try{let e=new RegExp(t,`i`);return t=>e.test(t)}catch{}if(t.startsWith(`*.`)){let e=t.slice(2).toLowerCase();return t=>{let n=t.toLowerCase();return n===e||n.endsWith(`.`+e)}}let n=t.toLowerCase();return e=>{let t=e.toLowerCase();return t===n||t.endsWith(`.`+n)}}let lt=[],ut=[],dt=new Set(lt.map(e=>e.toLowerCase().trim())),I=[...ut];function ft(e){e.map(e=>ct(e)).filter(Boolean)}ft(I);function L(e){return Array.isArray(e)?e.map(e=>typeof e==`string`?e.toLowerCase().trim():``).filter(Boolean):typeof e==`string`?e.split(/[\n,]+/).map(e=>e.toLowerCase().trim()).filter(Boolean):[]}function R(e){return Array.isArray(e)?e.map(e=>typeof e==`string`?e.trim():``).filter(Boolean):typeof e==`string`?e.split(/[\n,]+/).map(e=>e.trim()).filter(Boolean):[]}function z(e){let t=L(e);dt=new Set(t)}function B(e){let t=R(e);I=t,ft(t)}function pt(e){if(!e||typeof e!=`string`)return!1;let t=e.trim().toLowerCase();return!t.includes(`-`)||t===`shadow-claw`||t.startsWith(`shadow-claw-`)?!0:dt.has(t)}let V=`allow-modals allow-scripts allow-popups allow-popups-to-escape-sandbox`,mt=[`'self'`,`blob:`,`data:`],ht=[`'self'`,`blob:`,`data:`],gt=[`'self'`,`'unsafe-inline'`,`https:`,`http:`],_t=[`'self'`,`blob:`,`data:`,`https:`,`http:`],H=V;[...mt],[...ht],[...gt],[..._t];function U(e){H=Array.isArray(e)?e.map(e=>typeof e==`string`?e.trim():``).filter(Boolean).join(` `):typeof e==`string`&&e.trim()?e.trim():V}function W(e){if(!e||typeof e!=`object`)return;let t=e.allowedCustomElements||(typeof e.customElements==`object`&&!Array.isArray(e.customElements)?e.customElements?.allowedElements:void 0);t!==void 0&&z(t);let n=e.allowedCustomElementDomains||(typeof e.customElements==`object`&&!Array.isArray(e.customElements)?e.customElements?.allowedDomains:void 0);n!==void 0&&B(n),e.security?.iframeSandbox===void 0?(e.security?.allowSameOrigin===!0||e.security?.allowIframeSameOrigin===!0)&&(H.includes(`allow-same-origin`)||(H=`${H} allow-same-origin`.trim())):U(e.security.iframeSandbox),e.security?.workerSrc!==void 0&&R(e.security.workerSrc),e.security?.connectSrc!==void 0&&R(e.security.connectSrc),e.security?.scriptSrc!==void 0&&R(e.security.scriptSrc),e.security?.styleSrc!==void 0&&R(e.security.styleSrc),e.security?.imgSrc!==void 0&&R(e.security.imgSrc)}function vt(){if(typeof document>`u`)return;let e=document.getElementById(`shadow-claw-site-config`);if(e&&e.textContent)try{W(JSON.parse(e.textContent))}catch{}}let G=null,K=!1;function yt(){vt(),!(K||typeof customElements>`u`||typeof customElements.define!=`function`)&&(G=customElements.define.bind(customElements),customElements.define=function(e,t,n){if(!pt((e||``).toLowerCase().trim())){let t=`[Security] Registration blocked: <${e}> is not an approved custom element.`;throw console.error(t),Error(t)}return G(e,t,n)},K=!0)}function q(e=typeof document<`u`?document.documentElement:null){if(typeof MutationObserver>`u`||!e)return null;if(typeof e.querySelectorAll==`function`)try{e.querySelectorAll(`*`).forEach(e=>{let t=e.tagName?e.tagName.toLowerCase():``;t.includes(`-`)&&!pt(t)&&(console.warn(`[Security] Removing existing unapproved custom element: <${t}>`),e.remove())})}catch{}let t=new MutationObserver(e=>{for(let t of e)t.addedNodes.forEach(e=>{if(e.nodeType===1){let t=e,n=t.tagName?t.tagName.toLowerCase():``;n.includes(`-`)&&!pt(n)&&(console.warn(`[Security] Removing unapproved custom element: <${n}>`),t.remove())}})});return t.observe(e,{childList:!0,subtree:!0}),t}function bt(e){let t=p();return t?`shadowclaw:${t}:${e}`:e}function xt(e){if(typeof localStorage>`u`)return null;let t=bt(e);try{let n=localStorage.getItem(t);if(n!==null)return n;if(t===e)return null;let r=localStorage.getItem(e);if(r!==null)return localStorage.setItem(t,r),r}catch(e){console.warn(`Unable to read from localStorage:`,e)}return null}function St(){let e=sessionStorage.getItem(`shadow-claw-github-pages-404-redirect`);e&&sessionStorage.removeItem(`shadow-claw-github-pages-404-redirect`),e&&e!==location.pathname+location.search+location.hash&&history.replaceState(null,``,e)}function Ct(){t(),o(),yt(),q();let e=document.documentElement;e.classList.add(`sc-js-enabled`,`sc-js-boot-pending`);let n=!1;try{let e=xt(`shadow-claw-override-prerender-skeleton`);n=e===null||e===`true`}catch{n=!0}n&&e.classList.add(`sc-prerender-override`);let r=()=>{let e=document.querySelector(`shadow-claw`);return!e||e.getAttribute(`data-prerender-no-seed`)!==`true`&&!n?!1:(n&&(e.setAttribute(`data-prerender-no-seed`,`true`),e.setAttribute(`data-js-boot-pending`,`true`),e.setAttribute(`data-hydration-pending`,`true`)),!0)};if(!r()){let e=new MutationObserver(()=>{r()&&e.disconnect()});e.observe(document.documentElement,{childList:!0,subtree:!0})}let i=xt(`shadow-claw-theme`)||`system`,a=window.matchMedia&&window.matchMedia(`(prefers-color-scheme: dark)`).matches,s=i===`system`?a?`dark`:`light`:i;document.documentElement.classList.add(`${s}-mode`)}return St(),Ct(),window.addEventListener(`load`,e=>{let t=e.target;if(t&&t.tagName===`LINK`){let e=t;e.rel===`stylesheet`&&e.media===`print`&&e.href.includes(`Material+Symbols`)&&(e.media=`all`)}},!0),e.handleGithubPages404Redirects=St,e.initializeThemeAndBootState=Ct,e})({});</script><link rel="manifest" href="manifest.json"><link href="assets/icons/favicon.ico" rel="icon" type="image/x-icon" /><link href="assets/icons/180.png" rel="apple-touch-icon" /><style>:root{--shadow-claw-font-mono:"Fira Code","Courier New",monospace;--shadow-claw-font-sans:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;--shadow-claw-accent-hover:#1e293b;--shadow-claw-accent-primary:#334155;--shadow-claw-bg-primary-reverse:#0f172a;--shadow-claw-bg-primary:#f8fafc;--shadow-claw-bg-secondary:#f1f5f9;--shadow-claw-bg-tertiary:#e2e8f0;--shadow-claw-border-color:#e2e8f0;--shadow-claw-error-color:#ba1a1a;--shadow-claw-important-color:#334155;--shadow-claw-link-hover:#334155;--shadow-claw-link:#1e40af;--shadow-claw-on-error:#fff;--shadow-claw-on-primary:#fff;--shadow-claw-success-color:#059669;--shadow-claw-surface-tint:#334155;--shadow-claw-text-primary:#0f172a;--shadow-claw-text-secondary:#475569;--shadow-claw-text-tertiary:#64748b;--shadow-claw-warning-color:#d97706;--shadow-claw-font-size-lg:1.5rem;--shadow-claw-font-size-md:1.125rem;--shadow-claw-font-size-sm:0.875rem;--shadow-claw-radius-s:0.5rem;--shadow-claw-radius-m:0.75rem;--shadow-claw-radius-l:1.25rem;--shadow-claw-radius-pill:62.5rem;--shadow-claw-shadow-sm:0 0.0625rem 0.1875rem rgba(0,0,0,.1),0 0.0625rem 0.125rem rgba(0,0,0,.06);--shadow-claw-shadow-md:0 0.25rem 0.375rem -0.0625rem rgba(0,0,0,.1),0 0.125rem 0.25rem -0.0625rem rgba(0,0,0,.06);--shadow-claw-shadow-lg:0 0.625rem 0.9375rem -0.1875rem rgba(0,0,0,.1),0 0.25rem 0.375rem -0.125rem rgba(0,0,0,.05);--shadow-claw-shadow-sm:0 0.625rem 0.75rem 0 rgba(0,0,0,.05);--shadow-claw-shadow-md:0 0.625rem 1.875rem 0 rgba(0,0,0,.08);--shadow-claw-shadow-lg:0 0.625rem 1.875rem 0 rgba(0,0,0,.1);--shadow-claw-ease-in:cubic-bezier(0.32,0,0.67,0);--shadow-claw-ease-out:cubic-bezier(0.33,1,0.68,1);--shadow-claw-ease-in-out:cubic-bezier(0.65,0,0.35,1);--shadow-claw-duration-min:150ms;--shadow-claw-duration-regular:300ms;--shadow-claw-logo-size:1.5rem;--shadow-claw-header-title-font-size:1.5rem;--shadow-claw-icon-accent-dark:#8e1d13;--shadow-claw-icon-bg:transparent;--shadow-claw-icon-body-segment:#c0392b;--shadow-claw-icon-body-shine:#e74c3c;--shadow-claw-icon-body:#922b21;--shadow-claw-icon-claw-inner:#922b21;--shadow-claw-icon-claw-main:#c0392b;--shadow-claw-icon-eye-shine:#fff;--shadow-claw-icon-eye:#171d1e;--shadow-claw-hljs-background-color:#282c34;display:contents}@media (prefers-color-scheme:dark){:root{--shadow-claw-accent-hover:#cbd5e1;--shadow-claw-accent-primary:#94a3b8;--shadow-claw-on-primary:#0f172a;--shadow-claw-surface-tint:#94a3b8;--shadow-claw-bg-primary:#0f172a;--shadow-claw-bg-primary-reverse:#f8fafc;--shadow-claw-bg-secondary:#1e293b;--shadow-claw-bg-tertiary:#334155;--shadow-claw-border-color:#334155;--shadow-claw-error-color:#ffb4ab;--shadow-claw-link:#94a3b8;--shadow-claw-link-hover:#94a3b8;--shadow-claw-on-error:#690005;--shadow-claw-success-color:#34d399;--shadow-claw-text-primary:#f1f5f9;--shadow-claw-text-secondary:#cbd5e1;--shadow-claw-text-tertiary:#94a3b8;--shadow-claw-shadow-sm:0 0.0625rem 0.1875rem rgba(0,0,0,.3);--shadow-claw-shadow-md:0 0.25rem 0.375rem -0.0625rem rgba(0,0,0,.4);--shadow-claw-shadow-lg:0 0.625rem 0.9375rem -0.1875rem rgba(0,0,0,.5);--shadow-claw-icon-accent-dark:#ff6b6b;--shadow-claw-icon-body-segment:#ff5252;--shadow-claw-icon-body-shine:hsla(0,0%,100%,.3);--shadow-claw-icon-body:#ff1744;--shadow-claw-icon-claw-inner:#ff1744;--shadow-claw-icon-claw-main:#ff5252;--shadow-claw-icon-eye-shine:#171d1e;--shadow-claw-icon-eye:#dee3e5}}.light-mode{--shadow-claw-accent-hover:#1e293b;--shadow-claw-accent-primary:#334155;--shadow-claw-on-primary:#fff;--shadow-claw-surface-tint:#334155;--shadow-claw-bg-primary:#f8fafc;--shadow-claw-bg-primary-reverse:#0f172a;--shadow-claw-bg-secondary:#f1f5f9;--shadow-claw-bg-tertiary:#e2e8f0;--shadow-claw-border-color:#e2e8f0;--shadow-claw-error-color:#ba1a1a;--shadow-claw-link:#334155;--shadow-claw-link-hover:#1e293b;--shadow-claw-on-error:#fff;--shadow-claw-success-color:#059669;--shadow-claw-warning-color:#d97706;--shadow-claw-text-primary:#0f172a;--shadow-claw-text-secondary:#475569;--shadow-claw-text-tertiary:#64748b}.dark-mode{--shadow-claw-accent-hover:#cbd5e1;--shadow-claw-accent-primary:#94a3b8;--shadow-claw-on-primary:#0f172a;--shadow-claw-surface-tint:#94a3b8;--shadow-claw-bg-primary:#0f172a;--shadow-claw-bg-primary-reverse:#f8fafc;--shadow-claw-bg-secondary:#1e293b;--shadow-claw-bg-tertiary:#334155;--shadow-claw-border-color:#334155;--shadow-claw-error-color:#ffb4ab;--shadow-claw-link:#94a3b8;--shadow-claw-link-hover:#cbd5e1;--shadow-claw-on-error:#690005;--shadow-claw-success-color:#34d399;--shadow-claw-text-primary:#f1f5f9;--shadow-claw-text-secondary:#cbd5e1;--shadow-claw-text-tertiary:#94a3b8;--shadow-claw-shadow-sm:0 0.0625rem 0.1875rem rgba(0,0,0,.3);--shadow-claw-shadow-md:0 0.25rem 0.375rem -0.0625rem rgba(0,0,0,.4);--shadow-claw-shadow-lg:0 0.625rem 0.9375rem -0.1875rem rgba(0,0,0,.5);--shadow-claw-icon-accent-dark:#ff6b6b;--shadow-claw-icon-bg:transparent;--shadow-claw-icon-body-segment:#ff5252;--shadow-claw-icon-body-shine:hsla(0,0%,100%,.3);--shadow-claw-icon-body:#ff1744;--shadow-claw-icon-claw-inner:#ff1744;--shadow-claw-icon-claw-main:#ff5252;--shadow-claw-icon-eye-shine:#171d1e;--shadow-claw-icon-eye:#dee3e5}*,:after,:before{font-family:var(--shadow-claw-font-sans)}*{box-sizing:border-box;margin:0;padding:0;scrollbar-color:var(--shadow-claw-border-color) transparent;scrollbar-width:thin}::-webkit-scrollbar{height:.5rem;width:.5rem}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--shadow-claw-border-color);border-radius:.25rem}::-webkit-scrollbar-thumb:hover{background:var(--shadow-claw-text-tertiary)}body,html{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--shadow-claw-bg-primary);color:var(--shadow-claw-text-primary);display:flex;flex-direction:column;width:100%}@media (max-width:48rem){input,select,textarea{font-size:16px}}html.sc-prerender-override shadow-claw{visibility:hidden}shadow-claw:not(:defined){background:radial-gradient(circle at 20% 15%,rgba(56,189,248,.08),transparent 40%),radial-gradient(circle at 85% 90%,rgba(51,65,85,.2),transparent 45%),var(--shadow-claw-bg-primary);color:var(--shadow-claw-text-primary);display:grid}.header-title-link,.header-title-link:hover{color:var(--shadow-claw-text-primary);display:flex;text-decoration:none}.header-title-logo{display:none;height:var(--shadow-claw-logo-size,1.5rem);width:var(--shadow-claw-logo-size,1.5rem)}.header-title{align-items:center;display:none;font-size:var(--shadow-claw-header-title-font-size,1.5rem);margin-left:.5rem}@media (min-width:30rem){.header-title,.header-title-logo{display:flex}}.header-actions-logo-link{align-items:center;color:inherit;display:flex;flex-direction:row;height:2.5rem;justify-content:center;width:2.5rem}.header-actions-logo-link svg{height:1.5rem;width:1.5rem}.app-dialog,dialog{background-color:var(--shadow-claw-bg-secondary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-l,1.25rem);box-shadow:var(--shadow-claw-shadow-lg);color:var(--shadow-claw-text-primary);padding:0}.app-dialog::backdrop,dialog::backdrop{backdrop-filter:blur(2px);background:color-mix(in srgb,#000 65%,transparent)}</style><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined&display=swap" media="print"><noscript> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined&display=swap"> </noscript> <script id="shadow-claw-static-manifest" type="application/json">{"pages":[{"displayPath":"~\u002fdocs\u002fskill-creator.md","content":"---\ntitle: \"Agent Skills & Skill Creator\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"skill-creator\"\n---\n\n## Agent Skills & Skill Creator\n\nWelcome to the ShadowClaw Agent Skills guide! Skills are workspace-local instruction packages and automated tool pipelines that give your AI assistant specialized capabilities.\n\nWhether you want to teach the assistant a specialized coding workflow, build silent background utility tools, or trigger automated tasks with slash commands, **Agent Skills** make it simple and declarative.\n\n---\n\n## 🌟 Quick Start: What is an Agent Skill?\n\nAn Agent Skill is a directory containing a `SKILL.md` file located inside your workspace's `.agents\u002fskills\u002f` folder:\n\n```text\n.agents\u002fskills\u002f\n└── main\u002f\n ├── skill-creator\u002f\n │ ├── SKILL.md\n │ └── references\u002f\n │ ├── frontmatter-spec.md\n │ ├── declarative-pipelines.md\n │ └── declarative-tools.md\n └── toast-random-number\u002f\n └── SKILL.md\n```\n\nEach skill includes:\n\n1. **`SKILL.md`**: Standard frontmatter metadata (name, description, slash command triggers) and step-by-step instructions.\n2. **`references\u002f` Directory**: Detailed reference guides and technical documentation co-located with the skill.\n3. **Declarative Pipelines**: Optional deterministic tool workflows (`execution.type: \"tools\"`) that execute instantly without calling LLM prompts.\n\n---\n\n## 🚀 Creating Skills with `\u002fskill-creator`\n\nShadowClaw comes with an official bundled **Skill Creator**. You can trigger it anytime by typing `\u002fskill-creator` in the chat thread or asking the AI assistant to create a skill for you.\n\n### Recommended Skill Authoring Workflow\n\n1. **Define the Scope & Trigger**: Decide on a clear skill name (e.g. `toast-random-number`) and write a concise description of what it does.\n2. **Set Up Workspace Folders**:\n - Skill files belong in `.agents\u002fskills\u002fmain\u002f\u003cskill-name\u003e\u002fSKILL.md`.\n - Custom declarative tools belong in `.agents\u002ftools\u002fmain\u002f\u003ctool-name\u003e.json`.\n3. **Write `SKILL.md`**: Configure standard frontmatter attributes and instructions.\n4. **Add Technical References**: Store detailed reference materials under the skill's `references\u002f` directory.\n\n---\n\n## 📚 Skill Reference Documentation\n\nFor deep technical details, explore the co-located reference guides bundled with the official `skill-creator` skill:\n\n- 📋 **[Frontmatter Specification](file:\u002f\u002f\u002f.agents\u002fskills\u002fmain\u002fskill-creator\u002freferences\u002ffrontmatter-spec.md)** \n Complete schema rules for `name`, `description`, `user-invocable`, `disable-model-invocation`, `argument-hint`, and `metadata.allowed-tools`.\n\n- ⚡ **[Declarative Execution Pipelines](file:\u002f\u002f\u002f.agents\u002fskills\u002fmain\u002fskill-creator\u002freferences\u002fdeclarative-pipelines.md)** \n How to write zero-LLM tool chains using `execution.type: \"tools\"`, `$pipe` output piping, `suppressToast`, and `suppressOutput`.\n\n- 🛠️ **[Declarative Tools Reference](file:\u002f\u002f\u002f.agents\u002fskills\u002fmain\u002fskill-creator\u002freferences\u002fdeclarative-tools.md)** \n How to author custom JSON tool definitions in `.agents\u002ftools\u002f` with sandboxed JavaScript evaluation and WebMCP model context integration.\n\n---\n\n## 💡 Example: A Two-Step Declarative Skill\n\nHere is a complete, real-world example of a declarative skill that generates a random number and displays it in a toast notification silently:\n\n```yaml\n---\nname: toast-random-number\ndescription: Generate a random integer from 1 to 1000000 and show it in a ShadowClaw toast notification.\nuser-invocable: true\nmetadata:\n allowed-tools: javascript show_toast generate_random_number\n execution:\n type: tools\n suppressToast: true\n suppressOutput: true\n tools:\n - name: javascript\n input:\n code: Math.floor(Math.random() * 1000000) + 1\n - name: show_toast\n input:\n title: Random Number\n message:\n $pipe: prev\n---\n# Toast Random Number\n\nThis skill generates a random integer and displays it instantly in a toast notification.\n```\n\nWhen you type `\u002ftoast-random-number`, ShadowClaw executes the two steps directly without delay!\n"},{"displayPath":"index.html","content":"---\ntitle: \"ShadowClaw Pages\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"shadow-claw-pages\"\n---\n\n\u003carticle\u003e\n \u003ch2\u003eWelcome to ShadowClaw Pages\u003c\u002fh2\u003e\n \u003cp\u003eThis is the default static page for your workspace.\u003c\u002fp\u003e\n \u003ch2 id=\"getting-started-with-shadowclaw\"\u003eGetting started with ShadowClaw\u003c\u002fh2\u003e\n \u003ch3 id=\"what-is-memorymd\"\u003eWhat is MEMORY.md?\u003c\u002fh3\u003e\n \u003cul\u003e\n \u003cli\u003e\n \"\u003ca href=\"\u002ffiles\u002fmain\u002fMEMORY.md\"\u003eMEMORY.md\u003c\u002fa\u003e\" is a per conversation, per\n invocation, auto-loaded, persistent agent memory file.\n \u003c\u002fli\u003e\n \u003cli\u003e\n It is designed to be a helpful scratchpad for agents to store important\n information, notes, and context about the conversation.\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003ch3 id=\"how-to-use-files\"\u003eHow to use Files\u003c\u002fh3\u003e\n \u003cul\u003e\n \u003cli\u003eOpen \"\u003ca href=\"\u002ffiles\u002fmain\"\u003eFiles\u003c\u002fa\u003e\" to browse your workspace.\u003c\u002fli\u003e\n \u003cli\u003e\n Edit and preview files with the file viewer:\n \u003cul\u003e\n \u003cli\u003e\u003ca href=\"\u002ffiles\u002fmain\u002findex.html\"\u003eindex.html\u003c\u002fa\u003e\u003c\u002fli\u003e\n \u003cli\u003e\n \u003ca href=\"\u002ffiles\u002fmain\u002f~\u002fdocs\u002fexample\u002farticle.html\"\u003earticle.html\u003c\u002fa\u003e\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003ch3 id=\"how-to-use-pages\"\u003eHow to use Pages\u003c\u002fh3\u003e\n \u003cul\u003e\n \u003cli\u003eUse Set as Page on any markdown or HTML file to add it to Pages.\u003c\u002fli\u003e\n \u003cli\u003eRemove a page anytime from the \"\u003ca href=\"\u002fpages\"\u003ePages\u003c\u002fa\u003e\" view.\u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003ch3 id=\"how-to-use-chat\"\u003eHow to use Chat\u003c\u002fh3\u003e\n \u003cul\u003e\n \u003cli\u003e\n Open \"\u003ca href=\"\u002fsettings\"\u003eSettings\u003c\u002fa\u003e\" to configure your agent's system\n prompt, tools, and more.\n \u003c\u002fli\u003e\n \u003cli\u003e\n Open \"\u003ca href=\"\u002fchat\u002fmain\"\u003eChat\u003c\u002fa\u003e\" to start a conversation with your\n agent.\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003ch2 id=\"further-information\"\u003eFurther information\u003c\u002fh2\u003e\n \u003cul\u003e\n \u003cli\u003e\n \u003ca href=\"https:\u002f\u002fgithub.com\u002fxt-ml\u002fshadow-claw#-shadowclaw\"\n \u003eShadowClaw Project\u003c\u002fa\n \u003e\n \u003c\u002fli\u003e\n \u003cli\u003e\u003ca href=\"https:\u002f\u002fdeepwiki.com\u002fxt-ml\u002fshadow-claw\"\u003eDeep Wiki\u003c\u002fa\u003e\u003c\u002fli\u003e\n \u003c\u002ful\u003e\n\u003c\u002farticle\u003e\n"},{"displayPath":"~\u002fdocs\u002fpublishing-to-github-pages.md","content":"---\ntitle: \"Publishing to GitHub Pages\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"publishing-to-github-pages\"\n---\n\n## Publishing to GitHub Pages\n\nShadowClaw can drive a fully automated static-site publishing pipeline directly from the browser, with the only server-side requirement being a GitHub Actions workflow that runs the Node.js build.\n\n---\n\n## Deployment strategies\n\n### Strategy A — Full fork\n\nClone the entire ShadowClaw repository, add your pages to `pages\u002fmain\u002f`, push to a new repo you own, and let CI build and deploy it.\n\n### Strategy B — Pages-only repo (Git clone & inject in CI)\n\nYour repo contains your content, an optional root-level `shadow-claw.config.json` (or `site-config.json`), and a GitHub Actions workflow. Content lives under `pages\u002f`; the workflow checks out ShadowClaw as a build toolchain in CI and builds into `dist\u002fpublic`.\n\n### Strategy C — NPM Package & CLI (`npx shadow-claw`)\n\nRun or deploy using the `shadow-claw` npm package directly:\n\n- Locally: `npx shadow-claw dev` (or `shadow-claw run`) to preview with dev server.\n- In CI: `npx shadow-claw build --prod` builds `dist\u002fpublic` without needing to clone ShadowClaw or copy files.\n- In `package.json`: add `\"shadow-claw\": \"^1.22.4\"` as a devDependency and run `npm run build`.\n\n**Strategy B and Strategy C are both fully supported for content-only repositories and knowledge hubs.**\n\n---\n\n## Strategy B — Step-by-step\n\n### 1. Create a new GitHub repository\n\nCreate an empty repo at `github.com\u002f\u003cyou\u003e\u002f\u003cyour-site\u003e`. Enable **Settings → Pages → Source: GitHub Actions**.\n\n### 2. Add the workflow\n\nCreate `.github\u002fworkflows\u002fdeploy-pages.yml`:\n\n```yaml\nname: Build and Deploy via ShadowClaw\n\non:\n push:\n branches: [main]\n workflow_dispatch:\n inputs:\n shadowclaw_version:\n description: \"ShadowClaw npm version (e.g. latest, 1.23.3)\"\n required: false\n default: \"latest\"\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\nconcurrency:\n group: pages\n cancel-in-progress: true\n\njobs:\n build-and-deploy:\n environment:\n name: github-pages\n url: ${{ steps.deployment.outputs.page_url }}\n runs-on: ubuntu-latest\n steps:\n - name: Checkout repository\n uses: actions\u002fcheckout@v6\n\n - name: Setup Node.js\n uses: actions\u002fsetup-node@v6\n with:\n node-version: \"24\"\n\n - name: Build static site via ShadowClaw CLI\n env:\n PAGES_ORIGIN: \"https:\u002f\u002f${{ github.repository_owner }}.github.io\u002f${{ github.event.repository.name }}\u002f\"\n PAGES_BASE_PATH: \"\u002f${{ github.event.repository.name }}\u002f\"\n run: |\n VERSION=\"${{ github.event.inputs.shadowclaw_version || 'latest' }}\"\n npx --yes \"shadow-claw@$VERSION\" build --prod\n\n - name: Upload Pages artifact\n uses: actions\u002fupload-pages-artifact@v3\n with:\n path: dist\u002fpublic\n\n - name: Deploy to GitHub Pages\n id: deployment\n uses: actions\u002fdeploy-pages@v4\n```\n\n### Version Pinning\n\nShadowClaw builds via `npx --yes shadow-claw@latest build --prod`. To pin to a specific npm release (e.g. `1.23.3`), specify the version in `.github\u002fworkflows\u002fdeploy-pages.yml` or supply `shadowclaw_version` when triggering the GitHub Actions workflow manually.\n\nFor a **custom apex domain** (e.g. `example.com`), override:\n\n```yaml\nPAGES_ORIGIN: \"https:\u002f\u002fexample.com\u002f\"\nPAGES_BASE_PATH: \"\u002f\"\n```\n\n### 3. Add your content\n\n```text\npages\u002f\n main\u002f\n index.html ← home page\n ~\u002fcontent\u002f\n about.md ← any other pages\n routes.json ← pretty-path config (optional)\n\nshadow-claw.config.json ← branding, default tool settings, and build configuration (optional)\n```\n\nSite configurations can also specify tool defaults under `settings`:\n\n```json\n{\n \"settings\": {\n \"defaultToolsProfile\": \"__builtin_default\",\n \"enabledTools\": [\"javascript\", \"read_file\", \"write_file\"]\n }\n}\n```\n\nThe `pages\u002f` directory is optional. If it is absent, the build succeeds and\nShadowClaw publishes its built-in `index.html` and `MEMORY.md` Pages content.\nPretty paths are skipped unless a `routes.json` file is present.\n\nMinimal `pages\u002froutes.json`:\n\n```json\n{\n \"routes\": {\n \"\u002fpages\u002fmain\u002findex.html\": { \"prettyPath\": \"\u002fmain\" },\n \"\u002fpages\u002fmain\u002f~\u002fcontent\u002fabout.md\": { \"prettyPath\": \"\u002fmain\u002fabout\" },\n \"\u002fpages\u002fmain\u002fMEMORY.md\": { \"prettyPath\": \"\u002fmain\u002fmemory\" }\n }\n}\n```\n\n\u003e **Reserved path prefixes** — the following first-path-segments are owned by\n\u003e ShadowClaw's own router and **must not** be used as pretty path prefixes:\n\u003e `\u002f`, `\u002fchat`, `\u002ffiles`, `\u002ftasks`, `\u002fpages`, `\u002fsettings`, `\u002ftools`, `\u002fchannels`.\n\u003e `\u002f` (root) is also reserved as the default pinned page and is unreachable as\n\u003e a pretty path. Use a safe namespace like `\u002fmain\u002f`, `\u002farticles\u002f`, `\u002fdocs\u002f`, or\n\u003e any custom prefix that doesn't collide with the list above.\n\n#### Default Pinned Page (`\u002f`)\n\nWhen visitors navigate to the root URL (`\u002f`) of your published site, ShadowClaw displays the **default pinned page**.\n\n**How ShadowClaw selects the default page for `\u002f`:**\n\n1. Both the static site prerenderer (`prerender-dsd-shell`) and runtime page store (`orchestratorStore`) gather all page files in `pages\u002fmain\u002f`. If `pages\u002fmain\u002f` is absent, both use the built-in default `index.html` and `MEMORY.md` pages.\n2. `MEMORY.md` is always moved to the bottom of the list.\n3. All remaining pages are sorted by `pages.sortOrder` from `shadow-claw.config.json` (or `site-config.json`) (`\"desc\"` by default, natural numeric, or `\"asc\"`).\n4. The first file in this sorted list (`pages[0]`) becomes the default page rendered at `\u002f`.\n\n**How to ensure your intended home page is rendered at `\u002f`:**\nName your landing page file so it sorts first in reverse-alphabetical order relative to other files in `pages\u002fmain\u002f`:\n\n- `index.md` or `index.html` will sort ahead of `about.md`, `contact.md`, or `faq.md`.\n- If you have files starting with letters after `i` (e.g. `welcome.md`), `welcome.md` will sort ahead of `index.md`. Ensure your preferred landing page filename sorts highest in reverse-alphabetical order.\n\n### 4. Push — CI does the rest\n\nEvery push to `main` triggers a build (~3–5 min on a cold runner, faster with the npm cache warm) and deploys to `https:\u002f\u002f\u003cyou\u003e.github.io\u002f\u003cyour-site\u003e\u002f`.\n\n---\n\n## In-browser automation (no LLM, no server)\n\nShadowClaw can publish to your content repo entirely from the browser using a `type: \"tools\"` task chain. The chain is deterministic — it makes **zero LLM calls**.\n\n### Prerequisites\n\n- Clone your content repo into the workspace: ask the agent to `git_clone https:\u002f\u002fgithub.com\u002f\u003cyou\u003e\u002f\u003cyour-site\u003e`, or do it manually.\n- Configure a GitHub Personal Access Token in **Settings → Git → PAT** (needs `repo` scope for private repos, `public_repo` for public ones).\n\n### Minimal publish chain\n\n```json\n{\n \"type\": \"tools\",\n \"tools\": [\n {\n \"name\": \"write_file\",\n \"input\": {\n \"path\": \"repos\u002fyour-site\u002fpages\u002fmain\u002fpost.md\",\n \"content\": \"---\\ntitle: My Post\\n---\\n\\n# Hello World\\n\\nContent here.\"\n }\n },\n {\n \"name\": \"git_add\",\n \"input\": {\n \"repo\": \"your-site\",\n \"files\": [\"pages\u002fmain\u002fpost.md\"]\n }\n },\n {\n \"name\": \"git_commit\",\n \"input\": {\n \"repo\": \"your-site\",\n \"message\": \"publish: new post\"\n }\n },\n {\n \"name\": \"git_push\",\n \"input\": {\n \"repo\": \"your-site\"\n }\n }\n ]\n}\n```\n\n### Fetch-transform-publish chain (fully automated data pipeline)\n\nThis chain fetches an external data source, transforms it to markdown via the JavaScript sandbox, writes it as a page, and pushes — no human in the loop:\n\n```json\n{\n \"type\": \"tools\",\n \"tools\": [\n {\n \"name\": \"fetch_url\",\n \"input\": {\n \"url\": \"https:\u002f\u002fapi.github.com\u002frepos\u002fxt-ml\u002fshadow-claw\u002freleases\u002flatest\"\n }\n },\n {\n \"name\": \"javascript\",\n \"input\": {\n \"code\": \"const match = $PIPE_DATA.match(\u002f--- BEGIN EXTERNAL CONTENT[\\\\s\\\\S]*?---\\\\n([\\\\s\\\\S]*?)\\\\n--- END EXTERNAL CONTENT ---\u002f); const raw = match ? match[1] : $PIPE_DATA; const rel = JSON.parse(raw); const date = rel.published_at?.slice(0, 10) ?? 'unknown'; return `---\\\\ntitle: ShadowClaw ${rel.tag_name}\\\\ndate: ${date}\\\\n---\\\\n\\\\n# ${rel.name}\\\\n\\\\nPublished: ${date}\\\\n\\\\n${rel.body ?? ''}`;\",\n \"data\": { \"$pipe\": \"prev\" }\n }\n },\n {\n \"name\": \"write_file\",\n \"input\": {\n \"path\": \"repos\u002fyour-site\u002fpages\u002fmain\u002frelease-notes.md\",\n \"content\": { \"$pipe\": \"prev\" }\n }\n },\n {\n \"name\": \"git_add\",\n \"input\": {\n \"repo\": \"your-site\",\n \"files\": [\"pages\u002fmain\u002frelease-notes.md\"]\n }\n },\n {\n \"name\": \"git_commit\",\n \"input\": {\n \"repo\": \"your-site\",\n \"message\": \"shadow-claw[bot]: sync release notes\"\n }\n },\n {\n \"name\": \"git_push\",\n \"input\": {\n \"repo\": \"your-site\"\n }\n }\n ]\n}\n```\n\n---\n\n## Strategy C — NPM Package & CLI Workflow\n\nIf you prefer building directly with `npx shadowclaw` without cloning the ShadowClaw repository in CI, use this minimal workflow:\n\n```yaml\nname: Build and Deploy via ShadowClaw CLI\n\non:\n push:\n branches: [main]\n workflow_dispatch:\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\nconcurrency:\n group: pages\n cancel-in-progress: true\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout content repo\n uses: actions\u002fcheckout@v4\n\n - uses: actions\u002fsetup-node@v4\n with:\n node-version: \"24\"\n\n - name: Build production bundle\n env:\n NODE_ENV: production\n PAGES_ORIGIN: \"https:\u002f\u002f${{ github.repository_owner }}.github.io\u002f${{ github.event.repository.name }}\u002f\"\n PAGES_BASE_PATH: \"\u002f${{ github.event.repository.name }}\u002f\"\n run: npx shadow-claw build --prod\n\n - name: Upload Pages artifact\n uses: actions\u002fupload-pages-artifact@v3\n with:\n path: dist\u002fpublic\n\n deploy:\n needs: build\n runs-on: ubuntu-latest\n environment:\n name: github-pages\n url: ${{ steps.deployment.outputs.page_url }}\n steps:\n - name: Deploy to GitHub Pages\n id: deployment\n uses: actions\u002fdeploy-pages@v4\n```\n\n\u003e **Tip:** Wrap this in a scheduled task (Tasks sidebar → New Task → type `tools`, set a cron interval) to run the pipeline automatically, e.g. every 24 hours. No LLM calls are made at execution time.\n\n---\n\n## Template repository\n\nA ready-to-fork starter template is available in the [`shadow-claw-template`](https:\u002f\u002fgithub.com\u002fxt-ml\u002fshadow-claw-template) repository. It contains the workflow, sample `pages\u002fmain\u002findex.html`, `pages\u002fmain\u002f~\u002fcontent\u002fabout.md`, root-level `shadow-claw.config.json`, and `pages\u002froutes.json`.\n"},{"displayPath":"~\u002fdocs\u002fexample\u002farticle.html","content":"---\ntitle: \"Article\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"article\"\n---\n\n\u003carticle\u003e\n \u003ch2\u003eBig Buck Bunny\u003c\u002fh2\u003e\n\n \u003cvideo controls style=\"border-radius: 0.5rem; width: 100%\"\u003e\n \u003csource\n src=\"https:\u002f\u002fxt-ml.github.io\u002fassets\u002fmedia\u002fBigBuckBunny\u002fBigBuckBunny_320x180.mp4\"\n type=\"video\u002fmp4\"\n \u002f\u003e\n \u003c\u002fvideo\u003e\n \u003csection\u003e\n \u003ch2\u003eLicensing\u003c\u002fh2\u003e\n \u003cul\u003e\n \u003cli\u003e\n \u003ccode\u003eBig Buck Bunny\u003c\u002fcode\u003e is licensed under the\n \u003ca href=\"https:\u002f\u002fblender.org\"\n \u003eCreative Commons Attribution 3.0 License\u003c\u002fa\n \u003e.\n \u003cul\u003e\n \u003cli\u003e\n Attribution: Blender Foundation \u002f\n \u003ca href=\"https:\u002f\u002fwww.blender.org\u002f\"\u003ewww.blender.org\u003c\u002fa\u003e\n \u003c\u002fli\u003e\n \u003cli\u003e\n Copyright: (c) copyright 2008, Blender Foundation \u002f\n \u003ca href=\"https:\u002f\u002fwww.bigbuckbunny.org\u002f\"\u003ewww.bigbuckbunny.org\u003c\u002fa\u003e\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003c\u002fsection\u003e\n\u003c\u002farticle\u003e\n"},{"displayPath":"MEMORY.md","content":"---\ntitle: \"Agent Memory\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"agent-memory\"\n---\n\n## Memory\n\n### Workspace Layout & Skills Conventions\n\n- **Skills**: `.agents\u002fskills\u002fmain\u002f\u003cskill-name\u003e\u002fSKILL.md`\n- **Declarative Tools**: `.agents\u002ftools\u002fmain\u002f\u003ctool-name\u003e.json`\n- **Skill Format**: Markdown file with YAML frontmatter AND a Markdown body (frontmatter is metadata only; always include a `# \u003cSkill Title\u003e` heading and human-readable description in the Markdown body so it renders in document previews):\n\n ```yaml\n ---\n name: \u003cskill-name\u003e\n description: \u003cclear summary for model and slash command\u003e\n user-invocable: true\n metadata:\n allowed-tools: \u003ctool1\u003e \u003ctool2\u003e\n execution:\n type: tools\n tools:\n - name: \u003ctool1\u003e\n input: { ... }\n - name: \u003ctool2\u003e\n input: { \"$pipe\": \"prev\" }\n ---\n # \u003cSkill Title\u003e\n\n \u003cOverview and description of what the skill does, parameters, and usage instructions.\u003e\n ```\n\n- **Declarative Tool Format**: JSON with `\"name\"`, `\"description\"`, `\"executor\": \"javascript\"`, `\"inputSchema\"`, and `\"code\"`.\n- **Authoring**: Use `create_directory` before writing new directories, then `write_file`.\n"}],"skills":[{"displayPath":"skill-creator\u002freferences\u002fdeclarative-pipelines.md","content":"# Declarative Execution Pipelines\n\nDeclarative execution pipelines allow skills to execute deterministic sequential tool chains directly on the worker thread without scheduling a Task or making model LLM calls.\n\n## Configuration Syntax\n\nPipelines are declared in `SKILL.md` frontmatter under `metadata.execution`:\n\n```yaml\n---\nname: sample-pipeline\ndescription: Run a deterministic tool chain.\nuser-invocable: true\nmetadata:\n allowed-tools: javascript show_toast\n execution:\n type: tools\n suppressToast: true\n suppressOutput: true\n tools:\n - name: javascript\n input:\n code: \"Math.floor(Math.random() * 100) + 1\"\n - name: show_toast\n input:\n title: \"Random Number\"\n message:\n $pipe: prev\n---\n```\n\n## Data Piping (`$pipe`)\n\nInputs in tool step configurations can reference outputs from previous steps using the `$pipe` operator:\n\n- `{ \"$pipe\": \"prev\" }` or `{ \"$pipe\": -1 }`: Resolves to the return output of the immediately preceding tool step.\n- `{ \"$pipe\": 0 }`: Resolves to the return output of step index `0` (0-indexed).\n- `{ \"$pipe\": \"javascript\" }`: Resolves to the return output of the last step that ran the `javascript` tool.\n\n## Execution Suppression\n\n- `suppressToast: true`: Suppresses step progress toasts (\"Running skill tool...\") during pipeline execution.\n- `suppressOutput: true`: Suppresses raw tool result blocks from being rendered in the chat thread.\n- Setting suppression options at the `execution` root cascades down to all steps unless explicitly overridden per tool step.\n"},{"displayPath":"skill-creator\u002freferences\u002fdeclarative-tools.md","content":"# Declarative Tools\n\nDeclarative tools allow workspace authors to define reusable custom tools using JSON definitions placed under `.agents\u002ftools\u002f\u003cgroup\u003e\u002f\u003ctool-name\u003e.json`.\n\n## Directory Structure\n\n```text\n.agents\u002ftools\u002f\n└── main\u002f\n └── generate_random_number.json\n```\n\n## Schema Format\n\n```json\n{\n \"name\": \"generate_random_number\",\n \"description\": \"Generate a random integer within a specified range.\",\n \"executor\": \"javascript\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"min\": { \"type\": \"number\", \"default\": 1 },\n \"max\": { \"type\": \"number\", \"default\": 1000000 }\n }\n },\n \"code\": \"const min = Number(inputs.min ?? 1); const max = Number(inputs.max ?? 1000000); return Math.floor(Math.random() * (max - min + 1)) + min;\"\n}\n```\n\n## Features\n\n- **Automatic Discovery**: Automatically loaded from `.agents\u002ftools\u002f` across conversation workspaces.\n- **WebMCP Integration**: Registered with the browser ModelContext API for both manual pinning and automated agent execution.\n- **Expression Evaluation**: Code expressions automatically evaluate and return results without needing explicit wrapper boilerplate.\n"},{"displayPath":"skill-creator\u002freferences\u002ffrontmatter-spec.md","content":"# Frontmatter Specification\n\nAgent skills in ShadowClaw are configured via YAML frontmatter at the top of `SKILL.md`. Frontmatter attributes adhere strictly to the standard Agent Skills specification.\n\n## Specification Schema\n\n```yaml\n---\nname: skill-name\ndescription: Clear, concise model-facing trigger description.\nuser-invocable: true\ndisable-model-invocation: false\nargument-hint: \"[arguments]\"\nmetadata:\n allowed-tools: read_file write_file javascript\ncompatibility: ShadowClaw\nlicense: MIT\n---\n```\n\n## Attribute Reference\n\n| Attribute | Type | Required | Description |\n| :------------------------- | :-------- | :------- | :-------------------------------------------------------------------------------------------------------- |\n| `name` | `string` | **Yes** | Skill identifier (1–64 lowercase alphanumeric characters and single hyphens). |\n| `description` | `string` | **Yes** | Model-facing description used for skill discovery and activation (max 1024 characters). |\n| `user-invocable` | `boolean` | No | When `true` (default), allows users to invoke the skill directly via slash commands (e.g. `\u002fskill-name`). |\n| `disable-model-invocation` | `boolean` | No | When `true`, hides the skill from model discovery so it is only triggered via slash command. |\n| `argument-hint` | `string` | No | Display placeholder in the UI search\u002fautocomplete menu when typing slash commands. |\n| `metadata` | `object` | No | Key-value dictionary for custom metadata, tool permissions (`allowed-tools`), and `execution` pipelines. |\n| `compatibility` | `string` | No | Platform compatibility requirements or version strings. |\n| `license` | `string` | No | Open-source software license string (e.g. `MIT`, `AGPL-3.0`). |\n\n## Metadata Attributes (`metadata`)\n\nCustom configuration properties and extension specifications (like declarative execution pipelines) that fall outside the standard Agent Skills frontmatter attributes should be placed inside `metadata`:\n\n```yaml\nmetadata:\n allowed-tools: javascript show_toast generate_random_number\n author: ShadowClaw Team\n version: 1.0.0\n execution:\n type: tools\n suppressToast: true\n tools:\n - name: javascript\n input:\n code: Math.floor(Math.random() * 100) + 1\n```\n"},{"displayPath":"skill-creator\u002fSKILL.md","content":"---\nname: skill-creator\ndescription: Create, edit, review, and validate ShadowClaw declarative skills and their supporting resources.\nuser-invocable: true\nmetadata:\n allowed-tools: read_file write_file javascript create_directory\n---\n\n# ShadowClaw Skill Creator\n\nUse this skill when creating, modifying, reviewing, or validating a ShadowClaw agent skill or declarative tool pipeline.\n\n## Workspace Layout Standards\n\n- **Skills**: Create each skill in its dedicated directory under `.agents\u002fskills\u002f\u003cgroup\u003e\u002f\u003cskill-name\u003e\u002fSKILL.md` (default group: `main`).\n- **Declarative Tools**: Define supporting declarative tools under `.agents\u002ftools\u002f\u003cgroup\u003e\u002f\u003ctool-name\u003e.json` (default group: `main`).\n- **Supporting Resources**: Co-locate skill-specific assets (reference documents, templates, helper scripts) inside the skill directory alongside `SKILL.md`.\n\n## Workflow\n\n1. **Establish Contract & Scope**\n - For existing skills, read `SKILL.md` and related resources before editing.\n - For new skills, define the trigger prompt, intended execution outcome, required tools, and output artifacts.\n2. **Configure Frontmatter**\n - Provide a clear, concise trigger description in `description` (1024 characters max).\n - Set `user-invocable: true` if the skill should be triggerable via slash command (e.g. `\u002fskill-name`).\n - Use `disable-model-invocation: true` for skills intended strictly for slash-command execution.\n - Place non-standard configuration (such as `allowed-tools`) within the standard `metadata` block to maintain Agent Skills specification compliance.\n3. **Structure & Draft Content**\n - Write instructions in `SKILL.md` using clear, modular procedures.\n - Place deterministic operations in `javascript` tool calls; use `read_file` and `write_file` for workspace persistence.\n - Create required target directories via `create_directory` prior to writing files.\n4. **Declarative Pipelines (`execution.type: tools`)**\n - Define sequential tool pipelines in frontmatter via `execution: { type: \"tools\", tools: [...] }`.\n - Pass outputs between steps using `{ \"$pipe\": \"prev\" }` or step\u002ftool identifiers.\n - Optionally apply `suppressToast: true` or `suppressOutput: true` at the execution root or per step to suppress notifications and output blocks.\n5. **Verify & Validate**\n - Re-read the saved `SKILL.md` and verify valid YAML frontmatter syntax.\n - Ensure the skill name uses 1–64 lowercase alphanumeric characters or hyphens and all referenced resource paths exist.\n"}]}</script>
6
+ `+u),H&&(u=ln(u)),_&&xt?b(u):u},t.setConfig=function(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};Yt(e),vt=!0,G=I,K=L},t.clearConfig=function(){Kt=null,vt=!1,G=null,K=null,_=ae,v=``},t.isValidAttribute=function(e,t,n){Kt||Yt({});let r=X(e),i=X(t);return vn(r,i,n)},t.addHook=function(e,t){typeof t==`function`&&E(D,e)&&he(D[e],t)},t.removeHook=function(e,t){if(E(D,e)){if(t!==void 0){let n=pe(D[e],t);return n===-1?void 0:ge(D[e],n,1)[0]}return me(D[e])}},t.removeHooks=function(e){E(D,e)&&(D[e]=[])},t.removeAllHooks=function(){D=it()},t}at();let ot=[`youtube.com`,`youtube-nocookie.com`,`youtu.be`,`xt-ml.github.io`,`kherrick.github.io`];function st(e){e.map(e=>ct(e)).filter(Boolean)}st(ot);function ct(e){let t=e.trim();if(!t)return()=>!1;if(t.startsWith(`/`)&&(t.endsWith(`/`)||/\/[gimuy]*$/.test(t)))try{let e=t.lastIndexOf(`/`),n=t.slice(1,e),r=t.slice(e+1),i=new RegExp(n,r||`i`);return e=>i.test(e)}catch{}if(t.includes(`^`)||t.includes(`$`)||t.includes(`(`)&&t.includes(`)`))try{let e=new RegExp(t,`i`);return t=>e.test(t)}catch{}if(t.startsWith(`*.`)){let e=t.slice(2).toLowerCase();return t=>{let n=t.toLowerCase();return n===e||n.endsWith(`.`+e)}}let n=t.toLowerCase();return e=>{let t=e.toLowerCase();return t===n||t.endsWith(`.`+n)}}let lt=[],ut=[],dt=new Set(lt.map(e=>e.toLowerCase().trim())),I=[...ut];function ft(e){e.map(e=>ct(e)).filter(Boolean)}ft(I);function L(e){return Array.isArray(e)?e.map(e=>typeof e==`string`?e.toLowerCase().trim():``).filter(Boolean):typeof e==`string`?e.split(/[\n,]+/).map(e=>e.toLowerCase().trim()).filter(Boolean):[]}function R(e){return Array.isArray(e)?e.map(e=>typeof e==`string`?e.trim():``).filter(Boolean):typeof e==`string`?e.split(/[\n,]+/).map(e=>e.trim()).filter(Boolean):[]}function z(e){let t=L(e);dt=new Set(t)}function B(e){let t=R(e);I=t,ft(t)}function pt(e){if(!e||typeof e!=`string`)return!1;let t=e.trim().toLowerCase();return!t.includes(`-`)||t===`shadow-claw`||t.startsWith(`shadow-claw-`)?!0:dt.has(t)}let V=`allow-modals allow-scripts allow-popups allow-popups-to-escape-sandbox`,mt=[`'self'`,`blob:`,`data:`],ht=[`'self'`,`blob:`,`data:`],gt=[`'self'`,`'unsafe-inline'`,`https:`,`http:`],_t=[`'self'`,`blob:`,`data:`,`https:`,`http:`],H=V;[...mt],[...ht],[...gt],[..._t];function U(e){H=Array.isArray(e)?e.map(e=>typeof e==`string`?e.trim():``).filter(Boolean).join(` `):typeof e==`string`&&e.trim()?e.trim():V}function W(e){if(!e||typeof e!=`object`)return;let t=e.allowedCustomElements||(typeof e.customElements==`object`&&!Array.isArray(e.customElements)?e.customElements?.allowedElements:void 0);t!==void 0&&z(t);let n=e.allowedCustomElementDomains||(typeof e.customElements==`object`&&!Array.isArray(e.customElements)?e.customElements?.allowedDomains:void 0);n!==void 0&&B(n),e.security?.iframeSandbox===void 0?(e.security?.allowSameOrigin===!0||e.security?.allowIframeSameOrigin===!0)&&(H.includes(`allow-same-origin`)||(H=`${H} allow-same-origin`.trim())):U(e.security.iframeSandbox),e.security?.workerSrc!==void 0&&R(e.security.workerSrc),e.security?.connectSrc!==void 0&&R(e.security.connectSrc),e.security?.scriptSrc!==void 0&&R(e.security.scriptSrc),e.security?.styleSrc!==void 0&&R(e.security.styleSrc),e.security?.imgSrc!==void 0&&R(e.security.imgSrc)}function vt(){if(typeof document>`u`)return;let e=document.getElementById(`shadow-claw-site-config`);if(e&&e.textContent)try{W(JSON.parse(e.textContent))}catch{}}let G=null,K=!1;function yt(){vt(),!(K||typeof customElements>`u`||typeof customElements.define!=`function`)&&(G=customElements.define.bind(customElements),customElements.define=function(e,t,n){if(!pt((e||``).toLowerCase().trim())){let t=`[Security] Registration blocked: <${e}> is not an approved custom element.`;throw console.error(t),Error(t)}return G(e,t,n)},K=!0)}function q(e=typeof document<`u`?document.documentElement:null){if(typeof MutationObserver>`u`||!e)return null;if(typeof e.querySelectorAll==`function`)try{e.querySelectorAll(`*`).forEach(e=>{let t=e.tagName?e.tagName.toLowerCase():``;t.includes(`-`)&&!pt(t)&&(console.warn(`[Security] Removing existing unapproved custom element: <${t}>`),e.remove())})}catch{}let t=new MutationObserver(e=>{for(let t of e)t.addedNodes.forEach(e=>{if(e.nodeType===1){let t=e,n=t.tagName?t.tagName.toLowerCase():``;n.includes(`-`)&&!pt(n)&&(console.warn(`[Security] Removing unapproved custom element: <${n}>`),t.remove())}})});return t.observe(e,{childList:!0,subtree:!0}),t}function bt(e){let t=p();return t?`shadowclaw:${t}:${e}`:e}function xt(e){if(typeof localStorage>`u`)return null;let t=bt(e);try{let n=localStorage.getItem(t);if(n!==null)return n;if(t===e)return null;let r=localStorage.getItem(e);if(r!==null)return localStorage.setItem(t,r),r}catch(e){console.warn(`Unable to read from localStorage:`,e)}return null}function St(){let e=sessionStorage.getItem(`shadow-claw-github-pages-404-redirect`);e&&sessionStorage.removeItem(`shadow-claw-github-pages-404-redirect`),e&&e!==location.pathname+location.search+location.hash&&history.replaceState(null,``,e)}function Ct(){t(),o(),yt(),q();let e=document.documentElement;e.classList.add(`sc-js-enabled`,`sc-js-boot-pending`);let n=!1;try{let e=xt(`shadow-claw-override-prerender-skeleton`);n=e===null||e===`true`}catch{n=!0}n&&e.classList.add(`sc-prerender-override`);let r=()=>{let e=document.querySelector(`shadow-claw`);return!e||e.getAttribute(`data-prerender-no-seed`)!==`true`&&!n?!1:(n&&(e.setAttribute(`data-prerender-no-seed`,`true`),e.setAttribute(`data-js-boot-pending`,`true`),e.setAttribute(`data-hydration-pending`,`true`)),!0)};if(!r()){let e=new MutationObserver(()=>{r()&&e.disconnect()});e.observe(document.documentElement,{childList:!0,subtree:!0})}let i=xt(`shadow-claw-theme`)||`system`,a=window.matchMedia&&window.matchMedia(`(prefers-color-scheme: dark)`).matches,s=i===`system`?a?`dark`:`light`:i;document.documentElement.classList.add(`${s}-mode`)}return St(),Ct(),window.addEventListener(`load`,e=>{let t=e.target;if(t&&t.tagName===`LINK`){let e=t;e.rel===`stylesheet`&&e.media===`print`&&e.href.includes(`Material+Symbols`)&&(e.media=`all`)}},!0),e.handleGithubPages404Redirects=St,e.initializeThemeAndBootState=Ct,e})({});</script><link rel="manifest" href="manifest.json"><link href="assets/icons/favicon.ico" rel="icon" type="image/x-icon" /><link href="assets/icons/180.png" rel="apple-touch-icon" /><style>:root{--shadow-claw-font-mono:"Fira Code","Courier New",monospace;--shadow-claw-font-sans:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;--shadow-claw-accent-hover:#1e293b;--shadow-claw-accent-primary:#334155;--shadow-claw-bg-primary-reverse:#0f172a;--shadow-claw-bg-primary:#f8fafc;--shadow-claw-bg-secondary:#f1f5f9;--shadow-claw-bg-tertiary:#e2e8f0;--shadow-claw-border-color:#e2e8f0;--shadow-claw-error-color:#ba1a1a;--shadow-claw-important-color:#334155;--shadow-claw-link-hover:#334155;--shadow-claw-link:#1e40af;--shadow-claw-on-error:#fff;--shadow-claw-on-primary:#fff;--shadow-claw-success-color:#059669;--shadow-claw-surface-tint:#334155;--shadow-claw-text-primary:#0f172a;--shadow-claw-text-secondary:#475569;--shadow-claw-text-tertiary:#64748b;--shadow-claw-warning-color:#d97706;--shadow-claw-font-size-lg:1.5rem;--shadow-claw-font-size-md:1.125rem;--shadow-claw-font-size-sm:0.875rem;--shadow-claw-radius-s:0.5rem;--shadow-claw-radius-m:0.75rem;--shadow-claw-radius-l:1.25rem;--shadow-claw-radius-pill:62.5rem;--shadow-claw-shadow-sm:0 0.0625rem 0.1875rem rgba(0,0,0,.1),0 0.0625rem 0.125rem rgba(0,0,0,.06);--shadow-claw-shadow-md:0 0.25rem 0.375rem -0.0625rem rgba(0,0,0,.1),0 0.125rem 0.25rem -0.0625rem rgba(0,0,0,.06);--shadow-claw-shadow-lg:0 0.625rem 0.9375rem -0.1875rem rgba(0,0,0,.1),0 0.25rem 0.375rem -0.125rem rgba(0,0,0,.05);--shadow-claw-shadow-sm:0 0.625rem 0.75rem 0 rgba(0,0,0,.05);--shadow-claw-shadow-md:0 0.625rem 1.875rem 0 rgba(0,0,0,.08);--shadow-claw-shadow-lg:0 0.625rem 1.875rem 0 rgba(0,0,0,.1);--shadow-claw-ease-in:cubic-bezier(0.32,0,0.67,0);--shadow-claw-ease-out:cubic-bezier(0.33,1,0.68,1);--shadow-claw-ease-in-out:cubic-bezier(0.65,0,0.35,1);--shadow-claw-duration-min:150ms;--shadow-claw-duration-regular:300ms;--shadow-claw-logo-size:1.5rem;--shadow-claw-header-title-font-size:1.5rem;--shadow-claw-icon-accent-dark:#8e1d13;--shadow-claw-icon-bg:transparent;--shadow-claw-icon-body-segment:#c0392b;--shadow-claw-icon-body-shine:#e74c3c;--shadow-claw-icon-body:#922b21;--shadow-claw-icon-claw-inner:#922b21;--shadow-claw-icon-claw-main:#c0392b;--shadow-claw-icon-eye-shine:#fff;--shadow-claw-icon-eye:#171d1e;--shadow-claw-hljs-background-color:#282c34;display:contents}@media (prefers-color-scheme:dark){:root{--shadow-claw-accent-hover:#cbd5e1;--shadow-claw-accent-primary:#94a3b8;--shadow-claw-on-primary:#0f172a;--shadow-claw-surface-tint:#94a3b8;--shadow-claw-bg-primary:#0f172a;--shadow-claw-bg-primary-reverse:#f8fafc;--shadow-claw-bg-secondary:#1e293b;--shadow-claw-bg-tertiary:#334155;--shadow-claw-border-color:#334155;--shadow-claw-error-color:#ffb4ab;--shadow-claw-link:#94a3b8;--shadow-claw-link-hover:#94a3b8;--shadow-claw-on-error:#690005;--shadow-claw-success-color:#34d399;--shadow-claw-text-primary:#f1f5f9;--shadow-claw-text-secondary:#cbd5e1;--shadow-claw-text-tertiary:#94a3b8;--shadow-claw-shadow-sm:0 0.0625rem 0.1875rem rgba(0,0,0,.3);--shadow-claw-shadow-md:0 0.25rem 0.375rem -0.0625rem rgba(0,0,0,.4);--shadow-claw-shadow-lg:0 0.625rem 0.9375rem -0.1875rem rgba(0,0,0,.5);--shadow-claw-icon-accent-dark:#ff6b6b;--shadow-claw-icon-body-segment:#ff5252;--shadow-claw-icon-body-shine:hsla(0,0%,100%,.3);--shadow-claw-icon-body:#ff1744;--shadow-claw-icon-claw-inner:#ff1744;--shadow-claw-icon-claw-main:#ff5252;--shadow-claw-icon-eye-shine:#171d1e;--shadow-claw-icon-eye:#dee3e5}}.light-mode{--shadow-claw-accent-hover:#1e293b;--shadow-claw-accent-primary:#334155;--shadow-claw-on-primary:#fff;--shadow-claw-surface-tint:#334155;--shadow-claw-bg-primary:#f8fafc;--shadow-claw-bg-primary-reverse:#0f172a;--shadow-claw-bg-secondary:#f1f5f9;--shadow-claw-bg-tertiary:#e2e8f0;--shadow-claw-border-color:#e2e8f0;--shadow-claw-error-color:#ba1a1a;--shadow-claw-link:#334155;--shadow-claw-link-hover:#1e293b;--shadow-claw-on-error:#fff;--shadow-claw-success-color:#059669;--shadow-claw-warning-color:#d97706;--shadow-claw-text-primary:#0f172a;--shadow-claw-text-secondary:#475569;--shadow-claw-text-tertiary:#64748b}.dark-mode{--shadow-claw-accent-hover:#cbd5e1;--shadow-claw-accent-primary:#94a3b8;--shadow-claw-on-primary:#0f172a;--shadow-claw-surface-tint:#94a3b8;--shadow-claw-bg-primary:#0f172a;--shadow-claw-bg-primary-reverse:#f8fafc;--shadow-claw-bg-secondary:#1e293b;--shadow-claw-bg-tertiary:#334155;--shadow-claw-border-color:#334155;--shadow-claw-error-color:#ffb4ab;--shadow-claw-link:#94a3b8;--shadow-claw-link-hover:#cbd5e1;--shadow-claw-on-error:#690005;--shadow-claw-success-color:#34d399;--shadow-claw-text-primary:#f1f5f9;--shadow-claw-text-secondary:#cbd5e1;--shadow-claw-text-tertiary:#94a3b8;--shadow-claw-shadow-sm:0 0.0625rem 0.1875rem rgba(0,0,0,.3);--shadow-claw-shadow-md:0 0.25rem 0.375rem -0.0625rem rgba(0,0,0,.4);--shadow-claw-shadow-lg:0 0.625rem 0.9375rem -0.1875rem rgba(0,0,0,.5);--shadow-claw-icon-accent-dark:#ff6b6b;--shadow-claw-icon-bg:transparent;--shadow-claw-icon-body-segment:#ff5252;--shadow-claw-icon-body-shine:hsla(0,0%,100%,.3);--shadow-claw-icon-body:#ff1744;--shadow-claw-icon-claw-inner:#ff1744;--shadow-claw-icon-claw-main:#ff5252;--shadow-claw-icon-eye-shine:#171d1e;--shadow-claw-icon-eye:#dee3e5}*,:after,:before{font-family:var(--shadow-claw-font-sans)}*{box-sizing:border-box;margin:0;padding:0;scrollbar-color:var(--shadow-claw-border-color) transparent;scrollbar-width:thin}::-webkit-scrollbar{height:.5rem;width:.5rem}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--shadow-claw-border-color);border-radius:.25rem}::-webkit-scrollbar-thumb:hover{background:var(--shadow-claw-text-tertiary)}body,html{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--shadow-claw-bg-primary);color:var(--shadow-claw-text-primary);display:flex;flex-direction:column;width:100%}@media (max-width:48rem){input,select,textarea{font-size:16px}}html.sc-prerender-override shadow-claw{visibility:hidden}shadow-claw:not(:defined){background:radial-gradient(circle at 20% 15%,rgba(56,189,248,.08),transparent 40%),radial-gradient(circle at 85% 90%,rgba(51,65,85,.2),transparent 45%),var(--shadow-claw-bg-primary);color:var(--shadow-claw-text-primary);display:grid}.header-title-link,.header-title-link:hover{color:var(--shadow-claw-text-primary);display:flex;text-decoration:none}.header-title-logo{display:none;height:var(--shadow-claw-logo-size,1.5rem);width:var(--shadow-claw-logo-size,1.5rem)}.header-title{align-items:center;display:none;font-size:var(--shadow-claw-header-title-font-size,1.5rem);font-weight:700;line-height:1;margin:0 0 0 .5rem}@media (min-width:30rem){.header-title,.header-title-logo{display:flex}}.header-actions-logo-link{align-items:center;color:inherit;display:flex;flex-direction:row;height:2.5rem;justify-content:center;width:2.5rem}.header-actions-logo-link svg{height:1.5rem;width:1.5rem}.app-dialog,dialog{background-color:var(--shadow-claw-bg-secondary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-l,1.25rem);box-shadow:var(--shadow-claw-shadow-lg);color:var(--shadow-claw-text-primary);padding:0}.app-dialog::backdrop,dialog::backdrop{backdrop-filter:blur(2px);background:color-mix(in srgb,#000 65%,transparent)}</style><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined&display=swap" media="print"><noscript> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined&display=swap"> </noscript> <script id="shadow-claw-static-manifest" type="application/json">{"pages":[{"displayPath":"~\u002fdocs\u002fskill-creator.md","content":"---\ntitle: \"Agent Skills & Skill Creator\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"skill-creator\"\n---\n\n## Agent Skills & Skill Creator\n\nWelcome to the ShadowClaw Agent Skills guide! Skills are workspace-local instruction packages and automated tool pipelines that give your AI assistant specialized capabilities.\n\nWhether you want to teach the assistant a specialized coding workflow, build silent background utility tools, or trigger automated tasks with slash commands, **Agent Skills** make it simple and declarative.\n\n---\n\n## 🌟 Quick Start: What is an Agent Skill?\n\nAn Agent Skill is a directory containing a `SKILL.md` file located inside your workspace's `.agents\u002fskills\u002f` folder:\n\n```text\n.agents\u002fskills\u002f\n└── main\u002f\n ├── skill-creator\u002f\n │ ├── SKILL.md\n │ └── references\u002f\n │ ├── frontmatter-spec.md\n │ ├── declarative-pipelines.md\n │ └── declarative-tools.md\n └── toast-random-number\u002f\n └── SKILL.md\n```\n\nEach skill includes:\n\n1. **`SKILL.md`**: Standard frontmatter metadata (name, description, slash command triggers) and step-by-step instructions.\n2. **`references\u002f` Directory**: Detailed reference guides and technical documentation co-located with the skill.\n3. **Declarative Pipelines**: Optional deterministic tool workflows (`execution.type: \"tools\"`) that execute instantly without calling LLM prompts.\n\n---\n\n## 🚀 Creating Skills with `\u002fskill-creator`\n\nShadowClaw comes with an official bundled **Skill Creator**. You can trigger it anytime by typing `\u002fskill-creator` in the chat thread or asking the AI assistant to create a skill for you.\n\n### Recommended Skill Authoring Workflow\n\n1. **Define the Scope & Trigger**: Decide on a clear skill name (e.g. `toast-random-number`) and write a concise description of what it does.\n2. **Set Up Workspace Folders**:\n - Skill files belong in `.agents\u002fskills\u002fmain\u002f\u003cskill-name\u003e\u002fSKILL.md`.\n - Custom declarative tools belong in `.agents\u002ftools\u002fmain\u002f\u003ctool-name\u003e.json`.\n3. **Write `SKILL.md`**: Configure standard frontmatter attributes and instructions.\n4. **Add Technical References**: Store detailed reference materials under the skill's `references\u002f` directory.\n\n---\n\n## 📚 Skill Reference Documentation\n\nFor deep technical details, explore the co-located reference guides bundled with the official `skill-creator` skill:\n\n- 📋 **[Frontmatter Specification](file:\u002f\u002f\u002f.agents\u002fskills\u002fmain\u002fskill-creator\u002freferences\u002ffrontmatter-spec.md)** \n Complete schema rules for `name`, `description`, `user-invocable`, `disable-model-invocation`, `argument-hint`, and `metadata.allowed-tools`.\n\n- ⚡ **[Declarative Execution Pipelines](file:\u002f\u002f\u002f.agents\u002fskills\u002fmain\u002fskill-creator\u002freferences\u002fdeclarative-pipelines.md)** \n How to write zero-LLM tool chains using `execution.type: \"tools\"`, `$pipe` output piping, `suppressToast`, and `suppressOutput`.\n\n- 🛠️ **[Declarative Tools Reference](file:\u002f\u002f\u002f.agents\u002fskills\u002fmain\u002fskill-creator\u002freferences\u002fdeclarative-tools.md)** \n How to author custom JSON tool definitions in `.agents\u002ftools\u002f` with sandboxed JavaScript evaluation and WebMCP model context integration.\n\n---\n\n## 💡 Example: A Two-Step Declarative Skill\n\nHere is a complete, real-world example of a declarative skill that generates a random number and displays it in a toast notification silently:\n\n```yaml\n---\nname: toast-random-number\ndescription: Generate a random integer from 1 to 1000000 and show it in a ShadowClaw toast notification.\nuser-invocable: true\nmetadata:\n allowed-tools: javascript show_toast generate_random_number\n execution:\n type: tools\n suppressToast: true\n suppressOutput: true\n tools:\n - name: javascript\n input:\n code: Math.floor(Math.random() * 1000000) + 1\n - name: show_toast\n input:\n title: Random Number\n message:\n $pipe: prev\n---\n# Toast Random Number\n\nThis skill generates a random integer and displays it instantly in a toast notification.\n```\n\nWhen you type `\u002ftoast-random-number`, ShadowClaw executes the two steps directly without delay!\n"},{"displayPath":"index.html","content":"---\ntitle: \"ShadowClaw Pages\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"shadow-claw-pages\"\n---\n\n\u003carticle\u003e\n \u003ch2\u003eWelcome to ShadowClaw Pages\u003c\u002fh2\u003e\n \u003cp\u003eThis is the default static page for your workspace.\u003c\u002fp\u003e\n \u003ch2 id=\"getting-started-with-shadowclaw\"\u003eGetting started with ShadowClaw\u003c\u002fh2\u003e\n \u003ch3 id=\"what-is-memorymd\"\u003eWhat is MEMORY.md?\u003c\u002fh3\u003e\n \u003cul\u003e\n \u003cli\u003e\n \"\u003ca href=\"\u002ffiles\u002fmain\u002fMEMORY.md\"\u003eMEMORY.md\u003c\u002fa\u003e\" is a per conversation, per\n invocation, auto-loaded, persistent agent memory file.\n \u003c\u002fli\u003e\n \u003cli\u003e\n It is designed to be a helpful scratchpad for agents to store important\n information, notes, and context about the conversation.\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003ch3 id=\"how-to-use-files\"\u003eHow to use Files\u003c\u002fh3\u003e\n \u003cul\u003e\n \u003cli\u003eOpen \"\u003ca href=\"\u002ffiles\u002fmain\"\u003eFiles\u003c\u002fa\u003e\" to browse your workspace.\u003c\u002fli\u003e\n \u003cli\u003e\n Edit and preview files with the file viewer:\n \u003cul\u003e\n \u003cli\u003e\u003ca href=\"\u002ffiles\u002fmain\u002findex.html\"\u003eindex.html\u003c\u002fa\u003e\u003c\u002fli\u003e\n \u003cli\u003e\n \u003ca href=\"\u002ffiles\u002fmain\u002f~\u002fdocs\u002fexample\u002farticle.html\"\u003earticle.html\u003c\u002fa\u003e\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003ch3 id=\"how-to-use-pages\"\u003eHow to use Pages\u003c\u002fh3\u003e\n \u003cul\u003e\n \u003cli\u003eUse Set as Page on any markdown or HTML file to add it to Pages.\u003c\u002fli\u003e\n \u003cli\u003eRemove a page anytime from the \"\u003ca href=\"\u002fpages\"\u003ePages\u003c\u002fa\u003e\" view.\u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003ch3 id=\"how-to-use-chat\"\u003eHow to use Chat\u003c\u002fh3\u003e\n \u003cul\u003e\n \u003cli\u003e\n Open \"\u003ca href=\"\u002fsettings\"\u003eSettings\u003c\u002fa\u003e\" to configure your agent's system\n prompt, tools, and more.\n \u003c\u002fli\u003e\n \u003cli\u003e\n Open \"\u003ca href=\"\u002fchat\u002fmain\"\u003eChat\u003c\u002fa\u003e\" to start a conversation with your\n agent.\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003ch2 id=\"further-information\"\u003eFurther information\u003c\u002fh2\u003e\n \u003cul\u003e\n \u003cli\u003e\n \u003ca href=\"https:\u002f\u002fgithub.com\u002fxt-ml\u002fshadow-claw#-shadowclaw\"\n \u003eShadowClaw Project\u003c\u002fa\n \u003e\n \u003c\u002fli\u003e\n \u003cli\u003e\u003ca href=\"https:\u002f\u002fdeepwiki.com\u002fxt-ml\u002fshadow-claw\"\u003eDeep Wiki\u003c\u002fa\u003e\u003c\u002fli\u003e\n \u003c\u002ful\u003e\n\u003c\u002farticle\u003e\n"},{"displayPath":"~\u002fdocs\u002fpublishing-to-github-pages.md","content":"---\ntitle: \"Publishing to GitHub Pages\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"publishing-to-github-pages\"\n---\n\n## Publishing to GitHub Pages\n\nShadowClaw can drive a fully automated static-site publishing pipeline directly from the browser, with the only server-side requirement being a GitHub Actions workflow that runs the Node.js build.\n\n---\n\n## Deployment strategies\n\n### Strategy A — Full fork\n\nClone the entire ShadowClaw repository, add your pages to `pages\u002fmain\u002f`, push to a new repo you own, and let CI build and deploy it.\n\n### Strategy B — Pages-only repo (Git clone & inject in CI)\n\nYour repo contains your content, an optional root-level `shadow-claw.config.json` (or `site-config.json`), and a GitHub Actions workflow. Content lives under `pages\u002f`; the workflow checks out ShadowClaw as a build toolchain in CI and builds into `dist\u002fpublic`.\n\n### Strategy C — NPM Package & CLI (`npx shadow-claw`)\n\nRun or deploy using the `shadow-claw` npm package directly:\n\n- Locally: `npx shadow-claw dev` (or `shadow-claw run`) to preview with dev server.\n- In CI: `npx shadow-claw build --prod` builds `dist\u002fpublic` without needing to clone ShadowClaw or copy files.\n- In `package.json`: add `\"shadow-claw\": \"^1.22.4\"` as a devDependency and run `npm run build`.\n\n**Strategy B and Strategy C are both fully supported for content-only repositories and knowledge hubs.**\n\n---\n\n## Strategy B — Step-by-step\n\n### 1. Create a new GitHub repository\n\nCreate an empty repo at `github.com\u002f\u003cyou\u003e\u002f\u003cyour-site\u003e`. Enable **Settings → Pages → Source: GitHub Actions**.\n\n### 2. Add the workflow\n\nCreate `.github\u002fworkflows\u002fdeploy-pages.yml`:\n\n```yaml\nname: Build and Deploy via ShadowClaw\n\non:\n push:\n branches: [main]\n workflow_dispatch:\n inputs:\n shadowclaw_version:\n description: \"ShadowClaw npm version (e.g. latest, 1.23.3)\"\n required: false\n default: \"latest\"\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\nconcurrency:\n group: pages\n cancel-in-progress: true\n\njobs:\n build-and-deploy:\n environment:\n name: github-pages\n url: ${{ steps.deployment.outputs.page_url }}\n runs-on: ubuntu-latest\n steps:\n - name: Checkout repository\n uses: actions\u002fcheckout@v6\n\n - name: Setup Node.js\n uses: actions\u002fsetup-node@v6\n with:\n node-version: \"24\"\n\n - name: Build static site via ShadowClaw CLI\n env:\n PAGES_ORIGIN: \"https:\u002f\u002f${{ github.repository_owner }}.github.io\u002f${{ github.event.repository.name }}\u002f\"\n PAGES_BASE_PATH: \"\u002f${{ github.event.repository.name }}\u002f\"\n run: |\n VERSION=\"${{ github.event.inputs.shadowclaw_version || 'latest' }}\"\n npx --yes \"shadow-claw@$VERSION\" build --prod\n\n - name: Upload Pages artifact\n uses: actions\u002fupload-pages-artifact@v3\n with:\n path: dist\u002fpublic\n\n - name: Deploy to GitHub Pages\n id: deployment\n uses: actions\u002fdeploy-pages@v4\n```\n\n### Version Pinning\n\nShadowClaw builds via `npx --yes shadow-claw@latest build --prod`. To pin to a specific npm release (e.g. `1.23.3`), specify the version in `.github\u002fworkflows\u002fdeploy-pages.yml` or supply `shadowclaw_version` when triggering the GitHub Actions workflow manually.\n\nFor a **custom apex domain** (e.g. `example.com`), override:\n\n```yaml\nPAGES_ORIGIN: \"https:\u002f\u002fexample.com\u002f\"\nPAGES_BASE_PATH: \"\u002f\"\n```\n\n### 3. Add your content\n\n```text\npages\u002f\n main\u002f\n index.html ← home page\n ~\u002fcontent\u002f\n about.md ← any other pages\n routes.json ← pretty-path config (optional)\n\nshadow-claw.config.json ← branding, default tool settings, and build configuration (optional)\n```\n\nSite configurations can also specify tool defaults under `settings`:\n\n```json\n{\n \"settings\": {\n \"defaultToolsProfile\": \"__builtin_default\",\n \"enabledTools\": [\"javascript\", \"read_file\", \"write_file\"]\n }\n}\n```\n\nThe `pages\u002f` directory is optional. If it is absent, the build succeeds and\nShadowClaw publishes its built-in `index.html` and `MEMORY.md` Pages content.\nPretty paths are skipped unless a `routes.json` file is present.\n\nMinimal `pages\u002froutes.json`:\n\n```json\n{\n \"routes\": {\n \"\u002fpages\u002fmain\u002findex.html\": { \"prettyPath\": \"\u002fmain\" },\n \"\u002fpages\u002fmain\u002f~\u002fcontent\u002fabout.md\": { \"prettyPath\": \"\u002fmain\u002fabout\" },\n \"\u002fpages\u002fmain\u002fMEMORY.md\": { \"prettyPath\": \"\u002fmain\u002fmemory\" }\n }\n}\n```\n\n\u003e **Reserved path prefixes** — the following first-path-segments are owned by\n\u003e ShadowClaw's own router and **must not** be used as pretty path prefixes:\n\u003e `\u002f`, `\u002fchat`, `\u002ffiles`, `\u002ftasks`, `\u002fpages`, `\u002fsettings`, `\u002ftools`, `\u002fchannels`.\n\u003e `\u002f` (root) is also reserved as the default pinned page and is unreachable as\n\u003e a pretty path. Use a safe namespace like `\u002fmain\u002f`, `\u002farticles\u002f`, `\u002fdocs\u002f`, or\n\u003e any custom prefix that doesn't collide with the list above.\n\n#### Default Pinned Page (`\u002f`)\n\nWhen visitors navigate to the root URL (`\u002f`) of your published site, ShadowClaw displays the **default pinned page**.\n\n**How ShadowClaw selects the default page for `\u002f`:**\n\n1. Both the static site prerenderer (`prerender-dsd-shell`) and runtime page store (`orchestratorStore`) gather all page files in `pages\u002fmain\u002f`. If `pages\u002fmain\u002f` is absent, both use the built-in default `index.html` and `MEMORY.md` pages.\n2. `MEMORY.md` is always moved to the bottom of the list.\n3. All remaining pages are sorted by `pages.sortOrder` from `shadow-claw.config.json` (or `site-config.json`) (`\"desc\"` by default, natural numeric, or `\"asc\"`).\n4. The first file in this sorted list (`pages[0]`) becomes the default page rendered at `\u002f`.\n\n**How to ensure your intended home page is rendered at `\u002f`:**\nName your landing page file so it sorts first in reverse-alphabetical order relative to other files in `pages\u002fmain\u002f`:\n\n- `index.md` or `index.html` will sort ahead of `about.md`, `contact.md`, or `faq.md`.\n- If you have files starting with letters after `i` (e.g. `welcome.md`), `welcome.md` will sort ahead of `index.md`. Ensure your preferred landing page filename sorts highest in reverse-alphabetical order.\n\n### 4. Push — CI does the rest\n\nEvery push to `main` triggers a build (~3–5 min on a cold runner, faster with the npm cache warm) and deploys to `https:\u002f\u002f\u003cyou\u003e.github.io\u002f\u003cyour-site\u003e\u002f`.\n\n---\n\n## In-browser automation (no LLM, no server)\n\nShadowClaw can publish to your content repo entirely from the browser using a `type: \"tools\"` task chain. The chain is deterministic — it makes **zero LLM calls**.\n\n### Prerequisites\n\n- Clone your content repo into the workspace: ask the agent to `git_clone https:\u002f\u002fgithub.com\u002f\u003cyou\u003e\u002f\u003cyour-site\u003e`, or do it manually.\n- Configure a GitHub Personal Access Token in **Settings → Git → PAT** (needs `repo` scope for private repos, `public_repo` for public ones).\n\n### Minimal publish chain\n\n```json\n{\n \"type\": \"tools\",\n \"tools\": [\n {\n \"name\": \"write_file\",\n \"input\": {\n \"path\": \"repos\u002fyour-site\u002fpages\u002fmain\u002fpost.md\",\n \"content\": \"---\\ntitle: My Post\\n---\\n\\n# Hello World\\n\\nContent here.\"\n }\n },\n {\n \"name\": \"git_add\",\n \"input\": {\n \"repo\": \"your-site\",\n \"files\": [\"pages\u002fmain\u002fpost.md\"]\n }\n },\n {\n \"name\": \"git_commit\",\n \"input\": {\n \"repo\": \"your-site\",\n \"message\": \"publish: new post\"\n }\n },\n {\n \"name\": \"git_push\",\n \"input\": {\n \"repo\": \"your-site\"\n }\n }\n ]\n}\n```\n\n### Fetch-transform-publish chain (fully automated data pipeline)\n\nThis chain fetches an external data source, transforms it to markdown via the JavaScript sandbox, writes it as a page, and pushes — no human in the loop:\n\n```json\n{\n \"type\": \"tools\",\n \"tools\": [\n {\n \"name\": \"fetch_url\",\n \"input\": {\n \"url\": \"https:\u002f\u002fapi.github.com\u002frepos\u002fxt-ml\u002fshadow-claw\u002freleases\u002flatest\"\n }\n },\n {\n \"name\": \"javascript\",\n \"input\": {\n \"code\": \"const match = $PIPE_DATA.match(\u002f--- BEGIN EXTERNAL CONTENT[\\\\s\\\\S]*?---\\\\n([\\\\s\\\\S]*?)\\\\n--- END EXTERNAL CONTENT ---\u002f); const raw = match ? match[1] : $PIPE_DATA; const rel = JSON.parse(raw); const date = rel.published_at?.slice(0, 10) ?? 'unknown'; return `---\\\\ntitle: ShadowClaw ${rel.tag_name}\\\\ndate: ${date}\\\\n---\\\\n\\\\n# ${rel.name}\\\\n\\\\nPublished: ${date}\\\\n\\\\n${rel.body ?? ''}`;\",\n \"data\": { \"$pipe\": \"prev\" }\n }\n },\n {\n \"name\": \"write_file\",\n \"input\": {\n \"path\": \"repos\u002fyour-site\u002fpages\u002fmain\u002frelease-notes.md\",\n \"content\": { \"$pipe\": \"prev\" }\n }\n },\n {\n \"name\": \"git_add\",\n \"input\": {\n \"repo\": \"your-site\",\n \"files\": [\"pages\u002fmain\u002frelease-notes.md\"]\n }\n },\n {\n \"name\": \"git_commit\",\n \"input\": {\n \"repo\": \"your-site\",\n \"message\": \"shadow-claw[bot]: sync release notes\"\n }\n },\n {\n \"name\": \"git_push\",\n \"input\": {\n \"repo\": \"your-site\"\n }\n }\n ]\n}\n```\n\n---\n\n## Strategy C — NPM Package & CLI Workflow\n\nIf you prefer building directly with `npx shadowclaw` without cloning the ShadowClaw repository in CI, use this minimal workflow:\n\n```yaml\nname: Build and Deploy via ShadowClaw CLI\n\non:\n push:\n branches: [main]\n workflow_dispatch:\n\npermissions:\n contents: read\n pages: write\n id-token: write\n\nconcurrency:\n group: pages\n cancel-in-progress: true\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout content repo\n uses: actions\u002fcheckout@v4\n\n - uses: actions\u002fsetup-node@v4\n with:\n node-version: \"24\"\n\n - name: Build production bundle\n env:\n NODE_ENV: production\n PAGES_ORIGIN: \"https:\u002f\u002f${{ github.repository_owner }}.github.io\u002f${{ github.event.repository.name }}\u002f\"\n PAGES_BASE_PATH: \"\u002f${{ github.event.repository.name }}\u002f\"\n run: npx shadow-claw build --prod\n\n - name: Upload Pages artifact\n uses: actions\u002fupload-pages-artifact@v3\n with:\n path: dist\u002fpublic\n\n deploy:\n needs: build\n runs-on: ubuntu-latest\n environment:\n name: github-pages\n url: ${{ steps.deployment.outputs.page_url }}\n steps:\n - name: Deploy to GitHub Pages\n id: deployment\n uses: actions\u002fdeploy-pages@v4\n```\n\n\u003e **Tip:** Wrap this in a scheduled task (Tasks sidebar → New Task → type `tools`, set a cron interval) to run the pipeline automatically, e.g. every 24 hours. No LLM calls are made at execution time.\n\n---\n\n## Template repository\n\nA ready-to-fork starter template is available in the [`shadow-claw-template`](https:\u002f\u002fgithub.com\u002fxt-ml\u002fshadow-claw-template) repository. It contains the workflow, sample `pages\u002fmain\u002findex.html`, `pages\u002fmain\u002f~\u002fcontent\u002fabout.md`, root-level `shadow-claw.config.json`, and `pages\u002froutes.json`.\n"},{"displayPath":"~\u002fdocs\u002fexample\u002farticle.html","content":"---\ntitle: \"Article\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"article\"\n---\n\n\u003carticle\u003e\n \u003ch2\u003eBig Buck Bunny\u003c\u002fh2\u003e\n\n \u003cvideo controls style=\"border-radius: 0.5rem; width: 100%\"\u003e\n \u003csource\n src=\"https:\u002f\u002fxt-ml.github.io\u002fassets\u002fmedia\u002fBigBuckBunny\u002fBigBuckBunny_320x180.mp4\"\n type=\"video\u002fmp4\"\n \u002f\u003e\n \u003c\u002fvideo\u003e\n \u003csection\u003e\n \u003ch2\u003eLicensing\u003c\u002fh2\u003e\n \u003cul\u003e\n \u003cli\u003e\n \u003ccode\u003eBig Buck Bunny\u003c\u002fcode\u003e is licensed under the\n \u003ca href=\"https:\u002f\u002fblender.org\"\n \u003eCreative Commons Attribution 3.0 License\u003c\u002fa\n \u003e.\n \u003cul\u003e\n \u003cli\u003e\n Attribution: Blender Foundation \u002f\n \u003ca href=\"https:\u002f\u002fwww.blender.org\u002f\"\u003ewww.blender.org\u003c\u002fa\u003e\n \u003c\u002fli\u003e\n \u003cli\u003e\n Copyright: (c) copyright 2008, Blender Foundation \u002f\n \u003ca href=\"https:\u002f\u002fwww.bigbuckbunny.org\u002f\"\u003ewww.bigbuckbunny.org\u003c\u002fa\u003e\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003c\u002fli\u003e\n \u003c\u002ful\u003e\n \u003c\u002fsection\u003e\n\u003c\u002farticle\u003e\n"},{"displayPath":"MEMORY.md","content":"---\ntitle: \"Agent Memory\"\ncreated: \"1970-01-01T00:00:00Z\"\nupdated: \"1970-01-01T00:00:00Z\"\nslug: \"agent-memory\"\n---\n\n## Memory\n\n### Workspace Layout & Skills Conventions\n\n- **Skills**: `.agents\u002fskills\u002fmain\u002f\u003cskill-name\u003e\u002fSKILL.md`\n- **Declarative Tools**: `.agents\u002ftools\u002fmain\u002f\u003ctool-name\u003e.json`\n- **Skill Format**: Markdown file with YAML frontmatter AND a Markdown body (frontmatter is metadata only; always include a `# \u003cSkill Title\u003e` heading and human-readable description in the Markdown body so it renders in document previews):\n\n ```yaml\n ---\n name: \u003cskill-name\u003e\n description: \u003cclear summary for model and slash command\u003e\n user-invocable: true\n metadata:\n allowed-tools: \u003ctool1\u003e \u003ctool2\u003e\n execution:\n type: tools\n tools:\n - name: \u003ctool1\u003e\n input: { ... }\n - name: \u003ctool2\u003e\n input: { \"$pipe\": \"prev\" }\n ---\n # \u003cSkill Title\u003e\n\n \u003cOverview and description of what the skill does, parameters, and usage instructions.\u003e\n ```\n\n- **Declarative Tool Format**: JSON with `\"name\"`, `\"description\"`, `\"executor\": \"javascript\"`, `\"inputSchema\"`, and `\"code\"`.\n- **Authoring**: Use `create_directory` before writing new directories, then `write_file`.\n"}],"skills":[{"displayPath":"skill-creator\u002freferences\u002fdeclarative-pipelines.md","content":"# Declarative Execution Pipelines\n\nDeclarative execution pipelines allow skills to execute deterministic sequential tool chains directly on the worker thread without scheduling a Task or making model LLM calls.\n\n## Configuration Syntax\n\nPipelines are declared in `SKILL.md` frontmatter under `metadata.execution`:\n\n```yaml\n---\nname: sample-pipeline\ndescription: Run a deterministic tool chain.\nuser-invocable: true\nmetadata:\n allowed-tools: javascript show_toast\n execution:\n type: tools\n suppressToast: true\n suppressOutput: true\n tools:\n - name: javascript\n input:\n code: \"Math.floor(Math.random() * 100) + 1\"\n - name: show_toast\n input:\n title: \"Random Number\"\n message:\n $pipe: prev\n---\n```\n\n## Data Piping (`$pipe`)\n\nInputs in tool step configurations can reference outputs from previous steps using the `$pipe` operator:\n\n- `{ \"$pipe\": \"prev\" }` or `{ \"$pipe\": -1 }`: Resolves to the return output of the immediately preceding tool step.\n- `{ \"$pipe\": 0 }`: Resolves to the return output of step index `0` (0-indexed).\n- `{ \"$pipe\": \"javascript\" }`: Resolves to the return output of the last step that ran the `javascript` tool.\n\n## Execution Suppression\n\n- `suppressToast: true`: Suppresses step progress toasts (\"Running skill tool...\") during pipeline execution.\n- `suppressOutput: true`: Suppresses raw tool result blocks from being rendered in the chat thread.\n- Setting suppression options at the `execution` root cascades down to all steps unless explicitly overridden per tool step.\n"},{"displayPath":"skill-creator\u002freferences\u002fdeclarative-tools.md","content":"# Declarative Tools\n\nDeclarative tools allow workspace authors to define reusable custom tools using JSON definitions placed under `.agents\u002ftools\u002f\u003cgroup\u003e\u002f\u003ctool-name\u003e.json`.\n\n## Directory Structure\n\n```text\n.agents\u002ftools\u002f\n└── main\u002f\n └── generate_random_number.json\n```\n\n## Schema Format\n\n```json\n{\n \"name\": \"generate_random_number\",\n \"description\": \"Generate a random integer within a specified range.\",\n \"executor\": \"javascript\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"min\": { \"type\": \"number\", \"default\": 1 },\n \"max\": { \"type\": \"number\", \"default\": 1000000 }\n }\n },\n \"code\": \"const min = Number(inputs.min ?? 1); const max = Number(inputs.max ?? 1000000); return Math.floor(Math.random() * (max - min + 1)) + min;\"\n}\n```\n\n## Features\n\n- **Automatic Discovery**: Automatically loaded from `.agents\u002ftools\u002f` across conversation workspaces.\n- **WebMCP Integration**: Registered with the browser ModelContext API for both manual pinning and automated agent execution.\n- **Expression Evaluation**: Code expressions automatically evaluate and return results without needing explicit wrapper boilerplate.\n"},{"displayPath":"skill-creator\u002freferences\u002ffrontmatter-spec.md","content":"# Frontmatter Specification\n\nAgent skills in ShadowClaw are configured via YAML frontmatter at the top of `SKILL.md`. Frontmatter attributes adhere strictly to the standard Agent Skills specification.\n\n## Specification Schema\n\n```yaml\n---\nname: skill-name\ndescription: Clear, concise model-facing trigger description.\nuser-invocable: true\ndisable-model-invocation: false\nargument-hint: \"[arguments]\"\nmetadata:\n allowed-tools: read_file write_file javascript\ncompatibility: ShadowClaw\nlicense: MIT\n---\n```\n\n## Attribute Reference\n\n| Attribute | Type | Required | Description |\n| :------------------------- | :-------- | :------- | :-------------------------------------------------------------------------------------------------------- |\n| `name` | `string` | **Yes** | Skill identifier (1–64 lowercase alphanumeric characters and single hyphens). |\n| `description` | `string` | **Yes** | Model-facing description used for skill discovery and activation (max 1024 characters). |\n| `user-invocable` | `boolean` | No | When `true` (default), allows users to invoke the skill directly via slash commands (e.g. `\u002fskill-name`). |\n| `disable-model-invocation` | `boolean` | No | When `true`, hides the skill from model discovery so it is only triggered via slash command. |\n| `argument-hint` | `string` | No | Display placeholder in the UI search\u002fautocomplete menu when typing slash commands. |\n| `metadata` | `object` | No | Key-value dictionary for custom metadata, tool permissions (`allowed-tools`), and `execution` pipelines. |\n| `compatibility` | `string` | No | Platform compatibility requirements or version strings. |\n| `license` | `string` | No | Open-source software license string (e.g. `MIT`, `AGPL-3.0`). |\n\n## Metadata Attributes (`metadata`)\n\nCustom configuration properties and extension specifications (like declarative execution pipelines) that fall outside the standard Agent Skills frontmatter attributes should be placed inside `metadata`:\n\n```yaml\nmetadata:\n allowed-tools: javascript show_toast generate_random_number\n author: ShadowClaw Team\n version: 1.0.0\n execution:\n type: tools\n suppressToast: true\n tools:\n - name: javascript\n input:\n code: Math.floor(Math.random() * 100) + 1\n```\n"},{"displayPath":"skill-creator\u002fSKILL.md","content":"---\nname: skill-creator\ndescription: Create, edit, review, and validate ShadowClaw declarative skills and their supporting resources.\nuser-invocable: true\nmetadata:\n allowed-tools: read_file write_file javascript create_directory\n---\n\n# ShadowClaw Skill Creator\n\nUse this skill when creating, modifying, reviewing, or validating a ShadowClaw agent skill or declarative tool pipeline.\n\n## Workspace Layout Standards\n\n- **Skills**: Create each skill in its dedicated directory under `.agents\u002fskills\u002f\u003cgroup\u003e\u002f\u003cskill-name\u003e\u002fSKILL.md` (default group: `main`).\n- **Declarative Tools**: Define supporting declarative tools under `.agents\u002ftools\u002f\u003cgroup\u003e\u002f\u003ctool-name\u003e.json` (default group: `main`).\n- **Supporting Resources**: Co-locate skill-specific assets (reference documents, templates, helper scripts) inside the skill directory alongside `SKILL.md`.\n\n## Workflow\n\n1. **Establish Contract & Scope**\n - For existing skills, read `SKILL.md` and related resources before editing.\n - For new skills, define the trigger prompt, intended execution outcome, required tools, and output artifacts.\n2. **Configure Frontmatter**\n - Provide a clear, concise trigger description in `description` (1024 characters max).\n - Set `user-invocable: true` if the skill should be triggerable via slash command (e.g. `\u002fskill-name`).\n - Use `disable-model-invocation: true` for skills intended strictly for slash-command execution.\n - Place non-standard configuration (such as `allowed-tools`) within the standard `metadata` block to maintain Agent Skills specification compliance.\n3. **Structure & Draft Content**\n - Write instructions in `SKILL.md` using clear, modular procedures.\n - Place deterministic operations in `javascript` tool calls; use `read_file` and `write_file` for workspace persistence.\n - Create required target directories via `create_directory` prior to writing files.\n4. **Declarative Pipelines (`execution.type: tools`)**\n - Define sequential tool pipelines in frontmatter via `execution: { type: \"tools\", tools: [...] }`.\n - Pass outputs between steps using `{ \"$pipe\": \"prev\" }` or step\u002ftool identifiers.\n - Optionally apply `suppressToast: true` or `suppressOutput: true` at the execution root or per step to suppress notifications and output blocks.\n5. **Verify & Validate**\n - Re-read the saved `SKILL.md` and verify valid YAML frontmatter syntax.\n - Ensure the skill name uses 1–64 lowercase alphanumeric characters or hyphens and all referenced resource paths exist.\n"}]}</script>
7
7
  <script id="shadow-claw-static-routing" type="application/json">{"routes":{"\u002fpages\u002fmain\u002findex.html":{"prettyPath":"\u002fmain"},"\u002fpages\u002fmain\u002f~\u002fdocs\u002fpublishing-to-github-pages.md":{"prettyPath":"\u002fdocs\u002fpublishing"},"\u002fpages\u002fmain\u002f~\u002fdocs\u002fskill-creator.md":{"prettyPath":"\u002fdocs\u002fskill-creator"},"\u002fpages\u002fmain\u002f~\u002fdocs\u002fexample\u002farticle.html":{"prettyPath":"\u002fdocs\u002fexample\u002farticle"},"\u002fpages\u002fmain\u002fMEMORY.md":{"prettyPath":"\u002fmain\u002fmemory"}}}</script>
8
8
  </head><body> <shadow-claw data-prerender-no-seed="true">
9
9
  <template shadowrootmode="open" data-shadow-claw-dsd="true"><style data-dsd-style>*,:after,:before{box-sizing:border-box}.hidden,[hidden]{display:none!important}a{color:var(--shadow-claw-link);text-decoration:underline;text-underline-offset:.125rem}a:hover{color:var(--shadow-claw-link-hover)}.header{background-color:var(--shadow-claw-bg-secondary);border-bottom:.0625rem solid var(--shadow-claw-border-color);gap:.5rem;height:4rem;justify-content:start;max-height:4rem;padding:.5rem 1rem}.header,.header h1{align-items:center;display:flex;width:100%}.header h1{color:var(--shadow-claw-text-primary);flex-direction:row;margin:0}#menu-button{align-items:center;background:transparent;border:none;border-radius:.25rem;color:var(--shadow-claw-text-secondary);cursor:pointer;display:flex;justify-content:center;padding:.5rem}#menu-button:hover,.theme-toggle:hover{background-color:var(--shadow-claw-bg-tertiary);color:var(--shadow-claw-text-primary)}.header-actions{gap:.5rem;margin-left:auto}.header-actions,.theme-toggle{align-items:center;display:flex}.theme-toggle{background:transparent;border:none;border-radius:.25rem;color:var(--shadow-claw-text-secondary);cursor:pointer;justify-content:center;padding:.5rem}.theme-mode-toggle .sun-icon{display:none}.theme-mode-toggle .moon-icon{display:block}.theme-toggle svg{transition:transform .2s ease}.activity-log-toggle[aria-pressed=true],.header-main-toggle[aria-pressed=true]{box-shadow:0 0 .5rem color-mix(in srgb,var(--shadow-claw-warning-color,#d97706) 50%,transparent);color:var(--shadow-claw-warning-color,#d97706)}.activity-log-toggle[aria-pressed=true] svg,.header-main-toggle[aria-pressed=true] svg{transform:rotate(180deg)}.webvm-toggle--booting,.webvm-toggle--ready,.webvm-toggle--visible{color:var(--shadow-claw-success-color)}.webvm-toggle--error{color:var(--shadow-claw-error-color)}.app{background-color:var(--shadow-claw-bg-primary);color:var(--shadow-claw-text-primary);display:flex;flex-direction:column;font-family:var(--shadow-claw-font-sans);visibility:visible;width:100%}.app-body{--sidebar-width:15.625rem;display:flex;flex:1;flex-direction:row;min-height:0;overflow:hidden}.sidebar{background-color:var(--shadow-claw-bg-secondary);border-right:.0625rem solid var(--shadow-claw-bg-tertiary);display:flex;flex:none;flex-direction:column;overflow-y:auto;position:relative;width:var(--sidebar-width)}.sidebar-resize-handle{background:transparent;cursor:col-resize;flex:none;outline:none;position:relative;touch-action:none;user-select:none;width:.75rem}.sidebar-resize-handle:before{background:color-mix(in srgb,var(--shadow-claw-bg-secondary) 72%,var(--shadow-claw-border-color));border:.0625rem solid color-mix(in srgb,var(--shadow-claw-border-color) 80%,transparent);height:4.25rem;transition:background-color .15s,border-color .15s,box-shadow .15s;width:.5625rem}.sidebar-resize-handle:after,.sidebar-resize-handle:before{border-radius:var(--shadow-claw-radius-pill);content:"";left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.sidebar-resize-handle:after{background:var(--shadow-claw-border-color);height:2.75rem;transition:background-color .15s;width:.1875rem}.sidebar-resize-handle.active:before,.sidebar-resize-handle:hover:before{background:color-mix(in srgb,var(--shadow-claw-accent-primary) 20%,var(--shadow-claw-bg-secondary));border-color:color-mix(in srgb,var(--shadow-claw-accent-primary) 45%,transparent);box-shadow:0 0 .5rem color-mix(in srgb,var(--shadow-claw-accent-primary) 18%,transparent)}.sidebar-resize-handle.active:after,.sidebar-resize-handle:hover:after{background:var(--shadow-claw-accent-primary)}.sidebar-resize-handle:focus-visible:before{background:color-mix(in srgb,var(--shadow-claw-accent-primary) 20%,var(--shadow-claw-bg-secondary));border-color:color-mix(in srgb,var(--shadow-claw-accent-primary) 45%,transparent);box-shadow:0 0 .5rem color-mix(in srgb,var(--shadow-claw-accent-primary) 18%,transparent)}.sidebar-resize-handle:focus-visible:after{background:var(--shadow-claw-accent-primary)}.sidebar-resize-handle:focus-visible{outline:.125rem solid color-mix(in srgb,var(--shadow-claw-accent-primary) 60%,transparent);outline-offset:.0625rem}@media (max-width:55.9375rem){.sidebar{display:none}.sidebar.open{border-radius:0 var(--shadow-claw-radius-m) var(--shadow-claw-radius-m) 0;box-shadow:var(--shadow-claw-shadow-lg);display:flex;height:calc(100vh - 4rem);height:calc(100dvh - 4rem);position:absolute;width:min(85vw,20rem);z-index:100}.sidebar-resize-handle{display:none}}@media (min-width:56rem){#menu-button{display:none}}.nav-menu{flex:none;list-style:none;margin:0;padding:.5rem}.sidebar-spacer{flex:1}shadow-claw-conversations{display:flex;flex:none;flex-direction:column;min-height:0;overflow:hidden}.nav-item{border-radius:var(--shadow-claw-radius-m);color:var(--shadow-claw-text-secondary);cursor:pointer;font-size:var(--shadow-claw-font-size-sm);font-weight:500;margin-bottom:.5rem;padding:.625rem .75rem;transition:background-color .15s,color .15s}.nav-item:hover{background-color:var(--shadow-claw-text-secondary)}.nav-item.active,.nav-item:hover{color:var(--shadow-claw-on-primary)}.nav-item.active{background-color:var(--shadow-claw-accent-primary)}.sidebar-footer{border-top:.0625rem solid var(--shadow-claw-border-color);flex:none;margin-bottom:.5rem;padding:.75rem}.settings-btn{background-color:transparent;border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-pill);color:var(--shadow-claw-text-secondary);cursor:pointer;font-size:.8125rem;padding:.625rem .75rem;transition:all var(--shadow-claw-duration-min) var(--shadow-claw-ease-out);width:100%}.settings-btn:hover{border-color:var(--shadow-claw-text-primary);box-shadow:var(--shadow-claw-shadow-md);color:var(--shadow-claw-text-primary)}.main-content{--chat-split-height:20rem;height:calc(100vh - 4rem);height:calc(100dvh - 4rem);overflow:hidden;position:relative}.main-content,.page{display:flex;flex:1;flex-direction:column;min-height:0}.page{display:none;overflow:auto}.page.active{display:flex}.chat-split-resize-handle{background:transparent;cursor:row-resize;display:none;flex:none;height:.75rem;outline:none;position:relative;touch-action:none;user-select:none;width:100%}.main-content.split-chat-active .page.active{order:1}.main-content.split-chat-active .chat-split-resize-handle{display:flex;margin-bottom:-.375rem;margin-top:-.375rem;order:2;z-index:10}.chat-split-resize-handle:before{background:color-mix(in srgb,var(--shadow-claw-bg-secondary) 72%,var(--shadow-claw-border-color));border:.0625rem solid color-mix(in srgb,var(--shadow-claw-border-color) 80%,transparent);height:.5625rem;transition:background-color .15s,border-color .15s,box-shadow .15s;width:4.25rem}.chat-split-resize-handle:after,.chat-split-resize-handle:before{border-radius:var(--shadow-claw-radius-pill);content:"";left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.chat-split-resize-handle:after{background:var(--shadow-claw-border-color);height:.1875rem;transition:background-color .15s;width:2.75rem}.chat-split-resize-handle.active:before,.chat-split-resize-handle:focus-visible:before,.chat-split-resize-handle:hover:before{background:color-mix(in srgb,var(--shadow-claw-accent-primary) 20%,var(--shadow-claw-bg-secondary));border-color:color-mix(in srgb,var(--shadow-claw-accent-primary) 45%,transparent);box-shadow:0 0 .5rem color-mix(in srgb,var(--shadow-claw-accent-primary) 18%,transparent)}.chat-split-resize-handle.active:after,.chat-split-resize-handle:focus-visible:after,.chat-split-resize-handle:hover:after{background:var(--shadow-claw-accent-primary)}.chat-split-resize-handle:focus-visible{outline:.125rem solid color-mix(in srgb,var(--shadow-claw-accent-primary) 60%,transparent);outline-offset:.0625rem}.main-content.split-chat-active .chat-page:not(.active){border-top:.0625rem solid var(--shadow-claw-border-color);display:flex;flex:none;height:var(--chat-split-height);max-height:calc(100% - 6.25rem);min-height:9.375rem;order:3}@media (max-width:55.9375rem){.chat-split-resize-handle,.main-content.split-chat-active .chat-page:not(.active){display:none!important}}.app-dialog{background:var(--shadow-claw-bg-secondary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-l);box-shadow:var(--shadow-claw-shadow-lg);color:var(--shadow-claw-text-primary);max-width:min(90vw,28rem);padding:0}.app-dialog::backdrop{background:color-mix(in srgb,#000 50%,transparent)}.app-confirm-dialog__form{display:flex;flex-direction:column;gap:.75rem;margin:0;padding:1rem}.app-dialog__title{font-size:1rem;margin:0}.app-dialog__details,.app-dialog__message{color:var(--shadow-claw-text-secondary);margin:0}.app-dialog__details{display:flex;flex-direction:column;gap:.25rem;padding-left:1rem}.app-dialog__links{display:flex;flex-wrap:wrap;gap:.5rem}.app-dialog__link{color:var(--shadow-claw-accent-primary);font-size:.9375rem;text-decoration:none}.app-dialog__link:focus-visible,.app-dialog__link:hover{text-decoration:underline}.app-dialog__countdown{color:var(--shadow-claw-text-secondary);font-size:.875rem;margin:0}.app-confirm-dialog__actions{display:flex;gap:.5rem;justify-content:flex-end}.app-dialog__btn{border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-m);cursor:pointer;font:inherit;padding:.5rem .75rem}.app-dialog__btn--cancel{background:var(--shadow-claw-bg-primary);color:var(--shadow-claw-text-primary)}.app-dialog__btn--confirm{background:var(--shadow-claw-accent-primary);border-color:var(--shadow-claw-accent-primary);color:var(--shadow-claw-on-primary)}.app-prompt-dialog__form{display:flex;flex-direction:column;gap:.75rem;margin:0;padding:1rem}.app-prompt-dialog__title{font-size:1rem;margin:0}.app-prompt-dialog__message{color:var(--shadow-claw-text-secondary);margin:0}.app-prompt-dialog__input-area{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem}.app-prompt-dialog__input{background:var(--shadow-claw-bg-primary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-s);color:var(--shadow-claw-text-primary);font:inherit;padding:.5rem;width:100%}.app-prompt-dialog__actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.5rem}.chat-page{flex-direction:column}:host([data-prerender-no-seed=true]) .nav-item,:host([data-prerender-no-seed=true]) .page.active,:host([data-prerender-no-seed=true]) .sidebar-footer,:host([data-prerender-no-seed=true]) shadow-claw-conversations,:host([data-prerender-no-seed=true]) shadow-claw-file-viewer,:host([data-prerender-no-seed=true]) shadow-claw-toast{opacity:1;transform:translateY(0);transition:opacity var(--shadow-claw-duration-min) var(--shadow-claw-ease-out),transform var(--shadow-claw-duration-min) var(--shadow-claw-ease-out)}:host([data-prerender-no-seed=true][data-hydration-pending=true]) .nav-item,:host([data-prerender-no-seed=true][data-hydration-pending=true]) .page.active,:host([data-prerender-no-seed=true][data-hydration-pending=true]) .sidebar-footer,:host([data-prerender-no-seed=true][data-hydration-pending=true]) shadow-claw-conversations,:host([data-prerender-no-seed=true][data-hydration-pending=true]) shadow-claw-file-viewer,:host([data-prerender-no-seed=true][data-hydration-pending=true]) shadow-claw-toast,:host([data-prerender-no-seed=true][data-js-boot-pending=true]) .nav-item,:host([data-prerender-no-seed=true][data-js-boot-pending=true]) .page.active,:host([data-prerender-no-seed=true][data-js-boot-pending=true]) .sidebar-footer,:host([data-prerender-no-seed=true][data-js-boot-pending=true]) shadow-claw-conversations,:host([data-prerender-no-seed=true][data-js-boot-pending=true]) shadow-claw-file-viewer,:host([data-prerender-no-seed=true][data-js-boot-pending=true]) shadow-claw-toast{opacity:0;pointer-events:none;transform:translateY(.25rem)}@media (prefers-reduced-motion:reduce){:host([data-prerender-no-seed=true]) .nav-item,:host([data-prerender-no-seed=true]) .page.active,:host([data-prerender-no-seed=true]) .sidebar-footer,:host([data-prerender-no-seed=true]) shadow-claw-conversations,:host([data-prerender-no-seed=true]) shadow-claw-file-viewer,:host([data-prerender-no-seed=true]) shadow-claw-toast{transform:none;transition:none}}.sidebar-boot-skeleton{background-color:var(--shadow-claw-bg-secondary);bottom:0;display:flex;flex-direction:column;left:0;opacity:0;padding:1rem .75rem;pointer-events:none;position:absolute;right:0;top:0;transition:opacity var(--shadow-claw-duration-regular) var(--shadow-claw-ease-out),visibility var(--shadow-claw-duration-regular) var(--shadow-claw-ease-out);visibility:hidden;z-index:10}:host([data-hydration-pending=true]) .sidebar-boot-skeleton,:host([data-js-boot-pending=true]) .sidebar-boot-skeleton{opacity:1;pointer-events:auto;visibility:visible}.skeleton-nav-wrapper{display:none;flex-direction:column;gap:.5rem;margin-bottom:.5rem}:host([data-prerender-no-seed=true]) .skeleton-nav-wrapper{display:flex}.skeleton-divider{border-top:.0625rem solid var(--shadow-claw-border-color);display:none;margin:.75rem 0}:host([data-prerender-no-seed=true]) .skeleton-divider{display:block}.skeleton-convo-wrapper{display:flex;flex-direction:column;gap:.75rem;margin-top:.5rem}.skeleton-item{animation:skeleton-pulse 1.8s ease-in-out infinite;background:linear-gradient(90deg,var(--shadow-claw-bg-secondary) 25%,var(--shadow-claw-bg-tertiary) 50%,var(--shadow-claw-bg-secondary) 75%);background-size:200% 100%}.skeleton-nav{border-radius:var(--shadow-claw-radius-m);height:2.25rem;width:100%}.skeleton-nav:first-child{width:85%}.skeleton-nav:nth-child(2){width:90%}.skeleton-nav:nth-child(3){width:75%}.skeleton-nav:nth-child(4){width:80%}.skeleton-convo{border-radius:var(--shadow-claw-radius-m);height:3.5rem;width:100%}.main-content-boot-skeleton{align-items:center;background-color:var(--shadow-claw-bg-primary);bottom:0;display:flex;flex-direction:column;justify-content:center;left:0;opacity:0;padding:2rem;pointer-events:none;position:absolute;right:0;top:0;transition:opacity var(--shadow-claw-duration-regular) var(--shadow-claw-ease-out),visibility var(--shadow-claw-duration-regular) var(--shadow-claw-ease-out);visibility:hidden;z-index:10}:host([data-prerender-no-seed=true][data-hydration-pending=true]) .main-content-boot-skeleton,:host([data-prerender-no-seed=true][data-js-boot-pending=true]) .main-content-boot-skeleton{opacity:1;pointer-events:auto;visibility:visible}.boot-loading-svg{height:4.5rem;opacity:.85;transition:color var(--shadow-claw-duration-min) var(--shadow-claw-ease-out);width:4.5rem}.boot-loading-svg,.boot-loading-text{color:var(--shadow-claw-text-secondary)}.boot-loading-text{font-size:var(--shadow-claw-font-size-sm);font-weight:600;letter-spacing:.075em;margin-top:1.25rem;text-transform:uppercase}@keyframes skeleton-pulse{0%{background-position:200% 0}to{background-position:-200% 0}}</style><div class="app"><header class="header"><button aria-label="Open menu" title="Open menu" id="menu-button"><svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" fill="currentColor" viewBox="0 -960 960 960"><path d="M120-680v-80h720v80zm0 480v-80h720v80zm0-240v-80h720v80z"/></svg></button><h1><slot name="header-title-link"></slot><div class="header-actions"><button aria-label="Toggle theme" title="Toggle theme" class="theme-mode-toggle theme-toggle"><svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" fill="currentColor" class="sun-icon" viewBox="0 -960 960 960"><path d="M480-360q50 0 85-35t35-85-35-85-85-35-85 35-35 85 35 85 85 35m0 80q-83 0-141.5-58.5T280-480t58.5-141.5T480-680t141.5 58.5T680-480t-58.5 141.5T480-280M200-440H40v-80h160zm720 0H760v-80h160zM440-760v-160h80v160zm0 720v-160h80v160zM256-650l-101-97 57-59 96 100zm492 496-97-101 53-55 101 97zm-98-550 97-101 59 57-101 97zM158-190l97-101 55 53-101 97z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" fill="currentColor" class="moon-icon" viewBox="0 -960 960 960"><path d="M480-120q-150 0-255-105T120-480t105-255 255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q52 0 99-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120m0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-74 30-122.5 100T204-480q0 116 82 198t194 82m-12-274"/></svg></button><button aria-label="Hide action header" title="Hide action header" aria-pressed="false" class="header-main-toggle theme-toggle" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" fill="currentColor" viewBox="0 -960 960 960"><path d="M280-200h400v-80H280zm200-200L280-600l56-56 104 104v-328h80v328l104-104 56 56z"/></svg></button><button aria-label="Hide activity log" title="Hide activity log" aria-pressed="false" class="activity-log-toggle theme-toggle" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 -960 960 960"><path d="M80-600v-160q0-33 23.5-56.5T160-840h640q33 0 56.5 23.5T880-760v160h-80v-160H160v160zm80 360q-33 0-56.5-23.5T80-320v-200h80v200h640v-200h80v200q0 33-23.5 56.5T800-240zM40-120v-80h880v80zm40-400v-80h240q11 0 21 6t15 16l47 93 123-215q5-9 14-14.5t20-5.5 21 5.5 15 16.5l49 98h235v80H620q-11 0-21-5.5T584-542l-26-53-123 215q-5 10-15 15t-21 5-20.5-6-14.5-16l-69-138z"/></svg></button><button aria-label="Hide WebVM terminal" title="Hide WebVM terminal" aria-pressed="true" class="theme-toggle webvm-toggle" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" fill="currentColor" viewBox="0 -960 960 960"><path d="M320-280 120-480l200-200 56 56-104 104h568v80H272l104 104zm320 0-56-56 104-104H120v-80h568L584-624l56-56 200 200z"/></svg></button><slot name="header-actions-logo"></slot></div></h1></header><div class="app-body"><aside class="sidebar"><div class="sidebar-boot-skeleton" aria-hidden="true"><div class="skeleton-nav-wrapper"><div class="skeleton-item skeleton-nav"></div><div class="skeleton-item skeleton-nav"></div><div class="skeleton-item skeleton-nav"></div><div class="skeleton-item skeleton-nav"></div></div><div class="skeleton-divider"></div><div class="skeleton-convo-wrapper"><div class="skeleton-convo skeleton-item"></div><div class="skeleton-convo skeleton-item"></div><div class="skeleton-convo skeleton-item"></div></div></div><nav><ul class="nav-menu"><li class="active nav-item" data-page="pages">📚 Pages</li><li class="nav-item" data-page="chat">💬 Chat</li><li class="nav-item" data-page="tasks">&nbsp;✓&nbsp;Tasks</li><li class="nav-item" data-page="files">📁 Files</li></ul></nav><div class="sidebar-spacer"></div><shadow-claw-conversations></shadow-claw-conversations><div class="sidebar-footer"><button class="settings-btn" data-action="show-settings"> ⚙️ Settings </button></div></aside><div class="sidebar-resize-handle" title="Drag to resize sidebar"></div><main class="main-content"><div class="main-content-boot-skeleton" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="boot-loading-svg" viewBox="0 0 44 44"><g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-width="2"><circle cx="22" cy="22" r="1"><animate attributeName="r" begin="0s" calcMode="spline" dur="1.8s" keySplines="0.165, 0.84, 0.44, 1" keyTimes="0; 1" repeatCount="indefinite" values="1; 20"/><animate attributeName="stroke-opacity" begin="0s" calcMode="spline" dur="1.8s" keySplines="0.3, 0.61, 0.355, 1" keyTimes="0; 1" repeatCount="indefinite" values="1; 0"/></circle><circle cx="22" cy="22" r="1"><animate attributeName="r" begin="-0.9s" calcMode="spline" dur="1.8s" keySplines="0.165, 0.84, 0.44, 1" keyTimes="0; 1" repeatCount="indefinite" values="1; 20"/><animate attributeName="stroke-opacity" begin="-0.9s" calcMode="spline" dur="1.8s" keySplines="0.3, 0.61, 0.355, 1" keyTimes="0; 1" repeatCount="indefinite" values="1; 0"/></circle></g></svg><div class="boot-loading-text">Preparing workspace...</div></div><div class="chat-page page" data-page-id="chat"></div><div class="page" data-page-id="tasks"></div><div class="page" data-page-id="files"></div><div class="active page" data-page-id="pages"><shadow-claw-pages><template shadowrootmode="open" data-shadow-claw-pages-dsd="true"><style data-dsd-style>*{box-sizing:border-box}:host{display:block;height:calc(100dvh + 4rem);line-height:1.5}.pages{background:var(--shadow-claw-bg-primary);color:var(--shadow-claw-text-primary);flex-direction:column}.pages,.pages__content{display:flex;min-height:0;min-width:0}.pages__content{flex:1;flex-direction:column}.pages__sidebar{display:none}.pages__list{padding:.625rem}.pages__group-details,.pages__list{display:flex;flex-direction:column;gap:.375rem}.pages__group-label{align-items:center;color:var(--shadow-claw-text-secondary);cursor:pointer;display:flex;font-size:.75rem;font-weight:700;justify-content:space-between;list-style:none;margin:.25rem 0 0;padding:.125rem .25rem;text-transform:uppercase;user-select:none}.pages__group-label::-webkit-details-marker{display:none}.pages__group-icon{font-size:.625rem;transform:rotate(-90deg);transition:transform var(--shadow-claw-duration-min) var(--shadow-claw-ease-out)}.pages__group-details[open] .pages__group-icon{transform:rotate(0deg)}.pages__group-pages{display:flex;flex-direction:column;gap:.375rem}.pages__list-item{align-items:center;background:var(--shadow-claw-bg-secondary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-m);color:var(--shadow-claw-text-primary);display:flex;font-size:var(--shadow-claw-font-size-sm);gap:.375rem;justify-content:space-between;line-height:1.35;padding:.375rem;width:100%}.pages__list-item:hover{border-color:var(--shadow-claw-accent-primary)}.pages__select{align-items:center;background:transparent;border:none;color:inherit;cursor:pointer;display:flex;flex:1;font:inherit;min-width:0;padding:.125rem .25rem;text-align:left}.pages__list-item.active{background:color-mix(in srgb,var(--shadow-claw-accent-primary) 20%,var(--shadow-claw-bg-secondary));border-color:var(--shadow-claw-accent-primary)}.pages__list-path{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%}.pages__remove{background:transparent;border:none;color:var(--shadow-claw-text-secondary);cursor:pointer;flex:none;font-size:1rem;line-height:1;padding:.125rem .25rem}.pages__remove:hover{color:var(--shadow-claw-error-color)}.pages__viewer{display:flex;flex:1;flex-direction:row;min-height:calc(100vh - 11rem);min-height:calc(100dvh - 11rem);min-width:0;overflow:hidden;position:relative}.pages__viewer-scroll{display:flex;flex:1;flex-direction:column;height:calc(100% + 1.5rem);min-width:0;padding:.75rem 1rem}.pages__rendered{max-width:72rem;padding:1rem 1.5rem 1rem 1rem}.pages__rendered :is(pre){overflow:auto}.pages__rendered img{max-height:100%;max-width:100%}.pages__rendered a{color:var(--shadow-claw-accent-primary)}.pages__rendered>h1,.pages__rendered>h2,article>h1,article>h2{margin-top:0}.pages__iframe{background:transparent;border-width:0;display:block;height:auto;min-height:20rem;overflow:hidden;width:100%}.pages__empty,.pages__status{color:var(--shadow-claw-text-secondary);font-size:var(--shadow-claw-font-size-sm)}.pages:has(.pages__sidebar.collapsed) .pages__remove-all-btn{display:none}.pages:has(.pages__sidebar.collapsed) shadow-claw-page-header::part(actions-disclosure){display:none}.pages__dropdown-container{align-items:center;display:flex;gap:.5rem;margin-bottom:1rem;position:relative;width:100%}.pages__nav-btn{align-items:center;backdrop-filter:blur(6px);background:color-mix(in srgb,var(--shadow-claw-bg-secondary) 80%,transparent);border:.0625rem solid color-mix(in srgb,var(--shadow-claw-border-color) 60%,transparent);border-radius:var(--shadow-claw-radius-m);color:var(--shadow-claw-text-secondary);cursor:pointer;display:flex;flex:none;height:8rem;justify-content:center;max-height:8rem;min-height:8rem;opacity:0;padding:.75rem .5rem;pointer-events:none;position:fixed;top:50dvh;transform:translateY(-50%);transition:opacity .4s var(--shadow-claw-ease-out),color .15s var(--shadow-claw-ease-out),border-color .15s var(--shadow-claw-ease-out),background .15s var(--shadow-claw-ease-out);z-index:100}.pages__nav-btn--prev{left:.5rem}.pages__nav-btn--next{right:.5rem}.pages__content:focus-within .pages__nav-btn:not(:disabled):not([hidden]),.pages__content:has(.pages__viewer--nav-visible) .pages__nav-btn:not(:disabled):not([hidden]),.pages__nav-btn:hover:not(:disabled):not([hidden]),.pages__viewer.pages__viewer--nav-visible~.pages__nav-btn:not(:disabled):not([hidden]),.pages__viewer:focus-within~.pages__nav-btn:not(:disabled):not([hidden]){opacity:1;pointer-events:auto}.pages__nav-btn:disabled,.pages__nav-btn[hidden]{display:none!important;opacity:0!important;pointer-events:none!important}.pages__nav-btn:hover:not(:disabled){background:color-mix(in srgb,var(--shadow-claw-accent-primary) 15%,var(--shadow-claw-bg-secondary));border-color:var(--shadow-claw-accent-primary);color:var(--shadow-claw-accent-primary);opacity:1}.pages__nav-btn:disabled{cursor:not-allowed}.pages__dropdown{background:var(--shadow-claw-bg-secondary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-m);box-shadow:var(--shadow-claw-shadow-sm);color:var(--shadow-claw-text-primary);display:block;transition:border-color var(--shadow-claw-duration-min) var(--shadow-claw-ease-out);width:100%}.pages__dropdown:hover{border-color:var(--shadow-claw-accent-primary)}.pages__dropdown-summary{align-items:center;cursor:pointer;display:flex;font-size:var(--shadow-claw-font-size-sm);font-weight:600;gap:.5rem;justify-content:space-between;list-style:none;padding:.625rem 1rem;user-select:none}.pages__dropdown-summary::-webkit-details-marker{display:none}.pages__dropdown-selected{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pages__dropdown-arrow{color:var(--shadow-claw-text-secondary);font-size:.75rem;transition:transform var(--shadow-claw-duration-min) var(--shadow-claw-ease-out)}.pages__dropdown[open] .pages__dropdown-arrow{transform:rotate(180deg)}.pages__dropdown-menu{backdrop-filter:blur(10px);background:var(--shadow-claw-bg-secondary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-m);box-shadow:var(--shadow-claw-shadow-lg);left:0;margin-top:.375rem;max-height:20rem;overflow-y:auto;position:absolute;right:0;z-index:100}.pages__dropdown-menu .pages__list{padding:.375rem}.pages__breadcrumbs{align-items:center;display:flex;font-size:.8125rem}.pages__sidebar-toggle-btn{background-color:var(--shadow-claw-bg-primary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:.1875rem;color:var(--shadow-claw-accent-primary);cursor:pointer;padding:.25rem .5rem;transition:all .1s}.pages__sidebar-toggle-btn:focus-visible,.pages__sidebar-toggle-btn:hover{background-color:var(--shadow-claw-bg-tertiary);border-color:var(--shadow-claw-accent-primary);outline:none}.pages__drag-handle{color:var(--shadow-claw-text-tertiary);cursor:grab;flex:none;font-size:.875rem;line-height:1;padding:.125rem .25rem;user-select:none}.pages__drag-handle:hover{color:var(--shadow-claw-text-secondary)}.pages__drag-handle:active,.pages__list-item.dragging .pages__drag-handle{cursor:grabbing}.pages__list-item.drag-over{border-color:var(--shadow-claw-accent-primary);box-shadow:0 0 0 .125rem var(--shadow-claw-accent-primary)}.pages__default-btn{background:transparent;border:none;color:var(--shadow-claw-text-tertiary);cursor:pointer;flex:none;font-size:.875rem;line-height:1;padding:.125rem .25rem}.pages__default-btn.is-default,.pages__default-btn:hover{color:var(--shadow-claw-accent-primary)}.pages__edit{background:transparent;border:none;color:var(--shadow-claw-text-secondary);cursor:pointer;flex:none;font-size:.875rem;line-height:1;padding:.125rem .25rem}.pages__edit:hover{color:var(--shadow-claw-text-primary)}@media (min-width:75rem){.pages__content{display:grid;grid-template-columns:minmax(14rem,20rem) minmax(0,1fr);grid-template-rows:minmax(0,1fr)}.pages__content.pages__content--sidebar-collapsed{grid-template-columns:1fr!important}.pages__sidebar{border-right:.0625rem solid var(--shadow-claw-border-color);display:block;min-height:0;overflow:auto}.pages__sidebar.collapsed{display:none!important}.pages__dropdown{display:none}.pages__nav-btn--prev{left:20.5rem}.pages__content.pages__content--sidebar-collapsed .pages__nav-btn--prev{left:.5rem}}ul{line-height:1.5}.pages__announcer{border:0;clip:rect(0,0,0,0);height:.0625rem;margin:-.0625rem;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:.0625rem}</style><section class="pages" aria-label="Pages"><div class="pages__announcer" data-pages-announcer aria-live="polite" aria-atomic="true"></div><shadow-claw-page-header icon="📚" title="Pages"><template shadowrootmode="open" data-shadow-claw-page-header-dsd="true"><style data-dsd-style>*,:after,:before{box-sizing:border-box;font-family:var(--shadow-claw-font-sans)}.hidden,[hidden]{display:none!important}:host{display:block}.header{background-color:var(--shadow-claw-bg-primary);border-bottom:.0625rem solid var(--shadow-claw-border-color)}.header__main{display:flex;flex-direction:column;padding:.75rem}.header__main,.header__top{align-items:flex-start;gap:.75rem}.header__top{display:grid;grid-template-columns:minmax(0,1fr);width:100%}.header__title{font-size:1rem;font-weight:600;margin:0}.header__title a{color:var(--shadow-claw-link);text-decoration:none}.header__title a:hover{color:var(--shadow-claw-link-hover);text-decoration:underline}.header__actions{display:flex;flex-direction:column;gap:.375rem;padding-top:.5rem;width:100%}.header__actions[hidden]{display:none!important}.header__actions-disclosure{width:100%}.header__actions-disclosure[hidden]{display:none!important}.header__actions-toggle{align-items:center;background-color:var(--shadow-claw-bg-secondary);border:.0625rem solid var(--shadow-claw-border-color);border-radius:var(--shadow-claw-radius-m,1rem);color:var(--shadow-claw-text-secondary);cursor:pointer;display:flex;font-size:.75rem;font-weight:600;gap:.5rem;justify-content:space-between;list-style:none;min-height:2rem;padding:.375rem .625rem;user-select:none;width:100%}.header__actions-toggle::-webkit-details-marker{display:none}.header__actions-toggle:after{border-color:currentcolor transparent transparent;border-style:solid;border-width:.375rem .3125rem 0;content:"";display:inline-block;flex:none;transform:rotate(0deg);transition:transform .2s ease}.header__actions-disclosure[open] .header__actions-toggle:after{transform:rotate(180deg)}.header__actions-toggle:focus-visible,.header__actions-toggle:hover{background-color:var(--shadow-claw-bg-tertiary,#f1f5f9);border-color:var(--shadow-claw-accent-primary,#334155);color:var(--shadow-claw-text-primary,#0f172a);outline:none}::slotted(button),::slotted(shadow-claw-page-header-action-button){flex:1 1 100%!important;min-width:0!important;width:100%!important}@media (min-width:40.625rem){.header__main{padding:.875rem 1rem 1rem}.header__title{font-size:var(--shadow-claw-font-size-md)}.header__top{align-items:start;grid-template-columns:1fr auto}.header__actions{flex-direction:row;flex-wrap:wrap;gap:.5rem;justify-content:flex-end;padding-top:0;width:auto}.header__actions-toggle{display:none}.header__actions-disclosure{width:auto}::slotted(button),::slotted(shadow-claw-page-header-action-button){flex:0 1 auto!important;min-width:fit-content!important;width:auto!important}}.header__breadcrumbs{width:100%}.header__breadcrumbs:empty{display:none}.header__status{align-items:flex-start;display:flex;flex-direction:column;gap:.5rem;width:100%}.header__status:empty{display:none}@media (min-width:40.625rem){.header__status{align-items:center;flex-direction:row;justify-content:space-between}}</style><header class="header"><div class="header__main"><div class="header__top"><h2 class="header__title">📚 Pages — Agent Skills &amp; Skill Creator</h2><details class="header__actions-disclosure" part="actions-disclosure"><summary aria-label="Toggle page actions" class="header__actions-toggle"> Actions </summary><div class="header__actions" id="header-actions-panel" hidden><slot name="actions"></slot></div></details></div><div class="header__status"><slot name="status"></slot></div><div class="header__breadcrumbs"><slot name="breadcrumbs"></slot></div></div></header></template><nav slot="breadcrumbs" class="pages__breadcrumbs" aria-label="Toggle pages sidebar"><button type="button" class="pages__sidebar-toggle-btn" data-pages-sidebar-toggle title="Toggle pages list"> 📁 Pages </button></nav><div class="pages__status" data-pages-status>5 saved pages</div><shadow-claw-page-header-action-button class="pages__remove-all-btn" slot="actions" title="Remove all saved pages" variant="danger"> 🗑️ Remove All </shadow-claw-page-header-action-button></shadow-claw-page-header><div class="pages__content pages__content--sidebar-collapsed"><aside class="collapsed pages__sidebar" aria-label="Saved pages"><div class="pages__list" data-pages-list role="list"><details class="pages__group-details" open><summary class="pages__group-label"><span>Main</span><span class="pages__group-icon">▼</span></summary><div class="pages__group-pages"><div class="pages__list-item active"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn is-default" title="Default page">⭐</span><button type="button" class="pages__select" title="Open ~/docs/skill-creator.md"><span class="pages__list-path">~/docs/skill-creator.md</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit ~/docs/skill-creator.md in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove ~/docs/skill-creator.md from Pages in Main">✕</button></div><div class="pages__list-item"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn" title="Default page">⭐</span><button type="button" class="pages__select" title="Open index.html"><span class="pages__list-path">index.html</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit index.html in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove index.html from Pages in Main">✕</button></div><div class="pages__list-item"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn" title="Default page">⭐</span><button type="button" class="pages__select" title="Open ~/docs/publishing-to-github-pages.md"><span class="pages__list-path">~/docs/publishing-to-github-pages.md</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit ~/docs/publishing-to-github-pages.md in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove ~/docs/publishing-to-github-pages.md from Pages in Main">✕</button></div><div class="pages__list-item"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn" title="Default page">⭐</span><button type="button" class="pages__select" title="Open ~/docs/example/article.html"><span class="pages__list-path">~/docs/example/article.html</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit ~/docs/example/article.html in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove ~/docs/example/article.html from Pages in Main">✕</button></div><div class="pages__list-item"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn" title="Default page">⭐</span><button type="button" class="pages__select" title="Open MEMORY.md"><span class="pages__list-path">MEMORY.md</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit MEMORY.md in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove MEMORY.md from Pages in Main">✕</button></div></div></details></div></aside><button type="button" class="pages__nav-btn pages__nav-btn--prev" data-pages-prev aria-label="Previous page" hidden disabled><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"><path d="m15 18-6-6 6-6"/></svg></button><article class="pages__viewer" aria-label="Page preview"><div class="pages__viewer-scroll"><div class="pages__dropdown-container" data-pages-dropdown-container><details class="pages__dropdown" data-pages-dropdown><summary class="pages__dropdown-summary"><span class="pages__dropdown-selected" data-pages-dropdown-selected>~/docs/skill-creator.md</span><span class="pages__dropdown-arrow">▼</span></summary><div class="pages__dropdown-menu"><div class="pages__list" data-pages-list role="list"><details class="pages__group-details" open><summary class="pages__group-label"><span>Main</span><span class="pages__group-icon">▼</span></summary><div class="pages__group-pages"><div class="pages__list-item active"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn is-default" title="Default page">⭐</span><button type="button" class="pages__select" title="Open ~/docs/skill-creator.md"><span class="pages__list-path">~/docs/skill-creator.md</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit ~/docs/skill-creator.md in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove ~/docs/skill-creator.md from Pages in Main">✕</button></div><div class="pages__list-item"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn" title="Default page">⭐</span><button type="button" class="pages__select" title="Open index.html"><span class="pages__list-path">index.html</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit index.html in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove index.html from Pages in Main">✕</button></div><div class="pages__list-item"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn" title="Default page">⭐</span><button type="button" class="pages__select" title="Open ~/docs/publishing-to-github-pages.md"><span class="pages__list-path">~/docs/publishing-to-github-pages.md</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit ~/docs/publishing-to-github-pages.md in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove ~/docs/publishing-to-github-pages.md from Pages in Main">✕</button></div><div class="pages__list-item"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn" title="Default page">⭐</span><button type="button" class="pages__select" title="Open ~/docs/example/article.html"><span class="pages__list-path">~/docs/example/article.html</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit ~/docs/example/article.html in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove ~/docs/example/article.html from Pages in Main">✕</button></div><div class="pages__list-item"><span class="pages__drag-handle" draggable="true" title="Drag to reorder">⠿</span><span class="pages__default-btn" title="Default page">⭐</span><button type="button" class="pages__select" title="Open MEMORY.md"><span class="pages__list-path">MEMORY.md</span></button><button class="pages__edit" type="button" title="Edit in file editor" aria-label="Edit MEMORY.md in file editor">✏️</button><button class="pages__remove" type="button" title="Remove from Pages" aria-label="Remove MEMORY.md from Pages in Main">✕</button></div></div></details></div></div></details></div><div class="pages__empty" data-pages-empty hidden> No pages yet. In Files, use "Set as Page" on a markdown or HTML file. </div><div class="pages__rendered" data-pages-rendered><section class="markdown-frontmatter" data-markdown-frontmatter="" data-frontmatter="{&#10; &quot;title&quot;: &quot;Agent Skills &amp; Skill Creator&quot;,&#10; &quot;created&quot;: &quot;1970-01-01T00:00:00Z&quot;,&#10; &quot;updated&quot;: &quot;1970-01-01T00:00:00Z&quot;,&#10; &quot;slug&quot;: &quot;skill-creator&quot;&#10;}"><details class="markdown-frontmatter__details" hidden="hidden"><summary class="markdown-frontmatter__summary">Frontmatter</summary><pre class="markdown-frontmatter__pre"><code class="language-json">{
@@ -45,6 +45,6 @@ metadata:
45
45
 
46
46
  This skill generates a random integer and displays it instantly in a toast notification.
47
47
  </code></pre> <p>When you type <code>/toast-random-number</code>, ShadowClaw executes the two steps directly without delay!</p></div></div></article><button type="button" class="pages__nav-btn pages__nav-btn--next" data-pages-next aria-label="Next page" hidden disabled><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"><path d="m9 18 6-6-6-6"/></svg></button></div></section></template></shadow-claw-pages></div><div class="page" data-page-id="settings"></div><div class="page" data-page-id="tools"></div><div class="page" data-page-id="channels"></div><div class="chat-split-resize-handle" title="Drag to resize chat panel" hidden></div><shadow-claw-toast></shadow-claw-toast></main></div><shadow-claw-dialog dialog-class="app-dialog" dialog-aria-labelledby="appDialogTitle"><template><form method="dialog" class="app-confirm-dialog__form"><h2 id="appDialogTitle" class="app-dialog__title">Confirm</h2><p class="app-dialog__message"></p><ul class="app-dialog__details" hidden></ul><div class="app-dialog__links" hidden></div><p class="app-dialog__countdown" hidden role="status" aria-live="polite" aria-atomic="true"></p><div class="app-confirm-dialog__actions"><button type="submit" value="cancel" class="app-dialog__btn app-dialog__btn--cancel"> Cancel </button><button type="submit" value="confirm" class="app-dialog__btn app-dialog__btn--confirm"> Confirm </button></div></form></template></shadow-claw-dialog><shadow-claw-dialog dialog-class="app-dialog app-prompt-dialog" dialog-aria-labelledby="appPromptTitle"><template><form method="dialog" class="app-prompt-dialog__form"><h2 id="appPromptTitle" class="app-prompt-dialog__title"> Agent Question </h2><p class="app-prompt-dialog__message"></p><div class="app-prompt-dialog__input-area"></div><div class="app-prompt-dialog__actions"><button type="submit" value="submit" class="app-dialog__btn app-dialog__btn--confirm app-prompt-dialog__submit"> Submit </button></div></form></template></shadow-claw-dialog></div></template>
48
- <a aria-label="ShadowClaw" class="header-title-link" href="https://xt-ml.github.io/shadow-claw/" slot="header-title-link"> <svg xmlns="http://www.w3.org/2000/svg" class="header-title-logo" viewBox="0 0 128 128"><rect width="128" height="128" fill="var(--shadow-claw-icon-bg)" rx="16"/><ellipse cx="64" cy="108" fill="var(--shadow-claw-icon-body)" rx="18" ry="12"/><ellipse cx="52" cy="112" fill="var(--shadow-claw-icon-accent-dark)" rx="8" ry="10"/><ellipse cx="76" cy="112" fill="var(--shadow-claw-icon-accent-dark)" rx="8" ry="10"/><ellipse cx="64" cy="92" fill="var(--shadow-claw-icon-body-segment)" rx="14" ry="8"/><ellipse cx="64" cy="82" fill="var(--shadow-claw-icon-body)" rx="12" ry="7"/><ellipse cx="64" cy="74" fill="var(--shadow-claw-icon-body-segment)" rx="10" ry="6"/><ellipse cx="64" cy="58" fill="var(--shadow-claw-icon-body)" rx="20" ry="18"/><ellipse cx="64" cy="50" fill="var(--shadow-claw-icon-body-segment)" rx="16" ry="10"/><rect width="18" height="8" x="28" y="45" fill="var(--shadow-claw-icon-body)" rx="4" transform="rotate(-20 37 49)"/><ellipse cx="20" cy="38" fill="var(--shadow-claw-icon-claw-main)" rx="14" ry="10"/><ellipse cx="16" cy="36" fill="var(--shadow-claw-icon-claw-inner)" rx="10" ry="7"/><ellipse cx="12" cy="34" fill="var(--shadow-claw-icon-accent-dark)" rx="5" ry="4"/><rect width="18" height="8" x="82" y="45" fill="var(--shadow-claw-icon-body)" rx="4" transform="rotate(20 91 49)"/><ellipse cx="108" cy="38" fill="var(--shadow-claw-icon-claw-main)" rx="14" ry="10"/><ellipse cx="112" cy="36" fill="var(--shadow-claw-icon-claw-inner)" rx="10" ry="7"/><ellipse cx="116" cy="34" fill="var(--shadow-claw-icon-accent-dark)" rx="5" ry="4"/><rect width="12" height="4" x="38" y="62" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(-30 44 64)"/><rect width="14" height="4" x="36" y="68" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(-25 43 70)"/><rect width="12" height="4" x="38" y="74" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(-20 44 76)"/><rect width="12" height="4" x="78" y="62" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(30 84 64)"/><rect width="14" height="4" x="78" y="68" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(25 85 70)"/><rect width="12" height="4" x="78" y="74" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(20 84 76)"/><ellipse cx="64" cy="38" fill="var(--shadow-claw-icon-body)" rx="14" ry="12"/><circle cx="56" cy="34" r="5" fill="var(--shadow-claw-icon-eye)"/><circle cx="72" cy="34" r="5" fill="var(--shadow-claw-icon-eye)"/><circle cx="56" cy="33" r="2" fill="var(--shadow-claw-icon-eye-shine)"/><circle cx="72" cy="33" r="2" fill="var(--shadow-claw-icon-eye-shine)"/><path fill="none" stroke="var(--shadow-claw-icon-accent-dark)" stroke-linecap="round" stroke-width="2" d="M60 42q4 4 8 0"/><path fill="none" stroke="var(--shadow-claw-icon-accent-dark)" stroke-linecap="round" stroke-width="3" d="M58 26Q50 14 42 8m28 18q8-12 16-18"/><path fill="none" stroke="var(--shadow-claw-icon-body)" stroke-linecap="round" stroke-width="2" d="M60 24q-6-8-10-14m18 14q6-8 10-14"/><ellipse cx="60" cy="55" fill="var(--shadow-claw-icon-body-shine)" opacity=".4" rx="6" ry="8"/></svg> <span class="header-title">ShadowClaw</span> </a> <a aria-label="Shadow Claw Project on GitHub" class="header-actions-logo-link" href="https://github.com/xt-ml/shadow-claw" slot="header-actions-logo"> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewBox="0 0 496 512"><path fill="var(--shadow-claw-bg-primary-reverse, currentColor)" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8"/></svg> </a>
48
+ <a aria-label="ShadowClaw" class="header-title-link" href="https://xt-ml.github.io/shadow-claw/" slot="header-title-link"> <svg xmlns="http://www.w3.org/2000/svg" class="header-title-logo" viewBox="0 0 128 128"><rect width="128" height="128" fill="var(--shadow-claw-icon-bg)" rx="16"/><ellipse cx="64" cy="108" fill="var(--shadow-claw-icon-body)" rx="18" ry="12"/><ellipse cx="52" cy="112" fill="var(--shadow-claw-icon-accent-dark)" rx="8" ry="10"/><ellipse cx="76" cy="112" fill="var(--shadow-claw-icon-accent-dark)" rx="8" ry="10"/><ellipse cx="64" cy="92" fill="var(--shadow-claw-icon-body-segment)" rx="14" ry="8"/><ellipse cx="64" cy="82" fill="var(--shadow-claw-icon-body)" rx="12" ry="7"/><ellipse cx="64" cy="74" fill="var(--shadow-claw-icon-body-segment)" rx="10" ry="6"/><ellipse cx="64" cy="58" fill="var(--shadow-claw-icon-body)" rx="20" ry="18"/><ellipse cx="64" cy="50" fill="var(--shadow-claw-icon-body-segment)" rx="16" ry="10"/><rect width="18" height="8" x="28" y="45" fill="var(--shadow-claw-icon-body)" rx="4" transform="rotate(-20 37 49)"/><ellipse cx="20" cy="38" fill="var(--shadow-claw-icon-claw-main)" rx="14" ry="10"/><ellipse cx="16" cy="36" fill="var(--shadow-claw-icon-claw-inner)" rx="10" ry="7"/><ellipse cx="12" cy="34" fill="var(--shadow-claw-icon-accent-dark)" rx="5" ry="4"/><rect width="18" height="8" x="82" y="45" fill="var(--shadow-claw-icon-body)" rx="4" transform="rotate(20 91 49)"/><ellipse cx="108" cy="38" fill="var(--shadow-claw-icon-claw-main)" rx="14" ry="10"/><ellipse cx="112" cy="36" fill="var(--shadow-claw-icon-claw-inner)" rx="10" ry="7"/><ellipse cx="116" cy="34" fill="var(--shadow-claw-icon-accent-dark)" rx="5" ry="4"/><rect width="12" height="4" x="38" y="62" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(-30 44 64)"/><rect width="14" height="4" x="36" y="68" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(-25 43 70)"/><rect width="12" height="4" x="38" y="74" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(-20 44 76)"/><rect width="12" height="4" x="78" y="62" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(30 84 64)"/><rect width="14" height="4" x="78" y="68" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(25 85 70)"/><rect width="12" height="4" x="78" y="74" fill="var(--shadow-claw-icon-accent-dark)" rx="2" transform="rotate(20 84 76)"/><ellipse cx="64" cy="38" fill="var(--shadow-claw-icon-body)" rx="14" ry="12"/><circle cx="56" cy="34" r="5" fill="var(--shadow-claw-icon-eye)"/><circle cx="72" cy="34" r="5" fill="var(--shadow-claw-icon-eye)"/><circle cx="56" cy="33" r="2" fill="var(--shadow-claw-icon-eye-shine)"/><circle cx="72" cy="33" r="2" fill="var(--shadow-claw-icon-eye-shine)"/><path fill="none" stroke="var(--shadow-claw-icon-accent-dark)" stroke-linecap="round" stroke-width="2" d="M60 42q4 4 8 0"/><path fill="none" stroke="var(--shadow-claw-icon-accent-dark)" stroke-linecap="round" stroke-width="3" d="M58 26Q50 14 42 8m28 18q8-12 16-18"/><path fill="none" stroke="var(--shadow-claw-icon-body)" stroke-linecap="round" stroke-width="2" d="M60 24q-6-8-10-14m18 14q6-8 10-14"/><ellipse cx="60" cy="55" fill="var(--shadow-claw-icon-body-shine)" opacity=".4" rx="6" ry="8"/></svg> <h1 class="header-title">ShadowClaw</h1> </a> <a aria-label="Shadow Claw Project on GitHub" class="header-actions-logo-link" href="https://github.com/xt-ml/shadow-claw" slot="header-actions-logo"> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewBox="0 0 496 512"><path fill="var(--shadow-claw-bg-primary-reverse, currentColor)" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8"/></svg> </a> <noscript> <div style="line-height:1.6;margin:0 auto;max-width:50rem;padding:2rem"> <h2>Browser-Native Personal AI Assistant</h2> <p> ShadowClaw is an open-source, browser-native AI assistant designed for autonomous orchestration, client-side tool execution, and private local storage via Origin Private File System (OPFS) and IndexedDB. </p> <h3>Agent & Developer Resources</h3> <ul> <li><a href="llms.txt">llms.txt (Agent Context & Guidance)</a></li> <li> <a href=".well-known/mcp.json">MCP Server Card (SEP-2127)</a> </li> <li> <a href=".well-known/ai-catalog.json">AI Catalog Discovery</a> </li> <li> <a href=".well-known/mcp/servers.json">MCP Servers Manifest</a> </li> <li><a href="sitemap.xml">XML Sitemap</a></li> <li> <a href="https://github.com/xt-ml/shadow-claw">GitHub Repository</a> </li> </ul> </div> </noscript>
49
49
  </shadow-claw> <script type="module" src="index.js"></script> <script type="module">try{self[`workbox:window:7.4.0`]&&_()}catch{}function e(e,t){return new Promise((function(n){var r=new MessageChannel;r.port1.onmessage=function(e){n(e.data)},e.postMessage(t,[r.port2])}))}function t(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function n(e,t,n){return t&&function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,`value`in r&&(r.writable=!0),Object.defineProperty(e,a(r.key),r)}}(e.prototype,t),Object.defineProperty(e,"prototype",{writable:!1}),e}function r(e,n){var r=typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(r)return(r=r.call(e)).next.bind(r);if(Array.isArray(e)||(r=function(e,n){if(e){if(typeof e==`string`)return t(e,n);var r={}.toString.call(e).slice(8,-1);return r===`Object`&&e.constructor&&(r=e.constructor.name),r===`Map`||r===`Set`?Array.from(e):r===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?t(e,n):void 0}}(e))||n){r&&(e=r);var i=0;return function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}}}throw TypeError(`Invalid attempt to iterate non-iterable instance.
50
50
  In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function i(e,t){return i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},i(e,t)}function a(e){var t=function(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return String(e)}(e,`string`);return typeof t==`symbol`?t:t+``}try{self[`workbox:core:7.4.0`]&&_()}catch{}var o=function(){var e=this;this.promise=new Promise((function(t,n){e.resolve=t,e.reject=n}))};function s(e,t){var n=location.href;return new URL(e,n).href===new URL(t,n).href}var c=function(e,t){this.type=e,Object.assign(this,t)};function l(e,t,n){return e&&e.then||(e=Promise.resolve(e)),t?e.then(t):e}function u(){}var d={type:`SKIP_WAITING`};function f(e,t){return e&&e.then?e.then(u):Promise.resolve()}var p=function(t){function r(e,n){var r,i;return n===void 0&&(n={}),(r=t.call(this)||this).nn={},r.tn=0,r.rn=new o,r.en=new o,r.on=new o,r.un=0,r.an=new Set,r.cn=function(){var e=r.fn,t=e.installing;r.tn>0||!s(t.scriptURL,r.sn.toString())||performance.now()>r.un+6e4?(r.vn=t,e.removeEventListener(`updatefound`,r.cn)):(r.hn=t,r.an.add(t),r.rn.resolve(t)),++r.tn,t.addEventListener(`statechange`,r.ln)},r.ln=function(e){var t=r.fn,n=e.target,i=n.state,a=n===r.vn,o={sw:n,isExternal:a,originalEvent:e};!a&&r.mn&&(o.isUpdate=!0),r.dispatchEvent(new c(i,o)),i===`installed`?r.wn=self.setTimeout((function(){i===`installed`&&t.waiting===n&&r.dispatchEvent(new c(`waiting`,o))}),200):i===`activating`&&(clearTimeout(r.wn),a||r.en.resolve(n))},r.yn=function(e){var t=r.hn,n=t!==navigator.serviceWorker.controller;r.dispatchEvent(new c(`controlling`,{isExternal:n,originalEvent:e,sw:t,isUpdate:r.mn})),n||r.on.resolve(t)},r.gn=(i=function(e){var t=e.data,n=e.ports,i=e.source;return l(r.getSW(),(function(){r.an.has(i)&&r.dispatchEvent(new c(`message`,{data:t,originalEvent:e,ports:n,sw:i}))}))},function(){var e=[...arguments];try{return Promise.resolve(i.apply(this,e))}catch(e){return Promise.reject(e)}}),r.sn=e,r.nn=n,navigator.serviceWorker.addEventListener(`message`,r.gn),r}var a,u=t;(a=r).prototype=Object.create(u.prototype),a.prototype.constructor=a,i(a,u);var p=r.prototype;return p.register=function(e){var t=(e===void 0?{}:e).immediate,n=t!==void 0&&t;try{var r=this;return l(function(e,t){var n=e();return n&&n.then?n.then(t):t(n)}((function(){if(!n&&document.readyState!==`complete`)return f(new Promise((function(e){return window.addEventListener(`load`,e)})))}),(function(){return r.mn=!!navigator.serviceWorker.controller,r.dn=r.pn(),l(r.bn(),(function(e){r.fn=e,r.dn&&(r.hn=r.dn,r.en.resolve(r.dn),r.on.resolve(r.dn),r.dn.addEventListener(`statechange`,r.ln,{once:!0}));var t=r.fn.waiting;return t&&s(t.scriptURL,r.sn.toString())&&(r.hn=t,Promise.resolve().then((function(){r.dispatchEvent(new c(`waiting`,{sw:t,wasWaitingBeforeRegister:!0}))})).then((function(){}))),r.hn&&(r.rn.resolve(r.hn),r.an.add(r.hn)),r.fn.addEventListener(`updatefound`,r.cn),navigator.serviceWorker.addEventListener(`controllerchange`,r.yn),r.fn}))})))}catch(e){return Promise.reject(e)}},p.update=function(){try{return this.fn?l(f(this.fn.update())):l()}catch(e){return Promise.reject(e)}},p.getSW=function(){return this.hn===void 0?this.rn.promise:Promise.resolve(this.hn)},p.messageSW=function(t){try{return l(this.getSW(),(function(n){return e(n,t)}))}catch(e){return Promise.reject(e)}},p.messageSkipWaiting=function(){this.fn&&this.fn.waiting&&e(this.fn.waiting,d)},p.pn=function(){var e=navigator.serviceWorker.controller;return e&&s(e.scriptURL,this.sn.toString())?e:void 0},p.bn=function(){try{var e=this;return l(function(e,t){try{var n=e()}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}((function(){return l(navigator.serviceWorker.register(e.sn,e.nn),(function(t){return e.un=performance.now(),t}))}),(function(e){throw e})))}catch(e){return Promise.reject(e)}},n(r,[{key:`active`,get:function(){return this.en.promise}},{key:`controlling`,get:function(){return this.on.promise}}])}(function(){function e(){this.Pn=new Map}var t=e.prototype;return t.addEventListener=function(e,t){this.jn(e).add(t)},t.removeEventListener=function(e,t){this.jn(e).delete(t)},t.dispatchEvent=function(e){e.target=this;for(var t,n=r(this.jn(e.type));!(t=n()).done;)(0,t.value)(e)},t.jn=function(e){return this.Pn.has(e)||this.Pn.set(e,new Set),this.Pn.get(e)},e}());const m=`__shadowClawDefaultTrustedTypesPolicyState`,h=`default`,g=`shadowclaw-sandbox`;function v(){let e=globalThis;return e[m]||(e[m]={initialized:!1,policy:null}),e[m]}function y(){let e=v();if(e.initialized)return;let t=Reflect.get(globalThis,`trustedTypes`);if(!(!t||typeof t.createPolicy!=`function`)){e.initialized=!0;try{if(typeof t.getPolicy==`function`){let n=t.getPolicy(h);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(h)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(g);if(n){e.policy=n;return}}e.policy=t.createPolicy(g,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(h,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(h)??t.getPolicy(g)??null)}}}function b(e){y();let t=v().policy;return!t||typeof t.createScriptURL!=`function`?e:t.createScriptURL(e)}const x=`shadowclaw-sw-update-intent`,S=3e4,C=`shadowclaw-sw-update-failure`;let w=!1,T=null;async function E(e=5e3){let t=Date.now();for(;Date.now()-t<e;){let e=document.querySelector(`shadow-claw`);if(e&&typeof e.requestDialog==`function`)return e;await new Promise(e=>{globalThis.setTimeout(e,50)})}return null}async function D(){let e=await E();return e?.requestDialog?await e.requestDialog({title:`Update Available`,message:`A new version of ShadowClaw is ready. Reload now to apply the update?`,confirmLabel:`Reload now`,cancelLabel:`Later`}):!1}async function O(){let e=await E();e?.requestDialog&&await e.requestDialog({title:`Update Failed`,message:`The app update failed to install automatically. Please try restarting your browser to complete the update.`,confirmLabel:`OK`}),console.warn(`[ShadowClaw] Service worker update failed. Please restart your browser to complete the update.`)}function k(){try{let e=globalThis.sessionStorage?.getItem(x);if(!e)return null;let t=JSON.parse(e);return typeof t.startedAt!=`number`||typeof t.fallbackReloadAttempts!=`number`?null:{startedAt:t.startedAt,fallbackReloadAttempts:t.fallbackReloadAttempts}}catch{return null}}function A(e){try{globalThis.sessionStorage?.setItem(x,JSON.stringify(e))}catch{}}function j(){try{globalThis.sessionStorage?.removeItem(x)}catch{}}function M(){let e=k();return e?Date.now()-e.startedAt<=S?!0:(j(),!1):!1}function N(){I(),A({startedAt:Date.now(),fallbackReloadAttempts:0})}function P(){try{let e=globalThis.sessionStorage?.getItem(C);if(!e)return null;let t=JSON.parse(e);return typeof t.failedAt==`number`?{failedAt:t.failedAt}:null}catch{return null}}function F(e){try{globalThis.sessionStorage?.setItem(C,JSON.stringify(e))}catch{}}function I(){try{globalThis.sessionStorage?.removeItem(C)}catch{}}function L(){let e=P();return e?Date.now()-e.failedAt<=3e5?!0:(I(),!1):!1}function R(){j(),F({failedAt:Date.now()})}function z(){if(w)return;w=!0,T!==null&&(globalThis.clearTimeout(T),T=null);let e=globalThis.location;typeof e?.reload==`function`&&e.reload()}async function B(){if(w||T!==null)return;let e=k();if(e){if(Date.now()-e.startedAt>S){j();return}if(e.fallbackReloadAttempts>=2){R(),await O();return}A({...e,fallbackReloadAttempts:e.fallbackReloadAttempts+1}),T=globalThis.setTimeout(()=>{z()},3e3)}}async function V(e){e.messageSkipWaiting(),await B()}function H(){return M()}function U(){let e=H();j(),I(),e&&z()}try{if(typeof navigator<`u`&&`serviceWorker`in navigator&&navigator.serviceWorker){y();let e=new p(b(`service-worker.js`));e.addEventListener(`waiting`,async()=>{if(!L()){if(M()){await V(e);return}await D()&&(N(),await V(e))}}),e.addEventListener(`controlling`,()=>{U()}),navigator.serviceWorker.addEventListener(`controllerchange`,()=>{U()});let t=()=>{globalThis.setTimeout(()=>{e.register()},1e4)};document.readyState===`complete`?t():globalThis.addEventListener(`load`,t)}}catch{}export{z as reloadCurrentPage,H as shouldReloadAfterControllerChange};</script> </body></html>
@@ -308,14 +308,17 @@ npx shadow-claw skills:index --stdout --no-write
308
308
  npx shadow-claw skills:index --out-file custom/discovery/index.json
309
309
  ```
310
310
 
311
- | Option | Type | Description | Default |
312
- | :------------------ | :------ | :---------------------------------------------- | :--------------------------- |
313
- | `--out-dir <dir>` | string | Output directory relative to content root | `".well-known/agent-skills"` |
314
- | `--out-file <file>` | string | Explicit destination file path for `index.json` | `undefined` |
315
- | `--stdout` | boolean | Print generated JSON directly to stdout | `false` |
316
- | `--no-write` | boolean | Skip writing the generated index file to disk | `false` |
317
-
318
- > **Build Pipeline Integration:** `bin/build/build.mjs` automatically executes `generateSkillsIndex(contentRoot)` during builds whenever `.agents/skills` exists, and copies `.agents/scripts` along with `.well-known/agent-skills/index.json` into `dist/public`.
311
+ | Option | Type | Description | Default |
312
+ | :---------------------- | :------ | :----------------------------------------------- | :--------------------------- |
313
+ | `--out-dir <dir>` | string | Output directory relative to content root | `".well-known/agent-skills"` |
314
+ | `--out-file <file>` | string | Explicit destination file path for `index.json` | `undefined` |
315
+ | `--metadata-root <dir>` | string | Directory to read site metadata from | content root |
316
+ | `--config <file>` | string | Path to `shadow-claw.config.json` | auto-discovered |
317
+ | `--no-bundled` | boolean | Exclude bundled ShadowClaw skills from discovery | `false` |
318
+ | `--stdout` | boolean | Print generated JSON directly to stdout | `false` |
319
+ | `--no-write` | boolean | Skip writing the generated index file to disk | `false` |
320
+
321
+ > **Build Pipeline Integration:** `bin/build/build.mjs` automatically generates `.well-known/agent-skills/index.json` during builds into `dist/public`, indexing both content skills and bundled skills (such as `skill-creator`) using the content root's site metadata, and keeps `.agents/scripts` and repository `.well-known` synchronized.
319
322
 
320
323
  ---
321
324
 
@@ -166,6 +166,7 @@ The host client fulfills the request by calling `tools/call` with `inputResponse
166
166
  | `shadowclaw_read_state` | Query orchestrator state (`idle`, `responding`), active conversation group, and model. | `clientId` |
167
167
  | `shadowclaw_list_tasks` | List scheduled background tasks configured on a connected client. | `clientId`, `groupId` |
168
168
  | `shadowclaw_manage_backup` | Trigger, list, or delete OPFS workspace snapshots on a client. | `action` (`trigger` \| `list` \| `delete`), `clientId`, `backupId`, `groupId` |
169
+ | `shadowclaw_send_notification` | Broadcast an OS push notification to all subscribed devices or a specific registered client via Web Push (VAPID). | `body` (required), `title` (optional), `clientId` (optional) |
169
170
  | `shadowclaw_server_status` | Query Node server status, version, and connected client count. | None |
170
171
 
171
172
  ---