@clipboard-health/groundcrew 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTEXT.md +10 -7
- package/README.md +15 -34
- package/configExample.ts +2 -15
- package/package.json +2 -2
- package/src/cli.js +0 -6
- package/src/cli.js.map +1 -1
- package/src/commands/doctor.js +32 -93
- package/src/commands/doctor.js.map +1 -1
- package/src/commands/setupWorkspace.js +6 -18
- package/src/commands/setupWorkspace.js.map +1 -1
- package/src/commands/spriteSetup.js +2 -2
- package/src/commands/spriteSetup.js.map +1 -1
- package/src/lib/config.d.ts +10 -75
- package/src/lib/config.js +22 -84
- package/src/lib/config.js.map +1 -1
- package/src/lib/host.d.ts +6 -9
- package/src/lib/host.js +4 -6
- package/src/lib/host.js.map +1 -1
- package/src/lib/launchCommand.d.ts +2 -6
- package/src/lib/launchCommand.js +8 -36
- package/src/lib/launchCommand.js.map +1 -1
- package/src/lib/localRunner.d.ts +2 -0
- package/src/lib/localRunner.js +9 -0
- package/src/lib/localRunner.js.map +1 -0
- package/src/lib/worktrees.d.ts +7 -14
- package/src/lib/worktrees.js +15 -111
- package/src/lib/worktrees.js.map +1 -1
- package/src/commands/sandboxAuth.d.ts +0 -8
- package/src/commands/sandboxAuth.js +0 -76
- package/src/commands/sandboxAuth.js.map +0 -1
- package/src/lib/isolation.d.ts +0 -26
- package/src/lib/isolation.js +0 -56
- package/src/lib/isolation.js.map +0 -1
- package/src/lib/sandbox.d.ts +0 -10
- package/src/lib/sandbox.js +0 -25
- package/src/lib/sandbox.js.map +0 -1
package/CONTEXT.md
CHANGED
|
@@ -7,13 +7,13 @@ Six nouns that are collision-prone in this codebase. Use them precisely; don't s
|
|
|
7
7
|
The directory an agent works in for a single ticket. Two kinds, one concept:
|
|
8
8
|
|
|
9
9
|
- **Host worktree** — a `git worktree add`'d sibling at `<projectDir>/<repo>-<TICKET>/`. Visible to the host's `git worktree list --porcelain`.
|
|
10
|
-
- **
|
|
10
|
+
- **Sprite worktree** — a remote git worktree under `remote.sprite.worktreeRoot` on the Sprite runner. Tracked by groundcrew in `sprite-worktrees.json`; not visible to the host's `git worktree list --porcelain`.
|
|
11
11
|
|
|
12
12
|
Lifecycle and lookup live in `src/lib/worktrees.ts`. Callers ask `worktrees.create(spec)` / `worktrees.findByTicket(...)` / `worktrees.remove(entry)` / `worktrees.teardown(entries)` and never branch on the kind themselves — the module dispatches.
|
|
13
13
|
|
|
14
|
-
Branch name is `<os-username>-<ticket-lowercased
|
|
14
|
+
Branch name is `<os-username>-<ticket-lowercased>`. One ticket can have at most one worktree per kind; local host and Sprite remote worktrees can coexist when a ticket moves between runners. `list()` returns host and Sprite worktrees, and intentionally ignores legacy `.sbx` directories.
|
|
15
15
|
|
|
16
|
-
`teardown(entries)` is the destructive lifecycle for a Worktree paired with its Workspace. It closes the live Workspace (deduped per ticket so host
|
|
16
|
+
`teardown(entries)` is the destructive lifecycle for a Worktree paired with its Workspace. It closes the live Workspace (deduped per ticket so host and Sprite entries share one close) before removing each Worktree, and survives per-entry failures, returning a structured result. The order is non-negotiable: the Workspace must close while its underlying directory and branch still exist, or the user is left with a zombie Workspace. Cleaner's per-iteration sweep, the `crew cleanup` CLI, and `setupWorkspace`'s rollback path all route through this one operation.
|
|
17
17
|
|
|
18
18
|
## Workspace
|
|
19
19
|
|
|
@@ -22,17 +22,20 @@ The host-side terminal session that runs an agent for one ticket. Two kinds, one
|
|
|
22
22
|
- **cmux workspace** — a pane/tab in [cmux](https://github.com/clayton-cole/cmux). macOS-only.
|
|
23
23
|
- **tmux workspace** — a window inside a dedicated `groundcrew` tmux session. Linux/macOS.
|
|
24
24
|
|
|
25
|
-
Every provisioned ticket gets one workspace, named with the ticket id (`TEAM-220`). Tracked by ticket, not by worktree kind — there is one workspace per ticket regardless of host vs
|
|
25
|
+
Every provisioned ticket gets one workspace, named with the ticket id (`TEAM-220`). Tracked by ticket, not by worktree kind — there is one workspace per ticket regardless of host vs Sprite runner.
|
|
26
26
|
|
|
27
27
|
Lifecycle and lookup live in `src/lib/workspaces.ts`. Callers ask `workspaces.open(spec)` / `workspaces.probe()` / `workspaces.close(name)` and never branch on the kind themselves — the module dispatches via the resolved adapter (`workspaceKind` config + host capabilities). `probe()` returns a typed `WorkspaceProbe` (`{ kind: "ok"; names }` or `{ kind: "unavailable"; error? }`) so callers don't re-invent a sentinel when the adapter binary is flaky.
|
|
28
28
|
|
|
29
29
|
`groundcrew` opens workspaces in `setupWorkspace`, closes them in `cleaner.runOnce`. Distinct from `worktrees`; do not call a workspace a "worktree."
|
|
30
30
|
|
|
31
|
-
##
|
|
31
|
+
## Runner
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
The environment that executes the agent command for a ticket.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
- **Local runner** — macOS only. Groundcrew requires `safehouse` on `PATH`, starts `clearance`, and launches the model command through `safehouse-clearance` inside the host worktree.
|
|
36
|
+
- **Sprite runner** — remote Linux. Tickets labeled `agent-remote` keep the workspace local but run repository setup and the agent command inside the configured Sprite.
|
|
37
|
+
|
|
38
|
+
There is no `models.isolation` strategy, Docker Sandboxes runner, or direct local runner. Linux/WSL users run tickets through Sprite. Legacy `.sbx` worktrees and persistent Docker Sandboxes state are no longer discovered or cleaned up by groundcrew; users remove old state manually with `sbx` if needed.
|
|
36
39
|
|
|
37
40
|
## Dispatcher
|
|
38
41
|
|
package/README.md
CHANGED
|
@@ -8,11 +8,11 @@ Watch a Linear project and farm out ready tickets to coding-agent CLIs running i
|
|
|
8
8
|
npm install -g @clipboard-health/groundcrew
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
This installs the `crew` binary. `@clipboard-health/clearance` is pulled in transitively and provides the `clearance` / `clearance-ensure` bins used by Safehouse
|
|
11
|
+
This installs the `crew` binary. `@clipboard-health/clearance` is pulled in transitively and provides the `clearance` / `clearance-ensure` bins used by local Safehouse execution.
|
|
12
12
|
|
|
13
13
|
## Quickstart
|
|
14
14
|
|
|
15
|
-
1. **Install prereqs.** Node 24, `git`, `cmux` _or_ `tmux`, and the
|
|
15
|
+
1. **Install prereqs.** Node 24, `git`, `cmux` _or_ `tmux`, and the agent CLIs themselves (`claude`, `codex`, `cursor-agent`, ...). Local runs require macOS with [Safehouse](https://agent-safehouse.dev/) on `PATH`; Linux/WSL hosts must run tickets remotely through Sprite by adding the `agent-remote` label. Optional: `codexbar` for session-usage gating. The `workspaceKind` config key picks the workspace backend (`auto` resolves to cmux when installed, else tmux).
|
|
16
16
|
|
|
17
17
|
2. **Create a Linear project to scope your work.** Any team works — make a project inside it and drop tickets in. The orchestrator polls by project, not by team, so you don't need a dedicated team.
|
|
18
18
|
|
|
@@ -41,28 +41,14 @@ This installs the `crew` binary. `@clipboard-health/clearance` is pulled in tran
|
|
|
41
41
|
op run --env-file .env.1password -- crew doctor
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
5. **Prepare
|
|
44
|
+
5. **Prepare the runner and agent auth.** Groundcrew supports one local runner and one remote runner:
|
|
45
|
+
- macOS local: `cmux` or `tmux` workspace, Safehouse on `PATH`, `clearance`, and locally authenticated agent CLIs.
|
|
46
|
+
- macOS remote: local `cmux` or `tmux` workspace that launches a Sprite session.
|
|
47
|
+
- Linux/WSL remote: `tmux` workspace that launches a Sprite session. Label tickets `agent-remote`; local execution is not supported.
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
Local setup fails before creating a worktree when the host is not macOS or `safehouse` is missing. `models.isolation`, per-model `isolation`, and per-model `sandbox` are legacy keys and now fail config validation.
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
sbx daemon start
|
|
50
|
-
sbx login
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Then prepare each repo/model sandbox once. For Claude, this opens the agent with no ticket prompt so you can complete `/login` without losing task context:
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
crew sandbox auth <repo> --model claude
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
For Codex, groundcrew starts Docker's host-side OpenAI OAuth flow before preparing the sandbox:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
crew sandbox auth <repo> --model codex
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
6. **Set the clearance allowlist (Safehouse only).** When the resolved isolation strategy is Safehouse, groundcrew starts `clearance` from `@clipboard-health/clearance` on `http://127.0.0.1:19999` (skipping the launch if something is already listening) and runs the agent through the bundled `safehouse-clearance` wrapper. Clearance refuses to start without an allowlist — see [its README](../clearance/README.md) for the proxy's env vars, log paths, and DNS rules. The shortest path is to set the env before `crew run`:
|
|
51
|
+
6. **Set the clearance allowlist for local macOS runs.** Groundcrew starts `clearance` from `@clipboard-health/clearance` on `http://127.0.0.1:19999` (skipping the launch if something is already listening) and runs the agent through the bundled `safehouse-clearance` wrapper. Clearance refuses to start without an allowlist — see [its README](../clearance/README.md) for the proxy's env vars, log paths, and DNS rules. The shortest path is to set the env before `crew run`:
|
|
66
52
|
|
|
67
53
|
```bash
|
|
68
54
|
CLEARANCE_ALLOW_HOSTS="api.openai.com,auth.openai.com,api.anthropic.com,mcp.linear.app,api.linear.app" \
|
|
@@ -95,7 +81,7 @@ This installs the `crew` binary. `@clipboard-health/clearance` is pulled in tran
|
|
|
95
81
|
|
|
96
82
|
Known MCP aliases are `linear`, `slack`, and `notion`. For another HTTP MCP server, pass `--mcp name=https://example.com/mcp`. The command creates the Sprite if needed, prepares `~/dev`, configures Git, runs selected auth flows, adds selected MCP servers to Claude Code, and then opens Claude so you can run `/mcp` and authenticate only those selected servers. `--copy-local-codex-auth` copies `${CODEX_HOME:-$HOME/.codex}/auth.json` into `/home/sprite/.codex/auth.json` and then verifies `codex login status`; it never prints the file contents. Use `--skip-mcp-auth` when you only want to add MCP definitions, and run the `/mcp` step later.
|
|
97
83
|
|
|
98
|
-
Repo setup is separate from runner setup and should run after the ticket branch exists, immediately before launching an agent. It clones/fetches the repo in the Sprite, checks out the requested branch (creating it from the base branch when it does not exist on origin), forwards only build-time secrets for the dependency install, removes the temporary secret file, clears those env vars, and then exits. It
|
|
84
|
+
Repo setup is separate from runner setup and should run after the ticket branch exists, immediately before launching an agent. It clones/fetches the repo in the Sprite, checks out the requested branch (creating it from the base branch when it does not exist on origin), forwards only build-time secrets for the dependency install, removes the temporary secret file, clears those env vars, and then exits. It uses groundcrew's remote setup command.
|
|
99
85
|
|
|
100
86
|
```bash
|
|
101
87
|
op run --env-file "${XDG_CONFIG_HOME:-$HOME/.config}/groundcrew/op.env" -- \
|
|
@@ -128,17 +114,15 @@ Required fields are marked **required**; everything else has a default and can b
|
|
|
128
114
|
| `linear.statuses.terminal` | `["Done"]` | Additional status names treated as terminal for cleanup, board remaining counts, and blocker checks. The `done` status is always included. |
|
|
129
115
|
| `git.remote` | `"origin"` | Remote used for `fetch` and as the worktree base ref. |
|
|
130
116
|
| `git.defaultBranch` | `"main"` | Branch fetched from `git.remote` and used as the worktree base. |
|
|
131
|
-
| `workspace.projectDir` | **required** | Parent dir for cloned repos.
|
|
117
|
+
| `workspace.projectDir` | **required** | Parent dir for cloned repos and local sibling ticket worktrees. Sprite ticket worktrees live in `remote.sprite.worktreeRoot` on the remote runner. |
|
|
132
118
|
| `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. |
|
|
133
119
|
| `orchestrator.maximumInProgress` | `4` | Cap on tickets in `linear.statuses.inProgress` at once. |
|
|
134
120
|
| `orchestrator.pollIntervalMilliseconds` | `120_000` | Poll interval in `--watch` mode. |
|
|
135
121
|
| `orchestrator.sessionLimitPercentage` | `85` | Number in `(0, 100]`. A model whose codexbar session window exceeds this percentage is skipped that tick. |
|
|
136
122
|
| `models.default` | `"claude"` | Tiebreak for `agent-any` resolution and fallback for explicit but unknown `agent-*` labels. Also used by `crew setup <TICKET>` for unlabeled tickets. `crew run` ignores unlabeled tickets and does not apply this default. Must exist in `models.definitions`. |
|
|
137
|
-
| `models.isolation` | `"auto"` | Isolation strategy. `"auto"` picks Safehouse on macOS, else Docker Sandboxes when the model has a sandbox config. Safehouse or a model sandbox config is required; if neither is available, setup fails. Set `"none"` explicitly to run directly. |
|
|
138
123
|
| `models.definitions` | `{ claude, codex }` | Agent definitions. Additive merge with shipped defaults. |
|
|
139
|
-
| `models.definitions.<name>.cmd` | — | Shell command launched for the model.
|
|
124
|
+
| `models.definitions.<name>.cmd` | — | Shell command launched for the model. Local macOS runs execute in the worktree through Safehouse/clearance; Sprite runs execute inside the remote worktree. `{{worktree}}` is replaced before launch and legacy `{{sandbox}}` expands to an empty string. |
|
|
140
125
|
| `models.definitions.<name>.color` | — | Color for the workspace status pill (cmux only; tmux silently drops it). |
|
|
141
|
-
| `models.definitions.<name>.sandbox` | `{ agent }` | Optional Docker Sandboxes backing. Defaults set `claude` → `agent: "claude"` and `codex` → `agent: "codex"`. Set `sandbox: false` on an override to run the command outside Docker Sandboxes. |
|
|
142
126
|
| `models.definitions.<name>.usage` | optional | If set, codexbar usage is fetched for this model and gated by `sessionLimitPercentage`. Omit to never gate. When `usage.codexbar.source` is omitted, groundcrew uses `auto` on macOS and `cli` elsewhere. |
|
|
143
127
|
| `prompts.initial` | (template) | First message sent to the agent. Placeholders: `{{ticket}}`, `{{worktree}}`, `{{title}}`, `{{description}}`. |
|
|
144
128
|
| `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. tmux windows live in a dedicated `groundcrew` session. |
|
|
@@ -154,8 +138,6 @@ The branch prefix (`<prefix>-<TICKET>`) is derived from your OS username (`os.us
|
|
|
154
138
|
## Manual commands
|
|
155
139
|
|
|
156
140
|
```bash
|
|
157
|
-
crew sandbox auth <repo> --model claude
|
|
158
|
-
crew sandbox auth <repo> --model codex
|
|
159
141
|
crew sprite setup crew-claude-1 --claude --codex --copy-local-codex-auth --github --mcp linear --checkpoint
|
|
160
142
|
crew sprite bootstrap crew-claude-1 core-utils --branch rocky-team-123
|
|
161
143
|
crew sprite sessions
|
|
@@ -166,14 +148,13 @@ crew run --ticket <TICKET>
|
|
|
166
148
|
crew cleanup <TICKET>
|
|
167
149
|
```
|
|
168
150
|
|
|
169
|
-
`crew run --ticket <TICKET>` provisions a single ticket the same way the orchestrator would: the repo is parsed from the ticket's Linear description, the model comes from the ticket's `agent-*` label, and `agent-remote` is honored. If the description does not mention a repo from `workspace.knownRepositories`, setup fails before provisioning. `--watch` and `--ticket` are mutually exclusive — `--watch` drives the orchestrator loop; `--ticket` provisions one ticket and exits. `crew cleanup <TICKET>` resolves to every worktree carrying that ticket id (host
|
|
151
|
+
`crew run --ticket <TICKET>` provisions a single ticket the same way the orchestrator would: the repo is parsed from the ticket's Linear description, the model comes from the ticket's `agent-*` label, and `agent-remote` is honored. If the description does not mention a repo from `workspace.knownRepositories`, setup fails before provisioning. `--watch` and `--ticket` are mutually exclusive — `--watch` drives the orchestrator loop; `--ticket` provisions one ticket and exits. `crew cleanup <TICKET>` resolves to every tracked worktree carrying that ticket id (host and Sprite kinds, across repos) and tears them all down. To inspect remote sessions, run `crew sprite sessions` or pass an explicit Sprite name. To attach to a listed session id or command selector, run `crew sprite attach <session-id-or-command>`. If an attached agent appears stuck in a long-running shell tool, use `crew sprite ps <sprite>` to find the child process group (`PGID`) under the agent, then use `crew sprite interrupt <PGID> --sprite <sprite>` to send SIGINT to that child command without killing the agent session. If cleanup cannot remove a remote worktree because the agent is still running, stop that session with `sprite sessions kill -s crew-claude-1 <session-id>` and retry cleanup. To inspect codexbar session windows directly, run `codexbar usage`; the orchestrator already gates on this internally via `orchestrator.sessionLimitPercentage`.
|
|
170
152
|
|
|
171
153
|
## Gotchas
|
|
172
154
|
|
|
173
|
-
- **
|
|
155
|
+
- **Local execution is macOS plus Safehouse only.** There is no `models.isolation` strategy and no direct local execution mode. On Linux/WSL, label tickets `agent-remote` and run them through Sprite.
|
|
174
156
|
- **Safehouse-already-wrapped commands are not re-wrapped.** If a `models.definitions.<name>.cmd` already starts with `safehouse`, groundcrew assumes that command owns its Safehouse flags and does not add the `safehouse-clearance` wrapper a second time. Changing the proxy's allowlist after it's running requires killing the PID in `${XDG_CACHE_HOME:-$HOME/.cache}/clearance/clearance.pid` so the next launch picks up the new env.
|
|
175
|
-
- **
|
|
176
|
-
- **Sandbox cleanup is intentionally conservative.** `crew cleanup` removes the per-ticket worktree and branch, but keeps the persistent sandbox so OAuth sessions, installed packages, and agent config survive later tickets. Use `sbx ls` and `sbx rm --force <name>` when you intentionally want to delete that persisted sandbox state.
|
|
157
|
+
- **Legacy Docker Sandboxes state is unmanaged.** Groundcrew no longer discovers or cleans `.sbx` worktrees or persistent Docker Sandboxes containers. If you have old state, inspect and remove it manually with `sbx`.
|
|
177
158
|
- **Sprite cleanup is also conservative.** `crew cleanup` removes tracked remote worktrees and branches, but it does not kill active Sprite sessions. Use `crew sprite sessions [<sprite>]` to inspect sessions and `sprite sessions kill -s <sprite> <session-id>` when Git reports a worktree is busy.
|
|
178
159
|
- **Long-running remote shell tools block agent input.** Claude Code and similar TUI agents cannot accept a new prompt while one of their shell tools is still running. Use `crew sprite ps <sprite>` to inspect the remote process tree; interrupt the tool's child `PGID`, not the agent session `PGID`, with `crew sprite interrupt <PGID> --sprite <sprite>`.
|
|
179
160
|
- **Codex auth in Sprites may need auth-file copy.** If `crew sprite setup <sprite> --codex` finishes interactive login but `codex login status` still fails inside the Sprite, rerun with `--copy-local-codex-auth` after confirming local Codex auth works.
|
|
@@ -183,7 +164,7 @@ crew cleanup <TICKET>
|
|
|
183
164
|
- **Tickets stay in the in-progress status until something else moves them.** Groundcrew sets a ticket to `inProgress` when it provisions a workspace and never advances it. The next transition (typically "in review" when a PR opens) is left to your team's Linear automation rules.
|
|
184
165
|
- **Project must be on a single Linear team in practice.** Cross-team projects work — the orchestrator caches the in-progress state ID per team — but every team in the project must use the same status name for `linear.statuses.inProgress`.
|
|
185
166
|
- **Claude launches in bypass-permissions mode by default.** Groundcrew creates isolated per-ticket worktrees and unattended remote sessions, so the shipped `claude` command is `claude --permission-mode bypassPermissions` to avoid workspace-trust and tool-permission prompts blocking automation. Override `models.definitions.claude.cmd` if you want a stricter mode.
|
|
186
|
-
- **Doctor's command introspection is shallow.**
|
|
167
|
+
- **Doctor's command introspection is shallow.** Doctor reports whether the host can run local tickets with macOS plus Safehouse, then tokenizes model `cmd` and checks the first two non-flag tokens against PATH (so `safehouse claude --foo` checks both `safehouse` and `claude`). Boolean flags without values, env-var assignments (`FOO=1`), shell pipelines, and subshells are not parsed — verify those manually. In particular, `npx -y claude` and `env FOO=1 claude` only check the wrapper, not the wrapped CLI.
|
|
187
168
|
- **Agent CLI must accept a positional prompt.** The handoff is `<your cmd> "<prompt>"`. `claude`, `codex`, and `cursor-agent` all support this.
|
|
188
169
|
|
|
189
170
|
## Hacking on groundcrew
|
package/configExample.ts
CHANGED
|
@@ -35,28 +35,15 @@ export const config: Config = {
|
|
|
35
35
|
//
|
|
36
36
|
// models: {
|
|
37
37
|
// default: "claude",
|
|
38
|
-
// // How model launch commands are wrapped. "auto" picks safehouse on a
|
|
39
|
-
// // supported host (currently macOS) when the binary is installed, then
|
|
40
|
-
// // Docker Sandboxes when configured. If neither isolated runner is
|
|
41
|
-
// // available, setup fails; set "none" explicitly to run directly.
|
|
42
|
-
// // Override to "safehouse", "docker", or "none" to pin a strategy.
|
|
43
|
-
// isolation: "auto",
|
|
44
38
|
// // Additive: defaults for `claude` and `codex` are merged in unless you
|
|
45
39
|
// // re-declare those keys here. Add a third agent (e.g. `cursor`) by
|
|
46
40
|
// // dropping it in this map and tagging tickets with `agent-cursor`.
|
|
41
|
+
// // Local runs on macOS are always wrapped with Safehouse/clearance.
|
|
42
|
+
// // Linux/WSL users should label tickets `agent-remote` to use Sprite.
|
|
47
43
|
// definitions: {
|
|
48
44
|
// cursor: {
|
|
49
45
|
// cmd: "cursor-agent",
|
|
50
46
|
// color: "#929292",
|
|
51
|
-
// // Optional per-model override of `models.isolation`:
|
|
52
|
-
// // isolation: "docker",
|
|
53
|
-
// // Optional for Docker Sandboxes-backed agents:
|
|
54
|
-
// // sandbox: {
|
|
55
|
-
// // agent: "cursor",
|
|
56
|
-
// // template: "groundcrew-node24:latest",
|
|
57
|
-
// // kits: ["./.sbx/kit"],
|
|
58
|
-
// // setupCommand: "npm clean-install",
|
|
59
|
-
// // },
|
|
60
47
|
// },
|
|
61
48
|
// },
|
|
62
49
|
// },
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/groundcrew",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Linear-driven orchestrator that launches AI coding agents in
|
|
3
|
+
"version": "1.6.0",
|
|
4
|
+
"description": "Linear-driven orchestrator that launches AI coding agents in git worktrees, with workspace lifecycle, Sprite remote runners, and usage tracking.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
7
7
|
"ai",
|
package/src/cli.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { cleanupWorkspaceCli } from "./commands/cleanupWorkspace.js";
|
|
2
2
|
import { doctor } from "./commands/doctor.js";
|
|
3
3
|
import { orchestrate } from "./commands/orchestrator.js";
|
|
4
|
-
import { sandboxAuthCli } from "./commands/sandboxAuth.js";
|
|
5
4
|
import { setupWorkspaceCli } from "./commands/setupWorkspace.js";
|
|
6
5
|
import { spriteCli } from "./commands/spriteSetup.js";
|
|
7
6
|
import { errorMessage, writeError, writeOutput } from "./lib/util.js";
|
|
@@ -59,11 +58,6 @@ const SUBCOMMANDS = {
|
|
|
59
58
|
usage: "[--force] <ticket>",
|
|
60
59
|
invoke: cleanupWorkspaceCli,
|
|
61
60
|
},
|
|
62
|
-
sandbox: {
|
|
63
|
-
summary: "Prepare persistent Docker Sandboxes auth",
|
|
64
|
-
usage: "auth <repo> [--model <name>]",
|
|
65
|
-
invoke: sandboxAuthCli,
|
|
66
|
-
},
|
|
67
61
|
sprite: {
|
|
68
62
|
summary: "Create, authenticate, bootstrap, and inspect a remote Sprite runner",
|
|
69
63
|
usage: "setup <sprite-name> [--claude] [--github] [--mcp <alias|name=url>] [--checkpoint]\n" +
|
package/src/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../../packages/groundcrew/src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../../packages/groundcrew/src/cli.ts"],"names":[],"mappings":"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"}
|
package/src/commands/doctor.js
CHANGED
|
@@ -3,16 +3,12 @@
|
|
|
3
3
|
* Returns true if every required check passes; false otherwise.
|
|
4
4
|
*/
|
|
5
5
|
import { existsSync, statSync } from "node:fs";
|
|
6
|
-
import { runCommandAsync } from "../lib/commandRunner.js";
|
|
7
6
|
import { loadConfig } from "../lib/config.js";
|
|
8
7
|
import { detectHostCapabilities, which } from "../lib/host.js";
|
|
9
|
-
import { resolveIsolationStrategy } from "../lib/isolation.js";
|
|
10
8
|
import { errorMessage, readEnvironmentVariable, writeOutput } from "../lib/util.js";
|
|
11
9
|
import { resolveWorkspaceKind } from "../lib/workspaces.js";
|
|
12
10
|
// Tokenization stops after this many non-flag tokens. Two is enough to
|
|
13
11
|
// catch wrapper + wrapped CLI commands like `safehouse claude --foo`.
|
|
14
|
-
// `sbx run` is handled specially because `run` is a subcommand, not a
|
|
15
|
-
// dependency the user installs separately.
|
|
16
12
|
const MAX_TOKENS_PER_CMD = 2;
|
|
17
13
|
async function checkCmd(cmd, required, hint) {
|
|
18
14
|
const path = await which(cmd);
|
|
@@ -27,25 +23,6 @@ async function checkCmd(cmd, required, hint) {
|
|
|
27
23
|
}
|
|
28
24
|
return result;
|
|
29
25
|
}
|
|
30
|
-
async function checkSbxDiagnose() {
|
|
31
|
-
try {
|
|
32
|
-
await runCommandAsync("sbx", ["diagnose"]);
|
|
33
|
-
return {
|
|
34
|
-
name: "sbx diagnose",
|
|
35
|
-
ok: true,
|
|
36
|
-
required: true,
|
|
37
|
-
hint: "Docker Sandboxes ready",
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
return {
|
|
42
|
-
name: "sbx diagnose",
|
|
43
|
-
ok: false,
|
|
44
|
-
required: true,
|
|
45
|
-
hint: "run `sbx daemon start` and `sbx login`, then retry",
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
26
|
function checkEnvironment(name) {
|
|
50
27
|
const value = readEnvironmentVariable(name);
|
|
51
28
|
const set = value !== undefined && value.length > 0;
|
|
@@ -109,22 +86,11 @@ function commandTokensToCheck(cmd) {
|
|
|
109
86
|
}
|
|
110
87
|
return result;
|
|
111
88
|
}
|
|
112
|
-
function gatherToolTokens(config
|
|
89
|
+
function gatherToolTokens(config) {
|
|
113
90
|
const all = new Set();
|
|
114
|
-
for (const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
if (outcome.resolution.resolved === "docker") {
|
|
120
|
-
all.add("sbx");
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (outcome.resolution.resolved === "safehouse") {
|
|
124
|
-
all.add("safehouse");
|
|
125
|
-
}
|
|
126
|
-
// The agent command (claude, codex, …) still has to be on PATH for the
|
|
127
|
-
// host strategies, so tokenize it regardless.
|
|
91
|
+
for (const definition of Object.values(config.models.definitions)) {
|
|
92
|
+
// Local runs execute the agent command on the host; Sprite runs need the
|
|
93
|
+
// same command remotely, but doctor cannot know ticket labels in advance.
|
|
128
94
|
for (const token of commandTokensToCheck(definition.cmd)) {
|
|
129
95
|
all.add(token);
|
|
130
96
|
}
|
|
@@ -169,8 +135,8 @@ export async function doctor() {
|
|
|
169
135
|
writeOutput(`[--] host: ${errorMessage(error)}`);
|
|
170
136
|
return false;
|
|
171
137
|
}
|
|
172
|
-
const
|
|
173
|
-
|
|
138
|
+
const localCapability = localCapabilityCheck(host);
|
|
139
|
+
reportLocalCapability(localCapability);
|
|
174
140
|
const workspaceOutcome = resolveWorkspaceOutcome(config, host);
|
|
175
141
|
reportWorkspaceKind(config, workspaceOutcome);
|
|
176
142
|
const checks = [
|
|
@@ -178,29 +144,22 @@ export async function doctor() {
|
|
|
178
144
|
await checkCmd("git", true, "https://git-scm.com/"),
|
|
179
145
|
...(await workspaceChecks(workspaceOutcome)),
|
|
180
146
|
checkDir(config.workspace.projectDir, "workspace.projectDir"),
|
|
181
|
-
|
|
147
|
+
localCapability,
|
|
182
148
|
];
|
|
183
|
-
const toolTokens = gatherToolTokens(config
|
|
184
|
-
let sbxAvailable = false;
|
|
149
|
+
const toolTokens = gatherToolTokens(config);
|
|
185
150
|
for (const token of toolTokens) {
|
|
186
|
-
|
|
187
|
-
if (token === "safehouse") {
|
|
188
|
-
hint = "macOS-only sandbox; edit config.ts to remove if you're not on macOS";
|
|
189
|
-
}
|
|
151
|
+
const required = localCapability.ok;
|
|
190
152
|
// oxlint-disable-next-line no-await-in-loop -- doctor reports tools in deterministic order
|
|
191
|
-
const check = await checkCmd(token,
|
|
153
|
+
const check = await checkCmd(token, required, required ? undefined : "required for local runs; Sprite runs need this inside the Sprite");
|
|
192
154
|
checks.push(check);
|
|
193
|
-
if (token === "sbx" && check.ok) {
|
|
194
|
-
sbxAvailable = true;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
if (sbxAvailable) {
|
|
198
|
-
checks.push(await checkSbxDiagnose());
|
|
199
155
|
}
|
|
200
156
|
if (anyModelUsesUsage(config)) {
|
|
201
157
|
checks.push(await checkCmd("codexbar", false, "optional — only used for usage gating"));
|
|
202
158
|
}
|
|
203
159
|
for (const check of checks) {
|
|
160
|
+
if (check === localCapability) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
204
163
|
writeOutput(format(check));
|
|
205
164
|
}
|
|
206
165
|
const failed = checks.filter((check) => !check.ok && check.required);
|
|
@@ -212,49 +171,29 @@ export async function doctor() {
|
|
|
212
171
|
writeOutput("All required checks passed.");
|
|
213
172
|
return true;
|
|
214
173
|
}
|
|
215
|
-
function
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const resolution = resolveIsolationStrategy({ config, model: name, host });
|
|
220
|
-
out.set(name, { kind: "ok", resolution });
|
|
221
|
-
}
|
|
222
|
-
catch (error) {
|
|
223
|
-
const requested = definition.isolation ?? config.models.isolation;
|
|
224
|
-
out.set(name, { kind: "error", requested, reason: errorMessage(error) });
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return out;
|
|
228
|
-
}
|
|
229
|
-
function isolationChecks(resolutions) {
|
|
230
|
-
const checks = [];
|
|
231
|
-
for (const [name, outcome] of resolutions) {
|
|
232
|
-
if (outcome.kind === "ok") {
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
checks.push({
|
|
236
|
-
name: `isolation[${name}]`,
|
|
174
|
+
function localCapabilityCheck(host) {
|
|
175
|
+
if (!host.isMacOS) {
|
|
176
|
+
return {
|
|
177
|
+
name: "local runner (macOS + Safehouse)",
|
|
237
178
|
ok: false,
|
|
238
|
-
required:
|
|
239
|
-
hint:
|
|
240
|
-
}
|
|
179
|
+
required: false,
|
|
180
|
+
hint: "required for local runs; on Linux/WSL use agent-remote with Sprite",
|
|
181
|
+
};
|
|
241
182
|
}
|
|
242
|
-
return
|
|
183
|
+
return {
|
|
184
|
+
name: "local runner (macOS + Safehouse)",
|
|
185
|
+
ok: host.hasSafehouse,
|
|
186
|
+
required: false,
|
|
187
|
+
hint: host.hasSafehouse
|
|
188
|
+
? "ready"
|
|
189
|
+
: "required for local runs; install Safehouse from https://agent-safehouse.dev/ and ensure `safehouse` is on PATH",
|
|
190
|
+
};
|
|
243
191
|
}
|
|
244
|
-
function
|
|
192
|
+
function reportLocalCapability(check) {
|
|
245
193
|
writeOutput();
|
|
246
|
-
writeOutput("
|
|
247
|
-
writeOutput("
|
|
248
|
-
writeOutput(
|
|
249
|
-
for (const [name, outcome] of resolutions) {
|
|
250
|
-
if (outcome.kind === "ok") {
|
|
251
|
-
const { requested, resolved, reason } = outcome.resolution;
|
|
252
|
-
writeOutput(`[ok] ${name}: requested=${requested}, resolved=${resolved} (${reason})`);
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
writeOutput(`[--] ${name}: requested=${outcome.requested} — ${outcome.reason}`);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
194
|
+
writeOutput("Local runner");
|
|
195
|
+
writeOutput("------------");
|
|
196
|
+
writeOutput(format(check));
|
|
258
197
|
}
|
|
259
198
|
function resolveWorkspaceOutcome(config, host) {
|
|
260
199
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../../../packages/groundcrew/src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../../../packages/groundcrew/src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,8 @@ import { ensureClearance } from "@clipboard-health/clearance";
|
|
|
5
5
|
import { fetchResolvedIssue } from "../lib/boardSource.js";
|
|
6
6
|
import { BUILD_SECRET_NAMES, loadConfig, } from "../lib/config.js";
|
|
7
7
|
import { detectHostCapabilities } from "../lib/host.js";
|
|
8
|
-
import { resolveIsolationStrategy } from "../lib/isolation.js";
|
|
9
8
|
import { buildLaunchCommand, buildSpriteLaunchCommand, shellSingleQuote, } from "../lib/launchCommand.js";
|
|
9
|
+
import { assertLocalRunnerRequirements } from "../lib/localRunner.js";
|
|
10
10
|
import { errorMessage, getLinearClient, log, readEnvironmentVariable } from "../lib/util.js";
|
|
11
11
|
import { workspaces } from "../lib/workspaces.js";
|
|
12
12
|
import { repoDirFor, worktrees } from "../lib/worktrees.js";
|
|
@@ -69,20 +69,13 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
69
69
|
});
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
host: await detectHostCapabilities(signal),
|
|
76
|
-
});
|
|
77
|
-
log(`Isolation strategy: ${strategy} (${reason})`);
|
|
78
|
-
if (strategy === "safehouse") {
|
|
79
|
-
await ensureClearance({ logger: log });
|
|
80
|
-
}
|
|
81
|
-
const spec = { repository, ticket, model, strategy, runner };
|
|
72
|
+
assertLocalRunnerRequirements(await detectHostCapabilities(signal));
|
|
73
|
+
await ensureClearance({ logger: log });
|
|
74
|
+
const spec = { repository, ticket, model, runner };
|
|
82
75
|
const created = signal === undefined
|
|
83
76
|
? await worktrees.create(config, spec)
|
|
84
77
|
: await worktrees.create(config, spec, signal);
|
|
85
|
-
const { branchName, dir: launchDir
|
|
78
|
+
const { branchName, dir: launchDir } = created;
|
|
86
79
|
const worktreeName = `${repository}-${ticket}`;
|
|
87
80
|
// Anything that fails after the worktree is on disk must roll it back
|
|
88
81
|
// (the worktree and the just-created branch). `workspaces.open` cleans
|
|
@@ -114,8 +107,6 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
114
107
|
definition,
|
|
115
108
|
promptFile,
|
|
116
109
|
worktreeDir: launchDir,
|
|
117
|
-
sandboxName,
|
|
118
|
-
strategy,
|
|
119
110
|
secretsFile,
|
|
120
111
|
});
|
|
121
112
|
log("Opening workspace...");
|
|
@@ -128,9 +119,6 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
128
119
|
log(`Workspace "${ticket}" launched (${model})`);
|
|
129
120
|
log(` Worktree: ${launchDir}`);
|
|
130
121
|
log(` Branch: ${branchName}`);
|
|
131
|
-
if (sandboxName !== undefined) {
|
|
132
|
-
log(` sbx: ${sandboxName}`);
|
|
133
|
-
}
|
|
134
122
|
}
|
|
135
123
|
catch (error) {
|
|
136
124
|
await rollbackWorktree({ config, entry: created, promptDir });
|
|
@@ -153,7 +141,7 @@ async function setupSpriteWorkspace(arguments_) {
|
|
|
153
141
|
throw new Error(`Unknown model: ${model}`);
|
|
154
142
|
}
|
|
155
143
|
log(`Workspace runner: sprite (${config.remote.sprite.spriteName})`);
|
|
156
|
-
const spec = { repository, ticket, model,
|
|
144
|
+
const spec = { repository, ticket, model, runner: "sprite" };
|
|
157
145
|
const created = signal === undefined
|
|
158
146
|
? await worktrees.create(config, spec)
|
|
159
147
|
: await worktrees.create(config, spec, signal);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupWorkspace.js","sourceRoot":"","sources":["../../../../../packages/groundcrew/src/commands/setupWorkspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,UAAU,GAGX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,
|
|
1
|
+
{"version":3,"file":"setupWorkspace.js","sourceRoot":"","sources":["../../../../../packages/groundcrew/src/commands/setupWorkspace.ts"],"names":[],"mappings":"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"}
|