agent-pager 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
@@ -2,19 +2,11 @@
2
2
 
3
3
  **Because people ignore their messages, but not their agents.**
4
4
 
5
- Agent Pager is a secure friend network for paging trusted friends through their active coding agent sessions. The current repo contains the local prototype plus the hosted V1 foundation: Supabase schema/auth/realtime setup, typed database client helpers, safe Vercel config, MCP tools, Codex/Claude skills, and a retro Authorized Human Contact Service web app.
5
+ Agent Pager lets trusted friends page your local Codex or Claude agent session. Public links can request access, but only approved friends can send pages. Messages are text-only, device-signed, friend-gated, and rate-limited.
6
6
 
7
- Production V1 is deployed at:
7
+ Web app: https://agent-pager.vercel.app
8
8
 
9
- ```text
10
- https://agent-pager.vercel.app
11
- ```
12
-
13
- Current launch status: GitHub, Supabase, Vercel production, and the npm CLI package are live.
14
-
15
- ## Quickstart
16
-
17
- Install the CLI:
9
+ ## Install
18
10
 
19
11
  ```bash
20
12
  npm install -g agent-pager
@@ -22,148 +14,62 @@ agent-pager login
22
14
  agent-pager start
23
15
  ```
24
16
 
25
- Local prototype:
17
+ `agent-pager login` opens a device-pairing flow. Approve the device in the web app, then keep `agent-pager start` running to receive pages.
26
18
 
27
- Terminal 1:
19
+ ## First Run
28
20
 
29
- ```bash
30
- npm install
31
- npm run build
32
- npm start
33
- ```
21
+ 1. Create an account at https://agent-pager.vercel.app.
22
+ 2. Run `agent-pager login` on the machine where your coding agent runs.
23
+ 3. Approve the pairing code in the web app.
24
+ 4. Run `agent-pager start`.
25
+ 5. Optional: run `agent-pager setup codex` or `agent-pager setup claude`.
34
26
 
35
- Terminal 2:
27
+ ## Share
36
28
 
37
29
  ```bash
38
- node dist/src/cli.js login --username bryson --local-dev
39
- node dist/src/cli.js start
30
+ agent-pager share
40
31
  ```
41
32
 
42
- Terminal 3, pretending to be a friend:
33
+ Your share link lets people request access. It does not let strangers page you. You approve or deny friend requests before any pages can be delivered.
43
34
 
44
- ```bash
45
- AGENT_PAGER_HOME=/tmp/agent-pager-sarah node dist/src/cli.js login --username sarah --local-dev
46
- node dist/src/cli.js friends invite
47
- AGENT_PAGER_HOME=/tmp/agent-pager-sarah node dist/src/cli.js friends add <bryson-invite-url>
48
- AGENT_PAGER_HOME=/tmp/agent-pager-sarah node dist/src/cli.js page bryson "Can you check the PR?"
49
- ```
50
-
51
- Open the web app:
52
-
53
- ```text
54
- http://127.0.0.1:8787
55
- ```
56
-
57
- Hosted V1 foundation:
35
+ ## Agent Tools
58
36
 
59
37
  ```bash
60
- npm run db:start
61
- npm run db:types:local
62
- npm run check
63
- npm run test:doctor
64
- npm run test:config
65
- npm run build
66
- npm run test:web
67
- npm run test:mcp
68
- npm run test:smoke
69
- npm run test:package
70
- npm run test:hosted
38
+ agent-pager setup codex
39
+ agent-pager setup claude
40
+ agent-pager mcp
71
41
  ```
72
42
 
73
- The hosted foundation includes Vercel-compatible API handlers under `/api` for public config, profiles, public profile links, friend requests, secure device pairing, devices, invites, friends, pages, deliveries, abuse reports, audit events, presence, and health. The retro web app uses Supabase Auth plus those hosted APIs for profile setup, `Page my agent` request-access links, friend invites, page compose/history, report filing, device approvals, and security logs. The tests are local-only and do not push to Supabase cloud or deploy to Vercel.
74
-
75
- `agent-pager doctor` is a local-only readiness check for the hosted V1. It verifies the npm package manifest, Vercel Git deployment guard, required environment variables, server signing keypair, local pairing state, Git remote/status, Docker runtime, and cloud-smoke gate without linking Supabase, pushing Git, publishing npm, or deploying Vercel.
76
-
77
- `agent-pager launch-check` is the live hosted preflight. It reads GitHub, Supabase, and Vercel state to confirm repo, schema, project, and env readiness before a manual preview deployment.
78
-
79
- `agent-pager login` now uses secure hosted device pairing by default. The old local prototype login is still available with `--username` / `--local-dev`.
80
-
81
- `agent-pager start` uses Supabase Realtime as the fast path and a signed HTTP polling fallback while it is running. `agent-pager check-pages` remains available for manual recovery or debugging.
82
-
83
- The npm package ships the built CLI plus bundled retro web assets. `npm run test:package` dry-runs `npm pack` and verifies the package contents.
43
+ The setup commands install local instructions and MCP wiring so agents know how to list friends, send pages, reply, review friend requests, mute/block users, and avoid abusing the pager.
84
44
 
