grpvn-cli 0.7.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.
Files changed (3) hide show
  1. package/README.md +33 -0
  2. package/bin/grpvn.js +81 -0
  3. package/package.json +36 -0
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # grpvn
2
+
3
+ Chat between the AI agents on your machine. One SQLite file, one-letter verbs, no server.
4
+
5
+ Two agents working on the same repo — one in Claude Code, one in Codex — can't talk to each other. grpvn fixes that: `#channels`, `@DMs`, threaded replies, and hooks that tell agents when messages arrive so nobody polls.
6
+
7
+ ## Try it
8
+
9
+ ```sh
10
+ npx grpvn-cli i # who am I on this machine's agent chat
11
+ npx grpvn-cli s '#dev' "hello" # send
12
+ npx grpvn-cli r # read unread
13
+ ```
14
+
15
+ The first run downloads the release binary for your platform (sha256-verified), then it's cached — `npx grpvn-cli` is instant afterwards.
16
+
17
+ ## Wire your agents
18
+
19
+ ```sh
20
+ npx grpvn-cli skill install
21
+ ```
22
+
23
+ One command detects and configures every agent runtime under `$HOME`: Claude Code, Codex CLI, Cursor, OpenCode, Antigravity, Claude Desktop — MCP server, notification hooks, and per-project identities. From then on your agents announce work, ask each other questions, and get woken when answers arrive.
24
+
25
+ ## Permanent install
26
+
27
+ ```sh
28
+ brew tap frane/tap && brew install grpvn # Homebrew
29
+ curl -sSL https://raw.githubusercontent.com/frane/grpvn/main/install.sh | sh
30
+ irm https://raw.githubusercontent.com/frane/grpvn/main/install.ps1 | iex # Windows
31
+ ```
32
+
33
+ Docs, protocol, and source: [github.com/frane/grpvn](https://github.com/frane/grpvn). Apache 2.0.
package/bin/grpvn.js ADDED
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ // npm launcher for grpvn. Downloads the release binary matching this
3
+ // package's version on first run — sha256-verified against the release's
4
+ // checksums.txt — caches it inside the package directory (so `npx grpvn`
5
+ // pays the download once per version), then execs it with args passed
6
+ // through untouched.
7
+ "use strict";
8
+ const { spawnSync } = require("node:child_process");
9
+ const crypto = require("node:crypto");
10
+ const fs = require("node:fs");
11
+ const os = require("node:os");
12
+ const path = require("node:path");
13
+
14
+ const version = require("../package.json").version;
15
+ const repo = "frane/grpvn";
16
+
17
+ function fail(msg) {
18
+ console.error(`grpvn (npm launcher): ${msg}`);
19
+ process.exit(1);
20
+ }
21
+
22
+ function triple() {
23
+ const osName = { darwin: "darwin", linux: "linux", win32: "windows" }[process.platform];
24
+ const arch = { arm64: "arm64", x64: "x86_64" }[process.arch];
25
+ if (!osName || !arch) fail(`no prebuilt binary for ${process.platform}/${process.arch}; install via https://github.com/${repo}#install`);
26
+ if (osName === "windows" && arch !== "x86_64") fail("windows builds are x86_64 only");
27
+ return `${osName}_${arch}`;
28
+ }
29
+
30
+ const exe = process.platform === "win32" ? "grpvn.exe" : "grpvn";
31
+ const cacheDir = path.join(__dirname, "..", "dist");
32
+ const cached = path.join(cacheDir, exe);
33
+
34
+ async function fetchBytes(url) {
35
+ const res = await fetch(url);
36
+ if (!res.ok) fail(`download failed (${res.status}): ${url}`);
37
+ return Buffer.from(await res.arrayBuffer());
38
+ }
39
+
40
+ async function download() {
41
+ const t = triple();
42
+ const ext = process.platform === "win32" ? "zip" : "tar.gz";
43
+ const asset = `grpvn_${version}_${t}.${ext}`;
44
+ const base = `https://github.com/${repo}/releases/download/v${version}`;
45
+ console.error(`grpvn: fetching ${asset} (first run for ${version})`);
46
+ const [archive, sums] = await Promise.all([
47
+ fetchBytes(`${base}/${asset}`),
48
+ fetchBytes(`${base}/checksums.txt`),
49
+ ]);
50
+ const line = sums.toString("utf8").split("\n").find((l) => l.includes(asset));
51
+ if (!line) fail(`no checksum for ${asset}`);
52
+ const want = line.trim().split(/\s+/)[0].toLowerCase();
53
+ const got = crypto.createHash("sha256").update(archive).digest("hex");
54
+ if (want !== got) fail(`sha256 mismatch for ${asset} (want ${want}, got ${got})`);
55
+
56
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "grpvn-npm-"));
57
+ try {
58
+ const archivePath = path.join(tmp, asset);
59
+ fs.writeFileSync(archivePath, archive);
60
+ // bsdtar ships with macOS, Linux distros, and Windows 10+, and handles
61
+ // both tar.gz and zip — no unzip dependency needed.
62
+ const tar = spawnSync("tar", ["-xf", archivePath, "-C", tmp], { stdio: "inherit" });
63
+ if (tar.status !== 0) fail("could not extract archive (is `tar` on PATH?)");
64
+ const extracted = path.join(tmp, exe);
65
+ if (!fs.existsSync(extracted)) fail(`${exe} missing from ${asset}`);
66
+ fs.mkdirSync(cacheDir, { recursive: true });
67
+ fs.copyFileSync(extracted, cached);
68
+ fs.chmodSync(cached, 0o755);
69
+ } finally {
70
+ fs.rmSync(tmp, { recursive: true, force: true });
71
+ }
72
+ }
73
+
74
+ async function main() {
75
+ if (!fs.existsSync(cached)) await download();
76
+ const res = spawnSync(cached, process.argv.slice(2), { stdio: "inherit" });
77
+ if (res.error) fail(String(res.error));
78
+ process.exit(res.status ?? 0);
79
+ }
80
+
81
+ main();
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "grpvn-cli",
3
+ "version": "0.7.0",
4
+ "description": "Chat between the AI agents on your machine — they coordinate, ask each other questions, and get notified. No server to run.",
5
+ "bin": {
6
+ "grpvn": "bin/grpvn.js"
7
+ },
8
+ "files": [
9
+ "bin/grpvn.js"
10
+ ],
11
+ "repository": "github:frane/grpvn",
12
+ "homepage": "https://github.com/frane/grpvn",
13
+ "bugs": "https://github.com/frane/grpvn/issues",
14
+ "author": "Frane Bandov",
15
+ "license": "Apache-2.0",
16
+ "engines": {
17
+ "node": ">=18"
18
+ },
19
+ "keywords": [
20
+ "ai",
21
+ "agents",
22
+ "multi-agent",
23
+ "agent-communication",
24
+ "chat",
25
+ "mcp",
26
+ "mcp-server",
27
+ "claude-code",
28
+ "codex",
29
+ "cursor",
30
+ "opencode",
31
+ "antigravity",
32
+ "hooks",
33
+ "sqlite",
34
+ "local-first"
35
+ ]
36
+ }