@brainbase-labs/cli 0.29.1 → 0.31.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.
Files changed (3) hide show
  1. package/README.md +3 -1
  2. package/dist/index.js +139 -56
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -83,7 +83,9 @@ prompt.
83
83
  Idempotency is explicit-only: requests omit the idempotency header unless
84
84
  `--idempotency-key` is supplied. Reuse a key only for an identical retry.
85
85
  Starting a run requires `--yes`; confirming the same plan ID is replay-safe.
86
- Interrupting `run watch` does not cancel the remote run.
86
+ Interrupting `run watch` does not cancel the remote run. A run that MAS pauses
87
+ for billing stops `run watch` with exit code 1; once billing is fixed, run
88
+ `brainbase benchmark run resume <run-id> --yes` to put it back in the queue.
87
89
 
88
90
  Use `brainbase benchmark --help`, `brainbase benchmark run --help`, or
89
91
  `brainbase benchmark <command> --help` for local command help.
package/dist/index.js CHANGED
@@ -36018,7 +36018,7 @@ function padStart(s, n) {
36018
36018
  // package.json
36019
36019
  var package_default = {
36020
36020
  name: "@brainbase-labs/cli",
36021
- version: "0.29.1",
36021
+ version: "0.31.0",
36022
36022
  description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
36023
36023
  type: "module",
36024
36024
  bin: {
@@ -62408,14 +62408,16 @@ var McpEntrySchema = exports_external.object({
62408
62408
  args: exports_external.array(exports_external.string()).optional(),
62409
62409
  env: exports_external.record(exports_external.string()).optional(),
62410
62410
  headers: exports_external.record(exports_external.string()).optional(),
62411
- is_enabled: exports_external.boolean().optional()
62411
+ is_enabled: exports_external.boolean().optional(),
62412
+ runtime_meta: exports_external.record(exports_external.unknown()).optional()
62412
62413
  });
62413
62414
  var CapabilitiesSchema = exports_external.object({
62414
62415
  memory: exports_external.boolean().optional(),
62415
62416
  browser: exports_external.boolean().optional(),
62416
62417
  slack: exports_external.boolean().optional(),
62417
62418
  meeting: exports_external.boolean().optional(),
62418
- github: exports_external.boolean().optional()
62419
+ github: exports_external.boolean().optional(),
62420
+ linear: exports_external.boolean().optional()
62419
62421
  });
62420
62422
  var EvalOutputShape = exports_external.enum(["binary", "rating", "classification"]);
62421
62423
  var EVAL_SLUG_RE = /^[a-z0-9][a-z0-9-]*$/;
@@ -63581,6 +63583,39 @@ function buildGithubMcpComponent(scope) {
63581
63583
  };
63582
63584
  }
63583
63585
 
63586
+ // src/core/linear-mcp.ts
63587
+ var DEFAULT_LINEAR_MCP_BASE = "https://brainbase-linear-mcp.onrender.com";
63588
+ var LINEAR_MCP_SLUG = "brainbase-linear";
63589
+ function linearMcpBaseUrl() {
63590
+ const envOverride = process.env.BRAINBASE_LINEAR_MCP_URL;
63591
+ if (envOverride)
63592
+ return envOverride.replace(/\/+$/, "");
63593
+ return DEFAULT_LINEAR_MCP_BASE;
63594
+ }
63595
+ function linearMcpUrl() {
63596
+ return `${linearMcpBaseUrl()}/t/\${BRAINBASE_THREAD_ID}/mcp`;
63597
+ }
63598
+ function linearMcpPayload() {
63599
+ return {
63600
+ url: linearMcpUrl(),
63601
+ headers: {
63602
+ Authorization: "Bearer ${BRAINBASE_TOKEN}"
63603
+ }
63604
+ };
63605
+ }
63606
+ function buildLinearMcpComponent(scope) {
63607
+ return {
63608
+ type: "mcp",
63609
+ slug: LINEAR_MCP_SLUG,
63610
+ scope,
63611
+ rootDir: "",
63612
+ description: "This agent's Linear connector (read and update issues, comment, and " + "report progress on delegated work). Scoped to this agent only.",
63613
+ meta: { mcp: linearMcpPayload() },
63614
+ payload: linearMcpPayload(),
63615
+ checksum: "builtin:brainbase-linear:v1"
63616
+ };
63617
+ }
63618
+
63584
63619
  // src/core/browser-mcp.ts
63585
63620
  var DEFAULT_BROWSER_MCP_BASE = "https://brainbase-browser-mcp.onrender.com";
63586
63621
  var BROWSER_MCP_SLUG = "brainbase-browser";
@@ -63621,7 +63656,8 @@ function capabilitiesFromAgent(agent) {
63621
63656
  browser: agent.browser_enabled !== false,
63622
63657
  slack: agent.slack_connected === true,
63623
63658
  meeting: agent.meeting_connected === true,
63624
- github: agent.github_connected === true
63659
+ github: agent.github_connected === true,
63660
+ linear: agent.linear_connected === true
63625
63661
  };
63626
63662
  }
63627
63663
  function capabilitiesFromManifest(manifest) {
@@ -63631,7 +63667,8 @@ function capabilitiesFromManifest(manifest) {
63631
63667
  browser: c2.browser !== false,
63632
63668
  slack: c2.slack === true,
63633
63669
  meeting: c2.meeting === true,
63634
- github: c2.github === true
63670
+ github: c2.github === true,
63671
+ linear: c2.linear === true
63635
63672
  };
63636
63673
  }
63637
63674
  function resolveBuiltinMcps(input) {
@@ -63642,7 +63679,8 @@ function resolveBuiltinMcps(input) {
63642
63679
  { slug: BROWSER_MCP_SLUG, enabled: caps.browser, build: buildBrowserMcpComponent },
63643
63680
  { slug: SLACK_MCP_SLUG, enabled: caps.slack, build: buildSlackMcpComponent },
63644
63681
  { slug: MEETING_MCP_SLUG, enabled: caps.meeting, build: buildMeetingMcpComponent },
63645
- { slug: GITHUB_MCP_SLUG, enabled: caps.github, build: buildGithubMcpComponent }
63682
+ { slug: GITHUB_MCP_SLUG, enabled: caps.github, build: buildGithubMcpComponent },
63683
+ { slug: LINEAR_MCP_SLUG, enabled: caps.linear, build: buildLinearMcpComponent }
63646
63684
  ];
63647
63685
  const install = [];
63648
63686
  const removeSlugs = [];
@@ -64408,7 +64446,7 @@ function diffAgentMeta(manifestMeta, lockMeta, cloudMeta) {
64408
64446
  };
64409
64447
  }
64410
64448
  var WRITABLE_CAPABILITIES = ["memory", "browser"];
64411
- var MIRRORED_CAPABILITIES = ["slack", "meeting", "github"];
64449
+ var MIRRORED_CAPABILITIES = ["slack", "meeting", "github", "linear"];
64412
64450
  function manifestConfigState(manifest) {
64413
64451
  return {
64414
64452
  ...manifest.machine_kind !== undefined ? { machine_kind: manifest.machine_kind } : {},
@@ -64432,7 +64470,8 @@ function staleConnectionMirrors(manifest, cloud) {
64432
64470
  const actualByName = {
64433
64471
  slack: cloud.slack_connected,
64434
64472
  meeting: cloud.meeting_connected,
64435
- github: cloud.github_connected
64473
+ github: cloud.github_connected,
64474
+ linear: cloud.linear_connected
64436
64475
  };
64437
64476
  const stale = [];
64438
64477
  for (const name of MIRRORED_CAPABILITIES) {
@@ -64595,6 +64634,41 @@ function capabilityBaselineAfterPush(cloudAgent, previous, diff2) {
64595
64634
  return out;
64596
64635
  }
64597
64636
 
64637
+ // src/core/mcp-merge.ts
64638
+ var RUNTIME_META_PREFIX = "runtime_";
64639
+ function runtimeMetaFromComponent(component) {
64640
+ const meta = component.meta ?? {};
64641
+ const carried = {};
64642
+ for (const [key2, value] of Object.entries(meta)) {
64643
+ if (key2.startsWith(RUNTIME_META_PREFIX) && value !== undefined) {
64644
+ carried[key2] = value;
64645
+ }
64646
+ }
64647
+ return Object.keys(carried).length > 0 ? carried : undefined;
64648
+ }
64649
+ function mcpEntriesFromCloudComponents(components) {
64650
+ return components.filter((c2) => c2.type === "mcp").map((c2) => {
64651
+ const payload = (c2.meta ?? {}).mcp ?? {};
64652
+ const entry = { name: c2.slug };
64653
+ if (typeof payload.url === "string")
64654
+ entry.url = payload.url;
64655
+ if (typeof payload.command === "string")
64656
+ entry.command = payload.command;
64657
+ if (Array.isArray(payload.args))
64658
+ entry.args = payload.args.map(String);
64659
+ if (payload.env && typeof payload.env === "object")
64660
+ entry.env = payload.env;
64661
+ if (payload.headers && typeof payload.headers === "object")
64662
+ entry.headers = payload.headers;
64663
+ if (typeof payload.is_enabled === "boolean")
64664
+ entry.is_enabled = payload.is_enabled;
64665
+ const runtimeMeta = runtimeMetaFromComponent(c2);
64666
+ if (runtimeMeta)
64667
+ entry.runtime_meta = runtimeMeta;
64668
+ return entry;
64669
+ });
64670
+ }
64671
+
64598
64672
  // src/core/secrets-env.ts
64599
64673
  import path78 from "node:path";
64600
64674
  import fs71 from "node:fs";
@@ -65445,23 +65519,7 @@ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness, localOnly = {}, s
65445
65519
  content
65446
65520
  };
65447
65521
  });
65448
- const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
65449
- const payload = (c2.meta ?? {}).mcp ?? {};
65450
- const entry = { name: c2.slug };
65451
- if (typeof payload.url === "string")
65452
- entry.url = payload.url;
65453
- if (typeof payload.command === "string")
65454
- entry.command = payload.command;
65455
- if (Array.isArray(payload.args))
65456
- entry.args = payload.args.map(String);
65457
- if (payload.env && typeof payload.env === "object")
65458
- entry.env = payload.env;
65459
- if (payload.headers && typeof payload.headers === "object")
65460
- entry.headers = payload.headers;
65461
- if (typeof payload.is_enabled === "boolean")
65462
- entry.is_enabled = payload.is_enabled;
65463
- return entry;
65464
- });
65522
+ const mcp = mcpEntriesFromCloudComponents(cloud.components);
65465
65523
  const evals = evalsFromCloudComponents(cloud.components);