85
- After an approved Vercel/Supabase deployment, `npm run cloud-smoke:run -- <vercel-url>` can verify the real hosted flow. The underlying cloud test skips by default and only touches hosted resources when `AGENT_PAGER_CLOUD_SMOKE=1` plus the smoke user credentials are set.
86
-
87
- ## Commands
45
+ ## Useful Commands
88
46
 
89
47
  ```bash
90
- agent-pager server
91
- agent-pager login
92
- agent-pager login --username bryson --local-dev
93
- agent-pager start
94
48
  agent-pager status
95
- agent-pager share
96
- agent-pager doctor
97
- agent-pager launch-check
98
- agent-pager settings quiet-hours on --start 22:00 --end 08:00 --timezone America/Denver
99
- agent-pager settings quiet-hours off
100
- agent-pager settings rate-limit 8
101
- agent-pager devices list
102
- agent-pager devices revoke <device-id>
103
- agent-pager logout
104
- agent-pager page sarah "Can you review this?"
105
- agent-pager mute sarah --for 1h
106
- agent-pager unmute sarah
107
- agent-pager mutes list
108
- agent-pager block sarah
109
- agent-pager unblock sarah
110
- agent-pager blocks list
111
- agent-pager report sarah --reason spam
112
- agent-pager report --page-id <page-id> --reason spam
113
- agent-pager reports list
114
- agent-pager friends invite
115
- agent-pager friends invites
116
- agent-pager friends revoke-invite <invite-url-or-code>
117
- agent-pager friends add <invite-url-or-code>
118
- agent-pager friends request sarah "Page my agent?"
119
49
  agent-pager friends requests
120
50
  agent-pager friends approve <request-id>
121
51
  agent-pager friends deny <request-id>
122
- agent-pager friends cancel <request-id>
123
52
  agent-pager friends list
124
- agent-pager friends remove <username>
125
- agent-pager check-pages
126
- agent-pager setup codex
127
- agent-pager setup claude
128
- agent-pager mcp
53
+ agent-pager page <friend> "Can you check the PR?"
54
+ agent-pager mute <friend> --for 1h
55
+ agent-pager devices list
56
+ agent-pager devices revoke <device-id>
57
+ agent-pager logout
129
58
  ```
130
59
 
131
- ## Security Model
60
+ ## Security
132
61
 
133
62
  - Devices generate local Ed25519 keypairs.
134
- - The service stores public keys only.
63
+ - The hosted service stores public keys only.
135
64
  - Device requests are signed with timestamped canonical request signatures.
136
- - Devices can be revoked from the web dashboard or CLI; revoked devices cannot sign future requests.
137
- - Page delivery envelopes are signed by the server and verified locally.
138
- - Pages deliver only between approved friends.
139
- - Approved friendships can be removed without blocking; removed friends cannot page unless friendship is approved again.
140
- - Public profiles do not allow arbitrary pages.
141
- - Pending friend requests can be approved, denied, or canceled before they grant access.
142
- - Messages are text-only; Agent Pager never lets a remote friend run commands.
143
- - Per-friend mutes block delivery before a page reaches a local session and can be listed or removed.
144
- - Blocks prevent friend requests, invite acceptance, approvals, and pages in either direction.
145
- - Abuse reports can target a username or a page the reporter participated in.
146
- - Quiet hours block delivery before page rows are created.
147
- - Invite links expire and can be revoked before use.
148
- - Rate limits and message length limits protect against spam.
149
- - Hosted V1 uses Supabase RLS policies and realtime delivery rows instead of exposing raw session lists.
150
-
151
- ## Agent Integration
152
-
153
- `agent-pager setup codex` installs:
154
-
155
- - a Codex skill at `~/.codex/skills/agent-pager/SKILL.md`
156
- - an MCP config block for `agent-pager mcp`
157
-
158
- `agent-pager setup claude` installs:
159
-
160
- - a Claude skill at `~/.claude/skills/agent-pager/SKILL.md`
161
- - setup instructions for `claude mcp add agent-pager -- agent-pager mcp`
162
-
163
- The MCP server exposes paging, replies, presence, Page my agent sharing, friend-request review, muting, blocking, removal, and abuse-report tools with explicit human-intent wording for access-changing actions.
164
-
165
- Claude Code channels are the best future path for true push into an already-running Claude session. The current local listener already receives signed pages, persists them, and sends desktop notifications.
65
+ - Delivery envelopes are signed by the server and verified locally.
66
+ - Pages only deliver between approved friends.
67
+ - Public profile links create friend requests, not unrestricted messages.
68
+ - Incoming pages are text-only. Agent Pager does not allow remote command execution.
69
+ - Mutes, blocks, quiet hours, message limits, and per-friend rate limits are enforced before delivery.
70
+ - Devices can be revoked from the web app or CLI.
71
+ - Friends see limited presence only; raw local agent sessions are not exposed.
166
72
 
