@join-pantheon/cli 0.19.0 → 0.19.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.
Files changed (3) hide show
  1. package/README.md +51 -27
  2. package/dist/relay.js +42 -1
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -28,8 +28,7 @@ npm install -g @join-pantheon/cli
28
28
  Or run it without installing at all:
29
29
 
30
30
  ```bash
31
- npx @join-pantheon/cli start # you
32
- npx @join-pantheon/cli join <invite> # them
31
+ npx @join-pantheon/cli # guided sign-in; it tells you what to run next
33
32
  ```
34
33
 
35
34
  **First, verify your email (once per person):**
@@ -121,7 +120,7 @@ internet, and whether you were actually admitted. Non-zero exit means don't star
121
120
  <details><summary>The long way round, if you want to control each piece</summary>
122
121
 
123
122
  `pantheon relay` · `pantheon init` · `pantheon join` · `pantheon members` · `pantheon admit <who> --may-wake`
124
- · `pantheon install` (project-scope, needs `npm link` and a commit). Membership by explicit
123
+ · `pantheon install` (project-scope: commits a `.mcp.json`, so `pantheon` must be on PATH). Membership by explicit
125
124
  allowlist with fingerprint confirmation, rather than by invite. Everything the two-command path
126
125
  does, one step at a time.
127
126
 
@@ -229,7 +228,7 @@ Human decisions use a separate, model-free path. `ESCALATE` creates a durable
229
228
  ```sh
230
229
  pantheon service install notifier # starts at login; no wake permission needed
231
230
  pantheon profile set --surface codex # codex | claude-code | cursor
232
- pantheon profile set --name "Praneet" --title "Co-founder & CEO" \
231
+ pantheon profile set --name "Alex" --title "Head of Product" \
233
232
  --responsibilities product-ui,gtm,marketing \
234
233
  --human-required product-ui,gtm,marketing
235
234
  pantheon directory # shared responsibility and authority graph
@@ -256,7 +255,8 @@ local. Before a consequential decision, agents call `pantheon_route_decision`
256
255
  with explicit domains. Matching `human_required` owners receive separate
257
256
  `HUMAN_REQUIRED` acts; matching `agent_can_decide` owners may answer through
258
257
  their delegate. Missing authority fails closed and escalates to the caller's
259
- human. See [Pantheon / Pantheon V1 acceptance](docs/PANTHEON_V1_ACCEPTANCE.md).
258
+ human. The security model is written up at
259
+ [joinpantheon.network/security](https://www.joinpantheon.network/security).
260
260
 
261
261
  Delegation is one hop, time-bounded, and preserves the original authority
262
262
  level: a human-only decision cannot become agent-decidable through delegation.
@@ -319,7 +319,7 @@ dead air on an unattended machine. And the worker finally says what it is doing:
319
319
  and cap refusal is logged with its reason, and `worker-state.json` feeds the same line to
320
320
  `pantheon ps` and the menu bar.
321
321
 
322
- Proven by team-shaped tests (`team-flow.test.ts`): a full unattended round trip where the asking
322
+ Proven by end-to-end tests with real workers and a real relay: a full unattended round trip where the asking
323
323
  session closes before the reply and both workers finish the goal anyway; deliver→review→accept
324
324
  with no human; the cap and lock governors under two workers per member.
325
325
 
@@ -335,12 +335,11 @@ the same "no shell unless you said so" rule spelled in its own dialect:
335
335
  | codex | `--sandbox read-only` (codex has no edits-without-shell mode) | `--sandbox workspace-write` |
336
336
  | cursor | proposes edits, never applies (`-p` without `--force`) | `--force` |
337
337
 
338
- Claude Code and Cursor are verified with **real live woken runs** (see `live-smoke.test.ts`;
339
- `PANTHEON_LIVE_SMOKE=1 PANTHEON_LIVE_BACKEND=cursor …`). The codex invocation is built against the
340
- verified `codex exec` surface but has not yet run against a real codex install smoke it on a
341
- machine that has one before leaning on it. Note codex quirks the tooling handles for you: no
342
- per-run approval flag exists in exec, MCP arrives via `-c` overrides (a worktree `.codex/` is
343
- ignored), and codex silently skips a newly installed hook until you approve it with `/hooks`.
338
+ All three backends are verified with **real live woken runs** an idle machine answering a
339
+ peer's ASK end to end with Claude Code, Cursor, and Codex. Codex quirks the tooling handles for
340
+ you: no per-run approval flag exists in `codex exec`, MCP arrives via `-c` overrides (a worktree
341
+ `.codex/` is ignored), and codex silently skips a newly installed hook until you approve it with
342
+ `/hooks`.
344
343
 
345
344
  ### Personas — telling the worker who to be
346
345
 
@@ -408,19 +407,25 @@ on each laptop; what crosses the wire is acts, contracts, diff summaries and dec
408
407
  ## Commands
409
408
 
410
409
  ```
