codedeck 0.1.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.
Files changed (72) hide show
  1. package/README.md +211 -0
  2. package/dist/cli/commands/diff.js +43 -0
  3. package/dist/cli/commands/diff.js.map +1 -0
  4. package/dist/cli/commands/doctor.js +90 -0
  5. package/dist/cli/commands/doctor.js.map +1 -0
  6. package/dist/cli/commands/logs.js +139 -0
  7. package/dist/cli/commands/logs.js.map +1 -0
  8. package/dist/cli/commands/ps.js +59 -0
  9. package/dist/cli/commands/ps.js.map +1 -0
  10. package/dist/cli/commands/run.js +145 -0
  11. package/dist/cli/commands/run.js.map +1 -0
  12. package/dist/cli/commands/send.js +29 -0
  13. package/dist/cli/commands/send.js.map +1 -0
  14. package/dist/cli/commands/show.js +99 -0
  15. package/dist/cli/commands/show.js.map +1 -0
  16. package/dist/cli/commands/stop.js +27 -0
  17. package/dist/cli/commands/stop.js.map +1 -0
  18. package/dist/cli/index.js +63 -0
  19. package/dist/cli/index.js.map +1 -0
  20. package/dist/config/config.js +26 -0
  21. package/dist/config/config.js.map +1 -0
  22. package/dist/config/paths.js +43 -0
  23. package/dist/config/paths.js.map +1 -0
  24. package/dist/core/capabilities.js +14 -0
  25. package/dist/core/capabilities.js.map +1 -0
  26. package/dist/core/driver.js +2 -0
  27. package/dist/core/driver.js.map +1 -0
  28. package/dist/core/errors.js +61 -0
  29. package/dist/core/errors.js.map +1 -0
  30. package/dist/core/events.js +10 -0
  31. package/dist/core/events.js.map +1 -0
  32. package/dist/core/session.js +33 -0
  33. package/dist/core/session.js.map +1 -0
  34. package/dist/daemon/daemon.js +534 -0
  35. package/dist/daemon/daemon.js.map +1 -0
  36. package/dist/daemon/ipc.js +292 -0
  37. package/dist/daemon/ipc.js.map +1 -0
  38. package/dist/daemon/process-manager.js +55 -0
  39. package/dist/daemon/process-manager.js.map +1 -0
  40. package/dist/daemon/protocol.js +2 -0
  41. package/dist/daemon/protocol.js.map +1 -0
  42. package/dist/drivers/claude/driver.js +247 -0
  43. package/dist/drivers/claude/driver.js.map +1 -0
  44. package/dist/drivers/claude/parser.js +184 -0
  45. package/dist/drivers/claude/parser.js.map +1 -0
  46. package/dist/drivers/codex/driver.js +241 -0
  47. package/dist/drivers/codex/driver.js.map +1 -0
  48. package/dist/drivers/codex/parser.js +184 -0
  49. package/dist/drivers/codex/parser.js.map +1 -0
  50. package/dist/drivers/helpers.js +85 -0
  51. package/dist/drivers/helpers.js.map +1 -0
  52. package/dist/drivers/omp/driver.js +372 -0
  53. package/dist/drivers/omp/driver.js.map +1 -0
  54. package/dist/drivers/opencode/driver.js +307 -0
  55. package/dist/drivers/opencode/driver.js.map +1 -0
  56. package/dist/drivers/registry.js +48 -0
  57. package/dist/drivers/registry.js.map +1 -0
  58. package/dist/git/diff.js +100 -0
  59. package/dist/git/diff.js.map +1 -0
  60. package/dist/git/repository.js +68 -0
  61. package/dist/git/repository.js.map +1 -0
  62. package/dist/git/worktree.js +89 -0
  63. package/dist/git/worktree.js.map +1 -0
  64. package/dist/store/database.js +85 -0
  65. package/dist/store/database.js.map +1 -0
  66. package/dist/store/events.js +39 -0
  67. package/dist/store/events.js.map +1 -0
  68. package/dist/store/sessions.js +128 -0
  69. package/dist/store/sessions.js.map +1 -0
  70. package/dist/utils/process.js +35 -0
  71. package/dist/utils/process.js.map +1 -0
  72. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # CodeDeck
