@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 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. Set the clearance egress proxy allowlist.
54
- export CLEARANCE_ALLOW_HOSTS_FILES="$(npm root -g)/@clipboard-health/groundcrew/clearance-allow-hosts"
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":"AAEA,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;AAqBD,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"}
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"}
@@ -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 path from "node:path";
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;AAGrB,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;AAsMD;;;;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"}
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 = shellSingleQuote(SAFEHOUSE_CLEARANCE_WRAPPER_PATH);
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,2 @@
1
+ export declare function splitPathList(value: string | undefined): string[];
2
+ //# sourceMappingURL=pathList.d.ts.map
@@ -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":"AAMA,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"}
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"}
@@ -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: readEnvironmentVariable("CLEARANCE_ALLOW_HOSTS_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. Clearance refuses to start without an allowlist.
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
- Shortest path:
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
- Groundcrew ships a starter file covering model APIs, Linear, Notion, Slack, Datadog, GitHub, npm, and common dev tooling at `$(npm root -g)/@clipboard-health/groundcrew/clearance-allow-hosts`. Point clearance at it, optionally with a personal file:
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="$(npm root -g)/@clipboard-health/groundcrew/clearance-allow-hosts:$HOME/.config/clearance/personal-allow-hosts" \
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.0",
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.1.14",
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",