@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.
- package/README.md +51 -27
- package/dist/relay.js +42 -1
- 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
|
|
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
|
|
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 "
|
|
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.
|
|
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
|
|
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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
|
412
|
-
pantheon
|
|
413
|
-
pantheon join
|
|
414
|
-
pantheon
|
|
415
|
-
pantheon status who
|
|
416
|
-
pantheon watch
|
|
417
|
-
pantheon
|
|
418
|
-
pantheon
|
|
419
|
-
pantheon
|
|
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
|
|
423
|
-
appended to
|
|
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
|
-
##
|
|
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
|
-
|
|
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.
|
|
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
|
-
"
|
|
41
|
-
|
|
42
|
-
"url": "
|
|
40
|
+
"homepage": "https://www.joinpantheon.network",
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://www.joinpantheon.network/security"
|
|
43
43
|
},
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"keywords": [
|