planbee 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # PlanBee CLI
2
2
 
3
- Kommandozeilen-Client für [PlanBee](https://planbee.infin8.world) — Agent-Koordination,
4
- Claude-Code-Hooks und Sprachbenachrichtigungen.
3
+ Command-line client for [PlanBee](https://planbee.cloud) — agent coordination,
4
+ Claude Code hooks and voice notifications.
5
5
 
6
- Das Paket ist ein Client. Es braucht einen PlanBee-Server (Cloud oder lokal) und
7
- ist ohne Zugang zu einem solchen nicht nutzbar.
6
+ This package is a client. It requires a PlanBee server (cloud or self-hosted)
7
+ and is not usable without access to one. Get started at
8
+ [planbee.cloud](https://planbee.cloud).
8
9
 
9
10
  ## Installation
10
11
 
@@ -13,64 +14,74 @@ npm install -g planbee
13
14
  planbee --version
14
15
  ```
15
16
 
16
- Node.js 18 oder neuer.
17
+ Node.js 18 or newer.
17
18
 
18
- ## Anmeldung
19
+ ## Updating
20
+
21
+ npm does not update global packages automatically. To upgrade to the latest
22
+ release:
23
+
24
+ ```bash
25
+ npm install -g planbee@latest
26
+ ```
27
+
28
+ ## Login
19
29
 
20
30
  ```bash
21
31
  planbee auth login --email you@example.com
22
32
  ```
23
33
 
24
- Dabei wird ein langlebiger CLI-Token (PAT) erzeugt und unter
25
- `~/.planbee/cli-auth.json` mit den Rechten `0600` abgelegt. Alternativ lässt sich
26
- ein bestehender Token mit `planbee auth login --token <token>` hinterlegen.
34
+ This creates a long-lived CLI token (PAT) and stores it in
35
+ `~/.planbee/cli-auth.json` with `0600` permissions. Alternatively, an existing
36
+ token can be stored with `planbee auth login --token <token>`.
27
37
 
28
- Gegen einen eigenen Server:
38
+ Against your own server:
29
39
 
30
40
  ```bash
31
- planbee --local <befehl> # http://localhost:3456
32
- PLANBEE_API_URL=https://… planbee … # beliebiger Endpunkt
41
+ planbee --local <command> # http://localhost:3456
42
+ PLANBEE_API_URL=https://… planbee … # any endpoint
33
43
  ```
34
44
 
35
- ## Was an den Server übertragen wird
45
+ ## What is sent to the server
36
46
 
37
- Der Client ist kein reines Anzeigewerkzeug. Damit du weißt, was passiert:
47
+ The client is not a read-only viewer. So you know what happens:
38
48
 
39
- - **Session- und Task-Daten:** Topic, Aufgabenliste, Fortschritt, Status und die
40
- von dir gesetzten Zustandsobjekte (`planbee progress`).
41
- - **Claude-Code-Transkripte:** Sind die Hooks installiert, liest der Client die
42
- Konversationsdateien unter `~/.claude/projects/<projekt>/<session>.jsonl`
43
- inkrementell aus und überträgt die neuen Zeilen an den Server, damit die
44
- Konversation im Dashboard sichtbar ist. Das umfasst **den vollständigen
45
- Verlauf inklusive deiner Prompts und der Modellantworten.**
46
- - **Maschinenname:** Beim Erzeugen eines CLI-Tokens wird der Hostname als
47
- Token-Bezeichnung mitgeschickt (`cli-<hostname>`), damit du Tokens
48
- auseinanderhalten kannst.
49
- - **Nachrichten** zwischen Agenten sowie Sprachnachrichten-Texte (`planbee speak`).
49
+ - **Session and task data:** topic, task list, progress, status and the state
50
+ objects you set yourself (`planbee progress`).
51
+ - **Claude Code transcripts:** once the hooks are installed, the client reads the
52
+ conversation files under `~/.claude/projects/<project>/<session>.jsonl`
53
+ incrementally and uploads the new lines to the server so the conversation is
54
+ visible in the dashboard. This includes **the complete history, including your
55
+ prompts and the model responses.**
56
+ - **Machine name:** when a CLI token is created, the hostname is sent as the
57
+ token label (`cli-<hostname>`) so you can tell tokens apart.
58
+ - **Messages** between agents and the text of voice notifications
59
+ (`planbee speak`).
50
60
 
51
- Ohne installierte Hooks findet keine Transkript-Übertragung statt. Die Hooks
52
- werden ausschließlich durch `planbee hooks install` eingerichtet; der Befehl
53
- schreibt in die `.claude/settings.json` des angegebenen Projekts.
61
+ Without installed hooks, no transcripts are transferred. Hooks are only set up
62
+ by `planbee hooks install`; the command writes to the `.claude/settings.json`
63
+ of the given project.
54
64
 
55
- Betreibst du einen eigenen Server (`--local` / `PLANBEE_API_URL`), gehen diese
56
- Daten ausschließlich dorthin.
65
+ If you run your own server (`--local` / `PLANBEE_API_URL`), this data goes
66
+ there exclusively.
57
67
 
58
68
  ## Hooks
59
69
 
60
70
  ```bash
61
- planbee hooks install --project /pfad/zum/projekt
71
+ planbee hooks install --project /path/to/project
62
72
  planbee hooks status
63
73
  ```
64
74
 
65
- ## Autor und Support
75
+ ## Author and support
66
76
 
67
- infin8 — infin8 world llc, [www.infin8.world](https://www.infin8.world)
77
+ [planbee.cloud](https://planbee.cloud) — infin8 world llc,
78
+ [www.infin8.world](https://www.infin8.world)
68
79
 
69
- ## Lizenz
80
+ ## License
70
81
 
71
- Proprietär, siehe `LICENSE`: Die Nutzung als Client ist gestattet,
72
- Weiterverkauf und die Wiederverwendung des Quellcodes sind es nicht.
82
+ Proprietary, see `LICENSE`: use as a client is permitted, resale and reuse of
83
+ the source code are not.
73
84
 
74
- Die Lizenztexte der gebündelten Open-Source-Pakete stehen vollständig in
75
- `THIRD-PARTY-NOTICES.txt` (44 Pakete, MIT/ISC) sowie in
76
- `bin/planbee.js.LEGAL.txt`; für diese Bestandteile gelten sie vorrangig.
85
+ The license texts of the bundled open-source packages are included in full in
86
+ `THIRD-PARTY-NOTICES.txt` (44 packages, MIT/ISC) and in
87
+ `bin/planbee.js.LEGAL.txt`; for those components they take precedence.
package/bin/planbee.js CHANGED
@@ -392,7 +392,7 @@ Found ${Fe.bold(n.length)} sessions (${Fe.green(`${s.length} new`)}, ${Fe.gray(`
392
392
  `),console.log(Fe.bold(" Provider Session ID Project First Prompt Date")),console.log(` ${"\u2500".repeat(95)}`);for(let r of n){let i=mB[r.provider]||"\u26AA",a=r.provider.padEnd(10),c=(r.sessionId||"").substring(0,8),l=(r.projectName||"\u2014").substring(0,14).padEnd(14),u=(r.firstPrompt||r.summary||"\u2014").substring(0,35).padEnd(35),p=r.timestamps?.modified?new Date(r.timestamps.modified).toLocaleDateString():"\u2014",d=r.alreadyImported?Fe.gray(" \u2713"):Fe.green(" \u2605");console.log(`${d} ${i} ${a} ${c} ${l} ${u} ${p}`)}if((t.import||t.importAll)&&s.length>0){console.log(`
393
393
  ${Fe.cyan(`Importing ${s.length} sessions...`)}`);try{let i=(await JE.post(`${ji}/api/v1/sessions/discover/import`,{sessions:s},{timeout:6e4})).data;if(console.log(Fe.green(`\u2713 Imported: ${i.imported}`)),i.skipped>0&&console.log(Fe.yellow(`\u2298 Skipped: ${i.skipped}`)),i.failed?.length>0){console.log(Fe.red(`\u2717 Failed: ${i.failed.length}`));for(let a of i.failed)console.log(Fe.red(` - ${a.sessionId}: ${a.error}`))}}catch(r){console.error(Fe.red(`Error: import failed, PlanBee API unreachable (${ji}/api/v1/sessions/discover/import).`)),console.error(Fe.red(` ${r.message}`)),process.exit(1)}}else s.length>0&&!t.import&&!t.importAll&&console.log(`
394
394
  ${Fe.gray("Use --import or --import-all to import new sessions.")}`)}catch(e){console.error(Fe.red(`Error: ${e.message}`)),process.exit(1)}}}});var XE=D((cU,YE)=>{function hB(t,e={}){let n=["CLI Authentication Status"],s=t||{},o=e.patSnapshot,r=e.jwtSnapshot;if(o){let i=o.daysOld!=null?`${o.daysOld}d`:"?",a=VE(s,"pat",!1);n.push(` PAT (cli-auth.json): ${a} (age ${i})`)}else n.push(" PAT (cli-auth.json): --");if(r){let i=gB(r.minutesLeft),a=VE(s,"jwt",!!r.expired);n.push(` JWT (auth.json): ${a} (${i})`)}else n.push(" JWT (auth.json): --");return s.kind?n.push(` Active source: ${s.kind.toUpperCase()}`):n.push(" Active source: none"),s.email&&n.push(` Account: ${s.email}`),s.valid||(n.push(""),s.errorCode==="MISSING_TOKEN"?(n.push(" No CLI token found. Run:"),n.push(" planbee auth login --github")):s.expiredError?(n.push(""),n.push(" Token rejected. Run ONE of:"),n.push(" planbee auth login --github (opens browser, easiest)"),n.push(" planbee auth login --google"),n.push(" planbee auth login --email <you> --password <pw>")):(s.errorCode==="TRANSIENT"||s.errorCode==="NETWORK")&&(n.push(""),n.push(` Cannot reach server right now (${s.errorCode}: ${s.errorMessage||"n/a"}).`),n.push(" Token may still be valid; will retry on next command."))),n.join(`
395
- `)}YE.exports={formatAuthStatus:hB};function VE(t,e,n){return t.kind!==e?n?"expired":"standby":t.valid?"valid":t.expiredError?"EXPIRED":"unreachable"}function gB(t){return t==null?"?":t<0?"expired":`${t}m left`}});var tD=D((lU,eD)=>{var QE=de(),yB=require("os"),Zn=it(),{resolveApiUrl:ZE}=te(),bB=ci(),{formatAuthStatus:xB}=XE();async function vB(t,e,n){let s=ZE(n),o;try{o=(await QE.post(`${s}/auth/login`,{email:t,password:e},{timeout:1e4})).data}catch(l){let u=l.response?.data?.error||l.response?.data?.details||l.message;throw new Error(`Login failed: ${u}`)}let r=o.access_token||o.session?.access_token;if(!r)throw new Error("Login failed: no access token in server response");let i;try{i=await QE.post(`${s}/api/v1/cli-tokens`,{name:`cli-${yB.hostname()}`},{headers:{Authorization:`Bearer ${r}`},timeout:1e4})}catch(l){let u=l.response?.data?.error||l.message;throw new Error(`Could not issue CLI token: ${u}`)}let{token:a}=i.data;if(!a)throw new Error("Could not issue CLI token: server returned no token");let c=o.user||o.session?.user||{};Zn.save({token:a,api_url:s,user:{id:c.id||null,email:c.email||t},created_at:new Date().toISOString()}),n.json?console.log(JSON.stringify({success:!0,user:{email:c.email||t}},null,2)):(console.log("Login successful"),console.log(`Welcome, ${c.email||t}`))}async function wB(t){if(t.github||t.google){console.error(`Error: OAuth login (--${t.github?"github":"google"}) is not available in the standalone planbee CLI. Use --email/--password, or log in via the PlanBee app and run \`planbee auth login --token <pat>\`.`),process.exit(1);return}if(t.token){Zn.save({token:t.token,api_url:ZE(t),user:null,created_at:new Date().toISOString()}),console.log("Token saved to ~/.planbee/cli-auth.json");return}let{email:e,password:n}=t;(!e||!n)&&(console.error("Error: Email and password are required"),console.error("Usage: planbee auth login --email <email> --password <pass>"),console.error(" Or: planbee auth login --token <personal-access-token>"),process.exit(1));try{await vB(e,n,t)}catch(s){t.json?console.log(JSON.stringify({success:!1,error:s.message},null,2)):console.error(s.message),process.exit(1)}}async function EB(t){let e=Zn.load();if(!e||!e.token){t.json?console.log(JSON.stringify({success:!0,message:"Already logged out"})):console.log("Not logged in");return}Zn.clear(),t.json?console.log(JSON.stringify({success:!0,message:"Logged out successfully"})):console.log("Logged out successfully")}async function DB(t){let e=await bB.validateAuth();if(t.json){console.log(JSON.stringify({authenticated:e.valid,user:e.user||(e.email?{email:e.email}:null),active_source:e.kind,pat:e.kind==="pat"?{store:e.store,daysOld:e.daysOld}:null,error:e.expiredError?{code:e.errorCode,message:e.expiredError.message}:null},null,2));return}let n=Zn.load(),s=n&&n.token?{daysOld:e.kind==="pat"?e.daysOld:null}:null;console.log(xB(e,{patSnapshot:s,jwtSnapshot:null}))}async function SB(t,e){switch(t){case"login":await wB(e);break;case"logout":await EB(e);break;case"status":case"whoami":await DB(e);break;default:console.error(`Unknown auth subcommand: ${t}`),console.error("Available subcommands: login, logout, status"),process.exit(1)}}eD.exports={authCommand:SB,loadToken:Zn.load.bind(Zn)}});var nD=D((uU,kB)=>{kB.exports={name:"planbee",version:"0.1.0",description:"PlanBee CLI - agent coordination, hooks, and voice notifications for Claude Code",license:"SEE LICENSE IN LICENSE",bin:{planbee:"bin/planbee.js"},files:["bin","LICENSE","THIRD-PARTY-NOTICES.txt"],engines:{node:">=18"},scripts:{build:"node scripts/build.js && node scripts/third-party-notices.js",prepublishOnly:"npm run build"},dependencies:{},devDependencies:{axios:"^1.6.2",yargs:"^17.7.2",i18next:"^26.2.0",esbuild:"^0.24.0"},repository:{type:"git",url:"git+https://git.infin8.world/infin8/planbee-cli.git"},author:"infin8 world llc (https://www.infin8.world)",homepage:"https://www.infin8.world"}});var AB=de(),{resolveApiUrl:_B}=te(),{isLinearEnabled:CB}=nh(),{validatePathAbsolute:OB}=Qa(),TB=`${_B()}/notify`,sD=1,oD=5e3,rD=100,PB=.5,$B=2,NB=0,IB=1,RB=["info","success","error","warning","progress","question","joke","finished_user_interaction_required"],FB=["happy","sad","excited","serious","calm","neutral","cheerful"],Ku=0,cD=1,Vo=2,zu=3;function lD(t){return!t||t.length<sD?`Message must be at least ${sD} character`:t.length>oD?`Message must not exceed ${oD} characters`:null}function uD(t){return t&&t.length>rD?`Title must not exceed ${rD} characters`:null}function pD(t){return OB(t)}function Wu(t,e,n,s){let o=parseFloat(t);return Number.isNaN(o)?`${s} must be a valid number`:o<e||o>n?`${s} must be between ${e} and ${n}`:null}function dD(t,e){return t&&!e||!t&&e?"Both --project and --path must be provided together":null}function iD(t,e=!1){e||console.error(`Error: ${t}`)}function aD(t,e=!1,n=!1){e||console.log(n?JSON.stringify(t,null,2):t)}function fD(t){let{id:e,status:n}=t;return n==="queued"?`[OK] Message queued (ID: ${e})`:`[OK] Message sent (ID: ${e})`}async function mD(t){let e={message:t.message};t.project&&t.path&&(e.project=t.project,e.path=t.path),t.type&&(e.type=t.type),t.title&&(e.title=t.title),t.mood&&(e.mood=t.mood),t.speed!==void 0&&(e.speech_speed=parseFloat(t.speed)),t.volume!==void 0&&(e.volume=parseFloat(t.volume)),t.voiceId&&(e.voice_id=t.voiceId);try{return{success:!0,data:(await AB.post(TB,e,{headers:{"Content-Type":"application/json"},timeout:5e3})).data}}catch(n){if(n.code==="ECONNREFUSED"||n.code==="ETIMEDOUT")return{success:!1,error:"Cannot connect to PlanBee server",exitCode:zu};if(n.response){let{status:s,data:o}=n.response;return s===503?{success:!1,error:"PlanBee server is offline",exitCode:zu}:s===404?{success:!1,error:"Project not found. Use --register to register project first.",exitCode:Vo}:{success:!1,error:`HTTP ${s}: ${o.error||o.message||"Unknown error"}`,exitCode:Vo}}return{success:!1,error:n.message||"Unknown error occurred",exitCode:Vo}}}function hD(){return process.argv.includes("--json")}var Ju={tasks:"planbee tasks <session-id> --json",status:"planbee status <session-id> --json",transcript:"planbee transcript <session-id> --json",send:'planbee send <session-id> "<message>" --json',spawn:'planbee spawn --task "<task>" --json'};function gD(){let t=process.argv[2];return t&&Ju[t]?Ju[t]:"planbee --help --json"}function yD(){return function(e,n,s){if(!e&&!n)return;let o=e||n?.message||"Unknown error";if(hD()){let r=gD();console.log(JSON.stringify({error:!0,message:o,suggestion:r})),process.exit(1)}else console.error(`Error: ${o}`),s.showHelp(),process.exit(1)}}async function jB(){let t=Fg(),{hideBin:e}=Lg(),n=Hg(),s=Wg(),o=Kg(),r=Qg(),i=ey(),a=ny(),c=iy(),l=uy(),u=dy(),p=my(),d=gy(),f=by(),m=vy(),h=Ey(),g=Sy(),b=_y(),v=Oy(),E=rx(),S=dx(),C=Rx(),B=hv(),L=wv(),$=Av(),I=Cv(),R=Pv(),U=Bv(),Q=Uv(),M=Wv(),z=Gv(),ge=Yv(),oe=Zv(),xe=nw(),Ee=gw(),ve=Ew(),Me=kw(),F=Ou(),H=T0(),W=N0(),N=z0(),ce=Q0(),pe=eE(),Z=nE(),me=oE(),_e=aE(),ie=lE(),Ue=pE(),ze=fE(),le=hE(),Xe=CE(),w=TE(),_=$E(),j=IE(),A=LE(),k=UE(),P=WE(),O=GE(),{authCommand:q}=tD(),G=await t(e(process.argv)).scriptName("planbee").version(nD().version).fail(yD()).usage("Usage: $0 <command> [options]").command(n).command(CB()?[{command:"linear",describe:"Linear integration commands",builder:ae=>ae.command(s).command(o).command(r).command(i).command(a).command(c).command(l).command(u).command(p).command(d).command(f).command(m).command(h).command(g).command(b).demandCommand(1,"You need to specify a linear subcommand").help(),handler:()=>{}}]:[]).command("auth <subcommand>","Authentication commands (login, logout, whoami)",ae=>ae.positional("subcommand",{describe:"Auth subcommand",choices:["login","logout","status","whoami"]}).option("email",{type:"string",description:"Email address"}).option("password",{type:"string",description:"Password"}).option("token",{type:"string",description:"Existing personal access token to store directly"}),async ae=>{await q(ae.subcommand,ae)}).command(E).command(S).command(oe).command(xe).command(Ee).command(C.send).command(C.sendToQueen).command(B).command(L).command($).command(Q).command("swarm","Swarm management commands",ae=>ae.command(M).command(z).demandCommand(1,"You need to specify a swarm subcommand").help()).command("providers","Provider management commands",ae=>ae.command(ge).demandCommand(1,"You need to specify a providers subcommand").help()).command("memory","Memory management commands",ae=>ae.command(I.store).command(I.get).command(I.list).command(I.delete).command(I.export).command(I.import).command(I.cleanup).command(I.history).command(I.diff).demandCommand(1,"You need to specify a memory subcommand").help()).command(R.agent).command(U.listChildren).command(ve).command(Me).command(F).command(H).command(W).command(v).command("audio","Audio and TTS configuration",ae=>ae.command(N).demandCommand(1,"You need to specify an audio subcommand").help()).command("hooks","Manage PlanBee hooks in projects",ae=>ae.command(ce).command(pe).command(Z).demandCommand(1,"You need to specify a hooks subcommand").help()).command("search","Search agents and transcripts",ae=>ae.command(me).command(_e).demandCommand(1,"You need to specify a search subcommand").help()).command(ie).command(Ue).command(ze).command(le).command(Xe).command(w).command(_).command(j).command(A).command(k).command(P).command(O).option("project",{type:"string",description:"Project identifier",global:!1}).option("path",{type:"string",description:"Absolute project path",global:!1}).option("message",{type:"string",description:"Message to send (1-5000 characters)",global:!1}).option("type",{type:"string",description:"Message type",choices:RB,default:"info",global:!1}).option("title",{type:"string",description:"Short title (max 100 chars)",global:!1}).option("mood",{type:"string",description:"Voice mood",choices:FB,default:"neutral",global:!1}).option("speed",{type:"number",description:"Speech speed (0.5-2.0)",default:1,global:!1}).option("volume",{type:"number",description:"Volume (0.0-1.0)",default:.8,global:!1}).option("voice-id",{type:"string",description:"Override voice selection",global:!1}).option("quiet",{type:"boolean",description:"Suppress stdout",default:!1,global:!1}).option("json",{type:"boolean",description:"Output JSON response",default:!1,global:!1}).option("local",{type:"boolean",description:"Use local dev server (http://localhost:3456) instead of cloud",default:!1,global:!0,coerce:ae=>(ae&&(process.env.PLANBEE_MODE="local"),ae)}).help("h").alias("h","help").example('$0 --project myapp --path /home/user/myapp --message "Build complete"').example('$0 --message "Quick notification" --type success').example('$0 register --folder /path/to/workspace --task "Research task" --agent-type researcher').example('$0 spawn --type coder --task "Implement feature" --parent session-id-here').example(`$0 memory store --key task-status --value '{"status": "completed"}'`).epilogue(`Modes: cloud (default, https://planbee.infin8.world), local (--local / PLANBEE_MODE=local -> http://localhost:3456).
395
+ `)}YE.exports={formatAuthStatus:hB};function VE(t,e,n){return t.kind!==e?n?"expired":"standby":t.valid?"valid":t.expiredError?"EXPIRED":"unreachable"}function gB(t){return t==null?"?":t<0?"expired":`${t}m left`}});var tD=D((lU,eD)=>{var QE=de(),yB=require("os"),Zn=it(),{resolveApiUrl:ZE}=te(),bB=ci(),{formatAuthStatus:xB}=XE();async function vB(t,e,n){let s=ZE(n),o;try{o=(await QE.post(`${s}/auth/login`,{email:t,password:e},{timeout:1e4})).data}catch(l){let u=l.response?.data?.error||l.response?.data?.details||l.message;throw new Error(`Login failed: ${u}`)}let r=o.access_token||o.session?.access_token;if(!r)throw new Error("Login failed: no access token in server response");let i;try{i=await QE.post(`${s}/api/v1/cli-tokens`,{name:`cli-${yB.hostname()}`},{headers:{Authorization:`Bearer ${r}`},timeout:1e4})}catch(l){let u=l.response?.data?.error||l.message;throw new Error(`Could not issue CLI token: ${u}`)}let{token:a}=i.data;if(!a)throw new Error("Could not issue CLI token: server returned no token");let c=o.user||o.session?.user||{};Zn.save({token:a,api_url:s,user:{id:c.id||null,email:c.email||t},created_at:new Date().toISOString()}),n.json?console.log(JSON.stringify({success:!0,user:{email:c.email||t}},null,2)):(console.log("Login successful"),console.log(`Welcome, ${c.email||t}`))}async function wB(t){if(t.github||t.google){console.error(`Error: OAuth login (--${t.github?"github":"google"}) is not available in the standalone planbee CLI. Use --email/--password, or log in via the PlanBee app and run \`planbee auth login --token <pat>\`.`),process.exit(1);return}if(t.token){Zn.save({token:t.token,api_url:ZE(t),user:null,created_at:new Date().toISOString()}),console.log("Token saved to ~/.planbee/cli-auth.json");return}let{email:e,password:n}=t;(!e||!n)&&(console.error("Error: Email and password are required"),console.error("Usage: planbee auth login --email <email> --password <pass>"),console.error(" Or: planbee auth login --token <personal-access-token>"),process.exit(1));try{await vB(e,n,t)}catch(s){t.json?console.log(JSON.stringify({success:!1,error:s.message},null,2)):console.error(s.message),process.exit(1)}}async function EB(t){let e=Zn.load();if(!e||!e.token){t.json?console.log(JSON.stringify({success:!0,message:"Already logged out"})):console.log("Not logged in");return}Zn.clear(),t.json?console.log(JSON.stringify({success:!0,message:"Logged out successfully"})):console.log("Logged out successfully")}async function DB(t){let e=await bB.validateAuth();if(t.json){console.log(JSON.stringify({authenticated:e.valid,user:e.user||(e.email?{email:e.email}:null),active_source:e.kind,pat:e.kind==="pat"?{store:e.store,daysOld:e.daysOld}:null,error:e.expiredError?{code:e.errorCode,message:e.expiredError.message}:null},null,2));return}let n=Zn.load(),s=n&&n.token?{daysOld:e.kind==="pat"?e.daysOld:null}:null;console.log(xB(e,{patSnapshot:s,jwtSnapshot:null}))}async function SB(t,e){switch(t){case"login":await wB(e);break;case"logout":await EB(e);break;case"status":case"whoami":await DB(e);break;default:console.error(`Unknown auth subcommand: ${t}`),console.error("Available subcommands: login, logout, status"),process.exit(1)}}eD.exports={authCommand:SB,loadToken:Zn.load.bind(Zn)}});var nD=D((uU,kB)=>{kB.exports={name:"planbee",version:"0.1.1",description:"PlanBee CLI - agent coordination, hooks, and voice notifications for Claude Code",license:"SEE LICENSE IN LICENSE",bin:{planbee:"bin/planbee.js"},files:["bin","LICENSE","THIRD-PARTY-NOTICES.txt"],engines:{node:">=18"},scripts:{build:"node scripts/build.js && node scripts/third-party-notices.js",prepublishOnly:"npm run build"},dependencies:{},devDependencies:{axios:"^1.6.2",yargs:"^17.7.2",i18next:"^26.2.0",esbuild:"^0.24.0"},author:"infin8 world llc (https://www.infin8.world)",homepage:"https://planbee.cloud"}});var AB=de(),{resolveApiUrl:_B}=te(),{isLinearEnabled:CB}=nh(),{validatePathAbsolute:OB}=Qa(),TB=`${_B()}/notify`,sD=1,oD=5e3,rD=100,PB=.5,$B=2,NB=0,IB=1,RB=["info","success","error","warning","progress","question","joke","finished_user_interaction_required"],FB=["happy","sad","excited","serious","calm","neutral","cheerful"],Ku=0,cD=1,Vo=2,zu=3;function lD(t){return!t||t.length<sD?`Message must be at least ${sD} character`:t.length>oD?`Message must not exceed ${oD} characters`:null}function uD(t){return t&&t.length>rD?`Title must not exceed ${rD} characters`:null}function pD(t){return OB(t)}function Wu(t,e,n,s){let o=parseFloat(t);return Number.isNaN(o)?`${s} must be a valid number`:o<e||o>n?`${s} must be between ${e} and ${n}`:null}function dD(t,e){return t&&!e||!t&&e?"Both --project and --path must be provided together":null}function iD(t,e=!1){e||console.error(`Error: ${t}`)}function aD(t,e=!1,n=!1){e||console.log(n?JSON.stringify(t,null,2):t)}function fD(t){let{id:e,status:n}=t;return n==="queued"?`[OK] Message queued (ID: ${e})`:`[OK] Message sent (ID: ${e})`}async function mD(t){let e={message:t.message};t.project&&t.path&&(e.project=t.project,e.path=t.path),t.type&&(e.type=t.type),t.title&&(e.title=t.title),t.mood&&(e.mood=t.mood),t.speed!==void 0&&(e.speech_speed=parseFloat(t.speed)),t.volume!==void 0&&(e.volume=parseFloat(t.volume)),t.voiceId&&(e.voice_id=t.voiceId);try{return{success:!0,data:(await AB.post(TB,e,{headers:{"Content-Type":"application/json"},timeout:5e3})).data}}catch(n){if(n.code==="ECONNREFUSED"||n.code==="ETIMEDOUT")return{success:!1,error:"Cannot connect to PlanBee server",exitCode:zu};if(n.response){let{status:s,data:o}=n.response;return s===503?{success:!1,error:"PlanBee server is offline",exitCode:zu}:s===404?{success:!1,error:"Project not found. Use --register to register project first.",exitCode:Vo}:{success:!1,error:`HTTP ${s}: ${o.error||o.message||"Unknown error"}`,exitCode:Vo}}return{success:!1,error:n.message||"Unknown error occurred",exitCode:Vo}}}function hD(){return process.argv.includes("--json")}var Ju={tasks:"planbee tasks <session-id> --json",status:"planbee status <session-id> --json",transcript:"planbee transcript <session-id> --json",send:'planbee send <session-id> "<message>" --json',spawn:'planbee spawn --task "<task>" --json'};function gD(){let t=process.argv[2];return t&&Ju[t]?Ju[t]:"planbee --help --json"}function yD(){return function(e,n,s){if(!e&&!n)return;let o=e||n?.message||"Unknown error";if(hD()){let r=gD();console.log(JSON.stringify({error:!0,message:o,suggestion:r})),process.exit(1)}else console.error(`Error: ${o}`),s.showHelp(),process.exit(1)}}async function jB(){let t=Fg(),{hideBin:e}=Lg(),n=Hg(),s=Wg(),o=Kg(),r=Qg(),i=ey(),a=ny(),c=iy(),l=uy(),u=dy(),p=my(),d=gy(),f=by(),m=vy(),h=Ey(),g=Sy(),b=_y(),v=Oy(),E=rx(),S=dx(),C=Rx(),B=hv(),L=wv(),$=Av(),I=Cv(),R=Pv(),U=Bv(),Q=Uv(),M=Wv(),z=Gv(),ge=Yv(),oe=Zv(),xe=nw(),Ee=gw(),ve=Ew(),Me=kw(),F=Ou(),H=T0(),W=N0(),N=z0(),ce=Q0(),pe=eE(),Z=nE(),me=oE(),_e=aE(),ie=lE(),Ue=pE(),ze=fE(),le=hE(),Xe=CE(),w=TE(),_=$E(),j=IE(),A=LE(),k=UE(),P=WE(),O=GE(),{authCommand:q}=tD(),G=await t(e(process.argv)).scriptName("planbee").version(nD().version).fail(yD()).usage("Usage: $0 <command> [options]").command(n).command(CB()?[{command:"linear",describe:"Linear integration commands",builder:ae=>ae.command(s).command(o).command(r).command(i).command(a).command(c).command(l).command(u).command(p).command(d).command(f).command(m).command(h).command(g).command(b).demandCommand(1,"You need to specify a linear subcommand").help(),handler:()=>{}}]:[]).command("auth <subcommand>","Authentication commands (login, logout, whoami)",ae=>ae.positional("subcommand",{describe:"Auth subcommand",choices:["login","logout","status","whoami"]}).option("email",{type:"string",description:"Email address"}).option("password",{type:"string",description:"Password"}).option("token",{type:"string",description:"Existing personal access token to store directly"}),async ae=>{await q(ae.subcommand,ae)}).command(E).command(S).command(oe).command(xe).command(Ee).command(C.send).command(C.sendToQueen).command(B).command(L).command($).command(Q).command("swarm","Swarm management commands",ae=>ae.command(M).command(z).demandCommand(1,"You need to specify a swarm subcommand").help()).command("providers","Provider management commands",ae=>ae.command(ge).demandCommand(1,"You need to specify a providers subcommand").help()).command("memory","Memory management commands",ae=>ae.command(I.store).command(I.get).command(I.list).command(I.delete).command(I.export).command(I.import).command(I.cleanup).command(I.history).command(I.diff).demandCommand(1,"You need to specify a memory subcommand").help()).command(R.agent).command(U.listChildren).command(ve).command(Me).command(F).command(H).command(W).command(v).command("audio","Audio and TTS configuration",ae=>ae.command(N).demandCommand(1,"You need to specify an audio subcommand").help()).command("hooks","Manage PlanBee hooks in projects",ae=>ae.command(ce).command(pe).command(Z).demandCommand(1,"You need to specify a hooks subcommand").help()).command("search","Search agents and transcripts",ae=>ae.command(me).command(_e).demandCommand(1,"You need to specify a search subcommand").help()).command(ie).command(Ue).command(ze).command(le).command(Xe).command(w).command(_).command(j).command(A).command(k).command(P).command(O).option("project",{type:"string",description:"Project identifier",global:!1}).option("path",{type:"string",description:"Absolute project path",global:!1}).option("message",{type:"string",description:"Message to send (1-5000 characters)",global:!1}).option("type",{type:"string",description:"Message type",choices:RB,default:"info",global:!1}).option("title",{type:"string",description:"Short title (max 100 chars)",global:!1}).option("mood",{type:"string",description:"Voice mood",choices:FB,default:"neutral",global:!1}).option("speed",{type:"number",description:"Speech speed (0.5-2.0)",default:1,global:!1}).option("volume",{type:"number",description:"Volume (0.0-1.0)",default:.8,global:!1}).option("voice-id",{type:"string",description:"Override voice selection",global:!1}).option("quiet",{type:"boolean",description:"Suppress stdout",default:!1,global:!1}).option("json",{type:"boolean",description:"Output JSON response",default:!1,global:!1}).option("local",{type:"boolean",description:"Use local dev server (http://localhost:3456) instead of cloud",default:!1,global:!0,coerce:ae=>(ae&&(process.env.PLANBEE_MODE="local"),ae)}).help("h").alias("h","help").example('$0 --project myapp --path /home/user/myapp --message "Build complete"').example('$0 --message "Quick notification" --type success').example('$0 register --folder /path/to/workspace --task "Research task" --agent-type researcher').example('$0 spawn --type coder --task "Implement feature" --parent session-id-here').example(`$0 memory store --key task-status --value '{"status": "completed"}'`).epilogue(`Modes: cloud (default, https://planbee.infin8.world), local (--local / PLANBEE_MODE=local -> http://localhost:3456).
396
396
  Override the API base URL entirely with PLANBEE_API_URL.
397
397
 
398
398
  infin8 -- infin8 world llc, www.infin8.world`).strict().parseAsync(),ee=["linear","register","spawn","start-agent","devices","send","send-to-queen","inbox","remote-control","memory","wait","status","list-children","tree","auth","progress","tasks","internal-hook","audio","hooks","search","transcript","todo","plan","bee","icon","watch-rules","swarm","providers","dashboard","agents","activity","system-load","test-lock","discover"];if(Array.isArray(G._)&&G._.length>0&&ee.includes(G._[0]))return;let Qe=[lD(G.message),uD(G.title),dD(G.project,G.path),G.path?pD(G.path):null,Wu(G.speed,PB,$B,"Speed"),Wu(G.volume,NB,IB,"Volume")];for(let ae of Qe)ae&&(iD(ae,G.quiet),process.exit(cD));let je=await mD({message:G.message,project:G.project,path:G.path,type:G.type,title:G.title,mood:G.mood,speed:G.speed,volume:G.volume,voiceId:G.voiceId});je.success?(G.json?aD(je.data,G.quiet,!0):aD(fD(je.data),G.quiet,!1),process.exit(Ku)):(iD(je.error,G.quiet),process.exit(je.exitCode))}function LB(){let t=n=>{let s=process.argv.indexOf(`--${n}`);return s!==-1?process.argv[s+1]:void 0},e=Ou();return Promise.resolve(e.handler({type:t("type"),session:t("session"),"transcript-path":t("transcript-path"),deliver:process.argv.includes("--deliver")}))}if(require.main===module){let t=process.argv[2]==="internal-hook";(t?LB():jB()).catch(n=>{console.error("Fatal error:",n.message),process.exit(t?Ku:Vo)})}module.exports={validateMessage:lD,validateTitle:uD,validateAbsolutePath:pD,validateRange:Wu,validateProjectContext:dD,sendNotification:mD,formatResponse:fD,isJsonMode:hD,buildJsonFailHandler:yD,buildSuggestion:gD,COMMAND_SUGGESTIONS:Ju,EXIT_SUCCESS:Ku,EXIT_VALIDATION_ERROR:cD,EXIT_SYSTEM_ERROR:Vo,EXIT_APP_OFFLINE:zu};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "planbee",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "PlanBee CLI - agent coordination, hooks, and voice notifications for Claude Code",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "bin": {
@@ -25,10 +25,6 @@
25
25
  "i18next": "^26.2.0",
26
26
  "esbuild": "^0.24.0"
27
27
  },
28
- "repository": {
29
- "type": "git",
30
- "url": "git+https://git.infin8.world/infin8/planbee-cli.git"
31
- },
32
28
  "author": "infin8 world llc (https://www.infin8.world)",
33
- "homepage": "https://www.infin8.world"
29
+ "homepage": "https://planbee.cloud"
34
30
  }