@clipboard-health/groundcrew 4.0.0 → 4.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 +248 -289
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -42,92 +42,106 @@ Eligibility
|
|
|
42
42
|
- **Linear-native.** Polls issues assigned to the API key's viewer with `agent-*` labels, honors blockers.
|
|
43
43
|
- **One worktree per ticket.** Agents work in parallel without stepping on each other.
|
|
44
44
|
- **Local-first sandboxing.** Safehouse on macOS, Docker Sandboxes on Linux, or an explicit `none` escape hatch.
|
|
45
|
-
- **Multi-agent.** Ships with `claude` and `codex`; bring your own CLI
|
|
46
|
-
|
|
47
|
-
## Install
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
npm install -g @clipboard-health/groundcrew
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Installs the `crew` binary. `@clipboard-health/clearance` is pulled in transitively and provides the `clearance` / `clearance-ensure` bins used by Safehouse runs.
|
|
45
|
+
- **Multi-agent.** Ships with `claude` and `codex`; bring your own CLI via `crew.config.ts`.
|
|
54
46
|
|
|
55
47
|
## Quickstart
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
2. **Pick an isolation runner.** See [Runners](#runners) — `auto` resolves to `safehouse` on macOS and `sdx` on Linux/WSL.
|
|
60
|
-
|
|
61
|
-
3. **Prepare tickets in Linear.** Assign tickets to yourself and add an `agent-*` label. Groundcrew picks them up across all visible teams and projects.
|
|
62
|
-
|
|
63
|
-
4. **Configure.** Create a `crew.config.ts` you can edit:
|
|
49
|
+
```bash
|
|
50
|
+
# 1. Install Node ≥ 24, git, cmux or tmux, and the agent CLIs you'll use (claude, codex, ...).
|
|
64
51
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
crew init && $EDITOR crew.config.ts
|
|
52
|
+
# 2. Install groundcrew
|
|
53
|
+
npm install -g @clipboard-health/groundcrew
|
|
68
54
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
```
|
|
55
|
+
# 3. Scaffold a config and edit workspace.projectDir + workspace.knownRepositories
|
|
56
|
+
crew init && $EDITOR crew.config.ts
|
|
72
57
|
|
|
73
|
-
|
|
58
|
+
# 4. Clone the repos referenced in your config
|
|
59
|
+
crew setup repos
|
|
74
60
|
|
|
75
|
-
|
|
61
|
+
# 5. Export your Linear API key
|
|
62
|
+
export GROUNDCREW_LINEAR_API_KEY="lin_api_..."
|
|
76
63
|
|
|
77
|
-
|
|
64
|
+
# 6. Verify setup, then dispatch
|
|
65
|
+
crew doctor
|
|
66
|
+
crew run --watch
|
|
67
|
+
```
|
|
78
68
|
|
|
79
|
-
|
|
69
|
+
In Linear, assign tickets to yourself and add an `agent-*` label (`agent-claude`, `agent-codex`, or `agent-any`). Groundcrew picks them up across every team and project your API key can see.
|
|
80
70
|
|
|
81
|
-
|
|
82
|
-
crew setup repos # clone all missing entries via gh
|
|
83
|
-
crew setup repos --dry-run # preview
|
|
84
|
-
crew setup repos owner/repo # restrict to one entry
|
|
85
|
-
```
|
|
71
|
+
`crew init --global` writes the config into `${XDG_CONFIG_HOME:-$HOME/.config}/groundcrew/` instead of the cwd. Both forms refuse to overwrite — pass `--force` to replace, `--dry-run` to preview.
|
|
86
72
|
|
|
87
|
-
|
|
73
|
+
## Commands
|
|
88
74
|
|
|
89
|
-
|
|
75
|
+
```bash
|
|
76
|
+
crew init [--global | --local] [--force] [--dry-run] # create a crew.config.ts
|
|
77
|
+
crew doctor # check setup
|
|
78
|
+
crew doctor --ticket <TICKET> # diagnose a specific ticket
|
|
79
|
+
crew run # one-shot dispatch
|
|
80
|
+
crew run --watch # poll forever
|
|
81
|
+
crew run --ticket <TICKET> # dispatch one ticket
|
|
82
|
+
crew setup repos [<repo>...] [--dry-run] # clone known repos via gh
|
|
83
|
+
crew interrupt <TICKET> [--reason <text>] # stop workspace, keep worktree
|
|
84
|
+
crew resume <TICKET> # reopen a paused ticket
|
|
85
|
+
crew cleanup <TICKET> # tear down every worktree for a ticket
|
|
86
|
+
```
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
export GROUNDCREW_LINEAR_API_KEY="lin_api_..."
|
|
93
|
-
```
|
|
88
|
+
## Configuration
|
|
94
89
|
|
|
95
|
-
|
|
96
|
-
<summary>Using 1Password (<code>op</code>) for the key</summary>
|
|
90
|
+
Two keys are required; everything else has a default.
|
|
97
91
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
| Key | What |
|
|
93
|
+
| ----------------------------- | ---------------------------------------------------------------------- |
|
|
94
|
+
| `workspace.projectDir` | Parent dir for cloned repos and sibling ticket worktrees. |
|
|
95
|
+
| `workspace.knownRepositories` | Repos searched for in ticket descriptions to infer where work belongs. |
|
|
102
96
|
|
|
103
|
-
|
|
97
|
+
The branch prefix (`<prefix>-<TICKET>`) is derived from `os.userInfo().username` and isn't configurable. There is no `linear` config block — groundcrew picks up every issue assigned to your API key's viewer that carries an `agent-*` label across every visible team and project, governed by a single `orchestrator.maximumInProgress` budget.
|
|
104
98
|
|
|
105
|
-
|
|
99
|
+
<details>
|
|
100
|
+
<summary>Agent label routing</summary>
|
|
106
101
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
- `agent-claude`, `agent-codex`, `agent-<name>` → that model.
|
|
103
|
+
- `agent-any` → the model with the most available session capacity.
|
|
104
|
+
- Unknown `agent-<name>` → falls back to `models.default` with a warning.
|
|
105
|
+
- No `agent-*` label → ignored by `crew run`. Dispatch on demand with `crew run --ticket <TICKET>` (also falls back to `models.default`).
|
|
106
|
+
- Todo tickets blocked by non-terminal blockers are skipped until their blockers reach a terminal status.
|
|
112
107
|
|
|
113
|
-
|
|
108
|
+
Status classification uses Linear's workflow `state.type` (`unstarted`, `started`, `completed`, `canceled`, `duplicate`), so renamed status columns work without configuration. Parent issues with children are ignored — sub-issues are the work items.
|
|
114
109
|
|
|
115
|
-
|
|
110
|
+
</details>
|
|
116
111
|
|
|
117
|
-
|
|
112
|
+
<details>
|
|
113
|
+
<summary>Config discovery</summary>
|
|
118
114
|
|
|
119
|
-
- `
|
|
120
|
-
- `BUF_TOKEN`
|
|
115
|
+
Resolution order: `GROUNDCREW_CONFIG` → cosmiconfig project-walk from cwd (any of `crew.config.{ts,mjs,js,json}`, `.crewrc{,.json,.ts}`, `.config/crew.config.{ts,json}`, `.config/crewrc{,.json}`) → `${XDG_CONFIG_HOME:-$HOME/.config}/groundcrew/crew.config.ts` (legacy `config.ts` accepted for one release). The "Loaded config from …" line at startup tells you which won.
|
|
121
116
|
|
|
122
|
-
|
|
117
|
+
</details>
|
|
123
118
|
|
|
124
|
-
|
|
119
|
+
<details>
|
|
120
|
+
<summary>Full configuration reference</summary>
|
|
125
121
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
122
|
+
| Key | Default | What it does |
|
|
123
|
+
| --------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
124
|
+
| `sources` | `[]` | Additional pluggable ticket sources. Extra sources are verified at startup; the built-in Linear adapter remains the dispatch read path until the canonical consumer refactor. Built-in kinds: `shell`, `linear`. |
|
|
125
|
+
| `git.remote` | `"origin"` | Remote used for `fetch` and as the worktree base ref. |
|
|
126
|
+
| `git.defaultBranch` | `"main"` | Branch fetched from `git.remote` and used as the worktree base. |
|
|
127
|
+
| `workspace.projectDir` | **required** | Parent dir for cloned repos and sibling ticket worktrees. |
|
|
128
|
+
| `workspace.knownRepositories` | **required** | Repos searched for in ticket descriptions to infer where work belongs. A ticket labeled for groundcrew (`agent-*`) fails fast when no known repo appears; unlabeled tickets are ignored. |
|
|
129
|
+
| `orchestrator.maximumInProgress` | `4` | Cap on in-progress tickets at once for this `crew` instance. |
|
|
130
|
+
| `orchestrator.pollIntervalMilliseconds` | `120_000` | Poll interval in `--watch` mode. |
|
|
131
|
+
| `orchestrator.sessionLimitPercentage` | `85` | Number in `(0, 100]`. A model whose codexbar session window exceeds this percentage is skipped that tick. |
|
|
132
|
+
| `models.default` | `"claude"` | Tiebreak for `agent-any` resolution and fallback for explicit but unknown `agent-*` labels. Also used by `crew run --ticket <TICKET>` for unlabeled tickets. `crew run` without `--ticket` ignores unlabeled tickets and does not apply this default. Must exist in `models.definitions`. |
|
|
133
|
+
| `models.definitions` | `{ claude, codex }` | Agent definitions. Additive merge with shipped defaults. |
|
|
134
|
+
| `models.definitions.<name>.cmd` | — | Shell command launched for the model. Runs in the worktree through the resolved `local.runner`. `{{worktree}}` is replaced before launch; `{{sandbox}}` expands to the sbx sandbox name under the sdx runner and an empty string otherwise. |
|
|
135
|
+
| `models.definitions.<name>.color` | — | Color for the workspace status pill (cmux only; tmux silently drops it). |
|
|
136
|
+
| `models.definitions.<name>.usage` | optional | If set, codexbar usage is fetched for this model and gated by `sessionLimitPercentage`. Falls back to default when unset, with gating enabled for known models. When `usage.codexbar.source` is omitted, groundcrew uses `oauth` for Codex/Claude on macOS, `auto` for other macOS providers, and `cli` elsewhere. Set to `{ disabled: true }` to disable usage gating. |
|
|
137
|
+
| `models.definitions.<name>.sandbox` | optional | Docker Sandboxes binding for the model. Required at launch when `local.runner` resolves to `sdx`. Fields: `agent` (required sbx agent name), `template`, `kits`, `setupCommand` (override for the inside-sandbox setup script). |
|
|
138
|
+
| `models.definitions.<name>.disabled` | optional | When set to exactly `true`, drops the named shipped default (`claude` or `codex`). Doctor skips probing it; `agent-<name>` labels fall back to `models.default` with a warning. |
|
|
139
|
+
| `prompts.initial` | unattended template | First message sent to the agent. Placeholders: `{{ticket}}`, `{{worktree}}`, `{{title}}`, `{{description}}`. Override this from `crew.config.ts` for team-specific statuses, tools, plugins, or review loops. |
|
|
140
|
+
| `workspaceKind` | `"auto"` | Terminal session manager. `"auto"` picks `cmux` when on PATH, else `tmux`. Set to `"cmux"` or `"tmux"` to fail loudly when the chosen backend is missing. |
|
|
141
|
+
| `local.runner` | `"auto"` | Local isolation backend. `"auto"` → `safehouse` on macOS, `sdx` on Linux/WSL. Explicit: `"safehouse"`, `"sdx"`, `"none"`. `"none"` is never picked implicitly. |
|
|
142
|
+
| `logging.file` | XDG state path | Append-mode log file. `log()` / `logEvent()` tee here in addition to stdout. Defaults to `${XDG_STATE_HOME:-$HOME/.local/state}/groundcrew/groundcrew.log`. |
|
|
129
143
|
|
|
130
|
-
|
|
144
|
+
</details>
|
|
131
145
|
|
|
132
146
|
## Runners
|
|
133
147
|
|
|
@@ -139,8 +153,6 @@ Net effect: by the time the agent process exists, the values are gone from the e
|
|
|
139
153
|
| `sdx` | Linux / WSL | [Docker Sandboxes](https://docs.docker.com/sandboxes/) (`sbx`) — required when the agent needs `docker`. |
|
|
140
154
|
| `none` | — | Unsandboxed escape hatch. Never picked implicitly; doctor warns when configured. |
|
|
141
155
|
|
|
142
|
-
For `sdx`: each model that runs under it needs a `sandbox: { agent: "<sbx-agent>" }` block in `crew.config.ts`. Groundcrew names sandboxes `groundcrew-<agent>` (e.g. `groundcrew-claude`) and reuses one sandbox per agent across repos and tickets. First-time agent auth happens inside the sandbox the first time it launches. To bootstrap manually instead, run `sbx create --name groundcrew-<agent> <agent> <projectDir>` once.
|
|
143
|
-
|
|
144
156
|
<details>
|
|
145
157
|
<summary>Safehouse clearance allowlist</summary>
|
|
146
158
|
|
|
@@ -160,24 +172,180 @@ crew run --watch
|
|
|
160
172
|
|
|
161
173
|
Watch `${XDG_CACHE_HOME:-$HOME/.cache}/clearance/clearance.log` for `DENY` lines and add only the domains your agents actually need.
|
|
162
174
|
|
|
175
|
+
`@clipboard-health/clearance` is pulled in transitively when you install groundcrew and provides the `clearance` / `clearance-ensure` bins used by Safehouse runs.
|
|
176
|
+
|
|
163
177
|
</details>
|
|
164
178
|
|
|
165
|
-
|
|
179
|
+
<details>
|
|
180
|
+
<summary>Docker Sandboxes (sdx) setup</summary>
|
|
166
181
|
|
|
167
|
-
|
|
182
|
+
Each model that runs under `sdx` needs a `sandbox: { agent: "<sbx-agent>" }` block in `crew.config.ts`. Groundcrew names sandboxes `groundcrew-<agent>` (e.g. `groundcrew-claude`) and reuses one sandbox per agent across repos and tickets. First-time agent auth happens inside the sandbox the first time it launches. To bootstrap manually instead, run `sbx create --name groundcrew-<agent> <agent> <projectDir>` once.
|
|
168
183
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
184
|
+
Groundcrew auto-creates sandboxes when missing but never deletes them — they persist across tickets and `crew cleanup`. Auth state lives inside the sandbox, so deleting it forces a re-login. Manage with `sbx ls` / `sbx rm`.
|
|
185
|
+
|
|
186
|
+
</details>
|
|
187
|
+
|
|
188
|
+
## Diagnosing tickets
|
|
189
|
+
|
|
190
|
+
`crew doctor --ticket <TICKET>` runs the full per-ticket lifecycle: pre-dispatch eligibility (Todo status, `agent-*` label, model resolution, repo mention, local clone, blockers, session usage, capacity) **and** post-dispatch local recovery (run state, host worktree, workspace pane, branches, PR). Prints a single verdict with a copy-pasteable next step.
|
|
191
|
+
|
|
192
|
+
Verdict precedence: PR outcomes (`pr-open` > `pr-merged`) → recorded failed launches → `interrupted` (concrete recoverable git work first) → `in-flight` → `recoverable` → `unresolvable` > `ineligible` > `would-dispatch` > `lost`. Exits 0 on `would-dispatch`, `pr-open`, or `pr-merged`; any other verdict exits 1. `--watch` and `--ticket` are mutually exclusive. Use `codexbar usage` to inspect session windows directly.
|
|
193
|
+
|
|
194
|
+
Flags:
|
|
195
|
+
|
|
196
|
+
- `--no-linear` — skip the Linear GraphQL call. Resolution and Eligibility sections are skipped; verdicts that need only local state (`in-flight`, `recoverable`, `pr-open`, `pr-merged`, `lost`) still fire.
|
|
197
|
+
- `--no-fetch` — skip the upfront `git fetch origin <branch>` before checking remote presence.
|
|
198
|
+
|
|
199
|
+
| Verdict | What to do |
|
|
200
|
+
| ---------------- | --------------------------------------------------------------------------------------------- |
|
|
201
|
+
| `pr-open` | Nothing — the PR is the source of truth. |
|
|
202
|
+
| `pr-merged` | Done. |
|
|
203
|
+
| `in-flight` | The ticket is still being worked on; the verdict line names the workspace pane to attach to. |
|
|
204
|
+
| `recoverable` | Run the printed `nextStep` exactly. |
|
|
205
|
+
| `interrupted` | Resume the preserved worktree with `crew resume <ticket>` or inspect it by hand. |
|
|
206
|
+
| `failed-launch` | Fix the launch failure, then run `crew resume <ticket>` or `crew cleanup <ticket>`. |
|
|
207
|
+
| `would-dispatch` | Pre-dispatch checks pass; the orchestrator will pick the ticket up on its next tick. |
|
|
208
|
+
| `ineligible` | A resolution or eligibility check failed; the reason after the colon names the failing check. |
|
|
209
|
+
| `unresolvable` | The Linear ticket couldn't be fetched; the reason after the colon names the error. |
|
|
210
|
+
| `lost` | No trace exists. Re-dispatch via `crew run --ticket <ticket>`. |
|
|
211
|
+
|
|
212
|
+
<details>
|
|
213
|
+
<summary>Sample output (post-dispatch)</summary>
|
|
214
|
+
|
|
215
|
+
The Workspace section appends an attach hint to the pane name when the workspace backend exposes one (e.g. `tmux attach -t <session>:<pane>` or `cmux attach <name>`), so the verdict line is immediately actionable.
|
|
173
216
|
|
|
174
|
-
|
|
217
|
+
```text
|
|
218
|
+
groundcrew doctor --ticket HRD-442 (Multi-event extractor: year inference can produce date_start > date_end)
|
|
219
|
+
────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
220
|
+
|
|
221
|
+
Resolution
|
|
222
|
+
[ok] Ticket exists in Linear ("Multi-event extractor: year inference can produce date_start > date_end")
|
|
223
|
+
[ok] Status is Todo
|
|
224
|
+
(skipped — post-dispatch — pre-dispatch checks are irrelevant)
|
|
225
|
+
|
|
226
|
+
Eligibility
|
|
227
|
+
(skipped — post-dispatch — pre-dispatch checks are irrelevant)
|
|
228
|
+
|
|
229
|
+
Run state
|
|
230
|
+
[ok] Local run state (running)
|
|
231
|
+
[ok] Recorded model (claude)
|
|
232
|
+
[ok] Recorded worktree (/Users/paul/dev/groundcrew-workspaces/herds-social/herds-hrd-442)
|
|
233
|
+
[ok] Recorded branch (paul-hrd-442)
|
|
234
|
+
[ok] Resume count (0)
|
|
235
|
+
|
|
236
|
+
Worktree
|
|
237
|
+
[ok] Host worktree exists (/Users/paul/dev/groundcrew-workspaces/herds-social/herds-hrd-442)
|
|
238
|
+
[--] Working tree clean (0 modified, 1 untracked)
|
|
239
|
+
[ok] Branch checked out (paul-hrd-442)
|
|
240
|
+
|
|
241
|
+
Workspace
|
|
242
|
+
[ok] Workspace pane open (hrd-442 — attach: `tmux attach -t groundcrew:hrd-442`)
|
|
243
|
+
|
|
244
|
+
Local branch
|
|
245
|
+
[ok] Local branch exists (paul-hrd-442, 2 ahead / 0 behind origin/main)
|
|
246
|
+
|
|
247
|
+
Remote branch
|
|
248
|
+
[ok] Branch present on origin
|
|
249
|
+
|
|
250
|
+
Pull request
|
|
251
|
+
[ok] Open PR for this branch (#224 https://github.com/herds-social/herds/pull/224)
|
|
252
|
+
|
|
253
|
+
→ pr-open: https://github.com/herds-social/herds/pull/224 (#224)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
</details>
|
|
257
|
+
|
|
258
|
+
### `crew interrupt <TICKET>`
|
|
259
|
+
|
|
260
|
+
Stops a live workspace pane while preserving the ticket worktree and branch. The manual pause button for cases where you need terminal capacity back, want to stop an agent that's going in the wrong direction, or need to inspect the diff before letting another agent continue.
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
crew interrupt HRD-442 --reason "wrong implementation direction"
|
|
264
|
+
crew doctor --ticket HRD-442
|
|
265
|
+
crew resume HRD-442
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
The command closes the cmux/tmux workspace if present, records local run state, and never tears down the worktree. If the workspace was already gone but the worktree is still present, interrupt records that fact so doctor can point at the preserved branch instead of reporting a mystery ticket.
|
|
269
|
+
|
|
270
|
+
### `crew resume <TICKET>`
|
|
271
|
+
|
|
272
|
+
Reopens an existing ticket worktree with a continuation prompt. Resume never creates a new worktree; if none exists it fails and leaves re-dispatch to `crew run --ticket <ticket>`.
|
|
273
|
+
|
|
274
|
+
The resume prompt tells the agent to inspect git status and diff before editing, includes the previous interrupt reason when recorded, and reuses the recorded model, repository, branch, runner, sandbox, and workspace backend. When no run-state file exists but a worktree does, resume falls back to Linear resolution for the model and ticket context.
|
|
275
|
+
|
|
276
|
+
## Secrets
|
|
277
|
+
|
|
278
|
+
Groundcrew forwards a small allowlist of build-time secrets from your shell into the setup phase (so `npm install` can authenticate against private registries) and strips them before the agent runs. The agent process never inherits these values.
|
|
279
|
+
|
|
280
|
+
Recognized names, defined in [`BUILD_SECRET_NAMES`](./src/lib/buildSecrets.ts):
|
|
281
|
+
|
|
282
|
+
- `NPM_TOKEN`
|
|
283
|
+
- `BUF_TOKEN`
|
|
175
284
|
|
|
176
|
-
|
|
285
|
+
Set them in the shell you run `crew` from. Anything not in this list is ignored.
|
|
177
286
|
|
|
178
|
-
|
|
287
|
+
<details>
|
|
288
|
+
<summary>How the secret shuttle works</summary>
|
|
289
|
+
|
|
290
|
+
For each ticket:
|
|
291
|
+
|
|
292
|
+
1. If any recognized var is set and non-empty, groundcrew writes `secrets.env` (mode `0600`) into the ticket's temp prompt dir as `KEY='value'` lines — see `stageBuildSecrets` in [`src/commands/setupWorkspace.ts`](./src/commands/setupWorkspace.ts).
|
|
293
|
+
2. The launch script sources `secrets.env` with `set -a` so the values are exported into the setup phase only (and under `sdx`, forwarded into the sandbox via `-e KEY` flags).
|
|
294
|
+
3. After setup completes, the script `unset`s every name in `BUILD_SECRET_NAMES` and then `rm -rf`s the entire prompt dir (including `secrets.env`) before `exec`'ing the agent. See `sourceSecretsLine` / `unsetSecretsLine` and the `rm -rf` / `exec` lines in [`src/lib/launchCommand.ts`](./src/lib/launchCommand.ts). The rollback path on setup failure ([`src/commands/setupWorkspace.ts`](./src/commands/setupWorkspace.ts)) wipes the prompt dir too.
|
|
295
|
+
|
|
296
|
+
Net effect: by the time the agent process exists, the values are gone from the environment and the file is gone from disk.
|
|
297
|
+
|
|
298
|
+
</details>
|
|
299
|
+
|
|
300
|
+
## Per-repo setup hook
|
|
179
301
|
|
|
180
|
-
|
|
302
|
+
If `.groundcrew/setup.sh` exists in the repo root, groundcrew runs `bash .groundcrew/setup.sh --deps-only` before each agent launch; otherwise nothing runs. Same convention applies inside the sdx sandbox (overridable per-model via `models.definitions.<name>.sandbox.setupCommand`). No implicit `npm install`, `uv sync`, or anything else — groundcrew is language-agnostic, so opt in by adding the script.
|
|
303
|
+
|
|
304
|
+
The `--deps-only` flag tells the script "you're being called by an automated system before an agent launches — skip anything interactive or one-time-only." The same script handles both modes; branch on `$1`:
|
|
305
|
+
|
|
306
|
+
- **With `--deps-only`**: do the cheap recurring work this worktree needs (lockfile install, generate types, etc.). No prompts, no global installs, no `nvm` / `pyenv` bootstrap.
|
|
307
|
+
- **Without the flag**: full interactive bootstrap. Use this when an engineer runs the script by hand for first-time onboarding, or when wiring it into another tool's SessionStart hook.
|
|
308
|
+
|
|
309
|
+
Setup failures are advisory — groundcrew logs the non-zero exit and still launches the agent so a flaky network or stale lockfile doesn't block the session.
|
|
310
|
+
|
|
311
|
+
<details>
|
|
312
|
+
<summary>Examples</summary>
|
|
313
|
+
|
|
314
|
+
**Python (uv):**
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
#!/usr/bin/env bash
|
|
318
|
+
set -euo pipefail
|
|
319
|
+
if [ "${1:-}" = "--deps-only" ]; then
|
|
320
|
+
uv sync --dev
|
|
321
|
+
else
|
|
322
|
+
uv sync --dev
|
|
323
|
+
# ... extra one-time bootstrap (e.g., pre-commit install, db seed) ...
|
|
324
|
+
fi
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Node (npm):**
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
#!/usr/bin/env bash
|
|
331
|
+
set -euo pipefail
|
|
332
|
+
if [ "${1:-}" = "--deps-only" ]; then
|
|
333
|
+
npm clean-install
|
|
334
|
+
else
|
|
335
|
+
npm clean-install
|
|
336
|
+
# ... extra one-time bootstrap (e.g., husky install, codegen, link local packages) ...
|
|
337
|
+
fi
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
**Docs-only or polyglot repo with no install step:** omit the script. With nothing at `.groundcrew/setup.sh`, groundcrew skips the hook silently.
|
|
341
|
+
|
|
342
|
+
For a comprehensive real-world example (nvm bootstrap, hash-based skip-on-no-changes caching, portable SHA-256 detection), see [this repo's own `.groundcrew/setup.sh`](./.groundcrew/setup.sh). It's also symlinked at `.claude/setup.sh` so the same script doubles as a Claude Code SessionStart hook for this repo — that symlink is local convenience, not part of groundcrew's contract.
|
|
343
|
+
|
|
344
|
+
To scaffold `.groundcrew/setup.sh` with a coding agent (Claude Code, Cursor, etc.), see [docs/setup-hook-agent-prompt.md](./docs/setup-hook-agent-prompt.md) — it encodes the contract above as a copy-pasteable prompt.
|
|
345
|
+
|
|
346
|
+
</details>
|
|
347
|
+
|
|
348
|
+
## Pluggable ticket sources
|
|
181
349
|
|
|
182
350
|
`sources` declares extra ticket-system adapters. The current release verifies configured extra sources during `crew run` startup; the dispatch loop still reads Linear directly through the built-in Linear adapter until the canonical consumer refactor lands. This lets you validate shell/Jira/local-plan integrations without changing existing Linear behavior.
|
|
183
351
|
|
|
@@ -224,7 +392,7 @@ export default {
|
|
|
224
392
|
|
|
225
393
|
Allowed `status` values are `todo`, `in-progress`, `in-review`, `done`, and `other`. Use `null` for `repository` or `model` when a ticket should not be groundcrew-eligible. `hasMoreBlockers` is optional and defaults to `false`; `sourceRef` is opaque data that groundcrew passes back to your writeback command.
|
|
226
394
|
|
|
227
|
-
|
|
395
|
+
## Prompt customization
|
|
228
396
|
|
|
229
397
|
Groundcrew ships one model-agnostic unattended prompt by default. It tells the agent to make reasonable assumptions, follow repository instructions, run documented verification, review its diff, open a PR when GitHub/`gh` is available, and include a workspace continuation hint when known.
|
|
230
398
|
|
|
@@ -243,35 +411,7 @@ export default {
|
|
|
243
411
|
|
|
244
412
|
This keeps package defaults portable while letting your private config reference team-specific statuses, tools, plugins, or review loops.
|
|
245
413
|
|
|
246
|
-
|
|
247
|
-
<summary>Full reference table</summary>
|
|
248
|
-
|
|
249
|
-
| Key | Default | What it does |
|
|
250
|
-
| --------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
251
|
-
| `sources` | `[]` | Additional pluggable ticket sources. Extra sources are verified at startup; the built-in Linear adapter remains the dispatch read path until the canonical consumer refactor. Built-in kinds: `shell`, `linear`. |
|
|
252
|
-
| `git.remote` | `"origin"` | Remote used for `fetch` and as the worktree base ref. |
|
|
253
|
-
| `git.defaultBranch` | `"main"` | Branch fetched from `git.remote` and used as the worktree base. |
|
|
254
|
-
| `workspace.projectDir` | **required** | Parent dir for cloned repos and sibling ticket worktrees. |
|
|
255
|
-
| `workspace.knownRepositories` | **required** | Repos searched for in ticket descriptions to infer where work belongs. A ticket labeled for groundcrew (`agent-*`) fails fast when no known repo appears; unlabeled tickets are ignored. |
|
|
256
|
-
| `orchestrator.maximumInProgress` | `4` | Cap on in-progress tickets at once for this `crew` instance. |
|
|
257
|
-
| `orchestrator.pollIntervalMilliseconds` | `120_000` | Poll interval in `--watch` mode. |
|
|
258
|
-
| `orchestrator.sessionLimitPercentage` | `85` | Number in `(0, 100]`. A model whose codexbar session window exceeds this percentage is skipped that tick. |
|
|
259
|
-
| `models.default` | `"claude"` | Tiebreak for `agent-any` resolution and fallback for explicit but unknown `agent-*` labels. Also used by `crew run --ticket <TICKET>` for unlabeled tickets. `crew run` without `--ticket` ignores unlabeled tickets and does not apply this default. Must exist in `models.definitions`. |
|
|
260
|
-
| `models.definitions` | `{ claude, codex }` | Agent definitions. Additive merge with shipped defaults. |
|
|
261
|
-
| `models.definitions.<name>.cmd` | — | Shell command launched for the model. Runs in the worktree through the resolved `local.runner`. `{{worktree}}` is replaced before launch; `{{sandbox}}` expands to the sbx sandbox name under the sdx runner and an empty string otherwise. |
|
|
262
|
-
| `models.definitions.<name>.color` | — | Color for the workspace status pill (cmux only; tmux silently drops it). |
|
|
263
|
-
| `models.definitions.<name>.usage` | optional | If set, codexbar usage is fetched for this model and gated by `sessionLimitPercentage`. Falls back to default when unset, with gating enabled for known models. When `usage.codexbar.source` is omitted, groundcrew uses `oauth` for Codex/Claude on macOS, `auto` for other macOS providers, and `cli` elsewhere. Set to `{ disabled: true }` to disable usage gating. |
|
|
264
|
-
| `models.definitions.<name>.sandbox` | optional | Docker Sandboxes binding for the model. Required at launch when `local.runner` resolves to `sdx`. Fields: `agent` (required sbx agent name), `template`, `kits`, `setupCommand` (override for the inside-sandbox setup script). |
|
|
265
|
-
| `models.definitions.<name>.disabled` | optional | When set to exactly `true`, drops the named shipped default (`claude` or `codex`). Doctor skips probing it; `agent-<name>` labels fall back to `models.default` with a warning. |
|
|
266
|
-
| `prompts.initial` | unattended template | First message sent to the agent. Placeholders: `{{ticket}}`, `{{worktree}}`, `{{title}}`, `{{description}}`. Override this from `crew.config.ts` for team-specific statuses, tools, plugins, or review loops. |
|
|
267
|
-
| `workspaceKind` | `"auto"` | Terminal session manager. `"auto"` picks `cmux` when on PATH, else `tmux`. Set to `"cmux"` or `"tmux"` to fail loudly when the chosen backend is missing. |
|
|
268
|
-
| `local.runner` | `"auto"` | Local isolation backend. `"auto"` → `safehouse` on macOS, `sdx` on Linux/WSL. Explicit: `"safehouse"`, `"sdx"`, `"none"`. `"none"` is never picked implicitly. |
|
|
269
|
-
| `logging.file` | XDG state path | Append-mode log file. `log()` / `logEvent()` tee here in addition to stdout. Defaults to `${XDG_STATE_HOME:-$HOME/.local/state}/groundcrew/groundcrew.log`. |
|
|
270
|
-
|
|
271
|
-
</details>
|
|
272
|
-
|
|
273
|
-
<details>
|
|
274
|
-
<summary>Disabling a shipped default</summary>
|
|
414
|
+
## Disabling a shipped default model
|
|
275
415
|
|
|
276
416
|
Groundcrew ships `claude` and `codex` as default model definitions, additively merged into every resolved config. To stop probing one:
|
|
277
417
|
|
|
@@ -301,172 +441,19 @@ Rules:
|
|
|
301
441
|
- It cannot be combined with `cmd`, `color`, or `usage` in the same entry.
|
|
302
442
|
- `models.default` must point at an enabled model.
|
|
303
443
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
## Per-repo setup hook
|
|
307
|
-
|
|
308
|
-
When groundcrew launches a worktree, if `.groundcrew/setup.sh` exists in the repo root it's invoked as `bash .groundcrew/setup.sh --deps-only` before the agent starts; otherwise nothing runs. The same convention applies inside the sdx sandbox (overridable per-model via `models.definitions.<name>.sandbox.setupCommand`). No implicit `npm install`, `uv sync`, or anything else — groundcrew is language-agnostic, so opt in by adding the script.
|
|
309
|
-
|
|
310
|
-
### The `--deps-only` contract
|
|
444
|
+
## Using 1Password for the API key
|
|
311
445
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
- **With `--deps-only`**: do the cheap recurring work this worktree needs (lockfile install, generate types, etc.). No prompts, no global installs, no `nvm` / `pyenv` bootstrap that the host should already have.
|
|
315
|
-
- **Without the flag**: full interactive bootstrap. Use this path when an engineer runs the script by hand for first-time onboarding, or when wiring it into another tool's SessionStart hook.
|
|
316
|
-
|
|
317
|
-
Setup failures are advisory — groundcrew logs the non-zero exit and still launches the agent so a flaky network or stale lockfile doesn't block the session.
|
|
318
|
-
|
|
319
|
-
### Examples
|
|
320
|
-
|
|
321
|
-
**Python (uv):**
|
|
446
|
+
`crew` reads `GROUNDCREW_LINEAR_API_KEY` first, then falls back to `LINEAR_API_KEY`. To resolve from 1Password:
|
|
322
447
|
|
|
323
448
|
```bash
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if [ "${1:-}" = "--deps-only" ]; then
|
|
327
|
-
uv sync --dev
|
|
328
|
-
else
|
|
329
|
-
uv sync --dev
|
|
330
|
-
# ... extra one-time bootstrap (e.g., pre-commit install, db seed) ...
|
|
331
|
-
fi
|
|
449
|
+
echo "GROUNDCREW_LINEAR_API_KEY='op://<vault>/LINEAR_API_KEY/credential'" > .env.1password
|
|
450
|
+
op run --env-file .env.1password -- crew doctor
|
|
332
451
|
```
|
|
333
452
|
|
|
334
|
-
**Node (npm):**
|
|
335
|
-
|
|
336
|
-
```bash
|
|
337
|
-
#!/usr/bin/env bash
|
|
338
|
-
set -euo pipefail
|
|
339
|
-
if [ "${1:-}" = "--deps-only" ]; then
|
|
340
|
-
npm clean-install
|
|
341
|
-
else
|
|
342
|
-
npm clean-install
|
|
343
|
-
# ... extra one-time bootstrap (e.g., husky install, codegen, link local packages) ...
|
|
344
|
-
fi
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
**Docs-only or polyglot repo with no install step:**
|
|
348
|
-
|
|
349
|
-
Omit the script. With nothing at `.groundcrew/setup.sh`, groundcrew skips the hook silently — fine for documentation repos, polyglot monorepos where setup happens per-package, or anywhere the per-worktree work is genuinely zero.
|
|
350
|
-
|
|
351
|
-
For a more comprehensive real-world example (nvm bootstrap, hash-based skip-on-no-changes caching, portable SHA-256 detection), see [this repo's own `.groundcrew/setup.sh`](./.groundcrew/setup.sh). It's also symlinked at `.claude/setup.sh` so the same script doubles as a Claude Code SessionStart hook for this repo — that symlink is local convenience, not part of groundcrew's contract.
|
|
352
|
-
|
|
353
|
-
### Generating it with an agent
|
|
354
|
-
|
|
355
|
-
To have a coding agent (Claude Code, Cursor, etc.) scaffold `.groundcrew/setup.sh` for a repo you're onboarding, see [docs/setup-hook-agent-prompt.md](./docs/setup-hook-agent-prompt.md) — it encodes the contract above as a copy-pasteable prompt.
|
|
356
|
-
|
|
357
|
-
## Commands
|
|
358
|
-
|
|
359
|
-
```bash
|
|
360
|
-
crew init [--global | --local] [--force] [--dry-run] # create a crew.config.ts
|
|
361
|
-
crew doctor # full setup check
|
|
362
|
-
crew doctor --ticket <TICKET> [--no-linear] [--no-fetch] # full ticket lifecycle (dispatch + recovery)
|
|
363
|
-
crew run # one-shot dispatch
|
|
364
|
-
crew run --watch # poll forever
|
|
365
|
-
crew run --ticket <TICKET> # provision one ticket and exit
|
|
366
|
-
crew setup repos [--dry-run] [<repo>...]
|
|
367
|
-
crew interrupt <TICKET> [--reason <text>] # stop the live workspace, keep the worktree
|
|
368
|
-
crew resume <TICKET> # reopen an existing ticket worktree
|
|
369
|
-
crew cleanup <TICKET> # tear down every worktree carrying this ticket
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
`crew doctor --ticket <TICKET>` covers the full per-ticket lifecycle: pre-dispatch eligibility (Todo status, `agent-*` label, model resolution, repository mention, local clone, blockers, model session usage, in-progress capacity) **and** post-dispatch local-state recovery (recorded run state, host worktree, workspace pane, local branch, remote branch, open PR). Verdict precedence starts with PR outcomes (`pr-open` > `pr-merged`). Recorded failed launches report before ordinary local recovery, interrupted runs report concrete recoverable git work first when it exists and otherwise report `interrupted`, and ordinary post-dispatch cases report `in-flight` before `recoverable`. If none of those apply, doctor falls through to `unresolvable` > `ineligible` > `would-dispatch` > `lost`. Exits 0 on `would-dispatch`, `pr-open`, or `pr-merged`; any other verdict exits 1. `--watch` and `--ticket` are mutually exclusive. To inspect codexbar session windows directly, run `codexbar usage`.
|
|
373
|
-
|
|
374
|
-
### `crew doctor --ticket <ticket>`
|
|
375
|
-
|
|
376
|
-
Diagnose where a ticket is in its lifecycle and what to do next. Runs the same resolution and eligibility chain as the dispatcher, plus probes recorded run state, host worktree, workspace pane, local branch, remote branch, and PR; prints a single verdict with a copy-pasteable recovery step when one applies.
|
|
377
|
-
|
|
378
|
-
Flags:
|
|
379
|
-
|
|
380
|
-
- `--no-linear` — skip the Linear GraphQL call. Resolution and Eligibility sections are skipped; verdicts that need only local state (`in-flight`, `recoverable`, `pr-open`, `pr-merged`, `lost`) still fire.
|
|
381
|
-
- `--no-fetch` — skip the upfront `git fetch origin <branch>` before checking remote presence.
|
|
382
|
-
|
|
383
|
-
The Workspace section appends an attach hint to the pane name when the workspace backend exposes one (e.g. `tmux attach -t <session>:<pane>` or `cmux attach <name>`), so the verdict line is immediately actionable. The hero above shows a passing pre-dispatch run; here's the same command on a ticket that's already past dispatch:
|
|
384
|
-
|
|
385
|
-
```text
|
|
386
|
-
groundcrew doctor --ticket HRD-442 (Multi-event extractor: year inference can produce date_start > date_end)
|
|
387
|
-
────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
388
|
-
|
|
389
|
-
Resolution
|
|
390
|
-
[ok] Ticket exists in Linear ("Multi-event extractor: year inference can produce date_start > date_end")
|
|
391
|
-
[ok] Status is Todo
|
|
392
|
-
(skipped — post-dispatch — pre-dispatch checks are irrelevant)
|
|
393
|
-
|
|
394
|
-
Eligibility
|
|
395
|
-
(skipped — post-dispatch — pre-dispatch checks are irrelevant)
|
|
396
|
-
|
|
397
|
-
Run state
|
|
398
|
-
[ok] Local run state (running)
|
|
399
|
-
[ok] Recorded model (claude)
|
|
400
|
-
[ok] Recorded worktree (/Users/paul/dev/groundcrew-workspaces/herds-social/herds-hrd-442)
|
|
401
|
-
[ok] Recorded branch (paul-hrd-442)
|
|
402
|
-
[ok] Resume count (0)
|
|
403
|
-
|
|
404
|
-
Worktree
|
|
405
|
-
[ok] Host worktree exists (/Users/paul/dev/groundcrew-workspaces/herds-social/herds-hrd-442)
|
|
406
|
-
[--] Working tree clean (0 modified, 1 untracked)
|
|
407
|
-
[ok] Branch checked out (paul-hrd-442)
|
|
408
|
-
|
|
409
|
-
Workspace
|
|
410
|
-
[ok] Workspace pane open (hrd-442 — attach: `tmux attach -t groundcrew:hrd-442`)
|
|
411
|
-
|
|
412
|
-
Local branch
|
|
413
|
-
[ok] Local branch exists (paul-hrd-442, 2 ahead / 0 behind origin/main)
|
|
414
|
-
|
|
415
|
-
Remote branch
|
|
416
|
-
[ok] Branch present on origin
|
|
417
|
-
|
|
418
|
-
Pull request
|
|
419
|
-
[ok] Open PR for this branch (#224 https://github.com/herds-social/herds/pull/224)
|
|
420
|
-
|
|
421
|
-
→ pr-open: https://github.com/herds-social/herds/pull/224 (#224)
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
#### Recovering a stranded ticket
|
|
425
|
-
|
|
426
|
-
The verdict on the last line maps to a recovery action:
|
|
427
|
-
|
|
428
|
-
| Verdict | What to do |
|
|
429
|
-
| ---------------- | --------------------------------------------------------------------------------------------- |
|
|
430
|
-
| `pr-open` | Nothing — the PR is the source of truth. |
|
|
431
|
-
| `pr-merged` | Done. |
|
|
432
|
-
| `in-flight` | The ticket is still being worked on; the verdict line names the workspace pane to attach to. |
|
|
433
|
-
| `recoverable` | Run the printed `nextStep` exactly. |
|
|
434
|
-
| `interrupted` | Resume the preserved worktree with `crew resume <ticket>` or inspect it by hand. |
|
|
435
|
-
| `failed-launch` | Fix the launch failure, then run `crew resume <ticket>` or `crew cleanup <ticket>`. |
|
|
436
|
-
| `would-dispatch` | Pre-dispatch checks pass; the orchestrator will pick the ticket up on its next tick. |
|
|
437
|
-
| `ineligible` | A resolution or eligibility check failed; the reason after the colon names the failing check. |
|
|
438
|
-
| `unresolvable` | The Linear ticket couldn't be fetched; the reason after the colon names the error. |
|
|
439
|
-
| `lost` | No trace exists. Re-dispatch via `crew run --ticket <ticket>`. |
|
|
440
|
-
|
|
441
|
-
### `crew interrupt <ticket>`
|
|
442
|
-
|
|
443
|
-
Stop a live workspace pane while preserving the ticket worktree and branch. This is the manual pause button for cases where you need terminal capacity back, want to stop an agent that is going in the wrong direction, or need to inspect the diff before letting another agent continue.
|
|
444
|
-
|
|
445
|
-
```bash
|
|
446
|
-
crew interrupt HRD-442 --reason "wrong implementation direction"
|
|
447
|
-
crew doctor --ticket HRD-442
|
|
448
|
-
crew resume HRD-442
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
The command closes the cmux/tmux workspace when it exists, records local run state under the groundcrew state directory, and never tears down the worktree. If the workspace was already gone but the worktree is still present, interrupt records that fact so doctor can point at the preserved branch instead of reporting a mystery ticket.
|
|
452
|
-
|
|
453
|
-
### `crew resume <ticket>`
|
|
454
|
-
|
|
455
|
-
Reopen an existing ticket worktree with a continuation prompt. Resume never creates a new worktree; if none exists, it fails and leaves re-dispatch to `crew run --ticket <ticket>`.
|
|
456
|
-
|
|
457
|
-
The resume prompt tells the agent to inspect current git status and diff before editing, includes the previous interrupt reason when recorded, and reuses the recorded model, repository, branch, runner, sandbox, and workspace backend. When no run-state file exists but a worktree does, resume falls back to Linear resolution for the model and ticket context.
|
|
458
|
-
|
|
459
453
|
## Troubleshooting
|
|
460
454
|
|
|
461
455
|
First stop for "labeled but not on the board": `crew doctor --ticket <ticket>` lists every check the dispatcher runs and flags the failing one.
|
|
462
456
|
|
|
463
|
-
<details>
|
|
464
|
-
<summary>Local execution picks one of safehouse / sdx / none</summary>
|
|
465
|
-
|
|
466
|
-
`local.runner: "auto"` resolves to `safehouse` on macOS and `sdx` (Docker Sandboxes) on Linux/WSL. Override with `local.runner: "safehouse" | "sdx" | "none"`. There is no per-model `isolation` knob — the runner is global. `sdx` requires a per-model `sandbox: { agent }` block so groundcrew can map the model to an sbx agent.
|
|
467
|
-
|
|
468
|
-
</details>
|
|
469
|
-
|
|
470
457
|
<details>
|
|
471
458
|
<summary>Safehouse-already-wrapped commands are not re-wrapped</summary>
|
|
472
459
|
|
|
@@ -474,13 +461,6 @@ If a `models.definitions.<name>.cmd` already starts with `safehouse`, groundcrew
|
|
|
474
461
|
|
|
475
462
|
</details>
|
|
476
463
|
|
|
477
|
-
<details>
|
|
478
|
-
<summary>Sandbox lifecycle is create-only</summary>
|
|
479
|
-
|
|
480
|
-
Groundcrew auto-creates the sandbox for an sbx agent (`groundcrew-<agent>`) when missing, but never deletes one — sandboxes persist across tickets and across `crew cleanup`. Auth state lives inside the sandbox, so deleting it forces a re-login. Inspect or remove them manually with `sbx ls` / `sbx rm`.
|
|
481
|
-
|
|
482
|
-
</details>
|
|
483
|
-
|
|
484
464
|
<details>
|
|
485
465
|
<summary>Dead tmux windows vanish by default</summary>
|
|
486
466
|
|
|
@@ -488,20 +468,6 @@ When a wrapped agent command fails (e.g. `safehouse-clearance` not found, `npm i
|
|
|
488
468
|
|
|
489
469
|
</details>
|
|
490
470
|
|
|
491
|
-
<details>
|
|
492
|
-
<summary>Status names don't matter</summary>
|
|
493
|
-
|
|
494
|
-
Groundcrew classifies tickets by Linear's workflow `state.type` (`unstarted`, `started`, `completed`, `canceled`, `duplicate`), not by status name. Teams that rename "Todo" to "To Do" or "Done" to "Shipped" need no configuration — the orchestrator still classifies correctly.
|
|
495
|
-
|
|
496
|
-
</details>
|
|
497
|
-
|
|
498
|
-
<details>
|
|
499
|
-
<summary>Leaf-only</summary>
|
|
500
|
-
|
|
501
|
-
Parent issues with children are ignored — sub-issues are the work items.
|
|
502
|
-
|
|
503
|
-
</details>
|
|
504
|
-
|
|
505
471
|
<details>
|
|
506
472
|
<summary>Tickets stay in-progress until something else moves them</summary>
|
|
507
473
|
|
|
@@ -509,13 +475,6 @@ Groundcrew sets a ticket to `Started` (the first workflow state with `type === "
|
|
|
509
475
|
|
|
510
476
|
</details>
|
|
511
477
|
|
|
512
|
-
<details>
|
|
513
|
-
<summary>Cross-team boards work out of the box</summary>
|
|
514
|
-
|
|
515
|
-
Groundcrew picks up tickets across every team your API key's viewer can see. The "mark in progress" writeback looks up each ticket's own team workflow and uses that team's `started` state, so teams with different state names coexist without any per-team configuration.
|
|
516
|
-
|
|
517
|
-
</details>
|
|
518
|
-
|
|
519
478
|
<details>
|
|
520
479
|
<summary>Claude launches in auto mode by default</summary>
|
|
521
480
|
|
|
@@ -533,7 +492,7 @@ Doctor reports the resolved local runner (safehouse / sdx / none) and whether it
|
|
|
533
492
|
<details>
|
|
534
493
|
<summary>Doctor checks every enabled model</summary>
|
|
535
494
|
|
|
536
|
-
`models.definitions` includes both shipped defaults (`claude`, `codex`) by default via additive merge. If you only intend to label tickets `agent-claude` and don't have `codex` installed, set `models.definitions.codex: { disabled: true }
|
|
495
|
+
`models.definitions` includes both shipped defaults (`claude`, `codex`) by default via additive merge. If you only intend to label tickets `agent-claude` and don't have `codex` installed, set `models.definitions.codex: { disabled: true }`. Without that, doctor exits non-zero on a missing `codex` binary even though `crew run` would never route to it.
|
|
537
496
|
|
|
538
497
|
</details>
|
|
539
498
|
|
|
@@ -572,7 +531,7 @@ node --run crew:op -- run --watch
|
|
|
572
531
|
|
|
573
532
|
Both forms discover config via cosmiconfig — project-walk from cwd for `crew.config.ts` and friends, then `${XDG_CONFIG_HOME:-$HOME/.config}/groundcrew/crew.config.ts` (legacy `config.ts` is still accepted for one release). Set `GROUNDCREW_CONFIG` to point elsewhere. The `crew:op` wrapper additionally reads `${XDG_CONFIG_HOME:-$HOME/.config}/groundcrew/op.env` (1Password env-file with `op://` references resolved at launch).
|
|
574
533
|
|
|
575
|
-
Logs land in `${XDG_STATE_HOME:-$HOME/.local/state}/groundcrew/groundcrew.log` by default (override via `logging.file`).
|
|
534
|
+
Logs land in `${XDG_STATE_HOME:-$HOME/.local/state}/groundcrew/groundcrew.log` by default (override via `logging.file`).
|
|
576
535
|
|
|
577
536
|
Source edits in `src/**` are picked up on the next invocation. Requires Node ≥ 24.3 (native `.ts` type stripping).
|
|
578
537
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/groundcrew",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Linear-driven orchestrator that launches AI coding agents in git worktrees, with workspace lifecycle and usage tracking.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"@clipboard-health/clearance": "1.0.8",
|
|
71
71
|
"@inquirer/checkbox": "5.1.5",
|
|
72
|
-
"@linear/sdk": "
|
|
72
|
+
"@linear/sdk": "86.0.0",
|
|
73
73
|
"cosmiconfig": "9.0.1",
|
|
74
74
|
"tslib": "2.8.1",
|
|
75
75
|
"zod": "4.4.3"
|