65466
65524
  const caps = capabilitiesFromAgent(cloudAgent);
65467
65525
  const machineKind = cloudAgent.machine_kind ?? prev?.machine_kind;
@@ -65496,7 +65554,8 @@ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness, localOnly = {}, s
65496
65554
  browser: caps.browser,
65497
65555
  slack: caps.slack,
65498
65556
  meeting: caps.meeting,
65499
- github: caps.github
65557
+ github: caps.github,
65558
+ linear: caps.linear
65500
65559
  }
65501
65560
  };
65502
65561
  }
@@ -65881,7 +65940,7 @@ async function buildOutgoingComponents(cwd2, manifest, cloud, resolvedVersions)
65881
65940
  slug: entry.name,
65882
65941
  hash: "",
65883
65942
  files: [],
65884
- meta: { mcp: payload }
65943
+ meta: { ...entry.runtime_meta ?? {}, mcp: payload }
65885
65944
  });
65886
65945
  }
65887
65946
  return out;
@@ -69044,23 +69103,7 @@ function buildManifestFromCloud(cloud, agent, localOnly = {}) {
69044
69103
  return { source: `registry:${c2.slug}` };
69045
69104
  });
69046
69105
  const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
69047
- const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
69048
- const payload = (c2.meta ?? {}).mcp ?? {};
69049
- const entry = { name: c2.slug };
69050
- if (typeof payload.url === "string")
69051
- entry.url = payload.url;
69052
- if (typeof payload.command === "string")
69053
- entry.command = payload.command;
69054
- if (Array.isArray(payload.args))
69055
- entry.args = payload.args.map(String);
69056
- if (payload.env && typeof payload.env === "object")
69057
- entry.env = payload.env;
69058
- if (payload.headers && typeof payload.headers === "object")
69059
- entry.headers = payload.headers;
69060
- if (typeof payload.is_enabled === "boolean")
69061
- entry.is_enabled = payload.is_enabled;
69062
- return entry;
69063
- });
69106
+ const mcp = mcpEntriesFromCloudComponents(cloud.components);
69064
69107
  const playbooks = cloud.components.filter((c2) => c2.type === "playbook").map((c2) => {
69065
69108
  const raw = c2.files[0]?.content ?? "";
69066
69109
  const { frontmatter } = stripPlaybookFrontmatter(raw);
@@ -69100,7 +69143,8 @@ function buildManifestFromCloud(cloud, agent, localOnly = {}) {
69100
69143
  browser: caps.browser,
69101
69144
  slack: caps.slack,
69102
69145
  meeting: caps.meeting,
69103
- github: caps.github
69146
+ github: caps.github,
69147
+ linear: caps.linear
69104
69148
  }
69105
69149
  };
69106
69150
  }
