hivemind-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/dist/index.js +66 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# hivemind-cli
|
|
2
|
+
|
|
3
|
+
**One memory across every AI tool you use.**
|
|
4
|
+
|
|
5
|
+
Tell Claude Code something. Cursor already knows it. So does ChatGPT in your
|
|
6
|
+
browser, and Codex, and whatever you switch to next month.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx hivemind-cli init
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
That opens your browser, signs you in, finds every AI client installed on the
|
|
13
|
+
machine, and writes each one's config in its own dialect. There is no key to
|
|
14
|
+
copy and nothing to paste.
|
|
15
|
+
|
|
16
|
+
## What it configures
|
|
17
|
+
|
|
18
|
+
Claude Code · Claude Desktop · Cursor · VS Code · Windsurf · Zed · Cline ·
|
|
19
|
+
Roo Code · Codex CLI · Gemini CLI · Amp · OpenCode · Witsy
|
|
20
|
+
|
|
21
|
+
Each client gets its own credential, so revoking one machine leaves the rest
|
|
22
|
+
working.
|
|
23
|
+
|
|
24
|
+
## Commands
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx hivemind-cli init # sign in and configure everything detected
|
|
28
|
+
npx hivemind-cli init --dry-run # show what would change, write nothing
|
|
29
|
+
npx hivemind-cli status # which clients are connected, and to which account
|
|
30
|
+
npx hivemind-cli signout # remove Hivemind from every client
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
| Flag | |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `--with google\|github` | skip the provider chooser |
|
|
36
|
+
| `--key hm_live_...` | use an existing key instead of signing in |
|
|
37
|
+
| `--only cursor,vscode` | restrict to specific clients |
|
|
38
|
+
| `--url <endpoint>` | point at a different deployment |
|
|
39
|
+
| `--dry-run` | preview without writing |
|
|
40
|
+
|
|
41
|
+
## What it does to your files
|
|
42
|
+
|
|
43
|
+
Configs are merged, never replaced — your other MCP servers and editor settings
|
|
44
|
+
are left alone. A backup is written next to each file the first time it is
|
|
45
|
+
touched (`<config>.hivemind-bak`).
|
|
46
|
+
|
|
47
|
+
Where a client owns its config at runtime and rewrites it as it goes — Claude
|
|
48
|
+
Code does this — the client's own CLI is used instead of editing the file
|
|
49
|
+
underneath it.
|
|
50
|
+
|
|
51
|
+
## Why not just paste a key
|
|
52
|
+
|
|
53
|
+
Because a token in your shell history is a token in your shell history, and
|
|
54
|
+
because seven config files in five formats is not a thing anyone should do by
|
|
55
|
+
hand. `status` also tells you when a client is sitting on a *different* key
|
|
56
|
+
than the one you think, which is the failure that looks like a bug.
|
|
57
|
+
|
|
58
|
+
## Links
|
|
59
|
+
|
|
60
|
+
- Dashboard and docs: <https://hivemind-api.hivemind-api.workers.dev>
|
|
61
|
+
- Source: <https://github.com/0xadityaa/hivemind>
|
|
62
|
+
|
|
63
|
+
MIT.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{spawnSync as M}from"node:child_process";import{copyFileSync as a,existsSync as F,mkdirSync as i,readFileSync as N,writeFileSync as k}from"node:fs";import{dirname as r}from"node:path";import{homedir as u,platform as f}from"node:os";import{join as H}from"node:path";var B=u(),g=f()==="darwin",d=f()==="win32";function L(...z){if(g)return H(B,"Library","Application Support",...z);if(d)return H(process.env.APPDATA??H(B,"AppData","Roaming"),...z);return H(process.env.XDG_CONFIG_HOME??H(B,".config"),...z)}var T=(z)=>({Authorization:`Bearer ${z}`}),A=[{id:"claude-code",name:"Claude Code",configPath:H(B,".claude.json"),installHints:[H(B,".claude")],format:"json",serverMapKey:"mcpServers",entry:(z,Q)=>({type:"http",url:z,headers:T(Q)}),viaCommand:{bin:"claude",probeArgs:["--version"],args:(z,Q,X)=>["mcp","add","--scope","user","--transport","http",X,z,"--header",`Authorization: Bearer ${Q}`]}},{id:"claude-desktop",name:"Claude Desktop",configPath:L("Claude","claude_desktop_config.json"),installHints:["/Applications/Claude.app",L("Claude")],format:"json",serverMapKey:"mcpServers",entry:(z,Q)=>({type:"http",url:z,headers:T(Q)})},{id:"cursor",name:"Cursor",configPath:H(B,".cursor","mcp.json"),installHints:[H(B,".cursor"),"/Applications/Cursor.app"],format:"json",serverMapKey:"mcpServers",entry:(z,Q)=>({url:z,headers:T(Q)})},{id:"windsurf",name:"Windsurf",configPath:H(B,".codeium","windsurf","mcp_config.json"),installHints:[H(B,".codeium"),"/Applications/Windsurf.app"],format:"json",serverMapKey:"mcpServers",entry:(z,Q)=>({serverUrl:z,headers:T(Q)})},{id:"vscode",name:"VS Code",configPath:L("Code","User","mcp.json"),installHints:["/Applications/Visual Studio Code.app",L("Code")],format:"json",serverMapKey:"servers",entry:(z,Q)=>({type:"http",url:z,headers:T(Q)})},{id:"gemini-cli",name:"Gemini CLI",configPath:H(B,".gemini","settings.json"),installHints:[H(B,".gemini")],format:"json",serverMapKey:"mcpServers",entry:(z,Q)=>({httpUrl:z,headers:T(Q)})},{id:"zed",name:"Zed",configPath:H(B,".config","zed","settings.json"),installHints:[H(B,".config","zed"),"/Applications/Zed.app"],format:"json",serverMapKey:"context_servers",entry:(z,Q)=>({source:"custom",url:z,headers:T(Q)})},{id:"cline",name:"Cline",configPath:L("Code","User","globalStorage","saoudrizwan.claude-dev","settings","cline_mcp_settings.json"),installHints:[L("Code","User","globalStorage","saoudrizwan.claude-dev")],format:"json",serverMapKey:"mcpServers",entry:(z,Q)=>({type:"streamableHttp",url:z,headers:T(Q)})},{id:"roo",name:"Roo Code",configPath:L("Code","User","globalStorage","rooveterinaryinc.roo-cline","settings","mcp_settings.json"),installHints:[L("Code","User","globalStorage","rooveterinaryinc.roo-cline")],format:"json",serverMapKey:"mcpServers",entry:(z,Q)=>({type:"streamableHttp",url:z,headers:T(Q)})},{id:"witsy",name:"Witsy",configPath:L("Witsy","settings.json"),installHints:["/Applications/Witsy.app",L("Witsy")],format:"json",serverMapKey:"mcpServers",entry:(z,Q)=>({type:"http",url:z,headers:T(Q)})},{id:"amp",name:"Amp",configPath:L("amp","settings.json"),installHints:[L("amp"),H(B,".amp")],format:"json",serverMapKey:"amp.mcpServers",entry:(z,Q)=>({url:z,headers:T(Q)})},{id:"opencode",name:"OpenCode",configPath:H(B,".config","opencode","opencode.json"),installHints:[H(B,".config","opencode")],format:"json",serverMapKey:"mcp",entry:(z,Q)=>({type:"remote",url:z,enabled:!0,headers:T(Q)})},{id:"codex",name:"Codex CLI",configPath:H(B,".codex","config.toml"),installHints:[H(B,".codex")],format:"toml",serverMapKey:"mcp_servers",entry:(z)=>({url:z,bearer_token_env_var:"HIVEMIND_API_KEY"}),secretNote:"reads the key from $HIVEMIND_API_KEY — export it in your shell profile"}];function E(z,Q,X,$){let Z={},W=z.trim();if(W.length>0)try{let G=JSON.parse(W);if(G===null||typeof G!=="object"||Array.isArray(G))throw Error("config root is not an object");Z=G}catch(G){throw Error(`existing config is not valid JSON (${G instanceof Error?G.message:"parse error"})`)}let q=Z[Q],D=q&&typeof q==="object"&&!Array.isArray(q)?{...q}:{},J=Object.hasOwn(D,X);return D[X]=$,Z[Q]=D,{text:`${JSON.stringify(Z,null,2)}
|
|
3
|
+
`,replaced:J}}function x(z,Q,X){let $=`[mcp_servers.${Q}]`,Z=Object.entries(X).map(([G,O])=>`${G} = ${typeof O==="string"?JSON.stringify(O):String(O)}`).join(`
|
|
4
|
+
`),W=`${$}
|
|
5
|
+
${Z}
|
|
6
|
+
`,q=$.replace(/[.[\]]/g,"\\$&"),D=new RegExp(`^${q}[^\\[]*`,"m");if(D.test(z))return{text:z.replace(D,W),replaced:!0};let J=z.length===0||z.endsWith(`
|
|
7
|
+
|
|
8
|
+
`)?"":z.endsWith(`
|
|
9
|
+
`)?`
|
|
10
|
+
`:`
|
|
11
|
+
|
|
12
|
+
`;return{text:`${z}${J}${W}`,replaced:!1}}import{createHash as p,randomBytes as o}from"node:crypto";import{createServer as l}from"node:http";import{spawn as c}from"node:child_process";import{hostname as n,platform as j}from"node:os";var s=900000;function h(z){return z.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function t(z){let Q=j()==="darwin"?"open":j()==="win32"?"cmd":"xdg-open",X=j()==="win32"?["/c","start","",z]:[z];try{c(Q,X,{stdio:"ignore",detached:!0}).unref()}catch{}}var b=(z,Q)=>`<!doctype html><meta charset="utf-8"><title>Hivemind</title>
|
|
13
|
+
<style>body{margin:0;min-height:100vh;display:grid;place-items:center;
|
|
14
|
+
font:15px/1.6 ui-sans-serif,system-ui;background:#0b0f14;color:#e6edf3}
|
|
15
|
+
.c{text-align:center;padding:40px 48px;border:1px solid #1f2933;border-radius:14px;background:#111820}
|
|
16
|
+
.t{width:44px;height:44px;border-radius:50%;background:#0f2e2b;color:#4fd1c5;
|
|
17
|
+
display:grid;place-items:center;margin:0 auto 16px;font-size:22px}
|
|
18
|
+
p{margin:6px 0;color:#8b98a5}</style>
|
|
19
|
+
<div class="c"><div class="t">✓</div><strong>${z}</strong><p>${Q}</p></div>`;function S(z,Q,X){let $=h(o(48)),Z=h(p("sha256").update($).digest());return new Promise((W,q)=>{let D=l((C,P)=>{let I=new URL(C.url??"/","http://127.0.0.1");if(!I.pathname.startsWith("/callback")){P.writeHead(404).end();return}if(I.pathname==="/favicon.ico"){P.writeHead(204).end();return}let K=I.searchParams.get("code");if(!K){P.writeHead(400,{"content-type":"text/html"}),P.end(b("Sign-in failed","No authorization code was returned.")),O(Error("no code returned"));return}fetch(`${z}/auth/exchange`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({code:K,verifier:$,label:`cli@${n()}`.slice(0,60)})}).then(async(U)=>{let _=await U.json();if(!U.ok||!_.apiKey)throw Error(_.error??`exchange failed (${U.status})`);P.writeHead(200,{"content-type":"text/html"}),P.end(b("You're signed in","Return to your terminal — setup is continuing there.")),O(null,{apiKey:_.apiKey,email:_.email??null,userId:_.userId??""})}).catch((U)=>{P.writeHead(500,{"content-type":"text/html"}),P.end(b("Sign-in failed","Could not complete setup. Check your terminal.")),O(U)})}),J=!1,G=setTimeout(()=>O(Error("timed out waiting for sign-in")),s);function O(C,P){if(J)return;if(J=!0,clearTimeout(G),setTimeout(()=>{D.close(),D.closeAllConnections?.()},250),C)q(C);else W(P)}D.listen(0,"127.0.0.1",()=>{let C=D.address();if(C===null||typeof C==="string"){O(Error("could not open a local callback port"));return}let P=new URLSearchParams({challenge:Z,label:`loopback:${C.port}`}),I=Q?`${z}/auth/${Q}/start?${P}`:`${z}/signin?${P}`;X(I,`http://127.0.0.1:${C.port}/callback`),t(I)}),D.on("error",(C)=>O(C))})}var y="https://hivemind-api.hivemind-api.workers.dev/mcp",w="hivemind",Y={dim:(z)=>`\x1B[2m${z}\x1B[0m`,bold:(z)=>`\x1B[1m${z}\x1B[0m`,green:(z)=>`\x1B[32m${z}\x1B[0m`,yellow:(z)=>`\x1B[33m${z}\x1B[0m`,red:(z)=>`\x1B[31m${z}\x1B[0m`};function e(z){let X={command:z.some(($)=>$==="--help"||$==="-h")?"help":z[0]&&!z[0].startsWith("-")?z[0]:"init",url:process.env.HIVEMIND_URL??y,key:process.env.HIVEMIND_API_KEY,dryRun:!1};for(let $=0;$<z.length;$++){let Z=z[$];if(Z==="--key")X.key=z[++$];else if(Z==="--url")X.url=z[++$]??X.url;else if(Z==="--dry-run"||Z==="-n")X.dryRun=!0;else if(Z==="--only")X.only=(z[++$]??"").split(",").filter(Boolean);else if(Z==="--with")X.provider=z[++$]}return X}function R(z){if(F(z.configPath))return!0;return z.installHints.some((Q)=>F(Q))}function m(z){if(!z.viaCommand)return!1;return M(z.viaCommand.bin,z.viaCommand.probeArgs,{stdio:"ignore"}).status===0}function zz(z,Q,X,$){let Z=z.viaCommand;if($)return{client:z,status:"configured",detail:`dry run (${Z.bin})`};M(Z.bin,["mcp","remove","--scope","user",w],{stdio:"ignore"});let W=M(Z.bin,Z.args(Q,X,w),{stdio:["ignore","pipe","pipe"],encoding:"utf8"});if(W.status!==0)return{client:z,status:"failed",detail:(W.stderr||W.stdout||`${Z.bin} exited ${W.status}`).trim().split(`
|
|
20
|
+
`)[0]};return{client:z,status:"configured",detail:`via ${Z.bin}`}}function Qz(z,Q,X,$){if(m(z))return zz(z,Q,X,$);try{let Z=F(z.configPath)?N(z.configPath,"utf8"):"",W=z.entry(Q,X),q=z.format==="toml"?x(Z,w,W):E(Z,z.serverMapKey,w,W);if($)return{client:z,status:q.replaced?"updated":"configured",detail:"dry run"};if(i(r(z.configPath),{recursive:!0}),Z.length>0&&!F(`${z.configPath}.hivemind-bak`))a(z.configPath,`${z.configPath}.hivemind-bak`);return k(z.configPath,q.text,"utf8"),{client:z,status:q.replaced?"updated":"configured"}}catch(Z){return{client:z,status:"failed",detail:Z instanceof Error?Z.message:String(Z)}}}function Xz(z){return z.replace(/\/mcp\/?$/,"")}async function Yz(z){let Q=z.key;if(!Q){console.log(`
|
|
21
|
+
${Y.bold("Hivemind")} ${Y.dim(z.url)}
|
|
22
|
+
`),console.log(` Opening your browser to sign in…
|
|
23
|
+
`);try{let J=await S(Xz(z.url),z.provider??null,(G,O)=>{console.log(` ${Y.dim("If it did not open:")} ${G}
|
|
24
|
+
`),console.log(` ${Y.dim(`Waiting for the browser to return to ${O}`)}`),console.log(` ${Y.dim("This window must stay open. Ctrl-C to cancel.")}
|
|
25
|
+
`)});Q=J.apiKey,console.log(` ${Y.green("✓")} Signed in${J.email?` as ${Y.bold(J.email)}`:""}
|
|
26
|
+
`)}catch(J){let G=J instanceof Error?J.message:"sign-in failed";if(console.error(` ${Y.red("×")} ${G}
|
|
27
|
+
`),G.includes("timed out"))console.error(` ${Y.dim("The browser did not come back in time. If you saw a")}
|
|
28
|
+
${Y.dim('"connection refused" page, this window had already closed —')}
|
|
29
|
+
${Y.dim("run init again and finish signing in without leaving it.")}
|
|
30
|
+
`);return console.error(` ${Y.dim("Or use a key from the dashboard:")} hivemind init --key hm_live_...
|
|
31
|
+
`),1}}let X=A.filter((J)=>!z.only||z.only.includes(J.id)),$=X.filter(R);if($.length===0)return console.log(` No supported AI clients detected.
|
|
32
|
+
`),console.log(Y.dim(` Looked for: ${X.map((J)=>J.name).join(", ")}
|
|
33
|
+
`)),1;let Z=$.map((J)=>Qz(J,z.url,Q,z.dryRun));for(let J of Z){let G=J.status==="failed"?Y.red("×"):J.status==="updated"?Y.yellow("↻"):Y.green("✓"),O=J.status==="updated"?"updated":J.status,C=J.status!=="failed"&&J.detail?Y.dim(` ${J.detail}`):"";if(console.log(` ${G} ${J.client.name.padEnd(16)} ${Y.dim(O)}${C}`),J.detail&&J.status==="failed")console.log(` ${Y.red(J.detail)}`);if(J.client.secretNote)console.log(` ${Y.dim(J.client.secretNote)}`)}let W=X.filter((J)=>!$.includes(J));if(W.length>0)console.log(`
|
|
34
|
+
${Y.dim(`not installed: ${W.map((J)=>J.name).join(", ")}`)}`);let q=Z.filter((J)=>J.status==="failed").length,D=Z.length-q;if(z.dryRun)return console.log(`
|
|
35
|
+
${Y.dim(`dry run — ${D} client(s) would be configured`)}
|
|
36
|
+
`),0;return console.log(`
|
|
37
|
+
${D} client(s) configured${q>0?Y.red(`, ${q} failed`):""}.
|
|
38
|
+
${Y.dim("Restart them to pick up the change.")}
|
|
39
|
+
`),q>0?1:0}async function Zz(z,Q){if(!Q)return null;try{let X=await fetch(`${z.replace(/\/mcp$/,"")}/v3/me`,{headers:{Authorization:`Bearer ${Q}`}});if(!X.ok)return null;return(await X.json()).userId??null}catch{return null}}function v(z){return/hm_live_([A-Za-z0-9]{12})_/.exec(z)?.[1]??null}async function $z(z){console.log(`
|
|
40
|
+
${Y.bold("Hivemind")} — client status
|
|
41
|
+
`);let Q=await Zz(z.url,z.key);if(Q)console.log(` ${Y.dim(`account ${Q.slice(0,8)}`)}
|
|
42
|
+
`);for(let X of A){if(!R(X)){console.log(` ${Y.dim("–")} ${X.name.padEnd(16)} ${Y.dim("not installed")}`);continue}let $=!1,Z=null;try{let D=F(X.configPath)?N(X.configPath,"utf8"):"",J=X.format==="toml"?D.includes(`[mcp_servers.${w}]`)?D:"":JSON.stringify(JSON.parse(D||"{}")[X.serverMapKey]?.[w]??"");if($=Boolean(J&&J!=='""'),$)Z=v(J)}catch{$=!1}let W=Z&&z.key&&Z!==v(z.key),q=!$?"installed, not configured":W?`connected — DIFFERENT key (${Z})`:"connected";console.log(` ${$?W?Y.red("!"):Y.green("✓"):Y.yellow("○")} ${X.name.padEnd(16)} ${W?Y.red(q):Y.dim(q)}`)}return console.log(),0}function Jz(z){console.log(`
|
|
43
|
+
${Y.bold("Hivemind")} — removing from clients
|
|
44
|
+
`);let Q=0;for(let X of A){if(!R(X))continue;if(z.dryRun){if(F(X.configPath)&&N(X.configPath,"utf8").includes(w))console.log(` ${Y.yellow("○")} ${X.name.padEnd(16)} ${Y.dim("would be removed")}`),Q++;continue}if(m(X)){let $=X.viaCommand;if(M($.bin,["mcp","remove","--scope","user",w],{stdio:"ignore"}).status===0){console.log(` ${Y.green("✓")} ${X.name.padEnd(16)} ${Y.dim(`removed via ${$.bin}`)}`),Q++;continue}}if(!F(X.configPath))continue;try{let $=N(X.configPath,"utf8");if(X.format==="toml"){let Z=$.replace(new RegExp(`\\[mcp_servers\\.${w}\\][^\\[]*`,"g"),"");if(Z===$)continue;k(X.configPath,Z.trimStart(),"utf8")}else{let Z=JSON.parse($||"{}"),W=Z[X.serverMapKey];if(!W||!(w in W))continue;delete W[w],k(X.configPath,`${JSON.stringify(Z,null,2)}
|
|
45
|
+
`,"utf8")}console.log(` ${Y.green("✓")} ${X.name.padEnd(16)} ${Y.dim("removed")}`),Q++}catch($){console.log(` ${Y.red("×")} ${X.name.padEnd(16)} `+Y.red($ instanceof Error?$.message:"could not edit config"))}}if(z.dryRun)return console.log(`
|
|
46
|
+
${Y.dim(`dry run — ${Q} client(s) would be changed`)}
|
|
47
|
+
`),0;if(console.log(Q===0?`
|
|
48
|
+
${Y.dim("Nothing to remove.")}
|
|
49
|
+
`:`
|
|
50
|
+
Removed from ${Q} client(s). ${Y.dim("Restart them to pick up the change.")}
|
|
51
|
+
`),z.key)console.log(` ${Y.dim("Your API key is still valid — revoke it in the dashboard to end access.")}
|
|
52
|
+
`);return 0}function Wz(){return console.log(`
|
|
53
|
+
${Y.bold("hivemind")} — one memory across every AI tool
|
|
54
|
+
|
|
55
|
+
${Y.bold("init")} sign in and configure all detected clients
|
|
56
|
+
${Y.bold("status")} show which clients are connected
|
|
57
|
+
${Y.bold("signout")} remove Hivemind from every configured client
|
|
58
|
+
|
|
59
|
+
--with <p> sign in with a provider directly: google, github
|
|
60
|
+
--key <k> use an existing API key instead of signing in
|
|
61
|
+
--url <u> MCP endpoint (default: ${y})
|
|
62
|
+
--only a,b restrict to specific client ids
|
|
63
|
+
--dry-run show what would change, write nothing
|
|
64
|
+
|
|
65
|
+
${Y.dim(`clients: ${A.map((z)=>z.id).join(", ")}`)}
|
|
66
|
+
`),0}var V=e(process.argv.slice(2)),qz=V.command==="init"?await Yz(V):V.command==="status"?await $z(V):V.command==="signout"?Jz(V):Wz();process.exit(qz);
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hivemind-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "One memory across every AI tool. Signs in through your browser and configures every MCP client on your machine.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"hivemind": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"model-context-protocol",
|
|
20
|
+
"ai",
|
|
21
|
+
"memory",
|
|
22
|
+
"context",
|
|
23
|
+
"claude",
|
|
24
|
+
"cursor",
|
|
25
|
+
"llm"
|
|
26
|
+
],
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/0xadityaa/hivemind.git",
|
|
30
|
+
"directory": "cli"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "bun build src/index.ts --outdir dist --target node --format esm --minify && chmod +x dist/index.js",
|
|
34
|
+
"prepublishOnly": "bun run build",
|
|
35
|
+
"test": "bun test"
|
|
36
|
+
}
|
|
37
|
+
}
|