167
- ## Design
73
+ ## Notes
168
74
 
169
- The web app is inspired by retro authorized-service computing artwork: warm paper, chunky panels, rainbow service stripe, compact operator-console layout, and original Agent Pager branding. It intentionally avoids Apple logos or trademarks.
75
+ Agent Pager is experimental. Treat it like an early access tool: only approve people you trust, keep the CLI updated, and revoke devices you no longer use.
package/dist/src/cli.js CHANGED
@@ -13,6 +13,8 @@ import { statusBox } from "./render.js";
13
13
  import { runServer } from "./server.js";
14
14
  import { setupClaude, setupCodex } from "./setup.js";
15
15
  const DEFAULT_HOSTED_POLL_INTERVAL_MS = 30_000;
16
+ const DEFAULT_HOSTED_SERVER_URL = "https://agent-pager.vercel.app";
17
+ const DEFAULT_LOCAL_SERVER_URL = "http://127.0.0.1:8787";
16
18
  const EXPECTED_GITHUB_REPO = "brysonkbarney/agent-pager";
17
19
  const EXPECTED_SUPABASE_REF = "ghwzvpuggpqntowmbpih";
18
20
  const EXPECTED_VERCEL_PROJECT = "agent-pager";
@@ -112,7 +114,7 @@ async function login(args) {
112
114
  await localDevLogin(args);
113
115
  return;
114
116
  }
115
- const serverUrl = (readFlag(args, "--server") || process.env.AGENT_PAGER_SERVER_URL || "http://127.0.0.1:8787").replace(/\/+$/, "");
117
+ const serverUrl = (readFlag(args, "--server") || process.env.AGENT_PAGER_SERVER_URL || DEFAULT_HOSTED_SERVER_URL).replace(/\/+$/, "");
116
118
  const deviceName = readFlag(args, "--device") || `${process.env.USER || "local"}@${process.env.HOSTNAME || "mac"}`;
117
119
  const timeoutSeconds = Number(readFlag(args, "--timeout") || 600);
118
120
  const keys = createDeviceKeyPair();
@@ -120,7 +122,7 @@ async function login(args) {
120
122
  name: deviceName,
121
123
  publicKeyPem: keys.publicKeyPem,
122
124
  platform: process.platform,
123
- appVersion: "0.1.0"
125
+ appVersion: "0.1.1"
124
126
  });
125
127
  console.log(statusBox({
126
128
  Pairing: pairing.code,
@@ -153,7 +155,7 @@ async function login(args) {
153
155
  }));
154
156
  }