411
- pantheon relay run the coordination plane
412
- pantheon init claim a space, print an invite
413
- pantheon join join a colleague's space
414
- pantheon install wire the MCP server into claude code / cursor / conductor here
415
- pantheon status who's online, open goals, what you owe
416
- pantheon watch live tail of everything the delegates say to each other
417
- pantheon persona list / init / show what a woken worker may do and how it behaves
418
- pantheon say send an act by hand (kick things off, or debug)
419
- pantheon mcp the stdio MCP serveryour agent runs this, not you
410
+ pantheon signup / verify / login verify your email once; sign a second machine in
411
+ pantheon start create your team on the hosted relay, get the line to send
412
+ pantheon join <line> join a teammate's team from their line
413
+ pantheon invite another single-use line (third person, second machine)
414
+ pantheon status · brief · team who is here, what needs you, who is in the space
415
+ pantheon watch live tail of everything the delegates say to each other
416
+ pantheon doctor preflight: node, keys, MCP entry, relay, membership
417
+ pantheon worker / service stay answerable while you are away (install as a service)
418
+ pantheon persona list / init / show what a woken worker may do
419
+ pantheon sessions · logout your devices and sessions; sign this machine out
420
+ pantheon account delete remove your account and everything the relay holds on you
421
+ pantheon upgrade pull the latest release and re-wire your agents
422
+ pantheon relay run your own relay (self-hosting)
423
+ pantheon mcp the stdio MCP server — your agent runs this, not you
420
424
  ```
421
425
 
422
- `pantheon watch` is how a human stays oriented without being in the loop. Every act is also
423
- appended to `pantheon-data/<space>.jsonl`, so the full history is replayable with `tail`.
426
+ `pantheon help --all` lists everything. `pantheon watch` is how a human stays oriented without
427
+ being in the loop; every act is also appended to the relay's ledger, so the full history is
428
+ replayable.
424
429
 
425
430
  ## What this still is not
426
431
 
@@ -436,10 +441,29 @@ appended to `pantheon-data/<space>.jsonl`, so the full history is replayable wit
436
441
  - **A woken run is trusted with your repo.** `--allow-bash` in particular means a peer's request
437
442
  can execute commands on your machine. Grant `--may-wake` deliberately.
438
443
 
439
- ## Tests
444
+ ## Privacy, data, and support
445
+
446
+ The hosted relay at `relay.joinpantheon.network` holds only what coordination needs: your
447
+ verified email, username, and device public keys; the IPs and timestamps of your sessions and
448
+ an audit trail of identity and membership events; and, per space, the acts your delegates
449
+ exchanged plus open goals and obligations. Your code, credentials, and repo never leave your
450
+ machine — the relay has no filesystem or shell access by design.
451
+
452
+ - `pantheon sessions` shows every device and session on your account; `revoke` signs one out.
453
+ - `pantheon audit` is your own trail; `pantheon account delete` removes your account, devices,
454
+ sessions, and memberships.
455
+ - Prefer to run your own? `pantheon relay` is the whole server; point machines at it with
456
+ `pantheon start --relay wss://your-host`. Accounts are optional there.
457
+
458
+ Security details and how to report a vulnerability:
459
+ [joinpantheon.network/security](https://www.joinpantheon.network/security). Everything else:
460
+ [joinpantheon.network](https://www.joinpantheon.network).
461
+
462
+ ## Upgrading
440
463
 
441
464
  ```bash
442
- npm run build
443
- node --test dist/test/fabric.test.js # protocol, obligations, guards, auth, claims, durability
444
- node --test dist/test/mcp.test.js # real stdio JSON-RPC against the MCP server
465
+ pantheon upgrade # installs the latest release and re-wires your agents
445
466
  ```
467
+
468
+ Every command prints its version and nudges you when a newer release exists. Restart your agent
469
+ session after upgrading so it loads the new MCP server.
package/dist/relay.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createServer } from "node:http";
2
2
  import { createHash, randomBytes, timingSafeEqual as timingSafeEqualBuf } from "node:crypto";
3
3
  import { rmSync } from "node:fs";
4
+ import { spawn } from "node:child_process";
4
5
  import { join } from "node:path";
5
6
  import { WebSocketServer } from "ws";
6
7
  import { badRemote, Inbound, isContinuationFor, LIMITS, newId, PROTOCOL_VERSION, SENDABLE, shouldDeferToHuman, } from "./protocol.js";
@@ -275,7 +276,7 @@ export class Relay {
275
276
  onAuthHttp(req, res, url, ip) {
276
277
  if (url.pathname === "/")
277
278
  return this.landingPage(res);
278
- if (url.pathname === "/admin" || url.pathname === "/admin/export" || url.pathname === "/admin/login" || url.pathname === "/admin/logout") {
279
+ if (url.pathname === "/admin" || url.pathname === "/admin/export" || url.pathname === "/admin/backup" || url.pathname === "/admin/login" || url.pathname === "/admin/logout") {
279
280
  const A0 = this.accounts;
280
281
  if (!A0 || !this.adminToken)
281
282
  return this.json(res, 404, { error: "not found" });
@@ -307,6 +308,11 @@ export class Relay {
307
308
  return this.json(res, 403, { error: "sign in at /admin, or append ?token=…" });
308
309
  return this.adminExport(res, A0, url);
309
310
  }
311
+ if (url.pathname === "/admin/backup") {
312
+ if (!authed)
313
+ return this.json(res, 403, { error: "sign in at /admin, or append ?token=…" });
314
+ return this.adminBackup(res, A0);
315
+ }
310
316
  if (!authed)
311
317
  return this.adminLoginPage(res, false);
312
318
  return this.adminDashboard(res, A0);
@@ -646,6 +652,41 @@ button{width:100%;margin-top:12px;padding:10px;border:0;border-radius:8px;backgr
646
652
  res.writeHead(200, { "content-type": "text/csv", "content-disposition": `attachment; filename="${table}.csv"` });
647
653
  res.end(csv);
648
654
  }
655
+ adminBackup(res, A) {
656
+ try {
657
+ A.backup(join(this.dataDir, "backups"));
658
+ }
659
+ catch (e) {
660
+ this.log(`! backup snapshot before archive failed: ${e.message}`);
661
+ }
662
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
663
+ const tar = spawn("tar", ["czf", "-", "-C", this.dataDir, "."], { stdio: ["ignore", "pipe", "pipe"] });
664
+ let err = "";
665
+ tar.stderr.on("data", (c) => { err += String(c); });
666
+ tar.on("error", (e) => {
667
+ this.log(`! backup archive failed to start: ${e.message}`);
668
+ if (!res.headersSent)
669
+ this.json(res, 500, { error: `could not start tar: ${e.message}` });
670
+ });
671
+ tar.stdout.once("data", () => {
672
+ if (!res.headersSent) {
673
+ res.writeHead(200, { "content-type": "application/gzip", "content-disposition": `attachment; filename="pantheon-data-${stamp}.tgz"` });
674
+ }
675
+ });
676
+ tar.stdout.pipe(res);
677
+ tar.on("close", (code) => {
678
+ if (code !== 0) {
679
+ this.log(`! backup archive exited ${code}: ${err.trim()}`);
680
+ if (!res.headersSent)
681
+ this.json(res, 500, { error: `tar exited ${code}` });
682
+ }
683
+ res.end();
684
+ });
685
+ res.on("close", () => { try {
686
+ tar.kill();
687
+ }
688
+ catch { } });
689
+ }
649
690
  landingPage(res) {
650
691
  res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
651
692
  res.end(`<!doctype html><meta charset=utf-8><title>pantheon</title>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@join-pantheon/cli",
3
- "version": "0.19.0",
3
+ "version": "0.19.1",
4
4
  "description": "Let your coding agent collaborate directly with your teammates' agents — ask, agree an interface, and deliver, without a human relaying messages.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,9 +37,9 @@
37
37
  "README.md",
38
38
  "LICENSE"
39
39
  ],
40
- "repository": {
41
- "type": "git",
42
- "url": "git+https://github.com/guptasiddharth/agents-pantheon.git"
40
+ "homepage": "https://www.joinpantheon.network",
41
+ "bugs": {
42
+ "url": "https://www.joinpantheon.network/security"
43
43
  },
44
44
  "license": "MIT",
45
45
  "keywords": [