@hanskristoffer/agentpool 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 +133 -0
- package/bin/agentpool.js +10 -0
- package/package.json +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# agentgate
|
|
2
|
+
|
|
3
|
+
One daemon per machine that:
|
|
4
|
+
|
|
5
|
+
- pools several **Claude** and **Codex** subscriptions and moves to the next account when one hits its limit;
|
|
6
|
+
- hosts **MCP servers** and gives each GitHub repo its own set (e.g. a separate PostHog project per repo), plus general ones for every repo;
|
|
7
|
+
- **shares** all of it between your machines over Tailscale, and keeps working when the other machines are offline.
|
|
8
|
+
|
|
9
|
+
T3 Code (or plain Claude Code / Codex) runs the sessions; agentgate sits underneath. See [PLAN.md](PLAN.md) for the design and [STABILITY_PLAN.md](STABILITY_PLAN.md) for the code review, reliability fixes, and refactoring order.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
Requirements: Linux or macOS, [Tailscale](https://tailscale.com) on every machine, `claude` and/or `codex` CLIs for logging in, and Node (`npx`) or uv (`uvx`) for any stdio MCP servers you add.
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install -g @hanskristoffer/agentpool # installs the `agentgate` command (and an `agentpool` alias)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Without npm:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
curl -fsSL https://raw.githubusercontent.com/HansKristoffer/agentgate/main/install.sh | AGENTGATE_REPO=HansKristoffer/agentgate sh
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or from source: `bun install && bun run build` (binaries land in `dist/`), or run `bun src/cli.ts …` directly.
|
|
26
|
+
|
|
27
|
+
## First machine
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
agentgate init # names the node after the host; add --always-on on a server
|
|
31
|
+
agentgate login claude --label work # official login in a temp dir, imported, then deleted
|
|
32
|
+
agentgate login codex --label personal
|
|
33
|
+
agentgate setup # writes Claude Code / Codex config, prints the T3 settings
|
|
34
|
+
agentgate service install # launchd (macOS) or systemd --user (Linux)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Open http://127.0.0.1:7878 for the web UI. Everything below can also be done there.
|
|
38
|
+
|
|
39
|
+
## A second machine (e.g. an always-on server)
|
|
40
|
+
|
|
41
|
+
On the first machine: `agentgate pair`. It prints a command, valid for 10 minutes. On the server:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
agentgate init --name srv --always-on
|
|
45
|
+
agentgate join http://mac.<tailnet>.ts.net:7878 <code>
|
|
46
|
+
agentgate setup
|
|
47
|
+
agentgate service install # also runs `loginctl enable-linger` so it survives logout/reboot
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The server now has every account, MCP instance and repo mapping, and takes over token refreshes. The UI is reachable at `http://srv.<tailnet>.ts.net:7878` after logging in with `agentgate admin-token`.
|
|
51
|
+
|
|
52
|
+
## T3 Code
|
|
53
|
+
|
|
54
|
+
`agentgate setup` writes a Claude config dir (whose `settings.json` points Claude Code at the daemon) and a Codex home. In T3 Code, add one provider instance per provider:
|
|
55
|
+
|
|
56
|
+
| Provider | T3 setting |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Claude | `CLAUDE_CONFIG_DIR path` = `~/.config/agentgate/claude` |
|
|
59
|
+
| Codex | `CODEX_HOME path` = `~/.config/agentgate/codex` |
|
|
60
|
+
|
|
61
|
+
One instance per provider covers every account; the daemon switches accounts, so a thread never breaks when an account runs out. To prefer one account, pin it (`agentgate accounts pin <id>` or the UI).
|
|
62
|
+
|
|
63
|
+
### Or: your normal Claude login
|
|
64
|
+
|
|
65
|
+
`agentgate setup --primary` adds only `ANTHROPIC_BASE_URL` to `~/.claude/settings.json`, so the Claude Code you already use (and T3's default Claude instance) goes through agentgate while keeping its own login. Model requests use the pool; other requests keep your login, and your login is also the last resort when every pooled account is exhausted. Undo with `agentgate setup --primary off` (the previous base URL is restored, and later settings edits are preserved). Only do this with `agentgate service install`, or Claude Code can't reach Anthropic while the daemon is down.
|
|
66
|
+
|
|
67
|
+
## MCP servers per repo
|
|
68
|
+
|
|
69
|
+
In the UI (MCP servers page), paste a server's URL and a name and click **Connect**. If the server uses MCP OAuth, you are sent to its login page and back; agentgate keeps the login, refreshes it, and syncs it to your other machines. One-click buttons cover common hosted servers (PostHog, Linear, Sentry, Notion, Supabase, Stripe, Vercel, Cloudflare, Neon, Railway, Context7) and a per-worktree filesystem server. Servers that take an API key instead get it under **Extra headers** (`Authorization: Bearer …`); the same field pins a server to one project (`x-posthog-project-id: 12345`).
|
|
70
|
+
|
|
71
|
+
From the CLI:
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
agentgate mcp add geysier https://app.geysier.com/api/mcp
|
|
75
|
+
agentgate mcp login geysier # opens the login page; the daemon receives the callback
|
|
76
|
+
agentgate mcp add posthog-lullu posthog --header "x-posthog-project-id: 12345"
|
|
77
|
+
agentgate mcp add fs filesystem # presets: agentgate mcp presets
|
|
78
|
+
agentgate mcp add mytool --command "npx -y @some/mcp-server" [--per-session]
|
|
79
|
+
|
|
80
|
+
agentgate project set '*' fs=fs
|
|
81
|
+
agentgate project set Lullu-ai/lullu posthog=posthog-lullu
|
|
82
|
+
agentgate mcp test posthog-lullu
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The name is the tool prefix: in every repo mapped to `posthog-lullu` under the alias `posthog`, the agent sees `posthog__…` tools that reach that repo's PostHog project. The repo is taken from `git remote get-url origin` in the session's working directory (override with `AGENTGATE_PROJECT=owner/repo`). Mapping changes reach running sessions without a restart.
|
|
86
|
+
|
|
87
|
+
## Commands
|
|
88
|
+
|
|
89
|
+
Run `agentgate --help`. Useful ones: `status`, `accounts`, `accounts exhaust <id> [min]` (pretend an account hit its limit, for testing), `nodes`, `unpair <node>`, `export [--no-secrets]`, `import-backup <file>`, `service logs`.
|
|
90
|
+
|
|
91
|
+
## Things to know
|
|
92
|
+
|
|
93
|
+
- **Once imported, a login belongs to agentgate.** Don't keep using the original `~/.claude` or `~/.codex` login: its CLI would refresh the token and log agentgate out. `agentgate login` avoids this by using a throwaway directory.
|
|
94
|
+
- **Secrets are stored in plain text** in `~/.config/agentgate/agentgate.db` (mode 0600) and copied to every paired node. Pair only machines you control.
|
|
95
|
+
- **Terms of service.** Pool only your own accounts and keep a person driving the sessions; see PLAN.md §16.
|
|
96
|
+
|
|
97
|
+
## Development
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
bun install
|
|
101
|
+
bun test
|
|
102
|
+
bun run typecheck
|
|
103
|
+
AGENTGATE_HOME=/tmp/ag AGENTGATE_PORT=7979 bun src/cli.ts init # a throwaway node
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Reliability and upgrades
|
|
107
|
+
|
|
108
|
+
The reliability refactor is implemented; [STABILITY_PLAN.md](STABILITY_PLAN.md#implementation-and-verification--2026-09-30) records the changes, checks, and remaining live release gates. Account and MCP OAuth refreshes share holder coordination and a local cross-process lease. Running MCP shims reconnect after daemon restarts and update per-session mappings; tool calls with uncertain outcomes are never automatically replayed.
|
|
109
|
+
|
|
110
|
+
Upgrade paired nodes together. This version uses **sync protocol 2**, and older peers are rejected. Existing MCP OAuth credentials migrate automatically into a separate record when the database opens. Deletion history is retained so offline machines cannot resurrect old configuration. Keep a full backup before upgrading.
|
|
111
|
+
|
|
112
|
+
`export --no-secrets` / **Without secrets** produces an inventory: it omits logins, OAuth client secrets, and arbitrary MCP URLs, headers, commands/arguments, environment, fields, and secrets. Restored inventory transports need configuration again. Full exports contain working credentials and transport configuration.
|
|
113
|
+
|
|
114
|
+
`setup` preserves unrelated Claude/Codex settings and first-run backups. Generated shims/services include `AGENTGATE_HOME` and `AGENTGATE_PORT`; rerun setup and reinstall the service if you change either value or move the binary. An unsuccessful temporary CLI login/import keeps its folder for recovery instead of deleting the only credential copy.
|
|
115
|
+
|
|
116
|
+
The proxy bounds request bodies to 16 MiB, waits at most 30 seconds for upstream headers, and cancels a response stream after five minutes without data. MCP tool calls allow five minutes without progress, with a 30-minute total limit. Status reports expired logins, refresh failures, sync errors, and quota headers that could not be recognized.
|
|
117
|
+
|
|
118
|
+
Network partitions can still cause separate machines to compete for a rotating upstream token. Reconnect and sync the newer credential first; if the provider revoked it, log in again. Live subscription traffic, T3 provider sessions, physical Tailscale failover, and installed service reboot/logout behavior remain release checks.
|
|
119
|
+
|
|
120
|
+
## Development checks
|
|
121
|
+
|
|
122
|
+
Use Bun 1.4.2 and the committed lockfile:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
bun install --frozen-lockfile
|
|
126
|
+
bun run typecheck
|
|
127
|
+
bun test
|
|
128
|
+
bun run build
|
|
129
|
+
bun scripts/smoke.ts dist/agentgate-darwin-arm64 # use your host target
|
|
130
|
+
bun scripts/codex-smoke.ts # optional: installed Codex CLI, fake upstream
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Builds produce four macOS/Linux binaries and `dist/SHA256SUMS`. Pushing a `v*` tag publishes them to npm (`@hanskristoffer/agentpool` plus one `agentpool-<os>-<cpu>` package per binary, via `scripts/npm.ts`; needs the `NPM_TOKEN` secret) and to a GitHub release. The installer verifies the checksum from the same resolved release before replacing an installed binary. CI runs tests, typechecking, and compiled CLI checks on macOS and Linux.
|
package/bin/agentpool.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { spawnSync } = require("node:child_process");
|
|
3
|
+
const pkg = `agentpool-${process.platform}-${process.arch}`;
|
|
4
|
+
let binary;
|
|
5
|
+
try { binary = require.resolve(`${pkg}/bin/agentgate`); }
|
|
6
|
+
catch { console.error(`agentpool: ${pkg} is not installed; this platform may be unsupported (macOS/Linux, x64/arm64), or optional dependencies were skipped.`); process.exit(1); }
|
|
7
|
+
const child = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
|
|
8
|
+
if (child.error) throw child.error;
|
|
9
|
+
if (child.signal) process.kill(process.pid, child.signal);
|
|
10
|
+
process.exit(child.status ?? 1);
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hanskristoffer/agentpool",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"license": "UNLICENSED",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/HansKristoffer/agentgate.git"
|
|
8
|
+
},
|
|
9
|
+
"description": "Pools Claude and Codex subscriptions, hosts MCP servers per repo, and shares them between machines.",
|
|
10
|
+
"bin": {
|
|
11
|
+
"agentpool": "bin/agentpool.js",
|
|
12
|
+
"agentgate": "bin/agentpool.js"
|
|
13
|
+
},
|
|
14
|
+
"optionalDependencies": {
|
|
15
|
+
"agentpool-darwin-arm64": "0.1.1",
|
|
16
|
+
"agentpool-darwin-x64": "0.1.1",
|
|
17
|
+
"agentpool-linux-x64": "0.1.1",
|
|
18
|
+
"agentpool-linux-arm64": "0.1.1"
|
|
19
|
+
}
|
|
20
|
+
}
|