badgerclaw 0.2.37 → 0.2.39

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,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Eo=Object.create;var ye=Object.defineProperty;var Do=Object.getOwnPropertyDescriptor;var Oo=Object.getOwnPropertyNames;var No=Object.getPrototypeOf,To=Object.prototype.hasOwnProperty;var jo=(e,t)=>()=>(e&&(t=e(e=0)),t);var Bo=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Lo=(e,t)=>{for(var o in t)ye(e,o,{get:t[o],enumerable:!0})},wt=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Oo(t))!To.call(e,n)&&n!==o&&ye(e,n,{get:()=>t[n],enumerable:!(s=Do(t,n))||s.enumerable});return e};var c=(e,t,o)=>(o=e!=null?Eo(No(e)):{},wt(t||!e||!e.__esModule?ye(o,"default",{value:e,enumerable:!0}):o,e)),yt=e=>wt(ye({},"__esModule",{value:!0}),e);var z=Bo((Es,Yo)=>{Yo.exports={name:"badgerclaw",version:"0.2.37",description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","scripts/","README.md"],scripts:{build:"node build.mjs","verify-dist-version":`node -e "const v=require('./package.json').version; const d=require('fs').readFileSync('./dist/index.js','utf8'); if(!d.includes('version:\\"'+v+'\\"')){console.error('dist/index.js is stale \u2014 rebuild before publish (package.json='+v+')'); process.exit(1);} console.log('dist/index.js OK \u2014 version '+v);"`,prepublishOnly:"rm -rf dist && npm run build && npm run verify-dist-version",preuninstall:"node scripts/preuninstall.cjs",test:'echo "Error: no test specified" && exit 1'},keywords:[],author:"",license:"ISC",dependencies:{"@modelcontextprotocol/sdk":"^1.29.0",axios:"^1.6.0",chalk:"^4.1.2",commander:"^12.0.0",eventsource:"^1.1.2",open:"^8.4.2",ora:"^5.4.1"},devDependencies:{"@types/eventsource":"^1.1.15","@types/node":"^20.0.0",esbuild:"^0.28.0",typescript:"^5.3.0"}}});var dt={};Lo(dt,{getActiveSessions:()=>lt,launchClaudeCode:()=>at,launchMCPServer:()=>rt,recordSession:()=>it,stopSession:()=>ct});function tt(){try{if(E.default.existsSync(et))return JSON.parse(E.default.readFileSync(et,"utf-8"))}catch{}return[]}function ot(e){E.default.mkdirSync(Y,{recursive:!0}),E.default.writeFileSync(et,JSON.stringify(e,null,2))}function De(e){try{return process.kill(e,0),!0}catch{return!1}}function dn(){if(process.env.TMUX)return"tmux";try{if((0,F.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),E.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function nt(e,t){let o=j.default.join(Y,`claude-launcher-${t}.exp`),s=j.default.join(Y,`pending-input-${t}.txt`);E.default.writeFileSync(s,"","utf-8");let n=`#!/usr/bin/expect -f
2
+ "use strict";var zo=Object.create;var Ie=Object.defineProperty;var Yo=Object.getOwnPropertyDescriptor;var Ko=Object.getOwnPropertyNames;var Xo=Object.getPrototypeOf,Qo=Object.prototype.hasOwnProperty;var Zo=(e,t)=>()=>(e&&(t=e(e=0)),t);var en=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),tn=(e,t)=>{for(var o in t)Ie(e,o,{get:t[o],enumerable:!0})},At=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ko(t))!Qo.call(e,n)&&n!==o&&Ie(e,n,{get:()=>t[n],enumerable:!(s=Yo(t,n))||s.enumerable});return e};var c=(e,t,o)=>(o=e!=null?zo(Xo(e)):{},At(t||!e||!e.__esModule?Ie(o,"default",{value:e,enumerable:!0}):o,e)),Rt=e=>At(Ie({},"__esModule",{value:!0}),e);var K=en((Ks,pn)=>{pn.exports={name:"badgerclaw",version:"0.2.39",description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","scripts/","README.md"],scripts:{build:"node build.mjs","verify-dist-version":`node -e "const v=require('./package.json').version; const d=require('fs').readFileSync('./dist/index.js','utf8'); if(!d.includes('version:\\"'+v+'\\"')){console.error('dist/index.js is stale \u2014 rebuild before publish (package.json='+v+')'); process.exit(1);} console.log('dist/index.js OK \u2014 version '+v);"`,prepublishOnly:"rm -rf dist && npm run build && npm run verify-dist-version",preuninstall:"node scripts/preuninstall.cjs",test:'echo "Error: no test specified" && exit 1'},keywords:[],author:"",license:"ISC",dependencies:{"@modelcontextprotocol/sdk":"^1.29.0",axios:"^1.6.0",chalk:"^4.1.2",commander:"^12.0.0",eventsource:"^1.1.2",open:"^8.4.2",ora:"^5.4.1"},devDependencies:{"@types/eventsource":"^1.1.15","@types/node":"^20.0.0",esbuild:"^0.28.0",typescript:"^5.3.0"}}});var St={};tn(St,{getActiveSessions:()=>bt,launchClaudeCode:()=>wt,launchMCPServer:()=>ht,recordSession:()=>yt,stopSession:()=>_t});function mt(){try{if(R.default.existsSync(ut))return JSON.parse(R.default.readFileSync(ut,"utf-8"))}catch{}return[]}function gt(e){R.default.mkdirSync(X,{recursive:!0}),R.default.writeFileSync(ut,JSON.stringify(e,null,2))}function Ge(e){try{return process.kill(e,0),!0}catch{return!1}}function Rn(){if(process.env.TMUX)return"tmux";try{if((0,G.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),R.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function pt(e,t){let o=T.default.join(X,`claude-launcher-${t}.exp`),s=T.default.join(X,`pending-input-${t}.txt`);R.default.writeFileSync(s,"","utf-8");let n=`#!/usr/bin/expect -f
3
3
  set timeout -1
4
4
  set msgfile "${s}"
5
5
 
@@ -36,27 +36,27 @@ send "\\r"
36
36
  interact timeout 2 {
37
37
  check_and_send_messages
38
38
  }
39
- `;return E.default.mkdirSync(Y,{recursive:!0}),E.default.writeFileSync(o,n,{mode:493}),o}function st(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function un(e,t,o){let s=nt(e,o.BADGERCLAW_SESSION_ID||"default"),n=st(o),r=`
39
+ `;return R.default.mkdirSync(X,{recursive:!0}),R.default.writeFileSync(o,n,{mode:493}),o}function ft(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function Pn(e,t,o){let s=pt(e,o.BADGERCLAW_SESSION_ID||"default"),n=ft(o),r=`
40
40
  tell application "iTerm"
41
41
  activate
42
42
  set newWindow to (create window with default profile)
43
43
  tell current session of newWindow
44
- write text "cd ${Oe(t)} && ${n} && ${Oe(s)}"
44
+ write text "cd ${Ve(t)} && ${n} && ${Ve(s)}"
45
45
  end tell
46
46
  end tell
47
- `;(0,F.execSync)(`osascript -e '${r.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function mn(e,t,o){let s=nt(e,o.BADGERCLAW_SESSION_ID||"default"),n=st(o),a=`
47
+ `;(0,G.execSync)(`osascript -e '${r.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function En(e,t,o){let s=pt(e,o.BADGERCLAW_SESSION_ID||"default"),n=ft(o),a=`
48
48
  tell application "Terminal"
49
49
  activate
50
- do script "${`cd ${Oe(t)} && ${n} && ${Oe(s)}`.replace(/"/g,'\\"')}"
50
+ do script "${`cd ${Ve(t)} && ${n} && ${Ve(s)}`.replace(/"/g,'\\"')}"
51
51
  end tell