2
+
3
+ Local runtime for coding agents — session management, process supervision, event normalization, and git isolation.
4
+
5
+ > **Process manager for coding agents**: PM2 + tmux + git worktrees + normalized events
6
+
7
+ ## Overview
8
+
9
+ CodeDeck is not an agent. It manages the lifecycle of existing harnesses:
10
+
11
+ - **Claude Code** (`claude -p --output-format stream-json`)
12
+ - **Codex** (`codex exec --json` / app-server)
13
+ - **OpenCode** (`opencode run --format json`)
14
+ - **OMP** (`omp --mode rpc`)
15
+
16
+ The `codedeck` CLI provides a single unified interface for all of them:
17
+
18
+ ```bash
19
+ npx codedeck run "implement authentication" --agent claude
20
+ npx codedeck run "fix the tests" --agent codex
21
+ npx codedeck run "investigate this bug" --agent opencode
22
+ npx codedeck run "refactor this module" --agent omp
23
+
24
+ npx codedeck ps
25
+ npx codedeck logs a83f --follow
26
+ npx codedeck show a83f
27
+ npx codedeck send a83f "add tests"
28
+ npx codedeck stop a83f
29
+ npx codedeck diff a83f
30
+ npx codedeck doctor
31
+ ```
32
+
33
+ ## Stack
34
+
35
+ - TypeScript / Node.js
36
+ - SQLite (`node:sqlite` — `DatabaseSync`)
37
+ - Unix Domain Socket for IPC
38
+ - Git worktrees for isolation
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ npm install -g codedeck
44
+ # or
45
+ npx codedeck
46
+ ```
47
+
48
+ Binary: `codedeck`
49
+
50
+ For local development:
51
+
52
+ ```bash
53
+ npm install
54
+ npm run build
55
+ node dist/cli/index.js doctor
56
+ # or create a local alias
57
+ npm link
58
+ npx codedeck doctor
59
+ ```
60
+
61
+ ## Architecture
62
+
63
+ ```
64
+ codedeck CLI
65
+ │ IPC (Unix Socket, NDJSON)
66
+
67
+ CodeDeck Daemon
68
+ ├── Session Store (SQLite)
69
+ ├── Event Store (SQLite)
70
+ ├── Process Manager
71
+ └── Driver Registry
72
+ ├── ClaudeDriver (stream-json)
73
+ ├── CodexDriver (exec --json)
74
+ ├── OpencodeDriver (run --format json)
75
+ └── OmpDriver (rpc)
76
+ ```
77
+
78
+ The daemon owns the sessions. The CLI only follows events — closing the terminal does not kill the agent.
79
+
80
+ ## Commands
81
+
82
+ | Command | Description |
83
+ |---------|-------------|
84
+ | `npx codedeck doctor` | Check Node, Git, harnesses, daemon, and database |
85
+ | `npx codedeck run "<prompt>" --agent <id> [--model <m>] [--name <n>] [--worktree] [--detach]` | Start a session |
86
+ | `npx codedeck ps [--all] [--json]` | List recent sessions |
87
+ | `npx codedeck show <id> [--json]` | Show session details |
88
+ | `npx codedeck logs <id> [--follow] [--json] [--raw]` | Show normalized events |
89
+ | `npx codedeck send <id> "<msg>"` | Continue a session (new turn) |
90
+ | `npx codedeck stop <id>` | Graceful interrupt → SIGTERM → SIGKILL |
91
+ | `npx codedeck diff <id> [--stat] [--json]` | Git diff against base commit |
92
+
93
+ ## Session
94
+
95
+ ```ts
96
+ Session {
97
+ id: string // e.g. a83f (CodeDeck)
98
+ nativeSessionId? // internal harness id
99
+ agent: "claude" | "codex" | "opencode" | "omp"
100
+ status: "starting" | "working" | "needs_input" | "idle" | "completed" | "failed" | "stopped" | "orphaned"
101
+ cwd, worktree, branch, repository, baseCommit
102
+ pid, usage, createdAt, updatedAt
103
+ }
104
+ ```
105
+
106
+ `nativeSessionId` is an internal detail. Users only see the CodeDeck ID.
107
+
108
+ ## Normalized Events
109
+
110
+ ```ts
111
+ AgentEvent =
112
+ | session.started | turn.started | text.delta | message
113
+ | tool.started | tool.completed | file.changed
114
+ | permission.requested | permission.resolved
115
+ | usage.updated | turn.completed
116
+ | session.completed | session.failed | error
117
+ ```
118
+
119
+ Every event is persisted with its original `raw` payload intact for debugging and future compatibility.
120
+
121
+ Tables:
122
+
123
+ - `sessions` — per-session state
124
+ - `events` — monotonic log `(session_id, sequence)`
125
+
126
+ ## Worktrees
127
+
128
+ ```bash
129
+ npx codedeck run "implement oauth" --worktree
130
+ # creates ~/.run-agent/worktrees/<repo-hash>/<session-id>
131
+ # branch: ra/<slug>-<session-id>
132
+ ```
133
+
134
+ The driver receives the worktree as `cwd`. Isolation is the responsibility of CodeDeck, not the harness.
135
+
136
+ Global config: `~/.config/run-agent/config.json` or `~/.run-agent/` (fallback)
137
+
138
+ ```json
139
+ {
140
+ "defaultAgent": "claude",
141
+ "worktree": true
142
+ }
143
+ ```
144
+
145
+ ## Spikes
146
+
147
+ Validates each harness in isolation before abstractions:
148
+
149
+ ```
150
+ spikes/claude.ts
151
+ spikes/codex.ts
152
+ spikes/opencode.ts
153
+ spikes/omp.ts
154
+ ```
155
+
156
+ Run with:
157
+
158
+ ```bash
159
+ npx tsx spikes/claude.ts
160
+ ```
161
+
162
+ Each spike proves: detect, start, prompt, events, nativeSessionId, completion, interrupt, resume, stderr, and cleanup.
163
+
164
+ ## Development
165
+
166
+ ```
167
+ src/
168
+ cli/ → commander, commands (run/ps/show/logs/send/stop/diff/doctor)
169
+ core/ → driver interface, session, events, capabilities, errors
170
+ drivers/ → claude / codex / opencode / omp
171
+ daemon/ → daemon, ipc (Unix socket), process-manager, protocol
172
+ store/ → SQLite (sessions, events)
173
+ git/ → repository, worktree, diff
174
+ config/ → paths, config
175
+ utils/
176
+ ```
177
+
178
+ Build:
179
+
180
+ ```bash
181
+ npm run build
182
+ npm test
183
+ ```
184
+
185
+ ## Definition of Done (first release)
186
+
187
+ ```bash
188
+ cd example-project
189
+ npx codedeck doctor
190
+ npx codedeck run "find one improvement and implement it" --agent claude --worktree --detach
191
+ npx codedeck run "find one improvement and implement it" --agent codex --worktree --detach
192
+ npx codedeck ps
193
+ npx codedeck logs <claude-session> --follow
194
+ npx codedeck show <codex-session>
195
+ npx codedeck diff <claude-session>
196
+ npx codedeck diff <codex-session>
197
+ npx codedeck send <claude-session> "run the tests before finishing"
198
+ npx codedeck stop <codex-session>
199
+ ```
200
+
201
+ The same experience across all four harnesses.
202
+
203
+ ## Security
204
+
205
+ - Does not store API keys/tokens — uses harness authentication.
206
+ - Raw events may contain sensitive data (documented).
207
+ - Does not silently modify user configuration.
208
+
209
+ ## License
210
+
211
+ MIT
@@ -0,0 +1,43 @@
1
+ import { IpcClient } from "../../daemon/ipc.js";
2
+ export function registerDiffCommand(program) {
3
+ program
4
+ .command("diff")
5
+ .description("Show git diff for a session against its base commit (harness-independent)")
6
+ .argument("<id>", "session id (prefix allowed, e.g. a83f)")
7
+ .option("--stat", "show diff --stat and file list only")
8
+ .option("--json", "output JSON { base, diff, stat, files }")
9
+ .action(async (id, opts) => {
10
+ const client = new IpcClient();
11
+ try {
12
+ await client.ensureDaemonStarted();
13
+ }
14
+ catch { }
15
+ let result;
16
+ try {
17
+ result = await client.request("session.diff", { id });
18
+ }
19
+ catch (e) {
20
+ console.error(e instanceof Error ? e.message : String(e));
21
+ process.exit(1);
22
+ }
23
+ if (opts.json) {
24
+ console.log(JSON.stringify(result, null, 2));
25
+ return;
26
+ }
27
+ if (opts.stat) {
28
+ console.log(result.stat || "(no stat)");
29
+ if (result.files?.length) {
30
+ console.log(`\nFiles: ${result.files.join(", ")}`);
31
+ }
32
+ return;
33
+ }
34
+ if (!result.diff || !result.diff.trim()) {
35
+ console.log("(no changes)");
36
+ if (result.files?.length)
37
+ console.log(`Files: ${result.files.join(", ")}`);
38
+ return;
39
+ }
40
+ console.log(result.diff);
41
+ });
42
+ }
43
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/cli/commands/diff.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,2EAA2E,CAAC;SACxF,QAAQ,CAAC,MAAM,EAAE,wCAAwC,CAAC;SAC1D,MAAM,CAAC,QAAQ,EAAE,qCAAqC,CAAC;SACvD,MAAM,CAAC,QAAQ,EAAE,yCAAyC,CAAC;SAC3D,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAS,EAAE,EAAE;QACtC,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC;YAAC,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACpD,IAAI,MAAW,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7C,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC,CAAC;YACxC,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrD,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC5B,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM;gBAAE,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC3E,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,90 @@
1
+ import { IpcClient, isDaemonRunning } from "../../daemon/ipc.js";
2
+ import { getPaths } from "../../config/paths.js";
3
+ import fs from "node:fs";
4
+ function check(label, ok, detail) {
5
+ const icon = ok ? "✓" : "✗";
6
+ const msg = detail ? `${label.padEnd(20)} ${icon} ${detail}` : `${label.padEnd(20)} ${icon}`;
7
+ return ok ? msg : `\x1b[31m${msg}\x1b[0m`;
8
+ }
9
+ export function registerDoctorCommand(program) {
10
+ program
11
+ .command("doctor")
12
+ .description("Check Node, Git, harnesses, daemon, database and paths")
13
+ .option("--json", "output JSON with full health report")
14
+ .action(async (opts) => {
15
+ const client = new IpcClient();
16
+ let daemonRunning = await isDaemonRunning();
17
+ if (!daemonRunning) {
18
+ try {
19
+ await client.ensureDaemonStarted();
20
+ daemonRunning = true;
21
+ }
22
+ catch { }
23
+ }
24
+ let result;
25
+ try {
26
+ result = await client.request("doctor", {});
27
+ }
28
+ catch (e) {
29
+ console.error(`Doctor failed: ${e instanceof Error ? e.message : String(e)}`);
30
+ process.exit(1);
31
+ }
32
+ if (opts.json) {
33
+ console.log(JSON.stringify(result, null, 2));
34
+ return;
35
+ }
36
+ console.log("CodeDeck\n");
37
+ console.log("System");
38
+ console.log(` Node ${result.node.version}`);
39
+ console.log(` ${check("Git", result.git.installed, result.git.version || "not found")}`);
40
+ console.log("");
41
+ for (const [agent, info] of Object.entries(result.agents)) {
42
+ const label = agent.charAt(0).toUpperCase() + agent.slice(1);
43
+ // normalize name
44
+ const display = label === "Claude" ? "Claude Code" : label.charAt(0).toUpperCase() + label.slice(1);
45
+ console.log(display);
46
+ console.log(` ${check("installed", !!info.installed, info.version || info.path || (info.installed ? "yes" : "no"))}`);
47
+ if (info.installed) {
48
+ const auth = info.authenticated;
49
+ if (auth === true)
50
+ console.log(` ${check("authenticated", true, "yes")}`);
51
+ else if (auth === false)
52
+ console.log(` ${check("authenticated", false, "no")}`);
53
+ else
54
+ console.log(` ${check("authenticated", true, "unknown")}`);
55
+ const caps = info.capabilities || {};
56
+ for (const [k, v] of Object.entries(caps)) {
57
+ const ok = !!v;
58
+ const mark = ok ? "✓" : "✗";
59
+ // Use check helper but without color for capabilities maybe
60
+ console.log(` ${k.padEnd(20)} ${ok ? "✓" : "✗"} ${ok ? "yes" : "no"}`);
61
+ }
62
+ if (info.details)
63
+ console.log(` details ${info.details}`);
64
+ }
65
+ else if (info.error) {
66
+ console.log(` error ${info.error}`);
67
+ }
68
+ console.log("");
69
+ }
70
+ console.log("Daemon");
71
+ console.log(` ${check("running", !!result.daemon.running, result.daemon.running ? `pid ${result.daemon.pid}` : "not running")}`);
72
+ if (result.daemon.running) {
73
+ const up = result.daemon.uptime;
74
+ const upStr = up ? `${Math.floor(up / 1000)}s` : "unknown";
75
+ console.log(` uptime ${upStr}`);
76
+ }
77
+ console.log("");
78
+ console.log("Database");
79
+ console.log(` path ${result.database.path}`);
80
+ console.log(` ${check("exists", !!result.database.exists, result.database.exists ? "yes" : "no")}`);
81
+ console.log("");
82
+ const paths = getPaths();
83
+ console.log("Paths");
84
+ console.log(` base ${paths.base}`);
85
+ console.log(` socket ${paths.daemonSock} ${fs.existsSync(paths.daemonSock) ? "✓" : "✗"}`);
86
+ console.log(` worktrees ${paths.worktreesDir}`);
87
+ console.log("");
88
+ });
89
+ }
90
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ import { IpcClient } from "../../daemon/ipc.js";
2
+ function formatEvent(ev) {
3
+ const t = new Date(ev.timestamp).toLocaleTimeString();
4
+ switch (ev.type) {
5
+ case "session.started":
6
+ return `[${t}] ● Session started ${ev.nativeSessionId ? `(native ${String(ev.nativeSessionId).slice(0, 8)})` : ""}`;
7
+ case "turn.started":
8
+ return `[${t}] ▶ Turn started${ev.prompt ? `: ${String(ev.prompt).slice(0, 100)}` : ""}`;
9
+ case "message":
10
+ return `[${t}] ${ev.role === "user" ? "▶" : "●"} ${ev.role}: ${String(ev.content).slice(0, 500)}`;
11
+ case "text.delta":
12
+ return ev.delta;
13
+ case "tool.started":
14
+ return `[${t}] → ${ev.tool.name} ${ev.tool.input ? JSON.stringify(ev.tool.input).slice(0, 120) : ""}`;
15
+ case "tool.completed":
16
+ return `[${t}] ✓ ${ev.tool.name} ${ev.tool.success === false ? "failed" : "done"}${ev.tool.output ? `: ${String(ev.tool.output).slice(0, 200)}` : ""}`;
17
+ case "file.changed":
18
+ return `[${t}] ✎ ${ev.change} ${ev.path}`;
19
+ case "usage.updated":
20
+ return `[${t}] ◐ usage: ${JSON.stringify(ev.usage)}`;
21
+ case "turn.completed":
22
+ return `[${t}] ◑ turn completed (${ev.reason || ""})`;
23
+ case "session.completed":
24
+ return `[${t}] ● Session completed ${ev.reason || ""}`;
25
+ case "session.failed":
26
+ return `[${t}] ✗ Session failed: ${ev.error}`;
27
+ case "error":
28
+ return `[${t}] ✗ Error: ${ev.error}`;
29
+ case "permission.requested":
30
+ return `[${t}] ? Permission requested: ${ev.tool || ev.description || ""}`;
31
+ default:
32
+ return `[${t}] ${ev.type} ${JSON.stringify(ev).slice(0, 200)}`;
33
+ }
34
+ }
35
+ export function registerLogsCommand(program) {
36
+ program
37
+ .command("logs")
38
+ .description("Show normalized session logs (human, JSON, or raw)")
39
+ .argument("<id>", "session id (prefix allowed, e.g. a83f)")
40
+ .option("--follow", "follow logs in real time (Ctrl+C to detach, session keeps running)")
41
+ .option("--json", "output JSON array of normalized events")
42
+ .option("--raw", "output raw harness payloads (debug)")
43
+ .action(async (id, opts) => {
44
+ const client = new IpcClient();
45
+ try {
46
+ await client.ensureDaemonStarted();
47
+ }
48
+ catch { }
49
+ let result;
50
+ try {
51
+ result = await client.request("session.logs", { id, follow: !!opts.follow, json: !!opts.json, raw: !!opts.raw });
52
+ }
53
+ catch (e) {
54
+ console.error(e instanceof Error ? e.message : String(e));
55
+ process.exit(1);
56
+ }
57
+ const events = result.events || [];
58
+ if (opts.json) {
59
+ console.log(JSON.stringify(events, null, 2));
60
+ if (!opts.follow)
61
+ return;
62
+ }
63
+ else if (opts.raw) {
64
+ for (const ev of events) {
65
+ console.log(JSON.stringify(ev.raw || ev, null, 2));
66
+ }
67
+ if (!opts.follow)
68
+ return;
69
+ }
70
+ else {
71
+ for (const ev of events) {
72
+ if (ev.type === "text.delta") {
73
+ // For logs non-follow, show deltas as they are but maybe skip to avoid spam?
74
+ // We'll show them
75
+ process.stdout.write(ev.delta);
76
+ }
77
+ else {
78
+ console.log(formatEvent(ev));
79
+ }
80
+ }
81
+ if (!opts.follow) {
82
+ // If terminal not reached and follow not requested, just exit
83
+ return;
84
+ }
85
+ }
86
+ if (!opts.follow)
87
+ return;
88
+ // Follow mode: subscribe
89
+ console.log(`\n— following ${id} (Ctrl+C to exit) —\n`);
90
+ const onEvent = (ev) => {
91
+ if (opts.json) {
92
+ console.log(JSON.stringify(ev));
93
+ }
94
+ else if (opts.raw) {
95
+ console.log(JSON.stringify(ev.raw || ev, null, 2));
96
+ }
97
+ else {
98
+ if (ev.type === "text.delta")
99
+ process.stdout.write(ev.delta);
100
+ else
101
+ console.log(formatEvent(ev));
102
+ }
103
+ if (ev.type === "session.completed" || ev.type === "session.failed") {
104
+ console.log(`\n— session ${ev.type === "session.completed" ? "completed" : "failed"} —`);
105
+ process.exit(ev.type === "session.failed" ? 1 : 0);
106
+ }
107
+ };
108
+ const off = client.subscribe(id, onEvent, () => {
109
+ console.log("\n— stream ended —");
110
+ process.exit(0);
111
+ }, (err) => {
112
+ console.error(`Subscribe error: ${err.message}`);
113
+ process.exit(1);
114
+ });
115
+ process.on("SIGINT", () => {
116
+ console.log("\nDetached.");
117
+ off();
118
+ process.exit(0);
119
+ });
120
+ // Also poll status as fallback
121
+ const poll = async () => {
122
+ while (true) {
123
+ await new Promise((r) => setTimeout(r, 2000));
124
+ try {
125
+ const info = await client.request("session.get", { id });
126
+ const status = info.session.status;
127
+ if (["completed", "failed", "stopped"].includes(status)) {
128
+ console.log(`\nSession ${status}`);
129
+ off();
130
+ process.exit(status === "failed" ? 1 : 0);
131
+ }
132
+ }
133
+ catch { }
134
+ }
135
+ };
136
+ poll();
137
+ });
138
+ }
139
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { IpcClient } from "../../daemon/ipc.js";
2
+ function formatAge(date) {
3
+ const d = new Date(date);
4
+ const diffMs = Date.now() - d.getTime();
5
+ const mins = Math.floor(diffMs / 60000);
6
+ if (mins < 1)
7
+ return "now";
8
+ if (mins < 60)
9
+ return `${mins}m`;
10
+ const hours = Math.floor(mins / 60);
11
+ if (hours < 24)
12
+ return `${hours}h`;
13
+ const days = Math.floor(hours / 24);
14
+ return `${days}d`;
15
+ }
16
+ export function registerPsCommand(program) {
17
+ program
18
+ .command("ps")
19
+ .description("List recent sessions (daemon-owned, not harness IDs)")
20
+ .option("--all", "include all sessions including completed/failed (default: recent)")
21
+ .option("--json", "output JSON instead of table")
22
+ .action(async (opts) => {
23
+ const client = new IpcClient();
24
+ try {
25
+ await client.ensureDaemonStarted();
26
+ }
27
+ catch { }
28
+ let result;
29
+ try {
30
+ result = await client.request("session.list", { all: !!opts.all });
31
+ }
32
+ catch (e) {
33
+ console.error(`Failed to list sessions: ${e instanceof Error ? e.message : String(e)}`);
34
+ process.exit(1);
35
+ }
36
+ const sessions = result.sessions || [];
37
+ if (opts.json) {
38
+ console.log(JSON.stringify(sessions, null, 2));
39
+ return;
40
+ }
41
+ if (sessions.length === 0) {
42
+ console.log("No sessions");
43
+ return;
44
+ }
45
+ // Header
46
+ console.log("ID NAME AGENT STATUS AGE CWD");
47
+ console.log("─".repeat(80));
48
+ for (const s of sessions) {
49
+ const id = (s.id || "").padEnd(4);
50
+ const name = (s.name || s.branch?.replace("ra/", "") || "-").slice(0, 16).padEnd(16);
51
+ const agent = (s.agent || "").padEnd(9);
52
+ const status = (s.status || "").padEnd(12);
53
+ const age = formatAge(s.createdAt).padEnd(5);
54
+ const cwd = (s.worktree || s.cwd || "").replace(process.env.HOME || "", "~");
55
+ console.log(`${id} ${name} ${agent} ${status} ${age} ${cwd}`);
56
+ }
57
+ });
58
+ }
59
+ //# sourceMappingURL=ps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ps.js","sourceRoot":"","sources":["../../../src/cli/commands/ps.ts"],"names":[],"mappings":"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"}