shadow-claw 1.39.0 → 1.39.1

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://modelcontextprotocol.io/schemas/server-card/v1.json",
3
3
  "name": "shadow-claw",
4
- "version": "1.39.0",
4
+ "version": "1.39.1",
5
5
  "description": "Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.",
6
6
  "title": "ShadowClaw MCP Server",
7
7
  "websiteUrl": "https://xt-ml.github.io/shadow-claw/",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://modelcontextprotocol.io/schemas/server-card/v1.json",
3
3
  "name": "shadow-claw",
4
- "version": "1.39.0",
4
+ "version": "1.39.1",
5
5
  "description": "Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.",
6
6
  "title": "ShadowClaw MCP Server",
7
7
  "websiteUrl": "https://xt-ml.github.io/shadow-claw/",
package/dist/cli/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import{t as e}from"./chunk-uAI_Zi6n.js";import{n as t}from"./chunk-CzjkPhc1.js";import{t as n}from"./chunk-CFhvwUeL.js";import{c as r,i,o as a,s as o}from"./chunk-DHi40kQk.js";import{t as s}from"./chunk-DFh_pp_7.js";import{n as c}from"./chunk-D5mJX3Mr.js";import{r as l}from"./chunk-C-5VcG3a.js";import{a as u}from"./chunk-CS2NqF-O.js";import d from"node:fs";import f from"node:path";import{fileURLToPath as p}from"node:url";import m from"node:process";import{exec as h}from"node:child_process";import{mkdir as g,readFile as _,stat as v,writeFile as y}from"node:fs/promises";import{Command as b}from"commander";import x from"process";import S from"node:http";import C from"node:readline";async function w(e={}){let t=new s(e);try{let e=await t.listClients();if(!e||e.length===0){console.log(`No clients currently registered or connected.`);return}console.log(`Connected / registered clients (${e.length}):\n`),e.forEach((e,t)=>{let n=Math.max(0,Math.floor((Date.now()-e.lastSeen)/1e3)),r=n<60?`${n}s ago`:`${Math.floor(n/60)}m ago`;console.log(` ${t+1}. ${e.deviceLabel} (id: ${e.clientId})`),e.peerId&&console.log(` Peer ID: ${e.peerId}`),console.log(` Capabilities: ${e.capabilities.join(`, `)||`none`}`),console.log(` Version: ${e.version}`),console.log(` Last seen: ${r}\n`)})}catch(e){console.error(`Error fetching clients: ${e.message}`),x.exitCode=1}}async function T(e,t={}){if(!e||typeof e!=`string`||!e.trim()){console.error(`Error: Message cannot be empty.`),x.exitCode=1;return}let n=new s(t);try{let r=t.client;if(!r){let e=await n.listClients();if(!e||e.length===0){console.error(`Error: No clients are connected.`),x.exitCode=1;return}r=e[0].clientId,console.log(`Targeting client: ${e[0].deviceLabel||r} (${r})`)}let i=r||``,a=t.timeout?Number(t.timeout)*1e3:12e4,o;if(t.file?(console.log(`Sending message with file "${t.file}" to ${i}...`),o=await n.sendFile(i,t.file,{prompt:e.trim(),groupId:t.group,timeoutMs:a})):(console.log(`Sending message to ${i}...`),o=await n.sendCommand(i,`send-message`,{text:e.trim(),groupId:t.group},a)),o.success)if(console.log(`Message successfully dispatched.`),o.data?.reply||o.data?.text){let e=o.data.reply||o.data.text;console.log(``),console.log(`Response from ${i}:`),console.log(`----------------------------------------`),console.log(e),console.log(`----------------------------------------`)}else o.data&&(t.json,console.log(JSON.stringify(o.data,null,2)));else console.error(`Error from client: ${o.error||`Unknown error`}`),x.exitCode=1}catch(e){console.error(`Error sending message: ${e.message}`),x.exitCode=1}}async function E(e,t={}){if(!e||typeof e!=`string`||!e.trim()){console.error(`Error: File path cannot be empty.`),x.exitCode=1;return}let n=f.resolve(e.trim());if(!d.existsSync(n)){console.error(`Error: File not found: ${e}`),x.exitCode=1;return}let r=d.statSync(n);if(r.isDirectory()){console.error(`Error: Cannot send directory: ${e}`),x.exitCode=1;return}let i=new s(t);try{let e=t.client;if(!e){let t=await i.listClients();if(!t||t.length===0){console.error(`Error: No clients are connected.`),x.exitCode=1;return}e=t[0].clientId,console.log(`Targeting client: ${t[0].deviceLabel||e} (${e})`)}let a=e||``,o=t.name||f.basename(n);console.log(`Sending "${o}" (${r.size} bytes) to ${a}...`);let s=t.timeout?Number(t.timeout)*1e3:12e4,c=await i.sendFile(a,n,{prompt:t.prompt,name:t.name,groupId:t.group,timeoutMs:s});if(c.success)if(console.log(`File "${o}" successfully transferred to ${a}.`),c.data?.path&&console.log(`Remote location: ${c.data.path}`),c.data?.reply||c.data?.text){let e=c.data.reply||c.data.text;console.log(``),console.log(`Response from ${a}:`),console.log(`----------------------------------------`),console.log(e),console.log(`----------------------------------------`)}else t.json&&c.data&&console.log(JSON.stringify(c.data,null,2));else console.error(`Error from client: ${c.error||`Unknown error`}`),x.exitCode=1}catch(e){console.error(`Error sending file: ${e.message}`),x.exitCode=1}}async function D(e=`trigger`,t={}){let n=new s(t);try{if(e===`list`){let e=await n.listBackups(t.client);if(!e||e.length===0){console.log(`No backups found.`);return}console.log(`Available backups (${e.length}):\n`),e.forEach((e,t)=>{let n=new Date(e.timestamp).toISOString(),r=(e.totalBytes/(1024*1024)).toFixed(2);console.log(` ${t+1}. [${e.id}] Client: ${e.clientId}`),console.log(` Date: ${n}`),console.log(` Files: ${e.fileCount} (${r} MB)\n`)});return}if(e===`delete`){if(!t.backupId){console.error(`Error: --backup-id is required for delete action.`),x.exitCode=1;return}await n.deleteBackup(t.backupId,t.client),console.log(`Backup ${t.backupId} deleted.`);return}let r=t.client;if(!r){let e=await n.listClients();if(!e||e.length===0){console.error(`Error: No clients are connected to back up.`),x.exitCode=1;return}r=e[0].clientId}let i=r||``;console.log(`Requesting backup from client ${i}...`);let a=await n.sendCommand(i,`trigger-backup`,{groupId:t.group,token:n.token});a.success?(console.log(`Backup completed successfully.`),console.log(JSON.stringify(a.data,null,2))):(console.error(`Backup failed: ${a.error}`),x.exitCode=1)}catch(e){console.error(`Error executing backup command: ${e.message}`),x.exitCode=1}}async function O(e={}){let t=new s(e);try{let n=e.client;if(!n){let e=await t.listClients();if(!e||e.length===0){console.error(`Error: No clients connected.`),x.exitCode=1;return}n=e[0].clientId}let r=n||``;console.log(`Fetching tasks from client ${r}${e.group?` (group: ${e.group})`:``}...`);let i=await t.sendCommand(r,`list-tasks`,{groupId:e.group});if(i.success){let t=i.data?.tasks||[];if(t.length===0){console.log(e.group?`No tasks configured on client for group "${e.group}".`:`No tasks configured on client.`);return}console.log(`Tasks on ${n}${e.group?` (group: ${e.group})`:``} (${t.length}):\n`),t.forEach((e,t)=>{let n=e.enabled?`[enabled]`:`[disabled]`,r=e.name||e.prompt?.slice(0,30)||`Untitled task`;console.log(` ${t+1}. ${n} ${r} (${e.schedule||`manual`})`)})}else console.error(`Failed to list tasks: ${i.error}`),x.exitCode=1}catch(e){console.error(`Error executing tasks command: ${e.message}`),x.exitCode=1}}async function k(e=`get`,t={}){let n=t.cacheDir,s=i(n),c=!!(t.renew||e===`renew`||e===`generate`||e===`new`),l=t.set||(e===`set`&&t.id?t.id:null),u=``,d=!1;if(l)u=r(l,n),d=!0;else if(c)u=r(void 0,n),d=!0;else{let e=o(n);e?(u=e,d=!1):(u=a(void 0,n),d=!0)}return t.quiet?(console.log(u),{peerId:u,filePath:s,isRenewed:d}):t.json?(console.log(JSON.stringify({peerId:u,filePath:s,renewed:d},null,2)),{peerId:u,filePath:s,isRenewed:d}):(console.log(l?`WebRTC CLI Peer ID set to: ${u}`:d?`WebRTC CLI Peer ID created/renewed: ${u}`:`WebRTC CLI Peer ID: ${u}`),console.log(`Stored in: ${s}`),{peerId:u,filePath:s,isRenewed:d})}function A(e,t){return typeof e==`string`?t===`raw`?e.startsWith(`shadowclaw_client_`)?e.slice(18):e:e.startsWith(`shadowclaw_client_`)?e:`shadowclaw_client_${e}`:e}function j(e){return A(e,`raw`)}function M(e){return A(e,`exposed`)}const N=[{name:`shadowclaw_server_list_clients`,description:`List connected browser and Electron clients, including device type, ID, and active capabilities.`,inputSchema:{type:`object`,properties:{}}},{name:`shadowclaw_server_send_message`,description:`Send a message or prompt to a connected ShadowClaw client's active AI orchestrator queue.`,inputSchema:{type:`object`,properties:{text:{type:`string`,description:`The prompt or message text to dispatch.`},clientId:{type:`string`,description:`Target client ID. If omitted, targets the first available connected client.`},groupId:{type:`string`,description:`Target conversation group ID (e.g. 'br:main'). If omitted, targets the active group.`}},required:[`text`]}},{name:`shadowclaw_server_read_state`,description:`Read the current orchestrator state (idle, responding, etc.), active group ID, and capabilities from a connected client.`,inputSchema:{type:`object`,properties:{clientId:{type:`string`,description:`Target client ID (defaults to first available connected client).`}}}},{name:`shadowclaw_server_list_tasks`,description:`List scheduled background tasks configured on a connected client (optionally filtered by conversation group).`,inputSchema:{type:`object`,properties:{clientId:{type:`string`,description:`Target client ID (defaults to first available connected client).`},groupId:{type:`string`,description:`Optional conversation group ID filter.`}}}},{name:`shadowclaw_server_set_active_client`,description:`Set the active default connected client used when no clientId is explicitly provided in tool calls.`,inputSchema:{type:`object`,properties:{clientId:{type:`string`,description:`Target client ID (or index '0', '1', prefix, or device label) to make active.`}},required:[`clientId`]}},{name:`shadowclaw_server_manage_backup`,description:`Trigger or manage OPFS workspace file backups for a connected client (trigger, list, or delete).`,inputSchema:{type:`object`,properties:{action:{type:`string`,enum:[`trigger`,`list`,`delete`],description:`Backup action to perform (default: 'trigger').`,default:`trigger`},clientId:{type:`string`,description:`Target client ID.`},backupId:{type:`string`,description:`Backup snapshot ID (required for 'delete').`},groupId:{type:`string`,description:`Optional workspace conversation group ID.`}}}},{name:`shadowclaw_server_status`,description:`Query ShadowClaw Node server status, version, and active client count.`,inputSchema:{type:`object`,properties:{}}},{name:`shadowclaw_server_send_notification`,description:`Broadcast an OS-level push notification to subscribed devices via Web Push (VAPID), or send to a specific registered client. Works even when the client browser tab is closed, asleep, or running in the background.`,inputSchema:{type:`object`,properties:{title:{type:`string`,description:`Notification title (default: 'ShadowClaw').`},body:{type:`string`,description:`The notification body message text.`},clientId:{type:`string`,description:`Target client ID, prefix, or device label of a specific client that has registered in the past. If omitted, broadcasts to all subscribed devices.`}},required:[`body`]}}];function P(e,t){try{let n=typeof e.getConnectedClients==`function`?e.getConnectedClients():typeof e.listClients==`function`?e.listClients():[];if(Array.isArray(n)&&n.length>0){if(typeof t==`string`&&t.trim()){let e=t.trim(),r=n.find(t=>(t.clientId||t.id)===e);if(r)return r.clientId||r.id||``;let i=parseInt(e,10);if(!isNaN(i)&&i>=0&&i<n.length)return n[i].clientId||n[i].id||``;let a=n.find(t=>(t.clientId||t.id||``).startsWith(e)||(t.clientId||t.id||``).replace(/^client-/,``).startsWith(e));if(a)return a.clientId||a.id||``;let o=n.find(t=>t.deviceLabel?.toLowerCase().includes(e.toLowerCase()));return o?o.clientId||o.id||``:e}if(typeof e.getActiveClientId==`function`){let t=e.getActiveClientId();if(t)return t}return n[0].clientId||n[0].id||``}}catch{}return typeof t==`string`?t.trim():``}const F=f.dirname(p(import.meta.url));function I(){try{let e=f.resolve(F,`../../../package.json`);if(d.existsSync(e)){let t=JSON.parse(d.readFileSync(e,`utf8`));if(t.version)return t.version}}catch{}return`1.27.1`}const L=N;function R(e={}){let t=e.client||new s(e),n=e.relayClientTools!==!1,r=e.targetClientId||e.clientTarget,i=r||``,a={name:`shadow-claw`,version:e.version||I()},o={tools:{listChanged:!0},extensions:{"io.modelcontextprotocol/tasks":{}}};async function c(e){let n=e||i||r;try{let e=await t.listClients();return P({getConnectedClients:()=>e},n)}catch{}return P(t,n)}let l=new Map,u=new Map;async function d(){if(!n)return[];let e=[];try{e=await t.listClients()}catch{}if(!Array.isArray(e)||e.length===0)return l.clear(),u.clear(),[];l.clear(),u.clear();for(let n of e){let e=n.clientId||n.id;if(e)try{let r=await t.sendCommand(e,`list-tools`,{});if(r&&r.success&&r.data?.tools&&Array.isArray(r.data.tools))for(let e of r.data.tools){let t=j(e.name);t===`send_notification`||t.startsWith(`shadowclaw_`)&&!t.startsWith(`shadowclaw_client_`)||(u.has(t)||(u.set(t,e),l.set(t,[])),l.get(t).push(n))}}catch{}}let r=await c(),i=[];for(let[t,n]of u.entries()){let a=l.get(t)||[],o=a.map(e=>e.clientId||e.id).filter(Boolean),s=a.find(e=>(e.clientId||e.id)===r)||a[0],c=s?.clientId||s?.id||``,u=s?.deviceLabel||`Client`,d=n.inputSchema&&typeof n.inputSchema==`object`?n.inputSchema:{type:`object`,properties:{}},f={...d.properties||{},clientId:{type:`string`,description:`Target ShadowClaw client ID (optional; defaults to ${c} [${u}]). Available on: ${a.map(e=>`${e.clientId||e.id} (${e.deviceLabel||`Client`})`).join(`, `)}`,enum:o}},p=e.length>1?a.length>1?` [Default: ${u} (${c.slice(0,14)}...)]`:` [Client: ${u} (${c.slice(0,14)}...)]`:``,m=M(t);i.push({name:m,description:(n.description||`Relayed tool '${t}' from connected client.`)+p,inputSchema:{...d,type:`object`,properties:f},annotations:n.annotations})}return i}async function f(e,n={}){let r=e.id===void 0||e.id===null,s=e.id??null;if(n[`mcp-method`]&&n[`mcp-method`]!==e.method)return{jsonrpc:`2.0`,id:s,error:{code:-32020,message:`Mcp-Method header '${n[`mcp-method`]}' does not match '${e.method}'`}};switch(e.method){case`server/discover`:return{jsonrpc:`2.0`,id:s,result:{protocolVersion:`2026-07-28`,supportedProtocolVersions:[`2026-07-28`,`2025-11-25`,`2024-11-05`],capabilities:o,serverInfo:a,_meta:{"io.modelcontextprotocol/serverInfo":a}}};case`initialize`:return{jsonrpc:`2.0`,id:s,result:{protocolVersion:e.params?.protocolVersion||`2024-11-05`,capabilities:o,serverInfo:a}};case`notifications/initialized`:return null;case`tools/list`:{let e=[];try{if(typeof t.listPushClients==`function`)e=await t.listPushClients();else if(typeof t.listPushSubscriptions==`function`){let n=await t.listPushSubscriptions();if(Array.isArray(n)){let t=new Map;for(let e of n){let n=(e.client_id||``).trim()||(e.id?String(e.id):``);n&&!t.has(n)&&t.set(n,{clientId:n,deviceLabel:e.device_label||void 0})}e=Array.from(t.values())}}}catch{}let n=Array.isArray(e)?[...e].sort((e,t)=>(e.clientId||``).localeCompare(t.clientId||``)):[],r=n.map(e=>e.clientId).filter(Boolean),i=await d(),o=new Map;for(let e of L)o.set(e.name,e);for(let e of i)o.has(e.name)||o.set(e.name,e);if(r.length>0)for(let e of[`shadowclaw_server_send_notification`,`shadowclaw_send_notification`]){let t=o.get(e);t&&o.set(e,{...t,inputSchema:{...t.inputSchema,type:`object`,properties:{...t.inputSchema?.properties||{},clientId:{type:`string`,description:`Target client ID, prefix, or device label of a specific client registered for push notifications (optional; if omitted, broadcasts to all subscribed devices). Available on: ${n.map(e=>`${e.clientId} (${e.deviceLabel||`Client`})`).join(`, `)}`,enum:r}}}})}return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,ttlMs:5e3,cacheScope:`private`,tools:Array.from(o.values()).sort((e,t)=>e.name.localeCompare(t.name)),_meta:{"io.modelcontextprotocol/serverInfo":a}}}}case`tools/call`:{let n=e.params?.name,r=e.params?.arguments||{},o=e.params?.inputResponses;if(!n)return{jsonrpc:`2.0`,id:s,error:{code:-32602,message:`Missing required parameter 'name'`}};if(n===`shadowclaw_server_list_clients`||n===`shadowclaw_list_clients`)try{let e=await t.listClients();return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,content:[{type:`text`,text:JSON.stringify({clients:e},null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error listing clients: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}if(n===`shadowclaw_server_set_active_client`||n===`shadowclaw_set_active_client`){let e=await c(r.clientId);return e?(i=e,console.error(`[ShadowClaw MCP] Active default client set to: ${i}`),{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,content:[{type:`text`,text:`Active default client set to: ${i}`}],_meta:{activeClientId:i,"io.modelcontextprotocol/serverInfo":a}}}):{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: Client '${r.clientId}' not found among connected clients.`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}if(n===`shadowclaw_server_send_message`||n===`shadowclaw_send_message`){let e=await c(r.clientId);if(!e)return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: No connected client available.`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}};try{let n=await t.sendCommand(e,`send-message`,{text:r.text,groupId:r.groupId});return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!n.success,content:[{type:`text`,text:JSON.stringify(n.data||n,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error sending message: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}if(n===`shadowclaw_server_read_state`||n===`shadowclaw_read_state`){let e=await c(r.clientId);try{let n=await t.sendCommand(e,`read-state`,{});return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!n.success,content:[{type:`text`,text:JSON.stringify(n.data||n,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error reading state: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}if(n===`shadowclaw_server_list_tasks`||n===`shadowclaw_list_tasks`){let e=await c(r.clientId);try{let n=await t.sendCommand(e,`list-tasks`,{groupId:r.groupId});return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!n.success,content:[{type:`text`,text:JSON.stringify(n.data||n,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error listing tasks: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}if(n===`shadowclaw_server_manage_backup`||n===`shadowclaw_manage_backup`){let e=r.action||`trigger`,n=await c(r.clientId);try{if(e===`list`){let e=await t.listBackups(n);return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,content:[{type:`text`,text:JSON.stringify({backups:e},null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}if(e===`delete`){let e=await t.deleteBackup(r.backupId,n);return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,content:[{type:`text`,text:JSON.stringify(e,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}let i=await t.sendCommand(n,`trigger-backup`,{groupId:r.groupId});return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!i.success,content:[{type:`text`,text:JSON.stringify(i.data||i,null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error managing backup: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}if(n===`shadowclaw_server_status`||n===`shadowclaw_status`)try{let e=await t.listClients();return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,content:[{type:`text`,text:JSON.stringify({server:`ShadowClaw`,version:a.version,connectedClients:e.length,status:`healthy`},null,2)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error querying server status: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}if(n===`shadowclaw_server_send_notification`||n===`shadowclaw_send_notification`||n===`send_notification`){let e=String(r.body||``).trim();if(!e)return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: Notification 'body' parameter cannot be empty.`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}};let n=String(r.title||`ShadowClaw`).trim(),i=typeof r.clientId==`string`&&r.clientId.trim()?r.clientId.trim():void 0;try{let r=await t.broadcastNotification({title:n,body:e,...i?{clientId:i}:{}}),o=r?.sent??0,c=r?.failed??0,l;return l=r?.notFound?`Warning: No push subscriptions found for client '${i}'. Ensure push notifications were registered by this client in ShadowClaw Settings.`:r?.noSubscribers?`Warning: Push notification broadcast completed, but no devices are currently subscribed to push notifications. Ensure push notifications are enabled in ShadowClaw Settings on the client first.`:i?`Push notification sent to client '${i}': ${o} recipient(s) delivered, ${c} failed.`:`Push notification broadcast sent: ${o} recipient(s) delivered, ${c} failed.`,{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!1,content:[{type:`text`,text:l}],_meta:{...r,...i?{targetClientId:i}:{},"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Failed to send push notification: ${e.message}`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}}}}let f=j(n);if((f===`ask_user`||n===`ask_user`)&&o&&o.response)return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,content:[{type:`text`,text:String(o.response)}],_meta:{"io.modelcontextprotocol/serverInfo":a}}};u.size===0&&await d();let p=(l.get(f)||l.get(n)||[]).map(e=>e.clientId||e.id).filter(Boolean),m=``;if(r.clientId)m=await c(r.clientId);else{let e=await c();m=p.includes(e)?e:p.length>0?p[0]:e}if(!m)return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: No connected client available.`}],_meta:{"io.modelcontextprotocol/serverInfo":a}}};if(p.length>0&&!p.includes(m))return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Error: Tool '${n}' is not enabled or available on client '${m}'. (Available on: ${p.join(`, `)})`}],_meta:{clientId:m,"io.modelcontextprotocol/serverInfo":a}}};try{console.error(`[ShadowClaw MCP] Executing '${f}' on client: ${m}`);let e={...r};delete e.clientId;let n=f===`ask_user`?await t.sendCommand(m,`invoke-tool`,{toolName:f,input:e},3e5):await t.sendCommand(m,`invoke-tool`,{toolName:f,input:e}),i=n.data?.result===void 0?n.data:n.data.result,o=typeof i==`string`?i:JSON.stringify(i,null,2),c=n.error||n.data&&n.data.error||`Unknown tool execution error`;return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!n.success,content:[{type:`text`,text:n.success?o||``:o&&o!==`null`&&o!==`{}`?`${o}\n${c}`:`Tool execution error: ${c}`}],_meta:{clientId:m,"io.modelcontextprotocol/serverInfo":a}}}}catch(e){return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,isError:!0,content:[{type:`text`,text:`Tool error: ${e.message}`}],_meta:{clientId:m,"io.modelcontextprotocol/serverInfo":a}}}}}case`tasks/get`:return{jsonrpc:`2.0`,id:s,result:{resultType:`complete`,task:{taskId:e.params?.taskId||`task-1`,status:`completed`},_meta:{"io.modelcontextprotocol/serverInfo":a}}};default:return r?null:{jsonrpc:`2.0`,id:s,error:{code:-32601,message:`Method not found: '${e.method}'`}}}}return{handleMessage:f,getActiveClientId:()=>i,setActiveClientId:e=>{i=e}}}async function z(e={}){if((e.mcpTransport||(e.http?`http`:`stdio`))===`http`){let t=parseInt(String(e.port||x.env.MCP_PORT||`8888`),10),n=e.host||`127.0.0.1`,r=R(e);S.createServer(async(e,t)=>{if(e.method!==`POST`||e.url?.split(`?`)[0]!==`/mcp`){t.writeHead(404,{"Content-Type":`application/json`}),t.end(JSON.stringify({error:`Not found`}));return}let n=``;e.on(`data`,e=>n+=e),e.on(`end`,async()=>{let i;try{i=JSON.parse(n)}catch{t.writeHead(400,{"Content-Type":`application/json`}),t.end(JSON.stringify({jsonrpc:`2.0`,id:null,error:{code:-32700,message:`Parse error`}}));return}try{let n={"mcp-protocol-version":e.headers[`mcp-protocol-version`],"mcp-method":e.headers[`mcp-method`],"mcp-name":e.headers[`mcp-name`]},a=await r.handleMessage(i,n);if(a===null){t.writeHead(202),t.end();return}t.writeHead(200,{"Content-Type":`application/json`,"MCP-Protocol-Version":`2026-07-28`}),t.end(JSON.stringify(a))}catch(e){t.writeHead(500,{"Content-Type":`application/json`}),t.end(JSON.stringify({jsonrpc:`2.0`,id:i?.id??null,error:{code:-32603,message:e?.message||`Internal error`}}))}})}).listen(t,n,()=>{console.error(`[ShadowClaw MCP] HTTP MCP server listening at http://${n}:${t}/mcp (2026-07-28)`)});return}console.log=(...e)=>console.error(...e),console.info=(...e)=>console.error(...e);let t=R(e);C.createInterface({input:x.stdin,output:x.stdout,terminal:!1}).on(`line`,async e=>{let n=e.trim();if(!n)return;let r;try{r=JSON.parse(n)}catch{x.stdout.write(JSON.stringify({jsonrpc:`2.0`,id:null,error:{code:-32700,message:`Parse error`}})+`
2
2
  `);return}try{let e=await t.handleMessage(r);e!==null&&x.stdout.write(JSON.stringify(e)+`
3
3
  `)}catch(e){let t={jsonrpc:`2.0`,id:r?.id??null,error:{code:-32603,message:e?.message||`Internal error`}};x.stdout.write(JSON.stringify(t)+`
4
- `)}}),console.error(`[ShadowClaw MCP] STDIO MCP server active (2026-07-28)`)}const B=e(import.meta.url),V=new Set;function H(e){return typeof e==`function`?(V.add(e),()=>V.delete(e)):()=>!1}let U=!1;const W=(e,t)=>{U&&m.exit(t),U=!0;for(let t of V)try{t(e)}catch{}m.stderr.write(`\nProcess interrupted (${e}).\n`),m.exit(t)};m.on(`SIGINT`,()=>W(`SIGINT`,130)),m.on(`SIGTERM`,()=>W(`SIGTERM`,143)),m.on(`exit`,()=>{for(let e of V)try{e(`exit`)}catch{}});async function G(){try{let e=await _(f.join(B,`package.json`),`utf8`);return JSON.parse(e).version||`1.0.0`}catch{return`1.0.0`}}async function K(e){try{return await v(e),!0}catch{return!1}}function q(e){let t=m.platform===`darwin`?`open`:m.platform===`win32`?`start`:`xdg-open`;try{h(`${t} ${e}`)}catch{}}const J=await G(),Y=new b;Y.name(`shadow-claw`).description(`Browser-native personal AI assistant and static site publisher`).version(J,`-v, --version`,`Output the current version`),Y.commandsGroup(`Development:`),Y.command(`build`).description(`Build the static site bundle for production or staging`).optionsGroup(`Build Mode Options:`).option(`--prod, --production`,`Build in production mode with minification and optimizations`,!1).option(`--prerender-pages <mode>`,`Prerender page mode (all, auto, none)`,`auto`).option(`--copy-all-assets`,`Copy entire assets/ directory into output`,!1).optionsGroup(`Path & Routing Options:`).option(`--origin <url>`,`Canonical origin URL (e.g. https://user.github.io/repo/)`).option(`--base-path <path>`,`URL base path prefix (e.g. /repo/)`).option(`--out-dir <dir>`,`Output directory relative to content root`,`dist/public`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).action(async e=>{try{let t=f.resolve(e.contentRoot||m.cwd()),r=!!(e.prod||e.production||m.env.NODE_ENV===`production`);console.log(`Building ShadowClaw site from ${t}...`),await n({contentRoot:t,toolchainRoot:B,outDir:e.outDir||`dist/public`,isProduction:r,pagesOrigin:e.origin||m.env.PAGES_ORIGIN,basePath:e.basePath||m.env.PAGES_BASE_PATH,prerenderPages:e.prerenderPages,copyAllAssets:e.copyAllAssets})}catch(e){console.error(`Build failed:`,e),m.exit(1)}});async function X(e,t){try{let r=f.resolve(t.contentRoot||m.cwd()),i=parseInt(e||t.port||m.env.PORT||`8888`,10),a=t.host||t.ip||m.env.SHADOWCLAW_DEV_IP||`127.0.0.1`,o=t.outDir||`dist/public`,s=f.resolve(r,o),c=await u({contentRoot:r,cacheDir:t.cacheDir,databaseDir:t.databaseDir,tmp:t.tmp||t.temp,yes:t.yes}),l=c.cacheDir,d=c.databaseDir;console.log(`Preparing ShadowClaw dev build for ${r}...`),await n({contentRoot:r,toolchainRoot:B,outDir:o,isProduction:!1,pagesOrigin:t.origin||m.env.PAGES_ORIGIN,basePath:t.basePath||m.env.PAGES_BASE_PATH,prerenderPages:t.prerenderPages||`auto`,copyAllAssets:t.copyAllAssets});let p=await K(f.join(B,`dist/server.js`))?f.join(B,`dist/server.js`):f.join(B,`src/server/server.ts`);m.env.SHADOWCLAW_ROOT_PATH=s,m.env.SHADOWCLAW_CACHE_DIR=l,m.env.SHADOWCLAW_DATABASE_DIR=d,m.env.SHADOWCLAW_DEV_IP=a;let{startServer:h}=await import(p),g=new Set((t.corsAllowOrigin||m.env.SHADOWCLAW_CORS_ALLOWED_ORIGINS||`https://xt-ml.github.io`).split(`,`).map(e=>e.trim()).filter(Boolean)),_=!!(t.https||[`1`,`true`,`yes`].includes((m.env.SHADOWCLAW_HTTPS||``).toLowerCase().trim())),v=t.cert||(m.env.SHADOWCLAW_TLS_CERT||m.env.SHADOWCLAW_CERT||``).trim()||void 0,y=t.key||(m.env.SHADOWCLAW_TLS_KEY||m.env.SHADOWCLAW_KEY||``).trim()||void 0,b=f.resolve(r,t.sslDir||m.env.SHADOWCLAW_SSL_DIR||m.env.SHADOWCLAW_TLS_DIR||f.join(l,`tls`));await h({port:i,bindHost:a,corsMode:t.corsMode||`localhost`,allowedOrigins:g,verbose:!!t.verbose,peerjs:!!t.peerjs,rootPath:s,cacheDir:l,databaseDir:d,allowPrivateProxy:!!t.allowPrivateProxy,https:_,certPath:v,keyPath:y,sslDir:b});let x=`${_?`https`:`http`}://${a}:${i}`;t.open&&q(x)}catch(e){console.error(`Dev server error:`,e),m.exit(1)}}Y.command(`dev [port]`).description(`Build and launch the development server`).optionsGroup(`Server & Network Options:`).option(`-p, --port <port>`,`Port to listen on (default: 8888)`).option(`--host <host>`,`Bind host/IP`,`127.0.0.1`).option(`--ip <host>`,`Bind host/IP (alias)`).option(`--open`,`Automatically open default browser`,!1).option(`-v, --verbose`,`Enable verbose request/proxy logging`,!1).optionsGroup(`Site & Build Options:`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).option(`--out-dir <dir>`,`Output directory relative to content root`,`dist/public`).optionsGroup(`Security & Proxy Options:`).option(`--cors-mode <mode>`,`CORS policy: localhost | private | all`,`localhost`).option(`--allow-private-proxy`,`Allow proxy to reach private/loopback addresses`,!1).option(`--peerjs`,`Enable built-in PeerJS signaling server`,!1).optionsGroup(`TLS / HTTPS Options:`).option(`--https`,`Enable HTTPS dev server`,!1).option(`--cert <path>`,`Path to existing TLS certificate file`).option(`--key <path>`,`Path to existing TLS private key file`).option(`--ssl-dir <path>`,`Directory for TLS certificate generation/storage`).optionsGroup(`Storage & Database Options:`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases, tokens, and logs`).option(`--tmp, --temp`,`Store cache and databases in system temporary directory`,!1).option(`-y, --yes`,`Skip interactive cache directory prompt and use default .cache`,!1).action(X),Y.command(`run [port]`).description(`Alias for dev: build and launch the development server`).optionsGroup(`Server & Network Options:`).option(`-p, --port <port>`,`Port to listen on (default: 8888)`).option(`--host <host>`,`Bind host/IP`,`127.0.0.1`).option(`--ip <host>`,`Bind host/IP (alias)`).option(`--open`,`Automatically open default browser`,!1).option(`-v, --verbose`,`Enable verbose request/proxy logging`,!1).optionsGroup(`Site & Build Options:`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).option(`--out-dir <dir>`,`Output directory relative to content root`,`dist/public`).optionsGroup(`Security & Proxy Options:`).option(`--cors-mode <mode>`,`CORS policy: localhost | private | all`,`localhost`).option(`--allow-private-proxy`,`Allow proxy to reach private/loopback addresses`,!1).option(`--peerjs`,`Enable built-in PeerJS signaling server`,!1).optionsGroup(`TLS / HTTPS Options:`).option(`--https`,`Enable HTTPS dev server`,!1).option(`--cert <path>`,`Path to existing TLS certificate file`).option(`--key <path>`,`Path to existing TLS private key file`).option(`--ssl-dir <path>`,`Directory for TLS certificate generation/storage`).optionsGroup(`Storage & Database Options:`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases, tokens, and logs`).option(`--tmp, --temp`,`Store cache and databases in system temporary directory`,!1).option(`-y, --yes`,`Skip interactive cache directory prompt and use default .cache`,!1).action(X),Y.commandsGroup(`Server:`),Y.command(`serve [port]`).description(`Serve an existing static site build and start the backend proxy`).optionsGroup(`Server & Network Options:`).option(`-p, --port <port>`,`Port to listen on (default: 8888)`).option(`--host <host>`,`Bind host/IP`,`127.0.0.1`).option(`--no-static`,`Disable static file and UI serving (services-only mode)`).option(`--open`,`Automatically open default browser`,!1).option(`-v, --verbose`,`Enable verbose request/proxy logging`,!1).optionsGroup(`Site Options:`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).option(`--out-dir <dir>`,`Output directory relative to content root`,`dist/public`).optionsGroup(`Security & Proxy Options:`).option(`--cors-mode <mode>`,`CORS policy: localhost | private | all`,`localhost`).option(`--allow-private-proxy`,`Allow proxy to reach private/loopback addresses`,!1).option(`--peerjs`,`Enable built-in PeerJS signaling server`,!1).optionsGroup(`TLS / HTTPS Options:`).option(`--https`,`Enable HTTPS dev server`,!1).option(`--cert <path>`,`Path to existing TLS certificate file`).option(`--key <path>`,`Path to existing TLS private key file`).option(`--ssl-dir <path>`,`Directory for TLS certificate generation/storage`).optionsGroup(`Storage & Database Options:`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases, tokens, and logs`).option(`--tmp, --temp`,`Store cache and databases in system temporary directory`,!1).option(`-y, --yes`,`Skip interactive cache directory prompt and use default .cache`,!1).action(async(e,t)=>{try{let n=f.resolve(t.contentRoot||m.cwd()),r=parseInt(e||t.port||m.env.PORT||`8888`,10),i=t.host||t.ip||m.env.SHADOWCLAW_DEV_IP||`127.0.0.1`,a=t.outDir||`dist/public`,o=f.resolve(n,a),s=await u({contentRoot:n,cacheDir:t.cacheDir,databaseDir:t.databaseDir,tmp:t.tmp||t.temp,yes:t.yes}),c=s.cacheDir,l=s.databaseDir,d=t.static!==!1;d&&!await K(f.join(o,`index.html`))&&(console.error(`Error: No index.html found in ${o}. Run "shadow-claw build" first.`),m.exit(1));let p=await K(f.join(B,`dist/server.js`))?f.join(B,`dist/server.js`):f.join(B,`src/server/server.ts`);m.env.SHADOWCLAW_ROOT_PATH=o,m.env.SHADOWCLAW_CACHE_DIR=c,m.env.SHADOWCLAW_DATABASE_DIR=l,m.env.SHADOWCLAW_DEV_IP=i;let{startServer:h}=await import(p),g=new Set((t.corsAllowOrigin||m.env.SHADOWCLAW_CORS_ALLOWED_ORIGINS||`https://xt-ml.github.io`).split(`,`).map(e=>e.trim()).filter(Boolean)),_=!!(t.https||[`1`,`true`,`yes`].includes((m.env.SHADOWCLAW_HTTPS||``).toLowerCase().trim())),v=t.cert||(m.env.SHADOWCLAW_TLS_CERT||m.env.SHADOWCLAW_CERT||``).trim()||void 0,y=t.key||(m.env.SHADOWCLAW_TLS_KEY||m.env.SHADOWCLAW_KEY||``).trim()||void 0,b=f.resolve(n,t.sslDir||m.env.SHADOWCLAW_SSL_DIR||m.env.SHADOWCLAW_TLS_DIR||f.join(c,`tls`));await h({port:r,bindHost:i,corsMode:t.corsMode||`localhost`,allowedOrigins:g,verbose:!!t.verbose,peerjs:!!t.peerjs,rootPath:o,cacheDir:c,databaseDir:l,allowPrivateProxy:!!t.allowPrivateProxy,https:_,certPath:v,keyPath:y,sslDir:b,serveStatic:d});let x=`${_?`https`:`http`}://${i}:${r}`;d&&t.open&&q(x)}catch(e){console.error(`Serve error:`,e),m.exit(1)}});async function Z(e,t){try{let n=f.resolve(t.contentRoot||m.cwd()),r=parseInt(e||t.port||m.env.PORT||`8888`,10),i=t.host||t.ip||m.env.SHADOWCLAW_DEV_IP||`127.0.0.1`,a=await u({contentRoot:n,cacheDir:t.cacheDir,databaseDir:t.databaseDir,tmp:t.tmp||t.temp,yes:t.yes}),o=a.cacheDir,s=a.databaseDir,c=await K(f.join(B,`dist/server.js`))?f.join(B,`dist/server.js`):f.join(B,`src/server/server.ts`);m.env.SHADOWCLAW_CACHE_DIR=o,m.env.SHADOWCLAW_DATABASE_DIR=s,m.env.SHADOWCLAW_DEV_IP=i,m.env.SHADOWCLAW_SERVE_STATIC=`false`;let{startServer:l}=await import(c),d=new Set((t.corsAllowOrigin||m.env.SHADOWCLAW_CORS_ALLOWED_ORIGINS||`https://xt-ml.github.io`).split(`,`).map(e=>e.trim()).filter(Boolean)),p=!!(t.https||[`1`,`true`,`yes`].includes((m.env.SHADOWCLAW_HTTPS||``).toLowerCase().trim())),h=t.cert||(m.env.SHADOWCLAW_TLS_CERT||m.env.SHADOWCLAW_CERT||``).trim()||void 0,g=t.key||(m.env.SHADOWCLAW_TLS_KEY||m.env.SHADOWCLAW_KEY||``).trim()||void 0,_=f.resolve(n,t.sslDir||m.env.SHADOWCLAW_SSL_DIR||m.env.SHADOWCLAW_TLS_DIR||f.join(o,`tls`));await l({port:r,bindHost:i,corsMode:t.corsMode||`localhost`,allowedOrigins:d,verbose:!!t.verbose,peerjs:!!t.peerjs,rootPath:``,cacheDir:o,databaseDir:s,controlToken:t.controlToken||m.env.SHADOWCLAW_CONTROL_TOKEN||void 0,allowPrivateProxy:!!t.allowPrivateProxy,https:p,certPath:h,keyPath:g,sslDir:_,serveStatic:!1})}catch(e){console.error(`Server error:`,e),m.exit(1)}}Y.command(`server [port]`).aliases([`services`,`api`]).description(`Start backend services (Express, MCP, control plane) without building or serving the UI (aliases: services, api)`).optionsGroup(`Server & Network Options:`).option(`-p, --port <port>`,`Port to listen on (default: 8888)`).option(`--host <host>`,`Bind host/IP`,`127.0.0.1`).option(`--ip <host>`,`Bind host/IP (alias)`).option(`-v, --verbose`,`Enable verbose request/proxy logging`,!1).optionsGroup(`Security & Proxy Options:`).option(`--cors-mode <mode>`,`CORS policy: localhost | private | all`,`localhost`).option(`--cors-allow-origin <origin>`,`Explicit allowed origins (comma-separated)`).option(`--control-token <token>`,`Secret token for control-plane authentication`).option(`--peerjs`,`Enable built-in PeerJS signaling server`,!1).option(`--allow-private-proxy`,`Allow proxy to reach private/loopback addresses`,!1).optionsGroup(`TLS / HTTPS Options:`).option(`--https`,`Enable HTTPS server`,!1).option(`--cert <path>`,`Path to existing TLS certificate file`).option(`--key <path>`,`Path to existing TLS private key file`).option(`--ssl-dir <path>`,`Directory for TLS certificate generation/storage`).optionsGroup(`Storage & Database Options:`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases, tokens, and logs`).option(`--tmp, --temp`,`Store cache and databases in system temporary directory`,!1).option(`-y, --yes`,`Skip interactive cache directory prompt and use default .cache`,!1).action(Z),Y.command(`mcp`).description(`Run the official Stateless Model Context Protocol (MCP 2026-07-28) server`).optionsGroup(`MCP Protocol Options:`).option(`--mcp-transport <transport>`,`MCP transport: stdio | http`,`stdio`).option(`--relay-client-tools`,`Discover and relay tools from connected browser clients`,!0).option(`--no-relay-client-tools`,`Disable relaying browser client tools`).optionsGroup(`Target Client Options:`).option(`--client <id>`,`Target client ID (defaults to first active client)`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port or HTTP MCP port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Control plane client transport: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--cache-dir <dir>`,`Custom cache directory for control token and databases`).action(async e=>{await z(e)}),Y.commandsGroup(`Control Plane & Client Bridge:`),Y.command(`clients`).description(`List connected / registered browser and Electron clients`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before connecting`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).action(async e=>{await w(e)}),Y.command(`send <message>`).description(`Send a message/prompt to a connected client or peer agent`).optionsGroup(`Target Options:`).option(`--client <id>`,`Target client ID (defaults to first available)`).option(`--group <groupId>`,`Target conversation group ID`).option(`-f, --file <path>`,`Attach a local file to send with the message`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before sending`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).option(`--timeout <seconds>`,`Timeout in seconds to wait for response`,`120`).option(`--json`,`Output response payload as JSON`,!1).action(async(e,t)=>{await T(e,t)}),Y.command(`send-file <file>`).description(`Transfer a file to a connected peer or client over WebRTC or HTTP`).optionsGroup(`Target Options:`).option(`--client <id>`,`Target client ID (defaults to first available)`).option(`--prompt <prompt>`,`Accompanying prompt or instructions for the receiving agent`).option(`--name <fileName>`,`Override remote file name`).option(`--group <groupId>`,`Target conversation group ID`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`webrtc`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before sending`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).option(`--timeout <seconds>`,`Transfer and execution timeout in seconds`,`120`).option(`--json`,`Output response payload as JSON`,!1).action(async(e,t)=>{await E(e,t)}),Y.command(`tasks`).description(`List scheduled tasks on a connected client`).optionsGroup(`Target Options:`).option(`--client <id>`,`Target client ID`).option(`--group <groupId>`,`Filter tasks by conversation group ID`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before connecting`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).action(async e=>{await O(e)}),Y.command(`backup [action]`).description(`Trigger or manage client workspace backups (trigger | list | delete)`).optionsGroup(`Target Options:`).option(`--client <id>`,`Client ID`).option(`--backup-id <id>`,`Backup ID (for delete)`).option(`--group <groupId>`,`Specific workspace group ID`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before connecting`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).action(async(e,t)=>{await D(e||`trigger`,t)}),Y.commandsGroup(`WebRTC:`),Y.command(`webrtc [action] [customId]`).summary(`Manage WebRTC CLI configuration and peer identity (.cache/cli-peer-id)`).description(`Manage WebRTC CLI configuration and peer identity (.cache/cli-peer-id)
4
+ `)}}),console.error(`[ShadowClaw MCP] STDIO MCP server active (2026-07-28)`)}const B=e(import.meta.url),V=new Set;function H(e){return typeof e==`function`?(V.add(e),()=>V.delete(e)):()=>!1}let U=!1;const W=(e,t)=>{U&&m.exit(t),U=!0;for(let t of V)try{t(e)}catch{}m.stderr.write(`\nProcess interrupted (${e}).\n`),m.exit(t)};m.on(`SIGINT`,()=>W(`SIGINT`,130)),m.on(`SIGTERM`,()=>W(`SIGTERM`,143)),m.on(`exit`,()=>{for(let e of V)try{e(`exit`)}catch{}});async function G(){try{let e=await _(f.join(B,`package.json`),`utf8`);return JSON.parse(e).version||`1.0.0`}catch{return`1.0.0`}}async function K(e){try{return await v(e),!0}catch{return!1}}function q(e){return!!(e.a2a||[`1`,`true`,`yes`].includes((m.env.SHADOWCLAW_A2A||``).toLowerCase().trim()))}function J(e){let t=m.platform===`darwin`?`open`:m.platform===`win32`?`start`:`xdg-open`;try{h(`${t} ${e}`)}catch{}}const Y=await G(),X=new b;X.name(`shadow-claw`).description(`Browser-native personal AI assistant and static site publisher`).version(Y,`-v, --version`,`Output the current version`),X.commandsGroup(`Development:`),X.command(`build`).description(`Build the static site bundle for production or staging`).optionsGroup(`Build Mode Options:`).option(`--prod, --production`,`Build in production mode with minification and optimizations`,!1).option(`--prerender-pages <mode>`,`Prerender page mode (all, auto, none)`,`auto`).option(`--copy-all-assets`,`Copy entire assets/ directory into output`,!1).optionsGroup(`Path & Routing Options:`).option(`--origin <url>`,`Canonical origin URL (e.g. https://user.github.io/repo/)`).option(`--base-path <path>`,`URL base path prefix (e.g. /repo/)`).option(`--out-dir <dir>`,`Output directory relative to content root`,`dist/public`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).action(async e=>{try{let t=f.resolve(e.contentRoot||m.cwd()),r=!!(e.prod||e.production||m.env.NODE_ENV===`production`);console.log(`Building ShadowClaw site from ${t}...`),await n({contentRoot:t,toolchainRoot:B,outDir:e.outDir||`dist/public`,isProduction:r,pagesOrigin:e.origin||m.env.PAGES_ORIGIN,basePath:e.basePath||m.env.PAGES_BASE_PATH,prerenderPages:e.prerenderPages,copyAllAssets:e.copyAllAssets})}catch(e){console.error(`Build failed:`,e),m.exit(1)}});async function Z(e,t){try{let r=f.resolve(t.contentRoot||m.cwd()),i=parseInt(e||t.port||m.env.PORT||`8888`,10),a=t.host||t.ip||m.env.SHADOWCLAW_DEV_IP||`127.0.0.1`,o=t.outDir||`dist/public`,s=f.resolve(r,o),c=await u({contentRoot:r,cacheDir:t.cacheDir,databaseDir:t.databaseDir,tmp:t.tmp||t.temp,yes:t.yes}),l=c.cacheDir,d=c.databaseDir;console.log(`Preparing ShadowClaw dev build for ${r}...`),await n({contentRoot:r,toolchainRoot:B,outDir:o,isProduction:!1,pagesOrigin:t.origin||m.env.PAGES_ORIGIN,basePath:t.basePath||m.env.PAGES_BASE_PATH,prerenderPages:t.prerenderPages||`auto`,copyAllAssets:t.copyAllAssets});let p=await K(f.join(B,`dist/server.js`))?f.join(B,`dist/server.js`):f.join(B,`src/server/server.ts`);m.env.SHADOWCLAW_ROOT_PATH=s,m.env.SHADOWCLAW_CACHE_DIR=l,m.env.SHADOWCLAW_DATABASE_DIR=d,m.env.SHADOWCLAW_DEV_IP=a;let{startServer:h}=await import(p),g=new Set((t.corsAllowOrigin||m.env.SHADOWCLAW_CORS_ALLOWED_ORIGINS||`https://xt-ml.github.io`).split(`,`).map(e=>e.trim()).filter(Boolean)),_=!!(t.https||[`1`,`true`,`yes`].includes((m.env.SHADOWCLAW_HTTPS||``).toLowerCase().trim())),v=t.cert||(m.env.SHADOWCLAW_TLS_CERT||m.env.SHADOWCLAW_CERT||``).trim()||void 0,y=t.key||(m.env.SHADOWCLAW_TLS_KEY||m.env.SHADOWCLAW_KEY||``).trim()||void 0,b=f.resolve(r,t.sslDir||m.env.SHADOWCLAW_SSL_DIR||m.env.SHADOWCLAW_TLS_DIR||f.join(l,`tls`));await h({port:i,bindHost:a,corsMode:t.corsMode||`localhost`,allowedOrigins:g,verbose:!!t.verbose,peerjs:!!t.peerjs,a2aEnabled:q(t),rootPath:s,cacheDir:l,databaseDir:d,allowPrivateProxy:!!t.allowPrivateProxy,https:_,certPath:v,keyPath:y,sslDir:b});let x=`${_?`https`:`http`}://${a}:${i}`;t.open&&J(x)}catch(e){console.error(`Dev server error:`,e),m.exit(1)}}X.command(`dev [port]`).description(`Build and launch the development server`).optionsGroup(`Server & Network Options:`).option(`-p, --port <port>`,`Port to listen on (default: 8888)`).option(`--host <host>`,`Bind host/IP`,`127.0.0.1`).option(`--ip <host>`,`Bind host/IP (alias)`).option(`--open`,`Automatically open default browser`,!1).option(`-v, --verbose`,`Enable verbose request/proxy logging`,!1).optionsGroup(`Site & Build Options:`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).option(`--out-dir <dir>`,`Output directory relative to content root`,`dist/public`).optionsGroup(`Security & Proxy Options:`).option(`--cors-mode <mode>`,`CORS policy: localhost | private | all`,`localhost`).option(`--allow-private-proxy`,`Allow proxy to reach private/loopback addresses`,!1).option(`--peerjs`,`Enable built-in PeerJS signaling server`,!1).option(`--a2a`,`Enable A2A v1.0 agent card, JSON-RPC, and SSE endpoints`,!1).optionsGroup(`TLS / HTTPS Options:`).option(`--https`,`Enable HTTPS dev server`,!1).option(`--cert <path>`,`Path to existing TLS certificate file`).option(`--key <path>`,`Path to existing TLS private key file`).option(`--ssl-dir <path>`,`Directory for TLS certificate generation/storage`).optionsGroup(`Storage & Database Options:`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases, tokens, and logs`).option(`--tmp, --temp`,`Store cache and databases in system temporary directory`,!1).option(`-y, --yes`,`Skip interactive cache directory prompt and use default .cache`,!1).action(Z),X.command(`run [port]`).description(`Alias for dev: build and launch the development server`).optionsGroup(`Server & Network Options:`).option(`-p, --port <port>`,`Port to listen on (default: 8888)`).option(`--host <host>`,`Bind host/IP`,`127.0.0.1`).option(`--ip <host>`,`Bind host/IP (alias)`).option(`--open`,`Automatically open default browser`,!1).option(`-v, --verbose`,`Enable verbose request/proxy logging`,!1).optionsGroup(`Site & Build Options:`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).option(`--out-dir <dir>`,`Output directory relative to content root`,`dist/public`).optionsGroup(`Security & Proxy Options:`).option(`--cors-mode <mode>`,`CORS policy: localhost | private | all`,`localhost`).option(`--allow-private-proxy`,`Allow proxy to reach private/loopback addresses`,!1).option(`--peerjs`,`Enable built-in PeerJS signaling server`,!1).option(`--a2a`,`Enable A2A v1.0 agent card, JSON-RPC, and SSE endpoints`,!1).optionsGroup(`TLS / HTTPS Options:`).option(`--https`,`Enable HTTPS dev server`,!1).option(`--cert <path>`,`Path to existing TLS certificate file`).option(`--key <path>`,`Path to existing TLS private key file`).option(`--ssl-dir <path>`,`Directory for TLS certificate generation/storage`).optionsGroup(`Storage & Database Options:`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases, tokens, and logs`).option(`--tmp, --temp`,`Store cache and databases in system temporary directory`,!1).option(`-y, --yes`,`Skip interactive cache directory prompt and use default .cache`,!1).action(Z),X.commandsGroup(`Server:`),X.command(`serve [port]`).description(`Serve static files and start backend services (optional: --peerjs, --a2a)`).optionsGroup(`Server & Network Options:`).option(`-p, --port <port>`,`Port to listen on (default: 8888)`).option(`--host <host>`,`Bind host/IP`,`127.0.0.1`).option(`--no-static`,`Disable static file and UI serving (services-only mode)`).option(`--open`,`Automatically open default browser`,!1).option(`-v, --verbose`,`Enable verbose request/proxy logging`,!1).optionsGroup(`Site Options:`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).option(`--out-dir <dir>`,`Output directory relative to content root`,`dist/public`).optionsGroup(`Security & Proxy Options:`).option(`--cors-mode <mode>`,`CORS policy: localhost | private | all`,`localhost`).option(`--allow-private-proxy`,`Allow proxy to reach private/loopback addresses`,!1).option(`--peerjs`,`Enable built-in PeerJS signaling server`,!1).option(`--a2a`,`Enable A2A v1.0 agent card, JSON-RPC, and SSE endpoints`,!1).optionsGroup(`TLS / HTTPS Options:`).option(`--https`,`Enable HTTPS dev server`,!1).option(`--cert <path>`,`Path to existing TLS certificate file`).option(`--key <path>`,`Path to existing TLS private key file`).option(`--ssl-dir <path>`,`Directory for TLS certificate generation/storage`).optionsGroup(`Storage & Database Options:`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases, tokens, and logs`).option(`--tmp, --temp`,`Store cache and databases in system temporary directory`,!1).option(`-y, --yes`,`Skip interactive cache directory prompt and use default .cache`,!1).action(async(e,t)=>{try{let n=f.resolve(t.contentRoot||m.cwd()),r=parseInt(e||t.port||m.env.PORT||`8888`,10),i=t.host||t.ip||m.env.SHADOWCLAW_DEV_IP||`127.0.0.1`,a=t.outDir||`dist/public`,o=f.resolve(n,a),s=await u({contentRoot:n,cacheDir:t.cacheDir,databaseDir:t.databaseDir,tmp:t.tmp||t.temp,yes:t.yes}),c=s.cacheDir,l=s.databaseDir,d=t.static!==!1;d&&!await K(f.join(o,`index.html`))&&(console.error(`Error: No index.html found in ${o}. Run "shadow-claw build" first.`),m.exit(1));let p=await K(f.join(B,`dist/server.js`))?f.join(B,`dist/server.js`):f.join(B,`src/server/server.ts`);m.env.SHADOWCLAW_ROOT_PATH=o,m.env.SHADOWCLAW_CACHE_DIR=c,m.env.SHADOWCLAW_DATABASE_DIR=l,m.env.SHADOWCLAW_DEV_IP=i;let{startServer:h}=await import(p),g=new Set((t.corsAllowOrigin||m.env.SHADOWCLAW_CORS_ALLOWED_ORIGINS||`https://xt-ml.github.io`).split(`,`).map(e=>e.trim()).filter(Boolean)),_=!!(t.https||[`1`,`true`,`yes`].includes((m.env.SHADOWCLAW_HTTPS||``).toLowerCase().trim())),v=t.cert||(m.env.SHADOWCLAW_TLS_CERT||m.env.SHADOWCLAW_CERT||``).trim()||void 0,y=t.key||(m.env.SHADOWCLAW_TLS_KEY||m.env.SHADOWCLAW_KEY||``).trim()||void 0,b=f.resolve(n,t.sslDir||m.env.SHADOWCLAW_SSL_DIR||m.env.SHADOWCLAW_TLS_DIR||f.join(c,`tls`));await h({port:r,bindHost:i,corsMode:t.corsMode||`localhost`,allowedOrigins:g,verbose:!!t.verbose,peerjs:!!t.peerjs,a2aEnabled:q(t),rootPath:o,cacheDir:c,databaseDir:l,allowPrivateProxy:!!t.allowPrivateProxy,https:_,certPath:v,keyPath:y,sslDir:b,serveStatic:d});let x=`${_?`https`:`http`}://${i}:${r}`;d&&t.open&&J(x)}catch(e){console.error(`Serve error:`,e),m.exit(1)}});async function Q(e,t){try{let n=f.resolve(t.contentRoot||m.cwd()),r=parseInt(e||t.port||m.env.PORT||`8888`,10),i=t.host||t.ip||m.env.SHADOWCLAW_DEV_IP||`127.0.0.1`,a=await u({contentRoot:n,cacheDir:t.cacheDir,databaseDir:t.databaseDir,tmp:t.tmp||t.temp,yes:t.yes}),o=a.cacheDir,s=a.databaseDir,c=await K(f.join(B,`dist/server.js`))?f.join(B,`dist/server.js`):f.join(B,`src/server/server.ts`);m.env.SHADOWCLAW_CACHE_DIR=o,m.env.SHADOWCLAW_DATABASE_DIR=s,m.env.SHADOWCLAW_DEV_IP=i,m.env.SHADOWCLAW_SERVE_STATIC=`false`;let{startServer:l}=await import(c),d=new Set((t.corsAllowOrigin||m.env.SHADOWCLAW_CORS_ALLOWED_ORIGINS||`https://xt-ml.github.io`).split(`,`).map(e=>e.trim()).filter(Boolean)),p=!!(t.https||[`1`,`true`,`yes`].includes((m.env.SHADOWCLAW_HTTPS||``).toLowerCase().trim())),h=t.cert||(m.env.SHADOWCLAW_TLS_CERT||m.env.SHADOWCLAW_CERT||``).trim()||void 0,g=t.key||(m.env.SHADOWCLAW_TLS_KEY||m.env.SHADOWCLAW_KEY||``).trim()||void 0,_=f.resolve(n,t.sslDir||m.env.SHADOWCLAW_SSL_DIR||m.env.SHADOWCLAW_TLS_DIR||f.join(o,`tls`));await l({port:r,bindHost:i,corsMode:t.corsMode||`localhost`,allowedOrigins:d,verbose:!!t.verbose,peerjs:!!t.peerjs,a2aEnabled:q(t),rootPath:``,cacheDir:o,databaseDir:s,controlToken:t.controlToken||m.env.SHADOWCLAW_CONTROL_TOKEN||void 0,allowPrivateProxy:!!t.allowPrivateProxy,https:p,certPath:h,keyPath:g,sslDir:_,serveStatic:!1})}catch(e){console.error(`Server error:`,e),m.exit(1)}}X.command(`server [port]`).aliases([`services`,`api`]).description(`Start backend services (HTTP MCP, control plane, scheduler, and proxy) without serving static files (optional: --peerjs, --a2a; aliases: services, api)`).optionsGroup(`Server & Network Options:`).option(`-p, --port <port>`,`Port to listen on (default: 8888)`).option(`--host <host>`,`Bind host/IP`,`127.0.0.1`).option(`--ip <host>`,`Bind host/IP (alias)`).option(`-v, --verbose`,`Enable verbose request/proxy logging`,!1).optionsGroup(`Security & Proxy Options:`).option(`--cors-mode <mode>`,`CORS policy: localhost | private | all`,`localhost`).option(`--cors-allow-origin <origin>`,`Explicit allowed origins (comma-separated)`).option(`--control-token <token>`,`Secret token for control-plane authentication`).option(`--peerjs`,`Enable built-in PeerJS signaling server`,!1).option(`--a2a`,`Enable A2A v1.0 agent card, JSON-RPC, and SSE endpoints`,!1).option(`--allow-private-proxy`,`Allow proxy to reach private/loopback addresses`,!1).optionsGroup(`TLS / HTTPS Options:`).option(`--https`,`Enable HTTPS server`,!1).option(`--cert <path>`,`Path to existing TLS certificate file`).option(`--key <path>`,`Path to existing TLS private key file`).option(`--ssl-dir <path>`,`Directory for TLS certificate generation/storage`).optionsGroup(`Storage & Database Options:`).option(`--content-root <dir>`,`Content root directory`,m.cwd()).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases, tokens, and logs`).option(`--tmp, --temp`,`Store cache and databases in system temporary directory`,!1).option(`-y, --yes`,`Skip interactive cache directory prompt and use default .cache`,!1).action(Q),X.command(`mcp`).description(`Start the standalone MCP server only (does not start backend services, PeerJS, or A2A)`).optionsGroup(`MCP Protocol Options:`).option(`--mcp-transport <transport>`,`MCP transport: stdio | http`,`stdio`).option(`--relay-client-tools`,`Discover and relay tools from connected browser clients`,!0).option(`--no-relay-client-tools`,`Disable relaying browser client tools`).optionsGroup(`Target Client Options:`).option(`--client <id>`,`Target client ID (defaults to first active client)`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port or HTTP MCP port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Control plane client transport: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--cache-dir <dir>`,`Custom cache directory for control token and databases`).action(async e=>{await z(e)}),X.commandsGroup(`Control Plane & Client Bridge:`),X.command(`clients`).description(`List connected / registered browser and Electron clients`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before connecting`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).action(async e=>{await w(e)}),X.command(`send <message>`).description(`Send a message/prompt to a connected client or peer agent`).optionsGroup(`Target Options:`).option(`--client <id>`,`Target client ID (defaults to first available)`).option(`--group <groupId>`,`Target conversation group ID`).option(`-f, --file <path>`,`Attach a local file to send with the message`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before sending`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).option(`--timeout <seconds>`,`Timeout in seconds to wait for response`,`120`).option(`--json`,`Output response payload as JSON`,!1).action(async(e,t)=>{await T(e,t)}),X.command(`send-file <file>`).description(`Transfer a file to a connected peer or client over WebRTC or HTTP`).optionsGroup(`Target Options:`).option(`--client <id>`,`Target client ID (defaults to first available)`).option(`--prompt <prompt>`,`Accompanying prompt or instructions for the receiving agent`).option(`--name <fileName>`,`Override remote file name`).option(`--group <groupId>`,`Target conversation group ID`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`webrtc`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before sending`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).option(`--timeout <seconds>`,`Transfer and execution timeout in seconds`,`120`).option(`--json`,`Output response payload as JSON`,!1).action(async(e,t)=>{await E(e,t)}),X.command(`tasks`).description(`List scheduled tasks on a connected client`).optionsGroup(`Target Options:`).option(`--client <id>`,`Target client ID`).option(`--group <groupId>`,`Filter tasks by conversation group ID`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before connecting`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).action(async e=>{await O(e)}),X.command(`backup [action]`).description(`Trigger or manage client workspace backups (trigger | list | delete)`).optionsGroup(`Target Options:`).option(`--client <id>`,`Client ID`).option(`--backup-id <id>`,`Backup ID (for delete)`).option(`--group <groupId>`,`Specific workspace group ID`).optionsGroup(`Control Plane Connection Options:`).option(`--host <host>`,`Control plane host`).option(`--port <port>`,`Control plane port`).option(`--token <token>`,`Control token`).option(`--https`,`Connect to server via HTTPS`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates`,!0).optionsGroup(`Transport & Peer Options:`).option(`--transport <transport>`,`Transport to use: http | webrtc`,`http`).option(`--peer-id <id>`,`Custom WebRTC CLI peer ID`).option(`--renew-peer-id`,`Renew WebRTC CLI peer ID before connecting`,!1).option(`--cache-dir <dir>`,`Custom cache directory`).action(async(e,t)=>{await D(e||`trigger`,t)}),X.commandsGroup(`WebRTC:`),X.command(`webrtc [action] [customId]`).summary(`Manage WebRTC CLI configuration and peer identity (.cache/cli-peer-id)`).description(`Manage WebRTC CLI configuration and peer identity (.cache/cli-peer-id)
5
5
 
6
6
  Actions:
7
7
  (default) Show or generate the CLI peer ID
8
8
  listen Register as a live PeerJS peer — browser tabs can then
9
- connect directly without a control-plane connection`).optionsGroup(`Identity Options:`).option(`-r, --renew`,`Force renewal / generation of a new WebRTC CLI peer ID`).option(`--set <id>`,`Set a specific custom WebRTC CLI peer ID`).option(`--cache-dir <dir>`,`Custom cache directory (defaults to .cache)`).option(`-q, --quiet`,`Output only the peer ID string`).option(`--json`,`Output peer ID and file path as JSON`).optionsGroup(`Signaling & Listener Options (for listen action):`).option(`--host <host>`,`PeerJS signaling server host (for listen)`).option(`--port <port>`,`PeerJS signaling server port (for listen)`,`8888`).option(`--path <path>`,`PeerJS signaling server path (for listen)`,`/`).option(`--secure`,`Use TLS (wss://) for the signaling server (for listen)`,!1).option(`--https`,`Alias for --secure: use TLS (wss://) for the signaling server`,!1).option(`--trusted-peer <id>`,`Accept connections only from this peer ID (repeatable, for listen)`,(e,t)=>t?[...t,e]:[e],[]).option(`--verbose`,`Verbose connection logging (for listen)`,!1).option(`--renew-peer-id`,`Renew CLI peer ID before listening`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates for the signaling server (wss://)`,!0).optionsGroup(`Agent & Orchestration Options (for listen action):`).option(`--agent`,`Enable agent orchestration loop for incoming prompts (default: true)`,!0).option(`--no-agent`,`Disable agent orchestration loop for incoming prompts`).option(`--model <model>`,`Model name for the listening agent`).option(`--provider <provider>`,`LLM provider ID for the listening agent`).option(`--api-key <key>`,`API key for the listening agent`).option(`--system-prompt <text>`,`Override system prompt for the listening agent`).option(`--system-prompt-file <file>`,`Load system prompt from file for the listening agent`).option(`--tools <tools>`,`Comma-separated list of tools to enable for the listening agent`).option(`--workspace <dir>`,`Workspace directory for the listening agent`).option(`--transfers-dir <dir>`,`Directory to store received files`).option(`--allow-internet`,`Allow internet access for bash and javascript tools`).action(async(e,t,n)=>{if(e===`listen`){await c(n);return}let r={...n};t&&!r.set&&(r.set=t),await k(e,r)}),Y.command(`peer-id [action] [customId]`).alias(`webrtc-peer-id`).description(`Get, generate, or renew the WebRTC CLI peer ID stored in .cache/cli-peer-id`).optionsGroup(`Identity Options:`).option(`-r, --renew`,`Force renewal / generation of a new WebRTC CLI peer ID`).option(`--set <id>`,`Set a specific custom WebRTC CLI peer ID`).option(`--cache-dir <dir>`,`Custom cache directory (defaults to .cache)`).option(`-q, --quiet`,`Output only the peer ID string`).option(`--json`,`Output peer ID and file path as JSON`).action(async(e,t,n)=>{let r={...n};t&&!r.set&&(r.set=t),await k(e,r)}),Y.commandsGroup(`Project:`),Y.command(`init [dir]`).description(`Initialize a new ShadowClaw content template in the specified directory`).action(async e=>{try{let t=f.resolve(e||m.cwd());await g(f.join(t,`pages/main`),{recursive:!0});let n=f.join(t,`shadow-claw-config.json`),r=f.join(t,`shadow-claw.config.json`),i=f.join(t,`site-config.json`);!await K(n)&&!await K(r)&&!await K(i)&&(await y(n,JSON.stringify({$schema:`https://json-schema.org/draft/2020-12/schema`,site:{title:`My ShadowClaw Site`,description:`Personal AI assistant and knowledge hub powered by ShadowClaw.`},branding:{titleText:`My ShadowClaw Site`},pages:{sortOrder:`asc`,defaultPinnedPage:`/pages/main/index.html`}},null,2)+`
9
+ connect directly without a control-plane connection`).optionsGroup(`Identity Options:`).option(`-r, --renew`,`Force renewal / generation of a new WebRTC CLI peer ID`).option(`--set <id>`,`Set a specific custom WebRTC CLI peer ID`).option(`--cache-dir <dir>`,`Custom cache directory (defaults to .cache)`).option(`-q, --quiet`,`Output only the peer ID string`).option(`--json`,`Output peer ID and file path as JSON`).optionsGroup(`Signaling & Listener Options (for listen action):`).option(`--host <host>`,`PeerJS signaling server host (for listen)`).option(`--port <port>`,`PeerJS signaling server port (for listen)`,`8888`).option(`--path <path>`,`PeerJS signaling server path (for listen)`,`/`).option(`--secure`,`Use TLS (wss://) for the signaling server (for listen)`,!1).option(`--https`,`Alias for --secure: use TLS (wss://) for the signaling server`,!1).option(`--trusted-peer <id>`,`Accept connections only from this peer ID (repeatable, for listen)`,(e,t)=>t?[...t,e]:[e],[]).option(`--verbose`,`Verbose connection logging (for listen)`,!1).option(`--renew-peer-id`,`Renew CLI peer ID before listening`,!1).option(`-k, --insecure`,`Allow self-signed TLS certificates for the signaling server (wss://)`,!0).optionsGroup(`Agent & Orchestration Options (for listen action):`).option(`--agent`,`Enable agent orchestration loop for incoming prompts (default: true)`,!0).option(`--no-agent`,`Disable agent orchestration loop for incoming prompts`).option(`--model <model>`,`Model name for the listening agent`).option(`--provider <provider>`,`LLM provider ID for the listening agent`).option(`--api-key <key>`,`API key for the listening agent`).option(`--system-prompt <text>`,`Override system prompt for the listening agent`).option(`--system-prompt-file <file>`,`Load system prompt from file for the listening agent`).option(`--tools <tools>`,`Comma-separated list of tools to enable for the listening agent`).option(`--workspace <dir>`,`Workspace directory for the listening agent`).option(`--transfers-dir <dir>`,`Directory to store received files`).option(`--allow-internet`,`Allow internet access for bash and javascript tools`).action(async(e,t,n)=>{if(e===`listen`){await c(n);return}let r={...n};t&&!r.set&&(r.set=t),await k(e,r)}),X.command(`peer-id [action] [customId]`).alias(`webrtc-peer-id`).description(`Get, generate, or renew the WebRTC CLI peer ID stored in .cache/cli-peer-id`).optionsGroup(`Identity Options:`).option(`-r, --renew`,`Force renewal / generation of a new WebRTC CLI peer ID`).option(`--set <id>`,`Set a specific custom WebRTC CLI peer ID`).option(`--cache-dir <dir>`,`Custom cache directory (defaults to .cache)`).option(`-q, --quiet`,`Output only the peer ID string`).option(`--json`,`Output peer ID and file path as JSON`).action(async(e,t,n)=>{let r={...n};t&&!r.set&&(r.set=t),await k(e,r)}),X.commandsGroup(`Project:`),X.command(`init [dir]`).description(`Initialize a new ShadowClaw content template in the specified directory`).action(async e=>{try{let t=f.resolve(e||m.cwd());await g(f.join(t,`pages/main`),{recursive:!0});let n=f.join(t,`shadow-claw-config.json`),r=f.join(t,`shadow-claw.config.json`),i=f.join(t,`site-config.json`);!await K(n)&&!await K(r)&&!await K(i)&&(await y(n,JSON.stringify({$schema:`https://json-schema.org/draft/2020-12/schema`,site:{title:`My ShadowClaw Site`,description:`Personal AI assistant and knowledge hub powered by ShadowClaw.`},branding:{titleText:`My ShadowClaw Site`},pages:{sortOrder:`asc`,defaultPinnedPage:`/pages/main/index.html`}},null,2)+`
10
10
  `,`utf8`),console.log(`Created ${n}`));let a=f.join(t,`pages/main/index.html`);await K(a)||(await y(a,`---
11
11
  title: "Welcome to ShadowClaw"
12
12
  created: "${new Date().toISOString()}"
@@ -22,4 +22,4 @@ slug: "home"
22
22
  .cache/
23
23
  node_modules/
24
24
  `,`utf8`),console.log(`Created ${o}`)),console.log(`\nShadowClaw template successfully initialized in ${t}`),console.log(`To start developing, run:`),console.log(` npx shadow-claw dev
25
- `)}catch(e){console.error(`Init failed:`,e),m.exit(1)}}),Y.command(`skills:index [dir]`).alias(`agent-skills`).description(`Generate or update .well-known/agent-skills/index.json per the Agent Skills Discovery RFC`).optionsGroup(`Output & Path Options:`).option(`--out-dir <dir>`,`Output directory relative to content root (default: .well-known/agent-skills)`).option(`--out-file <file>`,`Explicit destination path for index.json`).option(`--metadata-root <dir>`,`Directory to read site metadata from (default: content root)`).option(`--config <file>`,`Explicit path to shadow-claw.config.json or site-config.json`).optionsGroup(`Generation Options:`).option(`--bundled`,`Include and materialize bundled ShadowClaw skills in index and .agents/skills`,!1).option(`--no-bundled`,`Exclude bundled ShadowClaw skills from index`).option(`--stdout`,`Print generated index.json to stdout`,!1).option(`--no-write`,`Skip writing file to disk`).action(async(e,t)=>{try{await l(e,t)}catch(e){console.error(`Failed to generate skills index:`,e),m.exit(1)}}),Y.commandsGroup(`Headless Agent:`),Y.command(`agent [action] [args...]`).description(`Run the headless CLI agent (init | model | skills | tools | tool | skill | import | run | listen)`).optionsGroup(`Agent Options:`).option(`--workspace <dir>`,`Workspace directory (default: .cache)`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases and logs`).option(`--tmp, --temp`,`Store cache, token, and databases in OS temporary directory`).option(`-y, --yes`,`Skip interactive cache directory prompt and accept defaults`).option(`--group <groupId>`,`Conversation group ID`,`server:main`).option(`--provider <provider>`,`LLM provider ID`).option(`--model <model>`,`Model name`).option(`--download`,`Prewarm and download the model during agent init or execution`,!1).option(`--api-key <key>`,`API key`).option(`-v, --verbose`,`Enable verbose execution logging`,!1).option(`--allow-internet, --internet-access`,`Allow full internet access for Bash and JavaScript tools (sets vm_bash_full_internet_access)`).option(`-o, --output <file>`,`Write command output to a file instead of stdout`).option(`--stream`,`Stream response tokens to stdout as they arrive (default: true)`,!0).option(`--no-stream`,`Disable streaming response tokens to stdout`).option(`--progress`,`Show progress bar during model downloads (default: true)`,!0).option(`--no-progress`,`Disable download progress bar`).option(`--system-prompt <text>`,`Override system prompt with inline text`).option(`--system-prompt-file <file>`,`Load system prompt from a text or markdown file`).option(`--tools <tools>`,`Comma-separated list of tools to enable or import (e.g. bash,read_file)`).option(`--skills <skills>`,`Comma-separated list of skills to filter or import`).option(`--scripts <scripts>`,`Comma-separated list of scripts to import`).option(`--all`,`Import all tools, skills, and scripts from discovery manifest`,!1).option(`--overwrite`,`Overwrite existing skills, tools, or scripts during import`,!1).option(`--auto-enable`,`Automatically enable imported declarative tools (default: true)`,!0).option(`--no-auto-enable`,`Do not automatically enable imported declarative tools`).option(`--tools-profile <name>`,`Tools profile to activate (e.g. __builtin_default)`).option(`-r, --remote`,`List or search available models from Hugging Face onnx-community repository`,!1).option(`--huggingface, --hf`,`Alias for --remote to query Hugging Face`,!1).option(`--query <query>`,`Filter models by search query`).option(`-q, --quiet`,`Suppress all non-error output`,!1).action(async(e,n,r)=>{await t(e,n,r)}),Y.commandsGroup(`Help & Utility:`),Y.helpCommand(`help [command]`,`display help for command`);async function Q(e=m.argv){await Y.parseAsync(e)}export{Q as main,Y as program,H as registerTerminationCleanup};
25
+ `)}catch(e){console.error(`Init failed:`,e),m.exit(1)}}),X.command(`skills:index [dir]`).alias(`agent-skills`).description(`Generate or update .well-known/agent-skills/index.json per the Agent Skills Discovery RFC`).optionsGroup(`Output & Path Options:`).option(`--out-dir <dir>`,`Output directory relative to content root (default: .well-known/agent-skills)`).option(`--out-file <file>`,`Explicit destination path for index.json`).option(`--metadata-root <dir>`,`Directory to read site metadata from (default: content root)`).option(`--config <file>`,`Explicit path to shadow-claw.config.json or site-config.json`).optionsGroup(`Generation Options:`).option(`--bundled`,`Include and materialize bundled ShadowClaw skills in index and .agents/skills`,!1).option(`--no-bundled`,`Exclude bundled ShadowClaw skills from index`).option(`--stdout`,`Print generated index.json to stdout`,!1).option(`--no-write`,`Skip writing file to disk`).action(async(e,t)=>{try{await l(e,t)}catch(e){console.error(`Failed to generate skills index:`,e),m.exit(1)}}),X.commandsGroup(`Headless Agent:`),X.command(`agent [action] [args...]`).description(`Run the headless CLI agent (init | model | skills | tools | tool | skill | import | run | listen)`).optionsGroup(`Agent Options:`).option(`--workspace <dir>`,`Workspace directory (default: .cache)`).option(`--database-dir <dir>`,`Directory where SQLite databases are stored`).option(`--cache-dir <dir>`,`Custom cache directory for databases and logs`).option(`--tmp, --temp`,`Store cache, token, and databases in OS temporary directory`).option(`-y, --yes`,`Skip interactive cache directory prompt and accept defaults`).option(`--group <groupId>`,`Conversation group ID`,`server:main`).option(`--provider <provider>`,`LLM provider ID`).option(`--model <model>`,`Model name`).option(`--download`,`Prewarm and download the model during agent init or execution`,!1).option(`--api-key <key>`,`API key`).option(`-v, --verbose`,`Enable verbose execution logging`,!1).option(`--allow-internet, --internet-access`,`Allow full internet access for Bash and JavaScript tools (sets vm_bash_full_internet_access)`).option(`-o, --output <file>`,`Write command output to a file instead of stdout`).option(`--stream`,`Stream response tokens to stdout as they arrive (default: true)`,!0).option(`--no-stream`,`Disable streaming response tokens to stdout`).option(`--progress`,`Show progress bar during model downloads (default: true)`,!0).option(`--no-progress`,`Disable download progress bar`).option(`--system-prompt <text>`,`Override system prompt with inline text`).option(`--system-prompt-file <file>`,`Load system prompt from a text or markdown file`).option(`--tools <tools>`,`Comma-separated list of tools to enable or import (e.g. bash,read_file)`).option(`--skills <skills>`,`Comma-separated list of skills to filter or import`).option(`--scripts <scripts>`,`Comma-separated list of scripts to import`).option(`--all`,`Import all tools, skills, and scripts from discovery manifest`,!1).option(`--overwrite`,`Overwrite existing skills, tools, or scripts during import`,!1).option(`--auto-enable`,`Automatically enable imported declarative tools (default: true)`,!0).option(`--no-auto-enable`,`Do not automatically enable imported declarative tools`).option(`--tools-profile <name>`,`Tools profile to activate (e.g. __builtin_default)`).option(`-r, --remote`,`List or search available models from Hugging Face onnx-community repository`,!1).option(`--huggingface, --hf`,`Alias for --remote to query Hugging Face`,!1).option(`--query <query>`,`Filter models by search query`).option(`-q, --quiet`,`Suppress all non-error output`,!1).action(async(e,n,r)=>{await t(e,n,r)}),X.commandsGroup(`Help & Utility:`),X.helpCommand(`help [command]`,`display help for command`);async function $(e=m.argv){await X.parseAsync(e)}export{$ as main,X as program,H as registerTerminationCleanup};
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://modelcontextprotocol.io/schemas/server-card/v1.json",
3
3
  "name": "shadow-claw",
4
- "version": "1.39.0",
4
+ "version": "1.39.1",
5
5
  "description": "Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.",
6
6
  "title": "ShadowClaw MCP Server",
7
7
  "websiteUrl": "https://xt-ml.github.io/shadow-claw/",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://modelcontextprotocol.io/schemas/server-card/v1.json",
3
3
  "name": "shadow-claw",
4
- "version": "1.39.0",
4
+ "version": "1.39.1",
5
5
  "description": "Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.",
6
6
  "title": "ShadowClaw MCP Server",
7
7
  "websiteUrl": "https://xt-ml.github.io/shadow-claw/",
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="b4d9144c6a1d15e1abfd1e1c8c8cad11ba4378e0" /><meta name="version" content="1.39.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="d87d3791a69017d1d08a21f3d824a6094b8f075a" /><meta name="version" content="1.39.1" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){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 r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();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(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return 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),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!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},...d!==void 0&&{supportsPromptCaching:d}})}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 c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(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 d(){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 f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){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=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;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 p=`/`,p;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 p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}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+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={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(_).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(_).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 v(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 y(e){if(Array.isArray(e))return e}function b(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 re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="b4d9144c6a1d15e1abfd1e1c8c8cad11ba4378e0" /><meta name="version" content="1.39.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="d87d3791a69017d1d08a21f3d824a6094b8f075a" /><meta name="version" content="1.39.1" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){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 r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();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(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return 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),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!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},...d!==void 0&&{supportsPromptCaching:d}})}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 c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(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 d(){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 f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){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=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;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 p=`/`,p;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 p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}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+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={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(_).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(_).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 v(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 y(e){if(Array.isArray(e))return e}function b(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 re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="b4d9144c6a1d15e1abfd1e1c8c8cad11ba4378e0" /><meta name="version" content="1.39.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="d87d3791a69017d1d08a21f3d824a6094b8f075a" /><meta name="version" content="1.39.1" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){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 r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();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(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return 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),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!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},...d!==void 0&&{supportsPromptCaching:d}})}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 c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(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 d(){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 f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){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=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;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 p=`/`,p;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 p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}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+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={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(_).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(_).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 v(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 y(e){if(Array.isArray(e))return e}function b(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 re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -89,6 +89,7 @@ Builds the site in development mode and starts the local server with live proxy,
89
89
  | `-y, --yes` | boolean | Skip interactive cache directory prompt and accept defaults | `false` |
90
90
  | `--cors-mode <mode>` | string | CORS policy: `localhost`, `private`, `all` | `"localhost"` |
91
91
  | `--peerjs` | boolean | Enable built-in PeerJS signaling server | `false` |
92
+ | `--a2a` | boolean | Enable the A2A v1.0 agent card, JSON-RPC, and SSE endpoints | `false` |
92
93
  | `--allow-private-proxy` | boolean | Allow `/proxy` endpoint to reach private/loopback addresses | `false` |
93
94
  | `--https` | boolean | Enable opt-in HTTPS server using dev TLS certificate | `false` |
94
95
  | `--cert <path>` | string | Path to custom TLS certificate (PEM) | `undefined` |
@@ -100,11 +101,11 @@ Builds the site in development mode and starts the local server with live proxy,
100
101
 
101
102
  ### `shadow-claw serve [port]`
102
103
 
103
- Serves an already-built `dist/public` static directory and runs the proxy server without triggering a rebuild. Pass `--no-static` to disable static file and UI serving (services-only mode).
104
+ Serves an already-built `dist/public` static directory and starts the backend services without triggering a rebuild. This includes the Express API, proxy, scheduler, control plane, and HTTP MCP endpoint. Pass `--no-static` to run those backend services without serving the UI. Use `--peerjs` and `--a2a` to enable the optional PeerJS signaling and A2A endpoints.
104
105
 
105
106
  ### `shadow-claw server [port]` / `shadow-claw services [port]` / `shadow-claw api [port]`
106
107
 
107
- Starts only the backend server and services (Express API, proxy, task scheduler, Control Plane, Stateless MCP HTTP endpoint, and optional PeerJS signaling) without building or serving the frontend UI or requiring a `dist` folder.
108
+ Starts only the backend services (Express API, proxy, task scheduler, Control Plane, and HTTP MCP endpoint) without building or serving the frontend UI or requiring a `dist` folder. Use `--peerjs` to enable PeerJS signaling and `--a2a` to enable the A2A agent card, JSON-RPC, and SSE endpoints.
108
109
 
109
110
  Ideal for scenarios where ShadowClaw frontends (such as static sites on GitHub Pages, Cloudflare Pages, or remote browser tabs) connect to a local or remote headless backend node.
110
111
 
@@ -129,7 +130,7 @@ Ideal for scenarios where ShadowClaw frontends (such as static sites on GitHub P
129
130
  | `--ssl-dir <path>` | string | Directory for self-signed TLS certs (defaults to `<cacheDir>/tls`) | `".cache/tls"` |
130
131
  | `-v, --verbose` | boolean | Enable verbose request and proxy logging | `false` |
131
132
 
132
- When `--a2a` is enabled, the server exposes `GET /.well-known/agent-card.json`,
133
+ When `--a2a` is enabled on `dev`, `run`, `serve`, or `server`, the backend exposes `GET /.well-known/agent-card.json`,
133
134
  `POST /a2a`, and `GET /a2a/tasks/:taskId`. Set `SHADOWCLAW_A2A=1` to enable the
134
135
  same endpoints through the environment. Discovery is public; JSON-RPC and SSE
135
136
  requests use the control token when one is configured. The native
@@ -441,7 +442,7 @@ npx shadow-claw tasks --transport webrtc --client <browser-peer-id>
441
442
 
442
443
  ### `shadow-claw mcp [options]`
443
444
 
444
- Runs the official Stateless Model Context Protocol (2026-07-28) server via STDIO or HTTP. Exposes ShadowClaw CLI capabilities and dynamically relayed tools from connected browser clients to external agent hosts (Claude Desktop, Cursor, Goose).
445
+ Runs only the standalone official Stateless Model Context Protocol (2026-07-28) server via STDIO or HTTP. It exposes ShadowClaw CLI capabilities and dynamically relayed tools from connected browser clients to external agent hosts (Claude Desktop, Cursor, Goose); it does not start the backend services, PeerJS signaling, or A2A endpoints.
445
446
 
446
447
  ```bash
447
448
  # Run in STDIO mode (default, for Claude Desktop or Cursor configuration)
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="b4d9144c6a1d15e1abfd1e1c8c8cad11ba4378e0" /><meta name="version" content="1.39.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="d87d3791a69017d1d08a21f3d824a6094b8f075a" /><meta name="version" content="1.39.1" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){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 r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();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(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return 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),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!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},...d!==void 0&&{supportsPromptCaching:d}})}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 c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(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 d(){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 f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){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=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;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 p=`/`,p;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 p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}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+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={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(_).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(_).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 v(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 y(e){if(Array.isArray(e))return e}function b(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 re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="b4d9144c6a1d15e1abfd1e1c8c8cad11ba4378e0" /><meta name="version" content="1.39.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="d87d3791a69017d1d08a21f3d824a6094b8f075a" /><meta name="version" content="1.39.1" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){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 r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();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(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return 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),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!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},...d!==void 0&&{supportsPromptCaching:d}})}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 c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(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 d(){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 f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){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=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;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 p=`/`,p;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 p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}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+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={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(_).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(_).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 v(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 y(e){if(Array.isArray(e))return e}function b(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 re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="b4d9144c6a1d15e1abfd1e1c8c8cad11ba4378e0" /><meta name="version" content="1.39.0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
1
+ <!doctype html><html lang="en"><head><title>ShadowClaw</title><meta charset="utf-8"><meta name="revision" content="d87d3791a69017d1d08a21f3d824a6094b8f075a" /><meta name="version" content="1.39.1" /><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><meta name="description" content="ShadowClaw - multi-runtime AI assistant." /><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 - multi-runtime AI assistant.","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"},"agent":{"defaultProvider":"transformers_js_local","defaultModel":"onnx-community\u002fgemma-3-1b-it-ONNX-GQA"},"customElements":{"allowedElements":["block-garden","block-garden-option","block-garden-select"],"allowedDomains":["kherrick.github.io","cdn.jsdelivr.net"]},"security":{"connectSrc":["'self'","blob:","data:","https:\u002f\u002fkherrick.github.io","https:\u002f\u002fcdn.jsdelivr.net"]}}</script>
2
2
  <script>var ShadowClawThemeInit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);function n(){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 r=`__shadowClawDefaultTrustedTypesPolicyState`,i=`default`,a=`shadowclaw-sandbox`;function o(){let e=globalThis;return e[r]||(e[r]={initialized:!1,policy:null}),e[r]}function s(){let e=o();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(i);if(n){e.policy=n;return}}let n=!1;if(typeof t.getPolicyNames==`function`){let e=t.getPolicyNames();Array.isArray(e)&&e.includes(i)&&(n=!0)}if(n){if(typeof t.getPolicy==`function`){let n=t.getPolicy(a);if(n){e.policy=n;return}}e.policy=t.createPolicy(a,{createHTML:e=>e,createScriptURL:e=>e});return}e.policy=t.createPolicy(i,{createHTML:e=>e,createScriptURL:e=>e})}catch{typeof t.getPolicy==`function`&&(e.policy=t.getPolicy(i)??t.getPolicy(a)??null)}}}new class{loading=!1;models=new Map;getModelInfo(e){if(!e||typeof e!=`string`)return null;let t=e.toLowerCase().trim(),n=this.models.get(t);if(n)return n;if(t.includes(`/`)){let e=t.split(`/`).pop();if(e&&this.models.has(e))return this.models.get(e)}else for(let[e,n]of this.models.entries())if(e.endsWith(`/${t}`))return n;if(t.includes(`:`)){let e=t.split(`:`)[0],n=this.getModelInfo(e);if(n)return n}return 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),d=typeof e.supports_prompt_caching==`boolean`?e.supports_prompt_caching:typeof e.supportsPromptCaching==`boolean`?e.supportsPromptCaching:this.supportedParametersInclude(e,`cache_control`,`prompt_caching`)?!0:void 0;!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},...d!==void 0&&{supportsPromptCaching:d}})}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 c(e){return e.replace(/^\/+|\/+$/g,``)}function l(e){let t=c(e);return t.endsWith(`/index.html`)?t=t.slice(0,-11):t.endsWith(`index.html`)&&(t=t.slice(0,-10)),c(t)}function u(e){let t=c(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 d(){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 f(e,t){let n=t||d();if(!n||!n.routes)return null;let r=l(e);if(!r)return null;for(let[e,t]of Object.entries(n.routes))if(!(!t||!t.prettyPath)&&l(t.prettyPath)===r)return u(e);return null}let p=null,ee=new Set([`chat`,`files`,`tasks`,`pages`,`settings`,`tools`,`channels`]);function m(){p=null}typeof globalThis<`u`&&(globalThis.__applyBasePathCacheReset=m);function h(){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=te();return!n||n===`/`?``:n.replace(/^\/+|\/+$/g,``).replace(/[^a-zA-Z0-9_-]/g,`-`)}function te(){if(p!==null)return p;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 p=`/`,p;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 p=`/`,p;if(!n)return p=`/`+e[0]+`/`,p}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+=`/`),p=t,p}catch{}}}let t=e.pathname||`/`;if(t===`/`)return p=`/`,p;let n=t.split(`/`).filter(Boolean),r=n.findIndex(e=>ee.has(e.toLowerCase()));return r>=0?r===0?(p=`/`,p):(p=`/`+n.slice(0,r).join(`/`)+`/`,p):f(t)?(p=`/`,p):n.length===1&&!t.includes(`.`)?(p=`/`+n[0]+`/`,p):(p=`/`,p)}function ne(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}ne(`ShadowClaw`);function g(){let e=h();return e?`shadowclaw-${e}`:`shadowclaw`}g();let _={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(_).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(_).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 v(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 y(e){if(Array.isArray(e))return e}function b(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 re(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
@@ -36,4 +36,4 @@ const shadowClawImportScripts = (...urls) => {
36
36
 
37
37
  shadowClawNativeImportScripts(...urls.map((url) => shadowClawServiceWorkerTrustedTypesPolicy.createScriptURL(url)));
38
38
  };
39
- if(!self.define){let e,s={};const a=(a,c)=>(a=new URL(a+".js",c).href,s[a]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,shadowClawImportScripts(a),s()}).then(()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e}));self.define=(c,o)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(s[i])return;let r={};const d=e=>a(e,i),n={module:{uri:i},exports:r,require:d};s[i]=Promise.all(c.map(e=>n[e]||d(e))).then(e=>(o(...e),r))}}define(["./workbox-92eae37e"],function(e){"use strict";shadowClawImportScripts("service-worker/fetch-proxy.js","service-worker/push-handler.js","service-worker/share-target.js"),self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.clientsClaim(),e.precacheAndRoute([{url:"index.css",revision:"411cebe9d73dc845bdbe6dc25374886d"},{url:"subsystems/channels/bindings/webrtc-datachannel/v1/index.css",revision:"84ea62c12532f5339a455f7da8e47048"},{url:"components/shadow-claw-tools/shadow-claw-tools.css",revision:"83e53f4fc50714d75f4f223c8cc1126b"},{url:"components/shadow-claw-toast/shadow-claw-toast.css",revision:"4ce2dcc1c81363147fa0a5e79474aed3"},{url:"components/shadow-claw-terminal/shadow-claw-terminal.css",revision:"34974a6d9a97832231fd931006a071d1"},{url:"components/shadow-claw-tasks/shadow-claw-tasks.css",revision:"520159be0d18dc3caad54e9e1dc1eb1b"},{url:"components/shadow-claw-settings/shadow-claw-settings.css",revision:"ad9bba0bb9beb555b3b43a90e590dfa1"},{url:"components/shadow-claw-pdf-viewer/shadow-claw-pdf-viewer.css",revision:"4c02b802e45b7e2377ecd915909ddf1c"},{url:"components/shadow-claw-pages/shadow-claw-pages.css",revision:"8ad238a0442ad57c12fe1c2094215cef"},{url:"components/shadow-claw-page-header/shadow-claw-page-header.css",revision:"5af6ca91ae275bdbb7f0f6bc470c83df"},{url:"components/shadow-claw-files/shadow-claw-files.css",revision:"8ea713f1228d9638039afde711505bab"},{url:"components/shadow-claw-file-viewer/shadow-claw-file-viewer.css",revision:"08101d1aefc62f51c5bff42cd468e663"},{url:"components/shadow-claw-file-viewer/highlightjs-atom-one-dark.min.css",revision:"70ec8740925f3c6615ec654090b9e2ce"},{url:"components/shadow-claw-conversations/shadow-claw-conversations.css",revision:"a941256c23d142754ea3c7e9b416f784"},{url:"components/shadow-claw-chat/shadow-claw-chat.css",revision:"b6c9d27682fce5e686696943ae1bf9b8"},{url:"components/shadow-claw-channels/shadow-claw-channels.css",revision:"431a76502c7ba3f8c83bb572f0afd71f"},{url:"components/shadow-claw-a2ui/shadow-claw-a2ui.css",revision:"d05fdf188a8295021735e601bcc5b743"},{url:"components/shadow-claw/shadow-claw.css",revision:"81482994292b2b187885d08316ef8a81"},{url:"components/settings/shadow-claw-webvm/shadow-claw-webvm.css",revision:"f8167aff26a24125d7b9b23aee8f728a"},{url:"components/settings/shadow-claw-task-server/shadow-claw-task-server.css",revision:"f6e534a6023b143270e772c7ee6119a0"},{url:"components/settings/shadow-claw-storage/shadow-claw-storage.css",revision:"dd8009443e450b709657368a19974f09"},{url:"components/settings/shadow-claw-peerjs/shadow-claw-peerjs.css",revision:"81e589816bc4fd4da2c7d688b3db5ba9"},{url:"components/settings/shadow-claw-notifications/shadow-claw-notifications.css",revision:"32804d3923655ae18f137db78bfaccfa"},{url:"components/settings/shadow-claw-networking/shadow-claw-networking.css",revision:"f186e80f555986dc26ab392cf7c29e92"},{url:"components/settings/shadow-claw-mcp-remote/shadow-claw-mcp-remote.css",revision:"c9be041c099a1d4733ed14a87ee37bfa"},{url:"components/settings/shadow-claw-llm/shadow-claw-llm.css",revision:"8703cbfc0af3167237d71d7e3f5da4f5"},{url:"components/settings/shadow-claw-integrations/shadow-claw-integrations.css",revision:"d7b9e45ff13eecf7c6571ed755dc8358"},{url:"components/settings/shadow-claw-git/shadow-claw-git.css",revision:"eab353bd20d322d0c87a7a53e639c2a6"},{url:"components/settings/shadow-claw-control-plane/shadow-claw-control-plane.css",revision:"2cc9185fc887fb10055d9edd405bd59c"},{url:"components/settings/shadow-claw-channel-config/shadow-claw-channel-config.css",revision:"c6da4c8aa3ad1b6359e6cb7af9d5f267"},{url:"components/settings/shadow-claw-accounts/shadow-claw-accounts.css",revision:"f9a43c87ce69b7be36ad18100311c14e"},{url:"components/common/shadow-claw-provider-module-settings/shadow-claw-provider-module-settings.css",revision:"b6bbdcee11cf8fd83c411f6734e10da8"},{url:"components/common/shadow-claw-provider-model-picker/shadow-claw-provider-model-picker.css",revision:"65f56fa4a760d0207440697739be250a"},{url:"components/common/shadow-claw-page-header-action-button/shadow-claw-page-header-action-button.css",revision:"192878cb48a9bb8cf206cea1672ec390"},{url:"components/common/shadow-claw-empty-state/shadow-claw-empty-state.css",revision:"001dbd8ee37eccb2b865795cb75b32e8"},{url:"components/common/shadow-claw-card/shadow-claw-card.css",revision:"ea9fb2a5ee318103b19fdf5df14dd2ea"},{url:"components/common/shadow-claw-actions/shadow-claw-actions.css",revision:"330a4d63944580d4dc150d7c08379f26"},{url:"bindings/webrtc-datachannel/v1/index.css",revision:"8c0f3bcf62cbe9579d136150c5288ba8"},{url:"index.html",revision:"3eb08c43338020f4c7913eb52963bc8d"},{url:"404.html",revision:"74bc1afc55391d3ff43b99e39de1c72f"},{url:"subsystems/channels/bindings/webrtc-datachannel/v1/index.html",revision:"d6e785383b73b911b8593265c36eaecd"},{url:"static-main/index.html",revision:"38e716481eecfdb88c3349562d815f10"},{url:"static-main/~/docs/example/article.html",revision:"cb73f16b2098cf2e77db992b6b286805"},{url:"share/share-target.html",revision:"ea535454fa33b093d0ee59fddc6f5c02"},{url:"pages/main/index.html",revision:"38e716481eecfdb88c3349562d815f10"},{url:"pages/main/~/docs/example/article.html",revision:"cb73f16b2098cf2e77db992b6b286805"},{url:"main/index.html",revision:"3eb08c43338020f4c7913eb52963bc8d"},{url:"main/memory/index.html",revision:"90eee06fd756b3e7f5c49ff5755e26fc"},{url:"files/main/index.html",revision:"38e716481eecfdb88c3349562d815f10"},{url:"files/main/~/docs/example/article.html",revision:"cb73f16b2098cf2e77db992b6b286805"},{url:"docs/skill-creator/index.html",revision:"4597e2dd6379f5b26f40219a259e6c98"},{url:"docs/publishing/index.html",revision:"80257b688c51bf5b3f01735a642e2427"},{url:"docs/example/article/index.html",revision:"5d6cb94bafc330cf491c1feb40a3aa34"},{url:"components/shadow-claw-tools/shadow-claw-tools.html",revision:"323310ef472dd2974ff78db1afbdd02c"},{url:"components/shadow-claw-toast/shadow-claw-toast.html",revision:"83ef4f69b85bc562f3e41d2038a75298"},{url:"components/shadow-claw-terminal/shadow-claw-terminal.html",revision:"d4a9d42553a49cccdabe858a1bcdfb6d"},{url:"components/shadow-claw-tasks/shadow-claw-tasks.html",revision:"6dde9f871430da8bb157d57f05876572"},{url:"components/shadow-claw-settings/shadow-claw-settings.html",revision:"dd5421c221ad0d1e11602b0466636eb0"},{url:"components/shadow-claw-pdf-viewer/shadow-claw-pdf-viewer.html",revision:"8b1d69f282f194a98c9e9e7a2eb87009"},{url:"components/shadow-claw-pages/shadow-claw-pages.html",revision:"0f03cef912be6910360117da9b98f94a"},{url:"components/shadow-claw-page-header/shadow-claw-page-header.html",revision:"9dd0f64e1c4d31367923ae2e56662b5e"},{url:"components/shadow-claw-files/shadow-claw-files.html",revision:"7727f97dd065000b055d303d5d8a671a"},{url:"components/shadow-claw-file-viewer/shadow-claw-file-viewer.html",revision:"ff21f570a074f875b13e20fc47f54b93"},{url:"components/shadow-claw-conversations/shadow-claw-conversations.html",revision:"e1dda7d82b02568714a37db5905f8dfd"},{url:"components/shadow-claw-chat/shadow-claw-chat.html",revision:"83927b073730bce66081aa1d720351c7"},{url:"components/shadow-claw-channels/shadow-claw-channels.html",revision:"ee52d98315e62d80086d156608a94e05"},{url:"components/shadow-claw-a2ui/shadow-claw-a2ui.html",revision:"04363cb02303c1f31ad6951105e2b630"},{url:"components/shadow-claw/shadow-claw.html",revision:"f06a2944fa75b8325f8a226c5429cb9a"},{url:"components/settings/shadow-claw-webvm/shadow-claw-webvm.html",revision:"b41ff0201055fc03963a115cbeef4de6"},{url:"components/settings/shadow-claw-task-server/shadow-claw-task-server.html",revision:"9e715d1a569b1e589834ffa77a109a95"},{url:"components/settings/shadow-claw-storage/shadow-claw-storage.html",revision:"33501ece794e35a2948ea03df57d47cc"},{url:"components/settings/shadow-claw-peerjs/shadow-claw-peerjs.html",revision:"40d51a573cfef6fda61358fc25d806b3"},{url:"components/settings/shadow-claw-notifications/shadow-claw-notifications.html",revision:"74d4d4d3f2b368d971e74cf9e600d6bf"},{url:"components/settings/shadow-claw-networking/shadow-claw-networking.html",revision:"bca46b725edc47a4ed30cb5e2ed4d8be"},{url:"components/settings/shadow-claw-mcp-remote/shadow-claw-mcp-remote.html",revision:"595f5626bd4a024572393c39aefe6155"},{url:"components/settings/shadow-claw-llm/shadow-claw-llm.html",revision:"ba05b5e3536c9d4a8f400696aad239b7"},{url:"components/settings/shadow-claw-integrations/shadow-claw-integrations.html",revision:"12a847b968869c521b6d17285211cf8a"},{url:"components/settings/shadow-claw-git/shadow-claw-git.html",revision:"7f0d55e8f5c74b30f2ee02cab5af93e3"},{url:"components/settings/shadow-claw-control-plane/shadow-claw-control-plane.html",revision:"83a363c0cc27bec61f7fc3126990b3b8"},{url:"components/settings/shadow-claw-channel-config/shadow-claw-channel-config.html",revision:"38805e60640572b4ada99d11343a64dd"},{url:"components/settings/shadow-claw-accounts/shadow-claw-accounts.html",revision:"6537ff4c3ee01a3107e8b138425812b9"},{url:"components/common/shadow-claw-provider-module-settings/shadow-claw-provider-module-settings.html",revision:"4022e66f6cd3ac15723063c394e429c2"},{url:"components/common/shadow-claw-provider-model-picker/shadow-claw-provider-model-picker.html",revision:"ce6d7fcbdaf710d498cdd650597d86c1"},{url:"components/common/shadow-claw-page-header-action-button/shadow-claw-page-header-action-button.html",revision:"89fa6723613dad5fcc9773685846a81f"},{url:"components/common/shadow-claw-empty-state/shadow-claw-empty-state.html",revision:"f1304d2789cf72435301709539f67a58"},{url:"components/common/shadow-claw-card/shadow-claw-card.html",revision:"332bf79a4dbd90356ea4982fc28f0312"},{url:"components/common/shadow-claw-actions/shadow-claw-actions.html",revision:"cbfba0838bc7cf14f38b80473e0d7cca"},{url:"bindings/webrtc-datachannel/v1/index.html",revision:"7f7ae8499f2c25e8e94409fa272f9f73"},{url:"favicon.ico",revision:"58fff7908409f246a6228529f384802e"},{url:"assets/icons/favicon.ico",revision:"58fff7908409f246a6228529f384802e"},{url:"static-routing.json",revision:"36f9e3515f28f864c4b329a9b3c7020a"},{url:"static-main-manifest.json",revision:"959aaefa4960add61f4f337126c3b5c7"},{url:"manifest.json",revision:"62f8d50f4e8fd710cb66c883f94b1c48"},{url:"writer-DSCZugcv.js",revision:"aa52e090e23fb66e87ae150868b73617"},{url:"writer-DKYhUsR4.js",revision:"2c1ebca2bcb7c424b3c40a335208f9f3"},{url:"webmcp-Bo3KTgRb.js",revision:"6247588e7944cfc805357755cea52f26"},{url:"webllm-_JXFm0yh.js",revision:"9eb250fab559a4b9781d8a3d8ed35ec7"},{url:"webllm-BDMz9yZR.js",revision:"86ffb13f1b7691d5d39b7a44210761ba"},{url:"ulid-BY7rQVLN.js",revision:"e1f3add55342551fd82b63ca9c9fa3ed"},{url:"txPromise-C2iYogHX.js",revision:"74a1df07fb201bd47d0a318f30b6f527"},{url:"translator-HKOMI-RS.js",revision:"0442e3e7545bf383ce11ad047ca3b4c8"},{url:"translator-CGBLZJIJ.js",revision:"484866c38f92eed3b1073f3a2cf63614"},{url:"transformers-js.worker.js",revision:"85d9dc5f8e5f3a31cddb9a7e7288504e"},{url:"transformers-BTGkWJf4.js",revision:"50bb330f47facc065c63f9d684375a58"},{url:"transformers--9oz-RLQ.js",revision:"b81607b6adb3b7b3a956301d3510c91e"},{url:"tools-vzWYHFBC.js",revision:"b8e70b785c14b2e2de15cde940497b51"},{url:"tools-Day-D-vL.js",revision:"c10a562cce98174f91470e6cdafb0f14"},{url:"tools-D45SbDqr.js",revision:"4f5b114eb4c940bbcf5217a5f3481443"},{url:"toast-BXgUfbyh.js",revision:"b7c62da49835547bd07f2010219562bd"},{url:"theme-init.js",revision:"8be9481cf42b1c5fa97853b8365cc1b0"},{url:"syncWebMcpRegistration-B-3hci9w.js",revision:"5acbbf8573829f55bb090c21fc517e37"},{url:"summarizer-P3JHUhJ4.js",revision:"c61ee9cefeca591ad5618d95d153a2f4"},{url:"summarizer-CweqtGSY.js",revision:"fc2cafa5615e2284fbe262cc416fa32c"},{url:"shadow-claw-webvm-DhVAtKbf.js",revision:"9999f31f438f5a1a764fa0bfc1829b21"},{url:"shadow-claw-tools-DDC0NSIB.js",revision:"f9113edbcdab4c05aac614216a6895e7"},{url:"shadow-claw-toast-C_zXWKX9.js",revision:"b6a160902a77d1197facbca3603d990a"},{url:"shadow-claw-terminal-hsEBRKQ_.js",revision:"169c13fa072b3940565c877242928398"},{url:"shadow-claw-tasks-CpSPVHQA.js",revision:"e81e7da79b3e87b91e5b696c84320339"},{url:"shadow-claw-task-server-mUlL48ZK.js",revision:"4bac49370e635dd2a12d796972f9e8b0"},{url:"shadow-claw-storage-B_kmiomL.js",revision:"1970f06e4c6c7d07ed59deb46884f859"},{url:"shadow-claw-settings-0q-oqDCT.js",revision:"a5989fab60f41c5d79c243648bde1f61"},{url:"shadow-claw-pdf-viewer-gOiW-_Bh.js",revision:"e84932e68c4b1a60d8d72b37cfc1c920"},{url:"shadow-claw-pages-CToKEqmr.js",revision:"eafa94893c0126dcb8f46d8fa60018b6"},{url:"shadow-claw-page-header-action-button-Bmua3mAb.js",revision:"2e4b1fc665cfcf6a51510a08ba0a5da0"},{url:"shadow-claw-page-header-CAXokjQy.js",revision:"8cb4cd1b9553604539b2baf095b7ed89"},{url:"shadow-claw-notifications-BrgDOD0W.js",revision:"d8dcc05dc321c0e4217e4d3cf12e56d2"},{url:"shadow-claw-networking-CzhfxUkn.js",revision:"df6f0e24414352aaf3e27d814171dc76"},{url:"shadow-claw-mcp-remote-BPuV22So.js",revision:"b526171aae63744e9d2fe1849881740a"},{url:"shadow-claw-llm-CD_Xdb9C.js",revision:"5867aee128a0b2715722af9b407edf98"},{url:"shadow-claw-integrations-CjtkA6l0.js",revision:"55a8e3d22e52d237a5de95a000fe5820"},{url:"shadow-claw-git-Dy-rA9pI.js",revision:"a52ef3ef6e1f8835aaa4d24da3bcfbf0"},{url:"shadow-claw-files-DCyse0Cc.js",revision:"668548ab53b58872bb2aa6b43f822c25"},{url:"shadow-claw-file-viewer-ChiLYAes.js",revision:"abe7a8060668c908f536297ff9bbdb02"},{url:"shadow-claw-empty-state-CkvLk0-B.js",revision:"1ef0891c108feeab7b5ca2f38ed07abf"},{url:"shadow-claw-element-DIrv3P6A.js",revision:"740ad3d06fc485e6ab3d815d996036ee"},{url:"shadow-claw-dialog-BrOwAOdk.js",revision:"cef105280f387f95d4763386497c3de9"},{url:"shadow-claw-conversations-BZYPSA1r.js",revision:"b89cf8c1bc1cf3ff0009c617b4842d8b"},{url:"shadow-claw-control-plane-CKqp8pKA.js",revision:"bce077fe1b3c72b5a02dac5fc7173288"},{url:"shadow-claw-chat-DczwLjR3.js",revision:"fb1332ccf41078218f41fb025c9ff8ee"},{url:"shadow-claw-channels-CQUdW5vc.js",revision:"08b56f6e2355aeca3e73c155a2cdcf36"},{url:"shadow-claw-card-DCxWEHgX.js",revision:"16fb58ffeced559d6ae06ad22dc83449"},{url:"shadow-claw-accounts-BqGrm47Z.js",revision:"d883ac4d322369c2bb92a4f1d4375019"},{url:"shadow-claw-D00hTXng.js",revision:"381ba022ae26a954f9e1d6c34545764c"},{url:"setConfig-DdSThoKj.js",revision:"c8468805ffd4cffac5c56b089a278ba6"},{url:"rolldown-runtime-aKtaBQYM.js",revision:"fe1c45aeeb5cda97a4081341cf8c64f0"},{url:"rewriter-CxdIIXnr.js",revision:"7fc8f9305671e6294279be5cd6055784"},{url:"rewriter-BLblP4kZ.js",revision:"2a9589202c37a5526d03e1ad2a4bbbf7"},{url:"push-client-BVlW9jAI.js",revision:"bacb2b8e14f7c811ddbabc7b1da9e22a"},{url:"prompt-utils-DpfOVJQv-DorZAfZa.js",revision:"8d5a0482b00cf39c6d8ba0096bbce45e"},{url:"prompt-api-polyfill-DbfS1Lze.js",revision:"34df66e2fcb99a0cd133c7aceb7e183a"},{url:"prompt-api-polyfill-Bpb3g6PM.js",revision:"ad0fdd2c2d028167256c55596a697665"},{url:"prompt-api-OUOP-B-R.js",revision:"668dec7b318ba116659a49a0648c8a28"},{url:"peerjs-Cs2DmZSG.js",revision:"6a025cdd30407eb0ee950685c0c9deef"},{url:"pdf.worker.js",revision:"b169314e56c737213dba6418ab0b6512"},{url:"parseConfigBoolean-ByjZr9OM.js",revision:"3c1af0a9fb09aac85793c7e514ecd9c8"},{url:"orchestrator-CBVWDGrk.js",revision:"79b756100522aba717d99c5832e8a107"},{url:"orchestrator-BHBaVTlH.js",revision:"4ca53d59ce96a9b9415f77eecc202a81"},{url:"openai-DMG0vGCO.js",revision:"df9e8ac844b0d28349f23e0cfe7f5850"},{url:"openai-DFvWOhYR.js",revision:"2632c6c496b38c86d2facad810255b6e"},{url:"model-ranking-C60HgQ2c.js",revision:"1d4e60595bf418902c8845d595dea242"},{url:"memoryStorage-Bew1X8Uy.js",revision:"bc1a9624bbe401c5147e3f861b2c3a58"},{url:"mcp-reconnect-BK1bYBdC.js",revision:"bd1d18dfd4c03178ea763a4beba0e933"},{url:"markdown-iMdoOnPh.js",revision:"7b9728da75c84efcbe469c5ea6960186"},{url:"language-detector-DOtU3K2z.js",revision:"98fab7d797a22dff65667cd9a4fe7d26"},{url:"language-detector-BRaioT2A.js",revision:"1ba06db21f47352e1ab970aeff923fe2"},{url:"is-typed-array-CnI-JI7u.js",revision:"8fa25cfae743242964b3f06ed67f6297"},{url:"initControlPlane-DlhBI1MM.js",revision:"ce008c01ad8249c83d2de083cdd858c8"},{url:"initControlPlane-DQ9UI3n0.js",revision:"b521bed1dd9558d2326cb89df634bd1d"},{url:"initChatSplitResize-osJXM2gu.js",revision:"4d7a895335f8f436bdbf29454b7c9d2a"},{url:"index.js",revision:"3113a914352525d8e05316270c265d26"},{url:"iframe-storage-proxy-BvRiccH0.js",revision:"58acf97666f12aad6c1271aa3e5744e8"},{url:"iframe-sanitizer-CKOO7cxp.js",revision:"b9183ad55002c1002b31509e047377f8"},{url:"git-LwFKNmUN.js",revision:"a423bd16b1885ae644adeac5dc2a7509"},{url:"git-DgFF7xTW.js",revision:"baaadea2836b616c10809a3987a3dcb0"},{url:"getGroupDir-DyNpU2fd.js",revision:"e6c00657d7b7b7a52536665161bc6d16"},{url:"getConfig-4saf0Tkq.js",revision:"780d39ddfdf762ce720d202109fdf83a"},{url:"getAllTasks-CKZML6au.js",revision:"d1fd6769d57e12c0ca78f6fa9f71e6ef"},{url:"gemini-C4EOz8c4.js",revision:"92e9e18cb67f66af84aad790ccf35762"},{url:"firebase-CuxChDPd.js",revision:"c6f7f8621434c83c73aa2516ab73ed63"},{url:"firebase-BKi8D3q5.js",revision:"114f1f181b229e8b46a8be3c0abeb3a1"},{url:"file-viewer-D4MfqmNE.js",revision:"4738694d3de33ecbff4994478c688533"},{url:"effect-BJCrpFdp.js",revision:"853102f8a6f55c95dfa3fc82f9e0e3fb"},{url:"e2e-bridge-BnL0OElm.js",revision:"49ba9980ad9cf2bfe1aa2e71b5446982"},{url:"downloadGroupFile-CP96GxoD.js",revision:"df060c5863faabafc3797c6f7a2aef59"},{url:"dist-DUy1CvmT.js",revision:"8f723f5280a9a0153814b2010a389dea"},{url:"dist-B9m1QM9v.js",revision:"54b15459024339745e68780b3493fcd0"},{url:"defaults-DwNb0lWM-Drx4e34U.js",revision:"07f566607c044acac4fce8fb133d7837"},{url:"custom-element-security-piU2U-Ec.js",revision:"51b05a37641d92c072f4de2a094d83d0"},{url:"crypto-browserify-U1v0eryt.js",revision:"9ec767425b59e5d2796b521157dad059"},{url:"crypto-browserify-B0z4QnB8.js",revision:"247ca3e52ef33c59adda8b8d1f954acf"},{url:"crypto-C8c5wMzN.js",revision:"2e4e24021e870c5fda72a84c0875677b"},{url:"constants-DiETpg52.js",revision:"c9f220286288beca5e353a2ac1b9d7a4"},{url:"constants-BR3kgTKA.js",revision:"4db79026565dcb309e0462d27c05ef8e"},{url:"connections-CiukjGiH.js",revision:"ceed006a54deba5adece531f1a88dd33"},{url:"configurePeerJs-DoursLSS.js",revision:"e281cb6de52317c687b0330368c36ebc"},{url:"config-D4lVqMs8.js",revision:"fcb9ed4e2ae6b0d123064ddebc0ef82a"},{url:"bundler-0if-QelV.js",revision:"b3656ce7ef711de0b6975db785cde1c0"},{url:"buffer-9oRIc-5Z.js",revision:"5f8bcab43db1e23f92aae427e03fbb5a"},{url:"browser-nBz_r6l4.js",revision:"e7d5c0309995473bf0dd730d3575a102"},{url:"base-task-model-CYkpwnvU-DS4fzK9O.js",revision:"3786720aea61a5be150fb388767c844b"},{url:"base-task-model-CYkpwnvU-D-idZRbr.js",revision:"5d9f4020612c5a65ad0111b10e1780e4"},{url:"backup-controller-CvzDOq4T.js",revision:"bc3e84fcc8df8c5d18ed903487df3d83"},{url:"app-routes-BMQ4HFaM.js",revision:"254eb72a2d89b010f1d3420eef40cf99"},{url:"agent.worker.js",revision:"22d9089762a52fb2b46c177d4234be72"},{url:"assets/iframe-storage-bridge.js",revision:"63df93333e520c84c9850ec0371894bd"},{url:"assets/file-viewer-preview-bridge.js",revision:"2c82c9cbe0d1a0554952c9b4f237b613"},{url:"assets/screenshots/xt-ml.github.io_shadow-claw-template-1024x768.png",revision:"1cc2cf3bfac85210d6d47f98a25bae84"},{url:"assets/screenshots/xt-ml.github.io_shadow-claw-agent-cli-weather-1024x768.png",revision:"a7c3d784e410c3284da9c2842f16842c"},{url:"assets/screenshots/shadow-claw-screenshot-731x1045.png",revision:"f3b9e801298660c14976d22f20a0c243"},{url:"assets/screenshots/shadow-claw-screenshot-1920x1052.png",revision:"16f391d0bbc913ec5aa239c8d577c7a4"},{url:"assets/screenshots/shadow-claw-screenshot-1024x768.png",revision:"3ee54a033db17e3bf3dfb7d0a11ab4e1"},{url:"assets/screenshots/kherrick.github.io_pwgen-knowledge-hub-1024x768.png",revision:"94ace19b1968a1955661d4390f9e11f4"},{url:"assets/screenshots/kherrick.github.io_block-garden-knowledge-hub-1024x768.png",revision:"fe5531f3dde6781830c3e5a5d9a3e705"},{url:"assets/icons/96.png",revision:"f91548690416c59ceb56cdb99809b955"},{url:"assets/icons/72.png",revision:"cba8470097972bdbc5d9a06fe67bfcf2"},{url:"assets/icons/512.png",revision:"ec2a8f28b812a0c2665a04cb3c535aab"},{url:"assets/icons/48.png",revision:"29eb2f38df4d5a6385399a04d7bdef00"},{url:"assets/icons/192.png",revision:"bf98264d7a62a47542e577245a292b77"},{url:"assets/icons/180.png",revision:"69128cf857af09292bb06fac0df9938b"},{url:"assets/icons/152.png",revision:"645ae818149dc508cc6146d620120db2"},{url:"assets/icons/128.png",revision:"84678d51d243c104d0c85a4e909fd0a6"},{url:"assets/icons/1024.png",revision:"ae17c81b3b93137df1702de6a9fcdab6"}],{}),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html"),{allowlist:[/^\/$/,/^\/(chat|files|pages|tasks|settings)(?:\/.*)?$/]})),e.registerRoute(({url:e,sameOrigin:s})=>{if(e.pathname.startsWith("/assets/v86.9pfs/"))return!1;const a=e.hostname.toLowerCase();if("huggingface.co"===a||a.endsWith(".huggingface.co")||a.endsWith(".hf.co")||"hf.co"===a||"hf-mirror.com"===a||a.endsWith(".hf-mirror.com")||"cdnjs.cloudflare.com"===a||"esm.sh"===a||a.endsWith(".esm.sh")||"unpkg.com"===a||"cdn.jsdelivr.net"===a||a.endsWith(".jsdelivr.net")||"esm.run"===a||"openrouter.ai"===a||a.endsWith(".openrouter.ai")||"api.telegram.org"===a)return!1;if(e.pathname.startsWith("/api/control/"))return!1;const c=e.pathname.endsWith("/share/share-target.html"),o="/proxy"===e.pathname||e.pathname.startsWith("/git-proxy/")||c||e.pathname.startsWith("/push/")||e.pathname.startsWith("/schedule/")||e.pathname.startsWith("/telegram/");return(!("localhost"===a||"127.0.0.1"===a||"::1"===a||"[::1]"===a)||!o)&&("boolean"!=typeof s||s)},new e.NetworkFirst({cacheName:"shadow-claw-cache",plugins:[new e.ExpirationPlugin({maxAgeSeconds:31536e3})]}),"GET")});
39
+ if(!self.define){let e,s={};const a=(a,c)=>(a=new URL(a+".js",c).href,s[a]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,shadowClawImportScripts(a),s()}).then(()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e}));self.define=(c,o)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(s[i])return;let r={};const d=e=>a(e,i),n={module:{uri:i},exports:r,require:d};s[i]=Promise.all(c.map(e=>n[e]||d(e))).then(e=>(o(...e),r))}}define(["./workbox-92eae37e"],function(e){"use strict";shadowClawImportScripts("service-worker/fetch-proxy.js","service-worker/push-handler.js","service-worker/share-target.js"),self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.clientsClaim(),e.precacheAndRoute([{url:"index.css",revision:"411cebe9d73dc845bdbe6dc25374886d"},{url:"subsystems/channels/bindings/webrtc-datachannel/v1/index.css",revision:"84ea62c12532f5339a455f7da8e47048"},{url:"components/shadow-claw-tools/shadow-claw-tools.css",revision:"83e53f4fc50714d75f4f223c8cc1126b"},{url:"components/shadow-claw-toast/shadow-claw-toast.css",revision:"4ce2dcc1c81363147fa0a5e79474aed3"},{url:"components/shadow-claw-terminal/shadow-claw-terminal.css",revision:"34974a6d9a97832231fd931006a071d1"},{url:"components/shadow-claw-tasks/shadow-claw-tasks.css",revision:"520159be0d18dc3caad54e9e1dc1eb1b"},{url:"components/shadow-claw-settings/shadow-claw-settings.css",revision:"ad9bba0bb9beb555b3b43a90e590dfa1"},{url:"components/shadow-claw-pdf-viewer/shadow-claw-pdf-viewer.css",revision:"4c02b802e45b7e2377ecd915909ddf1c"},{url:"components/shadow-claw-pages/shadow-claw-pages.css",revision:"8ad238a0442ad57c12fe1c2094215cef"},{url:"components/shadow-claw-page-header/shadow-claw-page-header.css",revision:"5af6ca91ae275bdbb7f0f6bc470c83df"},{url:"components/shadow-claw-files/shadow-claw-files.css",revision:"8ea713f1228d9638039afde711505bab"},{url:"components/shadow-claw-file-viewer/shadow-claw-file-viewer.css",revision:"08101d1aefc62f51c5bff42cd468e663"},{url:"components/shadow-claw-file-viewer/highlightjs-atom-one-dark.min.css",revision:"70ec8740925f3c6615ec654090b9e2ce"},{url:"components/shadow-claw-conversations/shadow-claw-conversations.css",revision:"a941256c23d142754ea3c7e9b416f784"},{url:"components/shadow-claw-chat/shadow-claw-chat.css",revision:"b6c9d27682fce5e686696943ae1bf9b8"},{url:"components/shadow-claw-channels/shadow-claw-channels.css",revision:"431a76502c7ba3f8c83bb572f0afd71f"},{url:"components/shadow-claw-a2ui/shadow-claw-a2ui.css",revision:"d05fdf188a8295021735e601bcc5b743"},{url:"components/shadow-claw/shadow-claw.css",revision:"81482994292b2b187885d08316ef8a81"},{url:"components/settings/shadow-claw-webvm/shadow-claw-webvm.css",revision:"f8167aff26a24125d7b9b23aee8f728a"},{url:"components/settings/shadow-claw-task-server/shadow-claw-task-server.css",revision:"f6e534a6023b143270e772c7ee6119a0"},{url:"components/settings/shadow-claw-storage/shadow-claw-storage.css",revision:"dd8009443e450b709657368a19974f09"},{url:"components/settings/shadow-claw-peerjs/shadow-claw-peerjs.css",revision:"81e589816bc4fd4da2c7d688b3db5ba9"},{url:"components/settings/shadow-claw-notifications/shadow-claw-notifications.css",revision:"32804d3923655ae18f137db78bfaccfa"},{url:"components/settings/shadow-claw-networking/shadow-claw-networking.css",revision:"f186e80f555986dc26ab392cf7c29e92"},{url:"components/settings/shadow-claw-mcp-remote/shadow-claw-mcp-remote.css",revision:"c9be041c099a1d4733ed14a87ee37bfa"},{url:"components/settings/shadow-claw-llm/shadow-claw-llm.css",revision:"8703cbfc0af3167237d71d7e3f5da4f5"},{url:"components/settings/shadow-claw-integrations/shadow-claw-integrations.css",revision:"d7b9e45ff13eecf7c6571ed755dc8358"},{url:"components/settings/shadow-claw-git/shadow-claw-git.css",revision:"eab353bd20d322d0c87a7a53e639c2a6"},{url:"components/settings/shadow-claw-control-plane/shadow-claw-control-plane.css",revision:"2cc9185fc887fb10055d9edd405bd59c"},{url:"components/settings/shadow-claw-channel-config/shadow-claw-channel-config.css",revision:"c6da4c8aa3ad1b6359e6cb7af9d5f267"},{url:"components/settings/shadow-claw-accounts/shadow-claw-accounts.css",revision:"f9a43c87ce69b7be36ad18100311c14e"},{url:"components/common/shadow-claw-provider-module-settings/shadow-claw-provider-module-settings.css",revision:"b6bbdcee11cf8fd83c411f6734e10da8"},{url:"components/common/shadow-claw-provider-model-picker/shadow-claw-provider-model-picker.css",revision:"65f56fa4a760d0207440697739be250a"},{url:"components/common/shadow-claw-page-header-action-button/shadow-claw-page-header-action-button.css",revision:"192878cb48a9bb8cf206cea1672ec390"},{url:"components/common/shadow-claw-empty-state/shadow-claw-empty-state.css",revision:"001dbd8ee37eccb2b865795cb75b32e8"},{url:"components/common/shadow-claw-card/shadow-claw-card.css",revision:"ea9fb2a5ee318103b19fdf5df14dd2ea"},{url:"components/common/shadow-claw-actions/shadow-claw-actions.css",revision:"330a4d63944580d4dc150d7c08379f26"},{url:"bindings/webrtc-datachannel/v1/index.css",revision:"8c0f3bcf62cbe9579d136150c5288ba8"},{url:"index.html",revision:"1ad87e689327f0f981bd62ffe8e6a82d"},{url:"404.html",revision:"74bc1afc55391d3ff43b99e39de1c72f"},{url:"subsystems/channels/bindings/webrtc-datachannel/v1/index.html",revision:"d6e785383b73b911b8593265c36eaecd"},{url:"static-main/index.html",revision:"38e716481eecfdb88c3349562d815f10"},{url:"static-main/~/docs/example/article.html",revision:"cb73f16b2098cf2e77db992b6b286805"},{url:"share/share-target.html",revision:"ea535454fa33b093d0ee59fddc6f5c02"},{url:"pages/main/index.html",revision:"38e716481eecfdb88c3349562d815f10"},{url:"pages/main/~/docs/example/article.html",revision:"cb73f16b2098cf2e77db992b6b286805"},{url:"main/index.html",revision:"1ad87e689327f0f981bd62ffe8e6a82d"},{url:"main/memory/index.html",revision:"6ec4ca0a89c2f2aabd41f2f958c93058"},{url:"files/main/index.html",revision:"38e716481eecfdb88c3349562d815f10"},{url:"files/main/~/docs/example/article.html",revision:"cb73f16b2098cf2e77db992b6b286805"},{url:"docs/skill-creator/index.html",revision:"20b84d358dced20f8a80146fb4b3dbc9"},{url:"docs/publishing/index.html",revision:"e45846e007bee6e44444d2097b289910"},{url:"docs/example/article/index.html",revision:"f0fb83d0a78d8023d06f485a4aa295cf"},{url:"components/shadow-claw-tools/shadow-claw-tools.html",revision:"323310ef472dd2974ff78db1afbdd02c"},{url:"components/shadow-claw-toast/shadow-claw-toast.html",revision:"83ef4f69b85bc562f3e41d2038a75298"},{url:"components/shadow-claw-terminal/shadow-claw-terminal.html",revision:"d4a9d42553a49cccdabe858a1bcdfb6d"},{url:"components/shadow-claw-tasks/shadow-claw-tasks.html",revision:"6dde9f871430da8bb157d57f05876572"},{url:"components/shadow-claw-settings/shadow-claw-settings.html",revision:"dd5421c221ad0d1e11602b0466636eb0"},{url:"components/shadow-claw-pdf-viewer/shadow-claw-pdf-viewer.html",revision:"8b1d69f282f194a98c9e9e7a2eb87009"},{url:"components/shadow-claw-pages/shadow-claw-pages.html",revision:"0f03cef912be6910360117da9b98f94a"},{url:"components/shadow-claw-page-header/shadow-claw-page-header.html",revision:"9dd0f64e1c4d31367923ae2e56662b5e"},{url:"components/shadow-claw-files/shadow-claw-files.html",revision:"7727f97dd065000b055d303d5d8a671a"},{url:"components/shadow-claw-file-viewer/shadow-claw-file-viewer.html",revision:"ff21f570a074f875b13e20fc47f54b93"},{url:"components/shadow-claw-conversations/shadow-claw-conversations.html",revision:"e1dda7d82b02568714a37db5905f8dfd"},{url:"components/shadow-claw-chat/shadow-claw-chat.html",revision:"83927b073730bce66081aa1d720351c7"},{url:"components/shadow-claw-channels/shadow-claw-channels.html",revision:"ee52d98315e62d80086d156608a94e05"},{url:"components/shadow-claw-a2ui/shadow-claw-a2ui.html",revision:"04363cb02303c1f31ad6951105e2b630"},{url:"components/shadow-claw/shadow-claw.html",revision:"f06a2944fa75b8325f8a226c5429cb9a"},{url:"components/settings/shadow-claw-webvm/shadow-claw-webvm.html",revision:"b41ff0201055fc03963a115cbeef4de6"},{url:"components/settings/shadow-claw-task-server/shadow-claw-task-server.html",revision:"9e715d1a569b1e589834ffa77a109a95"},{url:"components/settings/shadow-claw-storage/shadow-claw-storage.html",revision:"33501ece794e35a2948ea03df57d47cc"},{url:"components/settings/shadow-claw-peerjs/shadow-claw-peerjs.html",revision:"40d51a573cfef6fda61358fc25d806b3"},{url:"components/settings/shadow-claw-notifications/shadow-claw-notifications.html",revision:"74d4d4d3f2b368d971e74cf9e600d6bf"},{url:"components/settings/shadow-claw-networking/shadow-claw-networking.html",revision:"bca46b725edc47a4ed30cb5e2ed4d8be"},{url:"components/settings/shadow-claw-mcp-remote/shadow-claw-mcp-remote.html",revision:"595f5626bd4a024572393c39aefe6155"},{url:"components/settings/shadow-claw-llm/shadow-claw-llm.html",revision:"ba05b5e3536c9d4a8f400696aad239b7"},{url:"components/settings/shadow-claw-integrations/shadow-claw-integrations.html",revision:"12a847b968869c521b6d17285211cf8a"},{url:"components/settings/shadow-claw-git/shadow-claw-git.html",revision:"7f0d55e8f5c74b30f2ee02cab5af93e3"},{url:"components/settings/shadow-claw-control-plane/shadow-claw-control-plane.html",revision:"83a363c0cc27bec61f7fc3126990b3b8"},{url:"components/settings/shadow-claw-channel-config/shadow-claw-channel-config.html",revision:"38805e60640572b4ada99d11343a64dd"},{url:"components/settings/shadow-claw-accounts/shadow-claw-accounts.html",revision:"6537ff4c3ee01a3107e8b138425812b9"},{url:"components/common/shadow-claw-provider-module-settings/shadow-claw-provider-module-settings.html",revision:"4022e66f6cd3ac15723063c394e429c2"},{url:"components/common/shadow-claw-provider-model-picker/shadow-claw-provider-model-picker.html",revision:"ce6d7fcbdaf710d498cdd650597d86c1"},{url:"components/common/shadow-claw-page-header-action-button/shadow-claw-page-header-action-button.html",revision:"89fa6723613dad5fcc9773685846a81f"},{url:"components/common/shadow-claw-empty-state/shadow-claw-empty-state.html",revision:"f1304d2789cf72435301709539f67a58"},{url:"components/common/shadow-claw-card/shadow-claw-card.html",revision:"332bf79a4dbd90356ea4982fc28f0312"},{url:"components/common/shadow-claw-actions/shadow-claw-actions.html",revision:"cbfba0838bc7cf14f38b80473e0d7cca"},{url:"bindings/webrtc-datachannel/v1/index.html",revision:"7f7ae8499f2c25e8e94409fa272f9f73"},{url:"favicon.ico",revision:"58fff7908409f246a6228529f384802e"},{url:"assets/icons/favicon.ico",revision:"58fff7908409f246a6228529f384802e"},{url:"static-routing.json",revision:"36f9e3515f28f864c4b329a9b3c7020a"},{url:"static-main-manifest.json",revision:"959aaefa4960add61f4f337126c3b5c7"},{url:"manifest.json",revision:"62f8d50f4e8fd710cb66c883f94b1c48"},{url:"writer-DSCZugcv.js",revision:"aa52e090e23fb66e87ae150868b73617"},{url:"writer-DKYhUsR4.js",revision:"2c1ebca2bcb7c424b3c40a335208f9f3"},{url:"webmcp-Bo3KTgRb.js",revision:"6247588e7944cfc805357755cea52f26"},{url:"webllm-_JXFm0yh.js",revision:"9eb250fab559a4b9781d8a3d8ed35ec7"},{url:"webllm-BDMz9yZR.js",revision:"86ffb13f1b7691d5d39b7a44210761ba"},{url:"ulid-BY7rQVLN.js",revision:"e1f3add55342551fd82b63ca9c9fa3ed"},{url:"txPromise-C2iYogHX.js",revision:"74a1df07fb201bd47d0a318f30b6f527"},{url:"translator-HKOMI-RS.js",revision:"0442e3e7545bf383ce11ad047ca3b4c8"},{url:"translator-CGBLZJIJ.js",revision:"484866c38f92eed3b1073f3a2cf63614"},{url:"transformers-js.worker.js",revision:"85d9dc5f8e5f3a31cddb9a7e7288504e"},{url:"transformers-BTGkWJf4.js",revision:"50bb330f47facc065c63f9d684375a58"},{url:"transformers--9oz-RLQ.js",revision:"b81607b6adb3b7b3a956301d3510c91e"},{url:"tools-vzWYHFBC.js",revision:"b8e70b785c14b2e2de15cde940497b51"},{url:"tools-Day-D-vL.js",revision:"c10a562cce98174f91470e6cdafb0f14"},{url:"tools-D45SbDqr.js",revision:"4f5b114eb4c940bbcf5217a5f3481443"},{url:"toast-BXgUfbyh.js",revision:"b7c62da49835547bd07f2010219562bd"},{url:"theme-init.js",revision:"8be9481cf42b1c5fa97853b8365cc1b0"},{url:"syncWebMcpRegistration-B-3hci9w.js",revision:"5acbbf8573829f55bb090c21fc517e37"},{url:"summarizer-P3JHUhJ4.js",revision:"c61ee9cefeca591ad5618d95d153a2f4"},{url:"summarizer-CweqtGSY.js",revision:"fc2cafa5615e2284fbe262cc416fa32c"},{url:"shadow-claw-webvm-DhVAtKbf.js",revision:"9999f31f438f5a1a764fa0bfc1829b21"},{url:"shadow-claw-tools-DDC0NSIB.js",revision:"f9113edbcdab4c05aac614216a6895e7"},{url:"shadow-claw-toast-C_zXWKX9.js",revision:"b6a160902a77d1197facbca3603d990a"},{url:"shadow-claw-terminal-hsEBRKQ_.js",revision:"169c13fa072b3940565c877242928398"},{url:"shadow-claw-tasks-CpSPVHQA.js",revision:"e81e7da79b3e87b91e5b696c84320339"},{url:"shadow-claw-task-server-mUlL48ZK.js",revision:"4bac49370e635dd2a12d796972f9e8b0"},{url:"shadow-claw-storage-B_kmiomL.js",revision:"1970f06e4c6c7d07ed59deb46884f859"},{url:"shadow-claw-settings-0q-oqDCT.js",revision:"a5989fab60f41c5d79c243648bde1f61"},{url:"shadow-claw-pdf-viewer-gOiW-_Bh.js",revision:"e84932e68c4b1a60d8d72b37cfc1c920"},{url:"shadow-claw-pages-CToKEqmr.js",revision:"eafa94893c0126dcb8f46d8fa60018b6"},{url:"shadow-claw-page-header-action-button-Bmua3mAb.js",revision:"2e4b1fc665cfcf6a51510a08ba0a5da0"},{url:"shadow-claw-page-header-CAXokjQy.js",revision:"8cb4cd1b9553604539b2baf095b7ed89"},{url:"shadow-claw-notifications-BrgDOD0W.js",revision:"d8dcc05dc321c0e4217e4d3cf12e56d2"},{url:"shadow-claw-networking-CzhfxUkn.js",revision:"df6f0e24414352aaf3e27d814171dc76"},{url:"shadow-claw-mcp-remote-BPuV22So.js",revision:"b526171aae63744e9d2fe1849881740a"},{url:"shadow-claw-llm-CD_Xdb9C.js",revision:"5867aee128a0b2715722af9b407edf98"},{url:"shadow-claw-integrations-CjtkA6l0.js",revision:"55a8e3d22e52d237a5de95a000fe5820"},{url:"shadow-claw-git-Dy-rA9pI.js",revision:"a52ef3ef6e1f8835aaa4d24da3bcfbf0"},{url:"shadow-claw-files-DCyse0Cc.js",revision:"668548ab53b58872bb2aa6b43f822c25"},{url:"shadow-claw-file-viewer-ChiLYAes.js",revision:"abe7a8060668c908f536297ff9bbdb02"},{url:"shadow-claw-empty-state-CkvLk0-B.js",revision:"1ef0891c108feeab7b5ca2f38ed07abf"},{url:"shadow-claw-element-DIrv3P6A.js",revision:"740ad3d06fc485e6ab3d815d996036ee"},{url:"shadow-claw-dialog-BrOwAOdk.js",revision:"cef105280f387f95d4763386497c3de9"},{url:"shadow-claw-conversations-BZYPSA1r.js",revision:"b89cf8c1bc1cf3ff0009c617b4842d8b"},{url:"shadow-claw-control-plane-CKqp8pKA.js",revision:"bce077fe1b3c72b5a02dac5fc7173288"},{url:"shadow-claw-chat-DczwLjR3.js",revision:"fb1332ccf41078218f41fb025c9ff8ee"},{url:"shadow-claw-channels-CQUdW5vc.js",revision:"08b56f6e2355aeca3e73c155a2cdcf36"},{url:"shadow-claw-card-DCxWEHgX.js",revision:"16fb58ffeced559d6ae06ad22dc83449"},{url:"shadow-claw-accounts-BqGrm47Z.js",revision:"d883ac4d322369c2bb92a4f1d4375019"},{url:"shadow-claw-D00hTXng.js",revision:"381ba022ae26a954f9e1d6c34545764c"},{url:"setConfig-DdSThoKj.js",revision:"c8468805ffd4cffac5c56b089a278ba6"},{url:"rolldown-runtime-aKtaBQYM.js",revision:"fe1c45aeeb5cda97a4081341cf8c64f0"},{url:"rewriter-CxdIIXnr.js",revision:"7fc8f9305671e6294279be5cd6055784"},{url:"rewriter-BLblP4kZ.js",revision:"2a9589202c37a5526d03e1ad2a4bbbf7"},{url:"push-client-BVlW9jAI.js",revision:"bacb2b8e14f7c811ddbabc7b1da9e22a"},{url:"prompt-utils-DpfOVJQv-DorZAfZa.js",revision:"8d5a0482b00cf39c6d8ba0096bbce45e"},{url:"prompt-api-polyfill-DbfS1Lze.js",revision:"34df66e2fcb99a0cd133c7aceb7e183a"},{url:"prompt-api-polyfill-Bpb3g6PM.js",revision:"ad0fdd2c2d028167256c55596a697665"},{url:"prompt-api-OUOP-B-R.js",revision:"668dec7b318ba116659a49a0648c8a28"},{url:"peerjs-Cs2DmZSG.js",revision:"6a025cdd30407eb0ee950685c0c9deef"},{url:"pdf.worker.js",revision:"b169314e56c737213dba6418ab0b6512"},{url:"parseConfigBoolean-ByjZr9OM.js",revision:"3c1af0a9fb09aac85793c7e514ecd9c8"},{url:"orchestrator-CBVWDGrk.js",revision:"79b756100522aba717d99c5832e8a107"},{url:"orchestrator-BHBaVTlH.js",revision:"4ca53d59ce96a9b9415f77eecc202a81"},{url:"openai-DMG0vGCO.js",revision:"df9e8ac844b0d28349f23e0cfe7f5850"},{url:"openai-DFvWOhYR.js",revision:"2632c6c496b38c86d2facad810255b6e"},{url:"model-ranking-C60HgQ2c.js",revision:"1d4e60595bf418902c8845d595dea242"},{url:"memoryStorage-Bew1X8Uy.js",revision:"bc1a9624bbe401c5147e3f861b2c3a58"},{url:"mcp-reconnect-BK1bYBdC.js",revision:"bd1d18dfd4c03178ea763a4beba0e933"},{url:"markdown-iMdoOnPh.js",revision:"7b9728da75c84efcbe469c5ea6960186"},{url:"language-detector-DOtU3K2z.js",revision:"98fab7d797a22dff65667cd9a4fe7d26"},{url:"language-detector-BRaioT2A.js",revision:"1ba06db21f47352e1ab970aeff923fe2"},{url:"is-typed-array-CnI-JI7u.js",revision:"8fa25cfae743242964b3f06ed67f6297"},{url:"initControlPlane-DlhBI1MM.js",revision:"ce008c01ad8249c83d2de083cdd858c8"},{url:"initControlPlane-DQ9UI3n0.js",revision:"b521bed1dd9558d2326cb89df634bd1d"},{url:"initChatSplitResize-osJXM2gu.js",revision:"4d7a895335f8f436bdbf29454b7c9d2a"},{url:"index.js",revision:"3113a914352525d8e05316270c265d26"},{url:"iframe-storage-proxy-BvRiccH0.js",revision:"58acf97666f12aad6c1271aa3e5744e8"},{url:"iframe-sanitizer-CKOO7cxp.js",revision:"b9183ad55002c1002b31509e047377f8"},{url:"git-LwFKNmUN.js",revision:"a423bd16b1885ae644adeac5dc2a7509"},{url:"git-DgFF7xTW.js",revision:"baaadea2836b616c10809a3987a3dcb0"},{url:"getGroupDir-DyNpU2fd.js",revision:"e6c00657d7b7b7a52536665161bc6d16"},{url:"getConfig-4saf0Tkq.js",revision:"780d39ddfdf762ce720d202109fdf83a"},{url:"getAllTasks-CKZML6au.js",revision:"d1fd6769d57e12c0ca78f6fa9f71e6ef"},{url:"gemini-C4EOz8c4.js",revision:"92e9e18cb67f66af84aad790ccf35762"},{url:"firebase-CuxChDPd.js",revision:"c6f7f8621434c83c73aa2516ab73ed63"},{url:"firebase-BKi8D3q5.js",revision:"114f1f181b229e8b46a8be3c0abeb3a1"},{url:"file-viewer-D4MfqmNE.js",revision:"4738694d3de33ecbff4994478c688533"},{url:"effect-BJCrpFdp.js",revision:"853102f8a6f55c95dfa3fc82f9e0e3fb"},{url:"e2e-bridge-BnL0OElm.js",revision:"49ba9980ad9cf2bfe1aa2e71b5446982"},{url:"downloadGroupFile-CP96GxoD.js",revision:"df060c5863faabafc3797c6f7a2aef59"},{url:"dist-DUy1CvmT.js",revision:"8f723f5280a9a0153814b2010a389dea"},{url:"dist-B9m1QM9v.js",revision:"54b15459024339745e68780b3493fcd0"},{url:"defaults-DwNb0lWM-Drx4e34U.js",revision:"07f566607c044acac4fce8fb133d7837"},{url:"custom-element-security-piU2U-Ec.js",revision:"51b05a37641d92c072f4de2a094d83d0"},{url:"crypto-browserify-U1v0eryt.js",revision:"9ec767425b59e5d2796b521157dad059"},{url:"crypto-browserify-B0z4QnB8.js",revision:"247ca3e52ef33c59adda8b8d1f954acf"},{url:"crypto-C8c5wMzN.js",revision:"2e4e24021e870c5fda72a84c0875677b"},{url:"constants-DiETpg52.js",revision:"c9f220286288beca5e353a2ac1b9d7a4"},{url:"constants-BR3kgTKA.js",revision:"4db79026565dcb309e0462d27c05ef8e"},{url:"connections-CiukjGiH.js",revision:"ceed006a54deba5adece531f1a88dd33"},{url:"configurePeerJs-DoursLSS.js",revision:"e281cb6de52317c687b0330368c36ebc"},{url:"config-D4lVqMs8.js",revision:"fcb9ed4e2ae6b0d123064ddebc0ef82a"},{url:"bundler-0if-QelV.js",revision:"b3656ce7ef711de0b6975db785cde1c0"},{url:"buffer-9oRIc-5Z.js",revision:"5f8bcab43db1e23f92aae427e03fbb5a"},{url:"browser-nBz_r6l4.js",revision:"e7d5c0309995473bf0dd730d3575a102"},{url:"base-task-model-CYkpwnvU-DS4fzK9O.js",revision:"3786720aea61a5be150fb388767c844b"},{url:"base-task-model-CYkpwnvU-D-idZRbr.js",revision:"5d9f4020612c5a65ad0111b10e1780e4"},{url:"backup-controller-CvzDOq4T.js",revision:"bc3e84fcc8df8c5d18ed903487df3d83"},{url:"app-routes-BMQ4HFaM.js",revision:"254eb72a2d89b010f1d3420eef40cf99"},{url:"agent.worker.js",revision:"22d9089762a52fb2b46c177d4234be72"},{url:"assets/iframe-storage-bridge.js",revision:"63df93333e520c84c9850ec0371894bd"},{url:"assets/file-viewer-preview-bridge.js",revision:"2c82c9cbe0d1a0554952c9b4f237b613"},{url:"assets/screenshots/xt-ml.github.io_shadow-claw-template-1024x768.png",revision:"1cc2cf3bfac85210d6d47f98a25bae84"},{url:"assets/screenshots/xt-ml.github.io_shadow-claw-agent-cli-weather-1024x768.png",revision:"a7c3d784e410c3284da9c2842f16842c"},{url:"assets/screenshots/shadow-claw-screenshot-731x1045.png",revision:"f3b9e801298660c14976d22f20a0c243"},{url:"assets/screenshots/shadow-claw-screenshot-1920x1052.png",revision:"16f391d0bbc913ec5aa239c8d577c7a4"},{url:"assets/screenshots/shadow-claw-screenshot-1024x768.png",revision:"3ee54a033db17e3bf3dfb7d0a11ab4e1"},{url:"assets/screenshots/kherrick.github.io_pwgen-knowledge-hub-1024x768.png",revision:"94ace19b1968a1955661d4390f9e11f4"},{url:"assets/screenshots/kherrick.github.io_block-garden-knowledge-hub-1024x768.png",revision:"fe5531f3dde6781830c3e5a5d9a3e705"},{url:"assets/icons/96.png",revision:"f91548690416c59ceb56cdb99809b955"},{url:"assets/icons/72.png",revision:"cba8470097972bdbc5d9a06fe67bfcf2"},{url:"assets/icons/512.png",revision:"ec2a8f28b812a0c2665a04cb3c535aab"},{url:"assets/icons/48.png",revision:"29eb2f38df4d5a6385399a04d7bdef00"},{url:"assets/icons/192.png",revision:"bf98264d7a62a47542e577245a292b77"},{url:"assets/icons/180.png",revision:"69128cf857af09292bb06fac0df9938b"},{url:"assets/icons/152.png",revision:"645ae818149dc508cc6146d620120db2"},{url:"assets/icons/128.png",revision:"84678d51d243c104d0c85a4e909fd0a6"},{url:"assets/icons/1024.png",revision:"ae17c81b3b93137df1702de6a9fcdab6"}],{}),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html"),{allowlist:[/^\/$/,/^\/(chat|files|pages|tasks|settings)(?:\/.*)?$/]})),e.registerRoute(({url:e,sameOrigin:s})=>{if(e.pathname.startsWith("/assets/v86.9pfs/"))return!1;const a=e.hostname.toLowerCase();if("huggingface.co"===a||a.endsWith(".huggingface.co")||a.endsWith(".hf.co")||"hf.co"===a||"hf-mirror.com"===a||a.endsWith(".hf-mirror.com")||"cdnjs.cloudflare.com"===a||"esm.sh"===a||a.endsWith(".esm.sh")||"unpkg.com"===a||"cdn.jsdelivr.net"===a||a.endsWith(".jsdelivr.net")||"esm.run"===a||"openrouter.ai"===a||a.endsWith(".openrouter.ai")||"api.telegram.org"===a)return!1;if(e.pathname.startsWith("/api/control/"))return!1;const c=e.pathname.endsWith("/share/share-target.html"),o="/proxy"===e.pathname||e.pathname.startsWith("/git-proxy/")||c||e.pathname.startsWith("/push/")||e.pathname.startsWith("/schedule/")||e.pathname.startsWith("/telegram/");return(!("localhost"===a||"127.0.0.1"===a||"::1"===a||"[::1]"===a)||!o)&&("boolean"!=typeof s||s)},new e.NetworkFirst({cacheName:"shadow-claw-cache",plugins:[new e.ExpirationPlugin({maxAgeSeconds:31536e3})]}),"GET")});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadow-claw",
3
- "version": "1.39.0",
3
+ "version": "1.39.1",
4
4
  "type": "module",
5
5
  "license": "AGPL-3.0",
6
6
  "description": "ShadowClaw - multi-runtime AI assistant.",
@@ -79,6 +79,15 @@ describe("shadow-claw CLI", () => {
79
79
  expect(stdout).toContain("run");
80
80
  expect(stdout).toContain("serve");
81
81
  expect(stdout).toContain("server");
82
+ const normalizedHelp = stdout.replace(/\s+/g, " ");
83
+ expect(normalizedHelp).toContain(
84
+ "Serve static files and start backend services (optional: --peerjs, --a2a)",
85
+ );
86
+ expect(normalizedHelp).toContain("Start backend services (HTTP MCP");
87
+ expect(normalizedHelp).toContain("without serving static files");
88
+ expect(normalizedHelp).toContain("optional: --peerjs, --a2a");
89
+ expect(normalizedHelp).toContain("Start the standalone MCP server only");
90
+ expect(normalizedHelp).toContain("does not start backend services, PeerJS");
82
91
  expect(stdout).toContain("init");
83
92
  expect(stdout).toContain("clients");
84
93
  expect(stdout).toContain("send");
@@ -98,6 +107,7 @@ describe("shadow-claw CLI", () => {
98
107
  expect(devHelp).toContain("Server & Network Options:");
99
108
  expect(devHelp).toContain("Site & Build Options:");
100
109
  expect(devHelp).toContain("Security & Proxy Options:");
110
+ expect(devHelp).toContain("--a2a");
101
111
  expect(devHelp).toContain("TLS / HTTPS Options:");
102
112
  expect(devHelp).toContain("Storage & Database Options:");
103
113
 
@@ -140,6 +150,18 @@ describe("shadow-claw CLI", () => {
140
150
  "--help",
141
151
  ]);
142
152
  expect(outServe).toContain("--no-static");
153
+ expect(outServe).toContain("--a2a");
154
+
155
+ const { stdout: outRun } = await execFileAsync(process.execPath, [
156
+ cliPath,
157
+ "run",
158
+ "--help",
159
+ ]);
160
+ expect(outRun).toContain("--a2a");
161
+
162
+ expect(outServer).toContain("--a2a");
163
+ expect(outServices).toContain("--a2a");
164
+ expect(outApi).toContain("--a2a");
143
165
  });
144
166
 
145
167
  it("outputs MCP command help with mcp --help", async () => {
package/src/cli/cli.ts CHANGED
@@ -78,6 +78,15 @@ async function pathExists(p) {
78
78
  }
79
79
  }
80
80
 
81
+ function isA2AEnabled(options) {
82
+ return Boolean(
83
+ options.a2a ||
84
+ ["1", "true", "yes"].includes(
85
+ (process.env.SHADOWCLAW_A2A || "").toLowerCase().trim(),
86
+ ),
87
+ );
88
+ }
89
+
81
90
  function openBrowser(url) {
82
91
  const start =
83
92
  process.platform === "darwin"
@@ -262,6 +271,7 @@ async function handleDev(portArg, options) {
262
271
  allowedOrigins,
263
272
  verbose: Boolean(options.verbose),
264
273
  peerjs: Boolean(options.peerjs),
274
+ a2aEnabled: isA2AEnabled(options),
265
275
  rootPath: distPublicDir,
266
276
  cacheDir,
267
277
  databaseDir,
@@ -311,6 +321,11 @@ program
311
321
  false,
312
322
  )
313
323
  .option("--peerjs", "Enable built-in PeerJS signaling server", false)
324
+ .option(
325
+ "--a2a",
326
+ "Enable A2A v1.0 agent card, JSON-RPC, and SSE endpoints",
327
+ false,
328
+ )
314
329
  .optionsGroup("TLS / HTTPS Options:")
315
330
  .option("--https", "Enable HTTPS dev server", false)
316
331
  .option("--cert <path>", "Path to existing TLS certificate file")
@@ -365,6 +380,11 @@ program
365
380
  false,
366
381
  )
367
382
  .option("--peerjs", "Enable built-in PeerJS signaling server", false)
383
+ .option(
384
+ "--a2a",
385
+ "Enable A2A v1.0 agent card, JSON-RPC, and SSE endpoints",
386
+ false,
387
+ )
368
388
  .optionsGroup("TLS / HTTPS Options:")
369
389
  .option("--https", "Enable HTTPS dev server", false)
370
390
  .option("--cert <path>", "Path to existing TLS certificate file")
@@ -402,7 +422,7 @@ program.commandsGroup("Server:");
402
422
  program
403
423
  .command("serve [port]")
404
424
  .description(
405
- "Serve an existing static site build and start the backend proxy",
425
+ "Serve static files and start backend services (optional: --peerjs, --a2a)",
406
426
  )
407
427
  .optionsGroup("Server & Network Options:")
408
428
  .option("-p, --port <port>", "Port to listen on (default: 8888)")
@@ -432,6 +452,11 @@ program
432
452
  false,
433
453
  )
434
454
  .option("--peerjs", "Enable built-in PeerJS signaling server", false)
455
+ .option(
456
+ "--a2a",
457
+ "Enable A2A v1.0 agent card, JSON-RPC, and SSE endpoints",
458
+ false,
459
+ )
435
460
  .optionsGroup("TLS / HTTPS Options:")
436
461
  .option("--https", "Enable HTTPS dev server", false)
437
462
  .option("--cert <path>", "Path to existing TLS certificate file")
@@ -553,6 +578,7 @@ program
553
578
  allowedOrigins,
554
579
  verbose: Boolean(options.verbose),
555
580
  peerjs: Boolean(options.peerjs),
581
+ a2aEnabled: isA2AEnabled(options),
556
582
  rootPath: distPublicDir,
557
583
  cacheDir,
558
584
  databaseDir,
@@ -660,6 +686,7 @@ async function handleServer(portArg, options) {
660
686
  allowedOrigins,
661
687
  verbose: Boolean(options.verbose),
662
688
  peerjs: Boolean(options.peerjs),
689
+ a2aEnabled: isA2AEnabled(options),
663
690
  rootPath: "",
664
691
  cacheDir,
665
692
  databaseDir,
@@ -684,7 +711,7 @@ program
684
711
  .command("server [port]")
685
712
  .aliases(["services", "api"])
686
713
  .description(
687
- "Start backend services (Express, MCP, control plane) without building or serving the UI (aliases: services, api)",
714
+ "Start backend services (HTTP MCP, control plane, scheduler, and proxy) without serving static files (optional: --peerjs, --a2a; aliases: services, api)",
688
715
  )
689
716
  .optionsGroup("Server & Network Options:")
690
717
  .option("-p, --port <port>", "Port to listen on (default: 8888)")
@@ -706,6 +733,11 @@ program
706
733
  "Secret token for control-plane authentication",
707
734
  )
708
735
  .option("--peerjs", "Enable built-in PeerJS signaling server", false)
736
+ .option(
737
+ "--a2a",
738
+ "Enable A2A v1.0 agent card, JSON-RPC, and SSE endpoints",
739
+ false,
740
+ )
709
741
  .option(
710
742
  "--allow-private-proxy",
711
743
  "Allow proxy to reach private/loopback addresses",
@@ -744,7 +776,7 @@ program
744
776
  program
745
777
  .command("mcp")
746
778
  .description(
747
- "Run the official Stateless Model Context Protocol (MCP 2026-07-28) server",
779
+ "Start the standalone MCP server only (does not start backend services, PeerJS, or A2A)",
748
780
  )
749
781
  .optionsGroup("MCP Protocol Options:")
750
782
  .option("--mcp-transport <transport>", "MCP transport: stdio | http", "stdio")