52
- `;(0,F.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function pn(e,t,o){let s=nt(e,o.BADGERCLAW_SESSION_ID||"default"),n=st(o),r=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${n} && ${s}`;(0,F.execSync)(`tmux new-session -d -s ${r} "${a}"`,{stdio:"pipe",timeout:1e4})}function Oe(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function rt(e){let t=j.default.join(__dirname,"..","claude-code","mcp-server.js"),o=E.default.existsSync(t)?t:j.default.join(__dirname,"mcp-server.js"),s=(0,F.spawn)("node",[o],{env:{...process.env,BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},cwd:e.projectDir,stdio:"ignore",detached:!0});return s.unref(),s}function at(e){let t=j.default.join(j.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=j.default.join(__dirname,"..","claude-code","mcp-server.js"),s=j.default.join(__dirname,"mcp-server.js"),n=E.default.existsSync(t)?t:E.default.existsSync(o)?o:s,r={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[n],env:r}}}),i=j.default.join(Y,`mcp-config-${e.sessionId}.json`);E.default.mkdirSync(Y,{recursive:!0}),E.default.writeFileSync(i,a,"utf-8");let l=`claude --dangerously-skip-permissions --mcp-config ${i}`;switch(dn()){case"iterm2":un(l,e.projectDir,r);break;case"terminal":mn(l,e.projectDir,r);break;case"tmux":pn(l,e.projectDir,r);break;case"direct":(0,F.spawn)(l,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...r},stdio:"ignore",detached:!0}).unref();break}}function it(e,t,o,s,n){let r=tt().filter(a=>a.sessionId!==e);r.push({sessionId:e,pid:t,mcpPid:o,port:s,projectDir:n,startedAt:new Date().toISOString()}),ot(r)}function ct(e){let t=tt(),o=t.find(n=>n.sessionId===e);if(!o)return!1;if(o.mcpPid&&De(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&De(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,F.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let s=t.filter(n=>n.sessionId!==e);return ot(s),!0}function lt(){let e=tt(),t=e.filter(o=>De(o.mcpPid)||De(o.pid));return t.length!==e.length&&ot(t),t}var F,E,j,ro,Y,et,Ne=jo(()=>{"use strict";F=require("child_process"),E=c(require("fs")),j=c(require("path")),ro=c(require("os")),Y=j.default.join(ro.default.homedir(),".badgerclaw"),et=j.default.join(Y,"claude-sessions.json")});var Ro=require("commander");var Wt=require("commander"),G=c(require("chalk")),qt=c(require("ora")),Ht=c(require("open")),Ye=c(require("os"));var Fe=c(require("crypto"));function _t(){return Fe.default.randomBytes(32).toString("base64url")}function bt(e){return Fe.default.createHash("sha256").update(e).digest("base64url")}var re=c(require("fs")),Me=c(require("path")),St=c(require("os")),$t=Me.default.join(St.default.homedir(),".badgerclaw"),Ge=Me.default.join($t,"auth.json");function h(){try{let e=re.default.readFileSync(Ge,"utf-8");return JSON.parse(e)}catch{return null}}function _e(e){re.default.mkdirSync($t,{recursive:!0}),re.default.writeFileSync(Ge,JSON.stringify(e,null,2),{mode:384})}function ae(){try{re.default.unlinkSync(Ge)}catch{}}function be(){let e=h();return e?new Date(e.expires_at)>new Date:!1}function Se(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var L=c(require("os")),Ct=c(require("crypto"));function Ve(){return Ct.default.createHash("sha256").update(`${L.default.hostname()}-${L.default.platform()}-${L.default.arch()}`).digest("hex").slice(0,16)}function J(){let e=h();if(e?.instance_id)return e.instance_id;let t=Ve();return`openclaw-${L.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function $e(){return{hostname:L.default.hostname(),os:L.default.platform(),arch:L.default.arch(),uptimeSeconds:Math.floor(L.default.uptime()),memFreeMb:Math.floor(L.default.freemem()/1024/1024)}}var ce=c(require("axios"));var vt=process.env.BADGERCLAW_ENV==="local",N=process.env.BADGERCLAW_API_URL??(vt?"http://localhost:8000":"https://api.badger.signout.io"),It=process.env.BADGERCLAW_AUTH_URL??(vt?"http://localhost:5500":"https://badgerclaw.ai");var ve=N,Q=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},xt=/account\s+has\s+been\s+(deleted|deactivated)/i,Ce=null,ie=null;function At(){return ie}function Uo(e){if(!e)return null;let t=e.split(".");if(t.length!==3)return null;try{let o=t[1].replace(/-/g,"+").replace(/_/g,"/"),s=o.length%4===0?o:o+"=".repeat(4-o.length%4),n=JSON.parse(Buffer.from(s,"base64").toString("utf8"));return(typeof n?.sub=="string"?n.sub:null)||null}catch{return null}}async function We(){let e=h();if(!e?.refresh_token||!e?.email)return ie=e?e.refresh_token?"no email in auth.json \u2014 re-run `badgerclaw login`":"no refresh_token in auth.json \u2014 re-run `badgerclaw login`":"not logged in (auth.json missing)",null;let t=Uo(e.access_token);try{let o=await ce.default.post(`${ve}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email,...t?{cognito_username:t}:{}}),s=o.data?.result??o.data,n=s?.access_token;if(!n)return ie="server returned no access_token",null;let r=s.expires_in||3600,a=new Date(Date.now()+r*1e3).toISOString();return _e({...e,access_token:n,expires_at:a}),ie=null,n}catch(o){let s=o?.response?.status,n=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";ie=s?`HTTP ${s}: ${n}`:`network error: ${n}`;let r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(s===403&&xt.test(r))throw ae(),new Q(r);return null}}function qe(e){return e.interceptors.response.use(t=>(t.data&&typeof t.data=="object"&&"result"in t.data&&"errors"in t.data&&(t.data=t.data.result),t),t=>{let o=t.response?.data?.errors;return o?.length&&(t.message=o[0]),Promise.reject(t)}),e}function kt(e){return e.interceptors.response.use(void 0,t=>{if(t.response?.status===403){let s=t.message||t.response?.data?.errors?.[0]||t.response?.data?.detail||"";if(xt.test(s))return ae(),Promise.reject(new Q(s))}return Promise.reject(t)}),e}function Rt(e){return e.interceptors.response.use(void 0,async t=>{let o=t.config;if(t.response?.status!==401||o._retried)return Promise.reject(t);o._retried=!0,Ce||(Ce=We().finally(()=>{Ce=null}));let s=await Ce;return s?(o.headers.Authorization=`Bearer ${s}`,e.request(o)):Promise.reject(t)}),e}function R(){let e=h(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=ce.default.create({baseURL:ve,headers:t});return qe(o),Rt(o),kt(o),o}function Pt(){return qe(ce.default.create({baseURL:ve,headers:{"Content-Type":"application/json"}}))}function Ie(e){let t=ce.default.create({baseURL:ve,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return qe(t),Rt(t),kt(t),t}var Et=require("commander"),B=c(require("chalk")),He=c(require("ora")),Dt=c(require("os")),Ot=c(require("path")),Nt=c(require("fs"));var Fo=Ot.default.join(Dt.default.homedir(),".openclaw","openclaw.json");function Tt(e,t,o="gateway"){for(let[s,n]of Object.entries(e)){let r=`${o}.${s}`;if(n==null)continue;if(typeof n=="object"&&!Array.isArray(n)){Tt(n,t,r);continue}let a=typeof n=="string"?`"${n.replace(/"/g,'\\"')}"`:String(n);try{t(`openclaw config set ${r} ${a}`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"})}catch{}}}async function le(e,t,o,s){let n=h();if(!n)return;let r=s?null:(0,He.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${N}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:J()})});if(!a.ok){if(a.status===410){r?.info(B.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let I=await a.json().catch(()=>({errors:[a.statusText]}));r?.fail(B.default.red(`Failed to redeem ${t}: ${I.errors?.[0]||a.status}`));return}let i=await a.json(),l=i.result??i,f=null;try{let I=Nt.default.readFileSync(Fo,"utf-8"),A=JSON.parse(I);A&&typeof A.gateway=="object"&&(f=A.gateway)}catch{}let{execSync:b}=await import("child_process"),v=`channels.badgerclaw.accounts.${l.user_id.split(":")[0].replace("@","").replace(/_bot$/,"")}`;b(`openclaw config set ${v}.userId "${l.user_id}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),b(`openclaw config set ${v}.accessToken "${l.access_token}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),b(`openclaw config set ${v}.homeserver "${l.homeserver}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),b(`openclaw config set ${v}.encryption true`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),l.device_id&&b(`openclaw config set ${v}.deviceId "${l.device_id}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),f&&Tt(f,b),await fetch(`${N}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${n.access_token}`}}).catch(()=>{}),r?.succeed(B.default.green(`\u2705 ${l.bot_name} (${l.user_id}) paired \u2014 bot is live!`))}catch(a){r?.fail(B.default.red(`Failed to pair ${t}: ${a.message}`))}}async function de(e=!1){let t=h();if(!t)return 0;let o=Ie(t.access_token);try{let{data:s}=await o.get("/api/v1/openclaw/pending-pairs");if(!s||s.length===0)return 0;let n=new Map;for(let a of s)n.set(a.bot_user_id,a);for(let a of s)n.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let r=0;for(let a of n.values()){let i=e?null:(0,He.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await le(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),r++}catch(l){i?.fail(B.default.red(`Error pairing ${a.bot_name}: ${l}`))}}if(r>0)try{let{execSync:a}=await import("child_process");a("openclaw gateway restart",{stdio:"ignore"}),e||console.log(B.default.green(`
53
- \u26A1 ${r} bot(s) paired \u2014 gateway restarted, bots are live!`))}catch{e||console.log(B.default.yellow(`
54
- \u26A1 ${r} bot(s) paired. Run: openclaw gateway restart`))}return r}catch{return 0}}var jt=new Et.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!h()){console.log(B.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(B.default.dim("Checking for pending bot pairs...")),await de(!1)===0&&console.log(B.default.dim("No pending pairs found."))});var Gt=c(require("os"));var xe=c(require("fs")),Z=c(require("path")),ue=c(require("os")),me=require("child_process"),Bt="ai.badgerclaw.watch",Lt=Z.default.join(ue.default.homedir(),"Library","LaunchAgents"),Je=Z.default.join(Lt,`${Bt}.plist`);function Mo(){try{return(0,me.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function Go(){try{return(0,me.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function Vo(e){let t=Z.default.join(ue.default.homedir(),".badgerclaw"),o=Go(),s=Z.default.dirname(o);return`<?xml version="1.0" encoding="UTF-8"?>
52
+ `;(0,G.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function On(e,t,o){let s=pt(e,o.BADGERCLAW_SESSION_ID||"default"),n=ft(o),r=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${n} && ${s}`;(0,G.execSync)(`tmux new-session -d -s ${r} "${a}"`,{stdio:"pipe",timeout:1e4})}function Ve(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ht(e){let t=T.default.join(__dirname,"..","claude-code","mcp-server.js"),o=R.default.existsSync(t)?t:T.default.join(__dirname,"mcp-server.js"),s=(0,G.spawn)("node",[o],{env:{...process.env,BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},cwd:e.projectDir,stdio:"ignore",detached:!0});return s.unref(),s}function wt(e){let t=T.default.join(T.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=T.default.join(__dirname,"..","claude-code","mcp-server.js"),s=T.default.join(__dirname,"mcp-server.js"),n=R.default.existsSync(t)?t:R.default.existsSync(o)?o:s,r={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[n],env:r}}}),i=T.default.join(X,`mcp-config-${e.sessionId}.json`);R.default.mkdirSync(X,{recursive:!0}),R.default.writeFileSync(i,a,"utf-8");let l=`claude --dangerously-skip-permissions --mcp-config ${i}`;switch(Rn()){case"iterm2":Pn(l,e.projectDir,r);break;case"terminal":En(l,e.projectDir,r);break;case"tmux":On(l,e.projectDir,r);break;case"direct":(0,G.spawn)(l,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...r},stdio:"ignore",detached:!0}).unref();break}}function yt(e,t,o,s,n){let r=mt().filter(a=>a.sessionId!==e);r.push({sessionId:e,pid:t,mcpPid:o,port:s,projectDir:n,startedAt:new Date().toISOString()}),gt(r)}function _t(e){let t=mt(),o=t.find(n=>n.sessionId===e);if(!o)return!1;if(o.mcpPid&&Ge(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Ge(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,G.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let s=t.filter(n=>n.sessionId!==e);return gt(s),!0}function bt(){let e=mt(),t=e.filter(o=>Ge(o.mcpPid)||Ge(o.pid));return t.length!==e.length&&gt(t),t}var G,R,T,So,X,ut,We=Zo(()=>{"use strict";G=require("child_process"),R=c(require("fs")),T=c(require("path")),So=c(require("os")),X=T.default.join(So.default.homedir(),".badgerclaw"),ut=T.default.join(X,"claude-sessions.json")});var Wo=require("commander");var so=require("commander"),W=c(require("chalk")),ro=c(require("ora")),ao=c(require("open")),it=c(require("os"));var Xe=c(require("crypto"));function Pt(){return Xe.default.randomBytes(32).toString("base64url")}function Et(e){return Xe.default.createHash("sha256").update(e).digest("base64url")}var ie=c(require("fs")),Qe=c(require("path")),Ot=c(require("os")),Dt=Qe.default.join(Ot.default.homedir(),".badgerclaw"),Ze=Qe.default.join(Dt,"auth.json");function h(){try{let e=ie.default.readFileSync(Ze,"utf-8");return JSON.parse(e)}catch{return null}}function xe(e){ie.default.mkdirSync(Dt,{recursive:!0}),ie.default.writeFileSync(Ze,JSON.stringify(e,null,2),{mode:384})}function ce(){try{ie.default.unlinkSync(Ze)}catch{}}function ke(){let e=h();return e?new Date(e.expires_at)>new Date:!1}function Ae(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var B=c(require("os")),Nt=c(require("crypto"));function et(){return Nt.default.createHash("sha256").update(`${B.default.hostname()}-${B.default.platform()}-${B.default.arch()}`).digest("hex").slice(0,16)}function z(){let e=h();if(e?.instance_id)return e.instance_id;let t=et();return`openclaw-${B.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function Re(){return{hostname:B.default.hostname(),os:B.default.platform(),arch:B.default.arch(),uptimeSeconds:Math.floor(B.default.uptime()),memFreeMb:Math.floor(B.default.freemem()/1024/1024)}}var de=c(require("axios"));var Tt=process.env.BADGERCLAW_ENV==="local",D=process.env.BADGERCLAW_API_URL??(Tt?"http://localhost:8000":"https://api.badger.signout.io"),jt=process.env.BADGERCLAW_AUTH_URL??(Tt?"http://localhost:5500":"https://badgerclaw.ai");var Ee=D,te=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},Lt=/account\s+has\s+been\s+(deleted|deactivated)/i,Pe=null,le=null;function Bt(){return le}function on(e){if(!e)return null;let t=e.split(".");if(t.length!==3)return null;try{let o=t[1].replace(/-/g,"+").replace(/_/g,"/"),s=o.length%4===0?o:o+"=".repeat(4-o.length%4),n=JSON.parse(Buffer.from(s,"base64").toString("utf8"));return(typeof n?.sub=="string"?n.sub:null)||null}catch{return null}}async function tt(){let e=h();if(!e?.refresh_token||!e?.email)return le=e?e.refresh_token?"no email in auth.json \u2014 re-run `badgerclaw login`":"no refresh_token in auth.json \u2014 re-run `badgerclaw login`":"not logged in (auth.json missing)",null;let t=on(e.access_token);try{let o=await de.default.post(`${Ee}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email,...t?{cognito_username:t}:{}}),s=o.data?.result??o.data,n=s?.access_token;if(!n)return le="server returned no access_token",null;let r=s.expires_in||3600,a=new Date(Date.now()+r*1e3).toISOString();return xe({...e,access_token:n,expires_at:a}),le=null,n}catch(o){let s=o?.response?.status,n=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";le=s?`HTTP ${s}: ${n}`:`network error: ${n}`;let r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(s===403&&Lt.test(r))throw ce(),new te(r);return null}}function ot(e){return e.interceptors.response.use(t=>(t.data&&typeof t.data=="object"&&"result"in t.data&&"errors"in t.data&&(t.data=t.data.result),t),t=>{let o=t.response?.data?.errors;return o?.length&&(t.message=o[0]),Promise.reject(t)}),e}function Ut(e){return e.interceptors.response.use(void 0,t=>{if(t.response?.status===403){let s=t.message||t.response?.data?.errors?.[0]||t.response?.data?.detail||"";if(Lt.test(s))return ce(),Promise.reject(new te(s))}return Promise.reject(t)}),e}function Ft(e){return e.interceptors.response.use(void 0,async t=>{let o=t.config;if(t.response?.status!==401||o._retried)return Promise.reject(t);o._retried=!0,Pe||(Pe=tt().finally(()=>{Pe=null}));let s=await Pe;return s?(o.headers.Authorization=`Bearer ${s}`,e.request(o)):Promise.reject(t)}),e}function A(){let e=h(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=de.default.create({baseURL:Ee,headers:t});return ot(o),Ft(o),Ut(o),o}function Mt(){return ot(de.default.create({baseURL:Ee,headers:{"Content-Type":"application/json"}}))}function Oe(e){let t=de.default.create({baseURL:Ee,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return ot(t),Ft(t),Ut(t),t}var Gt=require("commander"),j=c(require("chalk")),nt=c(require("ora")),Vt=c(require("os")),Wt=c(require("path")),Ht=c(require("fs"));var nn=Wt.default.join(Vt.default.homedir(),".openclaw","openclaw.json");function qt(e,t,o="gateway"){for(let[s,n]of Object.entries(e)){let r=`${o}.${s}`;if(n==null)continue;if(typeof n=="object"&&!Array.isArray(n)){qt(n,t,r);continue}let a=typeof n=="string"?`"${n.replace(/"/g,'\\"')}"`:String(n);try{t(`openclaw config set ${r} ${a}`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"})}catch{}}}async function ue(e,t,o,s){let n=h();if(!n)return;let r=s?null:(0,nt.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${D}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:z()})});if(!a.ok){if(a.status===410){r?.info(j.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let I=await a.json().catch(()=>({errors:[a.statusText]}));r?.fail(j.default.red(`Failed to redeem ${t}: ${I.errors?.[0]||a.status}`));return}let i=await a.json(),l=i.result??i,f=null;try{let I=Ht.default.readFileSync(nn,"utf-8"),k=JSON.parse(I);k&&typeof k.gateway=="object"&&(f=k.gateway)}catch{}let{execSync:b}=await import("child_process"),v=`channels.badgerclaw.accounts.${l.user_id.split(":")[0].replace("@","").replace(/_bot$/,"")}`;b(`openclaw config set ${v}.userId "${l.user_id}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),b(`openclaw config set ${v}.accessToken "${l.access_token}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),b(`openclaw config set ${v}.homeserver "${l.homeserver}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),b(`openclaw config set ${v}.encryption true`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),l.device_id&&b(`openclaw config set ${v}.deviceId "${l.device_id}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),f&&qt(f,b),await fetch(`${D}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${n.access_token}`}}).catch(()=>{}),r?.succeed(j.default.green(`\u2705 ${l.bot_name} (${l.user_id}) paired \u2014 bot is live!`))}catch(a){r?.fail(j.default.red(`Failed to pair ${t}: ${a.message}`))}}async function me(e=!1){let t=h();if(!t)return 0;let o=Oe(t.access_token);try{let{data:s}=await o.get("/api/v1/openclaw/pending-pairs");if(!s||s.length===0)return 0;let n=new Map;for(let a of s)n.set(a.bot_user_id,a);for(let a of s)n.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let r=0;for(let a of n.values()){let i=e?null:(0,nt.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await ue(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),r++}catch(l){i?.fail(j.default.red(`Error pairing ${a.bot_name}: ${l}`))}}if(r>0)try{let{execSync:a}=await import("child_process");a("openclaw gateway restart",{stdio:"ignore"}),e||console.log(j.default.green(`
53
+ \u26A1 ${r} bot(s) paired \u2014 gateway restarted, bots are live!`))}catch{e||console.log(j.default.yellow(`
54
+ \u26A1 ${r} bot(s) paired. Run: openclaw gateway restart`))}return r}catch{return 0}}var Jt=new Gt.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!h()){console.log(j.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(j.default.dim("Checking for pending bot pairs...")),await me(!1)===0&&console.log(j.default.dim("No pending pairs found."))});var Zt=c(require("os"));var De=c(require("fs")),oe=c(require("path")),ge=c(require("os")),pe=require("child_process"),zt="ai.badgerclaw.watch",Yt=oe.default.join(ge.default.homedir(),"Library","LaunchAgents"),st=oe.default.join(Yt,`${zt}.plist`);function sn(){try{return(0,pe.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function rn(){try{return(0,pe.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function an(e){let t=oe.default.join(ge.default.homedir(),".badgerclaw"),o=rn(),s=oe.default.dirname(o);return`<?xml version="1.0" encoding="UTF-8"?>
55
55
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
56
56
  <plist version="1.0">
57
57
  <dict>
58
58
  <key>Label</key>
59
- <string>${Bt}</string>
59
+ <string>${zt}</string>
60
60
  <key>ProgramArguments</key>
61
61
  <array>
62
62
  <string>${o}</string>
@@ -79,7 +79,7 @@ interact timeout 2 {
79
79
  <key>ThrottleInterval</key>
80
80
  <integer>30</integer>
81
81
  </dict>
82
- </plist>`}function Ut(){if(ue.default.platform()==="darwin")try{let e=Mo();xe.default.mkdirSync(Lt,{recursive:!0}),xe.default.mkdirSync(Z.default.join(ue.default.homedir(),".badgerclaw"),{recursive:!0}),xe.default.writeFileSync(Je,Vo(e));try{(0,me.execSync)(`launchctl unload "${Je}" 2>/dev/null`)}catch{}(0,me.execSync)(`launchctl load "${Je}"`),console.log("\x1B[2mPair-watcher registered as background service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register background service. Run `badgerclaw watch` manually.\x1B[0m")}}var Ae=c(require("fs")),pe=c(require("path")),ke=c(require("os")),U=require("child_process"),ze="badgerclaw-watch.service",Ft=pe.default.join(ke.default.homedir(),".config","systemd","user"),Wo=pe.default.join(Ft,ze);function qo(){try{return(0,U.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function Ho(){try{return(0,U.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function Jo(e){let t=Ho(),o=pe.default.dirname(t);return`[Unit]
82
+ </plist>`}function Kt(){if(ge.default.platform()==="darwin")try{let e=sn();De.default.mkdirSync(Yt,{recursive:!0}),De.default.mkdirSync(oe.default.join(ge.default.homedir(),".badgerclaw"),{recursive:!0}),De.default.writeFileSync(st,an(e));try{(0,pe.execSync)(`launchctl unload "${st}" 2>/dev/null`)}catch{}(0,pe.execSync)(`launchctl load "${st}"`),console.log("\x1B[2mPair-watcher registered as background service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register background service. Run `badgerclaw watch` manually.\x1B[0m")}}var Ne=c(require("fs")),fe=c(require("path")),Te=c(require("os")),F=require("child_process"),rt="badgerclaw-watch.service",Xt=fe.default.join(Te.default.homedir(),".config","systemd","user"),cn=fe.default.join(Xt,rt);function ln(){try{return(0,F.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function dn(){try{return(0,F.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function un(e){let t=dn(),o=fe.default.dirname(t);return`[Unit]
83
83
  Description=BadgerClaw background watcher (heartbeat + pair events)
84
84
  After=network-online.target
85
85
  Wants=network-online.target
@@ -95,10 +95,11 @@ StandardError=append:%h/.badgerclaw/heartbeat.log
95
95
 
96
96
  [Install]
97
97
  WantedBy=default.target
98
- `}function zo(){try{return(0,U.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function Mt(){if(ke.default.platform()==="linux"){if(!zo()){console.log("\x1B[2mNote: systemctl --user not available. Run `badgerclaw heartbeat` manually or start it under a process manager.\x1B[0m");return}try{let e=qo();Ae.default.mkdirSync(Ft,{recursive:!0}),Ae.default.mkdirSync(pe.default.join(ke.default.homedir(),".badgerclaw"),{recursive:!0}),Ae.default.writeFileSync(Wo,Jo(e)),(0,U.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,U.execSync)(`systemctl --user restart ${ze}`,{stdio:"ignore"})}catch{}(0,U.execSync)(`systemctl --user enable --now ${ze}`,{stdio:"ignore"});try{let t=(0,U.execSync)("whoami",{encoding:"utf-8"}).trim();(0,U.execSync)(`loginctl enable-linger ${t}`,{stdio:"ignore"})}catch{}console.log("\x1B[2mHeartbeat daemon registered as systemd user service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register systemd user service. Run `badgerclaw heartbeat` manually.\x1B[0m")}}}function Vt(){let e=Gt.default.platform();if(e==="darwin")return Ut();if(e==="linux")return Mt();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var Ko=2e3,Xo=12e4,Jt=new Wt.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=_t(),t=bt(e),o=`${It}/cli-auth?code=${t}`;console.log(G.default.yellow("Opening browser for authentication...")),console.log(G.default.dim(`If the browser doesn't open, visit: ${o}`)),await(0,Ht.default)(o);let s=(0,qt.default)("Waiting for authentication...").start(),n=Pt(),r=Date.now();for(;Date.now()-r<Xo;){try{let a=await n.post(`/api/v1/openclaw/cli/auth/poll/${t}`,{code_verifier:e,code_challenge:t});if(a.status===429){await new Promise(i=>setTimeout(i,5e3));continue}if(a.data?.access_token){let{access_token:i,user_id:l,expires_at:f,refresh_token:b,email:y}=a.data,v=Ve(),I=`openclaw-${Ye.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${v}`,A=I;try{let{version:P}=z(),se=await n.post("/api/v1/openclaw/register",{instance_id:I,label:Ye.default.hostname(),version:P,machine_fingerprint:v},{headers:{Authorization:`Bearer ${i}`}}),H=se.data?.result||se.data;H&&typeof H.instance_id=="string"&&H.instance_id.length>0&&(A=H.instance_id)}catch(P){let se=P?.response?.status;if(se===403||se===409){let H=P?.response?.data?.detail,Po=typeof H=="string"?H:"Your current plan only allows one OpenClaw instance. Upgrade your plan or remove the existing machine, then try again.";s.fail(G.default.red(Po)),process.exit(1)}}_e({access_token:i,user_id:l,instance_id:A,expires_at:f,refresh_token:b,email:y}),s.succeed(G.default.green(`Logged in as ${Se(l)}`));let k=await de(!0);k>0&&(console.log(G.default.green(`\u2705 ${k} bot(s) automatically paired to OpenClaw.`)),console.log(G.default.yellow("Run: openclaw gateway restart to activate."))),Vt();return}}catch{}await new Promise(a=>setTimeout(a,Ko))}s.fail(G.default.red("Authentication timed out. Please try again.")),process.exit(1)});var zt=require("commander"),Ke=c(require("chalk"));var Yt=new zt.Command("logout").description("Disconnect this machine and log out of BadgerClaw").action(async()=>{let e=h();if(!e){console.log(Ke.default.yellow("Not logged in."));return}try{let t=Ie(e.access_token),{version:o}=z();await t.post("/api/v1/openclaw/register",{instance_id:e.instance_id,label:require("os").hostname(),version:o,online:!1})}catch{}ae(),console.log(Ke.default.green("Logged out \u2014 this machine is now disconnected."))});var Kt=require("commander"),Xe=c(require("chalk"));var Xt=new Kt.Command("status").description("Show connected instance info").action(async()=>{let e=h();(!e||!be())&&(console.log(Xe.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(Xe.default.green("Authenticated")),console.log(` User: ${Se(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var ee=require("commander"),w=c(require("chalk")),Pe=c(require("ora")),Re=c(require("fs")),Qt=c(require("os")),Zt=c(require("path")),eo=require("child_process");function Qe(){be()||(console.log(w.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function Qo(e){return/^[a-z0-9_]{4,20}$/.test(e)}function to(e){return e.replace(/_bot$/,"")}var Zo=new ee.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").action(async e=>{Qe(),Qo(e)||(console.log(w.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let t=(0,Pe.default)(`Creating bot "${e}"...`).start();try{await R().post("/api/v1/openclaw/bots",{username:e}),t.succeed(w.default.green(`Bot "${e}" created successfully!`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(w.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),en=new ee.Command("list").description("List your bots").action(async()=>{Qe();let e=(0,Pe.default)("Fetching bots...").start();try{let s=(await R().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),s.length===0){console.log(w.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(w.default.green(`Your bots (${s.length}):
99
- `));for(let n of s){let r=to(n.username||n.name),a=n.active!==!1?w.default.green("active"):w.default.dim("inactive");console.log(` ${w.default.bold(r)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(w.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),tn=new ee.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{Qe();let t=(0,Pe.default)(`Deactivating bot "${e}"...`).start();try{await R().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(w.default.green(`Bot "${e}" deactivated.`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(w.default.red(`Failed to deactivate bot: ${s}`)),process.exit(1)}});function on(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),to(t)}function nn(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return Zt.default.join(Qt.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var sn=new ee.Command("refresh").description("Recover a bot stuck in quarantine \u2014 clears the quarantine ledger and restarts the gateway so the plugin's refresh chain runs from scratch").argument("<name>",'Bot name (e.g. "claude", "claude_bot", or full Matrix ID)').action(async e=>{let t=on(e);t||(console.log(w.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=nn(t),s=!1;if(Re.default.existsSync(o))try{let n=JSON.parse(Re.default.readFileSync(o,"utf-8")),r=n.failureCount??"?",a=n.quarantinedAt??"?";console.log(w.default.dim(` Quarantine for "${t}" \u2014 ${r} failures, since ${a}`)),Re.default.unlinkSync(o),s=!0}catch(n){console.log(w.default.red(`Failed to clear quarantine ledger at ${o}: ${n.message}`)),process.exit(1)}console.log(s?w.default.green(`\u2705 Cleared quarantine for "${t}"`):w.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(w.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,eo.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(n){console.log(w.default.yellow(` Gateway restart command failed: ${n.message}`)),console.log(w.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(w.default.green(`
100
- \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(w.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(w.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(w.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(w.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),oo=new ee.Command("bot").description("Manage bots").addCommand(Zo).addCommand(en).addCommand(tn).addCommand(sn);var fo=require("commander"),p=c(require("chalk"));var Ee=c(require("axios")),rn=7331,no=`http://localhost:${rn}`,an=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,cn=`http://127.0.0.1:${an}`,Ze="unknown";async function ln(){try{return await Ee.default.get(cn,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function ge(){try{let t=(await Ee.default.get(`${no}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(Ze=t.pluginVersion),t}catch{return{status:await ln()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:Ze,bots:[]}}}function so(e){e&&e!=="unknown"&&(Ze=e)}async function te(){try{return{success:!0,message:(await Ee.default.post(`${no}/restart`,{},{timeout:15e3})).data?.message||"Gateway restart initiated"}}catch(e){try{let{execSync:t}=await import("child_process");return t("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted via CLI fallback"}}catch{return{success:!1,message:e.message||"Failed to restart gateway"}}}}var co=require("commander"),d=c(require("chalk")),lo=c(require("axios"));var x=require("child_process"),m=c(require("fs")),S=c(require("path")),fe=c(require("os")),D=c(require("axios"));async function M(e){return e.command_type==="update_cli"?fn(e.payload?.target_version):e.command_type==="update_plugin"?hn(e.payload?.target_version):e.command_type==="restart_gateway"?gn():e.command_type==="leave_room"?Rn(e.payload):e.command_type==="start_claude_code"?Sn(e.payload):e.command_type==="stop_claude_code"?$n(e.payload):e.command_type==="start_claude_control"?Cn(e.payload):e.command_type==="stop_claude_control"?vn(e.payload):e.command_type==="update_claude_tools"?In(e.payload):e.command_type==="bot_share_notify"?xn(e.payload):e.command_type==="bot_share_revoked"?An(e.payload):e.command_type==="bot_share_expired"?kn(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function gn(){try{return(0,x.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,x.execSync)("curl -s -X POST http://localhost:7331/restart",{stdio:"pipe",timeout:1e4}).toString()}`}}catch(e){return{success:!1,message:`Gateway restart failed: ${e.message||"unknown error"}`}}}}function fn(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,x.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,x.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),n=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return yn(),{success:!0,message:`Updated CLI to ${n}`,newVersion:n}}catch(o){let s=o.stderr?.toString()||o.message||"Unknown error";return s.includes("EACCES")||s.includes("permission")?{success:!1,message:"Permission denied. Run: sudo npm install -g badgerclaw"}:{success:!1,message:`CLI update failed: ${s.slice(0,500)}`}}}async function hn(e){let t=S.default.join(fe.default.homedir(),".openclaw","extensions","badgerclaw");if(!m.default.existsSync(t))return{success:!1,message:"Cannot find plugin directory (~/.openclaw/extensions/badgerclaw). Re-run: badgerclaw setup"};let o=e?`@badgerclaw/connect@${e}`:"@badgerclaw/connect@latest";try{(0,x.execSync)(`npm install ${o}`,{cwd:t,stdio:"pipe",timeout:12e4});let s=S.default.join(t,"node_modules","@badgerclaw","connect"),n=S.default.join(s,"package.json"),r="unknown";m.default.existsSync(n)&&(r=JSON.parse(m.default.readFileSync(n,"utf-8")).version||"unknown"),so(r),wn(s,t);let a=S.default.join(t,"package.json");if(m.default.existsSync(a)&&m.default.existsSync(n))try{let i=JSON.parse(m.default.readFileSync(a,"utf-8")),l=JSON.parse(m.default.readFileSync(n,"utf-8"));i.version=r,l.openclaw&&(i.openclaw={...i.openclaw,...l.openclaw}),m.default.writeFileSync(a,JSON.stringify(i,null,2)+`
101
- `)}catch{}try{(0,x.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}for(let i=0;i<15;i++){await new Promise(l=>setTimeout(l,1e3));try{let l=await D.default.get("http://localhost:7331/health",{timeout:3e3});if(l.data?.status==="running"&&l.data?.pluginVersion===r)break}catch{}}return{success:!0,message:`Updated plugin to ${r}, gateway restarted`,newVersion:r}}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}function wn(e,t){let o=S.default.join(e,"dist"),s=S.default.join(t,"dist");m.default.existsSync(o)&&(m.default.mkdirSync(s,{recursive:!0}),ut(o,s));let n=S.default.join(e,"openclaw.plugin.json");m.default.existsSync(n)&&m.default.copyFileSync(n,S.default.join(t,"openclaw.plugin.json"));let r=S.default.join(e,"scripts"),a=S.default.join(t,"scripts");m.default.existsSync(r)&&(m.default.mkdirSync(a,{recursive:!0}),ut(r,a));for(let i of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let l=S.default.join(t,i);m.default.existsSync(l)&&(m.default.statSync(l).isDirectory()?m.default.rmSync(l,{recursive:!0,force:!0}):m.default.unlinkSync(l))}}function ut(e,t){for(let o of m.default.readdirSync(e,{withFileTypes:!0})){let s=S.default.join(e,o.name),n=S.default.join(t,o.name);o.isDirectory()?(m.default.mkdirSync(n,{recursive:!0}),ut(s,n)):m.default.copyFileSync(s,n)}}function yn(){try{try{(0,x.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,x.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,x.execSync)("sleep 1",{stdio:"pipe"});let e=(0,x.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,x.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,x.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function _n(){let e=S.default.join(fe.default.homedir(),".badgerclaw","workspace");m.default.mkdirSync(e,{recursive:!0});let t=S.default.join(e,".git");return m.default.existsSync(t)||(0,x.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),m.default.writeFileSync(S.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
98
+ `}function mn(){try{return(0,F.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function Qt(){if(Te.default.platform()==="linux"){if(!mn()){console.log("\x1B[2mNote: systemctl --user not available. Run `badgerclaw heartbeat` manually or start it under a process manager.\x1B[0m");return}try{let e=ln();Ne.default.mkdirSync(Xt,{recursive:!0}),Ne.default.mkdirSync(fe.default.join(Te.default.homedir(),".badgerclaw"),{recursive:!0}),Ne.default.writeFileSync(cn,un(e)),(0,F.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,F.execSync)(`systemctl --user restart ${rt}`,{stdio:"ignore"})}catch{}(0,F.execSync)(`systemctl --user enable --now ${rt}`,{stdio:"ignore"});try{let t=(0,F.execSync)("whoami",{encoding:"utf-8"}).trim();(0,F.execSync)(`loginctl enable-linger ${t}`,{stdio:"ignore"})}catch{}console.log("\x1B[2mHeartbeat daemon registered as systemd user service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register systemd user service. Run `badgerclaw heartbeat` manually.\x1B[0m")}}}function eo(){let e=Zt.default.platform();if(e==="darwin")return Kt();if(e==="linux")return Qt();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var at=c(require("fs")),oo=c(require("os")),no=c(require("path")),Y=require("child_process"),M=c(require("chalk")),to=no.default.join(oo.default.homedir(),".openclaw","openclaw.json");function gn(e=!1){let t=null;try{at.default.existsSync(to)&&(t=JSON.parse(at.default.readFileSync(to,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(M.default.dim(" Setting gateway.mode=local..."));try{return(0,Y.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0}catch(o){return e||(console.log(M.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(M.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}function je(e={}){let t=e.verbose!==!1,o=a=>{t&&console.log(a)};o(M.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,Y.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(M.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),gn(!t),o(M.default.dim(" Starting OpenClaw gateway..."));let n=(0,Y.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),r="started";return n.status!==0&&(n=(0,Y.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),r="restarted"),n.status!==0?{ok:!1,error:"gateway start/restart returned non-zero exit"}:{ok:!0,state:r}}function Le(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,Y.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(M.default.yellow(`
99
+ \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(M.default.dim(" Enable persistence: loginctl enable-linger root")))}var fn=2e3,hn=12e4,io=new so.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=Pt(),t=Et(e),o=`${jt}/cli-auth?code=${t}`;console.log(W.default.yellow("Opening browser for authentication...")),console.log(W.default.dim(`If the browser doesn't open, visit: ${o}`)),await(0,ao.default)(o);let s=(0,ro.default)("Waiting for authentication...").start(),n=Mt(),r=Date.now();for(;Date.now()-r<hn;){try{let a=await n.post(`/api/v1/openclaw/cli/auth/poll/${t}`,{code_verifier:e,code_challenge:t});if(a.status===429){await new Promise(i=>setTimeout(i,5e3));continue}if(a.data?.access_token){let{access_token:i,user_id:l,expires_at:f,refresh_token:b,email:y}=a.data,v=et(),I=`openclaw-${it.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${v}`,k=I;try{let{version:ve}=K(),ee=await n.post("/api/v1/openclaw/register",{instance_id:I,label:it.default.hostname(),version:ve,machine_fingerprint:v},{headers:{Authorization:`Bearer ${i}`}}),U=ee.data?.result||ee.data;U&&typeof U.instance_id=="string"&&U.instance_id.length>0&&(k=U.instance_id)}catch(ve){let ee=ve?.response?.status;if(ee===403||ee===409){let U=ve?.response?.data,Ho=Array.isArray(U?.errors)&&typeof U.errors[0]=="string"?U.errors[0]:null,Ke=U?.detail,qo=typeof Ke=="string"?Ke:Ke?.error==="downgrade_selection_required"?"Your account has an unresolved plan-change request. Open the BadgerClaw app to finish the downgrade selection, then try again.":null,Jo=Ho||qo||`Login refused (status ${ee}). Open the BadgerClaw app to check your subscription state.`;s.fail(W.default.red(Jo)),process.exit(1)}}xe({access_token:i,user_id:l,instance_id:k,expires_at:f,refresh_token:b,email:y}),s.succeed(W.default.green(`Logged in as ${Ae(l)}`)),je({verbose:!0}).ok||console.log(W.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair."));let N=await me(!0);N>0&&console.log(W.default.green(`\u2705 ${N} bot(s) automatically paired to OpenClaw.`)),eo(),Le();return}}catch{}await new Promise(a=>setTimeout(a,fn))}s.fail(W.default.red("Authentication timed out. Please try again.")),process.exit(1)});var lo=require("commander"),he=c(require("chalk")),Be=c(require("fs")),ne=c(require("os")),ye=c(require("path")),we=require("child_process");function wn(){let e=process.platform;if(e==="darwin"){let t=ye.default.join(ne.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,we.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{Be.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,we.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=ye.default.join(ne.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{Be.default.unlinkSync(t)}catch{}(0,we.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,we.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function co(e){try{return Be.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var uo=new lo.Command("logout").description("Disconnect this machine, log out of BadgerClaw, and wipe local state").option("--keep-state","Only clear auth.json (legacy behaviour); preserve bot-mapping, claude-sessions, heartbeat logs, and plugin quarantine ledger").action(async e=>{let t=h();if(t)try{let a=Oe(t.access_token),{version:i}=K();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:ne.default.hostname(),version:i,online:!1})}catch{}if(wn(),e.keepState){ce(),console.log(he.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=ye.default.join(ne.default.homedir(),".badgerclaw"),s=co(o),n=ye.default.join(ne.default.homedir(),".openclaw","badgerclaw"),r=co(n);s||r?(console.log(he.default.green("Logged out \u2014 local state cleared.")),console.log(he.default.dim(` Removed: ${o}${r?`, ${n}`:""}`))):console.log(he.default.green("Logged out."))});var mo=require("commander"),ct=c(require("chalk"));var go=new mo.Command("status").description("Show connected instance info").action(async()=>{let e=h();(!e||!ke())&&(console.log(ct.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(ct.default.green("Authenticated")),console.log(` User: ${Ae(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var se=require("commander"),w=c(require("chalk")),Fe=c(require("ora")),Ue=c(require("fs")),po=c(require("os")),fo=c(require("path")),ho=require("child_process");function lt(){ke()||(console.log(w.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function yn(e){return/^[a-z0-9_]{4,20}$/.test(e)}function wo(e){return e.replace(/_bot$/,"")}var _n=new se.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").action(async e=>{lt(),yn(e)||(console.log(w.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let t=(0,Fe.default)(`Creating bot "${e}"...`).start();try{await A().post("/api/v1/openclaw/bots",{username:e}),t.succeed(w.default.green(`Bot "${e}" created successfully!`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(w.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),bn=new se.Command("list").description("List your bots").action(async()=>{lt();let e=(0,Fe.default)("Fetching bots...").start();try{let s=(await A().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),s.length===0){console.log(w.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(w.default.green(`Your bots (${s.length}):
100
+ `));for(let n of s){let r=wo(n.username||n.name),a=n.active!==!1?w.default.green("active"):w.default.dim("inactive");console.log(` ${w.default.bold(r)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(w.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),Sn=new se.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{lt();let t=(0,Fe.default)(`Deactivating bot "${e}"...`).start();try{await A().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(w.default.green(`Bot "${e}" deactivated.`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(w.default.red(`Failed to deactivate bot: ${s}`)),process.exit(1)}});function $n(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),wo(t)}function Cn(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return fo.default.join(po.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var vn=new se.Command("refresh").description("Recover a bot stuck in quarantine \u2014 clears the quarantine ledger and restarts the gateway so the plugin's refresh chain runs from scratch").argument("<name>",'Bot name (e.g. "claude", "claude_bot", or full Matrix ID)').action(async e=>{let t=$n(e);t||(console.log(w.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=Cn(t),s=!1;if(Ue.default.existsSync(o))try{let n=JSON.parse(Ue.default.readFileSync(o,"utf-8")),r=n.failureCount??"?",a=n.quarantinedAt??"?";console.log(w.default.dim(` Quarantine for "${t}" \u2014 ${r} failures, since ${a}`)),Ue.default.unlinkSync(o),s=!0}catch(n){console.log(w.default.red(`Failed to clear quarantine ledger at ${o}: ${n.message}`)),process.exit(1)}console.log(s?w.default.green(`\u2705 Cleared quarantine for "${t}"`):w.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(w.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,ho.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(n){console.log(w.default.yellow(` Gateway restart command failed: ${n.message}`)),console.log(w.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(w.default.green(`
101
+ \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(w.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(w.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(w.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(w.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),yo=new se.Command("bot").description("Manage bots").addCommand(_n).addCommand(bn).addCommand(Sn).addCommand(vn);var Po=require("commander"),g=c(require("chalk"));var Me=c(require("axios")),In=7331,_o=`http://localhost:${In}`,xn=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,kn=`http://127.0.0.1:${xn}`,dt="unknown";async function An(){try{return await Me.default.get(kn,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function _e(){try{let t=(await Me.default.get(`${_o}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(dt=t.pluginVersion),t}catch{return{status:await An()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:dt,bots:[]}}}function bo(e){e&&e!=="unknown"&&(dt=e)}async function re(){try{return{success:!0,message:(await Me.default.post(`${_o}/restart`,{},{timeout:15e3})).data?.message||"Gateway restart initiated"}}catch(e){try{let{execSync:t}=await import("child_process");return t("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted via CLI fallback"}}catch{return{success:!1,message:e.message||"Failed to restart gateway"}}}}var vo=require("commander"),d=c(require("chalk")),Io=c(require("axios"));var x=require("child_process"),m=c(require("fs")),S=c(require("path")),be=c(require("os")),P=c(require("axios"));async function V(e){return e.command_type==="update_cli"?Nn(e.payload?.target_version):e.command_type==="update_plugin"?Tn(e.payload?.target_version):e.command_type==="restart_gateway"?Dn():e.command_type==="leave_room"?zn(e.payload):e.command_type==="start_claude_code"?Fn(e.payload):e.command_type==="stop_claude_code"?Mn(e.payload):e.command_type==="start_claude_control"?Gn(e.payload):e.command_type==="stop_claude_control"?Vn(e.payload):e.command_type==="update_claude_tools"?Wn(e.payload):e.command_type==="bot_share_notify"?Hn(e.payload):e.command_type==="bot_share_revoked"?qn(e.payload):e.command_type==="bot_share_expired"?Jn(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function Dn(){try{return(0,x.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,x.execSync)("curl -s -X POST http://localhost:7331/restart",{stdio:"pipe",timeout:1e4}).toString()}`}}catch(e){return{success:!1,message:`Gateway restart failed: ${e.message||"unknown error"}`}}}}function Nn(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,x.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,x.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),n=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return Ln(),{success:!0,message:`Updated CLI to ${n}`,newVersion:n}}catch(o){let s=o.stderr?.toString()||o.message||"Unknown error";return s.includes("EACCES")||s.includes("permission")?{success:!1,message:"Permission denied. Run: sudo npm install -g badgerclaw"}:{success:!1,message:`CLI update failed: ${s.slice(0,500)}`}}}async function Tn(e){let t=S.default.join(be.default.homedir(),".openclaw","extensions","badgerclaw");if(!m.default.existsSync(t))return{success:!1,message:"Cannot find plugin directory (~/.openclaw/extensions/badgerclaw). Re-run: badgerclaw setup"};let o=e?`@badgerclaw/connect@${e}`:"@badgerclaw/connect@latest";try{(0,x.execSync)(`npm install ${o}`,{cwd:t,stdio:"pipe",timeout:12e4});let s=S.default.join(t,"node_modules","@badgerclaw","connect"),n=S.default.join(s,"package.json"),r="unknown";m.default.existsSync(n)&&(r=JSON.parse(m.default.readFileSync(n,"utf-8")).version||"unknown"),bo(r),jn(s,t);let a=S.default.join(t,"package.json");if(m.default.existsSync(a)&&m.default.existsSync(n))try{let i=JSON.parse(m.default.readFileSync(a,"utf-8")),l=JSON.parse(m.default.readFileSync(n,"utf-8"));i.version=r,l.openclaw&&(i.openclaw={...i.openclaw,...l.openclaw}),m.default.writeFileSync(a,JSON.stringify(i,null,2)+`
102
+ `)}catch{}try{(0,x.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}for(let i=0;i<15;i++){await new Promise(l=>setTimeout(l,1e3));try{let l=await P.default.get("http://localhost:7331/health",{timeout:3e3});if(l.data?.status==="running"&&l.data?.pluginVersion===r)break}catch{}}return{success:!0,message:`Updated plugin to ${r}, gateway restarted`,newVersion:r}}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}function jn(e,t){let o=S.default.join(e,"dist"),s=S.default.join(t,"dist");m.default.existsSync(o)&&(m.default.mkdirSync(s,{recursive:!0}),$t(o,s));let n=S.default.join(e,"openclaw.plugin.json");m.default.existsSync(n)&&m.default.copyFileSync(n,S.default.join(t,"openclaw.plugin.json"));let r=S.default.join(e,"scripts"),a=S.default.join(t,"scripts");m.default.existsSync(r)&&(m.default.mkdirSync(a,{recursive:!0}),$t(r,a));for(let i of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let l=S.default.join(t,i);m.default.existsSync(l)&&(m.default.statSync(l).isDirectory()?m.default.rmSync(l,{recursive:!0,force:!0}):m.default.unlinkSync(l))}}function $t(e,t){for(let o of m.default.readdirSync(e,{withFileTypes:!0})){let s=S.default.join(e,o.name),n=S.default.join(t,o.name);o.isDirectory()?(m.default.mkdirSync(n,{recursive:!0}),$t(s,n)):m.default.copyFileSync(s,n)}}function Ln(){try{try{(0,x.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,x.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,x.execSync)("sleep 1",{stdio:"pipe"});let e=(0,x.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,x.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,x.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function Bn(){let e=S.default.join(be.default.homedir(),".badgerclaw","workspace");m.default.mkdirSync(e,{recursive:!0});let t=S.default.join(e,".git");return m.default.existsSync(t)||(0,x.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),m.default.writeFileSync(S.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
102
103
 
103
104
  When you receive a message, it will be formatted like:
104
105
  [Room: RoomName] Sender: message text
@@ -107,22 +108,22 @@ Reply using the reply tool with botId="..." and roomId="..."
107
108
  ALWAYS use the \`reply\` MCP tool to send your response back to the chat room.
108
109
  Use the exact botId and roomId provided in the message \u2014 do not modify them.
109
110
  Keep responses concise and helpful.
110
- `),e}var Te=S.default.join(fe.default.homedir(),".badgerclaw","claude-code.lock");function bn(){try{m.default.mkdirSync(S.default.dirname(Te),{recursive:!0});try{let e=m.default.statSync(Te);if(Date.now()-e.mtimeMs<6e4)return!1;m.default.unlinkSync(Te)}catch{}return m.default.writeFileSync(Te,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function Sn(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!bn())return{success:!0,message:"Claude Code start already in progress, skipping duplicate"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await he(e.bot_id),{launchClaudeCode:o,recordSession:s,getActiveSessions:n,stopSession:r}=(Ne(),yt(dt)),a=new Set;try{let v=(await D.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let I of v)if(I.botId!==t&&I.enabled!==!1){let A=I.port;typeof A=="number"&&A>=7332&&a.add(A)}}catch{}for(let y=7332;y<=7340;y++)try{(0,x.execSync)(`lsof -ti :${y} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(y)}catch{}let i=7332;for(;a.has(i);)i++;let l=n();for(let y of l)y.port===i&&(console.log(`[command-executor] Stopping existing session ${y.sessionId} on port ${i}`),r(y.sessionId));try{(0,x.execSync)(`lsof -ti :${i} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let f=e.session_id||`session-${Date.now()}`;await D.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:f,port:i},{timeout:1e4});let b=_n();return o({sessionId:f,port:i,projectDir:b}),s(f,0,0,i,b),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${f}, port: ${i})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function he(e){if(e.startsWith("@"))return e;try{let o=(await D.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],s=S.default.join(fe.default.homedir(),".badgerclaw","bot-mapping.json");if(m.default.existsSync(s)){let n=JSON.parse(m.default.readFileSync(s,"utf-8"));if(n[e])return n[e]}return o.length===1?o[0].botId:(console.warn(`[command-executor] Could not resolve bot UUID ${e} to Matrix ID, trying as-is`),e)}catch{return e}}async function $n(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await he(e.bot_id),o=e.session_id;if(!o)try{let s=await D.default.get("http://localhost:7331/claude-code/status",{timeout:5e3}),r=(s.data?.bots||s.data?.rooms||[]).find(a=>a.botId===t);r&&(o=r.sessionId)}catch{}if(await D.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:s}=(Ne(),yt(dt));s(o)}return{success:!0,message:"Claude Code stopped"}}catch(t){return{success:!1,message:`Failed to stop Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Cn(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;o.startsWith("@")||(o=await he(t));let s=e?.session_id||`cc-${Date.now()}`;return await D.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!0,sessionId:s,mode:"primary",tools:e?.tools},{timeout:1e4}),console.log(`[claude-control] Primary mode enabled for ${o} (session: ${s})`),{success:!0,message:`Claude Control (primary) started for ${o}`}}catch(t){return{success:!1,message:`Failed to start Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function vn(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;return o.startsWith("@")||(o=await he(t)),await D.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!1},{timeout:1e4}),console.log(`[claude-control] Primary mode disabled for ${o}`),{success:!0,message:`Claude Control stopped for ${o}`}}catch(t){return{success:!1,message:`Failed to stop Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function In(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t||!e?.tools)return{success:!1,message:"Missing bot_id or tools in payload"};let o=t;return o.startsWith("@")||(o=await he(t)),await D.default.post("http://localhost:7331/claude-code/tools",{botId:o,tools:e.tools},{timeout:1e4}),{success:!0,message:`Tools updated for ${o}`}}catch(t){return{success:!1,message:`Failed to update tools: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function xn(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await D.default.post("http://localhost:7331/bot-share/notify",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,ownerDisplayName:e.owner_display_name||void 0,botDisplayName:e.bot_name||void 0,expiresAt:e.expires_at||void 0},{timeout:1e4}),console.log(`[bot-share] Notify: ${e.shared_with_user_id} can now access ${e.bot_user_id}`),{success:!0,message:`Share notification sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to notify share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function An(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await D.default.post("http://localhost:7331/bot-share/revoked",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Revoked: ${e.shared_with_user_id} lost access to ${e.bot_user_id}`),{success:!0,message:`Share revocation sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to revoke share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function kn(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await D.default.post("http://localhost:7331/bot-share/expired",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Expired: ${e.shared_with_user_id} access to ${e.bot_user_id}`),{success:!0,message:`Share expiry sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to expire share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Rn(e){if(!e?.bot_id||!e?.room_id)return{success:!1,message:"Missing bot_id or room_id in payload"};try{return{success:!0,message:(await D.default.post("http://localhost:7331/leave-room",{botId:e.bot_id,roomId:e.room_id},{timeout:15e3})).data?.message||"Left room"}}catch(t){return{success:!1,message:`Failed to leave room: ${t.response?.data?.message||t.message||"Unknown error"}`}}}var ao=3e4,Pn=15e4,uo="/api/v1/dashboard/heartbeat",En="/api/v1/me/active-shares",je=new Map,Dn=3e4;function Be(e,t){if(e!=="start_claude_code"&&e!=="stop_claude_code")return!1;let o=`${e}:${t||"unknown"}`,s=Date.now();for(let[n,r]of je)s-r>Dn&&je.delete(n);return je.has(o)?!0:(je.set(o,s),!1)}function mo(e,t){let o=$e();return{instance_id:J(),timestamp:new Date().toISOString(),cli_version:t,plugin_version:e.pluginVersion||"unknown",hostname:o.hostname,os:o.os,arch:o.arch,uptime_seconds:o.uptimeSeconds,mem_free_mb:o.memFreeMb,gateway_status:e.status,gateway_pid:e.pid,last_gateway_restart:e.lastRestart,bots:e.bots.map(s=>({bot_id:s.botId,bot_username:s.botUsername,status:s.status,activity_state:s.activityState||"idle",active_task:s.activeTask||null,last_activity_at:s.lastActivity,messages_received:s.messagesReceived,messages_sent:s.messagesSent,chunked_messages:s.chunkedMessages,total_chunks_sent:s.totalChunksSent,errors:s.errors,last_error:s.lastError,last_error_at:s.lastErrorAt,uptime_seconds:s.uptimeSeconds,rooms_active:s.roomsActive,room_details:(s.roomDetails||[]).map(n=>({roomId:n.roomId,roomName:n.roomName,workspaceName:n.workspaceName||null,messagesInRoom:n.messagesInRoom,lastActivityInRoom:n.lastActivityInRoom})),claude_code_enabled:s.claudeCodeEnabled??!1,claude_code_session_id:s.claudeCodeSessionId??null}))}}async function O(){let{version:e}=z(),t=await ge(),o=mo(t,e);await R().post(uo,o)}function On(e,t){if(!e||e.status!==t.status)return!0;let o=new Map(e.bots.map(s=>[s.botId,s]));for(let s of t.bots){let n=o.get(s.botId);if(!n||n.status!==s.status||n.errors!==s.errors)return!0}return e.bots.length!==t.bots.length}async function io(){try{let o=(await R().get(En)).data?.shares||[],s={shares:o.map(n=>({botUserId:n.bot_user_id,sharedWithUserId:n.shared_with_user_id,expiresAt:n.expires_at||null,shareId:n.share_id}))};await lo.default.post("http://localhost:7331/bot-share/sync",s,{timeout:1e4}),console.log(d.default.dim(` [${_()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(d.default.dim(` [${_()}] Share sync failed (non-fatal): ${e.message}`))}}var po=new co.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=h();e||(console.log(d.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=z();console.log(d.default.green(`Heartbeat daemon started (v${t})`)),console.log(d.default.dim(` Instance: ${J()}`)),console.log(d.default.dim(` Interval: ${ao/1e3}s`)),console.log(d.default.dim(` Press Ctrl+C to stop.
111
- `));let o=null,s=10,n=0,r=async()=>{try{await go();let a=await ge(),i=mo(a,t);On(o,a)&&o!==null&&console.log(d.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let f=R(),b=await f.post(uo,i);n=0;let y=a.bots.length,v=a.bots.filter(k=>k.status==="running").length;console.log(d.default.dim(` [${new Date().toISOString()}] gateway=${a.status} bots=${v}/${y} running mem=${i.mem_free_mb}MB free`)),o=a;let I=b.data?.pending_commands||[],A=!1;for(let k of I)try{if(console.log(d.default.cyan(` [${new Date().toISOString()}] Received command: ${k.command_type} (${k.id})`)),await f.post(`/api/v1/dashboard/commands/${k.id}/ack`),Be(k.command_type,k.payload?.bot_id)){console.log(d.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${k.command_type}`));continue}let P=await M(k);console.log(P.success?d.default.green(` [${new Date().toISOString()}] ${P.message}`):d.default.red(` [${new Date().toISOString()}] ${P.message}`)),await f.post(`/api/v1/dashboard/commands/${k.id}/result`,{status:P.success?"success":"failed",result:P.message,new_version:P.newVersion||null}),k.command_type==="update_cli"&&P.success&&(A=!0)}catch(P){console.log(d.default.dim(` [${new Date().toISOString()}] Command ${k.id} error: ${P.message}`))}if(A){console.log(d.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await O()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(a){a instanceof Q&&(console.log(d.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),n+=1,console.log(d.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${n}/${s}): ${a.message}`)),n>=s&&(console.log(d.default.red(` [${new Date().toISOString()}] ${s} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await r(),await io(),setInterval(r,ao),setInterval(io,Pn),Tn(e.access_token,t),await new Promise(()=>{})});async function go(){let e=h();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),s=300*1e3;if(t-o<s)if(console.log(d.default.dim(` [${_()}] Token expires soon \u2014 refreshing proactively...`)),await We())console.log(d.default.green(` [${_()}] Token refreshed successfully`));else{let r=At()||"unknown reason";console.log(d.default.yellow(` [${_()}] Token refresh failed: ${r}`))}}var Nn=2700*1e3;function Tn(e,t){let o=3e3,s=3e4,n=null;async function r(){try{await go();let i=h()?.access_token||e,l=require("eventsource"),f=new l(`${N}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${i}`}});f.onopen=()=>{o=3e3,console.log(d.default.dim(` [${_()}] SSE connected \u2014 listening for real-time events`)),n&&clearTimeout(n),n=setTimeout(()=>{console.log(d.default.dim(` [${_()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),f.close(),r()},Nn)},f.onmessage=async b=>{try{let y=JSON.parse(b.data);await jn(y)}catch{}},f.onerror=async()=>{f.close(),n&&(clearTimeout(n),n=null),console.log(d.default.dim(` [${_()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}catch(a){console.log(d.default.dim(` [${_()}] SSE connection failed: ${a.message}`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}r()}function _(){return new Date().toISOString()}async function jn(e){if(e.type==="pair"){console.log(d.default.cyan(` [${_()}] Pair event: ${e.bot_name}`)),await le(e.pair_code,e.bot_name,e.bot_user_id,!0);try{let{execSync:t}=await import("child_process");t("openclaw gateway restart",{stdio:"ignore"}),console.log(d.default.green(` [${_()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await O()}catch{}}else if(e.type==="bot.delete"&&e.bot_user_id){let t=e.bot_user_id,o=t.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(d.default.yellow(` [${_()}] Bot deleted: ${t}`));try{let s=await import("fs"),n=await import("path"),r=await import("os"),a=n.join(r.homedir(),".openclaw","openclaw.json"),i=JSON.parse(s.readFileSync(a,"utf-8")),l=!1;if(i.channels?.badgerclaw?.accounts?.[o]&&(delete i.channels.badgerclaw.accounts[o],l=!0),i.agents?.list){let f=i.agents.list.length;i.agents.list=i.agents.list.filter(b=>b.id!==o),i.agents.list.length!==f&&(l=!0)}if(l){s.writeFileSync(a,JSON.stringify(i,null,2)),console.log(d.default.green(` [${_()}] Removed "${o}" from openclaw.json`));let{execSync:f}=await import("child_process");try{f("openclaw gateway restart",{stdio:"ignore"}),console.log(d.default.green(` [${_()}] Gateway restarted`))}catch{}}}catch(s){console.log(d.default.red(` [${_()}] Failed to clean up bot: ${s}`))}try{await O()}catch{}}else if(e.type==="gateway-restart"){console.log(d.default.cyan(` [${_()}] Remote gateway-restart received`));let t=await te();console.log(t.success?d.default.green(` [${_()}] Gateway restarted`):d.default.red(` [${_()}] Gateway restart failed: ${t.message}`));try{await O()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(d.default.cyan(` [${_()}] Claude Code START: bot=${e.bot_id}`)),Be("start_claude_code",e.bot_id)){console.log(d.default.dim(` [${_()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await M({id:e.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:e.bot_id,bot_user_id:e.bot_user_id,room_id:e.room_id,session_id:e.session_id}});e.command_id&&await R().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await O()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(d.default.cyan(` [${_()}] Claude Code STOP: bot=${e.bot_id}`)),Be("stop_claude_code",e.bot_id)){console.log(d.default.dim(` [${_()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await M({id:e.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:e.bot_id,bot_user_id:e.bot_user_id,room_id:e.room_id,session_id:e.session_id}});e.command_id&&await R().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await O()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(d.default.cyan(` [${_()}] Command: ${e.command_type} (${e.command_id})`)),Be(e.command_type,e.payload?.bot_id)){console.log(d.default.dim(` [${_()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=R();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await M({id:e.command_id,command_type:e.command_type,payload:e.payload});await t.post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:o.success?"success":"failed",result:o.message,new_version:o.newVersion||null}),e.command_type==="update_cli"&&o.success&&(console.log(d.default.cyan(` [${_()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await O()}catch{}}}var ho=new fo.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{let e=h();e||(console.log(p.default.yellow("Not logged in.")),process.exit(1)),await de(!1),console.log(p.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=new t(`${N}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${e.access_token}`}});o.onmessage=async s=>{try{let n=JSON.parse(s.data);if(n.type==="pair"){console.log(p.default.cyan(`
112
- \u{1F4F1} Pair event received: ${n.bot_name}`)),await le(n.pair_code,n.bot_name,n.bot_user_id,!1);try{let{execSync:r}=await import("child_process");r("openclaw gateway restart",{stdio:"ignore"}),console.log(p.default.green(" \u2705 Gateway restarted \u2014 bot is live!"))}catch{console.log(p.default.dim(" Gateway restart failed \u2014 run: openclaw gateway restart"))}}else if(n.type==="gateway-restart"){console.log(p.default.cyan(`
113
- \u{1F504} Remote gateway-restart command received`));let r=await te();r.success?console.log(p.default.green(` \u2705 Gateway restarted: ${r.message}`)):console.log(p.default.red(` \u274C Gateway restart failed: ${r.message}`));try{await O(),console.log(p.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(p.default.dim(" Could not push heartbeat."))}}else if(n.type==="bot.delete"&&n.bot_user_id){let r=n.bot_user_id,a=r.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(p.default.yellow(`
114
- \u{1F5D1}\uFE0F Bot deleted: ${r} \u2014 removing from OpenClaw config...`));try{let i=await import("fs"),l=await import("path"),f=await import("os"),b=l.join(f.homedir(),".openclaw","openclaw.json"),y=JSON.parse(i.readFileSync(b,"utf-8")),v=!1;if(y.channels?.badgerclaw?.accounts?.[a]&&(delete y.channels.badgerclaw.accounts[a],v=!0),y.agents?.list){let I=y.agents.list.length;y.agents.list=y.agents.list.filter(A=>A.id!==a),y.agents.list.length!==I&&(v=!0)}if(v){i.writeFileSync(b,JSON.stringify(y,null,2)),console.log(p.default.green(` \u2705 Removed "${a}" from openclaw.json`));let{execSync:I}=await import("child_process");try{I("openclaw gateway restart",{stdio:"ignore"}),console.log(p.default.green(" \u2705 Gateway restarted"))}catch{console.log(p.default.dim(" Gateway restart failed \u2014 restart manually"))}}else console.log(p.default.dim(` "${a}" not found in openclaw.json \u2014 nothing to remove`))}catch(i){console.log(p.default.red(` Failed to update openclaw.json: ${i}`))}}else if(n.type==="claude_code.start"&&n.bot_id&&n.room_id){console.log(p.default.cyan(`
115
- \u{1F916} Claude Code START received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await M({id:n.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:n.bot_id,room_id:n.room_id,session_id:n.session_id}});if(console.log(r.success?p.default.green(` \u2705 ${r.message}`):p.default.red(` \u274C ${r.message}`)),n.command_id)try{await R().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await O()}catch{}}catch(r){console.log(p.default.red(` Claude Code start error: ${r.message}`))}}else if(n.type==="claude_code.stop"&&n.bot_id&&n.room_id){console.log(p.default.cyan(`
116
- \u{1F916} Claude Code STOP received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await M({id:n.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:n.bot_id,room_id:n.room_id,session_id:n.session_id}});if(console.log(r.success?p.default.green(` \u2705 ${r.message}`):p.default.red(` \u274C ${r.message}`)),n.command_id)try{await R().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await O()}catch{}}catch(r){console.log(p.default.red(` Claude Code stop error: ${r.message}`))}}else if(n.type==="command.execute"&&n.command_id){console.log(p.default.cyan(`
117
- \u26A1 SSE command received: ${n.command_type} (${n.command_id})`));try{let r=R();await r.post(`/api/v1/dashboard/commands/${n.command_id}/ack`);let a=await M({id:n.command_id,command_type:n.command_type,payload:n.payload});console.log(a.success?p.default.green(` \u2705 ${a.message}`):p.default.red(` \u274C ${a.message}`)),await r.post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:a.success?"success":"failed",result:a.message,new_version:a.newVersion||null});try{await O()}catch{}n.command_type==="update_cli"&&a.success&&(console.log(p.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(r){console.log(p.default.red(` Command ${n.command_id} error: ${r.message}`))}}}catch{}},o.onerror=()=>{console.log(p.default.dim(" Reconnecting..."))},await new Promise(()=>{})});var So=require("commander"),u=c(require("chalk")),oe=require("child_process"),C=c(require("fs")),gt=c(require("os")),ft=c(require("path"));var yo=c(require("fs")),_o=c(require("os")),Le=c(require("path")),mt=require("child_process"),V=c(require("chalk"));var Bn=`${N}/api/v1/dashboard/versions/latest`,Ln=2500,Un=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),wo=Le.default.join(_o.default.homedir(),".openclaw/extensions/badgerclaw"),Fn=[Le.default.join(wo,"node_modules/@badgerclaw/connect/package.json"),Le.default.join(wo,"package.json")];function pt(){return"0.2.37"}function Mn(){for(let e of Fn)try{let t=yo.default.readFileSync(e,"utf-8"),o=JSON.parse(t);if(o.version&&(!o.name||o.name==="@badgerclaw/connect"||o.name==="badgerclaw")||o.version)return o.version}catch{}return null}function Gn(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function Ue(){if((0,mt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,mt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:Gn(t.stdout)||null}async function Vn(){let e=new AbortController,t=setTimeout(()=>e.abort(),Ln);try{let o=await fetch(Bn,{signal:e.signal});if(!o.ok)return null;let s=await o.json(),n=s.result&&typeof s.result=="object"?s.result:s;return{cli:n.cli??"unknown",plugin:n.plugin??"unknown",supported_openclaw:n.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function Wn(e){let t=[];if(e.cli&&e.cli!=="unknown"){let o=pt();o!==e.cli&&t.push({component:"cli",current:o,approved:e.cli})}if(e.plugin&&e.plugin!=="unknown"){let o=Mn();(o===null||o!==e.plugin)&&t.push({component:"plugin",current:o??"not installed",approved:e.plugin})}if(e.supported_openclaw&&e.supported_openclaw!=="unknown"){let o=Ue();(o===null||o!==e.supported_openclaw)&&t.push({component:"openclaw",current:o??"not installed",approved:e.supported_openclaw})}return t}function qn(e){return e[2]}function Hn(e){return!e||e.startsWith("-")?!0:Un.has(e)}function Jn(e){let t=[];t.push(""),t.push(V.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let s=o.component.padEnd(8);t.push(` ${s} ${V.default.yellow(o.current)} \u2192 ${V.default.green(o.approved)} ${V.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(V.default.green(" To fix, run:")),t.push(V.default.green.bold(" badgerclaw setup")),t.push(""),t.push(V.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
118
- `)}async function bo(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=qn(e);if(Hn(t))return;let o=await Vn();if(!o)return;let s=Wn(o);s.length!==0&&(process.stderr.write(Jn(s)),process.exit(1))}var T=ft.default.join(gt.default.homedir(),".openclaw","openclaw.json"),we=T+".badgerclaw-stash";async function zn(){try{let e=await fetch(`${N}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin:null,openclaw:null};let t=await e.json(),o=t.result&&typeof t.result=="object"?t.result:t,s=n=>typeof n!="string"||!n||n==="unknown"?null:n;return{cli:s(o.cli),plugin:s(o.plugin),openclaw:s(o.supported_openclaw)}}catch{return{cli:null,plugin:null,openclaw:null}}}function Yn(){if(!C.default.existsSync(T))return null;try{let e=JSON.parse(C.default.readFileSync(T,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,C.default.writeFileSync(T,JSON.stringify(e,null,2)),C.default.writeFileSync(we,JSON.stringify(t,null,2)),t):null}catch{return null}}function Kn(){if(!C.default.existsSync(T))return null;try{let e=JSON.parse(C.default.readFileSync(T,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function Xn(){let e=null;try{C.default.existsSync(T)&&(e=JSON.parse(C.default.readFileSync(T,"utf-8"))?.gateway?.mode??null)}catch{}if(!(typeof e=="string"&&e.length>0)){console.log(u.default.dim(" Setting gateway.mode=local (default for user-machine installs)..."));try{let{execSync:t}=require("child_process");t("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"})}catch(t){console.log(u.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${t.message}`)),console.log(u.default.yellow(" Run `openclaw config set gateway.mode local` manually before the next gateway restart."))}}}function Qn(e){if(e&&C.default.existsSync(T))try{let t=JSON.parse(C.default.readFileSync(T,"utf-8"));t.gateway={...e,...t.gateway||{}},C.default.writeFileSync(T,JSON.stringify(t,null,2))}catch(t){console.log(u.default.yellow(` \u26A0\uFE0F Could not restore gateway block: ${t.message}`)),console.log(u.default.yellow(" Run `openclaw config set gateway.mode local` manually if the gateway fails to start."))}}function Zn(){if(C.default.existsSync(we))try{let e=JSON.parse(C.default.readFileSync(we,"utf-8")),t=JSON.parse(C.default.readFileSync(T,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,C.default.writeFileSync(T,JSON.stringify(t,null,2)),C.default.unlinkSync(we)}catch(e){console.log(u.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(u.default.yellow(` Your bot credentials are backed up at: ${we}`))}}var $o=new So.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").action(async()=>{console.log(u.default.green(`
111
+ `),e}var He=S.default.join(be.default.homedir(),".badgerclaw","claude-code.lock");function Un(){try{m.default.mkdirSync(S.default.dirname(He),{recursive:!0});try{let e=m.default.statSync(He);if(Date.now()-e.mtimeMs<6e4)return!1;m.default.unlinkSync(He)}catch{}return m.default.writeFileSync(He,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function Fn(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!Un())return{success:!0,message:"Claude Code start already in progress, skipping duplicate"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await Se(e.bot_id),{launchClaudeCode:o,recordSession:s,getActiveSessions:n,stopSession:r}=(We(),Rt(St)),a=new Set;try{let v=(await P.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let I of v)if(I.botId!==t&&I.enabled!==!1){let k=I.port;typeof k=="number"&&k>=7332&&a.add(k)}}catch{}for(let y=7332;y<=7340;y++)try{(0,x.execSync)(`lsof -ti :${y} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(y)}catch{}let i=7332;for(;a.has(i);)i++;let l=n();for(let y of l)y.port===i&&(console.log(`[command-executor] Stopping existing session ${y.sessionId} on port ${i}`),r(y.sessionId));try{(0,x.execSync)(`lsof -ti :${i} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let f=e.session_id||`session-${Date.now()}`;await P.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:f,port:i},{timeout:1e4});let b=Bn();return o({sessionId:f,port:i,projectDir:b}),s(f,0,0,i,b),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${f}, port: ${i})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Se(e){if(e.startsWith("@"))return e;try{let o=(await P.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],s=S.default.join(be.default.homedir(),".badgerclaw","bot-mapping.json");if(m.default.existsSync(s)){let n=JSON.parse(m.default.readFileSync(s,"utf-8"));if(n[e])return n[e]}return o.length===1?o[0].botId:(console.warn(`[command-executor] Could not resolve bot UUID ${e} to Matrix ID, trying as-is`),e)}catch{return e}}async function Mn(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await Se(e.bot_id),o=e.session_id;if(!o)try{let s=await P.default.get("http://localhost:7331/claude-code/status",{timeout:5e3}),r=(s.data?.bots||s.data?.rooms||[]).find(a=>a.botId===t);r&&(o=r.sessionId)}catch{}if(await P.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:s}=(We(),Rt(St));s(o)}return{success:!0,message:"Claude Code stopped"}}catch(t){return{success:!1,message:`Failed to stop Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Gn(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;o.startsWith("@")||(o=await Se(t));let s=e?.session_id||`cc-${Date.now()}`;return await P.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!0,sessionId:s,mode:"primary",tools:e?.tools},{timeout:1e4}),console.log(`[claude-control] Primary mode enabled for ${o} (session: ${s})`),{success:!0,message:`Claude Control (primary) started for ${o}`}}catch(t){return{success:!1,message:`Failed to start Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Vn(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;return o.startsWith("@")||(o=await Se(t)),await P.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!1},{timeout:1e4}),console.log(`[claude-control] Primary mode disabled for ${o}`),{success:!0,message:`Claude Control stopped for ${o}`}}catch(t){return{success:!1,message:`Failed to stop Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Wn(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t||!e?.tools)return{success:!1,message:"Missing bot_id or tools in payload"};let o=t;return o.startsWith("@")||(o=await Se(t)),await P.default.post("http://localhost:7331/claude-code/tools",{botId:o,tools:e.tools},{timeout:1e4}),{success:!0,message:`Tools updated for ${o}`}}catch(t){return{success:!1,message:`Failed to update tools: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Hn(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await P.default.post("http://localhost:7331/bot-share/notify",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,ownerDisplayName:e.owner_display_name||void 0,botDisplayName:e.bot_name||void 0,expiresAt:e.expires_at||void 0},{timeout:1e4}),console.log(`[bot-share] Notify: ${e.shared_with_user_id} can now access ${e.bot_user_id}`),{success:!0,message:`Share notification sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to notify share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function qn(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await P.default.post("http://localhost:7331/bot-share/revoked",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Revoked: ${e.shared_with_user_id} lost access to ${e.bot_user_id}`),{success:!0,message:`Share revocation sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to revoke share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Jn(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await P.default.post("http://localhost:7331/bot-share/expired",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Expired: ${e.shared_with_user_id} access to ${e.bot_user_id}`),{success:!0,message:`Share expiry sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to expire share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function zn(e){if(!e?.bot_id||!e?.room_id)return{success:!1,message:"Missing bot_id or room_id in payload"};try{return{success:!0,message:(await P.default.post("http://localhost:7331/leave-room",{botId:e.bot_id,roomId:e.room_id},{timeout:15e3})).data?.message||"Left room"}}catch(t){return{success:!1,message:`Failed to leave room: ${t.response?.data?.message||t.message||"Unknown error"}`}}}var $o=3e4,Yn=15e4,xo="/api/v1/dashboard/heartbeat",Kn="/api/v1/me/active-shares",qe=new Map,Xn=3e4;function Je(e,t){if(e!=="start_claude_code"&&e!=="stop_claude_code")return!1;let o=`${e}:${t||"unknown"}`,s=Date.now();for(let[n,r]of qe)s-r>Xn&&qe.delete(n);return qe.has(o)?!0:(qe.set(o,s),!1)}function ko(e,t){let o=Re();return{instance_id:z(),timestamp:new Date().toISOString(),cli_version:t,plugin_version:e.pluginVersion||"unknown",hostname:o.hostname,os:o.os,arch:o.arch,uptime_seconds:o.uptimeSeconds,mem_free_mb:o.memFreeMb,gateway_status:e.status,gateway_pid:e.pid,last_gateway_restart:e.lastRestart,bots:e.bots.map(s=>({bot_id:s.botId,bot_username:s.botUsername,status:s.status,activity_state:s.activityState||"idle",active_task:s.activeTask||null,last_activity_at:s.lastActivity,messages_received:s.messagesReceived,messages_sent:s.messagesSent,chunked_messages:s.chunkedMessages,total_chunks_sent:s.totalChunksSent,errors:s.errors,last_error:s.lastError,last_error_at:s.lastErrorAt,uptime_seconds:s.uptimeSeconds,rooms_active:s.roomsActive,room_details:(s.roomDetails||[]).map(n=>({roomId:n.roomId,roomName:n.roomName,workspaceName:n.workspaceName||null,messagesInRoom:n.messagesInRoom,lastActivityInRoom:n.lastActivityInRoom})),claude_code_enabled:s.claudeCodeEnabled??!1,claude_code_session_id:s.claudeCodeSessionId??null}))}}async function E(){let{version:e}=K(),t=await _e(),o=ko(t,e);await A().post(xo,o)}function Qn(e,t){if(!e||e.status!==t.status)return!0;let o=new Map(e.bots.map(s=>[s.botId,s]));for(let s of t.bots){let n=o.get(s.botId);if(!n||n.status!==s.status||n.errors!==s.errors)return!0}return e.bots.length!==t.bots.length}async function Co(){try{let o=(await A().get(Kn)).data?.shares||[],s={shares:o.map(n=>({botUserId:n.bot_user_id,sharedWithUserId:n.shared_with_user_id,expiresAt:n.expires_at||null,shareId:n.share_id}))};await Io.default.post("http://localhost:7331/bot-share/sync",s,{timeout:1e4}),console.log(d.default.dim(` [${_()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(d.default.dim(` [${_()}] Share sync failed (non-fatal): ${e.message}`))}}var Ao=new vo.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=h();e||(console.log(d.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=K();console.log(d.default.green(`Heartbeat daemon started (v${t})`)),console.log(d.default.dim(` Instance: ${z()}`)),console.log(d.default.dim(` Interval: ${$o/1e3}s`)),console.log(d.default.dim(` Press Ctrl+C to stop.
112
+ `));let o=null,s=10,n=0,r=async()=>{try{await Ro();let a=await _e(),i=ko(a,t);Qn(o,a)&&o!==null&&console.log(d.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let f=A(),b=await f.post(xo,i);n=0;let y=a.bots.length,v=a.bots.filter(O=>O.status==="running").length;console.log(d.default.dim(` [${new Date().toISOString()}] gateway=${a.status} bots=${v}/${y} running mem=${i.mem_free_mb}MB free`)),o=a;let I=b.data?.pending_commands||[],k=!1;for(let O of I)try{if(console.log(d.default.cyan(` [${new Date().toISOString()}] Received command: ${O.command_type} (${O.id})`)),await f.post(`/api/v1/dashboard/commands/${O.id}/ack`),Je(O.command_type,O.payload?.bot_id)){console.log(d.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${O.command_type}`));continue}let N=await V(O);console.log(N.success?d.default.green(` [${new Date().toISOString()}] ${N.message}`):d.default.red(` [${new Date().toISOString()}] ${N.message}`)),await f.post(`/api/v1/dashboard/commands/${O.id}/result`,{status:N.success?"success":"failed",result:N.message,new_version:N.newVersion||null}),O.command_type==="update_cli"&&N.success&&(k=!0)}catch(N){console.log(d.default.dim(` [${new Date().toISOString()}] Command ${O.id} error: ${N.message}`))}if(k){console.log(d.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await E()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(a){a instanceof te&&(console.log(d.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),n+=1,console.log(d.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${n}/${s}): ${a.message}`)),n>=s&&(console.log(d.default.red(` [${new Date().toISOString()}] ${s} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await r(),await Co(),setInterval(r,$o),setInterval(Co,Yn),es(e.access_token,t),await new Promise(()=>{})});async function Ro(){let e=h();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),s=300*1e3;if(t-o<s)if(console.log(d.default.dim(` [${_()}] Token expires soon \u2014 refreshing proactively...`)),await tt())console.log(d.default.green(` [${_()}] Token refreshed successfully`));else{let r=Bt()||"unknown reason";console.log(d.default.yellow(` [${_()}] Token refresh failed: ${r}`))}}var Zn=2700*1e3;function es(e,t){let o=3e3,s=3e4,n=null;async function r(){try{await Ro();let i=h()?.access_token||e,l=require("eventsource"),f=new l(`${D}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${i}`}});f.onopen=()=>{o=3e3,console.log(d.default.dim(` [${_()}] SSE connected \u2014 listening for real-time events`)),n&&clearTimeout(n),n=setTimeout(()=>{console.log(d.default.dim(` [${_()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),f.close(),r()},Zn)},f.onmessage=async b=>{try{let y=JSON.parse(b.data);await ts(y)}catch{}},f.onerror=async()=>{f.close(),n&&(clearTimeout(n),n=null),console.log(d.default.dim(` [${_()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}catch(a){console.log(d.default.dim(` [${_()}] SSE connection failed: ${a.message}`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}r()}function _(){return new Date().toISOString()}async function ts(e){if(e.type==="pair"){console.log(d.default.cyan(` [${_()}] Pair event: ${e.bot_name}`)),await ue(e.pair_code,e.bot_name,e.bot_user_id,!0);try{let{execSync:t}=await import("child_process");t("openclaw gateway restart",{stdio:"ignore"}),console.log(d.default.green(` [${_()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await E()}catch{}}else if(e.type==="bot.delete"&&e.bot_user_id){let t=e.bot_user_id,o=t.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(d.default.yellow(` [${_()}] Bot deleted: ${t}`));try{let s=await import("fs"),n=await import("path"),r=await import("os"),a=n.join(r.homedir(),".openclaw","openclaw.json"),i=JSON.parse(s.readFileSync(a,"utf-8")),l=!1;if(i.channels?.badgerclaw?.accounts?.[o]&&(delete i.channels.badgerclaw.accounts[o],l=!0),i.agents?.list){let f=i.agents.list.length;i.agents.list=i.agents.list.filter(b=>b.id!==o),i.agents.list.length!==f&&(l=!0)}if(l){s.writeFileSync(a,JSON.stringify(i,null,2)),console.log(d.default.green(` [${_()}] Removed "${o}" from openclaw.json`));let{execSync:f}=await import("child_process");try{f("openclaw gateway restart",{stdio:"ignore"}),console.log(d.default.green(` [${_()}] Gateway restarted`))}catch{}}}catch(s){console.log(d.default.red(` [${_()}] Failed to clean up bot: ${s}`))}try{await E()}catch{}}else if(e.type==="gateway-restart"){console.log(d.default.cyan(` [${_()}] Remote gateway-restart received`));let t=await re();console.log(t.success?d.default.green(` [${_()}] Gateway restarted`):d.default.red(` [${_()}] Gateway restart failed: ${t.message}`));try{await E()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(d.default.cyan(` [${_()}] Claude Code START: bot=${e.bot_id}`)),Je("start_claude_code",e.bot_id)){console.log(d.default.dim(` [${_()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await V({id:e.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:e.bot_id,bot_user_id:e.bot_user_id,room_id:e.room_id,session_id:e.session_id}});e.command_id&&await A().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await E()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(d.default.cyan(` [${_()}] Claude Code STOP: bot=${e.bot_id}`)),Je("stop_claude_code",e.bot_id)){console.log(d.default.dim(` [${_()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await V({id:e.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:e.bot_id,bot_user_id:e.bot_user_id,room_id:e.room_id,session_id:e.session_id}});e.command_id&&await A().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await E()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(d.default.cyan(` [${_()}] Command: ${e.command_type} (${e.command_id})`)),Je(e.command_type,e.payload?.bot_id)){console.log(d.default.dim(` [${_()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=A();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await V({id:e.command_id,command_type:e.command_type,payload:e.payload});await t.post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:o.success?"success":"failed",result:o.message,new_version:o.newVersion||null}),e.command_type==="update_cli"&&o.success&&(console.log(d.default.cyan(` [${_()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await E()}catch{}}}var Eo=new Po.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{let e=h();e||(console.log(g.default.yellow("Not logged in.")),process.exit(1)),await me(!1),console.log(g.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=new t(`${D}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${e.access_token}`}});o.onmessage=async s=>{try{let n=JSON.parse(s.data);if(n.type==="pair"){console.log(g.default.cyan(`
113
+ \u{1F4F1} Pair event received: ${n.bot_name}`)),await ue(n.pair_code,n.bot_name,n.bot_user_id,!1);try{let{execSync:r}=await import("child_process");r("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(" \u2705 Gateway restarted \u2014 bot is live!"))}catch{console.log(g.default.dim(" Gateway restart failed \u2014 run: openclaw gateway restart"))}}else if(n.type==="gateway-restart"){console.log(g.default.cyan(`
114
+ \u{1F504} Remote gateway-restart command received`));let r=await re();r.success?console.log(g.default.green(` \u2705 Gateway restarted: ${r.message}`)):console.log(g.default.red(` \u274C Gateway restart failed: ${r.message}`));try{await E(),console.log(g.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(g.default.dim(" Could not push heartbeat."))}}else if(n.type==="bot.delete"&&n.bot_user_id){let r=n.bot_user_id,a=r.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(g.default.yellow(`
115
+ \u{1F5D1}\uFE0F Bot deleted: ${r} \u2014 removing from OpenClaw config...`));try{let i=await import("fs"),l=await import("path"),f=await import("os"),b=l.join(f.homedir(),".openclaw","openclaw.json"),y=JSON.parse(i.readFileSync(b,"utf-8")),v=!1;if(y.channels?.badgerclaw?.accounts?.[a]&&(delete y.channels.badgerclaw.accounts[a],v=!0),y.agents?.list){let I=y.agents.list.length;y.agents.list=y.agents.list.filter(k=>k.id!==a),y.agents.list.length!==I&&(v=!0)}if(v){i.writeFileSync(b,JSON.stringify(y,null,2)),console.log(g.default.green(` \u2705 Removed "${a}" from openclaw.json`));let{execSync:I}=await import("child_process");try{I("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(" \u2705 Gateway restarted"))}catch{console.log(g.default.dim(" Gateway restart failed \u2014 restart manually"))}}else console.log(g.default.dim(` "${a}" not found in openclaw.json \u2014 nothing to remove`))}catch(i){console.log(g.default.red(` Failed to update openclaw.json: ${i}`))}}else if(n.type==="claude_code.start"&&n.bot_id&&n.room_id){console.log(g.default.cyan(`
116
+ \u{1F916} Claude Code START received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await V({id:n.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:n.bot_id,room_id:n.room_id,session_id:n.session_id}});if(console.log(r.success?g.default.green(` \u2705 ${r.message}`):g.default.red(` \u274C ${r.message}`)),n.command_id)try{await A().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await E()}catch{}}catch(r){console.log(g.default.red(` Claude Code start error: ${r.message}`))}}else if(n.type==="claude_code.stop"&&n.bot_id&&n.room_id){console.log(g.default.cyan(`
117
+ \u{1F916} Claude Code STOP received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await V({id:n.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:n.bot_id,room_id:n.room_id,session_id:n.session_id}});if(console.log(r.success?g.default.green(` \u2705 ${r.message}`):g.default.red(` \u274C ${r.message}`)),n.command_id)try{await A().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await E()}catch{}}catch(r){console.log(g.default.red(` Claude Code stop error: ${r.message}`))}}else if(n.type==="command.execute"&&n.command_id){console.log(g.default.cyan(`
118
+ \u26A1 SSE command received: ${n.command_type} (${n.command_id})`));try{let r=A();await r.post(`/api/v1/dashboard/commands/${n.command_id}/ack`);let a=await V({id:n.command_id,command_type:n.command_type,payload:n.payload});console.log(a.success?g.default.green(` \u2705 ${a.message}`):g.default.red(` \u274C ${a.message}`)),await r.post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:a.success?"success":"failed",result:a.message,new_version:a.newVersion||null});try{await E()}catch{}n.command_type==="update_cli"&&a.success&&(console.log(g.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(r){console.log(g.default.red(` Command ${n.command_id} error: ${r.message}`))}}}catch{}},o.onerror=()=>{console.log(g.default.dim(" Reconnecting..."))},await new Promise(()=>{})});var jo=require("commander"),u=c(require("chalk")),$e=require("child_process"),C=c(require("fs")),It=c(require("os")),xt=c(require("path"));var Do=c(require("fs")),No=c(require("os")),ze=c(require("path")),Ct=require("child_process"),H=c(require("chalk"));var os=`${D}/api/v1/dashboard/versions/latest`,ns=2500,ss=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),Oo=ze.default.join(No.default.homedir(),".openclaw/extensions/badgerclaw"),rs=[ze.default.join(Oo,"node_modules/@badgerclaw/connect/package.json"),ze.default.join(Oo,"package.json")];function vt(){return"0.2.39"}function as(){for(let e of rs)try{let t=Do.default.readFileSync(e,"utf-8"),o=JSON.parse(t);if(o.version&&(!o.name||o.name==="@badgerclaw/connect"||o.name==="badgerclaw")||o.version)return o.version}catch{}return null}function is(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function Ye(){if((0,Ct.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Ct.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:is(t.stdout)||null}async function cs(){let e=new AbortController,t=setTimeout(()=>e.abort(),ns);try{let o=await fetch(os,{signal:e.signal});if(!o.ok)return null;let s=await o.json(),n=s.result&&typeof s.result=="object"?s.result:s;return{cli:n.cli??"unknown",plugin:n.plugin??"unknown",supported_openclaw:n.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function ls(e){let t=[];if(e.cli&&e.cli!=="unknown"){let o=vt();o!==e.cli&&t.push({component:"cli",current:o,approved:e.cli})}if(e.plugin&&e.plugin!=="unknown"){let o=as();(o===null||o!==e.plugin)&&t.push({component:"plugin",current:o??"not installed",approved:e.plugin})}if(e.supported_openclaw&&e.supported_openclaw!=="unknown"){let o=Ye();(o===null||o!==e.supported_openclaw)&&t.push({component:"openclaw",current:o??"not installed",approved:e.supported_openclaw})}return t}function ds(e){return e[2]}function us(e){return!e||e.startsWith("-")?!0:ss.has(e)}function ms(e){let t=[];t.push(""),t.push(H.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let s=o.component.padEnd(8);t.push(` ${s} ${H.default.yellow(o.current)} \u2192 ${H.default.green(o.approved)} ${H.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(H.default.green(" To fix, run:")),t.push(H.default.green.bold(" badgerclaw setup")),t.push(""),t.push(H.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
119
+ `)}async function To(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=ds(e);if(us(t))return;let o=await cs();if(!o)return;let s=ls(o);s.length!==0&&(process.stderr.write(ms(s)),process.exit(1))}var L=xt.default.join(It.default.homedir(),".openclaw","openclaw.json"),Ce=L+".badgerclaw-stash";async function gs(){try{let e=await fetch(`${D}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin:null,openclaw:null};let t=await e.json(),o=t.result&&typeof t.result=="object"?t.result:t,s=n=>typeof n!="string"||!n||n==="unknown"?null:n;return{cli:s(o.cli),plugin:s(o.plugin),openclaw:s(o.supported_openclaw)}}catch{return{cli:null,plugin:null,openclaw:null}}}function ps(){if(!C.default.existsSync(L))return null;try{let e=JSON.parse(C.default.readFileSync(L,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,C.default.writeFileSync(L,JSON.stringify(e,null,2)),C.default.writeFileSync(Ce,JSON.stringify(t,null,2)),t):null}catch{return null}}function fs(){if(!C.default.existsSync(L))return null;try{let e=JSON.parse(C.default.readFileSync(L,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function hs(e){if(e&&C.default.existsSync(L))try{let t=JSON.parse(C.default.readFileSync(L,"utf-8"));t.gateway={...e,...t.gateway||{}},C.default.writeFileSync(L,JSON.stringify(t,null,2))}catch(t){console.log(u.default.yellow(` \u26A0\uFE0F Could not restore gateway block: ${t.message}`)),console.log(u.default.yellow(" Run `openclaw config set gateway.mode local` manually if the gateway fails to start."))}}function ws(){if(C.default.existsSync(Ce))try{let e=JSON.parse(C.default.readFileSync(Ce,"utf-8")),t=JSON.parse(C.default.readFileSync(L,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,C.default.writeFileSync(L,JSON.stringify(t,null,2)),C.default.unlinkSync(Ce)}catch(e){console.log(u.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(u.default.yellow(` Your bot credentials are backed up at: ${Ce}`))}}var Lo=new jo.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").action(async()=>{console.log(u.default.green(`
119
120
  \u{1F9A1} BadgerClaw Setup
120
- `));let e=await zn();if(e.cli){let i=pt();i!==e.cli?(console.log(u.default.dim(` Updating CLI: ${i} \u2192 ${e.cli} (supported)...`)),(0,oe.spawnSync)("npm",["install","-g",`badgerclaw@${e.cli}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(u.default.green(` \u2705 CLI updated to ${e.cli}`))):console.log(u.default.dim(` CLI already at approved version ${i}.`))}if(e.openclaw){let i=Ue();i!==e.openclaw?(console.log(i===null?u.default.dim(` Installing OpenClaw ${e.openclaw} (supported)...`):u.default.dim(` Updating OpenClaw: ${i} \u2192 ${e.openclaw} (supported)...`)),(0,oe.spawnSync)("npm",["install","-g",`openclaw@${e.openclaw}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red("\n\u274C OpenClaw install/update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(u.default.green(` \u2705 OpenClaw at ${e.openclaw}`))):console.log(u.default.dim(` OpenClaw already at approved version ${i}.`))}else Ue()===null&&(console.log(u.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,oe.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
121
- \u274C OpenClaw install failed.`)),process.exit(1)));let t=Yn();t&&console.log(u.default.dim(" Existing bot config stashed temporarily..."));let o=Kn(),s=ft.default.join(gt.default.homedir(),".openclaw","extensions","badgerclaw");if(C.default.existsSync(s))try{C.default.rmSync(s,{recursive:!0,force:!0}),console.log(u.default.dim(" Cleared existing plugin directory."))}catch(i){console.log(u.default.yellow(` \u26A0\uFE0F Could not clear plugin directory (${i.message}); install may fail.`))}let n=e.plugin?`@badgerclaw/connect@${e.plugin}`:"@badgerclaw/connect";e.plugin?console.log(u.default.dim(` Installing ${n} (supported)...`)):console.log(u.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let r=(0,oe.spawnSync)("openclaw",["plugins","install",n,"--dangerously-force-unsafe-install"],{stdio:"inherit",shell:!0});t&&(Zn(),console.log(u.default.dim(" Bot config restored."))),o&&(Qn(o),console.log(u.default.dim(" Gateway config restored."))),Xn(),r.status!==0&&(console.log(u.default.red(`
121
+ `));let e=await gs();if(e.cli){let i=vt();i!==e.cli?(console.log(u.default.dim(` Updating CLI: ${i} \u2192 ${e.cli} (supported)...`)),(0,$e.spawnSync)("npm",["install","-g",`badgerclaw@${e.cli}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(u.default.green(` \u2705 CLI updated to ${e.cli}`))):console.log(u.default.dim(` CLI already at approved version ${i}.`))}if(e.openclaw){let i=Ye();i!==e.openclaw?(console.log(i===null?u.default.dim(` Installing OpenClaw ${e.openclaw} (supported)...`):u.default.dim(` Updating OpenClaw: ${i} \u2192 ${e.openclaw} (supported)...`)),(0,$e.spawnSync)("npm",["install","-g",`openclaw@${e.openclaw}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red("\n\u274C OpenClaw install/update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(u.default.green(` \u2705 OpenClaw at ${e.openclaw}`))):console.log(u.default.dim(` OpenClaw already at approved version ${i}.`))}else Ye()===null&&(console.log(u.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,$e.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
122
+ \u274C OpenClaw install failed.`)),process.exit(1)));let t=ps();t&&console.log(u.default.dim(" Existing bot config stashed temporarily..."));let o=fs(),s=xt.default.join(It.default.homedir(),".openclaw","extensions","badgerclaw");if(C.default.existsSync(s))try{C.default.rmSync(s,{recursive:!0,force:!0}),console.log(u.default.dim(" Cleared existing plugin directory."))}catch(i){console.log(u.default.yellow(` \u26A0\uFE0F Could not clear plugin directory (${i.message}); install may fail.`))}let n=e.plugin?`@badgerclaw/connect@${e.plugin}`:"@badgerclaw/connect";e.plugin?console.log(u.default.dim(` Installing ${n} (supported)...`)):console.log(u.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let r=(0,$e.spawnSync)("openclaw",["plugins","install",n,"--dangerously-force-unsafe-install"],{stdio:"inherit",shell:!0});t&&(ws(),console.log(u.default.dim(" Bot config restored."))),o&&(hs(o),console.log(u.default.dim(" Gateway config restored."))),r.status!==0&&(console.log(u.default.red(`
122
123
  \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(u.default.green(`
123
- \u2705 BadgerClaw plugin installed successfully!`)),console.log(u.default.dim(`
124
- Restarting OpenClaw gateway to load plugin...`)),(0,oe.spawnSync)("openclaw",["gateway","restart"],{stdio:"inherit",shell:!0}).status===0?console.log(u.default.green(" Gateway restarted.")):console.log(u.default.yellow(" Gateway restart failed or not running \u2014 start it manually: openclaw gateway start")),console.log(u.default.dim("\nNext: run `badgerclaw login` to authenticate."))});var vo=require("commander"),$=c(require("chalk"));var Io=new vo.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{h()||(console.log($.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=z(),o=$e(),s=await ge();console.log($.default.bold.green(`
124
+ \u2705 BadgerClaw plugin installed successfully!`)),console.log(""),je({verbose:!0}).ok||(console.log(u.default.red(`
125
+ \u274C Gateway failed to start. Diagnose with:`)),console.log(u.default.dim(" systemctl --user status openclaw-gateway.service # Linux")),console.log(u.default.dim(" launchctl list | grep openclaw # macOS")),console.log(u.default.dim(" openclaw config get gateway.mode")),console.log(u.default.dim(" Then re-run `badgerclaw setup` after fixing the underlying issue.")),process.exit(1)),console.log(u.default.green(" \u2705 Gateway is running.")),console.log(u.default.dim("\nNext: run `badgerclaw login` to authenticate.")),Le()});var Uo=require("commander"),$=c(require("chalk"));var Fo=new Uo.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{h()||(console.log($.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=K(),o=Re(),s=await _e();console.log($.default.bold.green(`
125
126
  BadgerClaw Dashboard
126
- `)),console.log($.default.bold(" Instance")),console.log(` ID: ${J()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${s.pluginVersion}`),console.log(),console.log($.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${Co(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let n=s.status==="running"?$.default.green:s.status==="error"?$.default.red:$.default.yellow;if(console.log($.default.bold(" Gateway")),console.log(` Status: ${n(s.status)}`),console.log(` PID: ${s.pid??"N/A"}`),console.log(` Last Restart: ${s.lastRestart??"N/A"}`),console.log(),s.bots.length===0)console.log($.default.bold(" Bots")),console.log($.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log($.default.bold(` Bots (${s.bots.length})`)),console.log();for(let r of s.bots){let a=r.status==="running"?$.default.green:r.status==="error"?$.default.red:$.default.yellow;if(console.log(` ${$.default.bold(r.botUsername)} ${a(`[${r.status}]`)}`),console.log(` ID: ${r.botId}`),console.log(` Uptime: ${Co(r.uptimeSeconds)}`),console.log(` Messages: ${r.messagesReceived} in / ${r.messagesSent} out`),r.chunkedMessages>0&&console.log(` Chunked: ${r.chunkedMessages} messages, ${r.totalChunksSent} chunks`),console.log(` Rooms: ${r.roomsActive} active`),console.log(` Errors: ${r.errors}`),r.lastError&&(console.log(` Last Error: ${$.default.red(r.lastError)}`),console.log(` Error At: ${r.lastErrorAt}`)),console.log(` Last Active: ${r.lastActivity??"N/A"}`),r.roomDetails&&r.roomDetails.length>0){console.log($.default.dim(" Rooms:"));for(let i of r.roomDetails)console.log($.default.dim(` ${i.roomName} \u2014 ${i.messagesInRoom} msgs, last: ${i.lastActivityInRoom??"N/A"}`))}console.log()}}console.log($.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function Co(e){if(e<60)return`${e}s`;if(e<3600)return`${Math.floor(e/60)}m ${e%60}s`;let t=Math.floor(e/3600),o=Math.floor(e%3600/60);return t<24?`${t}h ${o}m`:`${Math.floor(t/24)}d ${t%24}h ${o}m`}var ht=require("commander"),ne=c(require("chalk")),xo=c(require("ora"));var es=new ht.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{h()||(console.log(ne.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,xo.default)("Restarting gateway...").start(),o=await te();if(o.success){t.succeed(ne.default.green(`Gateway restarted: ${o.message}`));try{await O(),console.log(ne.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(ne.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(ne.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),Ao=new ht.Command("gateway").description("Manage the OpenClaw gateway").addCommand(es);var q=require("commander"),g=c(require("chalk")),X=c(require("ora")),W=c(require("axios"));Ne();var K="http://localhost:7331",ts=new q.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{h()||(console.log(g.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,s=parseInt(e.port,10),n=e.project.replace(/^~/,process.env.HOME||""),r=(0,X.default)("Starting Claude Code session...").start();try{await W.default.post(`${K}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),r.text="Gateway toggled \u2014 launching MCP server...";let i=rt({sessionId:o,port:s,projectDir:n}).pid||0;await new Promise(l=>setTimeout(l,1500)),r.text="MCP server running \u2014 launching Claude Code...",at({sessionId:o,port:s,projectDir:n}),it(o,0,i,s,n),r.succeed(g.default.green("Claude Code session started")+g.default.dim(` (session: ${o}, port: ${s})`)),console.log(g.default.dim(` Bot: ${e.bot}`)),console.log(g.default.dim(` Room: ${e.room}`)),console.log(g.default.dim(` Project: ${n}`)),console.log(g.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let i=a.response?.data?.message||a.message||"Unknown error";r.fail(g.default.red(`Failed to start Claude Code: ${i}`)),process.exit(1)}}),os=new q.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{h()||(console.log(g.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,X.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await W.default.post(`${K}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let s=e.sessionId;if(!s)try{let a=((await W.default.get(`${K}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(i=>i.botId===e.bot&&i.roomId===e.room);a&&(s=a.sessionId)}catch{}s?(ct(s),o.succeed(g.default.green(`Claude Code session stopped (${s})`))):(o.succeed(g.default.green("Claude Code toggled off at gateway")),console.log(g.default.dim(" No local session found to kill \u2014 may need to close Claude Code manually.")))}catch(s){let n=s.response?.data?.message||s.message||"Unknown error";o.fail(g.default.red(`Failed to stop Claude Code: ${n}`)),process.exit(1)}}),ns=new q.Command("status").description("Show active Claude Code sessions").action(async()=>{h()||(console.log(g.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,X.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await W.default.get(`${K}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let s=lt();if(t.stop(),o.length===0&&s.length===0){console.log(g.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(g.default.bold(`
127
- Gateway Claude Code Rooms:`)),console.log(g.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(g.default.dim(" "+"-".repeat(88)));for(let n of o){let r=n.enabled?g.default.green("ON"):g.default.dim("OFF");console.log(` ${(n.botId||"").padEnd(30)}${(n.roomName||n.roomId||"").padEnd(30)}${(n.sessionId||"-").padEnd(20)}${r}`)}}if(s.length>0){console.log(g.default.bold(`
128
- Local Sessions:`)),console.log(g.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(g.default.dim(" "+"-".repeat(90)));for(let n of s)console.log(` ${n.sessionId.padEnd(25)}${String(n.port).padEnd(8)}${String(n.mcpPid).padEnd(10)}${n.projectDir.padEnd(40)}${n.startedAt}`)}console.log("")}catch(o){t.fail(g.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),ss=new q.Command("group").description("Group bots/rooms into a shared Claude Code session").requiredOption("--session <id>","Session ID to group under").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").action(async e=>{let t=(0,X.default)("Grouping bot+room into session...").start();try{await W.default.post(`${K}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(g.default.green(`Grouped ${e.bot} + ${e.room} into session "${e.session}"`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(g.default.red(`Failed to group: ${s}`)),process.exit(1)}}),rs=new q.Command("allow").description("Add a user to the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to allow (e.g. @alice:server)").action(async e=>{let t=(0,X.default)("Adding user to allowlist...").start();try{await W.default.post(`${K}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(g.default.green(`Added ${e.user} to allowlist for ${e.bot} in ${e.room}`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(g.default.red(`Failed to add user: ${s}`)),process.exit(1)}}),as=new q.Command("revoke").description("Remove a user from the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to revoke").action(async e=>{let t=(0,X.default)("Removing user from allowlist...").start();try{await W.default.post(`${K}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(g.default.green(`Removed ${e.user} from allowlist for ${e.bot} in ${e.room}`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(g.default.red(`Failed to revoke user: ${s}`)),process.exit(1)}}),ko=new q.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(ts).addCommand(os).addCommand(ns).addCommand(ss).addCommand(rs).addCommand(as);async function is(){await bo(process.argv);let e=new Ro.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.37"),e.addCommand(Jt),e.addCommand(Yt),e.addCommand(Xt),e.addCommand(oo),e.addCommand(jt),e.addCommand(ho),e.addCommand($o),e.addCommand(po),e.addCommand(Io),e.addCommand(Ao),e.addCommand(ko),e.parse(process.argv)}is().catch(e=>{console.error(e),process.exit(1)});
127
+ `)),console.log($.default.bold(" Instance")),console.log(` ID: ${z()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${s.pluginVersion}`),console.log(),console.log($.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${Bo(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let n=s.status==="running"?$.default.green:s.status==="error"?$.default.red:$.default.yellow;if(console.log($.default.bold(" Gateway")),console.log(` Status: ${n(s.status)}`),console.log(` PID: ${s.pid??"N/A"}`),console.log(` Last Restart: ${s.lastRestart??"N/A"}`),console.log(),s.bots.length===0)console.log($.default.bold(" Bots")),console.log($.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log($.default.bold(` Bots (${s.bots.length})`)),console.log();for(let r of s.bots){let a=r.status==="running"?$.default.green:r.status==="error"?$.default.red:$.default.yellow;if(console.log(` ${$.default.bold(r.botUsername)} ${a(`[${r.status}]`)}`),console.log(` ID: ${r.botId}`),console.log(` Uptime: ${Bo(r.uptimeSeconds)}`),console.log(` Messages: ${r.messagesReceived} in / ${r.messagesSent} out`),r.chunkedMessages>0&&console.log(` Chunked: ${r.chunkedMessages} messages, ${r.totalChunksSent} chunks`),console.log(` Rooms: ${r.roomsActive} active`),console.log(` Errors: ${r.errors}`),r.lastError&&(console.log(` Last Error: ${$.default.red(r.lastError)}`),console.log(` Error At: ${r.lastErrorAt}`)),console.log(` Last Active: ${r.lastActivity??"N/A"}`),r.roomDetails&&r.roomDetails.length>0){console.log($.default.dim(" Rooms:"));for(let i of r.roomDetails)console.log($.default.dim(` ${i.roomName} \u2014 ${i.messagesInRoom} msgs, last: ${i.lastActivityInRoom??"N/A"}`))}console.log()}}console.log($.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function Bo(e){if(e<60)return`${e}s`;if(e<3600)return`${Math.floor(e/60)}m ${e%60}s`;let t=Math.floor(e/3600),o=Math.floor(e%3600/60);return t<24?`${t}h ${o}m`:`${Math.floor(t/24)}d ${t%24}h ${o}m`}var kt=require("commander"),ae=c(require("chalk")),Mo=c(require("ora"));var ys=new kt.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{h()||(console.log(ae.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Mo.default)("Restarting gateway...").start(),o=await re();if(o.success){t.succeed(ae.default.green(`Gateway restarted: ${o.message}`));try{await E(),console.log(ae.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(ae.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(ae.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),Go=new kt.Command("gateway").description("Manage the OpenClaw gateway").addCommand(ys);var J=require("commander"),p=c(require("chalk")),Z=c(require("ora")),q=c(require("axios"));We();var Q="http://localhost:7331",_s=new J.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,s=parseInt(e.port,10),n=e.project.replace(/^~/,process.env.HOME||""),r=(0,Z.default)("Starting Claude Code session...").start();try{await q.default.post(`${Q}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),r.text="Gateway toggled \u2014 launching MCP server...";let i=ht({sessionId:o,port:s,projectDir:n}).pid||0;await new Promise(l=>setTimeout(l,1500)),r.text="MCP server running \u2014 launching Claude Code...",wt({sessionId:o,port:s,projectDir:n}),yt(o,0,i,s,n),r.succeed(p.default.green("Claude Code session started")+p.default.dim(` (session: ${o}, port: ${s})`)),console.log(p.default.dim(` Bot: ${e.bot}`)),console.log(p.default.dim(` Room: ${e.room}`)),console.log(p.default.dim(` Project: ${n}`)),console.log(p.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let i=a.response?.data?.message||a.message||"Unknown error";r.fail(p.default.red(`Failed to start Claude Code: ${i}`)),process.exit(1)}}),bs=new J.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,Z.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await q.default.post(`${Q}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let s=e.sessionId;if(!s)try{let a=((await q.default.get(`${Q}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(i=>i.botId===e.bot&&i.roomId===e.room);a&&(s=a.sessionId)}catch{}s?(_t(s),o.succeed(p.default.green(`Claude Code session stopped (${s})`))):(o.succeed(p.default.green("Claude Code toggled off at gateway")),console.log(p.default.dim(" No local session found to kill \u2014 may need to close Claude Code manually.")))}catch(s){let n=s.response?.data?.message||s.message||"Unknown error";o.fail(p.default.red(`Failed to stop Claude Code: ${n}`)),process.exit(1)}}),Ss=new J.Command("status").description("Show active Claude Code sessions").action(async()=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Z.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await q.default.get(`${Q}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let s=bt();if(t.stop(),o.length===0&&s.length===0){console.log(p.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(p.default.bold(`
128
+ Gateway Claude Code Rooms:`)),console.log(p.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(p.default.dim(" "+"-".repeat(88)));for(let n of o){let r=n.enabled?p.default.green("ON"):p.default.dim("OFF");console.log(` ${(n.botId||"").padEnd(30)}${(n.roomName||n.roomId||"").padEnd(30)}${(n.sessionId||"-").padEnd(20)}${r}`)}}if(s.length>0){console.log(p.default.bold(`
129
+ Local Sessions:`)),console.log(p.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(p.default.dim(" "+"-".repeat(90)));for(let n of s)console.log(` ${n.sessionId.padEnd(25)}${String(n.port).padEnd(8)}${String(n.mcpPid).padEnd(10)}${n.projectDir.padEnd(40)}${n.startedAt}`)}console.log("")}catch(o){t.fail(p.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),$s=new J.Command("group").description("Group bots/rooms into a shared Claude Code session").requiredOption("--session <id>","Session ID to group under").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").action(async e=>{let t=(0,Z.default)("Grouping bot+room into session...").start();try{await q.default.post(`${Q}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(p.default.green(`Grouped ${e.bot} + ${e.room} into session "${e.session}"`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(p.default.red(`Failed to group: ${s}`)),process.exit(1)}}),Cs=new J.Command("allow").description("Add a user to the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to allow (e.g. @alice:server)").action(async e=>{let t=(0,Z.default)("Adding user to allowlist...").start();try{await q.default.post(`${Q}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(p.default.green(`Added ${e.user} to allowlist for ${e.bot} in ${e.room}`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(p.default.red(`Failed to add user: ${s}`)),process.exit(1)}}),vs=new J.Command("revoke").description("Remove a user from the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to revoke").action(async e=>{let t=(0,Z.default)("Removing user from allowlist...").start();try{await q.default.post(`${Q}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(p.default.green(`Removed ${e.user} from allowlist for ${e.bot} in ${e.room}`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(p.default.red(`Failed to revoke user: ${s}`)),process.exit(1)}}),Vo=new J.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(_s).addCommand(bs).addCommand(Ss).addCommand($s).addCommand(Cs).addCommand(vs);async function Is(){await To(process.argv);let e=new Wo.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.39"),e.addCommand(io),e.addCommand(uo),e.addCommand(go),e.addCommand(yo),e.addCommand(Jt),e.addCommand(Eo),e.addCommand(Lo),e.addCommand(Ao),e.addCommand(Fo),e.addCommand(Go),e.addCommand(Vo),e.parse(process.argv)}Is().catch(e=>{console.error(e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badgerclaw",
3
- "version": "0.2.37",
3
+ "version": "0.2.39",
4
4
  "description": "BadgerClaw CLI — one-click bot provisioning",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -57,4 +57,18 @@ if (process.platform !== 'win32') {
57
57
  quiet("pkill -f 'badgerclaw heartbeat'");
58
58
  }
59
59
 
60
+ // Wipe local user state so a subsequent `npm install -g badgerclaw` +
61
+ // fresh `badgerclaw login` doesn't inherit the previous user's bot
62
+ // mapping, claude-sessions, heartbeat logs, or plugin quarantine ledger.
63
+ // Reproduced 2026-04-30 on srv1554824: `bot list` after a fresh install
64
+ // returned a previous user's bots because bot-mapping.json survived the
65
+ // uninstall. Scope is strictly user state: ~/.badgerclaw and
66
+ // ~/.openclaw/badgerclaw — we don't touch ~/.openclaw itself (gateway
67
+ // config + other plugins are managed by openclaw, not badgerclaw).
68
+ function rmrfSafe(target) {
69
+ try { fs.rmSync(target, { recursive: true, force: true }); } catch { /* best-effort */ }
70
+ }
71
+ rmrfSafe(path.join(os.homedir(), '.badgerclaw'));
72
+ rmrfSafe(path.join(os.homedir(), '.openclaw', 'badgerclaw'));
73
+
60
74
  console.log('[badgerclaw] preuninstall: done.');