155
157
  async function localDevLogin(args) {
156
- const serverUrl = (readFlag(args, "--server") || process.env.AGENT_PAGER_SERVER_URL || "http://127.0.0.1:8787").replace(/\/+$/, "");
158
+ const serverUrl = (readFlag(args, "--server") || process.env.AGENT_PAGER_SERVER_URL || DEFAULT_LOCAL_SERVER_URL).replace(/\/+$/, "");
157
159
  let username = readFlag(args, "--username");
158
160
  let displayName = readFlag(args, "--name");
159
161
  if (!username) {
@@ -1067,7 +1069,7 @@ Because people ignore their messages, but not their agents.
1067
1069
 
1068
1070
  Usage:
1069
1071
  agent-pager server [--host 127.0.0.1] [--port 8787]
1070
- agent-pager login [--server https://agentpager.dev]
1072
+ agent-pager login [--server https://agent-pager.vercel.app]
1071
1073
  agent-pager login --username bryson [--local-dev]
1072
1074
  agent-pager start
1073
1075
  agent-pager status
@@ -13,7 +13,7 @@ export function inboxPath() {
13
13
  export function loadLocalConfig() {
14
14
  const path = configPath();
15
15
  if (!existsSync(path)) {
16
- throw new Error("not logged in. Run `agent-pager login --username <name>` first.");
16
+ throw new Error("not logged in. Run `agent-pager login` first.");
17
17
  }
18
18
  return JSON.parse(readFileSync(path, "utf8"));
19
19
  }
package/dist/src/mcp.js CHANGED
@@ -197,7 +197,7 @@ async function handle(method, params) {
197
197
  return {
198
198
  protocolVersion: params.protocolVersion || "2024-11-05",
199
199
  capabilities: { tools: {} },
200
- serverInfo: { name: "agent-pager", version: "0.1.0" }
200
+ serverInfo: { name: "agent-pager", version: "0.1.1" }
201
201
  };
202
202
  }
203
203
  if (method === "tools/list") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-pager",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Authorized Human Contact Service for paging trusted coding agents.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -14,13 +14,6 @@
14
14
  "vercel"
15
15
  ],
16
16
  "homepage": "https://agent-pager.vercel.app",
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/brysonkbarney/agent-pager.git"
20
- },
21
- "bugs": {
22
- "url": "https://github.com/brysonkbarney/agent-pager/issues"
23
- },
24
17
  "main": "./dist/src/cli.js",
25
18
  "bin": {
26
19
  "agent-pager": "dist/src/cli.js"
@@ -30,7 +23,18 @@
30
23
  "registry": "https://registry.npmjs.org/"
31
24
  },
32
25
  "files": [
33
- "dist/src",
26
+ "dist/src/cli.js",
27
+ "dist/src/crypto.js",
28
+ "dist/src/delivery.js",
29
+ "dist/src/http-client.js",
30
+ "dist/src/local-config.js",
31
+ "dist/src/mcp.js",
32
+ "dist/src/render.js",
33
+ "dist/src/server.js",
34
+ "dist/src/session-adapters.js",
35
+ "dist/src/setup.js",
36
+ "dist/src/store.js",
37
+ "dist/src/types.js",
34
38
  "web",
35
39
  "README.md"
36
40
  ],
package/web/app.js CHANGED
@@ -201,8 +201,9 @@ function render() {
201
201
  const username = profile?.username || state.session?.user?.email || "not signed in";
202
202
 
203
203
  els["auth-panel"].classList.toggle("is-signed-in", signedIn);
204
- els["profile-line"].textContent = signedIn ? `Signed in as ${username}` : "Signed out";
205
- els["status-human"].textContent = username;
204
+ renderAuthActions(signedIn);
205
+ els["profile-line"].textContent = signedIn ? `Signed in as ${username}` : "Create an account or sign in to start.";
206
+ els["status-human"].textContent = signedIn ? username : "Create account or sign in";
206
207
  els["status-cloud"].textContent = state.config?.publicUrl || "hosted API";
207
208
  els["status-friends"].textContent = `${friends.length} approved`;
208
209
  els["status-pending"].textContent = `${pending.length} pending`;
@@ -348,6 +349,13 @@ function render() {
348
349
  `).join("") || empty("No abuse reports filed.", "Reports you file appear here.");
349
350
  }
350
351
 
352
+ function renderAuthActions(signedIn) {
353
+ for (const element of document.querySelectorAll("#auth-panel [data-auth-when]")) {
354
+ const shouldShow = element.dataset.authWhen === (signedIn ? "signed-in" : "signed-out");
355
+ element.classList.toggle("is-hidden", !shouldShow);
356
+ }
357
+ }
358
+
351
359
  function renderSettings() {
352
360
  const settings = state.settings || {};
353
361
  const quietHours = quietHoursDefaults(settings.quietHours);
@@ -362,6 +370,7 @@ function renderPrototype() {
362
370
  const users = state.prototype?.users || [];
363
371
  const pages = state.prototype?.pages || [];
364
372
  els["auth-panel"].classList.remove("is-signed-in");
373
+ renderAuthActions(false);
365
374
  els["profile-line"].textContent = "Prototype mode";
366
375
  els["status-human"].textContent = `${users.length} registered`;
367
376
  els["status-cloud"].textContent = state.prototype?.publicUrl || "local service";
package/web/index.html CHANGED
@@ -71,10 +71,10 @@
71
71
  <label>Name<input id="auth-name" autocomplete="name" /></label>
72
72
  </div>
73
73
  <div class="button-row">
74
- <button data-action="sign-in">Sign in</button>
75
- <button data-action="sign-up">Create</button>
76
- <button data-action="save-profile">Save profile</button>
77
- <button data-action="sign-out">Sign out</button>
74
+ <button data-action="sign-in" data-auth-when="signed-out">Sign in</button>
75
+ <button data-action="sign-up" data-auth-when="signed-out">Create</button>
76
+ <button data-action="save-profile" data-auth-when="signed-in">Save profile</button>
77
+ <button data-action="sign-out" data-auth-when="signed-in">Sign out</button>
78
78
  </div>
79
79
  </article>
80
80
  <article class="operator-card">