superclawd 0.1.3 → 0.1.5

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.
package/dist/index.js CHANGED
@@ -1,30 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __cr } from 'module'; const require = __cr(import.meta.url);
3
- import{spawn as tn,spawnSync as Dr,execSync as Or}from"node:child_process";import{fileURLToPath as en}from"node:url";import{existsSync as nn}from"node:fs";import{resolve as Tr,dirname as Ur,join as Wr}from"node:path";import{homedir as on}from"node:os";import{join as Z}from"node:path";import{randomBytes as sn}from"node:crypto";import{readFileSync as an,writeFileSync as Oe,mkdirSync as Te,chmodSync as cn,existsSync as Ue}from"node:fs";var H=(process.env.SUPERCLAWD_BACKEND||"real").toLowerCase(),k=H==="mock",B=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",ee=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com",U=process.env.SUPERCLAWD_HOME||Z(on(),".superclawd"),te=Z(U,"sessions"),Q=Z(U,"config.json");function ln(e){if(!e||typeof e!="object")return{};let t=e,n=t.credentials??{...typeof t.keyId=="string"?{keyId:t.keyId}:{},...typeof t.secret=="string"?{secret:t.secret}:{},...typeof t.workspace=="string"?{workspace:t.workspace}:{}},r=t.preferences??{...typeof t.skipPermissions=="boolean"?{skipPermissions:t.skipPermissions}:{},...typeof t.notifications=="boolean"?{notifications:t.notifications}:{},...typeof t.chooseWorkspaceAtStartup=="boolean"?{chooseWorkspaceAtStartup:t.chooseWorkspaceAtStartup}:{},...typeof t.experimental=="boolean"?{experimental:t.experimental}:{}},o={};return Object.keys(n).length&&(o.credentials=n),Object.keys(r).length&&(o.preferences=r),typeof t.machineId=="string"&&(o.machineId=t.machineId),o}function We(){let e=P()??{};if(e.machineId)return e.machineId;let t=sn(16).toString("hex");return G({...e,machineId:t}),t}function P(){try{return ln(JSON.parse(an(Q,"utf8")))}catch{return null}}function G(e){Te(U,{recursive:!0}),Oe(Q,`${JSON.stringify(e,null,2)}
4
- `,{mode:384});try{cn(Q,384)}catch{}}function Ne(){return P()?.preferences?.skipPermissions===!0}function un(){return P()?.preferences?.notifications===!0}function Ge(){return P()?.preferences?.chooseWorkspaceAtStartup!==!1}function we(e){let t=P()??{};G({...t,credentials:{...t.credentials,workspace:e}})}function ne(){let e=P();e?.credentials?.workspace&&G({...e,credentials:{...e.credentials,workspace:""}})}function je(){return P()?.preferences?.experimental===!0}function Fe(){return P()?.preferences?.keepAwake===!0}function Ke(){return P()?.preferences?.privateMemory!==!1}function Ye(){return P()?.preferences?.pipelinesMcp===!0}function Be(e){return Z(e,"config.json")}function pn(e,t){try{Te(e,{recursive:!0}),Oe(Be(e),`${JSON.stringify(t,null,2)}
5
- `)}catch{}}function He(e,t,n=!1){Ue(Be(e))||pn(e,{notifications:n?!1:un(),...t?{workspace:t}:{}})}function qe(){Ue(Q)||G({credentials:{keyId:"",secret:"",workspace:""},preferences:{notifications:!1,skipPermissions:!1,chooseWorkspaceAtStartup:!0,privateMemory:!0}})}var Ve=1e3*60*60*24*3;function Je(){if(k)return{ok:!0,session:{keyId:process.env.SUPERCLAWD_MCP_KEY||"mock-key",secret:process.env.SUPERCLAWD_MCP_SECRET||"mock-secret",workspace:process.env.SUPERCLAWD_MCP_WORKSPACE||"mock-workspace",apiUrl:B}};let e=P()?.credentials??{},t=process.env.SUPERCLAWD_MCP_KEY||e.keyId,n=process.env.SUPERCLAWD_MCP_SECRET||e.secret,r=process.env.SUPERCLAWD_MCP_WORKSPACE||e.workspace||"";return!t||!n?{ok:!1,error:"Not authenticated. Run `superclawd login` (or set SUPERCLAWD_MCP_KEY + SUPERCLAWD_MCP_SECRET)."}:{ok:!0,session:{keyId:t,secret:n,workspace:r,apiUrl:B}}}import{spawn as Se}from"node:child_process";var Xe=e=>{process.env.SUPERCLAWD_DEBUG&&process.stderr.write(`keep-awake: ${e}
6
- `)};function dn(){try{switch(process.platform){case"darwin":return Se("caffeinate",["-i","-w",String(process.pid)],{stdio:"ignore"});case"linux":return Se("systemd-inhibit",["--what=sleep:idle","--who=SuperClawd","--why=SuperClawd session running","--mode=block","cat"],{stdio:["pipe","ignore","ignore"]});case"win32":{let e=[`$p = Add-Type -MemberDefinition '[DllImport("kernel32.dll")] public static extern uint SetThreadExecutionState(uint e);' -Name P -Namespace W -PassThru;`,"$p::SetThreadExecutionState(0x80000000 -bor 0x00000001) | Out-Null;","[void][Console]::In.ReadToEnd();"].join(" ");return Se("powershell",["-NoProfile","-NonInteractive","-Command",e],{stdio:["pipe","ignore","ignore"]})}default:return null}}catch{return null}}function ze(){let e=dn();if(!e)return Xe(`unsupported platform ${process.platform}`),null;e.unref(),e.on("error",n=>Xe(n.message));let t=!1;return{stop(){if(!t){t=!0;try{e.kill()}catch{}}}}}import{spawnSync as Qe}from"node:child_process";var fn="https://registry.npmjs.org/superclawd",mn=1500;function gn(e,t){let n=s=>s.split("-")[0].split(".").map(i=>parseInt(i,10)||0),r=n(e),o=n(t);for(let s=0;s<3;s++){let i=r[s]??0,a=o[s]??0;if(i!==a)return i>a}return!1}async function hn(){let e=new AbortController,t=setTimeout(()=>e.abort(),mn);try{let n=await fetch(fn,{headers:{accept:"application/vnd.npm.install-v1+json"},signal:e.signal});return n.ok?(await n.json())["dist-tags"]?.latest??null:null}catch{return null}finally{clearTimeout(t)}}async function Ze(e,t){if(process.env.SUPERCLAWD_NO_UPDATE||process.env.SUPERCLAWD_BACKEND==="mock"||process.env.SUPERCLAWD_UPDATED)return{};let n=await hn();if(!n||!gn(n,e))return{};process.stderr.write(`SuperClawd ${e} is outdated (latest ${n}). Updating\u2026
7
- `);let r=Qe("npm install -g superclawd@latest",{stdio:"inherit",shell:!0});if(r.status!==0)return process.stderr.write(`
8
- \u2717 Couldn't auto-update to ${n} (npm exited ${r.status??"?"}).
9
- SuperClawd won't launch an outdated version. Update manually, then re-run:
10
- npm install -g superclawd@latest
11
- `),{exitCode:1};let o=Qe("superclawd",t,{stdio:"inherit",env:{...process.env,SUPERCLAWD_UPDATED:"1"}});return o.error?(process.stderr.write(`
12
- \u2713 Updated to ${n}. Re-run your command.
13
- `),{exitCode:0}):{exitCode:o.status??0}}import{randomUUID as et}from"node:crypto";function tt(e){let t={"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret,"x-workspace-slug":e.workspace,"x-request-id":et()};return process.env.SUPERCLAWD_EXPERIMENTAL==="true"&&(t["x-experimental"]="true"),t}async function re(e,t,n){let r=`${e.apiUrl}${t}`;if(n){let i=new URLSearchParams;for(let[l,c]of Object.entries(n))c!==void 0&&c!==""&&i.set(l,c);let a=i.toString();a&&(r+=(r.includes("?")?"&":"?")+a)}let o=await fetch(r,{headers:tt(e)}),s=await o.json().catch(()=>null);return{status:o.status,ok:o.ok,body:s}}async function nt(e,t,n){try{let r=await fetch(`${e}/api/prompt/workspaces`,{headers:{"content-type":"application/json","x-mcp-key-id":t,"x-mcp-secret":n,"x-request-id":et()}}),o=await r.json().catch(()=>null);return{ok:r.ok,status:r.status,workspaces:o?.workspaces??[]}}catch{return{ok:!1,status:0,workspaces:[]}}}async function rt(e,t,n,r={}){let o=await fetch(`${e.apiUrl}${t}`,{method:"POST",headers:{...tt(e),...r},body:JSON.stringify(n)}),s=await o.json().catch(()=>null);return{status:o.status,ok:o.ok,body:s}}async function ke(e,t){e.message("Loading your workspaces\u2026");let n=await nt(B,t.keyId,t.secret);if(!n.ok||n.workspaces.length===0)return{};let r=new Set(n.workspaces.map(i=>i.slug)),o=t.workspace&&r.has(t.workspace)?t.workspace:void 0;if(t.workspace&&!r.has(t.workspace)&&ne(),n.workspaces.length===1){let i=n.workspaces[0].slug;return i!==o&&we(i),{workspace:i}}let s=await e.selectWorkspace(n.workspaces,{currentSlug:o,defaultSlug:o,onSetDefault:i=>we(i)});return s===null?{cancelled:!0}:{workspace:s}}async function ye(e){if(k)return{ok:!0};try{let t=await re(e,"/api/prompt/catalog");return t.ok?{ok:!0}:t.status===401?{ok:!1,error:"Your credentials are invalid or expired. Run `superclawd login` again."}:t.status===404?{ok:!1,workspaceInvalid:!0,error:"Workspace not found. Run `superclawd` and pick a workspace."}:t.status===403?{ok:!1,workspaceInvalid:!0,error:"You are not a member of this workspace."}:t.status===502||t.status===503||t.status===504?{ok:!1,error:`SuperClawd backend is unreachable or starting up (HTTP ${t.status}). Try again in a moment.`}:{ok:!1,error:`Auth check failed (HTTP ${t.status}).`}}catch(t){return{ok:!1,error:`Cannot reach SuperClawd backend (${String(t)}).`}}}var Ee=[{id:"skill-backend-001",name:"backend-api-conventions",action:"code",executionMode:"auto",description:"writing, creating, modifying, or reviewing backend API code \u2014 HTTP endpoints, routes, controllers, request handlers, or server-side validation and security",categories:[{name:"endpoint-design",instructions:["Name routes with plural nouns and kebab-case (e.g. /user-profiles).","Return RFC-7807 problem+json on errors, never bare strings.","Validate and sanitize every request body against a schema before use."]},{name:"security",instructions:["Use parameterized queries only; never string-concatenate SQL.","Rate-limit auth endpoints to 5 requests/minute per IP."]}]},{id:"skill-testing-001",name:"testing-standards",action:"test",executionMode:"auto",description:"writing or updating automated tests \u2014 unit tests, integration tests, test files, assertions, mocks, or test coverage",categories:[{name:"unit",instructions:["One behavioral assertion per test; name tests as should_<expectation>.","Mock only at process boundaries (network, fs, clock)."]}]},{id:"skill-always-001",name:"repo-foundations",action:"behave",executionMode:"always",description:"foundational rules that always apply in this repository",categories:[{name:"house-rules",instructions:["Every source file must start with a one-line header comment describing its purpose.","Prefer clarity over cleverness; match the surrounding code's style."]}]}];var ot=[{id:"guardrail-no-rm-rf",match:{tools:["Bash"],commandPatterns:["\\brm\\s+-rf\\b","\\brm\\s+-fr\\b"]},action:"deny",message:"Destructive 'rm -rf' is blocked by a workspace guardrail. Remove paths explicitly and deliberately instead."},{id:"guardrail-payments-edits",match:{tools:["Edit","Write","MultiEdit","NotebookEdit"],pathGlobs:["**/payments/**"]},action:"ask",message:"Edits under payments/ touch billing-critical code \u2014 confirm before proceeding (workspace guardrail)."}],st=[{id:"agent-reviewer-001",name:"code-reviewer",description:"Reviews a diff for correctness and security issues. Use after writing code.",vendor:"anthropic",model:"claude-sonnet-4-6",prompt:"You are a meticulous senior code reviewer. Examine the change for correctness, security, and clarity. Report concrete findings with file:line; do not rewrite the code unless asked.",mode:"subagent",tools:{read:"allow",glob:"allow",grep:"allow",edit:"deny",write:"deny",bash:"deny",webfetch:"deny",task:"deny"},steps:null,inheritWorkspaceContext:!1},{id:"agent-orchestrator-001",name:"orchestrator",description:"Coordinates multi-step coding tasks and delegates focused work. Use when a task spans several files or steps.",vendor:"anthropic",model:"claude-sonnet-4-6",prompt:"You are an orchestrator. Break the request into concrete steps, perform the edits directly, and keep changes minimal and focused on what was asked.",mode:"subagent",tools:{read:"allow",glob:"allow",grep:"allow",edit:"allow",write:"allow",bash:"deny",webfetch:"deny",task:"allow"},steps:null,inheritWorkspaceContext:!0}],it=[{name:"ship-checklist",description:"Run this team's pre-merge checklist.",arguments:[{name:"scope",description:"what is being shipped",required:!1}],content:`Pre-merge checklist for $ARGUMENTS:
3
+ import{spawn as fn,spawnSync as zr,execSync as Qr}from"node:child_process";import{fileURLToPath as dn}from"node:url";import{existsSync as mn}from"node:fs";import{resolve as Zr,dirname as eo,join as to}from"node:path";import{homedir as hn}from"node:os";import{join as te}from"node:path";import{randomBytes as wn}from"node:crypto";import{readFileSync as Sn,writeFileSync as Ge,mkdirSync as je,chmodSync as kn,existsSync as Fe}from"node:fs";var J=(process.env.SUPERCLAWD_BACKEND||"real").toLowerCase(),k=J==="mock",q=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",ne=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com",x=process.env.SUPERCLAWD_HOME||te(hn(),".superclawd"),re=te(x,"sessions"),ee=te(x,"config.json");function yn(e){if(!e||typeof e!="object")return{};let t=e,n=t.credentials??{...typeof t.keyId=="string"?{keyId:t.keyId}:{},...typeof t.secret=="string"?{secret:t.secret}:{},...typeof t.workspace=="string"?{workspace:t.workspace}:{}},r=t.preferences??{...typeof t.skipPermissions=="boolean"?{skipPermissions:t.skipPermissions}:{},...typeof t.notifications=="boolean"?{notifications:t.notifications}:{},...typeof t.chooseWorkspaceAtStartup=="boolean"?{chooseWorkspaceAtStartup:t.chooseWorkspaceAtStartup}:{},...typeof t.experimental=="boolean"?{experimental:t.experimental}:{}},o={};return Object.keys(n).length&&(o.credentials=n),Object.keys(r).length&&(o.preferences=r),typeof t.machineId=="string"&&(o.machineId=t.machineId),o}function Ke(){let e=b()??{};if(e.machineId)return e.machineId;let t=wn(16).toString("hex");return G({...e,machineId:t}),t}function b(){try{return yn(JSON.parse(Sn(ee,"utf8")))}catch{return null}}function G(e){je(x,{recursive:!0}),Ge(ee,`${JSON.stringify(e,null,2)}
4
+ `,{mode:384});try{kn(ee,384)}catch{}}function Ye(){return b()?.preferences?.skipPermissions===!0}function En(){return b()?.preferences?.notifications===!0}function Be(){return b()?.preferences?.chooseWorkspaceAtStartup!==!1}function ke(e){let t=b()??{};G({...t,credentials:{...t.credentials,workspace:e}})}function oe(){let e=b();e?.credentials?.workspace&&G({...e,credentials:{...e.credentials,workspace:""}})}function He(){return b()?.preferences?.experimental===!0}function qe(){return b()?.preferences?.keepAwake===!0}function Je(){return b()?.preferences?.privateMemory!==!1}function Ve(){return b()?.preferences?.pipelinesMcp===!0}function Xe(e){return te(e,"config.json")}function Cn(e,t){try{je(e,{recursive:!0}),Ge(Xe(e),`${JSON.stringify(t,null,2)}
5
+ `)}catch{}}function ze(e,t,n=!1){Fe(Xe(e))||Cn(e,{notifications:n?!1:En(),...t?{workspace:t}:{}})}function Qe(){Fe(ee)||G({credentials:{keyId:"",secret:"",workspace:""},preferences:{notifications:!1,skipPermissions:!1,chooseWorkspaceAtStartup:!0,privateMemory:!0}})}var Ze=1e3*60*60*24*3;function et(){if(k)return{ok:!0,session:{keyId:process.env.SUPERCLAWD_MCP_KEY||"mock-key",secret:process.env.SUPERCLAWD_MCP_SECRET||"mock-secret",workspace:process.env.SUPERCLAWD_MCP_WORKSPACE||"mock-workspace",apiUrl:q}};let e=b()?.credentials??{},t=process.env.SUPERCLAWD_MCP_KEY||e.keyId,n=process.env.SUPERCLAWD_MCP_SECRET||e.secret,r=process.env.SUPERCLAWD_MCP_WORKSPACE||e.workspace||"";return!t||!n?{ok:!1,error:"Not authenticated. Run `superclawd login` (or set SUPERCLAWD_MCP_KEY + SUPERCLAWD_MCP_SECRET)."}:{ok:!0,session:{keyId:t,secret:n,workspace:r,apiUrl:q}}}import{spawn as ye}from"node:child_process";var tt=e=>{process.env.SUPERCLAWD_DEBUG&&process.stderr.write(`keep-awake: ${e}
6
+ `)};function Rn(){try{switch(process.platform){case"darwin":return ye("caffeinate",["-i","-w",String(process.pid)],{stdio:"ignore"});case"linux":return ye("systemd-inhibit",["--what=sleep:idle","--who=SuperClawd","--why=SuperClawd session running","--mode=block","cat"],{stdio:["pipe","ignore","ignore"]});case"win32":{let e=[`$p = Add-Type -MemberDefinition '[DllImport("kernel32.dll")] public static extern uint SetThreadExecutionState(uint e);' -Name P -Namespace W -PassThru;`,"$p::SetThreadExecutionState(0x80000000 -bor 0x00000001) | Out-Null;","[void][Console]::In.ReadToEnd();"].join(" ");return ye("powershell",["-NoProfile","-NonInteractive","-Command",e],{stdio:["pipe","ignore","ignore"]})}default:return null}}catch{return null}}function nt(){let e=Rn();if(!e)return tt(`unsupported platform ${process.platform}`),null;e.unref(),e.on("error",n=>tt(n.message));let t=!1;return{stop(){if(!t){t=!0;try{e.kill()}catch{}}}}}import{spawnSync as rt}from"node:child_process";import Pn from"node:readline/promises";import{readFileSync as _n,writeFileSync as vn,mkdirSync as bn}from"node:fs";import{join as An}from"node:path";var Mn=1500,ot=24*60*60*1e3,st=An(x,"update-state.json");function xn(e,t){let n=s=>s.split("-")[0].split(".").map(i=>parseInt(i,10)||0),r=n(e),o=n(t);for(let s=0;s<3;s++){let i=r[s]??0,a=o[s]??0;if(i!==a)return i>a}return!1}async function $n(e){let t=new AbortController,n=setTimeout(()=>t.abort(),Mn);try{let r=await fetch(`https://registry.npmjs.org/${e}`,{headers:{accept:"application/vnd.npm.install-v1+json"},signal:t.signal});return r.ok?(await r.json())["dist-tags"]?.latest??null:null}catch{return null}finally{clearTimeout(n)}}function it(){try{return JSON.parse(_n(st,"utf8"))}catch{return{}}}function Ln(e){try{bn(x,{recursive:!0}),vn(st,JSON.stringify(e,null,2))}catch{}}function at(e,t){let n=it();n[e]={...n[e],...t},Ln(n)}async function Ee(e,t,n=Date.now()){let r=it()[e]??{},o=r.latest??null;return(!r.checkedAt||n-r.checkedAt>=ot)&&(o=await $n(e),at(e,{latest:o??void 0,checkedAt:n})),!o||!xn(o,t)||r.dismissed===o||r.notifiedAt&&n-r.notifiedAt<ot?null:{latest:o}}function In(e){return!(e.includes("-p")||e.includes("--print"))&&!!process.stdin.isTTY}function Ce(e,t,n,r){process.stderr.write(`\u26A0 ${e} ${t} is outdated (latest ${n}). Update with: ${r}
7
+ `)}async function Re(e,t,n){let r=Pn.createInterface({input:process.stdin,output:process.stderr});try{process.stderr.write(`
8
+ ${e} ${t} is outdated \u2014 ${n} is available.
9
+ `);let o=(await r.question(" [U] Update now (default) [R] Run anyway > ")).trim().toLowerCase();return o==="r"||o==="run"?"run":"update"}finally{r.close()}}function Y(e,t){at(e,{notifiedAt:Date.now(),...t?{dismissed:t}:{}})}async function ct(e,t){if(process.env.SUPERCLAWD_NO_UPDATE||process.env.SUPERCLAWD_BACKEND==="mock"||process.env.SUPERCLAWD_UPDATED)return{};let n=await Ee("superclawd",e);if(!n)return{};let{latest:r}=n;if(!In(t))return Ce("SuperClawd",e,r,"superclawd update"),Y("superclawd"),{};if(await Re("SuperClawd",e,r)==="run")return Y("superclawd",r),{};Y("superclawd"),process.stderr.write(`Updating (npm i -g superclawd@latest) \u2026
10
+ `);let s=rt("npm install -g superclawd@latest",{stdio:"inherit",shell:!0});if(s.status!==0)return process.stderr.write(`\u2717 Update failed (npm exited ${s.status??"?"}). Running ${e} for now.
11
+ `),{};let i=rt("superclawd",t,{stdio:"inherit",env:{...process.env,SUPERCLAWD_UPDATED:"1"}});return i.error?(process.stderr.write(`\u2713 Updated to ${r}. Re-run your command.
12
+ `),{exitCode:0}):{exitCode:i.status??0}}import{randomUUID as lt}from"node:crypto";function ut(e){let t={"content-type":"application/json","x-mcp-key-id":e.keyId,"x-mcp-secret":e.secret,"x-workspace-slug":e.workspace,"x-request-id":lt()};return process.env.SUPERCLAWD_EXPERIMENTAL==="true"&&(t["x-experimental"]="true"),t}async function se(e,t,n){let r=`${e.apiUrl}${t}`;if(n){let i=new URLSearchParams;for(let[l,c]of Object.entries(n))c!==void 0&&c!==""&&i.set(l,c);let a=i.toString();a&&(r+=(r.includes("?")?"&":"?")+a)}let o=await fetch(r,{headers:ut(e)}),s=await o.json().catch(()=>null);return{status:o.status,ok:o.ok,body:s}}async function pt(e,t,n){try{let r=await fetch(`${e}/api/prompt/workspaces`,{headers:{"content-type":"application/json","x-mcp-key-id":t,"x-mcp-secret":n,"x-request-id":lt()}}),o=await r.json().catch(()=>null);return{ok:r.ok,status:r.status,workspaces:o?.workspaces??[]}}catch{return{ok:!1,status:0,workspaces:[]}}}async function dt(e,t,n,r={}){let o=await fetch(`${e.apiUrl}${t}`,{method:"POST",headers:{...ut(e),...r},body:JSON.stringify(n)}),s=await o.json().catch(()=>null);return{status:o.status,ok:o.ok,body:s}}async function Pe(e,t){e.message("Loading your workspaces\u2026");let n=await pt(q,t.keyId,t.secret);if(!n.ok||n.workspaces.length===0)return{};let r=new Set(n.workspaces.map(i=>i.slug)),o=t.workspace&&r.has(t.workspace)?t.workspace:void 0;if(t.workspace&&!r.has(t.workspace)&&oe(),n.workspaces.length===1){let i=n.workspaces[0].slug;return i!==o&&ke(i),{workspace:i}}let s=await e.selectWorkspace(n.workspaces,{currentSlug:o,defaultSlug:o,onSetDefault:i=>ke(i)});return s===null?{cancelled:!0}:{workspace:s}}async function _e(e){if(k)return{ok:!0};try{let t=await se(e,"/api/prompt/catalog");return t.ok?{ok:!0}:t.status===401?{ok:!1,error:"Your credentials are invalid or expired. Run `superclawd login` again."}:t.status===404?{ok:!1,workspaceInvalid:!0,error:"Workspace not found. Run `superclawd` and pick a workspace."}:t.status===403?{ok:!1,workspaceInvalid:!0,error:"You are not a member of this workspace."}:t.status===502||t.status===503||t.status===504?{ok:!1,error:`SuperClawd backend is unreachable or starting up (HTTP ${t.status}). Try again in a moment.`}:{ok:!1,error:`Auth check failed (HTTP ${t.status}).`}}catch(t){return{ok:!1,error:`Cannot reach SuperClawd backend (${String(t)}).`}}}var ve=[{id:"skill-backend-001",name:"backend-api-conventions",action:"code",executionMode:"auto",description:"writing, creating, modifying, or reviewing backend API code \u2014 HTTP endpoints, routes, controllers, request handlers, or server-side validation and security",categories:[{name:"endpoint-design",instructions:["Name routes with plural nouns and kebab-case (e.g. /user-profiles).","Return RFC-7807 problem+json on errors, never bare strings.","Validate and sanitize every request body against a schema before use."]},{name:"security",instructions:["Use parameterized queries only; never string-concatenate SQL.","Rate-limit auth endpoints to 5 requests/minute per IP."]}]},{id:"skill-testing-001",name:"testing-standards",action:"test",executionMode:"auto",description:"writing or updating automated tests \u2014 unit tests, integration tests, test files, assertions, mocks, or test coverage",categories:[{name:"unit",instructions:["One behavioral assertion per test; name tests as should_<expectation>.","Mock only at process boundaries (network, fs, clock)."]}]},{id:"skill-always-001",name:"repo-foundations",action:"behave",executionMode:"always",description:"foundational rules that always apply in this repository",categories:[{name:"house-rules",instructions:["Every source file must start with a one-line header comment describing its purpose.","Prefer clarity over cleverness; match the surrounding code's style."]}]}];var ft=[{id:"guardrail-no-rm-rf",match:{tools:["Bash"],commandPatterns:["\\brm\\s+-rf\\b","\\brm\\s+-fr\\b"]},action:"deny",message:"Destructive 'rm -rf' is blocked by a workspace guardrail. Remove paths explicitly and deliberately instead."},{id:"guardrail-payments-edits",match:{tools:["Edit","Write","MultiEdit","NotebookEdit"],pathGlobs:["**/payments/**"]},action:"ask",message:"Edits under payments/ touch billing-critical code \u2014 confirm before proceeding (workspace guardrail)."}],mt=[{id:"agent-reviewer-001",name:"code-reviewer",description:"Reviews a diff for correctness and security issues. Use after writing code.",vendor:"anthropic",model:"claude-sonnet-4-6",prompt:"You are a meticulous senior code reviewer. Examine the change for correctness, security, and clarity. Report concrete findings with file:line; do not rewrite the code unless asked.",mode:"subagent",tools:{read:"allow",glob:"allow",grep:"allow",edit:"deny",write:"deny",bash:"deny",webfetch:"deny",task:"deny"},steps:null,inheritWorkspaceContext:!1},{id:"agent-orchestrator-001",name:"orchestrator",description:"Coordinates multi-step coding tasks and delegates focused work. Use when a task spans several files or steps.",vendor:"anthropic",model:"claude-sonnet-4-6",prompt:"You are an orchestrator. Break the request into concrete steps, perform the edits directly, and keep changes minimal and focused on what was asked.",mode:"subagent",tools:{read:"allow",glob:"allow",grep:"allow",edit:"allow",write:"allow",bash:"deny",webfetch:"deny",task:"allow"},steps:null,inheritWorkspaceContext:!0}],gt=[{name:"ship-checklist",description:"Run this team's pre-merge checklist.",arguments:[{name:"scope",description:"what is being shipped",required:!1}],content:`Pre-merge checklist for $ARGUMENTS:
14
13
  1. Tests pass and cover new behavior.
15
14
  2. No secrets or debug logging left in.
16
15
  3. Public APIs documented.
17
- 4. Changelog updated.`}],at=[{name:"error-codes",description:"Canonical list of this platform's error codes.",content:`E1001 invalid_input
16
+ 4. Changelog updated.`}],ht=[{name:"error-codes",description:"Canonical list of this platform's error codes.",content:`E1001 invalid_input
18
17
  E1002 unauthorized
19
18
  E1003 rate_limited
20
- E2001 upstream_unavailable`}];var ct=[{id:"workflow-deploy-001",name:"production-deploy",description:"deploying to production, cutting a release, or shipping to prod",itemCount:6,content:`Production deploy workflow:
19
+ E2001 upstream_unavailable`}];var wt=[{id:"workflow-deploy-001",name:"production-deploy",description:"deploying to production, cutting a release, or shipping to prod",itemCount:6,content:`Production deploy workflow:
21
20
  1. Confirm CI is green on main.
22
21
  2. Bump version + update changelog.
23
22
  3. Tag the release.
24
23
  4. Run db migrations.
25
24
  5. Deploy and watch error rate for 10m.
26
- 6. Announce in #releases.`}];function wn(){let e=Ee.filter(n=>n.executionMode==="auto").map(n=>({id:n.id,name:n.name,action:n.action,executionMode:n.executionMode,description:n.description})),t=Ee.filter(n=>n.executionMode==="always").flatMap(n=>n.categories.flatMap(r=>r.instructions)).map((n,r)=>`${r+1}. ${n}`).join(`
27
- `);return{skills:e,agents:st,agentTeams:[],commands:it.map(({name:n,description:r,arguments:o,team:s})=>({name:n,description:r,arguments:o,team:s??null})),resources:at.map(({name:n,description:r})=>({name:n,description:r})),workflows:ct.map(({id:n,name:r,description:o})=>({id:n,name:r,description:o})),mcpServers:[],guardrails:ot,policyGuardrails:[],foundational:{text:t},teamMemoryEnabled:!0,repoMemoryEnabled:!0,agentMemoryEnabled:!0}}async function lt(e){if(k)return wn();let t=await re(e,"/api/prompt/catalog",{repoFingerprint:process.env.SUPERCLAWD_REPO_FINGERPRINT});if(!t.ok||!t.body)throw new Error(`Failed to fetch catalog (HTTP ${t.status}).`);return{skills:(t.body.skills??[]).filter(r=>r.executionMode==="auto"),agents:(t.body.agents??[]).map(r=>({...r,learnedMemories:r.learnedMemories??[]})),agentTeams:(t.body.agentTeams??[]).map(r=>({...r,linkedWorkflows:r.linkedWorkflows??[]})),commands:t.body.commands??[],resources:t.body.resources??[],workflows:t.body.workflows??[],mcpServers:t.body.mcpServers??[],guardrails:t.body.guardrails??[],policyGuardrails:t.body.policyGuardrails??[],foundational:{text:t.body.foundational?.text??""},teamMemoryEnabled:t.body.teamMemoryEnabled??!0,repoMemoryEnabled:t.body.repoMemoryEnabled??!0,agentMemoryEnabled:t.body.agentMemoryEnabled??!0}}async function ut(e,t,n=!0){if(k)return!0;try{return(await rt(e,"/api/prompt/inspector",{ide:!0,platform:"claude-code",llm_model:"claude",x_session_request_id:t,notify_on_checkpoint:n,enable_session_files:!1},{"x-session-request-id":t})).ok}catch{return!1}}import{mkdirSync as ar,writeFileSync as cr,chmodSync as lr}from"node:fs";import{dirname as Ot,join as Tt}from"node:path";function x(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)||"skill"}function Sn(e){return`${(e.description??e.name).trim().replace(/\.$/,"")}. SuperClawd-managed "${e.name}" guidance for ${e.action} tasks.`}function kn(e){return`# ${e.name} (SuperClawd-managed)
25
+ 6. Announce in #releases.`}];function Dn(){let e=ve.filter(n=>n.executionMode==="auto").map(n=>({id:n.id,name:n.name,action:n.action,executionMode:n.executionMode,description:n.description})),t=ve.filter(n=>n.executionMode==="always").flatMap(n=>n.categories.flatMap(r=>r.instructions)).map((n,r)=>`${r+1}. ${n}`).join(`
26
+ `);return{skills:e,agents:mt,agentTeams:[],commands:gt.map(({name:n,description:r,arguments:o,team:s})=>({name:n,description:r,arguments:o,team:s??null})),resources:ht.map(({name:n,description:r})=>({name:n,description:r})),workflows:wt.map(({id:n,name:r,description:o})=>({id:n,name:r,description:o})),mcpServers:[],guardrails:ft,policyGuardrails:[],foundational:{text:t},teamMemoryEnabled:!0,repoMemoryEnabled:!0,agentMemoryEnabled:!0}}async function St(e){if(k)return Dn();let t=await se(e,"/api/prompt/catalog",{repoFingerprint:process.env.SUPERCLAWD_REPO_FINGERPRINT});if(!t.ok||!t.body)throw new Error(`Failed to fetch catalog (HTTP ${t.status}).`);return{skills:(t.body.skills??[]).filter(r=>r.executionMode==="auto"),agents:(t.body.agents??[]).map(r=>({...r,learnedMemories:r.learnedMemories??[]})),agentTeams:(t.body.agentTeams??[]).map(r=>({...r,linkedWorkflows:r.linkedWorkflows??[]})),commands:t.body.commands??[],resources:t.body.resources??[],workflows:t.body.workflows??[],mcpServers:t.body.mcpServers??[],guardrails:t.body.guardrails??[],policyGuardrails:t.body.policyGuardrails??[],foundational:{text:t.body.foundational?.text??""},teamMemoryEnabled:t.body.teamMemoryEnabled??!0,repoMemoryEnabled:t.body.repoMemoryEnabled??!0,agentMemoryEnabled:t.body.agentMemoryEnabled??!0}}async function kt(e,t,n=!0){if(k)return!0;try{return(await dt(e,"/api/prompt/inspector",{ide:!0,platform:"claude-code",llm_model:"claude",x_session_request_id:t,notify_on_checkpoint:n,enable_session_files:!1},{"x-session-request-id":t})).ok}catch{return!1}}import{mkdirSync as Pr,writeFileSync as _r,chmodSync as vr}from"node:fs";import{dirname as Ht,join as qt}from"node:path";function $(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)||"skill"}function Tn(e){return`${(e.description??e.name).trim().replace(/\.$/,"")}. SuperClawd-managed "${e.name}" guidance for ${e.action} tasks.`}function On(e){return`# ${e.name} (SuperClawd-managed)
28
27
 
29
28
  The authoritative instructions for this skill are managed in SuperClawd and
30
29
  are **not** included here. You must fetch them before acting.
@@ -38,13 +37,13 @@ are **not** included here. You must fetch them before acting.
38
37
 
39
38
  Do not proceed using only this description \u2014 it is a pointer, not the rules.
40
39
  If \`get_directives\` returns an error, tell the user and stop.
41
- `}function yn(e){let t=Sn(e).replace(/"/g,'\\"');return`---
42
- name: ${x(e.name)}
40
+ `}function Un(e){let t=Tn(e).replace(/"/g,'\\"');return`---
41
+ name: ${$(e.name)}
43
42
  description: "${t}"
44
43
  user-invocable: false
45
44
  ---
46
45
 
47
- `}function pt(e){let t=new Set,n=[];for(let r of e){let o=x(r.name),s=2;for(;t.has(o);)o=`${x(r.name)}-${s++}`;t.add(o),n.push({relPath:`skills/${o}/SKILL.md`,content:yn(r)+kn(r)})}return n}var En=`SUPERCLAWD \u2014 operating manual (always in effect):
46
+ `}function yt(e){let t=new Set,n=[];for(let r of e){let o=$(r.name),s=2;for(;t.has(o);)o=`${$(r.name)}-${s++}`;t.add(o),n.push({relPath:`skills/${o}/SKILL.md`,content:Un(r)+On(r)})}return n}var Wn=`SUPERCLAWD \u2014 operating manual (always in effect):
48
47
  - The ALWAYS rules below are ALREADY LOADED and active for this entire session.
49
48
  Apply them directly to all work. Do NOT call any tool to fetch them \u2014 you
50
49
  already have them in full.
@@ -67,38 +66,38 @@ user-invocable: false
67
66
  \`record_memory\` for it; never claim a preference is "already" a saved convention, or
68
67
  that it "will persist", unless you just recorded it (or confirmed it via
69
68
  \`list_memories\`). A background pass also captures durable facts at session end as a
70
- backstop \u2014 but never rely on it for an explicit request; record that now.`;function Ce(e){let t=En,n=(e||"").trim();return n&&(t+=`
69
+ backstop \u2014 but never rely on it for an explicit request; record that now.`;function be(e){let t=Wn,n=(e||"").trim();return n&&(t+=`
71
70
 
72
71
  ALWAYS \u2014 foundational rules (already loaded & active for this whole session; apply directly, never fetch):
73
- ${n}`),t}function Cn(e){return e.inheritWorkspaceContext!==!1}function Rn(e){return Ce(e).trim()}function _n(e){return`You are SuperClawd agent \`${e.id}\`. SuperClawd automatically remembers the durable, reusable lessons from your work and applies them on your future runs \u2014 you do NOT need to save anything yourself.`}function Pn(e){let t=(e.learnedMemories??[]).filter(r=>r.trim());return t.length===0?"":`AGENT MEMORY \u2014 lessons you've learned in past work (apply by default; a more specific instruction wins):
72
+ ${n}`),t}function Nn(e){return e.inheritWorkspaceContext!==!1}function Gn(e){return be(e).trim()}function jn(e){return`You are SuperClawd agent \`${e.id}\`. SuperClawd automatically remembers the durable, reusable lessons from your work and applies them on your future runs \u2014 you do NOT need to save anything yourself.`}function Fn(e){let t=(e.learnedMemories??[]).filter(r=>r.trim());return t.length===0?"":`AGENT MEMORY \u2014 lessons you've learned in past work (apply by default; a more specific instruction wins):
74
73
  `+t.map(r=>`- ${r.trim()}`).join(`
75
- `)}function Re(e,t){let n=[];if(Cn(e)){let o=Rn(t);o&&n.push(o)}n.push(_n(e));let r=Pn(e);return r&&n.push(r),n.push(e.prompt),n.join(`
74
+ `)}function Ae(e,t){let n=[];if(Nn(e)){let o=Gn(t);o&&n.push(o)}n.push(jn(e));let r=Fn(e);return r&&n.push(r),n.push(e.prompt),n.join(`
76
75
 
77
76
  ---
78
77
 
79
- `)}var q="superclawd",oe="core",se=`mcp__plugin_${q}_${oe}__`,_e=e=>`${se}${e}`,dt=`${se}*`,vn=`${q}:`,ie=e=>`${vn}${e}`;var ae={read:"Read",glob:"Glob",grep:"Grep",edit:"Edit",write:"Write",bash:"Bash",webfetch:"WebFetch",task:"Task"};function bn(e){return e==="allow"||e==="ask"||e===!0}var Pe=_e("get_workflow"),ft=_e("get_directives"),An=e=>ie(e);function Mn(e,t=!1,n=!1,r=!1){let o=e.tools??{},s=Object.keys(ae).filter(i=>bn(o[i])).map(i=>ae[i]);return t&&!s.includes(ae.task)&&s.push(ae.task),n&&!s.includes(Pe)&&s.push(Pe),r&&!s.includes(ft)&&s.push(ft),s}function xn(e,t=!1,n=!1){let r=[`name: ${x(e.name)}`,`description: "${(e.description??e.name).replace(/"/g,'\\"')}"`];e.vendor==="anthropic"&&e.model&&e.model!=="default"&&r.push(`model: ${JSON.stringify(e.model)}`);let o=(e.skills?.length??0)>0,s=Mn(e,t,n,o);return s.length&&r.push(`tools: ${s.join(", ")}`),e.skills?.length&&r.push(`skills: ${e.skills.join(", ")}`),`---
78
+ `)}var V="superclawd",ie="core",ae=`mcp__plugin_${V}_${ie}__`,Me=e=>`${ae}${e}`,Et=`${ae}*`,Kn=`${V}:`,ce=e=>`${Kn}${e}`;var le={read:"Read",glob:"Glob",grep:"Grep",edit:"Edit",write:"Write",bash:"Bash",webfetch:"WebFetch",task:"Task"};function Yn(e){return e==="allow"||e==="ask"||e===!0}var xe=Me("get_workflow"),Ct=Me("get_directives"),Bn=e=>ce(e);function Hn(e,t=!1,n=!1,r=!1){let o=e.tools??{},s=Object.keys(le).filter(i=>Yn(o[i])).map(i=>le[i]);return t&&!s.includes(le.task)&&s.push(le.task),n&&!s.includes(xe)&&s.push(xe),r&&!s.includes(Ct)&&s.push(Ct),s}function qn(e,t=!1,n=!1){let r=[`name: ${$(e.name)}`,`description: "${(e.description??e.name).replace(/"/g,'\\"')}"`];e.vendor==="anthropic"&&e.model&&e.model!=="default"&&r.push(`model: ${JSON.stringify(e.model)}`);let o=(e.skills?.length??0)>0,s=Hn(e,t,n,o);return s.length&&r.push(`tools: ${s.join(", ")}`),e.skills?.length&&r.push(`skills: ${e.skills.join(", ")}`),`---
80
79
  ${r.join(`
81
80
  `)}
82
81
  ---
83
82
 
84
- `}function ce(e){let t=new Set;return e.map(n=>{let r=x(n.name),o=2;for(;t.has(r);)r=`${x(n.name)}-${o++}`;return t.add(r),{slug:r,agent:n}})}function mt(e){let t={};for(let{slug:n,agent:r}of ce(e))t[n]=r.id;return t}function $n(e,t){let n=t.map(s=>`- \`${An(s.slug)}\` \u2014 ${s.description??s.slug}`).join(`
83
+ `}function ue(e){let t=new Set;return e.map(n=>{let r=$(n.name),o=2;for(;t.has(r);)r=`${$(n.name)}-${o++}`;return t.add(r),{slug:r,agent:n}})}function Rt(e){let t={};for(let{slug:n,agent:r}of ue(e))t[n]=r.id;return t}function Jn(e,t){let n=t.map(s=>`- \`${Bn(s.slug)}\` \u2014 ${s.description??s.slug}`).join(`
85
84
  `),r=`## Team Lead \u2014 ${e.name}
86
85
  You lead the **${e.name}** agent team. When given a task, decompose it and **delegate to your team members via the Agent tool** \u2014 then **synthesize** their outputs into one consolidated answer. Delegate using the EXACT agent name shown below (including the \`superclawd:\` prefix). Call the Agent tool and use the result it returns directly \u2014 it returns the member's full output when that member finishes. To run members in parallel, issue multiple Agent calls in a single step; they run concurrently and each returns its own result. Do NOT run members as background agents, and NEVER poll for a "\`.done\`"/completion file or run a \`sleep\`/\`until\` wait loop \u2014 there is no such marker, so it will hang forever; just read the Agent tool's returned result. Your members:
87
86
  ${n}`,o=e.linkedWorkflows??[];if(o.length){let s=o.map(i=>`- ${i.name} (workflowId: ${i.id}) \u2014 ${i.description??""}`).join(`
88
87
  `);r+=`
89
88
 
90
89
  ### Linked workflows
91
- You **MAY** run any of these linked workflows if (and only if) one is relevant to the task \u2014 there is **no obligation** to run any. To run one, call the \`${Pe}\` MCP tool with its \`workflowId\`, then follow the returned steps in order.
92
- ${s}`}return r}function gt(e,t={},n=[]){let r=t.foundationalText??"",o=ce(e),s=new Map;for(let{slug:l,agent:c}of o)s.set(c.id,{slug:l,description:c.description});let i=new Map,a=new Set;for(let l of n){let c=l.memberAgentIds.map(w=>s.get(w)).filter(w=>!!w),g=$n(l,c),E=i.get(l.leadAgentId)??[];E.push(g),i.set(l.leadAgentId,E),l.linkedWorkflows?.length&&a.add(l.leadAgentId)}return o.map(({slug:l,agent:c})=>{let g=i.get(c.id),E=!!g&&g.length>0,w=a.has(c.id),p=E?[Re(c,r),...g].join(`
90
+ You **MAY** run any of these linked workflows if (and only if) one is relevant to the task \u2014 there is **no obligation** to run any. To run one, call the \`${xe}\` MCP tool with its \`workflowId\`, then follow the returned steps in order.
91
+ ${s}`}return r}function Pt(e,t={},n=[]){let r=t.foundationalText??"",o=ue(e),s=new Map;for(let{slug:l,agent:c}of o)s.set(c.id,{slug:l,description:c.description});let i=new Map,a=new Set;for(let l of n){let c=l.memberAgentIds.map(w=>s.get(w)).filter(w=>!!w),g=Jn(l,c),E=i.get(l.leadAgentId)??[];E.push(g),i.set(l.leadAgentId,E),l.linkedWorkflows?.length&&a.add(l.leadAgentId)}return o.map(({slug:l,agent:c})=>{let g=i.get(c.id),E=!!g&&g.length>0,w=a.has(c.id),p=E?[Ae(c,r),...g].join(`
93
92
 
94
93
  ---
95
94
 
96
- `):Re(c,r);return{relPath:`agents/${l}.md`,content:xn(c,E,w)+p}})}function Ln(e){return e.arguments.length?e.arguments.map(t=>t.required?`<${t.name}>`:`[${t.name}]`).join(" "):""}function In(e){let t=[`description: "${e.description.replace(/"/g,'\\"')}"`],n=Ln(e);return n&&t.push(`argument-hint: ${n}`),`---
95
+ `):Ae(c,r);return{relPath:`agents/${l}.md`,content:qn(c,E,w)+p}})}function Vn(e){return e.arguments.length?e.arguments.map(t=>t.required?`<${t.name}>`:`[${t.name}]`).join(" "):""}function Xn(e){let t=[`description: "${e.description.replace(/"/g,'\\"')}"`],n=Vn(e);return n&&t.push(`argument-hint: ${n}`),`---
97
96
  ${t.join(`
98
97
  `)}
99
98
  ---
100
99
 
101
- `}function Dn(e,t){let n=`This is the SuperClawd command **${e.name}**. Its content is managed in
100
+ `}function zn(e,t){let n=`This is the SuperClawd command **${e.name}**. Its content is managed in
102
101
  SuperClawd and fetched on use.
103
102
 
104
103
  **REQUIRED \u2014 do this now:**
@@ -108,11 +107,11 @@ SuperClawd and fetched on use.
108
107
 
109
108
  Do not improvise the command from this description.
110
109
  `,r=e.team;if(r&&t.has(r.leadAgentId)){let o=t.get(r.leadAgentId);return`## Team: ${r.name}
111
- Run this command WITH the **${r.name}** agent team. Delegate the task to its lead \`${ie(o)}\` via the Agent tool \u2014 the lead will decompose it, fan out to its members, and synthesize \u2014 then return the lead's result. Do the work through the team rather than alone. Call the Agent tool and use the result it returns directly; do NOT run the lead as a background agent or poll for a "\`.done\`"/completion file (there is none \u2014 it will hang).
110
+ Run this command WITH the **${r.name}** agent team. Delegate the task to its lead \`${ce(o)}\` via the Agent tool \u2014 the lead will decompose it, fan out to its members, and synthesize \u2014 then return the lead's result. Do the work through the team rather than alone. Call the Agent tool and use the result it returns directly; do NOT run the lead as a background agent or poll for a "\`.done\`"/completion file (there is none \u2014 it will hang).
112
111
 
113
112
  ---
114
113
 
115
- `+n}return n}function ht(e,t){let n=new Map(ce(t).map(({slug:s,agent:i})=>[i.id,s])),r=new Set,o=[];for(let s of e){let i=x(s.name),a=2;for(;r.has(i);)i=`${x(s.name)}-${a++}`;r.add(i),o.push({relPath:`commands/${i}.md`,content:In(s)+Dn(s,n)})}return o}function On(e,t){let n=e.mode==="reference",r=(e.description??e.name).trim().replace(/\.$/,""),o=(n?`${r}. Read the '${e.name}' SuperClawd reference workflow to understand how this works (do not execute it).`:`${r}. Runs the '${e.name}' SuperClawd workflow.`).replace(/"/g,'\\"'),s=n?`# ${e.name} (SuperClawd workflow \u2014 REFERENCE)
114
+ `+n}return n}function _t(e,t){let n=new Map(ue(t).map(({slug:s,agent:i})=>[i.id,s])),r=new Set,o=[];for(let s of e){let i=$(s.name),a=2;for(;r.has(i);)i=`${$(s.name)}-${a++}`;r.add(i),o.push({relPath:`commands/${i}.md`,content:Xn(s)+zn(s,n)})}return o}function Qn(e,t){let n=e.mode==="reference",r=(e.description??e.name).trim().replace(/\.$/,""),o=(n?`${r}. Read the '${e.name}' SuperClawd reference workflow to understand how this works (do not execute it).`:`${r}. Runs the '${e.name}' SuperClawd workflow.`).replace(/"/g,'\\"'),s=n?`# ${e.name} (SuperClawd workflow \u2014 REFERENCE)
116
115
 
117
116
  This is a **structured explanation** of how a system or flow works \u2014 NOT a procedure to run.
118
117
 
@@ -136,7 +135,7 @@ description: "${o}"
136
135
  user-invocable: false
137
136
  ---
138
137
 
139
- ${s}`}}function Tn(e,t){let n=e.mode==="reference",r=n?`Read the SuperClawd reference workflow **${e.name}** to understand how it works:
138
+ ${s}`}}function Zn(e,t){let n=e.mode==="reference",r=n?`Read the SuperClawd reference workflow **${e.name}** to understand how it works:
140
139
 
141
140
  1. Call the \`get_workflow\` tool with \`workflowId\`: \`${e.id}\`.
142
141
  2. **Read** the returned steps to understand the flow \u2014 do not execute them.
@@ -148,7 +147,7 @@ ${s}`}}function Tn(e,t){let n=e.mode==="reference",r=n?`Read the SuperClawd refe
148
147
  description: "${o}"
149
148
  ---
150
149
 
151
- ${r}`}}function wt(e){let t=new Set,n=[];for(let r of e){let o=x(r.name),s=2;for(;t.has(o);)o=`${x(r.name)}-${s++}`;t.add(o),n.push(On(r,o)),n.push(Tn(r,o))}return n}var Un=`---
150
+ ${r}`}}function vt(e){let t=new Set,n=[];for(let r of e){let o=$(r.name),s=2;for(;t.has(o);)o=`${$(r.name)}-${s++}`;t.add(o),n.push(Qn(r,o)),n.push(Zn(r,o))}return n}var er=`---
152
151
  description: Audit this session against your active SuperClawd directives.
153
152
  ---
154
153
 
@@ -160,7 +159,7 @@ Audit the work done so far in this session against your active SuperClawd direct
160
159
  4. Flag anything relevant you may have skipped \u2014 and if so, fetch and apply/run it now.
161
160
 
162
161
  Be concise; this is a compliance check, not a code review.
163
- `,Wn=`---
162
+ `,tr=`---
164
163
  description: Show SuperClawd service status, workspace info, and credit balance.
165
164
  ---
166
165
 
@@ -171,14 +170,14 @@ Give me a concise SuperClawd status overview. Call these tools and summarize the
171
170
  3. \`check_balance\` \u2014 current credit balance.
172
171
 
173
172
  Present it as a tidy summary; do not take any other action.
174
- `,Nn=`---
173
+ `,nr=`---
175
174
  description: Toggle SuperClawd notifications for this session.
176
175
  ---
177
176
 
178
177
  The user wants to flip SuperClawd notifications for this session.
179
178
 
180
179
  Call the \`notifications\` tool (no arguments \u2014 it toggles the current on/off state), then report the resulting state in one short line. Do not take any other action.
181
- `,Gn=`---
180
+ `,rr=`---
182
181
  description: Apply maximum extended thinking (ultrathink) to the work at hand.
183
182
  argument-hint: "[task or question]"
184
183
  ---
@@ -186,60 +185,60 @@ argument-hint: "[task or question]"
186
185
  To perform this work, please ultrathink \u2014 reason as deeply and carefully as you can before acting. Surface edge cases, weigh alternatives, and check your assumptions.
187
186
 
188
187
  $ARGUMENTS
189
- `;function St(){return[{relPath:"commands/audit-work.md",content:Un},{relPath:"commands/status.md",content:Wn},{relPath:"commands/notifications.md",content:Nn},{relPath:"commands/ultrathink.md",content:Gn}]}import{existsSync as jn,readFileSync as Fn,writeFileSync as Kn,chmodSync as Yn,mkdirSync as Bn}from"node:fs";import{execSync as Hn}from"node:child_process";import{dirname as qn,join as kt}from"node:path";function Ct(e){let t="hooks/foundational-fallback.txt",n=`${e.pluginDir}/${t}`,r=`${e.pluginDir}/hooks/reminder-context.txt`,o=`${e.pluginDir}/stepcount`,s=h=>({type:"command",command:`node "${e.helperPath}" ${h}`}),i=h=>({...s(h),async:!0}),a={SessionStart:[{hooks:[s(`foundational "${n}" SessionStart`)]}],Notification:[{matcher:"permission_prompt|elicitation_dialog|elicitation_complete|elicitation_response|auth_success",hooks:[i(`notify-local attention "${e.launchId}"`),i(`notify attention "${e.launchId}"`)]}],Stop:[{hooks:[i(`notify-local stop "${e.launchId}"`)]}],SessionEnd:[{hooks:[i(`notify completion "${e.launchId}"`)]}]},l=[{relPath:t,content:e.foundational.text??""}],c=Number(process.env.SUPERCLAWD_REMIND_EVERY??8),g=process.env.SUPERCLAWD_REPO_MEMORY!=="0",E=process.env.SUPERCLAWD_AGENT_MEMORY!=="0",w=process.env.SUPERCLAWD_PRIVATE_MEMORY==="1",p=process.env.SUPERCLAWD_NO_CAPTURE==="1",f=!p&&!!process.env.SUPERCLAWD_REPO_FINGERPRINT&&(g||w),d=(e.foundational.text??"").trim(),A=d?`REMINDER \u2014 these SuperClawd always-rules remain in effect:
190
- ${d}`:"";if(c>0&&A&&(a.PostToolUse=[{matcher:"*",hooks:[s(`remind "${r}" "${o}"`)]}],l.push({relPath:"hooks/reminder-context.txt",content:A})),f){let h={hooks:[i(`capture "${e.launchId}"`)]};a.Stop.push(h),a.SessionEnd.push(h)}let u=e.agents??[];if(!p&&E&&u.length){let h="hooks/agent-map.json",m=`${e.pluginDir}/${h}`;l.push({relPath:h,content:JSON.stringify(mt(u))}),a.SubagentStop=[{hooks:[i(`capture-agent "${m}" "${e.launchId}"`)]}]}let S=[];if(e.gate&&S.push({matcher:`${se}.*`,hooks:[s("gate")]}),e.guardrails?.length){let h="hooks/guardrails.json",m=`${e.pluginDir}/${h}`;l.push({relPath:h,content:JSON.stringify(e.guardrails,null,2)}),S.push({matcher:"*",hooks:[s(`guardrails "${m}"`)]})}if(e.policyGuardrails?.length){let h="hooks/policy-guardrails.json",m=`${e.pluginDir}/${h}`;l.push({relPath:h,content:JSON.stringify(e.policyGuardrails,null,2)}),S.push({matcher:"Bash",hooks:[s(`policy "${m}"`)]})}return process.env.SUPERCLAWD_AUTO_RETRIEVE!=="0"&&(a.UserPromptSubmit=[{hooks:[s("retrieve prompt")]}],S.push({matcher:"Read",hooks:[s("retrieve file")]})),S.length&&(a.PreToolUse=S),l.push({relPath:"hooks/hooks.json",content:JSON.stringify({hooks:a},null,2)}),l}var yt="# superclawd-report-commit";function Et(e){return`'${String(e).replace(/'/g,"'\\''")}'`}function Rt(e){let{cwd:t,helperPath:n,env:r}=e,o="";try{let c=Hn("git rev-parse --git-path hooks",{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();c&&(o=c.startsWith("/")?c:kt(t,c))}catch{return{installed:!1,reason:"not a git repo"}}if(!o)return{installed:!1,reason:"no hooks dir"};let s=kt(o,"post-commit");if(jn(s)){let c="";try{c=Fn(s,"utf8")}catch{return{installed:!1,reason:"post-commit unreadable; skipped"}}if(!c.includes(yt))return{installed:!1,reason:"existing user post-commit hook; skipped"}}let a=["SUPERCLAWD_BACKEND","SUPERCLAWD_MCP_API_URL","SUPERCLAWD_REPO_FINGERPRINT","SUPERCLAWD_MCP_KEY","SUPERCLAWD_MCP_SECRET","SUPERCLAWD_MCP_WORKSPACE","NODE_EXTRA_CA_CERTS","SUPERCLAWD_HOME","SUPERCLAWD_CLAUDE_BIN","SUPERCLAWD_POLICY_MODEL"].filter(c=>r[c]!==void 0&&r[c]!=="").map(c=>`export ${c}=${Et(r[c])}`).join(`
188
+ `;function bt(){return[{relPath:"commands/audit-work.md",content:er},{relPath:"commands/status.md",content:tr},{relPath:"commands/notifications.md",content:nr},{relPath:"commands/ultrathink.md",content:rr}]}import{existsSync as or,readFileSync as sr,writeFileSync as ir,chmodSync as ar,mkdirSync as cr}from"node:fs";import{execSync as lr}from"node:child_process";import{dirname as ur,join as At}from"node:path";function $t(e){let t="hooks/foundational-fallback.txt",n=`${e.pluginDir}/${t}`,r=`${e.pluginDir}/hooks/reminder-context.txt`,o=`${e.pluginDir}/stepcount`,s=h=>({type:"command",command:`node "${e.helperPath}" ${h}`}),i=h=>({...s(h),async:!0}),a={SessionStart:[{hooks:[s(`foundational "${n}" SessionStart`)]}],Notification:[{matcher:"permission_prompt|elicitation_dialog|elicitation_complete|elicitation_response|auth_success",hooks:[i(`notify-local attention "${e.launchId}"`),i(`notify attention "${e.launchId}"`)]}],Stop:[{hooks:[i(`notify-local stop "${e.launchId}"`)]}],SessionEnd:[{hooks:[i(`notify completion "${e.launchId}"`)]}]},l=[{relPath:t,content:e.foundational.text??""}],c=Number(process.env.SUPERCLAWD_REMIND_EVERY??8),g=process.env.SUPERCLAWD_REPO_MEMORY!=="0",E=process.env.SUPERCLAWD_AGENT_MEMORY!=="0",w=process.env.SUPERCLAWD_PRIVATE_MEMORY==="1",p=process.env.SUPERCLAWD_NO_CAPTURE==="1",f=!p&&!!process.env.SUPERCLAWD_REPO_FINGERPRINT&&(g||w),d=(e.foundational.text??"").trim(),A=d?`REMINDER \u2014 these SuperClawd always-rules remain in effect:
189
+ ${d}`:"";if(c>0&&A&&(a.PostToolUse=[{matcher:"*",hooks:[s(`remind "${r}" "${o}"`)]}],l.push({relPath:"hooks/reminder-context.txt",content:A})),f){let h={hooks:[i(`capture "${e.launchId}"`)]};a.Stop.push(h),a.SessionEnd.push(h)}let u=e.agents??[];if(!p&&E&&u.length){let h="hooks/agent-map.json",m=`${e.pluginDir}/${h}`;l.push({relPath:h,content:JSON.stringify(Rt(u))}),a.SubagentStop=[{hooks:[i(`capture-agent "${m}" "${e.launchId}"`)]}]}let S=[];if(e.gate&&S.push({matcher:`${ae}.*`,hooks:[s("gate")]}),e.guardrails?.length){let h="hooks/guardrails.json",m=`${e.pluginDir}/${h}`;l.push({relPath:h,content:JSON.stringify(e.guardrails,null,2)}),S.push({matcher:"*",hooks:[s(`guardrails "${m}"`)]})}if(e.policyGuardrails?.length){let h="hooks/policy-guardrails.json",m=`${e.pluginDir}/${h}`;l.push({relPath:h,content:JSON.stringify(e.policyGuardrails,null,2)}),S.push({matcher:"Bash",hooks:[s(`policy "${m}"`)]})}return process.env.SUPERCLAWD_AUTO_RETRIEVE!=="0"&&(a.UserPromptSubmit=[{hooks:[s("retrieve prompt")]}],S.push({matcher:"Read",hooks:[s("retrieve file")]})),S.length&&(a.PreToolUse=S),l.push({relPath:"hooks/hooks.json",content:JSON.stringify({hooks:a},null,2)}),l}var Mt="# superclawd-report-commit";function xt(e){return`'${String(e).replace(/'/g,"'\\''")}'`}function Lt(e){let{cwd:t,helperPath:n,env:r}=e,o="";try{let c=lr("git rev-parse --git-path hooks",{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();c&&(o=c.startsWith("/")?c:At(t,c))}catch{return{installed:!1,reason:"not a git repo"}}if(!o)return{installed:!1,reason:"no hooks dir"};let s=At(o,"post-commit");if(or(s)){let c="";try{c=sr(s,"utf8")}catch{return{installed:!1,reason:"post-commit unreadable; skipped"}}if(!c.includes(Mt))return{installed:!1,reason:"existing user post-commit hook; skipped"}}let a=["SUPERCLAWD_BACKEND","SUPERCLAWD_MCP_API_URL","SUPERCLAWD_REPO_FINGERPRINT","SUPERCLAWD_MCP_KEY","SUPERCLAWD_MCP_SECRET","SUPERCLAWD_MCP_WORKSPACE","NODE_EXTRA_CA_CERTS","SUPERCLAWD_HOME","SUPERCLAWD_CLAUDE_BIN","SUPERCLAWD_POLICY_MODEL"].filter(c=>r[c]!==void 0&&r[c]!=="").map(c=>`export ${c}=${xt(r[c])}`).join(`
191
190
  `),l=`#!/bin/sh
192
- ${yt}
191
+ ${Mt}
193
192
  # Auto-generated by superclawd \u2014 reports Learned Memory staleness after each
194
193
  # commit. Safe to delete; superclawd will not recreate it if you replace it.
195
194
  ${a}
196
- node ${Et(n)} report-commit >/dev/null 2>&1 &
197
- `;try{Bn(qn(s),{recursive:!0}),Kn(s,l),Yn(s,493)}catch(c){return{installed:!1,reason:`write failed: ${String(c)}`}}return{installed:!0,reason:"installed"}}import{spawn as ve,spawnSync as Vn}from"node:child_process";import b from"node:fs";import v from"node:path";import{fileURLToPath as Jn}from"node:url";import{createRequire as Xn}from"node:module";var Ae=v.join(U,"pipelines.pid"),Me=v.join(U,"pipelines.port"),_t=v.join(U,"pipelines.log"),zn=v.join(U,"pipelines-mcp.json"),xt=63210,$t=2e4;function Qn(e){let t="",n=null,r=!1;for(let o=0;o<e.length;o++){let s=e[o],i=e[o+1];if(s==="--port"||s==="-p"){let a=Number(i);i&&Number.isInteger(a)&&a>0&&a<65536&&(n=a,o++)}else s==="-d"||s==="--detach"?r=!0:!s.startsWith("-")&&!t&&(t=s)}return{sub:t,port:n,detach:r}}function be(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function Pt(e){try{let t=Number(b.readFileSync(e,"utf8").trim());return Number.isInteger(t)&&t>0?t:null}catch{return null}}function le(){let e=Pt(Ae),t=Pt(Me);return{pid:e,port:t,alive:e!==null&&be(e)}}function Zn(){try{let e=JSON.parse(b.readFileSync(zn,"utf8"));return e&&typeof e=="object"?e:null}catch{return null}}function Lt(){if(!Ye())return null;let e=Zn(),t=e?.port??xt,n=e?.token;return{name:"pipelines",type:"http",url:`http://127.0.0.1:${t}/mcp`,...n?{headers:{Authorization:`Bearer ${n}`}}:{}}}function vt(e,t){b.mkdirSync(U,{recursive:!0}),b.writeFileSync(Ae,String(e)),b.writeFileSync(Me,String(t))}function V(){for(let e of[Ae,Me])try{b.unlinkSync(e)}catch{}}function er(){let e=process.env.SUPERCLAWD_PIPELINES_DIR;if(e)return b.existsSync(e)?e:null;let t=v.dirname(Jn(import.meta.url));for(let n=0;n<8;n++){let r=v.join(t,"apps","pipelines");if(b.existsSync(v.join(r,"server","index.ts"))||b.existsSync(v.join(r,"dist-server","index.mjs")))return r;let o=v.dirname(t);if(o===t)break;t=o}try{let n=Xn(import.meta.url),r=v.dirname(n.resolve("@superclawd-ai/pipelines/package.json"));if(b.existsSync(v.join(r,"dist-server","index.mjs")))return r}catch{}return null}function tr(e){let t=[v.join(e,"node_modules",".bin","tsx"),v.join(e,"..","..","node_modules",".bin","tsx")];for(let n of t)if(b.existsSync(n))return n;return"tsx"}function nr(){let e=er();if(!e)return null;let t=v.join(e,"dist-server","index.mjs");if(b.existsSync(t))return{cmd:process.execPath,args:[t],cwd:e};let n=v.join(e,"server","index.ts");return b.existsSync(n)?{cmd:tr(e),args:[n],cwd:e}:null}async function bt(e,t=$t){let n=Date.now()+t;for(;Date.now()<n;){if(await It(e))return!0;await new Promise(r=>setTimeout(r,250))}return!1}async function It(e){let t=new AbortController,n=setTimeout(()=>t.abort(),1e3);try{return(await fetch(`http://localhost:${e}/api/session`,{signal:t.signal})).ok}catch{return!1}finally{clearTimeout(n)}}function At(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{ve(t,[e],{stdio:"ignore",detached:!0,shell:process.platform==="win32"}).unref()}catch{}}function O(e){process.stdout.write(e+`
195
+ node ${xt(n)} report-commit >/dev/null 2>&1 &
196
+ `;try{cr(ur(s),{recursive:!0}),ir(s,l),ar(s,493)}catch(c){return{installed:!1,reason:`write failed: ${String(c)}`}}return{installed:!0,reason:"installed"}}import{spawn as $e,spawnSync as Nt}from"node:child_process";import v from"node:fs";import _ from"node:path";import{fileURLToPath as pr}from"node:url";import{createRequire as dr}from"node:module";var j="@superclawd-ai/pipelines",Ie=_.join(x,"pipelines.pid"),De=_.join(x,"pipelines.port"),It=_.join(x,"pipelines.log"),fr=_.join(x,"pipelines-mcp.json"),Gt=63210,jt=2e4;function mr(e){let t="",n=null,r=!1;for(let o=0;o<e.length;o++){let s=e[o],i=e[o+1];if(s==="--port"||s==="-p"){let a=Number(i);i&&Number.isInteger(a)&&a>0&&a<65536&&(n=a,o++)}else s==="-d"||s==="--detach"?r=!0:!s.startsWith("-")&&!t&&(t=s)}return{sub:t,port:n,detach:r}}function Le(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function Dt(e){try{let t=Number(v.readFileSync(e,"utf8").trim());return Number.isInteger(t)&&t>0?t:null}catch{return null}}function pe(){let e=Dt(Ie),t=Dt(De);return{pid:e,port:t,alive:e!==null&&Le(e)}}function gr(){try{let e=JSON.parse(v.readFileSync(fr,"utf8"));return e&&typeof e=="object"?e:null}catch{return null}}function Ft(){if(!Ve())return null;let e=gr(),t=e?.port??Gt,n=e?.token;return{name:"pipelines",type:"http",url:`http://127.0.0.1:${t}/mcp`,...n?{headers:{Authorization:`Bearer ${n}`}}:{}}}function Tt(e,t){v.mkdirSync(x,{recursive:!0}),v.writeFileSync(Ie,String(e)),v.writeFileSync(De,String(t))}function X(){for(let e of[Ie,De])try{v.unlinkSync(e)}catch{}}function Kt(){let e=process.env.SUPERCLAWD_PIPELINES_DIR;if(e)return v.existsSync(e)?e:null;let t=_.dirname(pr(import.meta.url));for(let n=0;n<8;n++){let r=_.join(t,"apps","pipelines");if(v.existsSync(_.join(r,"server","index.ts"))||v.existsSync(_.join(r,"dist-server","index.mjs")))return r;let o=_.dirname(t);if(o===t)break;t=o}try{let n=dr(import.meta.url),r=_.dirname(n.resolve("@superclawd-ai/pipelines/package.json"));if(v.existsSync(_.join(r,"dist-server","index.mjs")))return r}catch{}return null}function hr(e){let t=[_.join(e,"node_modules",".bin","tsx"),_.join(e,"..","..","node_modules",".bin","tsx")];for(let n of t)if(v.existsSync(n))return n;return"tsx"}function wr(){let e=Kt();if(!e)return null;let t=_.join(e,"dist-server","index.mjs");if(v.existsSync(t))return{cmd:process.execPath,args:[t],cwd:e};let n=_.join(e,"server","index.ts");return v.existsSync(n)?{cmd:hr(e),args:[n],cwd:e}:null}async function Ot(e,t=jt){let n=Date.now()+t;for(;Date.now()<n;){if(await Yt(e))return!0;await new Promise(r=>setTimeout(r,250))}return!1}async function Yt(e){let t=new AbortController,n=setTimeout(()=>t.abort(),1e3);try{return(await fetch(`http://localhost:${e}/api/session`,{signal:t.signal})).ok}catch{return!1}finally{clearTimeout(n)}}function Ut(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{$e(t,[e],{stdio:"ignore",detached:!0,shell:process.platform==="win32"}).unref()}catch{}}function L(e){process.stdout.write(e+`
198
197
  `)}function F(e){process.stderr.write(e+`
199
- `)}async function rr(e){let t=le(),n=a=>`http://localhost:${a}`;if(t.alive&&t.port)return O(`Pipelines is already running (pid ${t.pid}) at ${n(t.port)}`),e.detach||At(n(t.port)),0;t.pid&&!t.alive&&V();let r=nr();if(!r)return F(`\u2717 Couldn't locate the Pipelines app.
200
- Set SUPERCLAWD_PIPELINES_DIR to its directory (the one containing server/index.ts).`),1;let o=e.port??xt,s={...process.env,PIPELINES_PORT:String(o)};if(e.detach){b.mkdirSync(U,{recursive:!0});let a=b.openSync(_t,"a"),l=ve(r.cmd,r.args,{cwd:r.cwd,env:s,detached:!0,stdio:["ignore",a,a]});return l.unref(),l.pid?(vt(l.pid,o),await bt(o)?(O(`\u2713 Pipelines started (pid ${l.pid}) at ${n(o)}`),0):(F(`\u2717 Daemon didn't become ready within ${$t/1e3}s. See ${_t}`),1)):(F("\u2717 Failed to spawn the Pipelines daemon."),1)}O(`Starting Pipelines at ${n(o)} \u2026 (Ctrl-C to stop)`);let i=ve(r.cmd,r.args,{cwd:r.cwd,env:s,stdio:"inherit"});return i.pid&&vt(i.pid,o),bt(o).then(a=>{a&&At(n(o))}),await new Promise(a=>{i.on("error",l=>{F(`\u2717 Could not launch the daemon: ${l.message}`),V(),a(1)}),i.on("close",l=>{V(),a(l??0)})})}async function or(){let e=le();if(!e.pid||!e.alive)return O("Pipelines is not running."),V(),0;let t=n=>{try{process.kill(-e.pid,n)}catch{try{process.kill(e.pid,n)}catch{}}};t("SIGTERM");for(let n=0;n<40&&be(e.pid);n++)await new Promise(r=>setTimeout(r,100));return be(e.pid)&&t("SIGKILL"),V(),O("\u2713 Pipelines stopped."),0}async function sr(){let e=le();if(!e.alive)return O("Pipelines: stopped."),0;let t=e.port?await It(e.port):!1;return O(`Pipelines: running (pid ${e.pid}) on port ${e.port??"?"} \u2014 `+(t?"responding \u2713":"not responding yet")),0}function ir(){if(le().alive)return F("\u2717 Stop the daemon first: superclawd pipelines stop"),1;O("Updating superclawd (npm i -g superclawd@latest) \u2026");let t=Vn("npm install -g superclawd@latest",{stdio:"inherit",shell:!0});return t.status!==0?(F(`\u2717 Update failed (npm exited ${t.status??"?"}).`),t.status??1):(O("\u2713 Updated. Start again with: superclawd pipelines start"),0)}function Mt(){return["superclawd pipelines \u2014 run the local Pipelines app",""," start [--port <n>] [-d] Start the daemon (foreground; -d detaches). Opens the browser."," stop Stop the running daemon."," status Show whether the daemon is running."," update Update superclawd (daemon must be stopped)."].join(`
201
- `)}async function Dt(e){let t=Qn(e);switch(t.sub){case"start":return rr(t);case"stop":return or();case"status":return sr();case"update":return ir();case"":case"help":return O(Mt()),0;default:return F(`Unknown pipelines command: ${t.sub}`),O(Mt()),1}}function ur(e){let t={},n=[];for(let r of e){if(!r.name||r.name===oe||r.name===q||t[r.name])continue;let o={};r.type==="http"?(o.type="http",o.url=r.url,r.headers&&Object.keys(r.headers).length&&(o.headers=r.headers)):(o.command=r.command,r.args&&r.args.length&&(o.args=r.args)),r.env&&Object.keys(r.env).length&&(o.env=r.env),t[r.name]=o,n.push(r.name)}return{map:t,names:n}}function pr(e,t,n,r,o){let s={SUPERCLAWD_BACKEND:H,SUPERCLAWD_MCP_API_URL:B,SUPERCLAWD_SESSION_ID:n};return k||(s.SUPERCLAWD_MCP_KEY=e.keyId,s.SUPERCLAWD_MCP_SECRET=e.secret,s.SUPERCLAWD_MCP_WORKSPACE=e.workspace),process.env.NODE_EXTRA_CA_CERTS&&(s.NODE_EXTRA_CA_CERTS=process.env.NODE_EXTRA_CA_CERTS),process.env.SUPERCLAWD_HOME&&(s.SUPERCLAWD_HOME=process.env.SUPERCLAWD_HOME),process.env.SUPERCLAWD_LOG_FILE&&(s.SUPERCLAWD_LOG_FILE=process.env.SUPERCLAWD_LOG_FILE),process.env.SUPERCLAWD_DEBUG&&(s.SUPERCLAWD_DEBUG=process.env.SUPERCLAWD_DEBUG),process.env.SUPERCLAWD_MOCK_TIER&&(s.SUPERCLAWD_MOCK_TIER=process.env.SUPERCLAWD_MOCK_TIER),process.env.SUPERCLAWD_MOCK_BALANCE&&(s.SUPERCLAWD_MOCK_BALANCE=process.env.SUPERCLAWD_MOCK_BALANCE),process.env.SUPERCLAWD_EXPERIMENTAL&&(s.SUPERCLAWD_EXPERIMENTAL=process.env.SUPERCLAWD_EXPERIMENTAL),process.env.SUPERCLAWD_REPO_FINGERPRINT&&(s.SUPERCLAWD_REPO_FINGERPRINT=process.env.SUPERCLAWD_REPO_FINGERPRINT),process.env.SUPERCLAWD_TEAM_MEMORY&&(s.SUPERCLAWD_TEAM_MEMORY=process.env.SUPERCLAWD_TEAM_MEMORY),process.env.SUPERCLAWD_REPO_MEMORY&&(s.SUPERCLAWD_REPO_MEMORY=process.env.SUPERCLAWD_REPO_MEMORY),process.env.SUPERCLAWD_AGENT_MEMORY&&(s.SUPERCLAWD_AGENT_MEMORY=process.env.SUPERCLAWD_AGENT_MEMORY),process.env.SUPERCLAWD_PRIVATE_MEMORY&&(s.SUPERCLAWD_PRIVATE_MEMORY=process.env.SUPERCLAWD_PRIVATE_MEMORY),process.env.SUPERCLAWD_PIPELINES_TOOLS&&(s.SUPERCLAWD_PIPELINES_TOOLS=process.env.SUPERCLAWD_PIPELINES_TOOLS),process.env.SUPERCLAWD_PIPELINES_URL&&(s.SUPERCLAWD_PIPELINES_URL=process.env.SUPERCLAWD_PIPELINES_URL),process.env.SUPERCLAWD_PIPELINES_TICKET&&(s.SUPERCLAWD_PIPELINES_TICKET=process.env.SUPERCLAWD_PIPELINES_TICKET),r.length&&(s.SUPERCLAWD_RESOURCES=JSON.stringify(r.map(a=>({name:a.name,description:a.description})))),{relPath:".claude-plugin/plugin.json",content:JSON.stringify({name:q,description:"SuperClawd skills + live, metered directives for Claude Code.",mcpServers:{[oe]:{command:"node",args:[t],env:s},...o}},null,2)}}function Ut(e){let{pluginDir:t,session:n,catalog:r,serverPath:o,launchId:s}=e,i=Tt(Ot(o),"hook-helper.mjs"),a=process.env.SUPERCLAWD_GATE==="1",l=ur(r.mcpServers),c=Lt();if(c&&!l.map[c.name]){let w={type:"http",url:c.url};c.headers&&(w.headers=c.headers),l.map[c.name]=w,l.names.push(c.name)}let g=[pr(n,o,s,r.resources,l.map),...pt(r.skills),...gt(r.agents,{foundationalText:r.foundational.text},r.agentTeams),...ht(r.commands,r.agents),...wt(r.workflows),...St(),...Ct({foundational:r.foundational,helperPath:i,pluginDir:t,launchId:s,gate:a,guardrails:r.guardrails,policyGuardrails:r.policyGuardrails,agents:r.agents})],E=[];for(let w of g){let p=Tt(t,w.relPath);ar(Ot(p),{recursive:!0}),cr(p,w.content),w.executable&&lr(p,493),E.push(w.relPath)}return{pluginDir:t,skillCount:r.skills.length,agentCount:r.agents.length,commandCount:r.commands.length,workflowCount:r.workflows.length,mcpServerNames:l.names,files:E}}import{mkdirSync as dr,rmSync as Wt,readdirSync as fr,statSync as mr}from"node:fs";import{join as xe}from"node:path";import{randomBytes as gr}from"node:crypto";function Nt(){let e=`${Date.now().toString(36)}-${gr(4).toString("hex")}`,t=xe(te,e),n=xe(t,"plugin");return dr(n,{recursive:!0}),{id:e,dir:t,pluginDir:n}}function Gt(e){try{Wt(e.dir,{recursive:!0,force:!0})}catch{}}function jt(e=Date.now()){let t=0,n=[];try{n=fr(te)}catch{return 0}for(let r of n){let o=xe(te,r);try{e-mr(o).mtimeMs>Ve&&(Wt(o,{recursive:!0,force:!0}),t++)}catch{}}return t}import{hostname as hr}from"node:os";import{spawn as wr}from"node:child_process";var Sr=e=>new Promise(t=>setTimeout(t,e));function kr(e){try{let t=process.platform,o=wr(t==="darwin"?"open":t==="win32"?"cmd":"xdg-open",t==="win32"?["/c","start","",e]:[e],{stdio:"ignore",detached:!0});o.on("error",()=>{}),o.unref()}catch{}}async function Ft(){if(k)return process.stdout.write(`Mock mode \u2014 login is not needed.
202
- `),{ok:!0};let e=We(),t=hr()||"Unknown device",n;try{let c=await fetch(`${ee}/api/auth/cli/device/start`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({machineId:e,hostname:t})});if(!c.ok)return{ok:!1,error:`Couldn't start login (HTTP ${c.status}).`};n=await c.json()}catch{return{ok:!1,error:`Couldn't reach ${ee}.`}}let r=n.verification_uri_complete||n.verification_uri;process.stdout.write(`
198
+ `)}async function Sr(e){let t=pe(),n=a=>`http://localhost:${a}`;if(t.alive&&t.port)return L(`Pipelines is already running (pid ${t.pid}) at ${n(t.port)}`),e.detach||Ut(n(t.port)),0;t.pid&&!t.alive&&X(),await Cr(!!process.stdin.isTTY&&!e.detach);let r=wr();if(!r)return F(`\u2717 Couldn't locate the Pipelines app.
199
+ Set SUPERCLAWD_PIPELINES_DIR to its directory (the one containing server/index.ts).`),1;let o=e.port??Gt,s={...process.env,PIPELINES_PORT:String(o)};if(e.detach){v.mkdirSync(x,{recursive:!0});let a=v.openSync(It,"a"),l=$e(r.cmd,r.args,{cwd:r.cwd,env:s,detached:!0,stdio:["ignore",a,a]});return l.unref(),l.pid?(Tt(l.pid,o),await Ot(o)?(L(`\u2713 Pipelines started (pid ${l.pid}) at ${n(o)}`),0):(F(`\u2717 Daemon didn't become ready within ${jt/1e3}s. See ${It}`),1)):(F("\u2717 Failed to spawn the Pipelines daemon."),1)}L(`Starting Pipelines at ${n(o)} \u2026 (Ctrl-C to stop)`);let i=$e(r.cmd,r.args,{cwd:r.cwd,env:s,stdio:"inherit"});return i.pid&&Tt(i.pid,o),Ot(o).then(a=>{a&&Ut(n(o))}),await new Promise(a=>{i.on("error",l=>{F(`\u2717 Could not launch the daemon: ${l.message}`),X(),a(1)}),i.on("close",l=>{X(),a(l??0)})})}async function kr(){let e=pe();if(!e.pid||!e.alive)return L("Pipelines is not running."),X(),0;let t=n=>{try{process.kill(-e.pid,n)}catch{try{process.kill(e.pid,n)}catch{}}};t("SIGTERM");for(let n=0;n<40&&Le(e.pid);n++)await new Promise(r=>setTimeout(r,100));return Le(e.pid)&&t("SIGKILL"),X(),L("\u2713 Pipelines stopped."),0}async function yr(){let e=pe();if(!e.alive)return L("Pipelines: stopped."),0;let t=e.port?await Yt(e.port):!1;return L(`Pipelines: running (pid ${e.pid}) on port ${e.port??"?"} \u2014 `+(t?"responding \u2713":"not responding yet")),0}function Er(e){try{return JSON.parse(v.readFileSync(_.join(e,"package.json"),"utf8")).version??null}catch{return null}}async function Cr(e){if(process.env.SUPERCLAWD_NO_UPDATE||process.env.SUPERCLAWD_BACKEND==="mock")return;let t=Kt(),n=t?Er(t):null;if(!n)return;let r=await Ee(j,n);if(!r)return;let{latest:o}=r;if(!e){Ce("Pipelines",n,o,"superclawd pipelines update"),Y(j);return}if(await Re("Pipelines",n,o)==="run"){Y(j,o);return}Y(j),L(`Updating Pipelines (npm i -g ${j}@latest) \u2026`);let i=Nt(`npm install -g ${j}@latest`,{stdio:"inherit",shell:!0});i.status!==0?F(`\u2717 Update failed (npm exited ${i.status??"?"}). Starting ${n} for now.`):L(`\u2713 Updated to ${o}.`)}function Rr(){if(pe().alive)return F("\u2717 Stop the daemon first: superclawd pipelines stop"),1;L(`Updating Pipelines (npm i -g ${j}@latest) \u2026`);let t=Nt(`npm install -g ${j}@latest`,{stdio:"inherit",shell:!0});return t.status!==0?(F(`\u2717 Update failed (npm exited ${t.status??"?"}).`),t.status??1):(L("\u2713 Updated. Start again with: superclawd pipelines start"),0)}function Wt(){return["superclawd pipelines \u2014 run the local Pipelines app",""," start [--port <n>] [-d] Start the daemon (foreground; -d detaches). Opens the browser."," stop Stop the running daemon."," status Show whether the daemon is running."," update Update the Pipelines app (daemon must be stopped)."].join(`
200
+ `)}async function Bt(e){let t=mr(e);switch(t.sub){case"start":return Sr(t);case"stop":return kr();case"status":return yr();case"update":return Rr();case"":case"help":return L(Wt()),0;default:return F(`Unknown pipelines command: ${t.sub}`),L(Wt()),1}}function br(e){let t={},n=[];for(let r of e){if(!r.name||r.name===ie||r.name===V||t[r.name])continue;let o={};r.type==="http"?(o.type="http",o.url=r.url,r.headers&&Object.keys(r.headers).length&&(o.headers=r.headers)):(o.command=r.command,r.args&&r.args.length&&(o.args=r.args)),r.env&&Object.keys(r.env).length&&(o.env=r.env),t[r.name]=o,n.push(r.name)}return{map:t,names:n}}function Ar(e,t,n,r,o){let s={SUPERCLAWD_BACKEND:J,SUPERCLAWD_MCP_API_URL:q,SUPERCLAWD_SESSION_ID:n};return k||(s.SUPERCLAWD_MCP_KEY=e.keyId,s.SUPERCLAWD_MCP_SECRET=e.secret,s.SUPERCLAWD_MCP_WORKSPACE=e.workspace),process.env.NODE_EXTRA_CA_CERTS&&(s.NODE_EXTRA_CA_CERTS=process.env.NODE_EXTRA_CA_CERTS),process.env.SUPERCLAWD_HOME&&(s.SUPERCLAWD_HOME=process.env.SUPERCLAWD_HOME),process.env.SUPERCLAWD_LOG_FILE&&(s.SUPERCLAWD_LOG_FILE=process.env.SUPERCLAWD_LOG_FILE),process.env.SUPERCLAWD_DEBUG&&(s.SUPERCLAWD_DEBUG=process.env.SUPERCLAWD_DEBUG),process.env.SUPERCLAWD_MOCK_TIER&&(s.SUPERCLAWD_MOCK_TIER=process.env.SUPERCLAWD_MOCK_TIER),process.env.SUPERCLAWD_MOCK_BALANCE&&(s.SUPERCLAWD_MOCK_BALANCE=process.env.SUPERCLAWD_MOCK_BALANCE),process.env.SUPERCLAWD_EXPERIMENTAL&&(s.SUPERCLAWD_EXPERIMENTAL=process.env.SUPERCLAWD_EXPERIMENTAL),process.env.SUPERCLAWD_REPO_FINGERPRINT&&(s.SUPERCLAWD_REPO_FINGERPRINT=process.env.SUPERCLAWD_REPO_FINGERPRINT),process.env.SUPERCLAWD_TEAM_MEMORY&&(s.SUPERCLAWD_TEAM_MEMORY=process.env.SUPERCLAWD_TEAM_MEMORY),process.env.SUPERCLAWD_REPO_MEMORY&&(s.SUPERCLAWD_REPO_MEMORY=process.env.SUPERCLAWD_REPO_MEMORY),process.env.SUPERCLAWD_AGENT_MEMORY&&(s.SUPERCLAWD_AGENT_MEMORY=process.env.SUPERCLAWD_AGENT_MEMORY),process.env.SUPERCLAWD_PRIVATE_MEMORY&&(s.SUPERCLAWD_PRIVATE_MEMORY=process.env.SUPERCLAWD_PRIVATE_MEMORY),process.env.SUPERCLAWD_PIPELINES_TOOLS&&(s.SUPERCLAWD_PIPELINES_TOOLS=process.env.SUPERCLAWD_PIPELINES_TOOLS),process.env.SUPERCLAWD_PIPELINES_URL&&(s.SUPERCLAWD_PIPELINES_URL=process.env.SUPERCLAWD_PIPELINES_URL),process.env.SUPERCLAWD_PIPELINES_TICKET&&(s.SUPERCLAWD_PIPELINES_TICKET=process.env.SUPERCLAWD_PIPELINES_TICKET),r.length&&(s.SUPERCLAWD_RESOURCES=JSON.stringify(r.map(a=>({name:a.name,description:a.description})))),{relPath:".claude-plugin/plugin.json",content:JSON.stringify({name:V,description:"SuperClawd skills + live, metered directives for Claude Code.",mcpServers:{[ie]:{command:"node",args:[t],env:s},...o}},null,2)}}function Jt(e){let{pluginDir:t,session:n,catalog:r,serverPath:o,launchId:s}=e,i=qt(Ht(o),"hook-helper.mjs"),a=process.env.SUPERCLAWD_GATE==="1",l=br(r.mcpServers),c=Ft();if(c&&!l.map[c.name]){let w={type:"http",url:c.url};c.headers&&(w.headers=c.headers),l.map[c.name]=w,l.names.push(c.name)}let g=[Ar(n,o,s,r.resources,l.map),...yt(r.skills),...Pt(r.agents,{foundationalText:r.foundational.text},r.agentTeams),..._t(r.commands,r.agents),...vt(r.workflows),...bt(),...$t({foundational:r.foundational,helperPath:i,pluginDir:t,launchId:s,gate:a,guardrails:r.guardrails,policyGuardrails:r.policyGuardrails,agents:r.agents})],E=[];for(let w of g){let p=qt(t,w.relPath);Pr(Ht(p),{recursive:!0}),_r(p,w.content),w.executable&&vr(p,493),E.push(w.relPath)}return{pluginDir:t,skillCount:r.skills.length,agentCount:r.agents.length,commandCount:r.commands.length,workflowCount:r.workflows.length,mcpServerNames:l.names,files:E}}import{mkdirSync as Mr,rmSync as Vt,readdirSync as xr,statSync as $r}from"node:fs";import{join as Te}from"node:path";import{randomBytes as Lr}from"node:crypto";function Xt(){let e=`${Date.now().toString(36)}-${Lr(4).toString("hex")}`,t=Te(re,e),n=Te(t,"plugin");return Mr(n,{recursive:!0}),{id:e,dir:t,pluginDir:n}}function zt(e){try{Vt(e.dir,{recursive:!0,force:!0})}catch{}}function Qt(e=Date.now()){let t=0,n=[];try{n=xr(re)}catch{return 0}for(let r of n){let o=Te(re,r);try{e-$r(o).mtimeMs>Ze&&(Vt(o,{recursive:!0,force:!0}),t++)}catch{}}return t}import{hostname as Ir}from"node:os";import{spawn as Dr}from"node:child_process";var Tr=e=>new Promise(t=>setTimeout(t,e));function Or(e){try{let t=process.platform,o=Dr(t==="darwin"?"open":t==="win32"?"cmd":"xdg-open",t==="win32"?["/c","start","",e]:[e],{stdio:"ignore",detached:!0});o.on("error",()=>{}),o.unref()}catch{}}async function Zt(){if(k)return process.stdout.write(`Mock mode \u2014 login is not needed.
201
+ `),{ok:!0};let e=Ke(),t=Ir()||"Unknown device",n;try{let c=await fetch(`${ne}/api/auth/cli/device/start`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({machineId:e,hostname:t})});if(!c.ok)return{ok:!1,error:`Couldn't start login (HTTP ${c.status}).`};n=await c.json()}catch{return{ok:!1,error:`Couldn't reach ${ne}.`}}let r=n.verification_uri_complete||n.verification_uri;process.stdout.write(`
203
202
  To authorize this machine, open:
204
203
  ${r}
205
204
 
206
205
  and confirm this code matches: ${n.user_code}
207
206
 
208
- `),kr(r),process.stdout.write(`Waiting for approval\u2026 (Ctrl-C to cancel)
209
- `);let o=(n.interval||5)*1e3,s=Date.now()+(n.expires_in||600)*1e3,i,a;for(;Date.now()<s;){await Sr(o);let c;try{c=await(await fetch(`${ee}/api/auth/cli/device/token`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({deviceCode:n.device_code})})).json()}catch{continue}if(c.status==="approved"){i=c.key_id,a=c.secret;break}if(c.status==="denied")return{ok:!1,error:"Request was denied in the browser."};if(c.status==="expired")return{ok:!1,error:"Login request expired. Run `superclawd login` again."}}if(!i||!a)return{ok:!1,error:"Login timed out. Run `superclawd login` again."};process.stdout.write(`\u2713 Authorized.
207
+ `),Or(r),process.stdout.write(`Waiting for approval\u2026 (Ctrl-C to cancel)
208
+ `);let o=(n.interval||5)*1e3,s=Date.now()+(n.expires_in||600)*1e3,i,a;for(;Date.now()<s;){await Tr(o);let c;try{c=await(await fetch(`${ne}/api/auth/cli/device/token`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({deviceCode:n.device_code})})).json()}catch{continue}if(c.status==="approved"){i=c.key_id,a=c.secret;break}if(c.status==="denied")return{ok:!1,error:"Request was denied in the browser."};if(c.status==="expired")return{ok:!1,error:"Login request expired. Run `superclawd login` again."}}if(!i||!a)return{ok:!1,error:"Login timed out. Run `superclawd login` again."};process.stdout.write(`\u2713 Authorized.
210
209
 
211
- `);let l=P()??{};return G({...l,credentials:{...l.credentials,keyId:i,secret:a}}),process.stdout.write("\u2713 Logged in. Run `superclawd` to choose a workspace and start.\n\n"),{ok:!0}}var C="\x1B",ue=[{key:"notifications",label:"Notifications",description:"Default for new sessions \u2014 ping when Claude needs you or finishes",defaultOn:!1},{key:"skipPermissions",label:"Dangerously skip permissions",description:"Launch Claude Code with --dangerously-skip-permissions (no approval prompts)",defaultOn:!1},{key:"chooseWorkspaceAtStartup",label:"Choose workspace at startup",description:"Pick the workspace to boot into each time you run superclawd",defaultOn:!0},{key:"experimental",label:"Experimental mode",description:"Run the latest unpublished (draft) versions instead of the stable release",defaultOn:!1},{key:"keepAwake",label:"Keep Awake",description:"Prevent your computer from sleeping while a session is running",defaultOn:!1},{key:"privateMemory",label:"Private Memory",description:"Remember your personal preferences across all your sessions (private to you, never shared)",defaultOn:!0},{key:"pipelinesMcp",label:"Pipelines MCP",description:"Let Claude Code drive your Pipelines board (requires SuperClawd Pipelines running)",defaultOn:!1}].sort((e,t)=>e.label.localeCompare(t.label)),$e=(e,t)=>e.preferences?.[t.key]??t.defaultOn;async function Kt(){let e=P()??{},t=process.stdin;if(!t.isTTY){process.stdout.write(`SuperClawd options:
212
- `);for(let n of ue)process.stdout.write(` ${$e(e,n)?"on ":"off"} ${n.label}
213
- `);return}await new Promise(n=>{let r=ue.length,o=r+2,s=0,i=f=>{f||process.stdout.write(`${C}[${o}A`);for(let d=0;d<r;d++){let A=ue[d],u=d===s?`${C}[38;5;208m\u276F `:" ",S=$e(e,A)?`${C}[38;5;208m[\u2713]${C}[0m`:"[ ]";process.stdout.write(`${C}[2K${u}${S} ${A.label}${C}[0m ${C}[2m${A.description}${C}[0m
210
+ `);let l=b()??{};return G({...l,credentials:{...l.credentials,keyId:i,secret:a}}),process.stdout.write("\u2713 Logged in. Run `superclawd` to choose a workspace and start.\n\n"),{ok:!0}}var C="\x1B",de=[{key:"notifications",label:"Notifications",description:"Default for new sessions \u2014 ping when Claude needs you or finishes",defaultOn:!1},{key:"skipPermissions",label:"Dangerously skip permissions",description:"Launch Claude Code with --dangerously-skip-permissions (no approval prompts)",defaultOn:!1},{key:"chooseWorkspaceAtStartup",label:"Choose workspace at startup",description:"Pick the workspace to boot into each time you run superclawd",defaultOn:!0},{key:"experimental",label:"Experimental mode",description:"Run the latest unpublished (draft) versions instead of the stable release",defaultOn:!1},{key:"keepAwake",label:"Keep Awake",description:"Prevent your computer from sleeping while a session is running",defaultOn:!1},{key:"privateMemory",label:"Private Memory",description:"Remember your personal preferences across all your sessions (private to you, never shared)",defaultOn:!0},{key:"pipelinesMcp",label:"Pipelines MCP",description:"Let Claude Code drive your Pipelines board (requires SuperClawd Pipelines running)",defaultOn:!1}].sort((e,t)=>e.label.localeCompare(t.label)),Oe=(e,t)=>e.preferences?.[t.key]??t.defaultOn;async function en(){let e=b()??{},t=process.stdin;if(!t.isTTY){process.stdout.write(`SuperClawd options:
211
+ `);for(let n of de)process.stdout.write(` ${Oe(e,n)?"on ":"off"} ${n.label}
212
+ `);return}await new Promise(n=>{let r=de.length,o=r+2,s=0,i=f=>{f||process.stdout.write(`${C}[${o}A`);for(let d=0;d<r;d++){let A=de[d],u=d===s?`${C}[38;5;208m\u276F `:" ",S=Oe(e,A)?`${C}[38;5;208m[\u2713]${C}[0m`:"[ ]";process.stdout.write(`${C}[2K${u}${S} ${A.label}${C}[0m ${C}[2m${A.description}${C}[0m
214
213
  `)}process.stdout.write(`${C}[2K
215
214
  `),process.stdout.write(`${C}[2K${C}[2mPress Esc (or Ctrl-C) to exit${C}[0m
216
215
  `)};process.stdout.write(`
217
216
  SuperClawd options ${C}[2m(\u2191/\u2193 move \xB7 Space/Enter to toggle)${C}[0m
218
217
  ${C}[?7l${C}[?25l`),i(!0),t.setRawMode(!0),t.resume();let a=!1,l=()=>{if(!a){a=!0;try{t.setRawMode(!1)}catch{}process.stdout.write(`${C}[?7h${C}[?25h`)}},c=["SIGINT","SIGTERM","SIGHUP"],g=()=>l(),E=f=>{l(),process.kill(process.pid,f)};process.once("exit",g);for(let f of c)process.once(f,E);let w=()=>{t.off("data",p),process.off("exit",g);for(let f of c)process.off(f,E);t.pause(),l(),process.stdout.write(`
219
218
  `)},p=f=>{let d=f.toString();if(d===""||d===C)w(),n();else if(d==="\r"||d===`
220
- `||d===" "){let A=ue[s];e.preferences={...e.preferences,[A.key]:!$e(e,A)},G(e),i(!1)}else d===`${C}[A`||d==="k"?(s=(s-1+r)%r,i(!1)):(d===`${C}[B`||d==="j")&&(s=(s+1)%r,i(!1))};t.on("data",p)})}import{execSync as Vt}from"node:child_process";var y="\x1B",W=`${y}[38;5;208m`,Y=`${y}[2m`,fe=`${y}[31m`,R=`${y}[0m`,yr=`${y}[?1049h`,Yt=`${y}[?1049l`,Er=`${y}[?25l`,Le=`${y}[?25h`,Cr=`${y}[?1007l`,Bt=`${y}[?1007h`,Rr=`${y}[?1000l${y}[?1002l${y}[?1003l${y}[?1004l${y}[?1006l${y}[?1015l`,Ie=`${y}[2J${y}[H`,pe=[" _ _"," ____ _ _ __ ___ _ _ __| |__ ___ __ ____| |","(_-< || | '_ \\/ -_) '_/ _| / _` \\ V V / _` |","/__/\\_,_| .__/\\___|_| \\__|_\\__,_|\\_/\\_/\\__,_|"," |_|"],Ht=45,J=36,_r=140,Pr=350,I=e=>void process.stdout.write(e),vr=e=>new Promise(t=>setTimeout(t,e)),K=e=>e>0?" ".repeat(e):"",Jt=process.platform!=="win32";function br(){if(!Jt)return null;try{return Vt("stty -g </dev/tty",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return null}}function qt(e){if(Jt)try{Vt(`stty ${e} </dev/tty`,{stdio:"ignore"})}catch{}}var de=null;function Xt(e){de?.(),de=null,process.stderr.write(`${fe}\u2717 ${e}${R}
221
- `)}function Ar(e,t){return I(`${W}${pe.join(`
222
- `)}${R} ${Y}v${t}${R}
223
-
224
- `),{async phase(n,r){I(`${Y} \xB7 ${r}${R}
225
- `)},message(n){I(`${Y} \xB7 ${n}${R}
226
- `)},async selectWorkspace(n,r){return r?.currentSlug??n[0]?.slug??null},async ready(n){I(`${W} \u2713 ${n}${R}
227
- `)},fail(n){I(`${fe} \u2717 ${n}${R}
228
- `)},note(n){I(` ${n}
229
- `)},handoff(){},finish(){}}}function Mr(e,t){let n=br(),r=0,o=!0,s=!1,i=u=>{u.includes(3)&&g()},a=()=>{let u=process.stdin;if(u.isTTY){try{u.setRawMode(!0)}catch{}u.resume(),u.on("data",i),s=!0}},l=()=>{if(!s)return;let u=process.stdin;u.off("data",i);try{u.setRawMode(!1)}catch{}u.pause(),s=!1},c=()=>{l();try{process.stdin.isTTY&&process.stdin.setRawMode(!1)}catch{}I(Le+Bt+Yt),n&&qt(n)},g=()=>{o&&c(),o=!1,process.exit(130)},E=()=>{l(),o&&I(Le+Bt+Yt)},w=()=>{process.off("SIGINT",g),process.off("SIGTERM",g),process.off("exit",E),de=null};qt("-echo"),I(yr+Er+Cr+Rr),a(),process.on("SIGINT",g),process.on("SIGTERM",g),process.on("exit",E),de=c;let p=(u,S)=>{let _=process.stdout.columns||80,h=process.stdout.rows||24,m=Math.floor(u*J/e);m<0&&(m=0),m>J&&(m=J);let $="\u2588".repeat(m)+"\u2591".repeat(J-m),T=Math.floor(u*100/e),D=J+6,M=Math.max(0,Math.floor((h-9)/2)),N=Ie+`
230
- `.repeat(M),L=Math.max(0,Math.floor((_-Ht)/2));for(let rn of pe)N+=`${K(L)}${W}${rn}${R}
219
+ `||d===" "){let A=de[s];e.preferences={...e.preferences,[A.key]:!Oe(e,A)},G(e),i(!1)}else d===`${C}[A`||d==="k"?(s=(s-1+r)%r,i(!1)):(d===`${C}[B`||d==="j")&&(s=(s+1)%r,i(!1))};t.on("data",p)})}import{execSync as sn}from"node:child_process";var y="\x1B",W=`${y}[38;5;208m`,H=`${y}[2m`,ge=`${y}[31m`,R=`${y}[0m`,Ur=`${y}[?1049h`,tn=`${y}[?1049l`,Wr=`${y}[?25l`,Ue=`${y}[?25h`,Nr=`${y}[?1007l`,nn=`${y}[?1007h`,Gr=`${y}[?1000l${y}[?1002l${y}[?1003l${y}[?1004l${y}[?1006l${y}[?1015l`,We=`${y}[2J${y}[H`,fe=[" _ _"," ____ _ _ __ ___ _ _ __| |__ ___ __ ____| |","(_-< || | '_ \\/ -_) '_/ _| / _` \\ V V / _` |","/__/\\_,_| .__/\\___|_| \\__|_\\__,_|\\_/\\_/\\__,_|"," |_|"],rn=45,z=36,jr=140,Fr=350,T=e=>void process.stdout.write(e),Kr=e=>new Promise(t=>setTimeout(t,e)),B=e=>e>0?" ".repeat(e):"",an=process.platform!=="win32";function Yr(){if(!an)return null;try{return sn("stty -g </dev/tty",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return null}}function on(e){if(an)try{sn(`stty ${e} </dev/tty`,{stdio:"ignore"})}catch{}}var me=null;function cn(e){me?.(),me=null,process.stderr.write(`${ge}\u2717 ${e}${R}
220
+ `)}function Br(e,t){return T(`${W}${fe.join(`
221
+ `)}${R} ${H}v${t}${R}
222
+
223
+ `),{async phase(n,r){T(`${H} \xB7 ${r}${R}
224
+ `)},message(n){T(`${H} \xB7 ${n}${R}
225
+ `)},async selectWorkspace(n,r){return r?.currentSlug??n[0]?.slug??null},async ready(n){T(`${W} \u2713 ${n}${R}
226
+ `)},fail(n){T(`${ge} \u2717 ${n}${R}
227
+ `)},note(n){T(` ${n}
228
+ `)},handoff(){},finish(){}}}function Hr(e,t){let n=Yr(),r=0,o=!0,s=!1,i=u=>{u.includes(3)&&g()},a=()=>{let u=process.stdin;if(u.isTTY){try{u.setRawMode(!0)}catch{}u.resume(),u.on("data",i),s=!0}},l=()=>{if(!s)return;let u=process.stdin;u.off("data",i);try{u.setRawMode(!1)}catch{}u.pause(),s=!1},c=()=>{l();try{process.stdin.isTTY&&process.stdin.setRawMode(!1)}catch{}T(Ue+nn+tn),n&&on(n)},g=()=>{o&&c(),o=!1,process.exit(130)},E=()=>{l(),o&&T(Ue+nn+tn)},w=()=>{process.off("SIGINT",g),process.off("SIGTERM",g),process.off("exit",E),me=null};on("-echo"),T(Ur+Wr+Nr+Gr),a(),process.on("SIGINT",g),process.on("SIGTERM",g),process.on("exit",E),me=c;let p=(u,S)=>{let P=process.stdout.columns||80,h=process.stdout.rows||24,m=Math.floor(u*z/e);m<0&&(m=0),m>z&&(m=z);let I="\u2588".repeat(m)+"\u2591".repeat(z-m),U=Math.floor(u*100/e),O=z+6,M=Math.max(0,Math.floor((h-9)/2)),N=We+`
229
+ `.repeat(M),D=Math.max(0,Math.floor((P-rn)/2));for(let gn of fe)N+=`${B(D)}${W}${gn}${R}
231
230
  `;N+=`
232
- `;let j=Math.max(0,Math.floor((_-S.length)/2));N+=`${K(j)}${Y}${S}${R}
231
+ `;let K=Math.max(0,Math.floor((P-S.length)/2));N+=`${B(K)}${H}${S}${R}
233
232
 
234
- `;let X=Math.max(0,Math.floor((_-D)/2));N+=`${K(X)}${W}${$}${R} ${String(T).padStart(3)}%
235
- `;let z=`v${t}`,ge=Math.max(1,h-1),he=Math.max(1,_-z.length-1);N+=`${y}[${ge};${he}H${W}${z}${R}`,I(N)},f=async(u,S,_)=>{let h=_-(Date.now()-r);h>0&&await vr(h),p(u,S),r=Date.now()},d=u=>{let S=process.stdout.columns||80,_=process.stdout.rows||24,h=Math.max(0,Math.floor((_-(pe.length+1+u.length))/2)),m=Ie+`
236
- `.repeat(h),$=Math.max(0,Math.floor((S-Ht)/2));for(let D of pe)m+=`${K($)}${W}${D}${R}
233
+ `;let Q=Math.max(0,Math.floor((P-O)/2));N+=`${B(Q)}${W}${I}${R} ${String(U).padStart(3)}%
234
+ `;let Z=`v${t}`,we=Math.max(1,h-1),Se=Math.max(1,P-Z.length-1);N+=`${y}[${we};${Se}H${W}${Z}${R}`,T(N)},f=async(u,S,P)=>{let h=P-(Date.now()-r);h>0&&await Kr(h),p(u,S),r=Date.now()},d=u=>{let S=process.stdout.columns||80,P=process.stdout.rows||24,h=Math.max(0,Math.floor((P-(fe.length+1+u.length))/2)),m=We+`
235
+ `.repeat(h),I=Math.max(0,Math.floor((S-rn)/2));for(let O of fe)m+=`${B(I)}${W}${O}${R}
237
236
  `;m+=`
238
- `;for(let D of u)m+=`${D}
239
- `;let T=`v${t}`;m+=`${y}[${Math.max(1,_-1)};${Math.max(1,S-T.length-1)}H${W}${T}${R}`,I(m)},A=(u,S,_)=>{let h=process.stdout.columns||80,m="Select your workspace \u2191/\u2193 \xB7 enter launches \xB7 d sets default \xB7 esc cancels",$=Math.max(0,Math.floor((h-m.length)/2)),T=L=>` ${L.name} ${L.slug} \xB7 ${L.role}`,D=Math.max(...u.map(L=>T(L).length)),M=Math.max(0,Math.floor((h-D)/2)),N=[`${K($)}${Y}${m}${R}`,""];for(let L=0;L<u.length;L++){let j=u[L],X=L===S,z=X?`${W}\u276F `:" ",ge=X?`${W}${j.name}${R}`:j.name,he=j.slug===_?` ${W}\u2605 default${R}`:"";N.push(`${K(M)}${z}${ge} ${Y}${j.slug} \xB7 ${j.role}${R}${he}`)}d(N)};return{phase:(u,S)=>f(u-1,S,_r),ready:u=>f(e,u,Pr),message(u){let S=process.stdout.columns||80,_=Math.max(0,Math.floor((S-u.length)/2));d([`${K(_)}${Y}${u}${R}`]),r=Date.now()},selectWorkspace(u,S){return new Promise(_=>{let h=S?.currentSlug?u.findIndex(D=>D.slug===S.currentSlug):-1,m=h>=0?h:0,$=S?.defaultSlug;s&&process.stdin.off("data",i),A(u,m,$);let T=D=>{let M=D.toString();M===""||M===y?(process.stdin.off("data",T),_(null)):M==="\r"||M===`
240
- `?(process.stdin.off("data",T),process.stdin.on("data",i),_(u[m].slug)):M==="d"||M==="D"?($=u[m].slug,S?.onSetDefault?.($),A(u,m,$)):M===`${y}[A`||M==="k"?(m=(m-1+u.length)%u.length,A(u,m,$)):(M===`${y}[B`||M==="j")&&(m=(m+1)%u.length,A(u,m,$))};process.stdin.on("data",T)})},fail(u){o&&c(),o=!1,w(),process.stderr.write(`${fe}\u2717 ${u}${R}
241
- `)},note(){},handoff(){s&&(process.stdin.off("data",i),process.stdin.pause(),s=!1),I(Ie+Le),process.off("SIGINT",g),process.off("SIGTERM",g)},finish(){o&&c(),o=!1,w()}}}function xr(){return process.platform!=="win32"?!0:!!(process.env.WT_SESSION||process.env.TERM_PROGRAM||process.env.TERM)}function $r(){return{async phase(){},message(){},async selectWorkspace(e,t){return t?.currentSlug??e[0]?.slug??null},async ready(){},fail(e){process.stderr.write(`${fe}\u2717 ${e}${R}
242
- `)},note(){},handoff(){},finish(){}}}function zt(e){if(e.quiet)return $r();let t=process.stdout.isTTY===!0,n=e.version??"";return e.plain||!t||!xr()?Ar(e.total,n):Mr(e.total,n)}var Lr=["low","medium","high","xhigh","max"];function Qt(e){let t=!1,n="",r=null,o=!1,s=!1,i=null,a=!1,l=!1,c="board",g=null,E=null,w=null;for(let p=0;p<e.length;p++){let f=e[p],d=e[p+1];f==="-p"||f==="--print"?(t=!0,d&&!d.startsWith("-")&&(n=d,p++)):f==="--workspace"||f==="-w"?d&&!d.startsWith("-")&&(r=d,p++):f==="--no-capture"?o=!0:f==="--resume"||f==="-r"?(s=!0,d&&!d.startsWith("-")&&(i=d,p++)):f==="--pipelines"?a=!0:f==="--pipelines-tools"?l=!0:f.startsWith("--pipelines-tools=")?(l=!0,c=f.slice(18)==="restricted"?"restricted":"board"):f==="--session-id"?d&&!d.startsWith("-")&&(g=d,p++):f==="--model"?d&&!d.startsWith("-")&&(E=d,p++):f==="--effort"&&d&&Lr.includes(d)&&(w=d,p++)}return{printMode:t,printPrompt:n,workspace:r,noCapture:o,resume:s,resumeSessionId:i,pipelines:a,pipelinesTools:l,pipelinesToolsMode:c,sessionId:g,model:E,effort:w}}var Zt={name:"superclawd",version:"0.1.3",description:"Claude Code, supercharged \u2014 your team's standards, every session. The superclawd CLI loads your workspace's skills, agents, commands, workflows, and live directives into Claude Code as a plugin.",author:"SuperClawd <support@superclawd.com>",license:"SEE LICENSE IN LICENSE",homepage:"https://superclawd.com",repository:{type:"git",url:"https://github.com/superclawd-ai/superclawd"},bugs:{url:"https://github.com/superclawd-ai/superclawd/issues"},keywords:["superclawd","claude-code","claude","plugin","skills","agents","mcp","ai-assistant","coding-standards","model-context-protocol"],engines:{node:">=20"},type:"module",main:"dist/index.js",bin:{superclawd:"dist/index.js"},files:["dist","README.md","LICENSE"],scripts:{build:"node build.mjs",dev:"node build.mjs && tsx src/index.ts",typecheck:"tsc --noEmit",lint:"eslint 'src/**/*.{ts,tsx}'","lint:fix":"eslint 'src/**/*.{ts,tsx}' --fix",format:"prettier --check 'src/**/*.{ts,tsx}'","format:fix":"prettier --write 'src/**/*.{ts,tsx}'",selftest:"tsx test/mcp-selftest.ts","test:guardrails":"tsx test/guardrails-eval.test.ts",test:"node build.mjs && tsx test/mcp-selftest.ts && tsx test/pipelines-tools.test.ts && tsx test/guardrails-eval.test.ts && tsx test/hooks-capture.test.ts && tsx test/translator-teams.test.ts && tsx test/run-args.test.ts && tsx test/pipelines.test.ts && tsx test/update-check.test.ts && tsx test/retrieve.test.ts && tsx test/config-private-memory.test.ts && tsx test/config-choose-workspace.test.ts && tsx test/config.test.ts && tsx test/translator-basics.test.ts && tsx test/hook-helper-guardrails.test.ts && tsx test/capture-prompts.test.ts && tsx test/mcp-backend-real.test.ts && tsx test/catalog.test.ts",prepublishOnly:"npm run build","publish:npm":"npm publish","version:bump":"npm version patch --no-git-tag-version"},dependencies:{"@modelcontextprotocol/sdk":"^1.7.0",zod:"^3.24.2"},devDependencies:{"@eslint/js":"^9.39.1","@types/node":"^22.10.0","@typescript-eslint/eslint-plugin":"^8.44.1","@typescript-eslint/parser":"^8.44.1",esbuild:"^0.24.0",eslint:"^9.36.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4",prettier:"^3.6.2",tsx:"^4.19.0",typescript:"^5.7.0"}};var De=Zt.version,me=process.env.SUPERCLAWD_DRY_RUN==="1"||process.argv.includes("--dry-run");function Nr(){try{let e=Or("git remote get-url origin",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(e)return e.replace(/\.git$/,"").toLowerCase()}catch{}return`dir:${Tr(process.cwd())}`}function Gr(){if(process.env.SUPERCLAWD_MCP_SERVER_PATH)return process.env.SUPERCLAWD_MCP_SERVER_PATH;let e=en(new URL("./mcp-server.mjs",import.meta.url));return nn(e)?e:en(new URL("../dist/mcp-server.mjs",import.meta.url))}function jr(){return`superclawd \u2014 Claude Code, supercharged with your SuperClawd workspace.
237
+ `;for(let O of u)m+=`${O}
238
+ `;let U=`v${t}`;m+=`${y}[${Math.max(1,P-1)};${Math.max(1,S-U.length-1)}H${W}${U}${R}`,T(m)},A=(u,S,P)=>{let h=process.stdout.columns||80,m="Select your workspace \u2191/\u2193 \xB7 enter launches \xB7 d sets default \xB7 esc cancels",I=Math.max(0,Math.floor((h-m.length)/2)),U=D=>` ${D.name} ${D.slug} \xB7 ${D.role}`,O=Math.max(...u.map(D=>U(D).length)),M=Math.max(0,Math.floor((h-O)/2)),N=[`${B(I)}${H}${m}${R}`,""];for(let D=0;D<u.length;D++){let K=u[D],Q=D===S,Z=Q?`${W}\u276F `:" ",we=Q?`${W}${K.name}${R}`:K.name,Se=K.slug===P?` ${W}\u2605 default${R}`:"";N.push(`${B(M)}${Z}${we} ${H}${K.slug} \xB7 ${K.role}${R}${Se}`)}d(N)};return{phase:(u,S)=>f(u-1,S,jr),ready:u=>f(e,u,Fr),message(u){let S=process.stdout.columns||80,P=Math.max(0,Math.floor((S-u.length)/2));d([`${B(P)}${H}${u}${R}`]),r=Date.now()},selectWorkspace(u,S){return new Promise(P=>{let h=S?.currentSlug?u.findIndex(O=>O.slug===S.currentSlug):-1,m=h>=0?h:0,I=S?.defaultSlug;s&&process.stdin.off("data",i),A(u,m,I);let U=O=>{let M=O.toString();M===""||M===y?(process.stdin.off("data",U),P(null)):M==="\r"||M===`
239
+ `?(process.stdin.off("data",U),process.stdin.on("data",i),P(u[m].slug)):M==="d"||M==="D"?(I=u[m].slug,S?.onSetDefault?.(I),A(u,m,I)):M===`${y}[A`||M==="k"?(m=(m-1+u.length)%u.length,A(u,m,I)):(M===`${y}[B`||M==="j")&&(m=(m+1)%u.length,A(u,m,I))};process.stdin.on("data",U)})},fail(u){o&&c(),o=!1,w(),process.stderr.write(`${ge}\u2717 ${u}${R}
240
+ `)},note(){},handoff(){s&&(process.stdin.off("data",i),process.stdin.pause(),s=!1),T(We+Ue),process.off("SIGINT",g),process.off("SIGTERM",g)},finish(){o&&c(),o=!1,w()}}}function qr(){return process.platform!=="win32"?!0:!!(process.env.WT_SESSION||process.env.TERM_PROGRAM||process.env.TERM)}function Jr(){return{async phase(){},message(){},async selectWorkspace(e,t){return t?.currentSlug??e[0]?.slug??null},async ready(){},fail(e){process.stderr.write(`${ge}\u2717 ${e}${R}
241
+ `)},note(){},handoff(){},finish(){}}}function ln(e){if(e.quiet)return Jr();let t=process.stdout.isTTY===!0,n=e.version??"";return e.plain||!t||!qr()?Br(e.total,n):Hr(e.total,n)}var Vr=["low","medium","high","xhigh","max"];function un(e){let t=!1,n="",r=null,o=!1,s=!1,i=null,a=!1,l=!1,c="board",g=null,E=null,w=null;for(let p=0;p<e.length;p++){let f=e[p],d=e[p+1];f==="-p"||f==="--print"?(t=!0,d&&!d.startsWith("-")&&(n=d,p++)):f==="--workspace"||f==="-w"?d&&!d.startsWith("-")&&(r=d,p++):f==="--no-capture"?o=!0:f==="--resume"||f==="-r"?(s=!0,d&&!d.startsWith("-")&&(i=d,p++)):f==="--pipelines"?a=!0:f==="--pipelines-tools"?l=!0:f.startsWith("--pipelines-tools=")?(l=!0,c=f.slice(18)==="restricted"?"restricted":"board"):f==="--session-id"?d&&!d.startsWith("-")&&(g=d,p++):f==="--model"?d&&!d.startsWith("-")&&(E=d,p++):f==="--effort"&&d&&Vr.includes(d)&&(w=d,p++)}return{printMode:t,printPrompt:n,workspace:r,noCapture:o,resume:s,resumeSessionId:i,pipelines:a,pipelinesTools:l,pipelinesToolsMode:c,sessionId:g,model:E,effort:w}}var pn={name:"superclawd",version:"0.1.5",description:"Claude Code, supercharged \u2014 your team's standards, every session. The superclawd CLI loads your workspace's skills, agents, commands, workflows, and live directives into Claude Code as a plugin.",author:"SuperClawd <support@superclawd.com>",license:"SEE LICENSE IN LICENSE",homepage:"https://superclawd.com",repository:{type:"git",url:"https://github.com/superclawd-ai/superclawd"},bugs:{url:"https://github.com/superclawd-ai/superclawd/issues"},keywords:["superclawd","claude-code","claude","plugin","skills","agents","mcp","ai-assistant","coding-standards","model-context-protocol"],engines:{node:">=20"},type:"module",main:"dist/index.js",bin:{superclawd:"dist/index.js"},files:["dist","README.md","LICENSE"],scripts:{build:"node build.mjs",dev:"node build.mjs && tsx src/index.ts",typecheck:"tsc --noEmit",lint:"eslint 'src/**/*.{ts,tsx}'","lint:fix":"eslint 'src/**/*.{ts,tsx}' --fix",format:"prettier --check 'src/**/*.{ts,tsx}'","format:fix":"prettier --write 'src/**/*.{ts,tsx}'",selftest:"tsx test/mcp-selftest.ts","test:guardrails":"tsx test/guardrails-eval.test.ts",test:"node build.mjs && tsx test/mcp-selftest.ts && tsx test/pipelines-tools.test.ts && tsx test/guardrails-eval.test.ts && tsx test/hooks-capture.test.ts && tsx test/translator-teams.test.ts && tsx test/run-args.test.ts && tsx test/pipelines.test.ts && tsx test/update-check.test.ts && tsx test/retrieve.test.ts && tsx test/config-private-memory.test.ts && tsx test/config-choose-workspace.test.ts && tsx test/config.test.ts && tsx test/translator-basics.test.ts && tsx test/hook-helper-guardrails.test.ts && tsx test/capture-prompts.test.ts && tsx test/mcp-backend-real.test.ts && tsx test/catalog.test.ts",prepublishOnly:"npm run build","publish:npm":"npm publish","version:bump":"npm version patch --no-git-tag-version"},dependencies:{"@modelcontextprotocol/sdk":"^1.7.0",zod:"^3.24.2"},devDependencies:{"@eslint/js":"^9.39.1","@types/node":"^22.10.0","@typescript-eslint/eslint-plugin":"^8.44.1","@typescript-eslint/parser":"^8.44.1",esbuild:"^0.24.0",eslint:"^9.36.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4",prettier:"^3.6.2",tsx:"^4.19.0",typescript:"^5.7.0"}};var Ne=pn.version,he=process.env.SUPERCLAWD_DRY_RUN==="1"||process.argv.includes("--dry-run");function no(){try{let e=Qr("git remote get-url origin",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(e)return e.replace(/\.git$/,"").toLowerCase()}catch{}return`dir:${Zr(process.cwd())}`}function ro(){if(process.env.SUPERCLAWD_MCP_SERVER_PATH)return process.env.SUPERCLAWD_MCP_SERVER_PATH;let e=dn(new URL("./mcp-server.mjs",import.meta.url));return mn(e)?e:dn(new URL("../dist/mcp-server.mjs",import.meta.url))}function oo(){return`superclawd \u2014 Claude Code, supercharged with your SuperClawd workspace.
243
242
 
244
243
  Usage:
245
244
  superclawd Launch Claude with your skills/agents/directives loaded
@@ -262,17 +261,17 @@ Print-mode flags (with -p):
262
261
  --no-capture Don't write learned memories for this run (handy for behavior tests)
263
262
 
264
263
  Not authenticated yet? Run \`superclawd login\` first.
265
- `}function Fr(){try{return!Dr("claude",["--version"],{stdio:"ignore"}).error}catch{return!1}}function Kr(e,t=[],n,r,o,s,i){let a=["--plugin-dir",e.pluginDir];a.push("--allowedTools",dt);for(let l of t)a.push("--allowedTools",`mcp__plugin_superclawd_${l}__*`);return(Ne()||n)&&a.push("--dangerously-skip-permissions"),r?(a.push("--resume"),r.sessionId&&a.push(r.sessionId)):o&&a.push("--session-id",o),s&&a.push("--model",s),i&&a.push("--effort",i),n&&a.push("-p",n.prompt),new Promise(l=>{let c=tn("claude",a,{stdio:"inherit",env:{...process.env,CLAUDE_CODE_DISABLE_AUTO_MEMORY:"1"}});c.on("error",g=>l({code:127,error:`Could not launch claude: ${g.message}. Is Claude Code installed and on PATH?`})),c.on("close",g=>l({code:g??0}))})}function Yr(){return process.stdout.write(`Updating superclawd (npm i -g superclawd@latest)\u2026
266
- `),new Promise(e=>{let t=tn("npm install -g superclawd@latest",{stdio:"inherit",shell:!0});t.on("error",n=>{process.stderr.write(`\u2717 Could not run npm: ${n.message}. Is npm on your PATH?
264
+ `}function so(){try{return!zr("claude",["--version"],{stdio:"ignore"}).error}catch{return!1}}function io(e,t=[],n,r,o,s,i){let a=["--plugin-dir",e.pluginDir];a.push("--allowedTools",Et);for(let l of t)a.push("--allowedTools",`mcp__plugin_superclawd_${l}__*`);return(Ye()||n)&&a.push("--dangerously-skip-permissions"),r?(a.push("--resume"),r.sessionId&&a.push(r.sessionId)):o&&a.push("--session-id",o),s&&a.push("--model",s),i&&a.push("--effort",i),n&&a.push("-p",n.prompt),new Promise(l=>{let c=fn("claude",a,{stdio:"inherit",env:{...process.env,CLAUDE_CODE_DISABLE_AUTO_MEMORY:"1"}});c.on("error",g=>l({code:127,error:`Could not launch claude: ${g.message}. Is Claude Code installed and on PATH?`})),c.on("close",g=>l({code:g??137}))})}function ao(){return process.stdout.write(`Updating superclawd (npm i -g superclawd@latest)\u2026
265
+ `),new Promise(e=>{let t=fn("npm install -g superclawd@latest",{stdio:"inherit",shell:!0});t.on("error",n=>{process.stderr.write(`\u2717 Could not run npm: ${n.message}. Is npm on your PATH?
267
266
  `),e(127)}),t.on("close",n=>{n===0?process.stdout.write("\u2713 Updated. Run `superclawd version` to confirm.\n"):process.stderr.write(`\u2717 Update failed (npm exited ${n}).
268
- `),e(n??1)})})}async function Br(e){if(e.printMode&&!e.printPrompt.trim())return process.stderr.write(`Provide a prompt: superclawd -p "<your prompt>"
269
- `),1;if(e.pipelines&&(process.env.SUPERCLAWD_NO_UPDATE="1"),e.pipelinesTools&&(process.env.SUPERCLAWD_PIPELINES_TOOLS=e.pipelinesToolsMode),!me){let p=await Ze(De,process.argv.slice(2));if(p.exitCode!==void 0)return p.exitCode}if(e.noCapture&&(process.env.SUPERCLAWD_NO_CAPTURE="1"),!me&&!Fr())return process.stderr.write(`\u2717 Claude Code isn't installed (or isn't on your PATH).
267
+ `),e(n??1)})})}async function co(e){if(e.printMode&&!e.printPrompt.trim())return process.stderr.write(`Provide a prompt: superclawd -p "<your prompt>"
268
+ `),1;if(e.pipelines&&(process.env.SUPERCLAWD_NO_UPDATE="1"),e.pipelinesTools&&(process.env.SUPERCLAWD_PIPELINES_TOOLS=e.pipelinesToolsMode),!he){let p=await ct(Ne,process.argv.slice(2));if(p.exitCode!==void 0)return p.exitCode}if(e.noCapture&&(process.env.SUPERCLAWD_NO_CAPTURE="1"),!he&&!so())return process.stderr.write(`\u2717 Claude Code isn't installed (or isn't on your PATH).
270
269
 
271
270
  SuperClawd supercharges Claude Code, so you'll need it first:
272
271
  \u2192 https://claude.com/code
273
272
 
274
273
  Once it's installed, run \`superclawd\` again.
275
- `),1;k||qe(),!k&&je()&&(process.env.SUPERCLAWD_EXPERIMENTAL="true"),process.env.SUPERCLAWD_REPO_FINGERPRINT=Nr();let t=Je();if(!t.ok&&!k)return process.stderr.write(`${t.error??"Could not resolve credentials."}
276
- `),1;let n=t.session;e.workspace&&(n={...n,workspace:e.workspace});let r=zt({total:5,plain:me,quiet:e.printMode,version:De});if(!k&&!e.printMode&&!e.workspace&&process.stdin.isTTY&&(!n.workspace||Ge())){let p=await ke(r,n);if(p.cancelled)return r.finish(),130;p.workspace&&(n={...n,workspace:p.workspace})}if(!k&&!n.workspace)return r.finish(),process.stderr.write("No workspace selected. Pass --workspace <id>, set SUPERCLAWD_MCP_WORKSPACE, or run `superclawd` interactively once to pick a default.\n"),1;await r.phase(1,"Resolving credentials\u2026"),await r.phase(2,"Authenticating\u2026");let o=await ye(n);if(o.workspaceInvalid&&!k&&!e.printMode&&!e.workspace&&process.stdin.isTTY){ne();let p=await ke(r,{...n,workspace:""});if(p.cancelled)return r.finish(),130;p.workspace&&(n={...n,workspace:p.workspace},await r.phase(2,"Authenticating\u2026"),o=await ye(n))}if(!o.ok)return r.fail(o.error??"Authentication failed."),1;await r.phase(3,k?"Loading mock catalog\u2026":"Fetching your workspace\u2026");let s;try{s=await lt(n)}catch(p){return r.fail(`Catalog fetch failed: ${String(p)}`),1}process.env.SUPERCLAWD_TEAM_MEMORY=s.teamMemoryEnabled?"1":"0",process.env.SUPERCLAWD_REPO_MEMORY=s.repoMemoryEnabled?"1":"0",process.env.SUPERCLAWD_AGENT_MEMORY=s.agentMemoryEnabled?"1":"0",process.env.SUPERCLAWD_PRIVATE_MEMORY=k||Ke()?"1":"0",await r.phase(4,"Establishing session\u2026"),jt();let i=Nt();He(i.dir,n.workspace,e.pipelines===!0);let a=Gr();if(!nn(a))return r.fail(`Bundled MCP server not found at ${a}. Run \`npm run build\` first.`),1;await ut(n,i.id,e.pipelines!==!0),await r.phase(5,"Generating plugin\u2026");let l=Ut({pluginDir:i.pluginDir,session:n,catalog:s,serverPath:a,launchId:i.id});if(!k)try{let p=Wr(Ur(a),"hook-helper.mjs"),f=Rt({cwd:process.cwd(),helperPath:p,env:{SUPERCLAWD_BACKEND:H,SUPERCLAWD_MCP_API_URL:n.apiUrl,SUPERCLAWD_REPO_FINGERPRINT:process.env.SUPERCLAWD_REPO_FINGERPRINT,SUPERCLAWD_MCP_KEY:n.keyId,SUPERCLAWD_MCP_SECRET:n.secret,SUPERCLAWD_MCP_WORKSPACE:n.workspace,NODE_EXTRA_CA_CERTS:process.env.NODE_EXTRA_CA_CERTS,SUPERCLAWD_HOME:process.env.SUPERCLAWD_HOME,SUPERCLAWD_CLAUDE_BIN:process.env.SUPERCLAWD_CLAUDE_BIN,SUPERCLAWD_POLICY_MODEL:process.env.SUPERCLAWD_POLICY_MODEL}});!f.installed&&f.reason!=="not a git repo"&&r.note(`Post-commit hook: ${f.reason}`)}catch{}let c=k?"mock":n.workspace;if(await r.ready(`${c} \xB7 ${l.skillCount} skills \xB7 ${l.commandCount} commands \xB7 ${l.workflowCount} workflows`),me){r.note("Dry run \u2014 not launching Claude. Generated files:");for(let p of l.files)r.note(` ${p}`);return 0}r.handoff();let g=!k&&Fe()?ze():null,{code:E,error:w}=await Kr(i,l.mcpServerNames,e.printMode?{prompt:e.printPrompt}:void 0,e.resume?{sessionId:e.resumeSessionId}:void 0,e.sessionId,e.model,e.effort);return g?.stop(),r.finish(),Gt(i),w&&process.stderr.write(`${w}
277
- `),w?127:E}async function Hr(){let e=await Ft();return e.cancelled||e.ok?0:(process.stderr.write(`\u2717 ${e.error??"Login failed."}
278
- `),1)}async function qr(){let[e]=process.argv.slice(2).filter(t=>t!=="--dry-run");switch(e){case"login":process.exit(await Hr());return;case"config":await Kt(),process.exit(0);return;case"update":process.exit(await Yr());return;case"pipelines":{let t=process.argv.slice(2).filter(n=>n!=="--dry-run");process.exit(await Dt(t.slice(t.indexOf("pipelines")+1)));return}case"version":case"--version":case"-v":console.log(De);return;case"help":case"--help":case"-h":console.log(jr());return;default:process.exit(await Br(Qt(process.argv.slice(2))))}}qr().catch(e=>{Xt(String(e)),process.exit(1)});
274
+ `),1;k||Qe(),!k&&He()&&(process.env.SUPERCLAWD_EXPERIMENTAL="true"),process.env.SUPERCLAWD_REPO_FINGERPRINT=no();let t=et();if(!t.ok&&!k)return process.stderr.write(`${t.error??"Could not resolve credentials."}
275
+ `),1;let n=t.session;e.workspace&&(n={...n,workspace:e.workspace});let r=ln({total:5,plain:he,quiet:e.printMode,version:Ne});if(!k&&!e.printMode&&!e.workspace&&process.stdin.isTTY&&(!n.workspace||Be())){let p=await Pe(r,n);if(p.cancelled)return r.finish(),130;p.workspace&&(n={...n,workspace:p.workspace})}if(!k&&!n.workspace)return r.finish(),process.stderr.write("No workspace selected. Pass --workspace <id>, set SUPERCLAWD_MCP_WORKSPACE, or run `superclawd` interactively once to pick a default.\n"),1;await r.phase(1,"Resolving credentials\u2026"),await r.phase(2,"Authenticating\u2026");let o=await _e(n);if(o.workspaceInvalid&&!k&&!e.printMode&&!e.workspace&&process.stdin.isTTY){oe();let p=await Pe(r,{...n,workspace:""});if(p.cancelled)return r.finish(),130;p.workspace&&(n={...n,workspace:p.workspace},await r.phase(2,"Authenticating\u2026"),o=await _e(n))}if(!o.ok)return r.fail(o.error??"Authentication failed."),1;await r.phase(3,k?"Loading mock catalog\u2026":"Fetching your workspace\u2026");let s;try{s=await St(n)}catch(p){return r.fail(`Catalog fetch failed: ${String(p)}`),1}process.env.SUPERCLAWD_TEAM_MEMORY=s.teamMemoryEnabled?"1":"0",process.env.SUPERCLAWD_REPO_MEMORY=s.repoMemoryEnabled?"1":"0",process.env.SUPERCLAWD_AGENT_MEMORY=s.agentMemoryEnabled?"1":"0",process.env.SUPERCLAWD_PRIVATE_MEMORY=k||Je()?"1":"0",await r.phase(4,"Establishing session\u2026"),Qt();let i=Xt();ze(i.dir,n.workspace,e.pipelines===!0);let a=ro();if(!mn(a))return r.fail(`Bundled MCP server not found at ${a}. Run \`npm run build\` first.`),1;await kt(n,i.id,e.pipelines!==!0),await r.phase(5,"Generating plugin\u2026");let l=Jt({pluginDir:i.pluginDir,session:n,catalog:s,serverPath:a,launchId:i.id});if(!k)try{let p=to(eo(a),"hook-helper.mjs"),f=Lt({cwd:process.cwd(),helperPath:p,env:{SUPERCLAWD_BACKEND:J,SUPERCLAWD_MCP_API_URL:n.apiUrl,SUPERCLAWD_REPO_FINGERPRINT:process.env.SUPERCLAWD_REPO_FINGERPRINT,SUPERCLAWD_MCP_KEY:n.keyId,SUPERCLAWD_MCP_SECRET:n.secret,SUPERCLAWD_MCP_WORKSPACE:n.workspace,NODE_EXTRA_CA_CERTS:process.env.NODE_EXTRA_CA_CERTS,SUPERCLAWD_HOME:process.env.SUPERCLAWD_HOME,SUPERCLAWD_CLAUDE_BIN:process.env.SUPERCLAWD_CLAUDE_BIN,SUPERCLAWD_POLICY_MODEL:process.env.SUPERCLAWD_POLICY_MODEL}});!f.installed&&f.reason!=="not a git repo"&&r.note(`Post-commit hook: ${f.reason}`)}catch{}let c=k?"mock":n.workspace;if(await r.ready(`${c} \xB7 ${l.skillCount} skills \xB7 ${l.commandCount} commands \xB7 ${l.workflowCount} workflows`),he){r.note("Dry run \u2014 not launching Claude. Generated files:");for(let p of l.files)r.note(` ${p}`);return 0}r.handoff();let g=!k&&qe()?nt():null,{code:E,error:w}=await io(i,l.mcpServerNames,e.printMode?{prompt:e.printPrompt}:void 0,e.resume?{sessionId:e.resumeSessionId}:void 0,e.sessionId,e.model,e.effort);return g?.stop(),r.finish(),zt(i),w&&process.stderr.write(`${w}
276
+ `),w?127:E}async function lo(){let e=await Zt();return e.cancelled||e.ok?0:(process.stderr.write(`\u2717 ${e.error??"Login failed."}
277
+ `),1)}async function uo(){let[e]=process.argv.slice(2).filter(t=>t!=="--dry-run");switch(e){case"login":process.exit(await lo());return;case"config":await en(),process.exit(0);return;case"update":process.exit(await ao());return;case"pipelines":{let t=process.argv.slice(2).filter(n=>n!=="--dry-run");process.exit(await Bt(t.slice(t.indexOf("pipelines")+1)));return}case"version":case"--version":case"-v":console.log(Ne);return;case"help":case"--help":case"-h":console.log(oo());return;default:process.exit(await co(un(process.argv.slice(2))))}}uo().catch(e=>{cn(String(e)),process.exit(1)});
@@ -73,7 +73,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
73
73
  `);if(e===-1)return null;let r=this._buffer.toString("utf8",0,e).replace(/\r$/,"");return this._buffer=this._buffer.subarray(e+1),eE(r)}clear(){this._buffer=void 0}};function eE(t){return jp.parse(JSON.parse(t))}function Sg(t){return JSON.stringify(t)+`
74
74
  `}var ri=class{constructor(e=zg.stdin,r=zg.stdout){this._stdin=e,this._stdout=r,this._readBuffer=new ti,this._started=!1,this._ondata=n=>{this._readBuffer.append(n),this.processReadBuffer()},this._onerror=n=>{var o;(o=this.onerror)===null||o===void 0||o.call(this,n)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(var e,r;;)try{let n=this._readBuffer.readMessage();if(n===null)break;(e=this.onmessage)===null||e===void 0||e.call(this,n)}catch(n){(r=this.onerror)===null||r===void 0||r.call(this,n)}}async close(){var e;this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),(e=this.onclose)===null||e===void 0||e.call(this)}send(e){return new Promise(r=>{let n=Sg(e);this._stdout.write(n)?r():this._stdout.once("drain",r)})}};async function Dg(){return(process.env.SUPERCLAWD_BACKEND||"real").toLowerCase()==="mock"?(await Promise.resolve().then(()=>(Cg(),Ng))).mockBackend:(await Promise.resolve().then(()=>(jg(),Mg))).realBackend}ni();var ai="superclawd",bE="core",xE=`mcp__plugin_${ai}_${bE}__`;var PC=`${xE}*`,TC=`${ai}:`;import{existsSync as El}from"node:fs";import{homedir as wE}from"node:os";import{spawn as $E,execSync as kE}from"node:child_process";var SE="sonnet",zE=2e4;function EE(){let t=process.env.SUPERCLAWD_CLAUDE_BIN;if(t&&El(t))return t;try{let r=process.platform==="win32"?"where claude":"command -v claude",n=kE(r,{encoding:"utf8"}).trim().split(`
75
75
  `)[0];if(n&&El(n))return n}catch{}let e=[`${wE()}/.local/bin/claude`,"/opt/homebrew/bin/claude","/usr/local/bin/claude","/usr/bin/claude"];for(let r of e)if(El(r))return r;return null}function PE(t){let e=t.indexOf("{"),r=t.lastIndexOf("}");return e>=0&&r>e?t.slice(e,r+1):t}function TE(t){let{system:e,user:r}=t,n=t.model||SE,o=t.timeoutMs??zE,s=EE();return s?new Promise(i=>{let a="",c=!1,u=h=>{c||(c=!0,i(h))},l;try{l=$E(s,["-p","--model",n,"--output-format","json","--strict-mcp-config","--setting-sources","user","--tools","","--append-system-prompt",e],{stdio:["pipe","pipe","ignore"],env:{...process.env,SUPERCLAWD_POLICY_JUDGE:"1"}})}catch{return u(null)}let d=setTimeout(()=>{try{l.kill("SIGKILL")}catch{}u(null)},o);l.stdout?.on("data",h=>a+=h),l.on("error",()=>{clearTimeout(d),u(null)}),l.on("close",()=>{if(clearTimeout(d),t.onRaw)try{t.onRaw(a)}catch{}u(a)});try{l.stdin?.write(r),l.stdin?.end()}catch{}}):Promise.resolve(null)}function Lg(t){return TE(t).then(e=>{if(!e)return null;try{let r=e;try{let n=JSON.parse(e);typeof n.result=="string"&&(r=n.result)}catch{}return JSON.parse(PE(r))}catch{return null}})}var AC=["You maintain the durable memory for ONE repository. You review a FINISHED coding session and RECONCILE what it taught against the memories ALREADY SAVED (shown below with ids), keeping the set accurate, current, and non-redundant for the NEXT session. ","SAVE or UPDATE a fact when it would save a newcomer real time or prevent a wrong turn \u2014 for example: the build/test/run command (especially anything non-default, e.g. a subdirectory or required env flags); where key code or config lives when the layout is non-obvious (e.g. the app is in a subdirectory, or content is data-driven from one file); a setup step or arrangement needed to make things work (e.g. ESM-only deps must be mocked for tests to run); a correction to a reasonable wrong assumption (e.g. the repo uses npm despite a pnpm convention); or a non-obvious gotcha and its fix. A fact STILL qualifies even if it 'could be figured out by reading the files'. ","NEVER save: secrets or credentials; code dumps; transient state (a test that merely happened to pass or fail this run); one-off task details; or truly trivial facts (e.g. 'this is a React project', or that a file exists). ","NEVER bake VOLATILE SuperClawd identifiers into a fact: a workflow/skill/command/agent SLUG or id, or a tool-invocation recipe like 'call get_workflow with <slug>'. These break the moment the entity is renamed. Refer to an entity by its human NAME (e.g. the 'Code Review Process' workflow), or omit the identifier entirely. ","CRITICAL \u2014 the ALREADY-SAVED list is the ONLY knowledge future sessions have. If it is NONE, this repo has ZERO saved knowledge: nobody knows the build command, the package manager, or where the app lives \u2014 so the session's basic orientation facts (build/test command, package manager, where the app actually lives, key setup steps) are exactly what the first memories should record. Never call a fact 'already known' or 'standard' \u2014 judge only against the literal list. ","Emit OPERATIONS against the existing set: ",'\u2022 "create" \u2014 a genuinely NEW fact not represented by any existing memory. ','\u2022 "update" \u2014 the session REFINES, SHARPENS, or CORRECTS an existing memory: cite its id and rewrite its COMPLETE body to the now-correct version. Prefer update over create whenever an existing memory is about the same thing (the package manager, the app location, the build command, \u2026), even if the wording differs. A correction (e.g. the app moved from apps/web to apps/app) is an UPDATE to that memory, NOT a new one. When you correct a fact, also UPDATE any OTHER memory that still references the now-stale version. ',"\u2022 Omit any fact already captured accurately (no op). ","A memory tagged [LOCKED] is read-only: never update it; you may only create a complementary fact. ","Keep the set MINIMAL and CURRENT: never leave two memories about the same thing, and never leave an outdated fact beside its correction. ",'CRITICAL \u2014 within THIS single response, every fact must end up in EXACTLY ONE memory: never emit a "create" whose content is already covered by (or overlaps) a memory you keep or "update" in the same response. If the session adds a fact related to an existing memory, FOLD it into that memory with ONE "update" \u2014 do NOT also create a separate memory for the same fact. ',"This is a ONE-SHOT reconciliation of an already-finished session \u2014 do NOT continue the work, ask questions, or take any action. ",`Every op MUST include a "title": a distilled, human one-line SUMMARY of its body (<=120 chars) \u2014 a real summary, NOT the body's first words copied verbatim. `,'Respond with ONLY a strict JSON object {"ops":[ ... ],"reason":"<short overall why>"} and nothing else. Each op is {"op":"create","title":"<=120-char summary","body":"<self-contained 1-4 sentence note with concrete commands/paths + the gotcha & its fix>"} or {"op":"update","id":"<existing id>","title":"<=120-char summary","body":"<rewritten complete note>"}. If the session taught nothing durable, return {"ops":[],"reason":"..."}.'].join(""),ZC=["You review a FINISHED coding session and RECONCILE what it taught against the memories ALREADY SAVED (shown below with ids), keeping each memory set accurate, current, and non-redundant for the NEXT session. You maintain TWO memory sets and route every op to the correct one: ",'\u2022 "repo" \u2014 durable knowledge about THIS repository, SHARED with the whole team: the build/test/run command (especially non-default ones, e.g. a subdirectory or required env flags); where key code/config lives when non-obvious; a required setup step (e.g. an ESM-only dep must be mocked for tests); a correction to a wrong assumption; or a non-obvious gotcha and its fix. A rule about the codebase, the product, or how the TEAM works is "repo" EVEN IF the user phrases it as "I want\u2026", "always\u2026", or "going forward\u2026". A fact STILL qualifies even if it could be figured out by reading the files. ',`\u2022 "private" \u2014 a preference PRIVATE to THIS individual user about how THEY themselves want to work or be treated: tone/verbosity, what to call them, their experience level, editor/workflow habits, how the assistant should behave toward them specifically. NEVER shared with the team. ONLY for preferences about the person themselves \u2014 never about the code or the team's process. `,'Route each fact by what it is ABOUT \u2014 the WORK/team (repo) or the PERSON (private). Do NOT require the user to label something "private"; infer it. When genuinely unsure whether a stated preference is a team convention or a private one, treat it as "repo" (shared): never leak a team rule into a private memory, and never put a genuinely private preference into the shared repo set. ',"NEVER save (either set): secrets or credentials; code dumps; transient state (a test that merely passed/failed this run); one-off task details; trivia. ","NEVER bake VOLATILE SuperClawd identifiers into a fact: a workflow/skill/command/agent SLUG or id, or a tool-invocation recipe like 'call get_workflow with <slug>'. These break the moment the entity is renamed. Refer to an entity by its human NAME, or omit the identifier entirely. ","CRITICAL \u2014 the ALREADY-SAVED lists are the ONLY knowledge future sessions have. If a set is NONE it has ZERO saved knowledge (nobody knows the build command, package manager, or where the app lives), so the session's basic orientation facts are exactly what its first memories should record. Judge 'already known' only against the literal lists, never against what is 'standard'. ","Emit OPERATIONS, each tagged with its scope: ",'\u2022 {"op":"create","scope":"repo"|"private","body":"<self-contained note>"} \u2014 a genuinely NEW fact/preference not represented by any existing memory in that set. ','\u2022 {"op":"update","scope":"repo","id":"<existing repo id>","body":"<rewritten COMPLETE body>"} \u2014 the session REFINES, SHARPENS, or CORRECTS an existing REPO memory: prefer update over create whenever an existing repo memory is about the same thing (the package manager, the app location, \u2026); a correction (e.g. the app moved from apps/web to apps/app) is an UPDATE, not a new memory; also update any other repo memory that still references a now-stale fact. UPDATE applies to the repo set ONLY. ','\u2022 For the PRIVATE set, emit ONLY "create" for a genuinely new preference \u2014 never update or restate one already saved (the user curates their private memories themselves); omit (no op) any private preference already captured. ',"\u2022 Omit any fact already captured accurately (no op). ","A memory tagged [LOCKED] is read-only: never update it; you may only create a complementary fact. ","Keep each set MINIMAL and CURRENT: never leave two memories about the same thing, and never leave an outdated fact beside its correction. ",'CRITICAL \u2014 within THIS single response, every fact must end up in EXACTLY ONE memory of its set: never emit a "create" whose content is already covered by (or overlaps) a memory you keep or "update" in the same response. If the session adds a fact related to an existing memory, FOLD it into that memory with ONE "update" \u2014 do NOT also create a separate memory for the same fact. ',"This is a ONE-SHOT reconciliation of an already-finished session \u2014 do NOT continue the work, ask questions, or take any action. ",`Every op MUST include a "title": a distilled, human one-line SUMMARY of its body (<=120 chars) \u2014 a real summary, NOT the body's first words copied verbatim. `,'Respond with ONLY a strict JSON object {"ops":[ ... ],"reason":"<short overall why>"} and nothing else. Each op is {"op":"create","scope":"repo"|"private","title":"<=120-char summary","body":"..."} or {"op":"update","scope":"repo","id":"<existing id>","title":"<=120-char summary","body":"..."}. If the session taught nothing durable, return {"ops":[],"reason":"..."}.'].join(""),MC=["You maintain the durable lessons for a single reusable AGENT (a specialist invoked to do a job). You review a FINISHED run and RECONCILE what it learned about HOW TO PERFORM ITS ROLE against the lessons ALREADY SAVED (shown below with ids), keeping the set accurate, current, and non-redundant for the agent's NEXT invocation (in ANY repository). ","SAVE or UPDATE a lesson when it would make this agent do its job better next time: a standing preference or convention the user/team established for its work, a correction to how it should operate, or a recurring gotcha in its domain and how to handle it. Lessons are about the ROLE, not a codebase \u2014 they qualify regardless of which repo this run happened in. ","NEVER save: secrets or credentials; code dumps; one-off task details specific only to THIS single run; transient state; or truly trivial facts. ","NEVER record a lesson about TOOL AVAILABILITY \u2014 e.g. that a tool 'does not exist', 'is unavailable', 'is not in the toolset', or that a call failed because the tool wasn't callable. Which tools a run can call is an environment/config detail set per-invocation (this agent runs with a RESTRICTED toolset that omits tools the main session has), NOT a durable fact about the role: the tool may well exist and be available in another context, so such a lesson is misleading and goes stale. Treat a 'no such tool' / 'tool not found' error as a transient environment artifact, never a lesson. ","The ALREADY-SAVED list is the ONLY knowledge the agent carries between runs \u2014 treat anything NOT listed as new; never claim a lesson is 'already known' unless it literally appears. ","IMPORTANT \u2014 the agent runs under workspace SKILLS, instructions, and guardrails that you CANNOT see in this transcript. So: do NOT treat an asserted convention, rule, or guideline as fabricated or 'hallucinated' merely because the transcript shows no basis for it \u2014 it may come from the agent's hidden instructions. NEVER record a lesson that tells the agent to stop asserting conventions, to second-guess its guidance, or that is based on YOUR OWN judgment that the agent made a mistake this run. Capture a lesson ONLY when the run itself shows the USER establishing or correcting a standing preference, or a concrete reproducible domain gotcha the agent itself confirmed. ","Emit OPERATIONS against the existing set: ",'\u2022 "create" \u2014 a genuinely NEW lesson not represented by any existing one. ','\u2022 "update" \u2014 the run REFINES or CORRECTS an existing lesson: cite its id and rewrite its COMPLETE body. Prefer update over create whenever an existing lesson is about the same thing, even if the wording differs. ',"\u2022 Omit any lesson already captured accurately (no op). ","A lesson tagged [LOCKED] is read-only: never update it; you may only create a complementary lesson. ","Keep the set MINIMAL and CURRENT: never leave two lessons about the same thing, and never leave an outdated lesson beside its correction. ",'CRITICAL \u2014 within THIS single response, every lesson must end up exactly ONCE: never emit a "create" whose content is already covered by (or overlaps) a lesson you keep or "update" in the same response. If the run adds something related to an existing lesson, FOLD it in with ONE "update" \u2014 do NOT also create a separate lesson for the same thing. ',"This is a ONE-SHOT reconciliation of an already-finished run \u2014 do NOT continue the work, ask questions, or take any action. ",`Every op MUST include a "title": a distilled, human one-line SUMMARY of its lesson (<=120 chars) \u2014 a real summary, NOT the lesson's first words copied verbatim. `,'Respond with ONLY a strict JSON object {"ops":[ ... ],"reason":"<short overall why>"} and nothing else. Each op is {"op":"create","title":"<=120-char summary","body":"<self-contained instruction the agent can apply next time>"} or {"op":"update","id":"<existing id>","title":"<=120-char summary","body":"<rewritten complete lesson>"}. If the run taught nothing durable, return {"ops":[],"reason":"..."}.'].join(""),qg=`You are given the CONTENT of a saved memory. Return ONLY strict JSON {"title":"..."}: a concise, self-contained one-line summary of the content, MAX 120 characters, that is NOT merely the content's first words copied verbatim. Nothing else but the JSON object.`,jC=["You decide whether a code change makes a remembered lesson STALE (no longer true).",'Respond ONLY strict JSON {"verdict":"stale"|"valid","reason":"<one line>","confidence":<0..1>}.'].join(" ");import{homedir as RE}from"node:os";import{join as go}from"node:path";import{readFileSync as Ug,writeFileSync as IE,mkdirSync as OE,chmodSync as VC,existsSync as FC}from"node:fs";var HC=(process.env.SUPERCLAWD_BACKEND||"real").toLowerCase();var WC=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",BC=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com",Vg=process.env.SUPERCLAWD_HOME||go(RE(),".superclawd"),NE=go(Vg,"sessions"),CE=go(Vg,"config.json");function AE(t){if(!t||typeof t!="object")return{};let e=t,r=e.credentials??{...typeof e.keyId=="string"?{keyId:e.keyId}:{},...typeof e.secret=="string"?{secret:e.secret}:{},...typeof e.workspace=="string"?{workspace:e.workspace}:{}},n=e.preferences??{...typeof e.skipPermissions=="boolean"?{skipPermissions:e.skipPermissions}:{},...typeof e.notifications=="boolean"?{notifications:e.notifications}:{},...typeof e.chooseWorkspaceAtStartup=="boolean"?{chooseWorkspaceAtStartup:e.chooseWorkspaceAtStartup}:{},...typeof e.experimental=="boolean"?{experimental:e.experimental}:{}},o={};return Object.keys(r).length&&(o.credentials=r),Object.keys(n).length&&(o.preferences=n),typeof e.machineId=="string"&&(o.machineId=e.machineId),o}function ZE(){try{return AE(JSON.parse(Ug(CE,"utf8")))}catch{return null}}function ME(){return ZE()?.preferences?.notifications===!0}function Fg(t){return go(NE,t)}function Hg(t){return go(t,"config.json")}function Wg(t){try{return JSON.parse(Ug(Hg(t),"utf8"))}catch{return null}}function jE(t,e){try{OE(t,{recursive:!0}),IE(Hg(t),`${JSON.stringify(e,null,2)}
76
- `)}catch{}}function Bg(t){let e=t?Wg(Fg(t)):null;return e&&typeof e.notifications=="boolean"?e.notifications:ME()}function Kg(t,e){if(!t)return e;let r=Fg(t),n=Wg(r)??{};return jE(r,{...n,notifications:e}),e}var KC=1e3*60*60*24*3;var Jg=(process.env.SUPERCLAWD_PIPELINES_URL||"").replace(/\/+$/,""),DE=process.env.SUPERCLAWD_PIPELINES_TICKET||"",zt=t=>({content:[{type:"text",text:t}]}),yo=t=>zt(JSON.stringify(t,null,2)),se=t=>({isError:!0,content:[{type:"text",text:`<superclawd_error>${t}</superclawd_error>`}]});async function xe(t,e){if(!Jg)throw new Error("SUPERCLAWD_PIPELINES_URL is not set");let r=await fetch(`${Jg}${t}`,{...e,headers:{"Content-Type":"application/json",...e?.headers??{}}});if(!r.ok){let n=await r.text().catch(()=>""),o="";try{let s=JSON.parse(n);typeof s.error=="string"&&(o=s.error,typeof s.unresolved=="number"&&(o+=` (${s.unresolved} unresolved open question${s.unresolved===1?"":"s"})`))}catch{}throw new Error(o||`${e?.method??"GET"} ${t} \u2192 ${r.status}${n?`: ${n.slice(0,300)}`:""}`)}return r.status===204?void 0:await r.json()}function jt(t){return t&&t.trim()||DE||null}var Dt="No ticketId given and no ticket is bound to this session \u2014 pass a ticketId (use list_tickets to find one).";function Gg(t,e="board"){t.tool("list_boards","List the SuperClawd Pipelines boards in this workspace (a Local board plus any connected vendor boards like Linear). Use this to find a board id \u2014 e.g. the Local board to create a ticket on, or a board to list its tickets. `lastSyncedAt` shows how fresh a vendor board's data is (there is no way to sync from here).",{},async()=>{try{let n=await xe("/api/connections");return yo(n.filter(o=>o.linkStatus==="linked").map(o=>({boardId:o.id,name:o.displayName||o.providerAccountName,provider:o.provider,isLocal:o.provider==="local",workspaceId:o.workspaceId,workspaceName:o.workspaceName,ticketCount:o.ticketCount,lastSyncedAt:o.lastSyncedAt})))}catch(n){return se(String(n))}}),t.tool("list_tickets","List the tickets on a Pipelines board (by boardId from list_boards). Returns each ticket's id, identifier, title, priority and whether it's blocked \u2014 use read_ticket for the full detail. Workflow status/column is intentionally omitted.",{boardId:O.string().describe("The board id (from list_boards).")},async({boardId:n})=>{try{let o=await xe(`/api/board?connectionId=${encodeURIComponent(n)}`);return yo(o.map(({ticket:s})=>({ticketId:s.id,identifier:s.externalIdentifier,title:s.title,priority:s.priority,assignee:s.assignee?.name,blocked:!!s.blockedReason})))}catch(o){return se(String(o))}}),t.tool("read_ticket","Read a Pipelines ticket in full \u2014 description, additional context, plan, conclusion, open questions and notes, plus whether it's blocked (and why). For a board run you can omit ticketId to read the ticket this session is working on. Workflow status is intentionally omitted; `lastSyncedAt` shows how fresh vendor data is (no sync is possible from here).",{ticketId:O.string().optional().describe("The Pipelines ticket id. Omit on a board run to read the bound ticket.")},async({ticketId:n})=>{let o=jt(n);if(!o)return se(Dt);try{let[s,i,a,c]=await Promise.all([xe(`/api/tickets/${encodeURIComponent(o)}`),xe(`/api/tickets/${encodeURIComponent(o)}/open-questions`),xe(`/api/tickets/${encodeURIComponent(o)}/notes`),xe("/api/connections").catch(()=>[])]),u=s.ticket,l=c.find(d=>d.id===u.connectionId);return yo({ticketId:u.id,identifier:u.externalIdentifier,title:u.title,description:u.description??null,provider:u.provider,project:u.project??null,parent:u.parent??null,assignee:u.assignee?.name??null,priority:u.priority??null,labels:u.labels?.map(d=>d.name)??[],connectionName:s.connectionName,workspaceName:s.workspaceName,workingDir:u.workingDir??null,model:u.model??null,effort:u.effort??null,blocked:!!u.blockedReason,blockedReason:u.blockedReason??null,additionalContext:u.additionalContext??null,plan:u.plan??null,conclusion:u.conclusion??null,lastSyncedAt:l?.lastSyncedAt??null,openQuestions:i,notes:a.map(d=>({id:d.id,author:d.author,body:d.body}))})}catch(s){return se(String(s))}}),t.tool("create_ticket","Create a new ticket on a workspace's LOCAL board (vendor boards are read-only from here). Omit boardId to use the workspace's Local board when there's exactly one; otherwise pass a local boardId from list_boards.",{title:O.string().describe("The ticket title (required)."),description:O.string().optional().describe("Optional description (markdown)."),boardId:O.string().optional().describe("A LOCAL board id (from list_boards). Omit to use the sole Local board.")},async({title:n,description:o,boardId:s})=>{try{let i=s;if(!i){let u=(await xe("/api/connections")).filter(l=>l.provider==="local"&&l.linkStatus==="linked");if(u.length===0)return se("No local board found in this workspace.");if(u.length>1)return se("Multiple local boards exist \u2014 pass a boardId (see list_boards).");i=u[0].id}let a=await xe(`/api/board/${encodeURIComponent(i)}/tickets`,{method:"POST",body:JSON.stringify({title:n,description:o})});return zt(`Created ${a.externalIdentifier} \u2014 "${a.title}" (ticketId ${a.id}).`)}catch(i){return se(String(i))}});let r=[{tool:"set_plan",field:"plan",label:"plan",desc:"Write (or replace) the ticket's Plan \u2014 how you'll approach the task, as markdown (it needn't be technical). Prefer this over writing a plan file in the repo."},{tool:"set_conclusion",field:"conclusion",label:"conclusion",desc:"Write (or replace) the ticket's Conclusion \u2014 a short wrap-up of what you did and any results/findings, as markdown. Write this once you've fully completed what the ticket asked."},{tool:"set_additional_context",field:"additionalContext",label:"additional context",desc:"Write (or replace) the ticket's Additional context \u2014 extra context the vendor description can't carry, as markdown."}];for(let n of r)t.tool(n.tool,n.desc+" For a board run you can omit ticketId to target the bound ticket. Pass empty markdown to clear it.",{markdown:O.string().describe(`The ${n.label} content (markdown).`),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({markdown:o,ticketId:s})=>{let i=jt(s);if(!i)return se(Dt);try{return await xe(`/api/tickets/${encodeURIComponent(i)}`,{method:"PATCH",body:JSON.stringify({[n.field]:o})}),zt(`Saved the ${n.label} for ${i}.`)}catch(a){return se(String(a))}});t.tool("add_open_question","Add an open question to a ticket \u2014 something that needs an answer before/while working it. Use this for answerable questions; use block_ticket when you truly can't proceed. Note: if the ticket is (or becomes) blocked, every open question on it must be resolved before it can be unblocked. For a board run you can omit ticketId.",{question:O.string().describe("The question to record."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({question:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);try{let i=await xe(`/api/tickets/${encodeURIComponent(s)}/open-questions`,{method:"POST",body:JSON.stringify({question:n})});return zt(`Added open question (id ${i.id}).`)}catch(i){return se(String(i))}}),t.tool("update_open_question","Answer and/or resolve an existing open question (by its id, from read_ticket). Pass an answer, a resolved flag, or both.",{questionId:O.string().describe("The open question id."),answer:O.string().optional().describe("The answer text."),resolved:O.boolean().optional().describe("Mark the question resolved (true) or reopened (false).")},async({questionId:n,answer:o,resolved:s})=>{if(o===void 0&&s===void 0)return se("Pass an answer and/or a resolved flag.");try{return await xe(`/api/open-questions/${encodeURIComponent(n)}`,{method:"PATCH",body:JSON.stringify({answer:o,resolved:s})}),zt(`Updated open question ${n}.`)}catch(i){return se(String(i))}}),t.tool("add_note","Add a note to a ticket (recorded as authored by the assistant). Use for durable findings or decisions worth keeping on the ticket. For a board run you can omit ticketId.",{body:O.string().describe("The note text."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({body:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);try{let i=await xe(`/api/tickets/${encodeURIComponent(s)}/notes`,{method:"POST",body:JSON.stringify({body:n,author:"assistant"})});return zt(`Added note (id ${i.id}).`)}catch(i){return se(String(i))}}),t.tool("edit_note","Edit the body of an existing note (by its id, from read_ticket). Notes cannot be deleted.",{noteId:O.string().describe("The note id."),body:O.string().describe("The revised note text.")},async({noteId:n,body:o})=>{try{return await xe(`/api/notes/${encodeURIComponent(n)}`,{method:"PATCH",body:JSON.stringify({body:o})}),zt(`Edited note ${n}.`)}catch(s){return se(String(s))}}),t.tool("block_ticket","Mark a ticket as blocked with a reason \u2014 an escalation signal that you can't proceed and a human needs to look. Prefer add_open_question for questions you can still work around. If you record open questions on a blocked ticket, they must all be resolved before it can be unblocked. For a board run you can omit ticketId.",{reason:O.string().describe("Why the ticket is blocked (required)."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({reason:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);if(!n.trim())return se("A blocked reason is required.");try{return await xe(`/api/tickets/${encodeURIComponent(s)}`,{method:"PATCH",body:JSON.stringify({blockedReason:n})}),zt(`Blocked ${s}: ${n}`)}catch(i){return se(String(i))}}),t.tool("unblock_ticket","Clear a ticket's blocked state. Drops a note (authored by the assistant) recording why, so there's a trail. You can only unblock once EVERY open question on the ticket is resolved \u2014 answer/resolve them with update_open_question first, or this will fail. For a board run you can omit ticketId.",{reason:O.string().optional().describe("Why you're unblocking it (recorded as a note)."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({reason:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);try{await xe(`/api/tickets/${encodeURIComponent(s)}`,{method:"PATCH",body:JSON.stringify({blockedReason:null})});let i=`Unblocked${n&&n.trim()?`: ${n.trim()}`:"."}`;return await xe(`/api/tickets/${encodeURIComponent(s)}/notes`,{method:"POST",body:JSON.stringify({body:i,author:"assistant"})}).catch(()=>{}),zt(`Unblocked ${s}.`)}catch(i){return se(String(i))}}),t.tool("list_repos","List the git repositories available in this ticket's working directory. The working dir is often an umbrella project folder holding several repos in subfolders \u2014 use this to see what you can work on. For a board run you can omit ticketId.",{ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({ticketId:n})=>{let o=jt(n);if(!o)return se(Dt);try{let s=await xe(`/api/tickets/${encodeURIComponent(o)}/repos`);return yo(s)}catch(s){return se(String(s))}}),e==="board"&&(t.tool("start_repo_work","Claim a repo to modify \u2014 creates an isolated git worktree on a fresh branch and returns its path. You MUST make ALL changes to that repo inside the returned `worktreePath`, and commit there \u2014 NEVER edit the repo in the working directory itself (other runs may be working on it concurrently). Call once per repo you need (a task may touch several). Returns { worktreePath, branch, base, compareUrl }. When done: commit, push the branch, then record the PR with add_pr_link \u2014 if you can't open a PR (e.g. no `gh`), just push and share the compareUrl. For a board run you can omit ticketId.",{repo:O.string().optional().describe("Which repo (folder name from list_repos). Omit only if the working dir is a single repo."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({repo:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);try{let i=await xe(`/api/tickets/${encodeURIComponent(s)}/worktree`,{method:"POST",body:JSON.stringify({repo:n})});return yo(i)}catch(i){return se(String(i))}}),t.tool("add_pr_link","Record a pull-request link on the ticket. A ticket can have several PRs (one per repo/branch), so call this once per PR you open. If you couldn't open the PR yourself, still push the branch and (optionally) record the compare URL from start_repo_work so a human can open it. For a board run you can omit ticketId.",{url:O.string().describe("The PR (or compare) URL."),title:O.string().optional().describe("Optional short label for the PR."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({url:n,title:o,ticketId:s})=>{let i=jt(s);if(!i)return se(Dt);try{return await xe(`/api/tickets/${encodeURIComponent(i)}/pr-links`,{method:"POST",body:JSON.stringify({url:n,title:o})}),zt(`Recorded PR link on ${i}.`)}catch(a){return se(String(a))}}))}var Ve=await Dg();async function LE(t){if(process.env.SUPERCLAWD_BACKEND!=="mock")try{let r=((await Lg({system:qg,user:`CONTENT:
76
+ `)}catch{}}function Bg(t){let e=t?Wg(Fg(t)):null;return e&&typeof e.notifications=="boolean"?e.notifications:ME()}function Kg(t,e){if(!t)return e;let r=Fg(t),n=Wg(r)??{};return jE(r,{...n,notifications:e}),e}var KC=1e3*60*60*24*3;var Jg=(process.env.SUPERCLAWD_PIPELINES_URL||"").replace(/\/+$/,""),DE=process.env.SUPERCLAWD_PIPELINES_TICKET||"",zt=t=>({content:[{type:"text",text:t}]}),yo=t=>zt(JSON.stringify(t,null,2)),se=t=>({isError:!0,content:[{type:"text",text:`<superclawd_error>${t}</superclawd_error>`}]});async function xe(t,e){if(!Jg)throw new Error("SUPERCLAWD_PIPELINES_URL is not set");let r=await fetch(`${Jg}${t}`,{...e,headers:{"Content-Type":"application/json",...e?.headers??{}}});if(!r.ok){let n=await r.text().catch(()=>""),o="";try{let s=JSON.parse(n);typeof s.error=="string"&&(o=s.error,typeof s.unresolved=="number"&&(o+=` (${s.unresolved} unresolved open question${s.unresolved===1?"":"s"})`))}catch{}throw new Error(o||`${e?.method??"GET"} ${t} \u2192 ${r.status}${n?`: ${n.slice(0,300)}`:""}`)}return r.status===204?void 0:await r.json()}function jt(t){return t&&t.trim()||DE||null}var Dt="No ticketId given and no ticket is bound to this session \u2014 pass a ticketId (use list_tickets to find one).";function Gg(t,e="board"){t.tool("list_boards","List the SuperClawd Pipelines boards in this workspace (a Local board plus any connected vendor boards like Linear). Use this to find a board id \u2014 e.g. the Local board to create a ticket on, or a board to list its tickets. `lastSyncedAt` shows how fresh a vendor board's data is (there is no way to sync from here).",{},async()=>{try{let n=await xe("/api/connections");return yo(n.filter(o=>o.linkStatus==="linked").map(o=>({boardId:o.id,name:o.displayName||o.providerAccountName,provider:o.provider,isLocal:o.provider==="local",workspaceId:o.workspaceId,workspaceName:o.workspaceName,ticketCount:o.ticketCount,lastSyncedAt:o.lastSyncedAt})))}catch(n){return se(String(n))}}),t.tool("list_tickets","List the tickets on a Pipelines board (by boardId from list_boards). Returns each ticket's id, identifier, title, priority and whether it's blocked \u2014 use read_ticket for the full detail. Workflow status/column is intentionally omitted.",{boardId:O.string().describe("The board id (from list_boards).")},async({boardId:n})=>{try{let o=await xe(`/api/board?connectionId=${encodeURIComponent(n)}`);return yo(o.map(({ticket:s})=>({ticketId:s.id,identifier:s.externalIdentifier,title:s.title,priority:s.priority,assignee:s.assignee?.name,blocked:!!s.blockedReason})))}catch(o){return se(String(o))}}),t.tool("read_ticket","Read a Pipelines ticket in full \u2014 description, vendor comments (the ticket's discussion, synced read-only from the provider \u2014 often where the real acceptance criteria live), additional context, plan, conclusion, open questions and notes, plus whether it's blocked (and why). For a board run you can omit ticketId to read the ticket this session is working on. Workflow status is intentionally omitted; `lastSyncedAt` shows how fresh vendor data is (no sync is possible from here).",{ticketId:O.string().optional().describe("The Pipelines ticket id. Omit on a board run to read the bound ticket.")},async({ticketId:n})=>{let o=jt(n);if(!o)return se(Dt);try{let[s,i,a,c]=await Promise.all([xe(`/api/tickets/${encodeURIComponent(o)}`),xe(`/api/tickets/${encodeURIComponent(o)}/open-questions`),xe(`/api/tickets/${encodeURIComponent(o)}/notes`),xe("/api/connections").catch(()=>[])]),u=s.ticket,l=c.find(d=>d.id===u.connectionId);return yo({ticketId:u.id,identifier:u.externalIdentifier,title:u.title,description:u.description??null,provider:u.provider,project:u.project??null,parent:u.parent??null,assignee:u.assignee?.name??null,priority:u.priority??null,labels:u.labels?.map(d=>d.name)??[],connectionName:s.connectionName,workspaceName:s.workspaceName,workingDir:u.workingDir??null,model:u.model??null,effort:u.effort??null,blocked:!!u.blockedReason,blockedReason:u.blockedReason??null,additionalContext:u.additionalContext??null,plan:u.plan??null,conclusion:u.conclusion??null,lastSyncedAt:l?.lastSyncedAt??null,openQuestions:i,comments:(u.comments??[]).map(d=>({id:d.id,author:d.author??null,body:d.body,createdAt:d.createdAt??null})),notes:a.map(d=>({id:d.id,author:d.author,body:d.body}))})}catch(s){return se(String(s))}}),t.tool("create_ticket","Create a new ticket on a workspace's LOCAL board (vendor boards are read-only from here). Omit boardId to use the workspace's Local board when there's exactly one; otherwise pass a local boardId from list_boards.",{title:O.string().describe("The ticket title (required)."),description:O.string().optional().describe("Optional description (markdown)."),boardId:O.string().optional().describe("A LOCAL board id (from list_boards). Omit to use the sole Local board.")},async({title:n,description:o,boardId:s})=>{try{let i=s;if(!i){let u=(await xe("/api/connections")).filter(l=>l.provider==="local"&&l.linkStatus==="linked");if(u.length===0)return se("No local board found in this workspace.");if(u.length>1)return se("Multiple local boards exist \u2014 pass a boardId (see list_boards).");i=u[0].id}let a=await xe(`/api/board/${encodeURIComponent(i)}/tickets`,{method:"POST",body:JSON.stringify({title:n,description:o})});return zt(`Created ${a.externalIdentifier} \u2014 "${a.title}" (ticketId ${a.id}).`)}catch(i){return se(String(i))}});let r=[{tool:"set_plan",field:"plan",label:"plan",desc:"Write (or replace) the ticket's Plan \u2014 how you'll approach the task, as markdown (it needn't be technical). Prefer this over writing a plan file in the repo."},{tool:"set_conclusion",field:"conclusion",label:"conclusion",desc:"Write (or replace) the ticket's Conclusion \u2014 a short wrap-up of what you did and any results/findings, as markdown. Write this once you've fully completed what the ticket asked."},{tool:"set_additional_context",field:"additionalContext",label:"additional context",desc:"Write (or replace) the ticket's Additional context \u2014 extra context the vendor description can't carry, as markdown."}];for(let n of r)t.tool(n.tool,n.desc+" For a board run you can omit ticketId to target the bound ticket. Pass empty markdown to clear it.",{markdown:O.string().describe(`The ${n.label} content (markdown).`),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({markdown:o,ticketId:s})=>{let i=jt(s);if(!i)return se(Dt);try{return await xe(`/api/tickets/${encodeURIComponent(i)}`,{method:"PATCH",body:JSON.stringify({[n.field]:o})}),zt(`Saved the ${n.label} for ${i}.`)}catch(a){return se(String(a))}});t.tool("add_open_question","Add an open question to a ticket \u2014 something that needs an answer before/while working it. Use this for answerable questions; use block_ticket when you truly can't proceed. Note: if the ticket is (or becomes) blocked, every open question on it must be resolved before it can be unblocked. For a board run you can omit ticketId.",{question:O.string().describe("The question to record."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({question:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);try{let i=await xe(`/api/tickets/${encodeURIComponent(s)}/open-questions`,{method:"POST",body:JSON.stringify({question:n})});return zt(`Added open question (id ${i.id}).`)}catch(i){return se(String(i))}}),t.tool("update_open_question","Answer and/or resolve an existing open question (by its id, from read_ticket). Pass an answer, a resolved flag, or both.",{questionId:O.string().describe("The open question id."),answer:O.string().optional().describe("The answer text."),resolved:O.boolean().optional().describe("Mark the question resolved (true) or reopened (false).")},async({questionId:n,answer:o,resolved:s})=>{if(o===void 0&&s===void 0)return se("Pass an answer and/or a resolved flag.");try{return await xe(`/api/open-questions/${encodeURIComponent(n)}`,{method:"PATCH",body:JSON.stringify({answer:o,resolved:s})}),zt(`Updated open question ${n}.`)}catch(i){return se(String(i))}}),t.tool("add_note","Add a note to a ticket (recorded as authored by the assistant). Use for durable findings or decisions worth keeping on the ticket. For a board run you can omit ticketId.",{body:O.string().describe("The note text."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({body:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);try{let i=await xe(`/api/tickets/${encodeURIComponent(s)}/notes`,{method:"POST",body:JSON.stringify({body:n,author:"assistant"})});return zt(`Added note (id ${i.id}).`)}catch(i){return se(String(i))}}),t.tool("edit_note","Edit the body of an existing note (by its id, from read_ticket). Notes cannot be deleted.",{noteId:O.string().describe("The note id."),body:O.string().describe("The revised note text.")},async({noteId:n,body:o})=>{try{return await xe(`/api/notes/${encodeURIComponent(n)}`,{method:"PATCH",body:JSON.stringify({body:o})}),zt(`Edited note ${n}.`)}catch(s){return se(String(s))}}),t.tool("block_ticket","Mark a ticket as blocked with a reason \u2014 an escalation signal that you can't proceed and a human needs to look. Prefer add_open_question for questions you can still work around. If you record open questions on a blocked ticket, they must all be resolved before it can be unblocked. For a board run you can omit ticketId.",{reason:O.string().describe("Why the ticket is blocked (required)."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({reason:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);if(!n.trim())return se("A blocked reason is required.");try{return await xe(`/api/tickets/${encodeURIComponent(s)}`,{method:"PATCH",body:JSON.stringify({blockedReason:n})}),zt(`Blocked ${s}: ${n}`)}catch(i){return se(String(i))}}),t.tool("unblock_ticket","Clear a ticket's blocked state. Drops a note (authored by the assistant) recording why, so there's a trail. You can only unblock once EVERY open question on the ticket is resolved \u2014 answer/resolve them with update_open_question first, or this will fail. For a board run you can omit ticketId.",{reason:O.string().optional().describe("Why you're unblocking it (recorded as a note)."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({reason:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);try{await xe(`/api/tickets/${encodeURIComponent(s)}`,{method:"PATCH",body:JSON.stringify({blockedReason:null})});let i=`Unblocked${n&&n.trim()?`: ${n.trim()}`:"."}`;return await xe(`/api/tickets/${encodeURIComponent(s)}/notes`,{method:"POST",body:JSON.stringify({body:i,author:"assistant"})}).catch(()=>{}),zt(`Unblocked ${s}.`)}catch(i){return se(String(i))}}),t.tool("list_repos","List the git repositories available in this ticket's working directory. The working dir is often an umbrella project folder holding several repos in subfolders \u2014 use this to see what you can work on. For a board run you can omit ticketId.",{ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({ticketId:n})=>{let o=jt(n);if(!o)return se(Dt);try{let s=await xe(`/api/tickets/${encodeURIComponent(o)}/repos`);return yo(s)}catch(s){return se(String(s))}}),e==="board"&&(t.tool("start_repo_work","Claim a repo to modify \u2014 creates an isolated git worktree on a fresh branch and returns its path. You MUST make ALL changes to that repo inside the returned `worktreePath`, and commit there \u2014 NEVER edit the repo in the working directory itself (other runs may be working on it concurrently). Call once per repo you need (a task may touch several). Returns { worktreePath, branch, base, compareUrl }. When done: commit, push the branch, then record the PR with add_pr_link \u2014 if you can't open a PR (e.g. no `gh`), just push and share the compareUrl. For a board run you can omit ticketId.",{repo:O.string().optional().describe("Which repo (folder name from list_repos). Omit only if the working dir is a single repo."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({repo:n,ticketId:o})=>{let s=jt(o);if(!s)return se(Dt);try{let i=await xe(`/api/tickets/${encodeURIComponent(s)}/worktree`,{method:"POST",body:JSON.stringify({repo:n})});return yo(i)}catch(i){return se(String(i))}}),t.tool("add_pr_link","Record a pull-request link on the ticket. A ticket can have several PRs (one per repo/branch), so call this once per PR you open. If you couldn't open the PR yourself, still push the branch and (optionally) record the compare URL from start_repo_work so a human can open it. For a board run you can omit ticketId.",{url:O.string().describe("The PR (or compare) URL."),title:O.string().optional().describe("Optional short label for the PR."),ticketId:O.string().optional().describe("The ticket id; omit on a board run to use the bound one.")},async({url:n,title:o,ticketId:s})=>{let i=jt(s);if(!i)return se(Dt);try{return await xe(`/api/tickets/${encodeURIComponent(i)}/pr-links`,{method:"POST",body:JSON.stringify({url:n,title:o})}),zt(`Recorded PR link on ${i}.`)}catch(a){return se(String(a))}}))}var Ve=await Dg();async function LE(t){if(process.env.SUPERCLAWD_BACKEND!=="mock")try{let r=((await Lg({system:qg,user:`CONTENT:
77
77
  ${t}`,model:"haiku",timeoutMs:15e3}))?.title||"").trim();return r?r.slice(0,120):void 0}catch{return}}var Ce=new ei({name:ai,version:"0.1.0"});Ce.tool("get_directives","Fetch and apply the authoritative SuperClawd instructions for one or more skills. Call this whenever an SuperClawd skill activates, BEFORE acting, passing the skill's skillId. If several skills activate at the same time, pass them together in `skills` to fetch them in one (cheaper) call.",{skillId:O.string().optional().describe("A single activated skill's skillId."),action:O.string().optional().describe("Action context for `skillId`, e.g. code/test/review."),skills:O.array(O.object({skillId:O.string().describe("The activated skill's skillId."),action:O.string().optional().describe("Action context, e.g. code/test/review.")})).optional().describe("Batch form: multiple activated skills to fetch in a single call.")},async({skillId:t,action:e,skills:r})=>{let n=r?.length?r:t?[{skillId:t,action:e}]:[];if(n.length===0)return{isError:!0,content:[{type:"text",text:'<superclawd_error status="400">Provide a skillId, or a non-empty skills array.</superclawd_error>'}]};let o=await Ve.getDirectives(n);return o.ok?{content:[{type:"text",text:o.text??""}]}:{isError:!0,content:[{type:"text",text:`<superclawd_error status="${o.status}">${o.message}</superclawd_error>`}]}});function qE(){try{let t=JSON.parse(process.env.SUPERCLAWD_RESOURCES??"[]");return Array.isArray(t)?t:[]}catch{return[]}}var Pl=qE();function UE(){return Pl.length===0?"":`
78
78
 
79
79
  Available resources (fetch by name when relevant to the task):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superclawd",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Claude Code, supercharged — your team's standards, every session. The superclawd CLI loads your workspace's skills, agents, commands, workflows, and live directives into Claude Code as a plugin.",
5
5
  "author": "SuperClawd <support@superclawd.com>",
6
6
  "license": "SEE LICENSE IN LICENSE",