@hua-labs/tap 0.2.6 → 0.3.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HUA Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,194 +1,280 @@
1
- # @hua-labs/tap
2
-
3
- Zero-dependency CLI for cross-model AI agent communication setup.
4
-
5
- One command to connect Claude, Codex, and Gemini agents through a shared file-based communication layer.
6
-
7
- ## Quick Start
8
-
9
- > `bun` is required to run the managed tap MCP server. When installed from npm, `@hua-labs/tap` now ships its own bundled MCP server entry.
10
-
11
- ```bash
12
- # 1. Initialize comms directory and state
13
- npx @hua-labs/tap init
14
-
15
- # 2. Add runtimes
16
- npx @hua-labs/tap add claude
17
- npx @hua-labs/tap add codex
18
- npx @hua-labs/tap add gemini
19
-
20
- # 3. Check status
21
- npx @hua-labs/tap status
22
- ```
23
-
24
- Your agents can now communicate through the shared comms directory.
25
-
26
- ## Commands
27
-
28
- ### `init`
29
-
30
- Initialize the comms directory and `.tap-comms/` state.
31
-
32
- By default, the comms directory is created inside the current repo at `./tap-comms`.
33
-
34
- ```bash
35
- npx @hua-labs/tap init
36
- npx @hua-labs/tap init --comms-dir /path/to/comms
37
- npx @hua-labs/tap init --permissions safe # default: deny destructive ops
38
- npx @hua-labs/tap init --permissions full # no restrictions (use with caution)
39
- npx @hua-labs/tap init --force # re-initialize
40
- ```
41
-
42
- ### `add <runtime>`
43
-
44
- Add a runtime. Probes config, plans patches, applies, and verifies.
45
-
46
- ```bash
47
- npx @hua-labs/tap add claude
48
- npx @hua-labs/tap add codex
49
- npx @hua-labs/tap add gemini
50
- npx @hua-labs/tap add claude --force # re-install
51
- ```
52
-
53
- ### `remove <runtime>`
54
-
55
- Remove a runtime and rollback config changes.
56
-
57
- ```bash
58
- npx @hua-labs/tap remove claude
59
- npx @hua-labs/tap remove codex
60
- ```
61
-
62
- ### `status`
63
-
64
- Show installed runtimes and their status.
65
-
66
- ```bash
67
- npx @hua-labs/tap status
68
- ```
69
-
70
- Output shows three status levels:
71
-
72
- - **installed** — config written but not verified
73
- - **configured** — config written and verified
74
- - **active** runtime is running and connected
75
-
76
- ### `serve`
77
-
78
- Start the tap-comms MCP server (stdio). Convenience command for running the MCP server locally.
79
-
80
- ```bash
81
- npx @hua-labs/tap serve
82
- npx @hua-labs/tap serve --comms-dir /path/to/comms
83
- ```
84
-
85
- Requires `bun`. Uses the bundled MCP server entry from `@hua-labs/tap`, with a repo-local fallback for monorepo checkouts.
86
-
87
- ## Supported Runtimes
88
-
89
- | Runtime | Config | Bridge | Mode |
90
- | ------- | ----------------------- | ---------------------- | ------------------ |
91
- | Claude | `.mcp.json` | native-push (fs.watch) | No daemon needed |
92
- | Codex | `~/.codex/config.toml` | WebSocket bridge | Daemon per session |
93
- | Gemini | `.gemini/settings.json` | polling | No daemon needed |
94
-
95
- ## `--json` Flag
96
-
97
- All commands support `--json` for machine-readable output. Returns a single JSON object to stdout with no human log noise.
98
-
99
- ```bash
100
- npx @hua-labs/tap status --json
101
- ```
102
-
103
- ```json
104
- {
105
- "ok": true,
106
- "command": "status",
107
- "code": "TAP_STATUS_OK",
108
- "message": "2 runtime(s) installed",
109
- "warnings": [],
110
- "data": {
111
- "version": "0.2.2",
112
- "commsDir": "/path/to/comms",
113
- "runtimes": {
114
- "claude": { "status": "active", "bridgeMode": "native-push" },
115
- "codex": { "status": "configured", "bridgeMode": "app-server" }
116
- }
117
- }
118
- }
119
- ```
120
-
121
- Error codes use `TAP_*` prefix: `TAP_ADD_OK`, `TAP_NO_OP`, `TAP_PATCH_FAILED`, etc.
122
-
123
- Exit codes: `0` = ok, `1` = error.
124
-
125
- ## Permissions
126
-
127
- `tap init` auto-configures runtime permissions.
128
-
129
- ### Safe mode (default)
130
-
131
- **Claude**: Adds deny rules to `.claude/settings.local.json` blocking destructive operations (force push, hard reset, rm -rf, etc.).
132
-
133
- **Codex**: Sets `workspace-write` sandbox, `full` network access, trusted project paths, and writable roots in `~/.codex/config.toml`.
134
-
135
- ### Full mode
136
-
137
- ```bash
138
- npx @hua-labs/tap init --permissions full
139
- ```
140
-
141
- **Claude**: Removes tap-managed deny rules. User-added rules preserved.
142
-
143
- **Codex**: Sets `danger-full-access` sandbox. Use on trusted local machines only.
144
-
145
- ## How It Works
146
-
147
- Agents communicate through a shared directory (`comms/`) using markdown files:
148
-
149
- ```
150
- comms/
151
- ├── inbox/ # Agent-to-agent messages
152
- ├── reviews/ # Code review results
153
- ├── findings/ # Out-of-scope discoveries
154
- ├── handoff/ # Session handoff documents
155
- ├── retros/ # Retrospectives
156
- └── archive/ # Archived messages
157
- ```
158
-
159
- Each runtime has an adapter that:
160
-
161
- 1. **Probes** — finds config files, checks runtime installation
162
- 2. **Plans** — determines what patches to apply
163
- 3. **Applies** — backs up and patches config files
164
- 4. **Verifies** — confirms the runtime can read the config
165
-
166
- The adapter contract (`RuntimeAdapter`) is the extension point for adding new runtimes.
167
-
168
- ## Changelog (0.2.2)
169
-
170
- ### Bridge
171
-
172
- - **Auth gateway** — Managed bridge now includes an auth proxy with timing-safe token validation (M99)
173
- - **`--no-auth` flag** Skip auth gateway for localhost-only setups; app-server listens directly on public port (M102)
174
- - **TUI connect URL** — `bridge start` and `bridge status` output shows where to connect Codex TUI (M102)
175
- - **Identity routing** — Bridge matches inbox messages by both `agentId` and `agentName`; self echo-back filtered by both (M101)
176
- - **Display labels** — Bridge prompts, `tap_who`, and notifications use `name [id]` format (M101)
177
-
178
- ### CLI
179
-
180
- - **`tap doctor`** Diagnose comms, bridge, message, and MCP issues (M95)
181
- - **`tap doctor --fix`** — Auto-fix common issues with post-fix revalidation (M100)
182
- - **Error codes** 24 CLI error codes with consistent `TAP_*` prefix (M91)
183
- - **Boot streamline** — Faster CLI startup with agent-name persistence (M92)
184
-
185
- ### Infrastructure
186
-
187
- - **Auto-poll fallback** — Bridge falls back to polling when fs.watch is unavailable (M93)
188
- - **Watcher dedup** — Root-cause fix for duplicate message dispatch (M90)
189
- - **tap-plugin test infra** — In-memory test harness for MCP channel tests (M94)
190
- - **Blind test CI** Cross-model communication verification framework (M98)
191
-
192
- ## License
193
-
194
- MIT
1
+ # @hua-labs/tap
2
+
3
+ > *Other tools give agents instructions. tap gives them context.*
4
+
5
+ **탑 (塔)** Korean for *stone tower* and *control tower*. Stone towers are built by stacking stones one by one. Each generation of AI agents adds records to a shared directory findings, retros, letters, handoffs. The tower grows. A control tower observes and coordinates. The tower agent orchestrates missions, routes reviews, and keeps the team aligned.
6
+
7
+ *"돌이 쌓이면 탑이 된다"* — When stones stack, they become a tower.
8
+
9
+ Zero-dependency CLI for cross-model AI agent communication setup.
10
+
11
+ One command to connect Claude, Codex, and Gemini agents through a shared file-based communication layer.
12
+
13
+ ### Why "tap"?
14
+
15
+ (塔) Korean for **stone tower** and **control tower**.
16
+
17
+ - **Stone tower** (석탑): built by stacking stones one by one. Each generation of agents adds records to the comms directory — findings, retros, letters, handoffs. The tower grows.
18
+ - **Control tower** (관제탑): observes and coordinates from the center. The tower agent orchestrates missions, routes reviews, and keeps the team aligned.
19
+
20
+ *Stacked records + central coordination = tap.*
21
+
22
+ ## Quick Start
23
+
24
+ > `bun` is required to run the managed tap MCP server. When installed from npm, `@hua-labs/tap` now ships its own bundled MCP server entry.
25
+
26
+ ```bash
27
+ # 1. Initialize comms directory and state
28
+ npx @hua-labs/tap init
29
+
30
+ # 2. Add runtimes
31
+ npx @hua-labs/tap add claude
32
+ npx @hua-labs/tap add codex
33
+ npx @hua-labs/tap add gemini
34
+
35
+ # 3. Check status
36
+ npx @hua-labs/tap status
37
+ ```
38
+
39
+ Your agents can now communicate through the shared comms directory.
40
+
41
+ ### Running Claude with tap
42
+
43
+ ```bash
44
+ # Start Claude Code with tap MCP server
45
+ claude --mcp-config .mcp.json
46
+ ```
47
+
48
+ The `.mcp.json` file is auto-generated by `tap init`. It connects Claude to the tap communication layer, enabling `tap_reply`, `tap_who`, `tap_list_unread`, and other tools.
49
+
50
+ ## Commands
51
+
52
+ ### `init`
53
+
54
+ Initialize the comms directory and `.tap-comms/` state.
55
+
56
+ By default, the comms directory is created inside the current repo at `./tap-comms`.
57
+
58
+ ```bash
59
+ npx @hua-labs/tap init
60
+ npx @hua-labs/tap init --comms-dir /path/to/comms
61
+ npx @hua-labs/tap init --permissions safe # default: deny destructive ops
62
+ npx @hua-labs/tap init --permissions full # no restrictions (use with caution)
63
+ npx @hua-labs/tap init --force # re-initialize
64
+ ```
65
+
66
+ ### `add <runtime>`
67
+
68
+ Add a runtime. Probes config, plans patches, applies, and verifies.
69
+
70
+ ```bash
71
+ npx @hua-labs/tap add claude
72
+ npx @hua-labs/tap add codex
73
+ npx @hua-labs/tap add gemini
74
+ npx @hua-labs/tap add claude --force # re-install
75
+ ```
76
+
77
+ ### `remove <runtime>`
78
+
79
+ Remove a runtime and rollback config changes.
80
+
81
+ ```bash
82
+ npx @hua-labs/tap remove claude
83
+ npx @hua-labs/tap remove codex
84
+ ```
85
+
86
+ ### `status`
87
+
88
+ Show installed runtimes and their status.
89
+
90
+ ```bash
91
+ npx @hua-labs/tap status
92
+ ```
93
+
94
+ Output shows three status levels:
95
+
96
+ - **installed** — config written but not verified
97
+ - **configured** config written and verified
98
+ - **active** — runtime is running and connected
99
+
100
+ ### `doctor`
101
+
102
+ Diagnose and optionally fix tap infrastructure health.
103
+
104
+ ```bash
105
+ npx @hua-labs/tap doctor
106
+ npx @hua-labs/tap doctor --fix
107
+ ```
108
+
109
+ ### `up` / `down`
110
+
111
+ Start or stop all managed bridges.
112
+
113
+ ```bash
114
+ npx @hua-labs/tap up
115
+ npx @hua-labs/tap down
116
+ ```
117
+
118
+ ### `gui`
119
+
120
+ Start a local web dashboard showing bridge status, agents, mission kanban, and PR board.
121
+
122
+ ```bash
123
+ npx @hua-labs/tap gui
124
+ ```
125
+
126
+ ### `watch`
127
+
128
+ Autonomous bridge health monitoring with auto-restart for stuck bridges.
129
+
130
+ ```bash
131
+ npx @hua-labs/tap watch
132
+ npx @hua-labs/tap watch --loop --interval 60
133
+ ```
134
+
135
+ ### `serve`
136
+
137
+ Start the tap MCP server (stdio). Convenience command for running the MCP server locally.
138
+
139
+ ```bash
140
+ npx @hua-labs/tap serve
141
+ npx @hua-labs/tap serve --comms-dir /path/to/comms
142
+ ```
143
+
144
+ Requires `bun`. Uses the bundled MCP server entry from `@hua-labs/tap`, with a repo-local fallback for monorepo checkouts.
145
+
146
+ ## Supported Runtimes
147
+
148
+ | Runtime | Config | Bridge | Mode |
149
+ | ------- | ----------------------- | ---------------------- | ------------------ |
150
+ | Claude | `.mcp.json` | native-push (fs.watch) | No daemon needed |
151
+ | Codex | `~/.codex/config.toml` | WebSocket bridge | Daemon per session |
152
+ | Gemini | `.gemini/settings.json` | polling | No daemon needed |
153
+
154
+ ## `--json` Flag
155
+
156
+ All commands support `--json` for machine-readable output. Returns a single JSON object to stdout with no human log noise.
157
+
158
+ ```bash
159
+ npx @hua-labs/tap status --json
160
+ ```
161
+
162
+ ```json
163
+ {
164
+ "ok": true,
165
+ "command": "status",
166
+ "code": "TAP_STATUS_OK",
167
+ "message": "2 runtime(s) installed",
168
+ "warnings": [],
169
+ "data": {
170
+ "version": "0.3.0",
171
+ "commsDir": "/path/to/comms",
172
+ "instances": {
173
+ "claude": { "status": "active", "bridgeMode": "native-push" },
174
+ "codex": { "status": "configured", "bridgeMode": "app-server" }
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
180
+ Error codes use `TAP_*` prefix: `TAP_ADD_OK`, `TAP_NO_OP`, `TAP_PATCH_FAILED`, etc.
181
+
182
+ Exit codes: `0` = ok, `1` = error.
183
+
184
+ ## Permissions
185
+
186
+ `tap init` auto-configures runtime permissions.
187
+
188
+ ### Safe mode (default)
189
+
190
+ **Claude**: Adds deny rules to `.claude/settings.local.json` blocking destructive operations (force push, hard reset, rm -rf, etc.).
191
+
192
+ **Codex**: Sets `workspace-write` sandbox, `full` network access, trusted project paths, and writable roots in `~/.codex/config.toml`.
193
+
194
+ ### Full mode
195
+
196
+ ```bash
197
+ npx @hua-labs/tap init --permissions full
198
+ ```
199
+
200
+ **Claude**: Removes tap-managed deny rules. User-added rules preserved.
201
+
202
+ **Codex**: Sets `danger-full-access` sandbox. Use on trusted local machines only.
203
+
204
+ ## How It Works
205
+
206
+ Agents communicate through a shared directory (`comms/`) using markdown files:
207
+
208
+ ```
209
+ comms/
210
+ ├── inbox/ # Agent-to-agent messages
211
+ ├── reviews/ # Code review results
212
+ ├── findings/ # Out-of-scope discoveries
213
+ ├── handoff/ # Session handoff documents
214
+ ├── retros/ # Retrospectives
215
+ └── archive/ # Archived messages
216
+ ```
217
+
218
+ Each runtime has an adapter that:
219
+
220
+ 1. **Probes** — finds config files, checks runtime installation
221
+ 2. **Plans** — determines what patches to apply
222
+ 3. **Applies** — backs up and patches config files
223
+ 4. **Verifies** — confirms the runtime can read the config
224
+
225
+ The adapter contract (`RuntimeAdapter`) is the extension point for adding new runtimes.
226
+
227
+ ## What's New (0.3.0)
228
+
229
+ ### Headless Durable
230
+
231
+ TUI-free Codex operation is now fully automated:
232
+ - **Auto app-server spawn** — `tap bridge start` launches codex app-server without manual setup
233
+ - **Thread self-heal** — Stale thread state automatically reconciled from heartbeat
234
+ - **Warmup on restart** — Cold-start warmup triggers on `bridge restart`, not just `tap up`
235
+
236
+ ### Web Dashboard
237
+
238
+ ```bash
239
+ npx @hua-labs/tap gui
240
+ ```
241
+
242
+ Live dashboard at `http://127.0.0.1:3847` with:
243
+ - Agent status + bridge health (SSE live updates)
244
+ - Mission kanban board (`/missions`)
245
+ - PR board (`/prs`)
246
+ - JSON APIs with CORS (`/api/snapshot`, `/api/missions`, `/api/prs`)
247
+
248
+ ### Autonomous Monitoring
249
+
250
+ ```bash
251
+ npx @hua-labs/tap watch --loop --interval 60
252
+ ```
253
+
254
+ Continuous health monitoring with auto-restart for stuck bridges. Cron/systemd friendly.
255
+
256
+ ### Cross-Platform
257
+
258
+ - **Windows**: PowerShell hidden spawn + `.cmd` shim unwrap
259
+ - **macOS/Linux**: Unix detached process + `lsof` PID discovery
260
+ - **Gemini**: Fake IDE companion server (MCP-over-HTTP)
261
+
262
+ ### Modular Architecture
263
+
264
+ bridge.ts split from 1,744 to 241 lines (-86%) across 16 focused modules. See `docs/areas/tap/splitting-convention.md`.
265
+
266
+ ## Examples
267
+
268
+ Real multi-agent collaboration highlights from 18 generations:
269
+
270
+ - [Logic Battle: "Will You Ship Broken Code?"](examples/01-logic-battle-known-broken.md)
271
+ - [Cross-Model Review Catches Root Cause Misdiagnosis](examples/02-cross-model-review-root-cause.md)
272
+ - [Independent Convergence Across 3 Generations](examples/03-convergence-pattern.md)
273
+ - [Tower Broadcast: "Stop Talking, Write Code"](examples/04-tower-broadcast.md)
274
+ - [Self-Awareness ≠ Self-Correction](examples/05-self-awareness-paradox.md)
275
+
276
+ [See all 10 examples →](examples/)
277
+
278
+ ## License
279
+
280
+ MIT
@@ -30,6 +30,13 @@ interface Candidate {
30
30
  body: string;
31
31
  mtimeMs: number;
32
32
  }
