@elhu/pit 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.
Files changed (192) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +380 -0
  3. package/dist/adapters/claude-code.d.ts +70 -0
  4. package/dist/adapters/claude-code.d.ts.map +1 -0
  5. package/dist/adapters/claude-code.js +166 -0
  6. package/dist/adapters/claude-code.js.map +1 -0
  7. package/dist/adapters/index.d.ts +16 -0
  8. package/dist/adapters/index.d.ts.map +1 -0
  9. package/dist/adapters/index.js +49 -0
  10. package/dist/adapters/index.js.map +1 -0
  11. package/dist/adapters/opencode.d.ts +53 -0
  12. package/dist/adapters/opencode.d.ts.map +1 -0
  13. package/dist/adapters/opencode.js +120 -0
  14. package/dist/adapters/opencode.js.map +1 -0
  15. package/dist/adapters/process-utils.d.ts +29 -0
  16. package/dist/adapters/process-utils.d.ts.map +1 -0
  17. package/dist/adapters/process-utils.js +96 -0
  18. package/dist/adapters/process-utils.js.map +1 -0
  19. package/dist/adapters/types.d.ts +41 -0
  20. package/dist/adapters/types.d.ts.map +1 -0
  21. package/dist/adapters/types.js +6 -0
  22. package/dist/adapters/types.js.map +1 -0
  23. package/dist/assets.generated.d.ts +13 -0
  24. package/dist/assets.generated.d.ts.map +1 -0
  25. package/dist/assets.generated.js +162 -0
  26. package/dist/assets.generated.js.map +1 -0
  27. package/dist/beads.d.ts +85 -0
  28. package/dist/beads.d.ts.map +1 -0
  29. package/dist/beads.js +120 -0
  30. package/dist/beads.js.map +1 -0
  31. package/dist/cli.d.ts +3 -0
  32. package/dist/cli.d.ts.map +1 -0
  33. package/dist/cli.js +39 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/commands/add.d.ts +10 -0
  36. package/dist/commands/add.d.ts.map +1 -0
  37. package/dist/commands/add.js +58 -0
  38. package/dist/commands/add.js.map +1 -0
  39. package/dist/commands/cleanup.d.ts +13 -0
  40. package/dist/commands/cleanup.d.ts.map +1 -0
  41. package/dist/commands/cleanup.js +174 -0
  42. package/dist/commands/cleanup.js.map +1 -0
  43. package/dist/commands/daemon.d.ts +3 -0
  44. package/dist/commands/daemon.d.ts.map +1 -0
  45. package/dist/commands/daemon.js +162 -0
  46. package/dist/commands/daemon.js.map +1 -0
  47. package/dist/commands/init.d.ts +20 -0
  48. package/dist/commands/init.d.ts.map +1 -0
  49. package/dist/commands/init.js +125 -0
  50. package/dist/commands/init.js.map +1 -0
  51. package/dist/commands/install-keybinding.d.ts +61 -0
  52. package/dist/commands/install-keybinding.d.ts.map +1 -0
  53. package/dist/commands/install-keybinding.js +138 -0
  54. package/dist/commands/install-keybinding.js.map +1 -0
  55. package/dist/commands/install-status.d.ts +35 -0
  56. package/dist/commands/install-status.d.ts.map +1 -0
  57. package/dist/commands/install-status.js +115 -0
  58. package/dist/commands/install-status.js.map +1 -0
  59. package/dist/commands/log.d.ts +7 -0
  60. package/dist/commands/log.d.ts.map +1 -0
  61. package/dist/commands/log.js +60 -0
  62. package/dist/commands/log.js.map +1 -0
  63. package/dist/commands/pause.d.ts +12 -0
  64. package/dist/commands/pause.d.ts.map +1 -0
  65. package/dist/commands/pause.js +47 -0
  66. package/dist/commands/pause.js.map +1 -0
  67. package/dist/commands/resume.d.ts +12 -0
  68. package/dist/commands/resume.d.ts.map +1 -0
  69. package/dist/commands/resume.js +59 -0
  70. package/dist/commands/resume.js.map +1 -0
  71. package/dist/commands/shared.d.ts +7 -0
  72. package/dist/commands/shared.d.ts.map +1 -0
  73. package/dist/commands/shared.js +56 -0
  74. package/dist/commands/shared.js.map +1 -0
  75. package/dist/commands/start.d.ts +12 -0
  76. package/dist/commands/start.d.ts.map +1 -0
  77. package/dist/commands/start.js +274 -0
  78. package/dist/commands/start.js.map +1 -0
  79. package/dist/commands/status.d.ts +24 -0
  80. package/dist/commands/status.d.ts.map +1 -0
  81. package/dist/commands/status.js +101 -0
  82. package/dist/commands/status.js.map +1 -0
  83. package/dist/commands/stop.d.ts +11 -0
  84. package/dist/commands/stop.d.ts.map +1 -0
  85. package/dist/commands/stop.js +52 -0
  86. package/dist/commands/stop.js.map +1 -0
  87. package/dist/commands/teardown.d.ts +15 -0
  88. package/dist/commands/teardown.d.ts.map +1 -0
  89. package/dist/commands/teardown.js +72 -0
  90. package/dist/commands/teardown.js.map +1 -0
  91. package/dist/config.d.ts +58 -0
  92. package/dist/config.d.ts.map +1 -0
  93. package/dist/config.js +129 -0
  94. package/dist/config.js.map +1 -0
  95. package/dist/daemon/client.d.ts +38 -0
  96. package/dist/daemon/client.d.ts.map +1 -0
  97. package/dist/daemon/client.js +254 -0
  98. package/dist/daemon/client.js.map +1 -0
  99. package/dist/daemon/context.d.ts +63 -0
  100. package/dist/daemon/context.d.ts.map +1 -0
  101. package/dist/daemon/context.js +14 -0
  102. package/dist/daemon/context.js.map +1 -0
  103. package/dist/daemon/handlers.d.ts +79 -0
  104. package/dist/daemon/handlers.d.ts.map +1 -0
  105. package/dist/daemon/handlers.js +1260 -0
  106. package/dist/daemon/handlers.js.map +1 -0
  107. package/dist/daemon/index.d.ts +6 -0
  108. package/dist/daemon/index.d.ts.map +1 -0
  109. package/dist/daemon/index.js +7 -0
  110. package/dist/daemon/index.js.map +1 -0
  111. package/dist/daemon/lifecycle.d.ts +56 -0
  112. package/dist/daemon/lifecycle.d.ts.map +1 -0
  113. package/dist/daemon/lifecycle.js +341 -0
  114. package/dist/daemon/lifecycle.js.map +1 -0
  115. package/dist/daemon/protocol.d.ts +174 -0
  116. package/dist/daemon/protocol.d.ts.map +1 -0
  117. package/dist/daemon/protocol.js +3 -0
  118. package/dist/daemon/protocol.js.map +1 -0
  119. package/dist/daemon/recovery.d.ts +37 -0
  120. package/dist/daemon/recovery.d.ts.map +1 -0
  121. package/dist/daemon/recovery.js +197 -0
  122. package/dist/daemon/recovery.js.map +1 -0
  123. package/dist/daemon/server.d.ts +31 -0
  124. package/dist/daemon/server.d.ts.map +1 -0
  125. package/dist/daemon/server.js +294 -0
  126. package/dist/daemon/server.js.map +1 -0
  127. package/dist/daemon/socket.d.ts +18 -0
  128. package/dist/daemon/socket.d.ts.map +1 -0
  129. package/dist/daemon/socket.js +36 -0
  130. package/dist/daemon/socket.js.map +1 -0
  131. package/dist/daemon/state.d.ts +60 -0
  132. package/dist/daemon/state.d.ts.map +1 -0
  133. package/dist/daemon/state.js +156 -0
  134. package/dist/daemon/state.js.map +1 -0
  135. package/dist/daemon/systemd.d.ts +19 -0
  136. package/dist/daemon/systemd.d.ts.map +1 -0
  137. package/dist/daemon/systemd.js +131 -0
  138. package/dist/daemon/systemd.js.map +1 -0
  139. package/dist/hooks/claude-code-hook.d.ts +32 -0
  140. package/dist/hooks/claude-code-hook.d.ts.map +1 -0
  141. package/dist/hooks/claude-code-hook.js +112 -0
  142. package/dist/hooks/claude-code-hook.js.map +1 -0
  143. package/dist/instructions-template.d.ts +9 -0
  144. package/dist/instructions-template.d.ts.map +1 -0
  145. package/dist/instructions-template.js +123 -0
  146. package/dist/instructions-template.js.map +1 -0
  147. package/dist/logger.d.ts +25 -0
  148. package/dist/logger.d.ts.map +1 -0
  149. package/dist/logger.js +44 -0
  150. package/dist/logger.js.map +1 -0
  151. package/dist/loop.d.ts +88 -0
  152. package/dist/loop.d.ts.map +1 -0
  153. package/dist/loop.js +161 -0
  154. package/dist/loop.js.map +1 -0
  155. package/dist/orchestrator-instructions-template.d.ts +13 -0
  156. package/dist/orchestrator-instructions-template.d.ts.map +1 -0
  157. package/dist/orchestrator-instructions-template.js +147 -0
  158. package/dist/orchestrator-instructions-template.js.map +1 -0
  159. package/dist/output.d.ts +12 -0
  160. package/dist/output.d.ts.map +1 -0
  161. package/dist/output.js +25 -0
  162. package/dist/output.js.map +1 -0
  163. package/dist/plugin/pit.js +57 -0
  164. package/dist/session.d.ts +55 -0
  165. package/dist/session.d.ts.map +1 -0
  166. package/dist/session.js +135 -0
  167. package/dist/session.js.map +1 -0
  168. package/dist/setup.d.ts +92 -0
  169. package/dist/setup.d.ts.map +1 -0
  170. package/dist/setup.js +382 -0
  171. package/dist/setup.js.map +1 -0
  172. package/dist/shell-quote.d.ts +16 -0
  173. package/dist/shell-quote.d.ts.map +1 -0
  174. package/dist/shell-quote.js +18 -0
  175. package/dist/shell-quote.js.map +1 -0
  176. package/dist/signals.d.ts +17 -0
  177. package/dist/signals.d.ts.map +1 -0
  178. package/dist/signals.js +26 -0
  179. package/dist/signals.js.map +1 -0
  180. package/dist/state-machine.d.ts +74 -0
  181. package/dist/state-machine.d.ts.map +1 -0
  182. package/dist/state-machine.js +153 -0
  183. package/dist/state-machine.js.map +1 -0
  184. package/dist/tmux.d.ts +101 -0
  185. package/dist/tmux.d.ts.map +1 -0
  186. package/dist/tmux.js +208 -0
  187. package/dist/tmux.js.map +1 -0
  188. package/dist/worktree.d.ts +33 -0
  189. package/dist/worktree.d.ts.map +1 -0
  190. package/dist/worktree.js +116 -0
  191. package/dist/worktree.js.map +1 -0
  192. package/package.json +66 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 pit contributors
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 ADDED
@@ -0,0 +1,380 @@
1
+ # pit
2
+
3
+ [![CI](https://github.com/elhu/pit/actions/workflows/ci.yml/badge.svg)](https://github.com/elhu/pit/actions/workflows/ci.yml)
4
+
5
+ A tmux-based orchestrator that automates parallel AI coding agent sessions.
6
+
7
+ `pit` manages git worktrees, tmux windows, and agent TUIs (Claude Code or opencode),
8
+ driving each agent through a ticket loop powered by [beads](https://github.com/anomalyco/beads)
9
+ for issue tracking. The primary consumer of `pit` is an LLM in an orchestrator session --
10
+ the human talks to the model, the model calls `pit`.
11
+
12
+ ```
13
+ +-----------------+
14
+ | Orchestrator |
15
+ | (LLM session) |
16
+ +--------+--------+
17
+ |
18
+ pit CLI
19
+ |
20
+ +--------+--------+
21
+ | Daemon |
22
+ | (Unix socket) |
23
+ +--------+--------+
24
+ |
25
+ +--------------+--------------+
26
+ | | |
27
+ +-----+-----+ +-----+-----+ +-----+-----+
28
+ | Worktree 1 | | Worktree 2 | | Worktree 3 |
29
+ | tmux win 1 | | tmux win 2 | | tmux win 3 |
30
+ | Agent TUI | | Agent TUI | | Agent TUI |
31
+ +------------+ +------------+ +------------+
32
+ ```
33
+
34
+ ---
35
+
36
+ > **WARNING: EXPERIMENTAL SOFTWARE**
37
+ >
38
+ > ```
39
+ > _____
40
+ > / \
41
+ > | () () |
42
+ > \ ^ /
43
+ > |||||
44
+ > |||||
45
+ > ```
46
+ >
47
+ > **This software is highly experimental.** It is under active development, APIs will
48
+ > change without notice, and things will break.
49
+ >
50
+ > **This software deliberately bypasses AI agent security features.** `pit` launches
51
+ > Claude Code with `--dangerously-skip-permissions`, which disables ALL permission
52
+ > checks -- file writes, shell commands, network access, everything. Agents execute
53
+ > arbitrary commands without human confirmation.
54
+ >
55
+ > **This software is for people who like taking risks.** If you are not comfortable
56
+ > with autonomous AI agents running shell commands in your codebase without asking
57
+ > first, this is not for you. If "move fast and break things" makes you nervous
58
+ > rather than excited, look elsewhere.
59
+ >
60
+ > **This software is built using itself.** `pit` is developed with `pit` -- the
61
+ > codebase is almost entirely written by AI coding agents orchestrated by `pit`. If
62
+ > running AI-generated code makes you uncomfortable, this is not for you.
63
+ >
64
+ > **This software will burn through tokens.** `pit` runs autonomous agents that work
65
+ > fast but are not frugal. Multiple agents running in parallel, each looping through
66
+ > tickets, each with full context windows. Monitor your API usage. You have been
67
+ > warned twice now.
68
+ >
69
+ > **Do NOT use `pit` on untrusted repositories or with untrusted ticket content.** The
70
+ > agents will execute whatever they're told to, without confirmation. You have been
71
+ > warned.
72
+
73
+ ---
74
+
75
+ ## Philosophy
76
+
77
+ `pit` is opinionated software. It encodes a specific workflow for AI-assisted development
78
+ and does not try to be all things to all people.
79
+
80
+ **The core belief:** the quality of autonomous AI coding comes down to the quality of
81
+ the tickets. `pit`'s prompt loop is deliberately simplistic -- "find the next ticket and
82
+ work on it" -- because all the nuance, context, and constraints should live in the
83
+ tickets themselves. If you write vague tickets, you get vague results. If you write
84
+ detailed, unambiguous tickets with clear acceptance criteria, agents can execute
85
+ independently.
86
+
87
+ **Context is cleared between tickets.** When an agent finishes a ticket, `pit` clears
88
+ its conversation context before sending the next one. Each ticket starts fresh -- the
89
+ agent has no memory of previous tickets. This means tickets must be self-contained:
90
+ include all relevant context, file paths, and constraints in the ticket itself. In
91
+ practice this is rarely a problem if your tickets are well-written, and it prevents
92
+ context window pollution from accumulating over a long epic.
93
+
94
+ ### The Intended Workflow
95
+
96
+ 1. **Write requirements.** Start with a set of high-level requirements for the feature
97
+ or project you want to build.
98
+
99
+ 2. **Refine into detailed beads.** Break the requirements down into highly detailed
100
+ beads tickets. Each ticket should contain enough context for a coding agent to pick
101
+ it up and execute independently -- the problem statement, relevant file paths,
102
+ expected behavior, edge cases, and constraints. This is where you invest your time.
103
+
104
+ 3. **Set up your AGENTS.md.** Your project's AGENTS.md (or equivalent agent
105
+ instructions file) should contain the "landing the plane" instructions -- quality
106
+ gates to run, what to commit, when to push, coding conventions. This is the
107
+ persistent context every agent session gets. `pit` injects its orchestrator
108
+ instructions here via `pit init`.
109
+
110
+ 4. **Let `pit` run.** `pit start --epics <epic-id>` spins up agents and they work through
111
+ tickets autonomously. Monitor with `pit status`, intervene when agents pause.
112
+
113
+ 5. **Merge and clean up.** Once an epic is done, the human operator (or an agent you
114
+ instruct) merges the worktree branch back to main, runs quality gates, pushes, and
115
+ calls `pit teardown` to clean up all `pit` artifacts.
116
+
117
+ `pit` does not try to be smart about what agents do. It manages the plumbing -- worktrees,
118
+ tmux sessions, idle detection, ticket cycling -- and gets out of the way. The
119
+ intelligence lives in your tickets and your AGENTS.md.
120
+
121
+ ## How It Works
122
+
123
+ 1. You set up an epic (a group of tickets) using [beads](https://github.com/anomalyco/beads)
124
+ 2. You run `pit start --epics <epic-id>`
125
+ 3. `pit` creates one git worktree + tmux window + agent TUI per epic
126
+ 4. Each agent autonomously loops: pick ticket, work on it, commit, push, pick next
127
+ 5. You monitor with `pit status`, intervene with `pit pause`/`pit resume`
128
+ 6. When an epic completes, you merge the worktree branch back
129
+
130
+ Agents work in isolated git worktrees so they don't interfere with each other or your
131
+ main checkout. Each agent has its own branch, its own files, its own tmux window.
132
+
133
+ ## Watching and Intervening
134
+
135
+ `pit` runs agents inside a tmux session (named `pit` by default). You can attach to it
136
+ at any time to watch agents work in real time:
137
+
138
+ ```bash
139
+ tmux attach -t pit
140
+ ```
141
+
142
+ Use tmux's normal window-switching keys (`Ctrl-b n` / `Ctrl-b p`) to move between
143
+ epic windows. Each window is named `epic-<id>` and shows the agent's TUI.
144
+
145
+ From any terminal (you don't need to be attached to tmux), you can:
146
+
147
+ ```bash
148
+ # Check what all agents are doing
149
+ pit status --pretty
150
+
151
+ # Read an agent's recent output without attaching to tmux
152
+ pit log my-epic --lines 100
153
+
154
+ # Pause an agent that's going in circles
155
+ pit pause my-epic
156
+
157
+ # Resume with specific guidance
158
+ pit resume my-epic --message "The config file is in src/config.ts, not lib/config.ts"
159
+
160
+ # Resume without a message (re-prompts with the next ticket)
161
+ pit resume my-epic
162
+ ```
163
+
164
+ You can also install tmux integrations for quicker access:
165
+
166
+ ```bash
167
+ pit install-keybinding # Binds prefix+R to resume and prefix+H to pause the current epic
168
+ pit install-status # Appends #{@pit-status} to the tmux status bar
169
+ ```
170
+
171
+ ## Prerequisites
172
+
173
+ - **Node.js** >= 24
174
+ - **tmux** installed and available in PATH
175
+ - **beads** (`bd`) installed and available in PATH
176
+ - **An AI coding agent**: [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (`claude`) or [opencode](https://opencode.ai) (`opencode`)
177
+ - A git repository with beads epics and tickets set up
178
+
179
+ ## Install
180
+
181
+ ```bash
182
+ npm install -g pit
183
+ ```
184
+
185
+ Or clone and build from source:
186
+
187
+ ```bash
188
+ git clone https://github.com/anomalyco/pit.git
189
+ cd pit
190
+ npm install
191
+ npm run build
192
+ npm link
193
+ ```
194
+
195
+ ## Quick Start
196
+
197
+ ```bash
198
+ # 1. Initialize pit in your project (injects orchestrator instructions into AGENTS.md)
199
+ pit init
200
+
201
+ # 2. Optionally configure pit (or just use defaults)
202
+ cat > .pit.json << 'EOF'
203
+ {
204
+ "agent": "auto",
205
+ "baseBranch": "main"
206
+ }
207
+ EOF
208
+
209
+ # 3. Make sure you have beads epics set up
210
+ bd list
211
+
212
+ # 4. Start agents for one or more epics
213
+ pit start --epics my-epic-id
214
+
215
+ # 5. Monitor progress
216
+ pit status
217
+ pit status --pretty
218
+
219
+ # 6. Read agent output
220
+ pit log my-epic-id
221
+
222
+ # 7. Pause/resume as needed
223
+ pit pause my-epic-id
224
+ pit resume my-epic-id --message "Try a different approach for the auth module"
225
+
226
+ # 8. Clean up when done
227
+ pit teardown
228
+ ```
229
+
230
+ ## CLI Reference
231
+
232
+ All commands output JSON by default (for LLM consumption). Add `--pretty` for
233
+ human-readable output.
234
+
235
+ | Command | Description |
236
+ | ------------------------- | ----------------------------------------------------------- |
237
+ | `pit init` | Inject orchestrator instructions into AGENTS.md |
238
+ | `pit start --epics <ids>` | Start agent sessions for given epic IDs |
239
+ | `pit status` | Show status of all running epics |
240
+ | `pit log <epic>` | Capture agent's recent terminal output |
241
+ | `pit pause <epic>` | Pause a running epic |
242
+ | `pit resume <epic>` | Resume a paused epic (optionally with `--message`) |
243
+ | `pit stop [epic]` | Stop epic(s), transition to done |
244
+ | `pit add <epic>` | Add an epic to a running session |
245
+ | `pit teardown [epic]` | Tear down epics and clean up resources |
246
+ | `pit cleanup` | Garbage-collect stale session directories |
247
+ | `pit daemon <cmd>` | Manage the background daemon (start/stop/status/restart) |
248
+ | `pit install-keybinding` | Install tmux keybindings for quick resume (R) and pause (H) |
249
+ | `pit install-status` | Append `#{@pit-status}` to the tmux status bar |
250
+
251
+ For detailed flag reference, examples, and edge cases, see [docs/cli.md](docs/cli.md).
252
+
253
+ ## Configuration
254
+
255
+ `pit` reads `.pit.json` from the project root. CLI flags override file values.
256
+
257
+ ```jsonc
258
+ {
259
+ // Which coding agent to run in each tmux window.
260
+ // "auto" - tries opencode first, falls back to claude-code
261
+ // "opencode" - use opencode (https://opencode.ai)
262
+ // "claude-code" - use Claude Code (https://docs.anthropic.com/en/docs/claude-code)
263
+ "agent": "auto",
264
+
265
+ // Model passed to the agent CLI. Format depends on the agent:
266
+ // Claude Code: "claude-sonnet-4-20250514", "claude-opus-4-20250514", etc.
267
+ // opencode: "anthropic/claude-sonnet-4-20250514", etc.
268
+ // null = let the agent use its default model.
269
+ "model": null,
270
+
271
+ "worktreeDir": ".worktrees", // Where git worktrees are created
272
+ "baseBranch": "main", // Branch worktrees are created from
273
+ "tmuxSession": "pit", // tmux session name
274
+
275
+ "clearDelay": 2000, // Ms to wait after clearing agent context
276
+ "initDelay": 5000, // Ms to wait for agent TUI to start
277
+ "ticketTimeout": null, // Minutes before auto-pausing a ticket (null = no limit)
278
+ }
279
+ ```
280
+
281
+ | Field | Default | Description |
282
+ | --------------- | -------------- | ---------------------------------------------------------------- |
283
+ | `agent` | `"auto"` | Agent type: `auto`, `opencode`, or `claude-code` |
284
+ | `model` | `null` | Model to pass to the agent CLI (null = agent default) |
285
+ | `worktreeDir` | `".worktrees"` | Directory for git worktrees |
286
+ | `baseBranch` | `"main"` | Base branch for worktrees |
287
+ | `tmuxSession` | `"pit"` | tmux session name |
288
+ | `clearDelay` | `2000` | Ms to wait before clearing agent context after ticket completion |
289
+ | `initDelay` | `5000` | Ms to wait before starting the agent after setup |
290
+ | `ticketTimeout` | `null` | Minutes before a ticket auto-pauses the agent (null = disabled) |
291
+
292
+ ## Security Model
293
+
294
+ `pit` is designed for autonomous agent operation. This comes with deliberate trade-offs:
295
+
296
+ - **Claude Code** is launched with `--dangerously-skip-permissions`, bypassing all
297
+ permission checks. The agent can read/write any file, run any shell command, and
298
+ make network requests without human approval.
299
+ - **opencode** uses its plugin system for event detection. Permission handling is
300
+ managed through the plugin bridge.
301
+ - Each agent runs in an **isolated git worktree**, not your main checkout. The
302
+ worktree is disposable and can be recreated from the base branch.
303
+ - The daemon communicates over a **Unix domain socket** in `/tmp/pit/`. No network
304
+ exposure.
305
+
306
+ **This is intentional.** `pit` exists to let agents work autonomously. If you need
307
+ human-in-the-loop approval for every file write, `pit` is the wrong tool.
308
+
309
+ **Mitigations:**
310
+
311
+ - Worktree isolation limits blast radius
312
+ - Worktrees are on branches, not main -- you review before merging
313
+ - `pit pause` lets you halt an agent at any time
314
+ - `pit teardown` cleans everything up
315
+
316
+ ## Documentation
317
+
318
+ | Document | Audience | Description |
319
+ | ---------------------------------------------- | ----------------- | ----------------------------------------------------------- |
320
+ | [docs/cli.md](docs/cli.md) | Agents + humans | Detailed per-command reference |
321
+ | [docs/architecture.md](docs/architecture.md) | Agents + humans | Internal architecture and design |
322
+ | [docs/orchestration.md](docs/orchestration.md) | Orchestrator LLMs | How to drive `pit` from an LLM session |
323
+ | [AGENTS.md](AGENTS.md) | Coding agents | Conventions and workflow for agents working on `pit` itself |
324
+
325
+ ## Releasing
326
+
327
+ Releases are published to npm and GitHub Releases automatically by CI when a version
328
+ tag is pushed. Use the release script to bump the version and push the tag:
329
+
330
+ ```bash
331
+ # Patch release (e.g. 1.2.3 -> 1.2.4)
332
+ npm run release -- patch
333
+
334
+ # Minor release (e.g. 1.2.3 -> 1.3.0)
335
+ npm run release -- minor
336
+
337
+ # Major release (e.g. 1.2.3 -> 2.0.0)
338
+ npm run release -- major
339
+
340
+ # Explicit version
341
+ npm run release -- 1.2.3
342
+ ```
343
+
344
+ The script will:
345
+
346
+ 1. Verify a clean working tree and that you're on `main`
347
+ 2. Pull latest from origin
348
+ 3. Run local quality gates (`npm test`, `npm run test:e2e`, `npm run lint`, `npm run build`)
349
+ 4. Bump the version and create a git commit + tag via `npm version`
350
+ 5. Push the commit and tag (`git push --follow-tags`), triggering the CI publish workflow
351
+ 6. Print a link to GitHub Actions so you can monitor the publish
352
+
353
+ CI handles the actual `npm publish` and GitHub Release creation — you do not need to
354
+ run `npm publish` manually.
355
+
356
+ ### What CI does automatically
357
+
358
+ When a `v*` tag is pushed, the [Publish workflow](.github/workflows/publish.yml):
359
+
360
+ 1. Verifies the tag matches the version in `package.json`
361
+ 2. Runs quality gates (lint, build, unit tests, E2E tests)
362
+ 3. Publishes the package to npm (`npm publish --access public`)
363
+ 4. Creates a GitHub Release with auto-generated release notes
364
+
365
+ ### Required secrets
366
+
367
+ The repository must have an `NPM_TOKEN` secret set in GitHub Actions:
368
+
369
+ 1. Go to [npmjs.com](https://www.npmjs.com) → Account → Access Tokens → Generate New Token
370
+ 2. Choose **Automation** token type (bypasses 2FA requirement for CI publishing)
371
+ 3. Add the token to GitHub: Repository → Settings → Secrets and variables → Actions → `NPM_TOKEN`
372
+
373
+ ### Verifying a release
374
+
375
+ Monitor the publish workflow at:
376
+ [https://github.com/elhu/pit/actions/workflows/publish.yml](https://github.com/elhu/pit/actions/workflows/publish.yml)
377
+
378
+ ## License
379
+
380
+ [MIT](LICENSE)
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ClaudeCodeAdapter — implements AgentAdapter for the Claude Code CLI agent.
3
+ *
4
+ * Claude Code is a CLI tool (`claude`) that reads instructions from CLAUDE.md
5
+ * in the worktree. Hooks are installed into .claude/hooks/ and registered in
6
+ * .claude/settings.local.json for Stop events.
7
+ *
8
+ * ## Permission handling
9
+ *
10
+ * Claude Code is launched with `--dangerously-skip-permissions` so that the
11
+ * agent can work autonomously without interactive permission prompts blocking
12
+ * the tmux session. This flag bypasses **all** permission checks — file writes,
13
+ * shell commands, network access, etc. — which is acceptable because:
14
+ *
15
+ * 1. Each agent runs in an isolated git worktree, not the main checkout.
16
+ * 2. The worktree is disposable and can be recreated from the base branch.
17
+ * 3. pit is designed for autonomous agent operation where human approval
18
+ * for every tool call would defeat the purpose.
19
+ *
20
+ * **Security note:** Do NOT use pit (or this flag) on untrusted repositories
21
+ * or with untrusted ticket content. The agent will execute arbitrary commands
22
+ * without confirmation.
23
+ */
24
+ import type { AgentAdapter } from "./types.js";
25
+ export declare class ClaudeCodeAdapter implements AgentAdapter {
26
+ readonly name = "claude-code";
27
+ startCommand(_worktree: string, _env: Record<string, string>, model?: string): string;
28
+ /** Claude Code is a full-screen TUI; use timeout-based readiness. */
29
+ readonly readinessPattern: undefined;
30
+ readonly clearCommand = "/clear";
31
+ /**
32
+ * Install the pit hook into the worktree's .claude/hooks/ directory and
33
+ * register it in .claude/settings.local.json for the Stop event (idle
34
+ * detection). PermissionRequest hooks are not needed because the agent is
35
+ * launched with --dangerously-skip-permissions.
36
+ *
37
+ * The hook content is embedded as an inline string (CLAUDE_CODE_HOOK_JS) at
38
+ * build time, so it is always the correct version regardless of where pit is
39
+ * installed globally (npm link, npm install -g, etc.). Resolving via __dirname
40
+ * was unreliable because it pointed to the global install's dist directory
41
+ * rather than the worktree's bundled copy.
42
+ */
43
+ installEventBridge(worktreeDir: string, _epic: string): Promise<void>;
44
+ /**
45
+ * Write agent instructions to CLAUDE.md using PIT:MANAGED markers.
46
+ * Creates the section if absent; replaces it if present (idempotent).
47
+ * Preserves any content outside the managed section.
48
+ */
49
+ writeInstructions(worktreeDir: string, content: string): Promise<void>;
50
+ /**
51
+ * Check whether the claude CLI is available on PATH.
52
+ * Returns true if `which claude` exits 0, false otherwise.
53
+ */
54
+ checkInstalled(): Promise<boolean>;
55
+ /**
56
+ * Wait for Claude Code to be ready using a simple timeout.
57
+ */
58
+ waitForReady({ timeoutMs }: {
59
+ timeoutMs: number;
60
+ }): Promise<void>;
61
+ /**
62
+ * Verify the Claude Code process is running in the given tmux window.
63
+ *
64
+ * The tmux pane PID is the shell (zsh/bash), not claude itself.
65
+ * We walk the process tree rooted at the pane PID and check whether any
66
+ * descendant process has a comm of "claude" or "node".
67
+ */
68
+ verifyRunning(tmuxSession: string, windowName: string): Promise<boolean>;
69
+ }
70
+ //# sourceMappingURL=claude-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAc/C,qBAAa,iBAAkB,YAAW,YAAY;IACpD,QAAQ,CAAC,IAAI,iBAAiB;IAE9B,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAKrF,qEAAqE;IACrE,QAAQ,CAAC,gBAAgB,YAAa;IAEtC,QAAQ,CAAC,YAAY,YAAY;IAEjC;;;;;;;;;;;OAWG;IACG,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2C3E;;;;OAIG;IACG,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC5E;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAQxC;;OAEG;IACG,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE;;;;;;OAMG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAkB/E"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * ClaudeCodeAdapter — implements AgentAdapter for the Claude Code CLI agent.
3
+ *
4
+ * Claude Code is a CLI tool (`claude`) that reads instructions from CLAUDE.md
5
+ * in the worktree. Hooks are installed into .claude/hooks/ and registered in
6
+ * .claude/settings.local.json for Stop events.
7
+ *
8
+ * ## Permission handling
9
+ *
10
+ * Claude Code is launched with `--dangerously-skip-permissions` so that the
11
+ * agent can work autonomously without interactive permission prompts blocking
12
+ * the tmux session. This flag bypasses **all** permission checks — file writes,
13
+ * shell commands, network access, etc. — which is acceptable because:
14
+ *
15
+ * 1. Each agent runs in an isolated git worktree, not the main checkout.
16
+ * 2. The worktree is disposable and can be recreated from the base branch.
17
+ * 3. pit is designed for autonomous agent operation where human approval
18
+ * for every tool call would defeat the purpose.
19
+ *
20
+ * **Security note:** Do NOT use pit (or this flag) on untrusted repositories
21
+ * or with untrusted ticket content. The agent will execute arbitrary commands
22
+ * without confirmation.
23
+ */
24
+ import { execFile } from "node:child_process";
25
+ import fs from "node:fs/promises";
26
+ import path from "node:path";
27
+ import { execTmux } from "../tmux.js";
28
+ import { shellQuote } from "../shell-quote.js";
29
+ import { CLAUDE_CODE_HOOK_JS } from "../assets.generated.js";
30
+ import { hasAgentDescendant } from "./process-utils.js";
31
+ /**
32
+ * Names that indicate Claude Code is running as a descendant process.
33
+ * Claude Code is distributed as "claude" CLI, but may run via Node.js.
34
+ */
35
+ const CLAUDE_CODE_COMM_NAMES = new Set(["claude", "node"]);
36
+ const PIT_HOOK_COMMAND = `node "$CLAUDE_PROJECT_DIR/.claude/hooks/pit-hook.js"`;
37
+ const PIT_HOOK_MARKER = "pit-hook.js";
38
+ const MANAGED_BEGIN = "<!-- PIT:MANAGED:BEGIN -->";
39
+ const MANAGED_END = "<!-- PIT:MANAGED:END -->";
40
+ export class ClaudeCodeAdapter {
41
+ name = "claude-code";
42
+ startCommand(_worktree, _env, model) {
43
+ const base = "claude --dangerously-skip-permissions";
44
+ return model ? `${base} --model ${shellQuote(model)}` : base;
45
+ }
46
+ /** Claude Code is a full-screen TUI; use timeout-based readiness. */
47
+ readinessPattern = undefined;
48
+ clearCommand = "/clear";
49
+ /**
50
+ * Install the pit hook into the worktree's .claude/hooks/ directory and
51
+ * register it in .claude/settings.local.json for the Stop event (idle
52
+ * detection). PermissionRequest hooks are not needed because the agent is
53
+ * launched with --dangerously-skip-permissions.
54
+ *
55
+ * The hook content is embedded as an inline string (CLAUDE_CODE_HOOK_JS) at
56
+ * build time, so it is always the correct version regardless of where pit is
57
+ * installed globally (npm link, npm install -g, etc.). Resolving via __dirname
58
+ * was unreliable because it pointed to the global install's dist directory
59
+ * rather than the worktree's bundled copy.
60
+ */
61
+ async installEventBridge(worktreeDir, _epic) {
62
+ const hooksDir = path.join(worktreeDir, ".claude", "hooks");
63
+ await fs.mkdir(hooksDir, { recursive: true });
64
+ const destPath = path.join(hooksDir, "pit-hook.js");
65
+ await fs.writeFile(destPath, CLAUDE_CODE_HOOK_JS, "utf8");
66
+ const settingsPath = path.join(worktreeDir, ".claude", "settings.local.json");
67
+ let config = {};
68
+ try {
69
+ const raw = await fs.readFile(settingsPath, "utf8");
70
+ config = JSON.parse(raw);
71
+ }
72
+ catch {
73
+ // File does not exist or is invalid JSON — start fresh
74
+ }
75
+ // Register the pit hook for the Stop event (agent-idle detection).
76
+ // PermissionRequest hooks are not needed because Claude Code is launched
77
+ // with --dangerously-skip-permissions (see startCommand / class doc).
78
+ const hooks = (config.hooks ?? {});
79
+ config.hooks = hooks;
80
+ const pitMatcher = {
81
+ hooks: [{ type: "command", command: PIT_HOOK_COMMAND }],
82
+ };
83
+ for (const event of ["Stop"]) {
84
+ if (!Array.isArray(hooks[event])) {
85
+ hooks[event] = [];
86
+ }
87
+ const existingEntries = hooks[event];
88
+ const alreadyInstalled = JSON.stringify(existingEntries).includes(PIT_HOOK_MARKER);
89
+ if (!alreadyInstalled) {
90
+ existingEntries.push(pitMatcher);
91
+ }
92
+ }
93
+ await fs.writeFile(settingsPath, JSON.stringify(config, null, 2) + "\n", "utf8");
94
+ }
95
+ /**
96
+ * Write agent instructions to CLAUDE.md using PIT:MANAGED markers.
97
+ * Creates the section if absent; replaces it if present (idempotent).
98
+ * Preserves any content outside the managed section.
99
+ */
100
+ async writeInstructions(worktreeDir, content) {
101
+ const mdPath = path.join(worktreeDir, "CLAUDE.md");
102
+ let existing = "";
103
+ try {
104
+ existing = await fs.readFile(mdPath, "utf8");
105
+ }
106
+ catch {
107
+ // File does not exist — will create it
108
+ }
109
+ const managedSection = `${MANAGED_BEGIN}\n${content}\n${MANAGED_END}\n`;
110
+ let updated;
111
+ if (existing.includes(MANAGED_BEGIN) && existing.includes(MANAGED_END)) {
112
+ // Replace existing managed section (inclusive of markers)
113
+ const beginIdx = existing.indexOf(MANAGED_BEGIN);
114
+ const endIdx = existing.indexOf(MANAGED_END) + MANAGED_END.length;
115
+ // Include trailing newline if present
116
+ const afterEnd = existing[endIdx] === "\n" ? endIdx + 1 : endIdx;
117
+ updated = existing.slice(0, beginIdx) + managedSection + existing.slice(afterEnd);
118
+ }
119
+ else if (existing === "") {
120
+ // Empty file — write managed section directly without leading newlines
121
+ updated = managedSection;
122
+ }
123
+ else {
124
+ // Non-empty file without markers — append
125
+ updated = existing + "\n\n" + managedSection;
126
+ }
127
+ await fs.writeFile(mdPath, updated, "utf8");
128
+ }
129
+ /**
130
+ * Check whether the claude CLI is available on PATH.
131
+ * Returns true if `which claude` exits 0, false otherwise.
132
+ */
133
+ async checkInstalled() {
134
+ return new Promise((resolve) => {
135
+ execFile("which", ["claude"], (err) => {
136
+ resolve(!err);
137
+ });
138
+ });
139
+ }
140
+ /**
141
+ * Wait for Claude Code to be ready using a simple timeout.
142
+ */
143
+ async waitForReady({ timeoutMs }) {
144
+ await new Promise((resolve) => setTimeout(resolve, timeoutMs));
145
+ }
146
+ /**
147
+ * Verify the Claude Code process is running in the given tmux window.
148
+ *
149
+ * The tmux pane PID is the shell (zsh/bash), not claude itself.
150
+ * We walk the process tree rooted at the pane PID and check whether any
151
+ * descendant process has a comm of "claude" or "node".
152
+ */
153
+ async verifyRunning(tmuxSession, windowName) {
154
+ try {
155
+ const { stdout } = await execTmux("list-panes", "-t", `${tmuxSession}:${windowName}`, "-F", "#{pane_pid}");
156
+ const panePid = stdout.trim();
157
+ if (!panePid)
158
+ return false;
159
+ return await hasAgentDescendant(panePid, CLAUDE_CODE_COMM_NAMES);
160
+ }
161
+ catch {
162
+ return false;
163
+ }
164
+ }
165
+ }
166
+ //# sourceMappingURL=claude-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/adapters/claude-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGxD;;;GAGG;AACH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAE3D,MAAM,gBAAgB,GAAG,sDAAsD,CAAC;AAChF,MAAM,eAAe,GAAG,aAAa,CAAC;AAEtC,MAAM,aAAa,GAAG,4BAA4B,CAAC;AACnD,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAE/C,MAAM,OAAO,iBAAiB;IACnB,IAAI,GAAG,aAAa,CAAC;IAE9B,YAAY,CAAC,SAAiB,EAAE,IAA4B,EAAE,KAAc;QAC1E,MAAM,IAAI,GAAG,uCAAuC,CAAC;QACrD,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,YAAY,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,CAAC;IAED,qEAAqE;IAC5D,gBAAgB,GAAG,SAAS,CAAC;IAE7B,YAAY,GAAG,QAAQ,CAAC;IAEjC;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,kBAAkB,CAAC,WAAmB,EAAE,KAAa;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACpD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,mBAAmB,EAAE,MAAM,CAAC,CAAC;QAE1D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;QAC9E,IAAI,MAAM,GAA4B,EAAE,CAAC;QAEzC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YACpD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,uDAAuD;QACzD,CAAC;QAED,mEAAmE;QACnE,yEAAyE;QACzE,sEAAsE;QACtE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAA8B,CAAC;QAChE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QAErB,MAAM,UAAU,GAAG;YACjB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;SACxD,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,CAAC,MAAM,CAAU,EAAE,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACpB,CAAC;YAED,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAc,CAAC;YAClD,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;YAEnF,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IACnF,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,iBAAiB,CAAC,WAAmB,EAAE,OAAe;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAEnD,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,uCAAuC;QACzC,CAAC;QAED,MAAM,cAAc,GAAG,GAAG,aAAa,KAAK,OAAO,KAAK,WAAW,IAAI,CAAC;QAExE,IAAI,OAAe,CAAC;QAEpB,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACvE,0DAA0D;YAC1D,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC;YAClE,sCAAsC;YACtC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACjE,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,cAAc,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpF,CAAC;aAAM,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;YAC3B,uEAAuE;YACvE,OAAO,GAAG,cAAc,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,0CAA0C;YAC1C,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,cAAc,CAAC;QAC/C,CAAC;QAED,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;gBACpC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,EAAE,SAAS,EAAyB;QACrD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IACvE,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,UAAkB;QACzD,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAC/B,YAAY,EACZ,IAAI,EACJ,GAAG,WAAW,IAAI,UAAU,EAAE,EAC9B,IAAI,EACJ,aAAa,CACd,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO;gBAAE,OAAO,KAAK,CAAC;YAE3B,OAAO,MAAM,kBAAkB,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Adapter factory — resolves the correct AgentAdapter based on the requested
3
+ * agent name, or auto-detects based on what is installed.
4
+ */
5
+ import type { AgentAdapter } from "./types.js";
6
+ /**
7
+ * Resolve an AgentAdapter by name.
8
+ *
9
+ * @param agent - "auto" | "opencode" | "claude-code"
10
+ * @returns The resolved adapter (Promise<AgentAdapter>)
11
+ *
12
+ * "auto" tries opencode first, then claude-code. Throws if neither is installed.
13
+ * Named agents throw if not installed.
14
+ */
15
+ export declare function resolveAdapter(agent: string): Promise<AgentAdapter>;
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAW/C;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCzE"}