@@ -84701,7 +84745,7 @@ class BenchmarkApiClient {
84701
84745
  try {
84702
84746
  responseBody = text3 ? JSON.parse(text3) : null;
84703
84747
  } catch {}
84704
- throw new BenchmarkApiError(redactSensitiveText(apiErrorMessage(responseBody, response.status)), response.status, responseBody, safeCode(responseBody), response.headers.get("x-request-id") ?? response.headers.get("x-correlation-id") ?? undefined);
84748
+ throw new BenchmarkApiError(redactSensitiveText(masApiErrorMessage(responseBody, response.status)), response.status, responseBody, safeCode(responseBody), response.headers.get("x-request-id") ?? response.headers.get("x-correlation-id") ?? undefined);
84705
84749
  }
84706
84750
  if (options.mode === "binary") {
84707
84751
  return {
@@ -84916,6 +84960,11 @@ class BenchmarkApiClient {
84916
84960
  method: "POST"
84917
84961
  });
84918
84962
  }
84963
+ resumeRun(runId) {
84964
+ return this.request(`/runs/${encodeURIComponent(runId)}/resume`, {
84965
+ method: "POST"
84966
+ });
84967
+ }
84919
84968
  listDiagnoses(runId, query = {}) {
84920
84969
  return this.request(`/runs/${encodeURIComponent(runId)}/diagnoses`, {
84921
84970
  query: {
@@ -87301,6 +87350,12 @@ class BenchmarkControlOutput {
87301
87350
  `);
87302
87351
  }
87303
87352
  }
87353
+ hint(text2) {
87354
+ if (this.mode.json || this.mode.jsonl)
87355
+ return;
87356
+ this.writer.stdout(`${text2}
87357
+ `);
87358
+ }
87304
87359
  page(page, all = false) {
87305
87360
  if (this.mode.jsonl) {
87306
87361
  for (const item of page.items)
@@ -87332,6 +87387,7 @@ class BenchmarkControlOutput {
87332
87387
 
87333
87388
  // src/cli/benchmark-control.ts
87334
87389
  var TERMINAL_RUN_STATUSES = new Set(["cancelled", "failed", "succeeded"]);
87390
+ var PAUSED_RUN_STATUS = "paused";
87335
87391
  var MAX_MANIFEST_IMPORT_BYTES = 2 * 1024 * 1024;
87336
87392
  var MAX_CSV_IMPORT_BYTES = 10 * 1024 * 1024;
87337
87393
  var MAX_PAGINATION_PAGES = 1e4;
@@ -87508,7 +87564,7 @@ function commandHelp() {
87508
87564
  "",
87509
87565
  ` ${import_picocolors60.default.cyan("init | list | show | create | validate | pull | push")}`,
87510
87566
  ` ${import_picocolors60.default.cyan("publish | revisions | import | export | archive | restore")}`,
87511
- ` ${import_picocolors60.default.cyan("run plan|start|watch|list|show|cancel")}`,
87567
+ ` ${import_picocolors60.default.cyan("run plan|start|watch|list|show|cancel|resume")}`,
87512
87568
  ` ${import_picocolors60.default.cyan("results | diagnoses | attempt | artifacts | export-results")}`,
87513
87569
  ` ${import_picocolors60.default.cyan("history | baseline show|set|clear")}`,
87514
87570
  "",
@@ -87908,7 +87964,7 @@ function runPlanInput(options, revisionId) {
87908
87964
  revision_id: revisionId,
87909
87965
  variants: variants.length > 0 ? variants.map(parseVariant) : [{ key: "default" }],
87910
87966
  repetitions: integerOption(options.parsed, "repetitions", { min: 1, max: 10 }) ?? 1,
87911
- concurrency: integerOption(options.parsed, "concurrency", { min: 1, max: 10 }) ?? 5
87967
+ concurrency: integerOption(options.parsed, "concurrency", { min: 1, max: 50 }) ?? 5
87912
87968
  };
87913
87969
  if (cases.length > 0)
87914
87970
  input.case_keys = cases;
@@ -87954,7 +88010,15 @@ async function runStart(cwd2, argv, deps) {
87954
88010
  const { client, output } = context(cwd2, "benchmark run start", options, deps);
87955
88011
  output.result(json(await client.confirmRunPlan(planId)));
87956
88012
  }
87957
- async function watchRun(client, output, runId, interval, deps) {
88013
+ function pausedRunHint(runId, run, agentId) {
88014
+ const reason = run.paused_reason;
88015
+ const message = reason && typeof reason === "object" && !Array.isArray(reason) ? reason.message : undefined;
88016
+ const first = typeof message === "string" && message.trim() ? `Run paused: ${message.trim()}` : "Run paused.";
88017
+ const agent = agentId ? ` --agent ${agentId}` : "";
88018
+ return `${first}
88019
+ Resume with: brainbase benchmark run resume ${runId} --yes${agent}`;
88020
+ }
88021
+ async function watchRun(client, output, runId, interval, agentId, deps) {
87958
88022
  let interrupted = false;
87959
88023
  const controller = new AbortController;
87960
88024
  const onInterrupt = () => {
@@ -87976,9 +88040,16 @@ async function watchRun(client, output, runId, interval, deps) {
87976
88040
  const digest2 = output.digest(latest);
87977
88041
  if (digest2 !== previous) {
87978
88042
  const status = typeof latest.status === "string" ? latest.status : "unknown";
87979
- output.event(TERMINAL_RUN_STATUSES.has(status) ? "run.completed" : "run.updated", latest, typeof latest.updated_at === "string" ? latest.updated_at : undefined);
88043
+ const terminal = TERMINAL_RUN_STATUSES.has(status);
88044
+ const paused = status === PAUSED_RUN_STATUS;
88045
+ output.event(terminal ? "run.completed" : paused ? "run.paused" : "run.updated", latest, typeof latest.updated_at === "string" ? latest.updated_at : undefined);
87980
88046
  previous = digest2;
87981
- if (TERMINAL_RUN_STATUSES.has(status)) {
88047
+ if (paused) {
88048
+ output.hint(pausedRunHint(runId, latest, agentId));
88049
+ deps.setExitCode(1);
88050
+ return { run: latest, interrupted: false };
88051
+ }
88052
+ if (terminal) {
87982
88053
  if (status !== "succeeded")
87983
88054
  deps.setExitCode(1);
87984
88055
  return { run: latest, interrupted: false };
@@ -88000,7 +88071,7 @@ async function runWatch(cwd2, argv, deps) {
88000
88071
  const watched = await watchRun(client, output, options.positionals[0], integerOption(options.parsed, "interval", {
88001
88072
  min: 100,
88002
88073
  max: 60000
88003
- }) ?? 2000, deps);
88074
+ }) ?? 2000, options.agent, deps);
88004
88075
  if (options.json) {
88005
88076
  output.result({
88006
88077
  run: watched.run,
@@ -88040,6 +88111,15 @@ async function runCancel(cwd2, argv, deps) {
88040
88111
  const { client, output } = context(cwd2, "benchmark run cancel", options, deps);
88041
88112
  output.result(json(await client.cancelRun(options.positionals[0])));
88042
88113
  }
88114
+ async function runResume(cwd2, argv, deps) {
88115
+ const options = parseControlOptions(argv, ["yes"]);
88116
+ expectPositionals(options.positionals, 1, 1, "brainbase benchmark run resume <run-id>");
88117
+ if (!bool(options.parsed, "yes")) {
88118
+ throw usageError("--yes is required to resume a benchmark run");
88119
+ }
88120
+ const { client, output } = context(cwd2, "benchmark run resume", options, deps);
88121
+ output.result(json(await client.resumeRun(options.positionals[0])));
88122
+ }
88043
88123
  async function runOneShot(cwd2, argv, deps) {
88044
88124
  const options = parseControlOptions(argv, [
88045
88125
  ...RUN_PLAN_OPTIONS,
@@ -88079,7 +88159,7 @@ async function runOneShot(cwd2, argv, deps) {
88079
88159
  const watched = await watchRun(client, output, runId, integerOption(options.parsed, "interval", {
88080
88160
  min: 100,
88081
88161
  max: 60000
88082
- }) ?? 2000, deps);
88162
+ }) ?? 2000, options.agent, deps);
88083
88163
  if (options.json) {
88084
88164
  output.result({
88085
88165
  plan,
@@ -88105,6 +88185,8 @@ async function runRunRouter(cwd2, argv, deps) {
88105
88185
  case "cancel":
88106
88186
  case "stop":
88107
88187
  return await runCancel(cwd2, rest2, deps);
88188
+ case "resume":
88189
+ return await runResume(cwd2, rest2, deps);
88108
88190
  case undefined:
88109
88191
  case "help":
88110
88192
  case "--help":
@@ -88378,10 +88460,10 @@ function commandLevelHelp(sub, argv) {
88378
88460
  if (action === "show") {
88379
88461
  return usage("brainbase benchmark run show <run-id>");
88380
88462
  }
88381
- if (action === "cancel" || action === "stop") {
88463
+ if (action === "cancel" || action === "stop" || action === "resume") {
88382
88464
  return usage(`brainbase benchmark run ${action} <run-id> --yes`);
88383
88465
  }
88384
- return usage("brainbase benchmark run <benchmark-id> --yes [--revision <revision-id>] [--watch] [--idempotency-key <key>]", "brainbase benchmark run plan <benchmark-id> --revision <revision-id>", "brainbase benchmark run start <plan-id> --yes", "brainbase benchmark run watch <run-id> [--interval-ms <n>]", "brainbase benchmark run list [benchmark-id] [--status <status>] [--limit <n>] [--cursor <cursor>] [--all]", "brainbase benchmark run show <run-id>", "brainbase benchmark run cancel <run-id> --yes");
88466
+ return usage("brainbase benchmark run <benchmark-id> --yes [--revision <revision-id>] [--watch] [--idempotency-key <key>]", "brainbase benchmark run plan <benchmark-id> --revision <revision-id>", "brainbase benchmark run start <plan-id> --yes", "brainbase benchmark run watch <run-id> [--interval-ms <n>]", "brainbase benchmark run list [benchmark-id] [--status <status>] [--limit <n>] [--cursor <cursor>] [--all]", "brainbase benchmark run show <run-id>", "brainbase benchmark run cancel <run-id> --yes", "brainbase benchmark run resume <run-id> --yes");
88385
88467
  case "results":
88386
88468
  return usage("brainbase benchmark results <run-id> [--baseline-target <target-id>]");
88387
88469
  case "diagnoses":
@@ -88414,7 +88496,7 @@ function automationCommand(sub, argv) {
88414
88496
  const action = argv[0];
88415
88497
  if (action === "stop")
88416
88498
  return "benchmark run cancel";
88417
- if (action && ["plan", "start", "watch", "list", "show", "cancel"].includes(action)) {
88499
+ if (action && ["plan", "start", "watch", "list", "show", "cancel", "resume"].includes(action)) {
88418
88500
  return `benchmark run ${action}`;
88419
88501
  }
88420
88502
  return "benchmark run";
@@ -89048,6 +89130,7 @@ function help() {
89048
89130
  out.push(` ${import_picocolors61.default.dim("BRAINBASE_SLACK_MCP_URL")} override the built-in Slack MCP host`);
89049
89131
  out.push(` ${import_picocolors61.default.dim("BRAINBASE_MEETING_MCP_URL")} override the built-in meeting MCP host`);
89050
89132
  out.push(` ${import_picocolors61.default.dim("BRAINBASE_GITHUB_MCP_URL")} override the built-in GitHub MCP host`);
89133
+ out.push(` ${import_picocolors61.default.dim("BRAINBASE_LINEAR_MCP_URL")} override the built-in Linear MCP host`);
89051
89134
  out.push(` ${import_picocolors61.default.dim("BRAINBASE_ORCHESTRATION_MCP_URL")} override the built-in orchestration MCP host`);
89052
89135
  out.push("");
89053
89136
  out.push(divider("HARNESSES"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainbase-labs/cli",
3
- "version": "0.29.1",
3
+ "version": "0.31.0",
4
4
  "description": "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
5
5
  "type": "module",
6
6
  "bin": {