@clipboard-health/groundcrew 2.3.6 → 3.0.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/README.md +51 -0
- package/clearance-allow-hosts +1 -0
- package/dist/lib/config.d.ts +2 -14
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +0 -13
- package/dist/lib/launchCommand.d.ts +5 -0
- package/dist/lib/launchCommand.d.ts.map +1 -1
- package/dist/lib/launchCommand.js +8 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -216,6 +216,57 @@ Rules:
|
|
|
216
216
|
|
|
217
217
|
</details>
|
|
218
218
|
|
|
219
|
+
## Per-repo setup hook
|
|
220
|
+
|
|
221
|
+
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.
|
|
222
|
+
|
|
223
|
+
### The `--deps-only` contract
|
|
224
|
+
|
|
225
|
+
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:
|
|
226
|
+
|
|
227
|
+
- **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.
|
|
228
|
+
- **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.
|
|
229
|
+
|
|
230
|
+
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.
|
|
231
|
+
|
|
232
|
+
### Examples
|
|
233
|
+
|
|
234
|
+
**Python (uv):**
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
#!/usr/bin/env bash
|
|
238
|
+
set -euo pipefail
|
|
239
|
+
if [ "${1:-}" = "--deps-only" ]; then
|
|
240
|
+
uv sync --dev
|
|
241
|
+
else
|
|
242
|
+
uv sync --dev
|
|
243
|
+
# ... extra one-time bootstrap (e.g., pre-commit install, db seed) ...
|
|
244
|
+
fi
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Node (npm):**
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
#!/usr/bin/env bash
|
|
251
|
+
set -euo pipefail
|
|
252
|
+
if [ "${1:-}" = "--deps-only" ]; then
|
|
253
|
+
npm clean-install
|
|
254
|
+
else
|
|
255
|
+
npm clean-install
|
|
256
|
+
# ... extra one-time bootstrap (e.g., husky install, codegen, link local packages) ...
|
|
257
|
+
fi
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Docs-only or polyglot repo with no install step:**
|
|
261
|
+
|
|
262
|
+
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.
|
|
263
|
+
|
|
264
|
+
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.
|
|
265
|
+
|
|
266
|
+
### Generating it with an agent
|
|
267
|
+
|
|
268
|
+
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.
|
|
269
|
+
|
|
219
270
|
## Commands
|
|
220
271
|
|
|
221
272
|
```bash
|
package/clearance-allow-hosts
CHANGED
|
@@ -55,6 +55,7 @@ productionresultssa17.blob.core.windows.net
|
|
|
55
55
|
productionresultssa18.blob.core.windows.net
|
|
56
56
|
productionresultssa19.blob.core.windows.net
|
|
57
57
|
raw.githubusercontent.com
|
|
58
|
+
release-assets.githubusercontent.com
|
|
58
59
|
results-receiver.actions.githubusercontent.com
|
|
59
60
|
|
|
60
61
|
# npm registry
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -44,7 +44,8 @@ export interface SandboxDefinition {
|
|
|
44
44
|
kits?: string[];
|
|
45
45
|
/**
|
|
46
46
|
* Setup command run **inside** the sandbox before the agent exec.
|
|
47
|
-
* Defaults to
|
|
47
|
+
* Defaults to the shared `.groundcrew/setup.sh --deps-only` convention
|
|
48
|
+
* (see `launchCommand.ts`) when omitted.
|
|
48
49
|
*/
|
|
49
50
|
setupCommand?: string;
|
|
50
51
|
}
|
|
@@ -85,19 +86,6 @@ interface DisabledUserModelDefinition {
|
|
|
85
86
|
disabled: true;
|
|
86
87
|
}
|
|
87
88
|
type UserModelDefinition = EnabledUserModelDefinition | DisabledUserModelDefinition;
|
|
88
|
-
/**
|
|
89
|
-
* Setup command run inside sibling worktrees on the host. The host is
|
|
90
|
-
* assumed to already have the right Node and npm versions.
|
|
91
|
-
*/
|
|
92
|
-
export declare const DEFAULT_HOST_SETUP_COMMAND = "if [ -x .claude/setup.sh ]; then ./.claude/setup.sh --deps-only; elif [ -f .claude/setup.sh ] && command -v bash >/dev/null 2>&1; then bash .claude/setup.sh --deps-only; else npm clean-install; fi";
|
|
93
|
-
/**
|
|
94
|
-
* Setup command run inside an sdx (Docker Sandboxes) sandbox before the
|
|
95
|
-
* agent process exec. Independent of the host setup — sandboxes typically
|
|
96
|
-
* lack Node tooling on first start, so we keep the recipe scoped to the
|
|
97
|
-
* common case of an npm-managed repo while still letting per-model
|
|
98
|
-
* `sandbox.setupCommand` override it for languages outside that path.
|
|
99
|
-
*/
|
|
100
|
-
export declare const DEFAULT_SANDBOX_SETUP_COMMAND = "if [ -x .claude/setup.sh ]; then ./.claude/setup.sh --deps-only; elif [ -f .claude/setup.sh ] && command -v bash >/dev/null 2>&1; then bash .claude/setup.sh --deps-only; else npm clean-install; fi";
|
|
101
89
|
/**
|
|
102
90
|
* Loose user-facing shape — what a `config.ts` file declares.
|
|
103
91
|
* Fields with defaults are optional; only `linear.projectSlug` and the
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5D,eAAO,MAAM,uBAAuB,EAAE,SAAS,oBAAoB,EAIzD,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC;AAEvD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,MAAM,CAAC;AAEtD,eAAO,MAAM,qBAAqB,EAAE,SAAS,kBAAkB,EAKrD,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/config.js
CHANGED
|
@@ -23,19 +23,6 @@ export const LOCAL_RUNNER_SETTINGS = [
|
|
|
23
23
|
"sdx",
|
|
24
24
|
"none",
|
|
25
25
|
];
|
|
26
|
-
/**
|
|
27
|
-
* Setup command run inside sibling worktrees on the host. The host is
|
|
28
|
-
* assumed to already have the right Node and npm versions.
|
|
29
|
-
*/
|
|
30
|
-
export const DEFAULT_HOST_SETUP_COMMAND = "if [ -x .claude/setup.sh ]; then ./.claude/setup.sh --deps-only; elif [ -f .claude/setup.sh ] && command -v bash >/dev/null 2>&1; then bash .claude/setup.sh --deps-only; else npm clean-install; fi";
|
|
31
|
-
/**
|
|
32
|
-
* Setup command run inside an sdx (Docker Sandboxes) sandbox before the
|
|
33
|
-
* agent process exec. Independent of the host setup — sandboxes typically
|
|
34
|
-
* lack Node tooling on first start, so we keep the recipe scoped to the
|
|
35
|
-
* common case of an npm-managed repo while still letting per-model
|
|
36
|
-
* `sandbox.setupCommand` override it for languages outside that path.
|
|
37
|
-
*/
|
|
38
|
-
export const DEFAULT_SANDBOX_SETUP_COMMAND = "if [ -x .claude/setup.sh ]; then ./.claude/setup.sh --deps-only; elif [ -f .claude/setup.sh ] && command -v bash >/dev/null 2>&1; then bash .claude/setup.sh --deps-only; else npm clean-install; fi";
|
|
39
26
|
const DEFAULT_STATUSES = {
|
|
40
27
|
todo: "Todo",
|
|
41
28
|
inProgress: "In Progress",
|
|
@@ -11,6 +11,11 @@ export { shellSingleQuote } from "./shell.ts";
|
|
|
11
11
|
* exercise the catch branch.
|
|
12
12
|
*/
|
|
13
13
|
export declare function resolveSafehouseClearancePath(baseUrl?: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Per-repo setup hook: if `.groundcrew/setup.sh` exists, run it with
|
|
16
|
+
* `--deps-only`; otherwise no-op.
|
|
17
|
+
*/
|
|
18
|
+
export declare const SETUP_COMMAND = "[ -f .groundcrew/setup.sh ] && bash .groundcrew/setup.sh --deps-only";
|
|
14
19
|
interface LaunchCommandArguments {
|
|
15
20
|
definition: ModelDefinition;
|
|
16
21
|
promptFile: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launchCommand.d.ts","sourceRoot":"","sources":["../../src/lib/launchCommand.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"launchCommand.d.ts","sourceRoot":"","sources":["../../src/lib/launchCommand.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAGzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,GAAE,MAAwB,GAAG,MAAM,CAcvF;AAID;;;GAGG;AACH,eAAO,MAAM,aAAa,yEAAyE,CAAC;AAiCpG,UAAU,sBAAsB;IAC9B,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;;OAIG;IACH,MAAM,EAAE,WAAW,CAAC;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,sBAAsB,GAAG,MAAM,CAK7E"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
|
-
import { BUILD_SECRET_NAMES
|
|
3
|
+
import { BUILD_SECRET_NAMES } from "./config.js";
|
|
4
4
|
import { shellSingleQuote } from "./shell.js";
|
|
5
5
|
export { shellSingleQuote } from "./shell.js";
|
|
6
6
|
/**
|
|
@@ -25,6 +25,11 @@ export function resolveSafehouseClearancePath(baseUrl = import.meta.url) {
|
|
|
25
25
|
return resolve(dirname(clearancePackageJson), "safehouse", "safehouse-clearance");
|
|
26
26
|
}
|
|
27
27
|
const SAFEHOUSE_CLEARANCE_WRAPPER_PATH = resolveSafehouseClearancePath();
|
|
28
|
+
/**
|
|
29
|
+
* Per-repo setup hook: if `.groundcrew/setup.sh` exists, run it with
|
|
30
|
+
* `--deps-only`; otherwise no-op.
|
|
31
|
+
*/
|
|
32
|
+
export const SETUP_COMMAND = "[ -f .groundcrew/setup.sh ] && bash .groundcrew/setup.sh --deps-only";
|
|
28
33
|
function renderAgentCommand(arguments_) {
|
|
29
34
|
return arguments_.agentCmd
|
|
30
35
|
.replaceAll("{{worktree}}", shellSingleQuote(arguments_.worktreeDir))
|
|
@@ -78,7 +83,7 @@ function buildHostLaunchCommand(arguments_) {
|
|
|
78
83
|
if (arguments_.secretsFile !== undefined) {
|
|
79
84
|
lines.push(sourceSecretsLine(arguments_.secretsFile));
|
|
80
85
|
}
|
|
81
|
-
lines.push(setupWithStatusReporting(
|
|
86
|
+
lines.push(setupWithStatusReporting(SETUP_COMMAND));
|
|
82
87
|
if (arguments_.secretsFile !== undefined) {
|
|
83
88
|
lines.push(unsetSecretsLine());
|
|
84
89
|
}
|
|
@@ -116,7 +121,7 @@ function buildSdxLaunchCommand(arguments_) {
|
|
|
116
121
|
worktreeDir: arguments_.worktreeDir,
|
|
117
122
|
sandboxName: arguments_.sandboxName,
|
|
118
123
|
});
|
|
119
|
-
const setupCommand = arguments_.definition.sandbox.setupCommand ??
|
|
124
|
+
const setupCommand = arguments_.definition.sandbox.setupCommand ?? SETUP_COMMAND;
|
|
120
125
|
const innerParts = [setupWithStatusReporting(setupCommand)];
|
|
121
126
|
if (arguments_.secretsFile !== undefined) {
|
|
122
127
|
innerParts.push(unsetSecretsLine());
|
package/package.json
CHANGED