33
+ interface ThreadStateRecord {
34
+ threadId: string;
35
+ updatedAt: string;
36
+ appServerUrl: string;
37
+ ephemeral: boolean;
38
+ cwd?: string | null;
39
+ }
33
40
  interface HeadlessWarmupClient {
34
41
  activeTurnId: string | null;
35
42
  lastTurnStatus: string | null;
@@ -52,6 +59,7 @@ declare const HEADLESS_WARMUP_PROMPT: string;
52
59
  declare function threadCwdMatches(expectedCwd: string, actualCwd: string | null | undefined): boolean;
53
60
  declare function chooseLoadedThreadForCwd(cwd: string, threads: LoadedThreadCandidate[]): LoadedThreadCandidate | null;
54
61
  declare function resolveAgentId(preferredAgentName?: string | null): string;
62
+ declare function loadResumableThreadState(stateDir: string, fallbackAppServerUrl: string): ThreadStateRecord | null;
55
63
  declare function recipientMatchesAgent(recipient: string, agentId: string, agentName: string): boolean;
56
64
  declare function isOwnMessageSender(sender: string, agentId: string, agentName: string): boolean;
57
65
  declare function resolveAddressLabel(address: string, heartbeats: HeartbeatStore): string;
@@ -62,4 +70,4 @@ declare function maybeBootstrapHeadlessTurn(options: Options, cutoff: Date, clie
62
70
  declare function buildOptions(argv: string[]): Options;
63
71
  declare function main(): Promise<void>;
64
72
 
65
- export { HEADLESS_WARMUP_PROMPT, type HeadlessWarmupClient, type LoadedThreadCandidate, buildOptions, buildUserInput, chooseLoadedThreadForCwd, isOwnMessageSender, main, maybeBootstrapHeadlessTurn, recipientMatchesAgent, resolveAddressLabel, resolveAgentId, resolveCurrentAgentName, threadCwdMatches, waitForTurnCompletion };
73
+ export { HEADLESS_WARMUP_PROMPT, type HeadlessWarmupClient, type LoadedThreadCandidate, buildOptions, buildUserInput, chooseLoadedThreadForCwd, isOwnMessageSender, loadResumableThreadState, main, maybeBootstrapHeadlessTurn, recipientMatchesAgent, resolveAddressLabel, resolveAgentId, resolveCurrentAgentName, threadCwdMatches, waitForTurnCompletion };