@clipboard-health/groundcrew 4.31.0 → 4.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/lib/agentLaunch.d.ts.map +1 -1
- package/dist/lib/agentLaunch.js +4 -0
- package/dist/lib/clearanceAllowlist.d.ts +8 -0
- package/dist/lib/clearanceAllowlist.d.ts.map +1 -0
- package/dist/lib/clearanceAllowlist.js +26 -0
- package/dist/lib/clearanceHosts.js +1 -10
- package/dist/lib/launchCommand.d.ts.map +1 -1
- package/dist/lib/launchCommand.js +5 -1
- package/dist/lib/pathList.d.ts +2 -0
- package/dist/lib/pathList.d.ts.map +1 -0
- package/dist/lib/pathList.js +11 -0
- package/dist/lib/srtLaunch.d.ts.map +1 -1
- package/dist/lib/srtLaunch.js +2 -1
- package/docs/runners.md +6 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -50,8 +50,8 @@ crew init --global --project-dir ~/dev --repo OWNER/REPO --agent claude
|
|
|
50
50
|
|
|
51
51
|
# 3. Run the clone commands printed by `crew init`.
|
|
52
52
|
|
|
53
|
-
# 4.
|
|
54
|
-
|
|
53
|
+
# 4. Safehouse runs use groundcrew's bundled clearance allowlist automatically.
|
|
54
|
+
# Add extra hosts later via CLEARANCE_ALLOW_HOSTS or CLEARANCE_ALLOW_HOSTS_FILES.
|
|
55
55
|
|
|
56
56
|
# 5. Using Linear? Export your API key. (Jira and other trackers: see Task Pickup.)
|
|
57
57
|
export GROUNDCREW_LINEAR_API_KEY="lin_api_..."
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/agentLaunch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agentLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/agentLaunch.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AASrB;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAwBhE;AAED,UAAU,mBAAmB;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA+C/B;AAwBD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB"}
|
package/dist/lib/agentLaunch.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ensureClearance } from "@clipboard-health/clearance";
|
|
2
|
+
import { clearanceAllowHostsFilesFromEnvironment } from "./clearanceAllowlist.js";
|
|
2
3
|
import { hasPreLaunchEnv, } from "./config.js";
|
|
3
4
|
import { detectHostCapabilities } from "./host.js";
|
|
4
5
|
import { buildLaunchCommand } from "./launchCommand.js";
|
|
@@ -77,6 +78,9 @@ async function alreadyReady() {
|
|
|
77
78
|
}
|
|
78
79
|
async function ensureSafehouseClearance(signal) {
|
|
79
80
|
await ensureClearance({
|
|
81
|
+
envOverrides: {
|
|
82
|
+
CLEARANCE_ALLOW_HOSTS_FILES: clearanceAllowHostsFilesFromEnvironment(),
|
|
83
|
+
},
|
|
80
84
|
logger: debug,
|
|
81
85
|
...(signal === undefined
|
|
82
86
|
? {}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface ClearanceAllowHostsFilesInput {
|
|
2
|
+
defaultFile?: string | undefined;
|
|
3
|
+
existingFiles?: string | undefined;
|
|
4
|
+
}
|
|
5
|
+
export declare function clearanceAllowHostsFilesValue(input?: ClearanceAllowHostsFilesInput): string;
|
|
6
|
+
export declare function clearanceAllowHostsFilesFromEnvironment(): string;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=clearanceAllowlist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearanceAllowlist.d.ts","sourceRoot":"","sources":["../../src/lib/clearanceAllowlist.ts"],"names":[],"mappings":"AAOA,UAAU,6BAA6B;IACrC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAMD,wBAAgB,6BAA6B,CAAC,KAAK,GAAE,6BAAkC,GAAG,MAAM,CAa/F;AAED,wBAAgB,uCAAuC,IAAI,MAAM,CAIhE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { splitPathList } from "./pathList.js";
|
|
3
|
+
import { readEnvironmentVariable } from "./util.js";
|
|
4
|
+
const CLEARANCE_ALLOW_HOSTS_FILES = "CLEARANCE_ALLOW_HOSTS_FILES";
|
|
5
|
+
function groundcrewClearanceAllowHostsFile() {
|
|
6
|
+
return path.resolve(import.meta.dirname, "..", "..", "clearance-allow-hosts");
|
|
7
|
+
}
|
|
8
|
+
export function clearanceAllowHostsFilesValue(input = {}) {
|
|
9
|
+
const defaultFile = input.defaultFile ?? groundcrewClearanceAllowHostsFile();
|
|
10
|
+
const files = [defaultFile, ...splitPathList(input.existingFiles)];
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
const uniqueFiles = [];
|
|
13
|
+
for (const file of files) {
|
|
14
|
+
if (seen.has(file)) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
seen.add(file);
|
|
18
|
+
uniqueFiles.push(file);
|
|
19
|
+
}
|
|
20
|
+
return uniqueFiles.join(path.delimiter);
|
|
21
|
+
}
|
|
22
|
+
export function clearanceAllowHostsFilesFromEnvironment() {
|
|
23
|
+
return clearanceAllowHostsFilesValue({
|
|
24
|
+
existingFiles: readEnvironmentVariable(CLEARANCE_ALLOW_HOSTS_FILES),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* validates.
|
|
15
15
|
*/
|
|
16
16
|
import { readFileSync } from "node:fs";
|
|
17
|
-
import
|
|
17
|
+
import { splitPathList } from "./pathList.js";
|
|
18
18
|
import { debug } from "./util.js";
|
|
19
19
|
/**
|
|
20
20
|
* Parse and validate clearance allow-host sources into a de-duplicated list of
|
|
@@ -51,15 +51,6 @@ export function collectAllowedDomains(input) {
|
|
|
51
51
|
}
|
|
52
52
|
return domains;
|
|
53
53
|
}
|
|
54
|
-
function splitPathList(value) {
|
|
55
|
-
if (value === undefined || value.length === 0) {
|
|
56
|
-
return [];
|
|
57
|
-
}
|
|
58
|
-
return value
|
|
59
|
-
.split(path.delimiter)
|
|
60
|
-
.map((entry) => entry.trim())
|
|
61
|
-
.filter((entry) => entry.length > 0);
|
|
62
|
-
}
|
|
63
54
|
/**
|
|
64
55
|
* Split a host source into candidate tokens. Handles env-style
|
|
65
56
|
* comma/whitespace separators and file-style newline lists with `#` comments
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launchCommand.d.ts","sourceRoot":"","sources":["../../src/lib/launchCommand.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"launchCommand.d.ts","sourceRoot":"","sources":["../../src/lib/launchCommand.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,GAAE,MAAwB,GAAG,MAAM,CAcvF;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,MAAwB,GAAG,MAAM,CAgB3E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,MAAM,CAMvF;AA0MD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA8B9D;AAED,UAAU,sBAAsB;IAC9B,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C;;;;OAIG;IACH,MAAM,EAAE,WAAW,CAAC;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACpE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,sBAAsB,GAAG,MAAM,CA6B7E"}
|
|
@@ -2,6 +2,7 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { BUILD_SECRET_NAMES, hasPreLaunchEnv, } from "./config.js";
|
|
5
|
+
import { clearanceAllowHostsFilesFromEnvironment } from "./clearanceAllowlist.js";
|
|
5
6
|
import { shellSingleQuote } from "./shell.js";
|
|
6
7
|
export { shellSingleQuote } from "./shell.js";
|
|
7
8
|
/**
|
|
@@ -100,6 +101,9 @@ function unsetEnvironmentLine(names) {
|
|
|
100
101
|
function unsetSecretsLine() {
|
|
101
102
|
return unsetEnvironmentLine(BUILD_SECRET_NAMES);
|
|
102
103
|
}
|
|
104
|
+
function safehouseClearanceWrapperCommand() {
|
|
105
|
+
return `CLEARANCE_ALLOW_HOSTS_FILES=${shellSingleQuote(clearanceAllowHostsFilesFromEnvironment())} ${shellSingleQuote(SAFEHOUSE_CLEARANCE_WRAPPER_PATH)}`;
|
|
106
|
+
}
|
|
103
107
|
function trapCleanupLine(promptDir) {
|
|
104
108
|
const cleanupCmd = `rm -rf ${shellSingleQuote(promptDir)}`;
|
|
105
109
|
return `trap ${shellSingleQuote(cleanupCmd)} EXIT`;
|
|
@@ -363,7 +367,7 @@ function buildSafehouseLaunchCommand(arguments_) {
|
|
|
363
367
|
const prepareWorktreeEnvPassFlag = arguments_.secretsFile === undefined ? "" : `--env-pass=${BUILD_SECRET_NAMES.join(",")} `;
|
|
364
368
|
const preLaunchEnvNames = arguments_.definition.preLaunchEnv ?? [];
|
|
365
369
|
const agentEnvPassFlag = preLaunchEnvNames.length === 0 ? "" : `--env-pass=${preLaunchEnvNames.join(",")} `;
|
|
366
|
-
const safehouseWrapper =
|
|
370
|
+
const safehouseWrapper = safehouseClearanceWrapperCommand();
|
|
367
371
|
// Defensive shim+promptDir trap: by the time we arm it, `rm -rf <promptDir>`
|
|
368
372
|
// has already run (line below) so the promptDir wipe is a no-op on the happy
|
|
369
373
|
// path. Keeps the failure-window between shim creation and the explicit
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathList.d.ts","sourceRoot":"","sources":["../../src/lib/pathList.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CASjE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function splitPathList(value) {
|
|
3
|
+
const paths = [];
|
|
4
|
+
for (const entry of value?.split(path.delimiter) ?? []) {
|
|
5
|
+
const pathEntry = entry.trim();
|
|
6
|
+
if (pathEntry.length > 0) {
|
|
7
|
+
paths.push(pathEntry);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return paths;
|
|
11
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"srtLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/srtLaunch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"srtLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/srtLaunch.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAKnD,MAAM,WAAW,eAAe;IAC9B,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAuBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,eAAe,CAAC;IAC5B,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,eAAe,CA6ClB"}
|
package/dist/lib/srtLaunch.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { clearanceAllowHostsFilesFromEnvironment } from "./clearanceAllowlist.js";
|
|
4
5
|
import { collectAllowedDomains } from "./clearanceHosts.js";
|
|
5
6
|
import { runCommand } from "./commandRunner.js";
|
|
6
7
|
import { inferAgentCommandName } from "./launchCommand.js";
|
|
@@ -53,7 +54,7 @@ export function buildAndStageSrtLaunch(input) {
|
|
|
53
54
|
gitCommonDir: resolveGitCommonDir(input.worktreeDir),
|
|
54
55
|
allowedDomains: collectAllowedDomains({
|
|
55
56
|
hosts: readEnvironmentVariable("CLEARANCE_ALLOW_HOSTS"),
|
|
56
|
-
files:
|
|
57
|
+
files: clearanceAllowHostsFilesFromEnvironment(),
|
|
57
58
|
}),
|
|
58
59
|
};
|
|
59
60
|
const directory = mkdtempSync(path.join(os.tmpdir(), `groundcrew-srt-${input.task}-`));
|
package/docs/runners.md
CHANGED
|
@@ -13,19 +13,21 @@
|
|
|
13
13
|
|
|
14
14
|
## Safehouse Clearance Allowlist
|
|
15
15
|
|
|
16
|
-
Only applies when `local.runner` resolves to `safehouse`. Groundcrew starts `clearance` on `http://127.0.0.1:19999` and runs the agent through the bundled `safehouse-clearance` wrapper.
|
|
16
|
+
Only applies when `local.runner` resolves to `safehouse`. Groundcrew starts `clearance` on `http://127.0.0.1:19999` and runs the agent through the bundled `safehouse-clearance` wrapper. Groundcrew automatically points clearance at its shipped starter allowlist, so a fresh install does not need a `CLEARANCE_ALLOW_HOSTS_FILES` export.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Groundcrew ships that starter file at `$(npm root -g)/@clipboard-health/groundcrew/clearance-allow-hosts`, covering model APIs, Linear, Notion, Slack, Datadog, GitHub, npm, and common dev tooling.
|
|
19
|
+
|
|
20
|
+
To add ad hoc hosts for one run, use `CLEARANCE_ALLOW_HOSTS`:
|
|
19
21
|
|
|
20
22
|
```bash
|
|
21
23
|
CLEARANCE_ALLOW_HOSTS="api.openai.com,auth.openai.com,api.anthropic.com,mcp.linear.app,api.linear.app" \
|
|
22
24
|
crew run --watch
|
|
23
25
|
```
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
To keep personal hosts in a file, set `CLEARANCE_ALLOW_HOSTS_FILES` to only the additional files. Groundcrew prepends its shipped file automatically:
|
|
26
28
|
|
|
27
29
|
```bash
|
|
28
|
-
CLEARANCE_ALLOW_HOSTS_FILES="$
|
|
30
|
+
CLEARANCE_ALLOW_HOSTS_FILES="$HOME/.config/clearance/personal-allow-hosts" \
|
|
29
31
|
crew run --watch
|
|
30
32
|
```
|
|
31
33
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/groundcrew",
|
|
3
|
-
"version": "4.31.
|
|
3
|
+
"version": "4.31.1",
|
|
4
4
|
"description": "Linear-driven orchestrator that launches AI coding agents in git worktrees, with workspace lifecycle and usage tracking.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"@anthropic-ai/sandbox-runtime": "0.0.52",
|
|
72
|
-
"@clipboard-health/clearance": "1.
|
|
72
|
+
"@clipboard-health/clearance": "1.2.0",
|
|
73
73
|
"@linear/sdk": "86.0.0",
|
|
74
74
|
"cosmiconfig": "9.0.1",
|
|
75
75
|
"tslib": "2.8.1",
|