agent-dag 1.0.0 → 1.0.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 +26 -5
- package/bin/ccgraph.js +6 -10
- package/package.json +1 -1
- package/src/server/index.mjs +29 -8
package/README.md
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# agent-dag
|
|
2
2
|
|
|
3
3
|
Live DAG of Claude Code agents. Watch parallel subagents fork, call tools, and return — all on one calm canvas.
|
|
4
4
|
|
|
5
5
|
## Run
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npx
|
|
8
|
+
npx agent-dag
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Opens http://127.0.0.1:4317. Start a Claude Code session in any directory and watch the graph fill in.
|
|
11
|
+
Opens http://127.0.0.1:4317 (or a random port in 4318–4400 if 4317 is taken). Start a Claude Code session in any directory and watch the graph fill in.
|
|
12
|
+
|
|
13
|
+
## Options
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
-p, --port <number> Preferred port (default: 4317; falls back to random 4318–4400)
|
|
17
|
+
--no-open Don't open the browser automatically
|
|
18
|
+
--workspace <path> Workspace root to filter events (default: cwd)
|
|
19
|
+
--all Capture sessions from all workspaces (machine-wide)
|
|
20
|
+
--history <path> Override events log file (default: ~/.claude/ccgraph/events.jsonl)
|
|
21
|
+
--no-persist RAM-only mode, no log file
|
|
22
|
+
--uninstall Remove agent-dag hooks from ~/.claude/settings.json
|
|
23
|
+
-h, --help Show help
|
|
24
|
+
```
|
|
12
25
|
|
|
13
26
|
## Design
|
|
14
27
|
|
|
@@ -20,11 +33,19 @@ Opens http://127.0.0.1:4317. Start a Claude Code session in any directory and wa
|
|
|
20
33
|
|
|
21
34
|
## How it works
|
|
22
35
|
|
|
23
|
-
`
|
|
36
|
+
`agent-dag` registers a hook script in `~/.claude/settings.json` for these Claude Code events:
|
|
24
37
|
|
|
25
38
|
`SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `SubagentStart`, `SubagentStop`, `Stop`, `SessionEnd`, `Notification`.
|
|
26
39
|
|
|
27
|
-
The hook forwards the event JSON to the running
|
|
40
|
+
The hook forwards the event JSON to the running server, which streams it to the browser via SSE.
|
|
41
|
+
|
|
42
|
+
## Uninstall
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx agent-dag --uninstall
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Removes all hooks from `~/.claude/settings.json`.
|
|
28
49
|
|
|
29
50
|
## Status
|
|
30
51
|
|
package/bin/ccgraph.js
CHANGED
|
@@ -41,7 +41,7 @@ if (!existsSync(WEB_DIST)) {
|
|
|
41
41
|
process.exit(1);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
console.log("
|
|
44
|
+
console.log("agent-dag");
|
|
45
45
|
console.log(" workspace:", workspace === "" ? "(all)" : workspace);
|
|
46
46
|
|
|
47
47
|
const { settingsPath, hookPath, events } = await installHooks();
|
|
@@ -50,11 +50,7 @@ console.log(" events:", events.join(", "));
|
|
|
50
50
|
console.log(" settings:", settingsPath);
|
|
51
51
|
|
|
52
52
|
const server = await startServer({ port, persist }).catch(err => {
|
|
53
|
-
|
|
54
|
-
console.error(`\nccgraph: port ${port} in use. Try --port <N>.`);
|
|
55
|
-
} else {
|
|
56
|
-
console.error("ccgraph: server failed:", err.message);
|
|
57
|
-
}
|
|
53
|
+
console.error("ccgraph: server failed:", err.message);
|
|
58
54
|
process.exit(1);
|
|
59
55
|
});
|
|
60
56
|
|
|
@@ -103,19 +99,19 @@ function parseArgs(args) {
|
|
|
103
99
|
}
|
|
104
100
|
|
|
105
101
|
function printHelp() {
|
|
106
|
-
process.stdout.write(`
|
|
102
|
+
process.stdout.write(`agent-dag — live DAG of Claude Code agents
|
|
107
103
|
|
|
108
104
|
Usage:
|
|
109
|
-
|
|
105
|
+
agent-dag [options]
|
|
110
106
|
|
|
111
107
|
Options:
|
|
112
|
-
-p, --port <number>
|
|
108
|
+
-p, --port <number> Preferred port (default: 4317; falls back to random 4318–4400)
|
|
113
109
|
--no-open Don't open the browser automatically
|
|
114
110
|
--workspace <path> Workspace root (default: cwd)
|
|
115
111
|
--all Capture sessions from ALL workspaces (machine-wide)
|
|
116
112
|
--history <path> Override events log file (default: ~/.claude/ccgraph/events.jsonl)
|
|
117
113
|
--no-persist Don't write or replay events log (RAM-only)
|
|
118
|
-
--uninstall Remove
|
|
114
|
+
--uninstall Remove agent-dag hook entries from ~/.claude/settings.json
|
|
119
115
|
-h, --help Show this help
|
|
120
116
|
`);
|
|
121
117
|
}
|
package/package.json
CHANGED
package/src/server/index.mjs
CHANGED
|
@@ -191,7 +191,21 @@ async function sweepStaleDiscovery() {
|
|
|
191
191
|
return removed;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
|
|
194
|
+
function randomPort(min, max) {
|
|
195
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function tryListen(server, port, host) {
|
|
199
|
+
return new Promise((res, rej) => {
|
|
200
|
+
server.once("error", rej);
|
|
201
|
+
server.listen(port, host, () => {
|
|
202
|
+
server.removeListener("error", rej);
|
|
203
|
+
res();
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export async function startServer({ port = 4317, host = "127.0.0.1", persist = null, portRange = [4318, 4400] } = {}) {
|
|
195
209
|
const removed = await sweepStaleDiscovery();
|
|
196
210
|
if (removed > 0) console.log(` swept ${removed} stale discovery file(s)`);
|
|
197
211
|
if (persist) {
|
|
@@ -227,13 +241,20 @@ export async function startServer({ port = 4317, host = "127.0.0.1", persist = n
|
|
|
227
241
|
send(res, 405, { error: "method not allowed" });
|
|
228
242
|
});
|
|
229
243
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
244
|
+
// Try requested port first, then up to 10 random ports from portRange.
|
|
245
|
+
const candidates = [port];
|
|
246
|
+
for (let i = 0; i < 10; i++) candidates.push(randomPort(portRange[0], portRange[1]));
|
|
247
|
+
|
|
248
|
+
for (const candidate of candidates) {
|
|
249
|
+
try {
|
|
250
|
+
await tryListen(server, candidate, host);
|
|
251
|
+
return server;
|
|
252
|
+
} catch (err) {
|
|
253
|
+
if (err && err.code === "EADDRINUSE") continue;
|
|
254
|
+
throw err;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
throw Object.assign(new Error(`all ports tried — none available`), { code: "EADDRINUSE" });
|
|
237
258
|
}
|
|
238
259
|
|
|
239
260
|
// Allow running this file directly for dev.
|