@clipboard-health/groundcrew 4.0.0 → 4.0.2
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 +246 -308
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -25
- package/dist/commands/doctor.d.ts +1 -6
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +24 -37
- package/dist/commands/interruptWorkspace.js +1 -1
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +178 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/lib/util.d.ts +3 -2
- package/dist/lib/util.d.ts.map +1 -1
- package/dist/lib/util.js +18 -2
- package/package.json +2 -2
- package/dist/commands/ticketCheck.d.ts +0 -22
- package/dist/commands/ticketCheck.d.ts.map +0 -1
- package/dist/commands/ticketCheck.js +0 -23
- package/dist/commands/ticketDoctor.d.ts +0 -223
- package/dist/commands/ticketDoctor.d.ts.map +0 -1
- package/dist/commands/ticketDoctor.js +0 -1134
package/README.md
CHANGED
|
@@ -17,24 +17,31 @@
|
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
19
|
```text
|
|
20
|
-
$ crew
|
|
21
|
-
groundcrew
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
20
|
+
$ crew status HRD-446
|
|
21
|
+
groundcrew status HRD-446
|
|
22
|
+
========================
|
|
23
|
+
ticket: hrd-446
|
|
24
|
+
|
|
25
|
+
Config snapshot
|
|
26
|
+
---------------
|
|
27
|
+
projectDir: /dev/workspaces
|
|
28
|
+
repositories: owner/repo
|
|
29
|
+
git: remote=origin; defaultBranch=main
|
|
30
|
+
workspaceKind: auto
|
|
31
|
+
|
|
32
|
+
Worktree state
|
|
33
|
+
--------------
|
|
34
|
+
- owner/repo host
|
|
35
|
+
branch: rocky-hrd-446
|
|
36
|
+
git: dirty (2 modified, 1 untracked)
|
|
37
|
+
|
|
38
|
+
Workspace probe
|
|
39
|
+
---------------
|
|
40
|
+
live: yes
|
|
41
|
+
|
|
42
|
+
Last Linear status
|
|
43
|
+
------------------
|
|
44
|
+
In Progress (state.type=started) — Add retry logic to the sync job
|
|
38
45
|
```
|
|
39
46
|
|
|
40
47
|
## Why
|
|
@@ -42,92 +49,106 @@ Eligibility
|
|
|
42
49
|
- **Linear-native.** Polls issues assigned to the API key's viewer with `agent-*` labels, honors blockers.
|
|
43
50
|
- **One worktree per ticket.** Agents work in parallel without stepping on each other.
|
|
44
51
|
- **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.
|
|
52
|
+
- **Multi-agent.** Ships with `claude` and `codex`; bring your own CLI via `crew.config.ts`.
|
|
54
53
|
|
|
55
54
|
## Quickstart
|
|
56
55
|
|
|
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:
|
|
56
|
+
```bash
|
|
57
|
+
# 1. Install Node ≥ 24, git, cmux or tmux, and the agent CLIs you'll use (claude, codex, ...).
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
crew init && $EDITOR crew.config.ts
|
|
59
|
+
# 2. Install groundcrew
|
|
60
|
+
npm install -g @clipboard-health/groundcrew
|
|
68
61
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
```
|
|
62
|
+
# 3. Scaffold a config and edit workspace.projectDir + workspace.knownRepositories
|
|
63
|
+
crew init && $EDITOR crew.config.ts
|
|
72
64
|
|
|
73
|
-
|
|
65
|
+
# 4. Clone the repos referenced in your config
|
|
66
|
+
crew setup repos
|
|
74
67
|
|
|
75
|
-
|
|
68
|
+
# 5. Export your Linear API key
|
|
69
|
+
export GROUNDCREW_LINEAR_API_KEY="lin_api_..."
|
|
76
70
|
|
|
77
|
-
|
|
71
|
+
# 6. Verify setup, then dispatch
|
|
72
|
+
crew doctor
|
|
73
|
+
crew run --watch
|
|
74
|
+
```
|
|
78
75
|
|
|
79
|
-
|
|
76
|
+
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
77
|
|
|
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
|
-
```
|
|
78
|
+
`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
79
|
|
|
87
|
-
|
|
80
|
+
## Commands
|
|
88
81
|
|
|
89
|
-
|
|
82
|
+
```bash
|
|
83
|
+
crew init [--global | --local] [--force] [--dry-run] # create a crew.config.ts
|
|
84
|
+
crew doctor # check setup
|
|
85
|
+
crew status [<TICKET>] # inspect current state or one ticket
|
|
86
|
+
crew run # one-shot dispatch
|
|
87
|
+
crew run --watch # poll forever
|
|
88
|
+
crew run --ticket <TICKET> # dispatch one ticket
|
|
89
|
+
crew setup repos [<repo>...] [--dry-run] # clone known repos via gh
|
|
90
|
+
crew interrupt <TICKET> [--reason <text>] # stop workspace, keep worktree
|
|
91
|
+
crew resume <TICKET> # reopen a paused ticket
|
|
92
|
+
crew cleanup <TICKET> # tear down every worktree for a ticket
|
|
93
|
+
```
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
export GROUNDCREW_LINEAR_API_KEY="lin_api_..."
|
|
93
|
-
```
|
|
95
|
+
## Configuration
|
|
94
96
|
|
|
95
|
-
|
|
96
|
-
<summary>Using 1Password (<code>op</code>) for the key</summary>
|
|
97
|
+
Two keys are required; everything else has a default.
|
|
97
98
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
| Key | What |
|
|
100
|
+
| ----------------------------- | ---------------------------------------------------------------------- |
|
|
101
|
+
| `workspace.projectDir` | Parent dir for cloned repos and sibling ticket worktrees. |
|
|
102
|
+
| `workspace.knownRepositories` | Repos searched for in ticket descriptions to infer where work belongs. |
|
|
102
103
|
|
|
103
|
-
|
|
104
|
+
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
105
|
|
|
105
|
-
|
|
106
|
+
<details>
|
|
107
|
+
<summary>Agent label routing</summary>
|
|
106
108
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
- `agent-claude`, `agent-codex`, `agent-<name>` → that model.
|
|
110
|
+
- `agent-any` → the model with the most available session capacity.
|
|
111
|
+
- Unknown `agent-<name>` → falls back to `models.default` with a warning.
|
|
112
|
+
- No `agent-*` label → ignored by `crew run`. Dispatch on demand with `crew run --ticket <TICKET>` (also falls back to `models.default`).
|
|
113
|
+
- Todo tickets blocked by non-terminal blockers are skipped until their blockers reach a terminal status.
|
|
112
114
|
|
|
113
|
-
|
|
115
|
+
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
116
|
|
|
115
|
-
|
|
117
|
+
</details>
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
<details>
|
|
120
|
+
<summary>Config discovery</summary>
|
|
118
121
|
|
|
119
|
-
- `
|
|
120
|
-
- `BUF_TOKEN`
|
|
122
|
+
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
123
|
|
|
122
|
-
|
|
124
|
+
</details>
|
|
123
125
|
|
|
124
|
-
|
|
126
|
+
<details>
|
|
127
|
+
<summary>Full configuration reference</summary>
|
|
125
128
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
| Key | Default | What it does |
|
|
130
|
+
| --------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
131
|
+
| `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`. |
|
|
132
|
+
| `git.remote` | `"origin"` | Remote used for `fetch` and as the worktree base ref. |
|
|
133
|
+
| `git.defaultBranch` | `"main"` | Branch fetched from `git.remote` and used as the worktree base. |
|
|
134
|
+
| `workspace.projectDir` | **required** | Parent dir for cloned repos and sibling ticket worktrees. |
|
|
135
|
+
| `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. |
|
|
136
|
+
| `orchestrator.maximumInProgress` | `4` | Cap on in-progress tickets at once for this `crew` instance. |
|
|
137
|
+
| `orchestrator.pollIntervalMilliseconds` | `120_000` | Poll interval in `--watch` mode. |
|
|
138
|
+
| `orchestrator.sessionLimitPercentage` | `85` | Number in `(0, 100]`. A model whose codexbar session window exceeds this percentage is skipped that tick. |
|
|
139
|
+
| `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`. |
|
|
140
|
+
| `models.definitions` | `{ claude, codex }` | Agent definitions. Additive merge with shipped defaults. |
|
|
141
|
+
| `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. |
|
|
142
|
+
| `models.definitions.<name>.color` | — | Color for the workspace status pill (cmux only; tmux silently drops it). |
|
|
143
|
+
| `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. |
|
|
144
|
+
| `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). |
|
|
145
|
+
| `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. |
|
|
146
|
+
| `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. |
|
|
147
|
+
| `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. |
|
|
148
|
+
| `local.runner` | `"auto"` | Local isolation backend. `"auto"` → `safehouse` on macOS, `sdx` on Linux/WSL. Explicit: `"safehouse"`, `"sdx"`, `"none"`. `"none"` is never picked implicitly. |
|
|
149
|
+
| `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
150
|
|
|
130
|
-
|
|
151
|
+
</details>
|
|
131
152
|
|
|
132
153
|
## Runners
|
|
133
154
|
|
|
@@ -139,8 +160,6 @@ Net effect: by the time the agent process exists, the values are gone from the e
|
|
|
139
160
|
| `sdx` | Linux / WSL | [Docker Sandboxes](https://docs.docker.com/sandboxes/) (`sbx`) — required when the agent needs `docker`. |
|
|
140
161
|
| `none` | — | Unsandboxed escape hatch. Never picked implicitly; doctor warns when configured. |
|
|
141
162
|
|
|
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
163
|
<details>
|
|
145
164
|
<summary>Safehouse clearance allowlist</summary>
|
|
146
165
|
|
|
@@ -160,24 +179,152 @@ crew run --watch
|
|
|
160
179
|
|
|
161
180
|
Watch `${XDG_CACHE_HOME:-$HOME/.cache}/clearance/clearance.log` for `DENY` lines and add only the domains your agents actually need.
|
|
162
181
|
|
|
182
|
+
`@clipboard-health/clearance` is pulled in transitively when you install groundcrew and provides the `clearance` / `clearance-ensure` bins used by Safehouse runs.
|
|
183
|
+
|
|
163
184
|
</details>
|
|
164
185
|
|
|
165
|
-
|
|
186
|
+
<details>
|
|
187
|
+
<summary>Docker Sandboxes (sdx) setup</summary>
|
|
166
188
|
|
|
167
|
-
|
|
189
|
+
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
190
|
|
|
169
|
-
|
|
170
|
-
| ----------------------------- | ---------------------------------------------------------------------- |
|
|
171
|
-
| `workspace.projectDir` | Parent dir for cloned repos and sibling ticket worktrees. |
|
|
172
|
-
| `workspace.knownRepositories` | Repos searched for in ticket descriptions to infer where work belongs. |
|
|
191
|
+
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`.
|
|
173
192
|
|
|
174
|
-
|
|
193
|
+
</details>
|
|
175
194
|
|
|
176
|
-
|
|
195
|
+
## Inspecting status
|
|
177
196
|
|
|
178
|
-
|
|
197
|
+
`crew status <TICKET>` prints a read-only snapshot for one ticket: resolved config, matching worktrees, workspace probe result, recorded run state, recent log lines for that ticket, and the latest Linear status. It does not fetch, recover, tear down, resume, or mutate any local/remote state.
|
|
179
198
|
|
|
180
|
-
|
|
199
|
+
`crew status` with no ticket prints the current inventory: known worktrees with workspace/run-state presence plus live workspaces reported by the configured backend.
|
|
200
|
+
|
|
201
|
+
Use `crew cleanup <TICKET>` to tear down stale worktrees and `crew resume <TICKET>` to reopen preserved work. Status is intentionally informational only.
|
|
202
|
+
|
|
203
|
+
## Doctor
|
|
204
|
+
|
|
205
|
+
`crew doctor` checks host prerequisites only: config validity, Linear reachability, required binaries on PATH, workspace backend availability, workspace.projectDir, local runner capability, and enabled model commands.
|
|
206
|
+
|
|
207
|
+
<details>
|
|
208
|
+
<summary>Sample ticket status output</summary>
|
|
209
|
+
|
|
210
|
+
```text
|
|
211
|
+
groundcrew status HRD-442
|
|
212
|
+
=========================
|
|
213
|
+
ticket: hrd-442
|
|
214
|
+
|
|
215
|
+
Run state
|
|
216
|
+
---------
|
|
217
|
+
running; model=claude; updated=2026-05-26T00:01:00.000Z; resumes=0
|
|
218
|
+
|
|
219
|
+
Worktree
|
|
220
|
+
--------
|
|
221
|
+
- herds-social host
|
|
222
|
+
branch: paul-hrd-442
|
|
223
|
+
dir: /Users/paul/dev/groundcrew-workspaces/herds-social/herds-hrd-442
|
|
224
|
+
git: dirty (0 modified, 1 untracked)
|
|
225
|
+
|
|
226
|
+
Workspace
|
|
227
|
+
---------
|
|
228
|
+
live: yes
|
|
229
|
+
|
|
230
|
+
Last Linear status
|
|
231
|
+
------------------
|
|
232
|
+
In Progress (state.type=started) — Multi-event extractor: year inference can produce date_start > date_end
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
</details>
|
|
236
|
+
|
|
237
|
+
### `crew interrupt <TICKET>`
|
|
238
|
+
|
|
239
|
+
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.
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
crew interrupt HRD-442 --reason "wrong implementation direction"
|
|
243
|
+
crew status HRD-442
|
|
244
|
+
crew resume HRD-442
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
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 status can show the preserved branch.
|
|
248
|
+
|
|
249
|
+
### `crew resume <TICKET>`
|
|
250
|
+
|
|
251
|
+
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>`.
|
|
252
|
+
|
|
253
|
+
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.
|
|
254
|
+
|
|
255
|
+
## Secrets
|
|
256
|
+
|
|
257
|
+
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.
|
|
258
|
+
|
|
259
|
+
Recognized names, defined in [`BUILD_SECRET_NAMES`](./src/lib/buildSecrets.ts):
|
|
260
|
+
|
|
261
|
+
- `NPM_TOKEN`
|
|
262
|
+
- `BUF_TOKEN`
|
|
263
|
+
|
|
264
|
+
Set them in the shell you run `crew` from. Anything not in this list is ignored.
|
|
265
|
+
|
|
266
|
+
<details>
|
|
267
|
+
<summary>How the secret shuttle works</summary>
|
|
268
|
+
|
|
269
|
+
For each ticket:
|
|
270
|
+
|
|
271
|
+
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).
|
|
272
|
+
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).
|
|
273
|
+
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.
|
|
274
|
+
|
|
275
|
+
Net effect: by the time the agent process exists, the values are gone from the environment and the file is gone from disk.
|
|
276
|
+
|
|
277
|
+
</details>
|
|
278
|
+
|
|
279
|
+
## Per-repo setup hook
|
|
280
|
+
|
|
281
|
+
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.
|
|
282
|
+
|
|
283
|
+
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`:
|
|
284
|
+
|
|
285
|
+
- **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.
|
|
286
|
+
- **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.
|
|
287
|
+
|
|
288
|
+
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.
|
|
289
|
+
|
|
290
|
+
<details>
|
|
291
|
+
<summary>Examples</summary>
|
|
292
|
+
|
|
293
|
+
**Python (uv):**
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
#!/usr/bin/env bash
|
|
297
|
+
set -euo pipefail
|
|
298
|
+
if [ "${1:-}" = "--deps-only" ]; then
|
|
299
|
+
uv sync --dev
|
|
300
|
+
else
|
|
301
|
+
uv sync --dev
|
|
302
|
+
# ... extra one-time bootstrap (e.g., pre-commit install, db seed) ...
|
|
303
|
+
fi
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Node (npm):**
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
#!/usr/bin/env bash
|
|
310
|
+
set -euo pipefail
|
|
311
|
+
if [ "${1:-}" = "--deps-only" ]; then
|
|
312
|
+
npm clean-install
|
|
313
|
+
else
|
|
314
|
+
npm clean-install
|
|
315
|
+
# ... extra one-time bootstrap (e.g., husky install, codegen, link local packages) ...
|
|
316
|
+
fi
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**Docs-only or polyglot repo with no install step:** omit the script. With nothing at `.groundcrew/setup.sh`, groundcrew skips the hook silently.
|
|
320
|
+
|
|
321
|
+
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.
|
|
322
|
+
|
|
323
|
+
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.
|
|
324
|
+
|
|
325
|
+
</details>
|
|
326
|
+
|
|
327
|
+
## Pluggable ticket sources
|
|
181
328
|
|
|
182
329
|
`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
330
|
|
|
@@ -224,7 +371,7 @@ export default {
|
|
|
224
371
|
|
|
225
372
|
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
373
|
|
|
227
|
-
|
|
374
|
+
## Prompt customization
|
|
228
375
|
|
|
229
376
|
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
377
|
|
|
@@ -243,35 +390,7 @@ export default {
|
|
|
243
390
|
|
|
244
391
|
This keeps package defaults portable while letting your private config reference team-specific statuses, tools, plugins, or review loops.
|
|
245
392
|
|
|
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>
|
|
393
|
+
## Disabling a shipped default model
|
|
275
394
|
|
|
276
395
|
Groundcrew ships `claude` and `codex` as default model definitions, additively merged into every resolved config. To stop probing one:
|
|
277
396
|
|
|
@@ -301,171 +420,18 @@ Rules:
|
|
|
301
420
|
- It cannot be combined with `cmd`, `color`, or `usage` in the same entry.
|
|
302
421
|
- `models.default` must point at an enabled model.
|
|
303
422
|
|
|
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
|
|
311
|
-
|
|
312
|
-
The 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`. The name is historical and Node-flavored, but the semantic is language-neutral:
|
|
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):**
|
|
322
|
-
|
|
323
|
-
```bash
|
|
324
|
-
#!/usr/bin/env bash
|
|
325
|
-
set -euo pipefail
|
|
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
|
|
332
|
-
```
|
|
333
|
-
|
|
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>`
|
|
423
|
+
## Using 1Password for the API key
|
|
442
424
|
|
|
443
|
-
|
|
425
|
+
`crew` reads `GROUNDCREW_LINEAR_API_KEY` first, then falls back to `LINEAR_API_KEY`. To resolve from 1Password:
|
|
444
426
|
|
|
445
427
|
```bash
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
crew resume HRD-442
|
|
428
|
+
echo "GROUNDCREW_LINEAR_API_KEY='op://<vault>/LINEAR_API_KEY/credential'" > .env.1password
|
|
429
|
+
op run --env-file .env.1password -- crew doctor
|
|
449
430
|
```
|
|
450
431
|
|
|
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
432
|
## Troubleshooting
|
|
460
433
|
|
|
461
|
-
First stop for "
|
|
462
|
-
|
|
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>
|
|
434
|
+
First stop for "what exists locally right now": `crew status <ticket>` shows the ticket's worktrees, workspace presence, run state, logs, and latest Linear status. Use `crew doctor` when you need to verify host setup.
|
|
469
435
|
|
|
470
436
|
<details>
|
|
471
437
|
<summary>Safehouse-already-wrapped commands are not re-wrapped</summary>
|
|
@@ -474,13 +440,6 @@ If a `models.definitions.<name>.cmd` already starts with `safehouse`, groundcrew
|
|
|
474
440
|
|
|
475
441
|
</details>
|
|
476
442
|
|
|
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
443
|
<details>
|
|
485
444
|
<summary>Dead tmux windows vanish by default</summary>
|
|
486
445
|
|
|
@@ -488,20 +447,6 @@ When a wrapped agent command fails (e.g. `safehouse-clearance` not found, `npm i
|
|
|
488
447
|
|
|
489
448
|
</details>
|
|
490
449
|
|
|
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
450
|
<details>
|
|
506
451
|
<summary>Tickets stay in-progress until something else moves them</summary>
|
|
507
452
|
|
|
@@ -509,13 +454,6 @@ Groundcrew sets a ticket to `Started` (the first workflow state with `type === "
|
|
|
509
454
|
|
|
510
455
|
</details>
|
|
511
456
|
|
|
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
457
|
<details>
|
|
520
458
|
<summary>Claude launches in auto mode by default</summary>
|
|
521
459
|
|
|
@@ -533,7 +471,7 @@ Doctor reports the resolved local runner (safehouse / sdx / none) and whether it
|
|
|
533
471
|
<details>
|
|
534
472
|
<summary>Doctor checks every enabled model</summary>
|
|
535
473
|
|
|
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 }
|
|
474
|
+
`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
475
|
|
|
538
476
|
</details>
|
|
539
477
|
|
|
@@ -572,7 +510,7 @@ node --run crew:op -- run --watch
|
|
|
572
510
|
|
|
573
511
|
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
512
|
|
|
575
|
-
Logs land in `${XDG_STATE_HOME:-$HOME/.local/state}/groundcrew/groundcrew.log` by default (override via `logging.file`).
|
|
513
|
+
Logs land in `${XDG_STATE_HOME:-$HOME/.local/state}/groundcrew/groundcrew.log` by default (override via `logging.file`).
|
|
576
514
|
|
|
577
515
|
Source edits in `src/**` are picked up on the next invocation. Requires Node ≥ 24.3 (native `.ts` type stripping).
|
|
578
516
|
|