@brainbase-labs/cli 0.16.5 → 0.18.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 +11 -5
  2. package/dist/index.js +1086 -533
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -35141,7 +35141,7 @@ var require_dist2 = __commonJS((exports, module) => {
35141
35141
  });
35142
35142
 
35143
35143
  // src/index.ts
35144
- var import_picocolors43 = __toESM(require_picocolors(), 1);
35144
+ var import_picocolors48 = __toESM(require_picocolors(), 1);
35145
35145
  import process14 from "node:process";
35146
35146
  import fs79 from "node:fs";
35147
35147
 
@@ -36008,7 +36008,7 @@ function padStart(s, n) {
36008
36008
  // package.json
36009
36009
  var package_default = {
36010
36010
  name: "@brainbase-labs/cli",
36011
- version: "0.16.5",
36011
+ version: "0.18.0",
36012
36012
  description: "Pack, share, and install agent templates across harnesses (Claude Code, Codex, ...).",
36013
36013
  type: "module",
36014
36014
  bin: {
@@ -53841,9 +53841,80 @@ function apiErrorMessage(body, status) {
53841
53841
  return `HTTP ${status}`;
53842
53842
  }
53843
53843
 
53844
+ // src/core/token.ts
53845
+ import path57 from "node:path";
53846
+ import fs47 from "node:fs";
53847
+ var TOKEN_FILE = path57.join(BRAINBASE_HOME, "token.json");
53848
+ var TOKEN_PREFIX = "bbpat_";
53849
+ var TOKEN_PREFIX_LEN = 14;
53850
+ function tokenPrefix(token) {
53851
+ if (!token.startsWith(TOKEN_PREFIX)) {
53852
+ throw new Error(`not a brainbase PAT: missing ${TOKEN_PREFIX} prefix`);
53853
+ }
53854
+ return token.slice(0, TOKEN_PREFIX_LEN);
53855
+ }
53856
+ function isValidTokenFormat(token) {
53857
+ if (typeof token !== "string")
53858
+ return false;
53859
+ if (!token.startsWith(TOKEN_PREFIX))
53860
+ return false;
53861
+ return /^bbpat_[A-Za-z0-9]{20,}$/.test(token);
53862
+ }
53863
+ var StoredTokenSchema = exports_external.object({
53864
+ schemaVersion: exports_external.literal(1),
53865
+ token: exports_external.string(),
53866
+ prefix: exports_external.string(),
53867
+ name: exports_external.string().optional(),
53868
+ createdAt: exports_external.string()
53869
+ });
53870
+ function readToken() {
53871
+ if (!exists(TOKEN_FILE))
53872
+ return null;
53873
+ try {
53874
+ return StoredTokenSchema.parse(readJson(TOKEN_FILE));
53875
+ } catch {
53876
+ return null;
53877
+ }
53878
+ }
53879
+ function writeToken(token, name) {
53880
+ if (!isValidTokenFormat(token)) {
53881
+ throw new Error("refusing to store token: invalid format");
53882
+ }
53883
+ ensureDir(BRAINBASE_HOME);
53884
+ const stored = {
53885
+ schemaVersion: 1,
53886
+ token,
53887
+ prefix: tokenPrefix(token),
53888
+ name,
53889
+ createdAt: new Date().toISOString()
53890
+ };
53891
+ writeJson(TOKEN_FILE, stored);
53892
+ try {
53893
+ fs47.chmodSync(TOKEN_FILE, 384);
53894
+ } catch {}
53895
+ return stored;
53896
+ }
53897
+ function clearToken() {
53898
+ if (exists(TOKEN_FILE))
53899
+ fs47.rmSync(TOKEN_FILE);
53900
+ }
53901
+
53844
53902
  // src/core/api.ts
53845
53903
  var DEFAULT_CONTROL_PLANE_BASE = "https://api.brainbaselabs.com";
53846
53904
  var DEFAULT_PROXY_BASE = "https://api.v1.brainbaselabs.com";
53905
+ var MAS_IN_PROGRESS_MAX_WAIT_MS = 15000;
53906
+ var MAS_REQUEST_TIMEOUT_MS = 30000;
53907
+ var MAS_MIN_RETRY_DELAY_MS = 100;
53908
+ var MAS_MAX_RETRY_DELAY_MS = 2000;
53909
+ var DEFINITELY_UNSENT_NETWORK_CODES = new Set([
53910
+ "ConnectionRefused",
53911
+ "ECONNREFUSED",
53912
+ "ENOTFOUND",
53913
+ "EAI_AGAIN",
53914
+ "ERR_INVALID_URL",
53915
+ "FailedToOpenSocket",
53916
+ "UND_ERR_CONNECT_TIMEOUT"
53917
+ ]);
53847
53918
 
53848
53919
  class ApiError extends Error {
53849
53920
  status;
@@ -53855,6 +53926,17 @@ class ApiError extends Error {
53855
53926
  this.name = "ApiError";
53856
53927
  }
53857
53928
  }
53929
+
53930
+ class NetworkApiError extends ApiError {
53931
+ definitelyUnsent;
53932
+ constructor(message, definitelyUnsent) {
53933
+ super(message);
53934
+ this.definitelyUnsent = definitelyUnsent;
53935
+ }
53936
+ }
53937
+
53938
+ class TaskRecoveryDeadlineError extends ApiError {
53939
+ }
53858
53940
  function normalizeControlPlaneUrl(url) {
53859
53941
  const normalized = url?.trim().replace(/\/+$/, "");
53860
53942
  return normalized || DEFAULT_CONTROL_PLANE_BASE;
@@ -53870,10 +53952,17 @@ function controlPlaneBaseUrl(session) {
53870
53952
  }
53871
53953
  return normalizeControlPlaneUrl(session?.control_plane_url);
53872
53954
  }
53955
+ function masControlPlaneBaseUrl(session) {
53956
+ const controlPlane = process.env.BRAINBASE_CONTROL_PLANE_URL?.trim();
53957
+ return normalizeControlPlaneUrl(controlPlane || session?.control_plane_url);
53958
+ }
53873
53959
  function apiBase(session) {
53874
53960
  const suffix = usesLegacyControlPlane() ? "/api/cli" : "/v2/cli";
53875
53961
  return `${controlPlaneBaseUrl(session)}${suffix}`;
53876
53962
  }
53963
+ function masApiBase(session) {
53964
+ return `${masControlPlaneBaseUrl(session)}/v2`;
53965
+ }
53877
53966
  function usesLegacyControlPlane() {
53878
53967
  return !process.env.BRAINBASE_CONTROL_PLANE_URL?.trim() && !!process.env.BRAINBASE_API_URL?.trim();
53879
53968
  }
@@ -53903,6 +53992,53 @@ async function resolveCredential() {
53903
53992
  const status = authStatus();
53904
53993
  throw new ApiError(status.ok ? "CLI authentication changed while this command was starting; retry it" : status.reason ?? "not logged in", 401);
53905
53994
  }
53995
+ async function resolveMasCredential() {
53996
+ const configuredSession = readAuth();
53997
+ try {
53998
+ return await resolveCredential();
53999
+ } catch (error) {
54000
+ if (!(error instanceof ApiError && error.status === 401)) {
54001
+ throw error;
54002
+ }
54003
+ if (configuredSession || readAuth()) {
54004
+ if (readToken()) {
54005
+ throw new ApiError(`${error.message}. A stored PAT is available but will not be used while a login session is configured. Run \`brainbase logout\` to use the stored PAT, or \`brainbase login\` to refresh the session.`, 401);
54006
+ }
54007
+ throw error;
54008
+ }
54009
+ }
54010
+ const storedToken = readToken();
54011
+ if (storedToken) {
54012
+ return {
54013
+ bearer: storedToken.token,
54014
+ session: null,
54015
+ source: "stored_pat"
54016
+ };
54017
+ }
54018
+ const status = authStatus();
54019
+ throw new ApiError(status.ok ? "CLI authentication changed while this command was starting; retry it" : status.reason ?? "not logged in", 401);
54020
+ }
54021
+ function networkErrorCode(error) {
54022
+ if (!error || typeof error !== "object")
54023
+ return;
54024
+ const code = error.code;
54025
+ if (typeof code === "string")
54026
+ return code;
54027
+ const cause = error.cause;
54028
+ if (!cause || typeof cause !== "object")
54029
+ return;
54030
+ const causeCode = cause.code;
54031
+ return typeof causeCode === "string" ? causeCode : undefined;
54032
+ }
54033
+ function isDefinitelyUnsentNetworkError(error) {
54034
+ const code = networkErrorCode(error);
54035
+ if (DEFINITELY_UNSENT_NETWORK_CODES.has(code ?? ""))
54036
+ return true;
54037
+ if (!error || typeof error !== "object")
54038
+ return false;
54039
+ const cause = error.cause;
54040
+ return !!cause && typeof cause === "object" && cause.message === "bad port";
54041
+ }
53906
54042
  async function sendRequest(url, init, bearer) {
53907
54043
  const headers = new Headers(init.headers);
53908
54044
  if (!headers.has("Authorization")) {
@@ -53916,7 +54052,7 @@ async function sendRequest(url, init, bearer) {
53916
54052
  try {
53917
54053
  return await fetch(url, { ...init, headers });
53918
54054
  } catch (err) {
53919
- throw new ApiError(`Network error: ${err.message}`);
54055
+ throw new NetworkApiError(`Network error: ${err.message}`, isDefinitelyUnsentNetworkError(err));
53920
54056
  }
53921
54057
  }
53922
54058
  async function sendWithAuthRetry(session, send) {
@@ -53945,6 +54081,160 @@ async function request(pathname, init = {}) {
53945
54081
  }
53946
54082
  return body;
53947
54083
  }
54084
+ function masApiErrorMessage(body, status) {
54085
+ if (body && typeof body === "object") {
54086
+ const obj = body;
54087
+ if (typeof obj.error === "string" && obj.error.trim() && typeof obj.message === "string" && obj.message.trim()) {
54088
+ const error = obj.error.trim();
54089
+ const message = obj.message.trim();
54090
+ return error === message ? message : `${error}: ${message}`;
54091
+ }
54092
+ for (const key2 of ["detail", "error", "message"]) {
54093
+ const value = obj[key2];
54094
+ if (!value || typeof value !== "object" || Array.isArray(value))
54095
+ continue;
54096
+ const nested = value;
54097
+ for (const nestedKey of ["message", "detail", "error"]) {
54098
+ const message = nested[nestedKey];
54099
+ if (typeof message === "string" && message.trim()) {
54100
+ return message.trim();
54101
+ }
54102
+ }
54103
+ }
54104
+ }
54105
+ return apiErrorMessage(body, status);
54106
+ }
54107
+ function masRetryDelayMs(retryAfterHeader, fallbackMs) {
54108
+ const normalized = retryAfterHeader?.trim();
54109
+ if (!normalized)
54110
+ return fallbackMs;
54111
+ const retryAfterSeconds = Number(normalized);
54112
+ if (!Number.isFinite(retryAfterSeconds) || retryAfterSeconds < 0) {
54113
+ return fallbackMs;
54114
+ }
54115
+ return Math.min(MAS_MAX_RETRY_DELAY_MS, Math.max(MAS_MIN_RETRY_DELAY_MS, retryAfterSeconds * 1000));
54116
+ }
54117
+ function parseMasTaskCreateResponse(body) {
54118
+ if (!body || typeof body !== "object") {
54119
+ throw new ApiError("Task creation may have succeeded, but MAS returned an invalid response. Check your tasks before running this command again.", undefined, body);
54120
+ }
54121
+ const task = body;
54122
+ if (typeof task.id !== "string" || !task.id.trim() || typeof task.agent_id !== "string" || !task.agent_id.trim() || typeof task.status !== "string" || !task.status.trim()) {
54123
+ throw new ApiError("Task creation may have succeeded, but MAS returned an invalid response. Check your tasks before running this command again.", undefined, body);
54124
+ }
54125
+ return {
54126
+ id: task.id,
54127
+ agent_id: task.agent_id,
54128
+ status: task.status
54129
+ };
54130
+ }
54131
+ async function masRequest(pathname, init) {
54132
+ const credential = await resolveMasCredential();
54133
+ let currentSession = credential.session;
54134
+ let ambiguousNetworkRetriesRemaining = 1;
54135
+ let requestMayHaveSucceeded = false;
54136
+ let transientHttpRetriesRemaining = 1;
54137
+ let recoveryDeadline = null;
54138
+ let recoveryTaskId = null;
54139
+ const recoveryRequestTimeoutMs = () => {
54140
+ if (recoveryDeadline === null)
54141
+ return MAS_REQUEST_TIMEOUT_MS;
54142
+ const remainingMs = recoveryDeadline - Date.now();
54143
+ if (remainingMs <= 0) {
54144
+ throw new TaskRecoveryDeadlineError(recoveryTaskId ? `Task ${recoveryTaskId} is still being processed. Check its status before starting another task.` : "Task creation may still be processing. Check your tasks before running this command again.");
54145
+ }
54146
+ return Math.min(MAS_REQUEST_TIMEOUT_MS, remainingMs);
54147
+ };
54148
+ while (true) {
54149
+ const retrySession = credential.source === "session" ? currentSession : null;
54150
+ let res;
54151
+ try {
54152
+ res = await sendWithAuthRetry(retrySession, async (refreshed) => {
54153
+ if (refreshed)
54154
+ currentSession = refreshed;
54155
+ while (true) {
54156
+ const signal = AbortSignal.timeout(recoveryRequestTimeoutMs());
54157
+ try {
54158
+ return await sendRequest(`${masApiBase(currentSession)}${pathname}`, {
54159
+ ...init,
54160
+ signal
54161
+ }, currentSession?.access_token ?? credential.bearer);
54162
+ } catch (error) {
54163
+ if (error instanceof NetworkApiError && error.definitelyUnsent) {
54164
+ throw error;
54165
+ }
54166
+ if (ambiguousNetworkRetriesRemaining === 0)
54167
+ throw error;
54168
+ requestMayHaveSucceeded = true;
54169
+ ambiguousNetworkRetriesRemaining -= 1;
54170
+ }
54171
+ }
54172
+ });
54173
+ } catch (error) {
54174
+ if (error instanceof TaskRecoveryDeadlineError)
54175
+ throw error;
54176
+ if (recoveryTaskId || recoveryDeadline !== null || requestMayHaveSucceeded) {
54177
+ throw new ApiError(recoveryTaskId ? `Task ${recoveryTaskId} may still be processing. Check its status before starting another task. ${error.message}` : `Task creation may still be processing. Check your tasks before running this command again. ${error.message}`);
54178
+ }
54179
+ throw error;
54180
+ }
54181
+ let text2;
54182
+ try {
54183
+ text2 = await res.text();
54184
+ } catch (error) {
54185
+ if (ambiguousNetworkRetriesRemaining > 0) {
54186
+ requestMayHaveSucceeded = true;
54187
+ ambiguousNetworkRetriesRemaining -= 1;
54188
+ continue;
54189
+ }
54190
+ throw new ApiError(recoveryTaskId ? `Task ${recoveryTaskId} may still be processing. Check its status before starting another task. ${error.message}` : recoveryDeadline !== null || requestMayHaveSucceeded ? `Task creation may still be processing. Check your tasks before running this command again. ${error.message}` : `Network error while reading response: ${error.message}`);
54191
+ }
54192
+ let body = text2;
54193
+ try {
54194
+ body = text2 ? JSON.parse(text2) : null;
54195
+ } catch {}
54196
+ const detail = body && typeof body === "object" ? body.detail : null;
54197
+ const detailObject = detail && typeof detail === "object" ? detail : null;
54198
+ const code = detailObject?.code;
54199
+ if (res.status === 409 && code === "idempotency_request_in_progress") {
54200
+ if (typeof detailObject?.task_id === "string") {
54201
+ recoveryTaskId = detailObject.task_id;
54202
+ }
54203
+ recoveryDeadline ??= Date.now() + MAS_IN_PROGRESS_MAX_WAIT_MS;
54204
+ const delayMs = masRetryDelayMs(res.headers.get("Retry-After"), 1000);
54205
+ if (Date.now() + delayMs >= recoveryDeadline) {
54206
+ throw new ApiError(recoveryTaskId ? `Task ${recoveryTaskId} is still being processed. Check its status before starting another task.` : masApiErrorMessage(body, res.status), res.status, body);
54207
+ }
54208
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
54209
+ continue;
54210
+ }
54211
+ if (res.status >= 500 && transientHttpRetriesRemaining > 0) {
54212
+ transientHttpRetriesRemaining -= 1;
54213
+ requestMayHaveSucceeded = true;
54214
+ const delayMs = masRetryDelayMs(res.headers.get("Retry-After"), 250);
54215
+ if (recoveryDeadline !== null && Date.now() + delayMs >= recoveryDeadline) {
54216
+ throw new TaskRecoveryDeadlineError(recoveryTaskId ? `Task ${recoveryTaskId} is still being processed. Check its status before starting another task.` : "Task creation may still be processing. Check your tasks before running this command again.");
54217
+ }
54218
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
54219
+ continue;
54220
+ }
54221
+ if (!res.ok) {
54222
+ const message = masApiErrorMessage(body, res.status);
54223
+ throw new ApiError(res.status >= 500 ? `${message} Task creation may still be processing; check your tasks before running this command again.` : message, res.status, body);
54224
+ }
54225
+ return body;
54226
+ }
54227
+ }
54228
+ var masApi = {
54229
+ async createTask(input, options) {
54230
+ const body = await masRequest("/tasks", {
54231
+ method: "POST",
54232
+ headers: { "Idempotency-Key": options.idempotencyKey },
54233
+ body: JSON.stringify(input)
54234
+ });
54235
+ return parseMasTaskCreateResponse(body);
54236
+ }
54237
+ };
53948
54238
  var api = {
53949
54239
  listOrgs() {
53950
54240
  return request("/orgs");
@@ -53958,6 +54248,22 @@ var api = {
53958
54248
  body: JSON.stringify({ name })
53959
54249
  });
53960
54250
  },
54251
+ async listAgents(orgId, teamId) {
54252
+ const path58 = `/orgs/${encodeURIComponent(orgId)}/teams/${encodeURIComponent(teamId)}/agents`;
54253
+ let body;
54254
+ try {
54255
+ body = await request(path58);
54256
+ } catch (err) {
54257
+ if (err instanceof ApiError && err.status === 404) {
54258
+ throw new ApiError("This control plane does not support listing agents yet. Update the server, or use the web app to find the agent id.", 404, err.body);
54259
+ }
54260
+ throw err;
54261
+ }
54262
+ if (!Array.isArray(body)) {
54263
+ throw new ApiError(`Unexpected response listing agents: expected an array from ${path58}.`, undefined, body);
54264
+ }
54265
+ return body;
54266
+ },
53961
54267
  createAgent(input) {
53962
54268
  if (usesLegacyControlPlane() && (input.machine_kind !== undefined || input.default_model !== undefined)) {
53963
54269
  return Promise.reject(legacyAgentConfigError());
@@ -54059,64 +54365,6 @@ function proxyBaseUrl(session) {
54059
54365
  return DEFAULT_PROXY_BASE.replace(/\/+$/, "");
54060
54366
  }
54061
54367
 
54062
- // src/core/token.ts
54063
- import path57 from "node:path";
54064
- import fs47 from "node:fs";
54065
- var TOKEN_FILE = path57.join(BRAINBASE_HOME, "token.json");
54066
- var TOKEN_PREFIX = "bbpat_";
54067
- var TOKEN_PREFIX_LEN = 14;
54068
- function tokenPrefix(token) {
54069
- if (!token.startsWith(TOKEN_PREFIX)) {
54070
- throw new Error(`not a brainbase PAT: missing ${TOKEN_PREFIX} prefix`);
54071
- }
54072
- return token.slice(0, TOKEN_PREFIX_LEN);
54073
- }
54074
- function isValidTokenFormat(token) {
54075
- if (typeof token !== "string")
54076
- return false;
54077
- if (!token.startsWith(TOKEN_PREFIX))
54078
- return false;
54079
- return /^bbpat_[A-Za-z0-9]{20,}$/.test(token);
54080
- }
54081
- var StoredTokenSchema = exports_external.object({
54082
- schemaVersion: exports_external.literal(1),
54083
- token: exports_external.string(),
54084
- prefix: exports_external.string(),
54085
- name: exports_external.string().optional(),
54086
- createdAt: exports_external.string()
54087
- });
54088
- function readToken() {
54089
- if (!exists(TOKEN_FILE))
54090
- return null;
54091
- try {
54092
- return StoredTokenSchema.parse(readJson(TOKEN_FILE));
54093
- } catch {
54094
- return null;
54095
- }
54096
- }
54097
- function writeToken(token, name) {
54098
- if (!isValidTokenFormat(token)) {
54099
- throw new Error("refusing to store token: invalid format");
54100
- }
54101
- ensureDir(BRAINBASE_HOME);
54102
- const stored = {
54103
- schemaVersion: 1,
54104
- token,
54105
- prefix: tokenPrefix(token),
54106
- name,
54107
- createdAt: new Date().toISOString()
54108
- };
54109
- writeJson(TOKEN_FILE, stored);
54110
- try {
54111
- fs47.chmodSync(TOKEN_FILE, 384);
54112
- } catch {}
54113
- return stored;
54114
- }
54115
- function clearToken() {
54116
- if (exists(TOKEN_FILE))
54117
- fs47.rmSync(TOKEN_FILE);
54118
- }
54119
-
54120
54368
  // src/core/registry-client.ts
54121
54369
  var DEFAULT_BASE = "https://api.v1.brainbaselabs.com";
54122
54370
  function baseUrl(session) {
@@ -62795,7 +63043,7 @@ function runHarnessInstall(harnessId, components, opts, agentName) {
62795
63043
  }
62796
63044
 
62797
63045
  // src/cli/agent.ts
62798
- var import_picocolors32 = __toESM(require_picocolors(), 1);
63046
+ var import_picocolors34 = __toESM(require_picocolors(), 1);
62799
63047
 
62800
63048
  // src/cli/agent-pull.ts
62801
63049
  import { spawn as spawn2 } from "node:child_process";
@@ -65104,7 +65352,7 @@ function formatExport(shell, key2, value) {
65104
65352
 
65105
65353
  // src/cli/agent-create.ts
65106
65354
  import path81 from "node:path";
65107
- var import_picocolors31 = __toESM(require_picocolors(), 1);
65355
+ var import_picocolors32 = __toESM(require_picocolors(), 1);
65108
65356
 
65109
65357
  // src/ui/box.ts
65110
65358
  var import_picocolors30 = __toESM(require_picocolors(), 1);
@@ -65130,110 +65378,189 @@ function tip(text2, indent = 2) {
65130
65378
  return " ".repeat(indent) + import_picocolors30.default.dim("›") + " " + import_picocolors30.default.dim(text2);
65131
65379
  }
65132
65380
 
65133
- // src/cli/agent-create.ts
65134
- async function runAgentCreate(cwd2, args) {
65135
- banner("agent create claim a brainbase.agent.yaml and link this folder");
65136
- let manifest = await loadOrScaffoldManifest(cwd2, args);
65137
- if (!manifest)
65138
- return;
65139
- if (manifest.id) {
65140
- f2.warn(`This folder already belongs to an agent — ${import_picocolors31.default.bold(manifest.agent.name)} (${import_picocolors31.default.dim(manifest.id)}).`);
65141
- f2.info(`If you want to detach it, run ${import_picocolors31.default.cyan("brainbase unlink")} first; or move to a different directory.`);
65142
- return;
65381
+ // src/core/org-team.ts
65382
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
65383
+ class OrgTeamError extends Error {
65384
+ constructor(message) {
65385
+ super(message);
65386
+ this.name = "OrgTeamError";
65143
65387
  }
65144
- const orgsSpinner = de();
65145
- orgsSpinner.start("Loading your organizations…");
65146
- let orgs;
65388
+ }
65389
+ async function loading(announce, message, done, fetch2) {
65390
+ if (!announce)
65391
+ return await fetch2();
65392
+ const sp = de();
65393
+ sp.start(message);
65147
65394
  try {
65148
- orgs = await api.listOrgs();
65395
+ const value = await fetch2();
65396
+ sp.stop(done(value));
65397
+ return value;
65149
65398
  } catch (err) {
65150
- orgsSpinner.stop("Failed.");
65151
- handleApiError4(err);
65152
- return;
65399
+ sp.stop("Failed.");
65400
+ throw err;
65401
+ }
65402
+ }
65403
+ async function chooseOne(opts) {
65404
+ if (!opts.allowPrompt) {
65405
+ throw new NonInteractiveError(`${opts.message} cannot be answered while emitting JSON. ${opts.flagHint}`);
65153
65406
  }
65154
- orgsSpinner.stop(`Found ${orgs.length} organization${orgs.length === 1 ? "" : "s"}.`);
65407
+ return await select({
65408
+ message: opts.message,
65409
+ options: opts.options,
65410
+ flagHint: opts.flagHint
65411
+ });
65412
+ }
65413
+ async function resolveOrg(orgRef, opts = {}) {
65414
+ if (orgRef === "") {
65415
+ throw new OrgTeamError("--org needs a value: an organization id or slug.");
65416
+ }
65417
+ const orgs = await loading(opts.announce, "Loading your organizations…", (found) => `Found ${found.length} organization${found.length === 1 ? "" : "s"}.`, () => api.listOrgs());
65155
65418
  if (orgs.length === 0) {
65156
- f2.warn("You are not in any organizations yet.");
65157
- $e("Create one on the web app first, then come back.");
65158
- return;
65419
+ throw new OrgTeamError("You are not a member of any organization. Create one in the web app first.");
65159
65420
  }
65160
- let org;
65161
- if (args.orgId) {
65162
- const found = orgs.find((o2) => o2.id === args.orgId || o2.slug === args.orgId);
65421
+ if (orgRef) {
65422
+ const found = orgs.find((o2) => o2.id === orgRef || o2.slug === orgRef);
65163
65423
  if (!found) {
65164
- f2.error(`Org ${args.orgId} not found or you're not a member.`);
65165
- return;
65424
+ throw new OrgTeamError(`Org ${orgRef} not found, or you're not a member of it.`);
65166
65425
  }
65167
- org = found;
65168
- } else if (orgs.length === 1) {
65169
- org = orgs[0];
65170
- f2.info(`Using organization ${import_picocolors31.default.bold(org.name)}.`);
65171
- } else {
65172
- const orgId = await select({
65173
- message: "Pick an organization",
65174
- options: orgs.map((o2) => ({ value: o2.id, label: o2.name, hint: o2.role })),
65175
- flagHint: "Pass --org <id-or-slug> to choose non-interactively."
65176
- });
65177
- org = orgs.find((o2) => o2.id === orgId);
65426
+ return found;
65178
65427
  }
65179
- const teamsSpinner = de();
65180
- teamsSpinner.start(`Loading teams in ${org.name}…`);
65181
- let teams;
65182
- try {
65183
- teams = await api.listTeams(org.id);
65184
- } catch (err) {
65185
- teamsSpinner.stop("Failed.");
65186
- handleApiError4(err);
65187
- return;
65428
+ if (orgs.length === 1) {
65429
+ const org = orgs[0];
65430
+ if (opts.announce)
65431
+ f2.info(`Using organization ${import_picocolors31.default.bold(org.name)}.`);
65432
+ return org;
65188
65433
  }
65189
- teamsSpinner.stop(`Found ${teams.length} team${teams.length === 1 ? "" : "s"}.`);
65190
- let team;
65434
+ const orgId = await chooseOne({
65435
+ message: "Which organization?",
65436
+ options: orgs.map((o2) => ({ value: o2.id, label: o2.name, hint: o2.role })),
65437
+ flagHint: "Pass --org <id-or-slug>.",
65438
+ allowPrompt: opts.allowPrompt !== false
65439
+ });
65440
+ return orgs.find((o2) => o2.id === orgId);
65441
+ }
65442
+ function canOfferTeamCreation(opts) {
65443
+ return !!opts.offerCreateTeam && opts.allowPrompt !== false && opts.interactive;
65444
+ }
65445
+ function shouldAutoPickLoneTeam(opts) {
65446
+ return opts.teamCount === 1 && !opts.canCreate;
65447
+ }
65448
+ async function resolveOrgAndTeam(args) {
65449
+ if (args.orgId === "") {
65450
+ throw new OrgTeamError("--org needs a value: an organization id or slug.");
65451
+ }
65452
+ if (args.teamId === "") {
65453
+ throw new OrgTeamError("--team needs a value: a team id.");
65454
+ }
65455
+ if (args.teamId && !args.orgId) {
65456
+ return await findTeamAcrossOrgs(args.teamId);
65457
+ }
65458
+ const org = await resolveOrg(args.orgId, {
65459
+ allowPrompt: args.allowPrompt,
65460
+ announce: args.announce
65461
+ });
65462
+ const teams = await loading(args.announce, `Loading teams in ${org.name}…`, (found) => `Found ${found.length} team${found.length === 1 ? "" : "s"}.`, () => api.listTeams(org.id));
65191
65463
  if (args.teamId) {
65192
65464
  const found = teams.find((t) => t.id === args.teamId);
65193
65465
  if (!found) {
65194
- f2.error(`Team ${args.teamId} not found in this org.`);
65195
- return;
65466
+ throw new OrgTeamError(`Team ${args.teamId} not found in ${org.name}.`);
65196
65467
  }
65197
- team = found;
65198
- } else if (!isInteractive()) {
65199
- if (teams.length === 1) {
65200
- team = teams[0];
65468
+ return { org, team: found };
65469
+ }
65470
+ const canCreate = canOfferTeamCreation({
65471
+ offerCreateTeam: args.offerCreateTeam,
65472
+ allowPrompt: args.allowPrompt,
65473
+ interactive: isInteractive()
65474
+ });
65475
+ if (teams.length === 0 && !canCreate) {
65476
+ throw new OrgTeamError(`${org.name} has no teams yet. Create one in the web app first.`);
65477
+ }
65478
+ if (shouldAutoPickLoneTeam({ teamCount: teams.length, canCreate })) {
65479
+ const team = teams[0];
65480
+ if (args.announce)
65201
65481
  f2.info(`Using team ${import_picocolors31.default.bold(team.name)}.`);
65202
- } else if (teams.length === 0) {
65203
- throw new NonInteractiveError(`No teams in ${org.name} yet — create one in the web app, then re-run.`);
65204
- } else {
65205
- throw new NonInteractiveError(`Multiple teams in ${org.name}. Pass --team <id> to choose non-interactively.`);
65206
- }
65207
- } else {
65208
- const teamOptions = [
65209
- ...teams.map((t) => ({ value: t.id, label: t.name, hint: t.role })),
65210
- { value: "__new__", label: "+ Create a new team" }
65211
- ];
65212
- const teamChoice = await ie({
65213
- message: "Pick a team (or create one)",
65214
- options: teamOptions
65482
+ return { org, team };
65483
+ }
65484
+ if (!canCreate) {
65485
+ const teamId = await chooseOne({
65486
+ message: "Which team?",
65487
+ options: teams.map((t) => ({ value: t.id, label: t.name, hint: t.role })),
65488
+ flagHint: "Pass --team <id>.",
65489
+ allowPrompt: args.allowPrompt !== false
65215
65490
  });
65216
- const picked = ensureNotCancelled(teamChoice);
65217
- if (picked === "__new__") {
65218
- const name = await te({
65219
- message: "New team name",
65220
- validate: (v3) => !v3?.trim() ? "Required" : undefined
65221
- });
65222
- const teamName = ensureNotCancelled(name);
65223
- const createSpinner2 = de();
65224
- createSpinner2.start("Creating team…");
65225
- try {
65226
- team = await api.createTeam(org.id, teamName.trim());
65227
- createSpinner2.stop(`Created team ${import_picocolors31.default.bold(team.name)}.`);
65228
- } catch (err) {
65229
- createSpinner2.stop("Failed.");
65230
- handleApiError4(err);
65231
- return;
65232
- }
65491
+ return { org, team: teams.find((t) => t.id === teamId) };
65492
+ }
65493
+ return { org, team: await pickOrCreateTeam(org, teams) };
65494
+ }
65495
+ var CREATE_TEAM = "__new__";
65496
+ async function pickOrCreateTeam(org, teams) {
65497
+ const picked = ensureNotCancelled(await ie({
65498
+ message: "Pick a team (or create one)",
65499
+ options: [
65500
+ ...teams.map((t) => ({ value: t.id, label: t.name, hint: t.role })),
65501
+ { value: CREATE_TEAM, label: "+ Create a new team" }
65502
+ ]
65503
+ }));
65504
+ if (picked !== CREATE_TEAM)
65505
+ return teams.find((t) => t.id === picked);
65506
+ const name = ensureNotCancelled(await te({
65507
+ message: "New team name",
65508
+ validate: (v3) => !v3?.trim() ? "Required" : undefined
65509
+ }));
65510
+ return await loading(true, "Creating team…", (created) => `Created team ${import_picocolors31.default.bold(created.name)}.`, () => api.createTeam(org.id, name.trim()));
65511
+ }
65512
+ async function findTeamAcrossOrgs(teamId) {
65513
+ const orgs = await api.listOrgs();
65514
+ if (orgs.length === 0) {
65515
+ throw new OrgTeamError("You are not a member of any organization.");
65516
+ }
65517
+ const { resolved, failures } = await listTeamsPerOrg(orgs);
65518
+ for (const { org, teams } of resolved) {
65519
+ const team = teams.find((t) => t.id === teamId);
65520
+ if (team)
65521
+ return { org, team };
65522
+ }
65523
+ if (failures.length > 0)
65524
+ throw failures[0].error;
65525
+ throw new OrgTeamError(`Team ${teamId} not found in any of your organizations. Run \`brainbase team list\` to see the ids you can use.`);
65526
+ }
65527
+ async function listTeamsPerOrg(orgs) {
65528
+ const settled = await Promise.allSettled(orgs.map((org) => api.listTeams(org.id)));
65529
+ const entries = [];
65530
+ const resolved = [];
65531
+ const failures = [];
65532
+ settled.forEach((outcome, index) => {
65533
+ const org = orgs[index];
65534
+ if (outcome.status === "fulfilled") {
65535
+ const entry = { org, teams: outcome.value };
65536
+ entries.push(entry);
65537
+ resolved.push(entry);
65233
65538
  } else {
65234
- team = teams.find((t) => t.id === picked);
65539
+ const error = outcome.reason;
65540
+ entries.push({ org, teams: [], error: error.message });
65541
+ failures.push({ org, error });
65235
65542
  }
65543
+ });
65544
+ return { entries, resolved, failures };
65545
+ }
65546
+
65547
+ // src/cli/agent-create.ts
65548
+ async function runAgentCreate(cwd2, args) {
65549
+ banner("agent create — claim a brainbase.agent.yaml and link this folder");
65550
+ let manifest = await loadOrScaffoldManifest(cwd2, args);
65551
+ if (!manifest)
65552
+ return;
65553
+ if (manifest.id) {
65554
+ f2.warn(`This folder already belongs to an agent — ${import_picocolors32.default.bold(manifest.agent.name)} (${import_picocolors32.default.dim(manifest.id)}).`);
65555
+ f2.info(`If you want to detach it, run ${import_picocolors32.default.cyan("brainbase unlink")} first; or move to a different directory.`);
65556
+ return;
65236
65557
  }
65558
+ const { org, team } = await resolveOrgAndTeam({
65559
+ orgId: args.orgId,
65560
+ teamId: args.teamId,
65561
+ announce: true,
65562
+ offerCreateTeam: true
65563
+ });
65237
65564
  const harness = normalizeHarnessId(args.harness ?? manifest.harness ?? await pickHarness2(cwd2));
65238
65565
  let agentName = args.name?.trim() || manifest.agent.name.trim();
65239
65566
  if (!agentName) {
@@ -65256,11 +65583,11 @@ async function runAgentCreate(cwd2, args) {
65256
65583
  }
65257
65584
  if (!autoProceed(args.yes)) {
65258
65585
  le([
65259
- `${import_picocolors31.default.dim("org")} ${import_picocolors31.default.bold(org.name)}`,
65260
- `${import_picocolors31.default.dim("team")} ${import_picocolors31.default.bold(team.name)}`,
65261
- `${import_picocolors31.default.dim("harness")} ${import_picocolors31.default.bold(harness)}`,
65262
- `${import_picocolors31.default.dim("agent")} ${import_picocolors31.default.bold(agentName)}`,
65263
- ...tagline ? [`${import_picocolors31.default.dim("tagline")} ${tagline}`] : []
65586
+ `${import_picocolors32.default.dim("org")} ${import_picocolors32.default.bold(org.name)}`,
65587
+ `${import_picocolors32.default.dim("team")} ${import_picocolors32.default.bold(team.name)}`,
65588
+ `${import_picocolors32.default.dim("harness")} ${import_picocolors32.default.bold(harness)}`,
65589
+ `${import_picocolors32.default.dim("agent")} ${import_picocolors32.default.bold(agentName)}`,
65590
+ ...tagline ? [`${import_picocolors32.default.dim("tagline")} ${tagline}`] : []
65264
65591
  ].join(`
65265
65592
  `), "Will create");
65266
65593
  const confirmed = await se({ message: "Create this agent?", initialValue: true });
@@ -65274,7 +65601,7 @@ async function runAgentCreate(cwd2, args) {
65274
65601
  const body = resolveEntrypoint(cwd2, manifest);
65275
65602
  if (body === null) {
65276
65603
  if (manifest.entrypoint.file) {
65277
- f2.error(`Entrypoint file ${import_picocolors31.default.bold(manifest.entrypoint.file)} not found.`);
65604
+ f2.error(`Entrypoint file ${import_picocolors32.default.bold(manifest.entrypoint.file)} not found.`);
65278
65605
  } else {
65279
65606
  f2.error("Entrypoint block is empty.");
65280
65607
  }
@@ -65296,10 +65623,11 @@ async function runAgentCreate(cwd2, args) {
65296
65623
  ...manifest.machine_kind !== undefined ? { machine_kind: manifest.machine_kind } : {},
65297
65624
  ...manifest.default_model !== undefined ? { default_model: manifest.default_model } : {}
65298
65625
  });
65299
- createSpinner.stop(`Created ${import_picocolors31.default.bold(agent.name)}.`);
65626
+ createSpinner.stop(`Created ${import_picocolors32.default.bold(agent.name)}.`);
65300
65627
  } catch (err) {
65301
65628
  createSpinner.stop("Failed.");
65302
65629
  handleApiError4(err);
65630
+ process.exitCode = 1;
65303
65631
  return;
65304
65632
  }
65305
65633
  const machineConfigMissing = manifest.machine_kind !== undefined && agent.machine_kind !== manifest.machine_kind;
@@ -65312,15 +65640,15 @@ async function runAgentCreate(cwd2, args) {
65312
65640
  ...machineConfigMissing ? ["machine_kind"] : [],
65313
65641
  ...modelConfigMissing ? ["default_model"] : []
65314
65642
  ];
65315
- f2.error(`Agent ${import_picocolors31.default.bold(agent.id)} was created, but this control plane did not apply ${fields.join(" / ")}.`);
65643
+ f2.error(`Agent ${import_picocolors32.default.bold(agent.id)} was created, but this control plane did not apply ${fields.join(" / ")}.`);
65316
65644
  if (machineConfigMissing) {
65317
65645
  if (agent.machine_kind) {
65318
- f2.info(`machine_kind is immutable. Run ${import_picocolors31.default.cyan("brainbase agent pull --force")} to accept ${agent.machine_kind}, or delete this agent and recreate it after upgrading the control plane.`);
65646
+ f2.info(`machine_kind is immutable. Run ${import_picocolors32.default.cyan("brainbase agent pull --force")} to accept ${agent.machine_kind}, or delete this agent and recreate it after upgrading the control plane.`);
65319
65647
  } else {
65320
65648
  f2.info("machine_kind is immutable and this server did not report the provider it created. Upgrade the control plane, delete this agent, and recreate it.");
65321
65649
  }
65322
65650
  } else {
65323
- f2.info(`Upgrade the control plane, then run ${import_picocolors31.default.cyan("brainbase agent push")} to apply default_model.`);
65651
+ f2.info(`Upgrade the control plane, then run ${import_picocolors32.default.cyan("brainbase agent push")} to apply default_model.`);
65324
65652
  }
65325
65653
  process.exitCode = 1;
65326
65654
  return;
@@ -65334,12 +65662,12 @@ async function runAgentCreate(cwd2, args) {
65334
65662
  wantsTracking = true;
65335
65663
  } else if (!isInteractive()) {
65336
65664
  wantsTracking = false;
65337
- f2.info(`Tracking left off (non-interactive). Re-run with ${import_picocolors31.default.cyan("--track")} to route ${harness} LLM traffic through brainbase.`);
65665
+ f2.info(`Tracking left off (non-interactive). Re-run with ${import_picocolors32.default.cyan("--track")} to route ${harness} LLM traffic through brainbase.`);
65338
65666
  } else if (args.yes) {
65339
65667
  wantsTracking = true;
65340
65668
  } else {
65341
65669
  const ans = await se({
65342
- message: `Track ${harness} conversations on the brainbase platform? ${import_picocolors31.default.dim("(routes LLM calls through brainbase so they appear under this agent)")}`,
65670
+ message: `Track ${harness} conversations on the brainbase platform? ${import_picocolors32.default.dim("(routes LLM calls through brainbase so they appear under this agent)")}`,
65343
65671
  initialValue: true
65344
65672
  });
65345
65673
  wantsTracking = ensureNotCancelled(ans);
@@ -65399,7 +65727,7 @@ async function runAgentCreate(cwd2, args) {
65399
65727
  if (hasContent) {
65400
65728
  const outgoing = await buildOutgoingComponents(cwd2, manifest, null);
65401
65729
  if (outgoing === null) {
65402
- f2.warn(`Agent created, but local content wasn't uploaded. Fix the issue above and run ${import_picocolors31.default.cyan("brainbase agent push")}.`);
65730
+ f2.warn(`Agent created, but local content wasn't uploaded. Fix the issue above and run ${import_picocolors32.default.cyan("brainbase agent push")}.`);
65403
65731
  } else if (outgoing.length > 0) {
65404
65732
  const pushSpinner = de();
65405
65733
  pushSpinner.start("Pushing local content…");
@@ -65413,9 +65741,9 @@ async function runAgentCreate(cwd2, args) {
65413
65741
  } catch (err) {
65414
65742
  pushSpinner.stop("Failed.");
65415
65743
  if (err instanceof ApiError) {
65416
- f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors31.default.cyan("brainbase agent push")} to retry.`);
65744
+ f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors32.default.cyan("brainbase agent push")} to retry.`);
65417
65745
  } else {
65418
- f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors31.default.cyan("brainbase agent push")} to retry.`);
65746
+ f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors32.default.cyan("brainbase agent push")} to retry.`);
65419
65747
  }
65420
65748
  }
65421
65749
  }
@@ -65453,7 +65781,7 @@ async function runAgentCreate(cwd2, args) {
65453
65781
  }
65454
65782
  };
65455
65783
  writeSyncState(cwd2, state);
65456
- $e(`Created ${import_picocolors31.default.bold(agent.name)} and linked this folder.`);
65784
+ $e(`Created ${import_picocolors32.default.bold(agent.name)} and linked this folder.`);
65457
65785
  await showResultCard({
65458
65786
  title: "CREATED",
65459
65787
  tone: "ok",
@@ -65466,9 +65794,9 @@ async function runAgentCreate(cwd2, args) {
65466
65794
  });
65467
65795
  console.log();
65468
65796
  if (tracking && harness === "codex") {
65469
- console.log(tip(`Run ${import_picocolors31.default.cyan("codex")} once in this folder and approve trust ${import_picocolors31.default.dim("— Codex only loads project-scope config in trusted projects.")}`));
65797
+ console.log(tip(`Run ${import_picocolors32.default.cyan("codex")} once in this folder and approve trust ${import_picocolors32.default.dim("— Codex only loads project-scope config in trusted projects.")}`));
65470
65798
  }
65471
- console.log(tip(`brainbase agent unpack ${import_picocolors31.default.dim("— install harness files (skills/mcps) under .claude/, .codex/, …")}`));
65799
+ console.log(tip(`brainbase agent unpack ${import_picocolors32.default.dim("— install harness files (skills/mcps) under .claude/, .codex/, …")}`));
65472
65800
  console.log();
65473
65801
  }
65474
65802
  async function loadOrScaffoldManifest(cwd2, args) {
@@ -65480,13 +65808,13 @@ async function loadOrScaffoldManifest(cwd2, args) {
65480
65808
  return null;
65481
65809
  }
65482
65810
  }
65483
- f2.warn(`No ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} here.`);
65811
+ f2.warn(`No ${import_picocolors32.default.bold(AGENT_MANIFEST_FILE)} here.`);
65484
65812
  if (!args.yes) {
65485
65813
  if (!isInteractive()) {
65486
65814
  throw new NonInteractiveError(`No ${AGENT_MANIFEST_FILE} here. Create one first, or re-run with --yes to scaffold a minimal one.`);
65487
65815
  }
65488
65816
  const ans = await se({
65489
- message: `Scaffold a minimal ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} and continue?`,
65817
+ message: `Scaffold a minimal ${import_picocolors32.default.bold(AGENT_MANIFEST_FILE)} and continue?`,
65490
65818
  initialValue: true
65491
65819
  });
65492
65820
  if (!ensureNotCancelled(ans)) {
@@ -65507,7 +65835,7 @@ async function loadOrScaffoldManifest(cwd2, args) {
65507
65835
  };
65508
65836
  try {
65509
65837
  writeManifest(cwd2, scaffold);
65510
- f2.info(`Wrote ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)}.`);
65838
+ f2.info(`Wrote ${import_picocolors32.default.bold(AGENT_MANIFEST_FILE)}.`);
65511
65839
  } catch (err) {
65512
65840
  f2.error(`Failed to write manifest: ${err.message}`);
65513
65841
  return null;
@@ -65518,7 +65846,7 @@ async function pickHarness2(cwd2) {
65518
65846
  const detections = await detectHarnesses(cwd2);
65519
65847
  const detected = detections.filter((d3) => d3.detection.detected);
65520
65848
  if (detected.length === 1) {
65521
- f2.info(`Detected harness: ${import_picocolors31.default.bold(detected[0].adapter.displayName)}.`);
65849
+ f2.info(`Detected harness: ${import_picocolors32.default.bold(detected[0].adapter.displayName)}.`);
65522
65850
  return detected[0].adapter.id;
65523
65851
  }
65524
65852
  return await select({
@@ -65544,6 +65872,46 @@ function handleApiError4(err) {
65544
65872
  $e("Aborted.");
65545
65873
  }
65546
65874
 
65875
+ // src/cli/agent-list.ts
65876
+ var import_picocolors33 = __toESM(require_picocolors(), 1);
65877
+ async function runAgentList(args) {
65878
+ if (!args.json)
65879
+ banner("agent list — agents in this team");
65880
+ const { org, team } = await resolveOrgAndTeam({
65881
+ orgId: args.orgId,
65882
+ teamId: args.teamId,
65883
+ allowPrompt: !args.json,
65884
+ announce: !args.json
65885
+ });
65886
+ const agents = await api.listAgents(org.id, team.id);
65887
+ if (args.json) {
65888
+ console.log(JSON.stringify(agents, null, 2));
65889
+ return;
65890
+ }
65891
+ console.log(formatAgentList(agents, { orgName: org.name, teamName: team.name }));
65892
+ }
65893
+ function formatAgentList(agents, labels) {
65894
+ const lines = [""];
65895
+ if (agents.length === 0) {
65896
+ lines.push(` ${import_picocolors33.default.dim(`No agents in ${labels.orgName} → ${labels.teamName} yet.`)}`, "", ` ${import_picocolors33.default.dim("create one with")} ${import_picocolors33.default.cyan("brainbase agent create")}`, "");
65897
+ return lines.join(`
65898
+ `);
65899
+ }
65900
+ for (const agent of agents) {
65901
+ lines.push(` ${import_picocolors33.default.bold(agent.name)} ${import_picocolors33.default.dim(agent.slug)}`);
65902
+ if (agent.tagline)
65903
+ lines.push(` ${import_picocolors33.default.dim(agent.tagline)}`);
65904
+ const meta = [agent.harness, agent.machine_kind, agent.default_model].filter((value) => !!value).join(" · ");
65905
+ if (meta)
65906
+ lines.push(` ${import_picocolors33.default.dim(meta)}`);
65907
+ lines.push(` ${import_picocolors33.default.dim(agent.id)}`);
65908
+ lines.push("");
65909
+ }
65910
+ lines.push(` ${import_picocolors33.default.dim("link this folder to one with")} ${import_picocolors33.default.cyan("brainbase link --agent <id>")}`, "");
65911
+ return lines.join(`
65912
+ `);
65913
+ }
65914
+
65547
65915
  // src/cli/agent.ts
65548
65916
  async function runAgent(cwd2, sub, args, opts) {
65549
65917
  if (args.some((arg) => arg === "--help" || arg === "-h")) {
@@ -65563,6 +65931,13 @@ async function runAgent(cwd2, sub, args, opts) {
65563
65931
  track: opts.track
65564
65932
  });
65565
65933
  return;
65934
+ case "list":
65935
+ await runAgentList({
65936
+ orgId: opts.orgId,
65937
+ teamId: opts.teamId,
65938
+ json: opts.json
65939
+ });
65940
+ return;
65566
65941
  case "pull":
65567
65942
  await runAgentPull(cwd2, {
65568
65943
  yes: opts.yes,
@@ -65606,26 +65981,111 @@ async function runAgent(cwd2, sub, args, opts) {
65606
65981
  function printHelp() {
65607
65982
  const out = [];
65608
65983
  out.push("");
65609
- out.push(` ${import_picocolors32.default.bold("brainbase agent")} ${import_picocolors32.default.dim("<sub> [options]")}`);
65984
+ out.push(` ${import_picocolors34.default.bold("brainbase agent")} ${import_picocolors34.default.dim("<sub> [options]")}`);
65610
65985
  out.push("");
65611
- out.push(` ${import_picocolors32.default.cyan("create")} ${import_picocolors32.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
65612
- out.push(` ${import_picocolors32.default.cyan("pull")} ${import_picocolors32.default.dim("[<id>]")} ${import_picocolors32.default.dim("apply cloud changes into this folder pass <id> to switch (--force to override); --run-entrypoint to also execute the agent entrypoint")}`);
65613
- out.push(` ${import_picocolors32.default.cyan("push")} ${import_picocolors32.default.dim("send local changes to the cloudinstructions, playbooks, skills, MCPs, entrypoint (--force to overwrite cloud-side conflicts with local)")}`);
65614
- out.push(` ${import_picocolors32.default.cyan("unpack")} ${import_picocolors32.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
65615
- out.push(` ${import_picocolors32.default.cyan("status")} ${import_picocolors32.default.dim("show what would push and what would pull")}`);
65616
- out.push(` ${import_picocolors32.default.cyan("env")} ${import_picocolors32.default.dim('print export statements use with `eval "$(brainbase agent env)"`')}`);
65986
+ out.push(` ${import_picocolors34.default.cyan("list")} ${import_picocolors34.default.dim("show the agents in a team, with the ids `brainbase link` takes (--json for scripts)")}`);
65987
+ out.push(` ${import_picocolors34.default.cyan("create")} ${import_picocolors34.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
65988
+ out.push(` ${import_picocolors34.default.cyan("pull")} ${import_picocolors34.default.dim("[<id>]")} ${import_picocolors34.default.dim("apply cloud changes into this folderpass <id> to switch (--force to override); --run-entrypoint to also execute the agent entrypoint")}`);
65989
+ out.push(` ${import_picocolors34.default.cyan("push")} ${import_picocolors34.default.dim("send local changes to the cloud instructions, playbooks, skills, MCPs, entrypoint (--force to overwrite cloud-side conflicts with local)")}`);
65990
+ out.push(` ${import_picocolors34.default.cyan("unpack")} ${import_picocolors34.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
65991
+ out.push(` ${import_picocolors34.default.cyan("status")} ${import_picocolors34.default.dim("show what would push and what would pull")}`);
65992
+ out.push(` ${import_picocolors34.default.cyan("env")} ${import_picocolors34.default.dim('print export statements — use with `eval "$(brainbase agent env)"`')}`);
65993
+ out.push("");
65994
+ console.log(out.join(`
65995
+ `));
65996
+ }
65997
+
65998
+ // src/cli/team.ts
65999
+ var import_picocolors36 = __toESM(require_picocolors(), 1);
66000
+
66001
+ // src/cli/team-list.ts
66002
+ var import_picocolors35 = __toESM(require_picocolors(), 1);
66003
+ async function runTeamList(args) {
66004
+ if (!args.json)
66005
+ banner("team list — teams you can put agents in");
66006
+ const orgs = args.orgId !== undefined ? [await resolveOrg(args.orgId)] : await api.listOrgs();
66007
+ const { entries, resolved, failures } = await listTeamsPerOrg(orgs);
66008
+ if (resolved.length === 0 && failures.length > 0)
66009
+ throw failures[0].error;
66010
+ if (args.json) {
66011
+ for (const { org, error } of failures) {
66012
+ console.error(`Could not load teams in ${org.name}: ${error.message}`);
66013
+ }
66014
+ console.log(JSON.stringify(entries, null, 2));
66015
+ return;
66016
+ }
66017
+ console.log(formatTeamList(entries));
66018
+ }
66019
+ function formatTeamList(grouped) {
66020
+ const lines = [""];
66021
+ if (grouped.length === 0) {
66022
+ lines.push(` ${import_picocolors35.default.dim("You are not a member of any organization.")}`, "");
66023
+ return lines.join(`
66024
+ `);
66025
+ }
66026
+ const nameWidth = Math.max(...grouped.flatMap(({ teams }) => teams.map((t) => t.name.length)), 0);
66027
+ for (const { org, teams, error } of grouped) {
66028
+ const slug = org.slug ? ` ${import_picocolors35.default.dim(org.slug)}` : "";
66029
+ lines.push(` ${import_picocolors35.default.bold(org.name)}${slug}`);
66030
+ if (error) {
66031
+ lines.push(` ${import_picocolors35.default.red(`could not load teams: ${error}`)}`);
66032
+ } else if (teams.length === 0) {
66033
+ lines.push(` ${import_picocolors35.default.dim("no teams yet — create one in the web app")}`);
66034
+ }
66035
+ for (const team of teams) {
66036
+ lines.push(` ${team.name.padEnd(nameWidth)} ${import_picocolors35.default.dim(team.id)}`);
66037
+ }
66038
+ lines.push("");
66039
+ }
66040
+ lines.push(` ${import_picocolors35.default.dim("list a team’s agents with")} ${import_picocolors35.default.cyan("brainbase agent list --team <id>")}`, "");
66041
+ return lines.join(`
66042
+ `);
66043
+ }
66044
+
66045
+ // src/cli/team.ts
66046
+ async function runTeam(sub, args, opts) {
66047
+ if (args.some((arg) => arg === "--help" || arg === "-h")) {
66048
+ printHelp2();
66049
+ return;
66050
+ }
66051
+ switch (sub) {
66052
+ case "list":
66053
+ await runTeamList({ orgId: opts.orgId, json: opts.json });
66054
+ return;
66055
+ case undefined:
66056
+ case "help":
66057
+ case "-h":
66058
+ case "--help":
66059
+ printHelp2();
66060
+ return;
66061
+ default:
66062
+ console.error(`Unknown team subcommand: ${sub}
66063
+ `);
66064
+ printHelp2();
66065
+ process.exit(1);
66066
+ }
66067
+ }
66068
+ function printHelp2() {
66069
+ const out = [];
66070
+ out.push("");
66071
+ out.push(` ${import_picocolors36.default.bold("brainbase team")} ${import_picocolors36.default.dim("<sub> [options]")}`);
66072
+ out.push("");
66073
+ out.push(` ${import_picocolors36.default.cyan("list")} ${import_picocolors36.default.dim("show the teams you can create agents in, grouped by organization")}`);
66074
+ out.push("");
66075
+ out.push(` ${import_picocolors36.default.dim("--org <id-or-slug>")} ${import_picocolors36.default.dim("limit to one organization")}`);
66076
+ out.push(` ${import_picocolors36.default.dim("--json")} ${import_picocolors36.default.dim("machine-readable output")}`);
65617
66077
  out.push("");
65618
66078
  console.log(out.join(`
65619
66079
  `));
65620
66080
  }
65621
66081
 
65622
66082
  // src/cli/orchestration.ts
65623
- var import_picocolors39 = __toESM(require_picocolors(), 1);
66083
+ var import_picocolors43 = __toESM(require_picocolors(), 1);
65624
66084
 
65625
66085
  // src/cli/orchestration-pull.ts
65626
66086
  import path85 from "node:path";
65627
66087
  import fs76 from "node:fs";
65628
- var import_picocolors33 = __toESM(require_picocolors(), 1);
66088
+ var import_picocolors37 = __toESM(require_picocolors(), 1);
65629
66089
 
65630
66090
  // src/core/orchestration-manifest.ts
65631
66091
  import path82 from "node:path";
@@ -66128,8 +66588,8 @@ async function runOrchestrationPull(cwd2, args) {
66128
66588
  orchId = args.orchestrationId;
66129
66589
  } else {
66130
66590
  f2.warn("This folder is not linked to any orchestration.");
66131
- f2.info(`Run ${import_picocolors33.default.cyan("brainbase orchestration pull <id>")} with an orchestration id,
66132
- or ${import_picocolors33.default.cyan("brainbase orchestration list")} to find one.`);
66591
+ f2.info(`Run ${import_picocolors37.default.cyan("brainbase orchestration pull <id>")} with an orchestration id,
66592
+ or ${import_picocolors37.default.cyan("brainbase orchestration list")} to find one.`);
66133
66593
  return;
66134
66594
  }
66135
66595
  const sp = de();
@@ -66148,24 +66608,24 @@ async function runOrchestrationPull(cwd2, args) {
66148
66608
  const slugFor = (agentId) => slugByAgent.get(agentId) ?? agentId;
66149
66609
  const planLines = [];
66150
66610
  planLines.push("");
66151
- planLines.push(` ${import_picocolors33.default.bold(cloud.name)} ${import_picocolors33.default.dim(`(${cloud.id})`)}`);
66611
+ planLines.push(` ${import_picocolors37.default.bold(cloud.name)} ${import_picocolors37.default.dim(`(${cloud.id})`)}`);
66152
66612
  if (cloud.description)
66153
- planLines.push(` ${import_picocolors33.default.dim(cloud.description)}`);
66613
+ planLines.push(` ${import_picocolors37.default.dim(cloud.description)}`);
66154
66614
  planLines.push("");
66155
- planLines.push(` ${import_picocolors33.default.dim("members:")}`);
66615
+ planLines.push(` ${import_picocolors37.default.dim("members:")}`);
66156
66616
  for (const m3 of cloud.members) {
66157
66617
  const skipped = !m3.manifest;
66158
- const tail2 = skipped ? import_picocolors33.default.red(" (manifest unavailable — skipped)") : "";
66159
- planLines.push(` ${import_picocolors33.default.cyan("•")} ${import_picocolors33.default.bold(slugFor(m3.agent_id))} ${import_picocolors33.default.dim(`(${m3.name})`)}${tail2}`);
66618
+ const tail2 = skipped ? import_picocolors37.default.red(" (manifest unavailable — skipped)") : "";
66619
+ planLines.push(` ${import_picocolors37.default.cyan("•")} ${import_picocolors37.default.bold(slugFor(m3.agent_id))} ${import_picocolors37.default.dim(`(${m3.name})`)}${tail2}`);
66160
66620
  }
66161
66621
  if (cloud.edges.length) {
66162
66622
  planLines.push("");
66163
- planLines.push(` ${import_picocolors33.default.dim("edges:")}`);
66623
+ planLines.push(` ${import_picocolors37.default.dim("edges:")}`);
66164
66624
  for (const e2 of cloud.edges) {
66165
66625
  const from = slugFor(e2.from_agent_id);
66166
66626
  const to2 = slugFor(e2.to_agent_id);
66167
- const desc = e2.description ? ` ${import_picocolors33.default.dim("— " + e2.description)}` : "";
66168
- planLines.push(` ${import_picocolors33.default.cyan(from)} ${import_picocolors33.default.dim("→")} ${import_picocolors33.default.cyan(to2)}${desc}`);
66627
+ const desc = e2.description ? ` ${import_picocolors37.default.dim("— " + e2.description)}` : "";
66628
+ planLines.push(` ${import_picocolors37.default.cyan(from)} ${import_picocolors37.default.dim("→")} ${import_picocolors37.default.cyan(to2)}${desc}`);
66169
66629
  }
66170
66630
  }
66171
66631
  planLines.push("");
@@ -66174,7 +66634,7 @@ async function runOrchestrationPull(cwd2, args) {
66174
66634
  const isRefresh = !!existingLink;
66175
66635
  if (!autoProceed(args.yes) && !isRefresh) {
66176
66636
  const ok = await se({
66177
- message: `Pull into ${import_picocolors33.default.bold(cwd2)}?`,
66637
+ message: `Pull into ${import_picocolors37.default.bold(cwd2)}?`,
66178
66638
  initialValue: true
66179
66639
  });
66180
66640
  if (!ensureNotCancelled(ok)) {
@@ -66218,7 +66678,7 @@ async function runOrchestrationPull(cwd2, args) {
66218
66678
  scope: "project",
66219
66679
  pullSecrets: true
66220
66680
  });
66221
- memberSp.stop(`Installed ${import_picocolors33.default.bold(slug)} ${import_picocolors33.default.dim(`(${m3.manifest.components.length} components)`)}.`);
66681
+ memberSp.stop(`Installed ${import_picocolors37.default.bold(slug)} ${import_picocolors37.default.dim(`(${m3.manifest.components.length} components)`)}.`);
66222
66682
  installedMembers.push({
66223
66683
  agent_id: m3.agent_id,
66224
66684
  slug,
@@ -66279,7 +66739,7 @@ async function runOrchestrationPull(cwd2, args) {
66279
66739
  payload_schema: e2.payload_schema ?? {}
66280
66740
  }))
66281
66741
  });
66282
- $e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path85.basename(cwd2)}/ ${import_picocolors33.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
66742
+ $e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path85.basename(cwd2)}/ ${import_picocolors37.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
66283
66743
  }
66284
66744
  function handleApiError5(err) {
66285
66745
  if (err instanceof ApiError) {
@@ -66296,7 +66756,7 @@ function handleApiError5(err) {
66296
66756
  }
66297
66757
 
66298
66758
  // src/cli/orchestration-push.ts
66299
- var import_picocolors34 = __toESM(require_picocolors(), 1);
66759
+ var import_picocolors38 = __toESM(require_picocolors(), 1);
66300
66760
 
66301
66761
  // src/core/orchestration-outgoing.ts
66302
66762
  function buildOrchestrationGraphPayload(manifest, slugToAgentId) {
@@ -66366,12 +66826,12 @@ async function runOrchestrationPush(cwd2, args) {
66366
66826
  const link2 = readOrchLink(cwd2);
66367
66827
  if (!link2) {
66368
66828
  f2.warn("This folder is not linked to any orchestration.");
66369
- f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull <id>")} first.`);
66829
+ f2.info(`Run ${import_picocolors38.default.cyan("brainbase orchestration pull <id>")} first.`);
66370
66830
  return;
66371
66831
  }
66372
66832
  if (!hasOrchManifest(cwd2)) {
66373
- f2.warn(`No ${import_picocolors34.default.bold(ORCH_MANIFEST_FILE)} here.`);
66374
- f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the manifest before pushing.`);
66833
+ f2.warn(`No ${import_picocolors38.default.bold(ORCH_MANIFEST_FILE)} here.`);
66834
+ f2.info(`Run ${import_picocolors38.default.cyan("brainbase orchestration pull")} to materialise the manifest before pushing.`);
66375
66835
  return;
66376
66836
  }
66377
66837
  let manifest;
@@ -66395,7 +66855,7 @@ async function runOrchestrationPush(cwd2, args) {
66395
66855
  }
66396
66856
  if (missing.length) {
66397
66857
  f2.error(`Missing local checkouts for: ${missing.join(", ")}.`);
66398
- f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
66858
+ f2.info(`Run ${import_picocolors38.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
66399
66859
  return;
66400
66860
  }
66401
66861
  let graph;
@@ -66407,13 +66867,13 @@ async function runOrchestrationPush(cwd2, args) {
66407
66867
  return;
66408
66868
  }
66409
66869
  const plan = [""];
66410
- plan.push(` ${import_picocolors34.default.bold(link2.name)} ${import_picocolors34.default.dim(`(${link2.orchestration_id})`)}`);
66411
- plan.push(` ${import_picocolors34.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}, ${graph.triggers.length} trigger${graph.triggers.length === 1 ? "" : "s"}`)}`);
66870
+ plan.push(` ${import_picocolors38.default.bold(link2.name)} ${import_picocolors38.default.dim(`(${link2.orchestration_id})`)}`);
66871
+ plan.push(` ${import_picocolors38.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}, ${graph.triggers.length} trigger${graph.triggers.length === 1 ? "" : "s"}`)}`);
66412
66872
  plan.push("");
66413
66873
  if (!args.graphOnly) {
66414
- plan.push(` ${import_picocolors34.default.dim("per-member agent push:")}`);
66874
+ plan.push(` ${import_picocolors38.default.dim("per-member agent push:")}`);
66415
66875
  for (const m3 of manifest.members) {
66416
- plan.push(` ${import_picocolors34.default.cyan("•")} ${import_picocolors34.default.bold(m3.slug)}`);
66876
+ plan.push(` ${import_picocolors38.default.cyan("•")} ${import_picocolors38.default.bold(m3.slug)}`);
66417
66877
  }
66418
66878
  plan.push("");
66419
66879
  }
@@ -66433,7 +66893,7 @@ async function runOrchestrationPush(cwd2, args) {
66433
66893
  for (const m3 of manifest.members) {
66434
66894
  const dir = memberDir(cwd2, m3.slug);
66435
66895
  console.log("");
66436
- console.log(`${import_picocolors34.default.dim("───")} ${import_picocolors34.default.bold(m3.slug)} ${import_picocolors34.default.dim("───")}`);
66896
+ console.log(`${import_picocolors38.default.dim("───")} ${import_picocolors38.default.bold(m3.slug)} ${import_picocolors38.default.dim("───")}`);
66437
66897
  try {
66438
66898
  await runAgentPush(dir, { yes: true });
66439
66899
  } catch (err) {
@@ -66491,7 +66951,7 @@ function handleApiError6(err) {
66491
66951
  f2.error("You do not have access to this orchestration.");
66492
66952
  } else if (err.status === 409) {
66493
66953
  f2.error(err.message);
66494
- f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
66954
+ f2.info(`Run ${import_picocolors38.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
66495
66955
  } else {
66496
66956
  f2.error(err.message);
66497
66957
  }
@@ -66501,13 +66961,13 @@ function handleApiError6(err) {
66501
66961
  }
66502
66962
 
66503
66963
  // src/cli/orchestration-status.ts
66504
- var import_picocolors35 = __toESM(require_picocolors(), 1);
66964
+ var import_picocolors39 = __toESM(require_picocolors(), 1);
66505
66965
  async function runOrchestrationStatus(cwd2) {
66506
66966
  banner("orchestration status — what changed locally, remotely, both");
66507
66967
  const link2 = readOrchLink(cwd2);
66508
66968
  if (!link2) {
66509
66969
  f2.warn("This folder is not linked to any orchestration.");
66510
- f2.info(`Run ${import_picocolors35.default.cyan("brainbase orchestration pull <id>")} first.`);
66970
+ f2.info(`Run ${import_picocolors39.default.cyan("brainbase orchestration pull <id>")} first.`);
66511
66971
  return;
66512
66972
  }
66513
66973
  const localManifest = hasOrchManifest(cwd2) ? readOrchManifest(cwd2) : null;
@@ -66530,8 +66990,8 @@ async function runOrchestrationStatus(cwd2) {
66530
66990
  }
66531
66991
  const lines = [];
66532
66992
  lines.push("");
66533
- lines.push(` ${import_picocolors35.default.bold(link2.name)} ${import_picocolors35.default.dim(`(${link2.orchestration_id})`)}`);
66534
- lines.push(` ${import_picocolors35.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
66993
+ lines.push(` ${import_picocolors39.default.bold(link2.name)} ${import_picocolors39.default.dim(`(${link2.orchestration_id})`)}`);
66994
+ lines.push(` ${import_picocolors39.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
66535
66995
  lines.push("");
66536
66996
  const localSlugByAgentId = new Map;
66537
66997
  for (const m3 of localManifest?.members ?? []) {
@@ -66545,12 +67005,12 @@ async function runOrchestrationStatus(cwd2) {
66545
67005
  const membersAdded = [...localMemberSet].filter((s3) => !cloudMemberSet.has(s3));
66546
67006
  const membersRemoved = [...cloudMemberSet].filter((s3) => !localMemberSet.has(s3));
66547
67007
  if (membersAdded.length || membersRemoved.length) {
66548
- lines.push(` ${import_picocolors35.default.bold("members")}`);
67008
+ lines.push(` ${import_picocolors39.default.bold("members")}`);
66549
67009
  for (const slug of membersAdded) {
66550
- lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${import_picocolors35.default.bold(slug)}`);
67010
+ lines.push(` ${import_picocolors39.default.yellow("→ push")} added in yaml: ${import_picocolors39.default.bold(slug)}`);
66551
67011
  }
66552
67012
  for (const slug of membersRemoved) {
66553
- lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${import_picocolors35.default.bold(slug)}`);
67013
+ lines.push(` ${import_picocolors39.default.cyan("← pull")} added on cloud: ${import_picocolors39.default.bold(slug)}`);
66554
67014
  }
66555
67015
  lines.push("");
66556
67016
  }
@@ -66565,11 +67025,11 @@ async function runOrchestrationStatus(cwd2) {
66565
67025
  const edgesAdded = [...localEdges.keys()].filter((k3) => !cloudEdges.has(k3));
66566
67026
  const edgesRemoved = [...cloudEdges.keys()].filter((k3) => !localEdges.has(k3));
66567
67027
  if (edgesAdded.length || edgesRemoved.length) {
66568
- lines.push(` ${import_picocolors35.default.bold("edges")}`);
67028
+ lines.push(` ${import_picocolors39.default.bold("edges")}`);
66569
67029
  for (const k3 of edgesAdded)
66570
- lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${k3}`);
67030
+ lines.push(` ${import_picocolors39.default.yellow("→ push")} added in yaml: ${k3}`);
66571
67031
  for (const k3 of edgesRemoved)
66572
- lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${k3}`);
67032
+ lines.push(` ${import_picocolors39.default.cyan("← pull")} added on cloud: ${k3}`);
66573
67033
  lines.push("");
66574
67034
  }
66575
67035
  const cloudTriggerKey = (t) => {
@@ -66607,11 +67067,11 @@ async function runOrchestrationStatus(cwd2) {
66607
67067
  const triggersAdded = [...localTriggers.keys()].filter((k3) => !cloudTriggers.has(k3));
66608
67068
  const triggersRemoved = [...cloudTriggers.keys()].filter((k3) => !localTriggers.has(k3));
66609
67069
  if (triggersAdded.length || triggersRemoved.length) {
66610
- lines.push(` ${import_picocolors35.default.bold("schedule triggers")}`);
67070
+ lines.push(` ${import_picocolors39.default.bold("schedule triggers")}`);
66611
67071
  for (const k3 of triggersAdded)
66612
- lines.push(` ${import_picocolors35.default.yellow("→ push")} added/changed in yaml: ${localTriggers.get(k3) ?? k3}`);
67072
+ lines.push(` ${import_picocolors39.default.yellow("→ push")} added/changed in yaml: ${localTriggers.get(k3) ?? k3}`);
66613
67073
  for (const k3 of triggersRemoved)
66614
- lines.push(` ${import_picocolors35.default.cyan("← pull")} added/changed on cloud: ${cloudTriggers.get(k3) ?? k3}`);
67074
+ lines.push(` ${import_picocolors39.default.cyan("← pull")} added/changed on cloud: ${cloudTriggers.get(k3) ?? k3}`);
66615
67075
  lines.push("");
66616
67076
  }
66617
67077
  const lockByAgentId = new Map((lock?.members ?? []).map((m3) => [m3.agent_id, m3]));
@@ -66634,27 +67094,27 @@ async function runOrchestrationStatus(cwd2) {
66634
67094
  }
66635
67095
  }
66636
67096
  if (memberDrift.length) {
66637
- lines.push(` ${import_picocolors35.default.bold("member content drift")}`);
67097
+ lines.push(` ${import_picocolors39.default.bold("member content drift")}`);
66638
67098
  for (const d3 of memberDrift) {
66639
- lines.push(` ${import_picocolors35.default.cyan("?")} ${import_picocolors35.default.bold(d3.slug)} ${import_picocolors35.default.dim("— " + d3.reason)}`);
67099
+ lines.push(` ${import_picocolors39.default.cyan("?")} ${import_picocolors39.default.bold(d3.slug)} ${import_picocolors39.default.dim("— " + d3.reason)}`);
66640
67100
  }
66641
- lines.push(` ${import_picocolors35.default.dim("cd into each member folder and run")} ${import_picocolors35.default.cyan("brainbase agent status")}`);
67101
+ lines.push(` ${import_picocolors39.default.dim("cd into each member folder and run")} ${import_picocolors39.default.cyan("brainbase agent status")}`);
66642
67102
  lines.push("");
66643
67103
  }
66644
67104
  const revisionDrift = lock?.revision != null && cloud.revision !== lock.revision;
66645
67105
  if (revisionDrift) {
66646
- lines.push(` ${import_picocolors35.default.bold("cloud revision")}`);
66647
- lines.push(` ${import_picocolors35.default.cyan("← pull")} cloud changed since last pull: ${import_picocolors35.default.dim(`lock ${lock.revision} → cloud ${cloud.revision}`)}`);
67106
+ lines.push(` ${import_picocolors39.default.bold("cloud revision")}`);
67107
+ lines.push(` ${import_picocolors39.default.cyan("← pull")} cloud changed since last pull: ${import_picocolors39.default.dim(`lock ${lock.revision} → cloud ${cloud.revision}`)}`);
66648
67108
  lines.push("");
66649
67109
  }
66650
67110
  if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !triggersAdded.length && !triggersRemoved.length && !memberDrift.length && !revisionDrift) {
66651
- lines.push(` ${import_picocolors35.default.green("✓")} everything is in sync`);
67111
+ lines.push(` ${import_picocolors39.default.green("✓")} everything is in sync`);
66652
67112
  lines.push("");
66653
67113
  console.log(lines.join(`
66654
67114
  `));
66655
67115
  return;
66656
67116
  }
66657
- lines.push(` ${import_picocolors35.default.dim("run")} ${import_picocolors35.default.cyan("brainbase orchestration pull")} ${import_picocolors35.default.dim("to apply cloud changes,")} ${import_picocolors35.default.cyan("brainbase orchestration push")} ${import_picocolors35.default.dim("to send yours")}`);
67117
+ lines.push(` ${import_picocolors39.default.dim("run")} ${import_picocolors39.default.cyan("brainbase orchestration pull")} ${import_picocolors39.default.dim("to apply cloud changes,")} ${import_picocolors39.default.cyan("brainbase orchestration push")} ${import_picocolors39.default.dim("to send yours")}`);
66658
67118
  lines.push("");
66659
67119
  console.log(lines.join(`
66660
67120
  `));
@@ -66669,108 +67129,45 @@ function stableJson(value) {
66669
67129
  }
66670
67130
 
66671
67131
  // src/cli/orchestration-list.ts
66672
- var import_picocolors36 = __toESM(require_picocolors(), 1);
67132
+ var import_picocolors40 = __toESM(require_picocolors(), 1);
66673
67133
  async function runOrchestrationList(args) {
66674
67134
  banner("orchestration list — orchestrations under a team");
66675
- let orgId = args.orgId;
66676
- let teamId = args.teamId;
66677
- if (!orgId || !isUuid(orgId)) {
66678
- let orgs;
66679
- try {
66680
- orgs = await api.listOrgs();
66681
- } catch (err) {
66682
- handleApiError7(err);
66683
- return;
66684
- }
66685
- if (orgs.length === 0) {
66686
- f2.warn("You are not a member of any organization.");
66687
- return;
66688
- }
66689
- if (orgId) {
66690
- const found = orgs.find((o2) => o2.id === orgId || o2.slug === orgId);
66691
- if (!found) {
66692
- f2.error(`Org ${orgId} not found or you're not a member.`);
66693
- return;
66694
- }
66695
- orgId = found.id;
66696
- } else if (orgs.length === 1) {
66697
- orgId = orgs[0].id;
66698
- } else {
66699
- orgId = await select({
66700
- message: "Which organization?",
66701
- options: orgs.map((o2) => ({ value: o2.id, label: o2.name, hint: o2.role })),
66702
- flagHint: "Pass --org <id-or-slug>."
66703
- });
66704
- }
66705
- }
66706
- if (!teamId) {
66707
- let teams;
66708
- try {
66709
- teams = await api.listTeams(orgId);
66710
- } catch (err) {
66711
- handleApiError7(err);
66712
- return;
66713
- }
66714
- if (teams.length === 0) {
66715
- f2.warn("No teams under this organization. Create one in the web app first.");
66716
- return;
66717
- }
66718
- if (teams.length === 1) {
66719
- teamId = teams[0].id;
66720
- } else {
66721
- teamId = await select({
66722
- message: "Which team?",
66723
- options: teams.map((t) => ({ value: t.id, label: t.name })),
66724
- flagHint: "Pass --team <id>."
66725
- });
66726
- }
66727
- }
66728
- let items;
67135
+ const { org, team } = await resolveOrgAndTeam({
67136
+ orgId: args.orgId,
67137
+ teamId: args.teamId,
67138
+ announce: true
67139
+ });
66729
67140
  const sp = de();
66730
67141
  sp.start("Fetching orchestrations…");
67142
+ let items;
66731
67143
  try {
66732
- items = await api.listOrchestrations(orgId, teamId);
66733
- sp.stop(`${items.length} orchestration${items.length === 1 ? "" : "s"}.`);
67144
+ items = await api.listOrchestrations(org.id, team.id);
66734
67145
  } catch (err) {
66735
67146
  sp.stop("Failed.");
66736
- handleApiError7(err);
66737
- return;
67147
+ throw err;
66738
67148
  }
67149
+ sp.stop(`${items.length} orchestration${items.length === 1 ? "" : "s"}.`);
66739
67150
  if (items.length === 0) {
66740
67151
  f2.info("This team has no orchestrations yet.");
66741
67152
  return;
66742
67153
  }
66743
67154
  const lines = [""];
66744
67155
  for (const o2 of items) {
66745
- lines.push(` ${import_picocolors36.default.bold(o2.name)} ${import_picocolors36.default.dim(o2.id)}`);
67156
+ lines.push(` ${import_picocolors40.default.bold(o2.name)} ${import_picocolors40.default.dim(o2.id)}`);
66746
67157
  if (o2.description)
66747
- lines.push(` ${import_picocolors36.default.dim(o2.description)}`);
66748
- lines.push(` ${import_picocolors36.default.dim(`${o2.member_count} member${o2.member_count === 1 ? "" : "s"} · ${o2.edge_count} edge${o2.edge_count === 1 ? "" : "s"}`)}`);
67158
+ lines.push(` ${import_picocolors40.default.dim(o2.description)}`);
67159
+ lines.push(` ${import_picocolors40.default.dim(`${o2.member_count} member${o2.member_count === 1 ? "" : "s"} · ${o2.edge_count} edge${o2.edge_count === 1 ? "" : "s"}`)}`);
66749
67160
  lines.push("");
66750
67161
  }
66751
- lines.push(` ${import_picocolors36.default.dim("pull one with")} ${import_picocolors36.default.cyan("brainbase orchestration pull <id>")}`);
67162
+ lines.push(` ${import_picocolors40.default.dim("pull one with")} ${import_picocolors40.default.cyan("brainbase orchestration pull <id>")}`);
66752
67163
  lines.push("");
66753
67164
  console.log(lines.join(`
66754
67165
  `));
66755
67166
  }
66756
- function isUuid(value) {
66757
- return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-9a-f][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
66758
- }
66759
- function handleApiError7(err) {
66760
- if (err instanceof ApiError) {
66761
- if (err.status === 401) {
66762
- f2.error("Your session is invalid. Run `brainbase login` and try again.");
66763
- } else {
66764
- f2.error(err.message);
66765
- }
66766
- } else {
66767
- f2.error(err.message);
66768
- }
66769
- }
66770
67167
 
66771
67168
  // src/cli/orchestration-add-agent.ts
66772
67169
  import fs77 from "node:fs";
66773
- var import_picocolors37 = __toESM(require_picocolors(), 1);
67170
+ var import_picocolors41 = __toESM(require_picocolors(), 1);
66774
67171
 
66775
67172
  // src/core/orchestration-add.ts
66776
67173
  function resolveOrgIdForGroup(groupId, orgsWithTeams) {
@@ -66835,7 +67232,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
66835
67232
  const link2 = readOrchLink(cwd2);
66836
67233
  if (!link2 || !hasOrchManifest(cwd2)) {
66837
67234
  f2.warn("This folder is not a linked orchestration.");
66838
- f2.info(`Run ${import_picocolors37.default.cyan("brainbase orchestration pull <id>")} first.`);
67235
+ f2.info(`Run ${import_picocolors41.default.cyan("brainbase orchestration pull <id>")} first.`);
66839
67236
  return;
66840
67237
  }
66841
67238
  let manifest;
@@ -66861,7 +67258,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
66861
67258
  while (manifest.members.some((m3) => m3.slug === candidate) || fs77.existsSync(memberDir(cwd2, candidate))) {
66862
67259
  candidate = `${slug}-${++n}`;
66863
67260
  }
66864
- f2.info(`Slug ${import_picocolors37.default.bold(slug)} is taken — using ${import_picocolors37.default.bold(candidate)}.`);
67261
+ f2.info(`Slug ${import_picocolors41.default.bold(slug)} is taken — using ${import_picocolors41.default.bold(candidate)}.`);
66865
67262
  slug = candidate;
66866
67263
  }
66867
67264
  let payloadSchema;
@@ -66885,7 +67282,7 @@ async function runOrchestrationAddAgent(cwd2, args) {
66885
67282
  const resolved = resolveOrgIdForGroup(link2.group_id, orgsWithTeams);
66886
67283
  if (!resolved) {
66887
67284
  sp.stop("Failed.");
66888
- f2.error(`Could not find an org that owns group ${import_picocolors37.default.bold(link2.group_id)}. ` + `Pass ${import_picocolors37.default.cyan("--org <id>")} explicitly.`);
67285
+ f2.error(`Could not find an org that owns group ${import_picocolors41.default.bold(link2.group_id)}. ` + `Pass ${import_picocolors41.default.cyan("--org <id>")} explicitly.`);
66889
67286
  return;
66890
67287
  }
66891
67288
  orgId = resolved;
@@ -66902,14 +67299,14 @@ async function runOrchestrationAddAgent(cwd2, args) {
66902
67299
  if (from.length === 0 && to2.length === 0 && isInteractive() && manifest.members.length > 0) {
66903
67300
  const memberOptions = manifest.members.map((m3) => ({ value: m3.slug, label: m3.slug }));
66904
67301
  const pickedFrom = await ae({
66905
- message: `Connect ${import_picocolors37.default.bold(slug)} FROM which member(s)? — edges INTO ${slug} (space to select, enter to skip)`,
67302
+ message: `Connect ${import_picocolors41.default.bold(slug)} FROM which member(s)? — edges INTO ${slug} (space to select, enter to skip)`,
66906
67303
  options: memberOptions,
66907
67304
  required: false
66908
67305
  });
66909
67306
  if (Array.isArray(pickedFrom))
66910
67307
  from = pickedFrom;
66911
67308
  const pickedTo = await ae({
66912
- message: `Connect ${import_picocolors37.default.bold(slug)} TO which member(s)? — edges OUT of ${slug} (space to select, enter to skip)`,
67309
+ message: `Connect ${import_picocolors41.default.bold(slug)} TO which member(s)? — edges OUT of ${slug} (space to select, enter to skip)`,
66913
67310
  options: memberOptions,
66914
67311
  required: false
66915
67312
  });
@@ -66948,23 +67345,23 @@ async function runOrchestrationAddAgent(cwd2, args) {
66948
67345
  }
66949
67346
  writeOrchManifest(cwd2, updated);
66950
67347
  if (args.noPush) {
66951
- f2.info(`Manifest updated. Run ${import_picocolors37.default.cyan("brainbase orchestration push")} to apply.`);
67348
+ f2.info(`Manifest updated. Run ${import_picocolors41.default.cyan("brainbase orchestration push")} to apply.`);
66952
67349
  return;
66953
67350
  }
66954
67351
  await runOrchestrationPush(cwd2, { yes: true, graphOnly: true });
66955
67352
  }
66956
67353
 
66957
67354
  // src/cli/orchestration-create.ts
66958
- var import_picocolors38 = __toESM(require_picocolors(), 1);
67355
+ var import_picocolors42 = __toESM(require_picocolors(), 1);
66959
67356
  async function runOrchestrationCreate(cwd2, args) {
66960
67357
  banner("orchestration create — claim a brainbase-orchestration.yaml");
66961
67358
  if (readOrchLink(cwd2)) {
66962
67359
  f2.warn("This folder is already linked to an orchestration.");
66963
- f2.info(`Run ${import_picocolors38.default.cyan("brainbase orchestration push")} to update it.`);
67360
+ f2.info(`Run ${import_picocolors42.default.cyan("brainbase orchestration push")} to update it.`);
66964
67361
  return;
66965
67362
  }
66966
67363
  if (!hasOrchManifest(cwd2)) {
66967
- f2.warn(`No ${import_picocolors38.default.bold(ORCH_MANIFEST_FILE)} here.`);
67364
+ f2.warn(`No ${import_picocolors42.default.bold(ORCH_MANIFEST_FILE)} here.`);
66968
67365
  f2.info(`Create one, or pull an existing orchestration first.`);
66969
67366
  return;
66970
67367
  }
@@ -66990,15 +67387,17 @@ async function runOrchestrationCreate(cwd2, args) {
66990
67387
  process.exitCode = 1;
66991
67388
  return;
66992
67389
  }
66993
- const target = await resolveOrgAndTeam(args);
66994
- if (!target)
66995
- return;
67390
+ const target = await resolveOrgAndTeam({
67391
+ orgId: args.orgId,
67392
+ teamId: args.teamId,
67393
+ announce: true
67394
+ });
66996
67395
  const plan = [
66997
67396
  "",
66998
- ` ${import_picocolors38.default.bold(manifest.orchestration.name)}`,
66999
- ` ${import_picocolors38.default.dim("org")} ${import_picocolors38.default.bold(target.org.name)}`,
67000
- ` ${import_picocolors38.default.dim("team")} ${import_picocolors38.default.bold(target.team.name)}`,
67001
- ` ${import_picocolors38.default.dim("graph")} ${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}, ${graph.triggers.length} trigger${graph.triggers.length === 1 ? "" : "s"}`,
67397
+ ` ${import_picocolors42.default.bold(manifest.orchestration.name)}`,
67398
+ ` ${import_picocolors42.default.dim("org")} ${import_picocolors42.default.bold(target.org.name)}`,
67399
+ ` ${import_picocolors42.default.dim("team")} ${import_picocolors42.default.bold(target.team.name)}`,
67400
+ ` ${import_picocolors42.default.dim("graph")} ${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}, ${graph.triggers.length} trigger${graph.triggers.length === 1 ? "" : "s"}`,
67002
67401
  ""
67003
67402
  ];
67004
67403
  console.log(plan.join(`
@@ -67028,7 +67427,7 @@ async function runOrchestrationCreate(cwd2, args) {
67028
67427
  edges: graph.edges,
67029
67428
  triggers: graph.triggers
67030
67429
  });
67031
- sp.stop(`Created ${import_picocolors38.default.bold(created.name)}.`);
67430
+ sp.stop(`Created ${import_picocolors42.default.bold(created.name)}.`);
67032
67431
  writeOrchLink(cwd2, {
67033
67432
  schemaVersion: 1,
67034
67433
  orchestration_id: created.id,
@@ -67059,92 +67458,11 @@ async function runOrchestrationCreate(cwd2, args) {
67059
67458
  $e(`Created ${created.name} at revision ${created.revision}.`);
67060
67459
  } catch (err) {
67061
67460
  sp.stop("Failed.");
67062
- handleApiError8(err);
67063
- process.exitCode = 1;
67064
- }
67065
- }
67066
- async function resolveOrgAndTeam(args) {
67067
- const orgsSpinner = de();
67068
- orgsSpinner.start("Loading your organizations…");
67069
- let orgs;
67070
- try {
67071
- orgs = await api.listOrgs();
67072
- } catch (err) {
67073
- orgsSpinner.stop("Failed.");
67074
- handleApiError8(err);
67075
- process.exitCode = 1;
67076
- return null;
67077
- }
67078
- orgsSpinner.stop(`Found ${orgs.length} organization${orgs.length === 1 ? "" : "s"}.`);
67079
- if (orgs.length === 0) {
67080
- f2.warn("You are not in any organizations yet.");
67081
- process.exitCode = 1;
67082
- return null;
67083
- }
67084
- let org;
67085
- if (args.orgId) {
67086
- const found = orgs.find((o2) => o2.id === args.orgId || o2.slug === args.orgId);
67087
- if (!found) {
67088
- f2.error(`Org ${args.orgId} not found or you're not a member.`);
67089
- process.exitCode = 1;
67090
- return null;
67091
- }
67092
- org = found;
67093
- } else if (orgs.length === 1) {
67094
- org = orgs[0];
67095
- f2.info(`Using organization ${import_picocolors38.default.bold(org.name)}.`);
67096
- } else if (!isInteractive()) {
67097
- throw new NonInteractiveError("Multiple organizations. Pass --org <id-or-slug> to choose non-interactively.");
67098
- } else {
67099
- const orgId = await select({
67100
- message: "Pick an organization",
67101
- options: orgs.map((o2) => ({ value: o2.id, label: o2.name, hint: o2.role })),
67102
- flagHint: "Pass --org <id-or-slug> to choose non-interactively."
67103
- });
67104
- org = orgs.find((o2) => o2.id === orgId);
67105
- }
67106
- const teamsSpinner = de();
67107
- teamsSpinner.start(`Loading teams in ${org.name}…`);
67108
- let teams;
67109
- try {
67110
- teams = await api.listTeams(org.id);
67111
- } catch (err) {
67112
- teamsSpinner.stop("Failed.");
67113
- handleApiError8(err);
67114
- process.exitCode = 1;
67115
- return null;
67116
- }
67117
- teamsSpinner.stop(`Found ${teams.length} team${teams.length === 1 ? "" : "s"}.`);
67118
- if (teams.length === 0) {
67119
- f2.warn(`No teams in ${org.name} yet.`);
67461
+ handleApiError7(err);
67120
67462
  process.exitCode = 1;
67121
- return null;
67122
- }
67123
- let team;
67124
- if (args.teamId) {
67125
- const found = teams.find((t) => t.id === args.teamId);
67126
- if (!found) {
67127
- f2.error(`Team ${args.teamId} not found in this org.`);
67128
- process.exitCode = 1;
67129
- return null;
67130
- }
67131
- team = found;
67132
- } else if (teams.length === 1) {
67133
- team = teams[0];
67134
- f2.info(`Using team ${import_picocolors38.default.bold(team.name)}.`);
67135
- } else if (!isInteractive()) {
67136
- throw new NonInteractiveError("Multiple teams. Pass --team <id> to choose non-interactively.");
67137
- } else {
67138
- const teamId = await select({
67139
- message: "Pick a team",
67140
- options: teams.map((t) => ({ value: t.id, label: t.name, hint: t.role })),
67141
- flagHint: "Pass --team <id> to choose non-interactively."
67142
- });
67143
- team = teams.find((t) => t.id === teamId);
67144
67463
  }
67145
- return { org, team };
67146
67464
  }
67147
- function handleApiError8(err) {
67465
+ function handleApiError7(err) {
67148
67466
  if (err instanceof ApiError) {
67149
67467
  if (err.status === 401) {
67150
67468
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
@@ -67161,7 +67479,7 @@ function handleApiError8(err) {
67161
67479
  // src/cli/orchestration.ts
67162
67480
  async function runOrchestration(cwd2, sub, args, opts) {
67163
67481
  if (args.some((arg) => arg === "--help" || arg === "-h")) {
67164
- printHelp2();
67482
+ printHelp3();
67165
67483
  return;
67166
67484
  }
67167
67485
  switch (sub) {
@@ -67210,33 +67528,33 @@ async function runOrchestration(cwd2, sub, args, opts) {
67210
67528
  case "help":
67211
67529
  case "-h":
67212
67530
  case "--help":
67213
- printHelp2();
67531
+ printHelp3();
67214
67532
  return;
67215
67533
  default:
67216
67534
  console.error(`Unknown orchestration subcommand: ${sub}
67217
67535
  `);
67218
- printHelp2();
67536
+ printHelp3();
67219
67537
  process.exit(1);
67220
67538
  }
67221
67539
  }
67222
- function printHelp2() {
67540
+ function printHelp3() {
67223
67541
  const out = [];
67224
67542
  out.push("");
67225
- out.push(` ${import_picocolors39.default.bold("brainbase orchestration")} ${import_picocolors39.default.dim("<sub> [options]")}`);
67543
+ out.push(` ${import_picocolors43.default.bold("brainbase orchestration")} ${import_picocolors43.default.dim("<sub> [options]")}`);
67226
67544
  out.push("");
67227
- out.push(` ${import_picocolors39.default.cyan("create")} ${import_picocolors39.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
67228
- out.push(` ${import_picocolors39.default.cyan("pull")} ${import_picocolors39.default.dim("<id>")} ${import_picocolors39.default.dim("fetch orchestration + every member agent into this folder")}`);
67229
- out.push(` ${import_picocolors39.default.cyan("push")} ${import_picocolors39.default.dim("push each member, then update the orchestration graph")}`);
67230
- out.push(` ${import_picocolors39.default.cyan("add-agent")} ${import_picocolors39.default.dim("<name>")} ${import_picocolors39.default.dim("create a member agent, wire edges (--from/--to), and push")}`);
67231
- out.push(` ${import_picocolors39.default.cyan("status")} ${import_picocolors39.default.dim("show what would push and what would pull")}`);
67232
- out.push(` ${import_picocolors39.default.cyan("list")} ${import_picocolors39.default.dim("list orchestrations under a team")}`);
67545
+ out.push(` ${import_picocolors43.default.cyan("create")} ${import_picocolors43.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
67546
+ out.push(` ${import_picocolors43.default.cyan("pull")} ${import_picocolors43.default.dim("<id>")} ${import_picocolors43.default.dim("fetch orchestration + every member agent into this folder")}`);
67547
+ out.push(` ${import_picocolors43.default.cyan("push")} ${import_picocolors43.default.dim("push each member, then update the orchestration graph")}`);
67548
+ out.push(` ${import_picocolors43.default.cyan("add-agent")} ${import_picocolors43.default.dim("<name>")} ${import_picocolors43.default.dim("create a member agent, wire edges (--from/--to), and push")}`);
67549
+ out.push(` ${import_picocolors43.default.cyan("status")} ${import_picocolors43.default.dim("show what would push and what would pull")}`);
67550
+ out.push(` ${import_picocolors43.default.cyan("list")} ${import_picocolors43.default.dim("list orchestrations under a team")}`);
67233
67551
  out.push("");
67234
- out.push(` ${import_picocolors39.default.bold("Flags")}`);
67235
- out.push(` ${import_picocolors39.default.dim("--yes, -y")} skip confirmations`);
67236
- out.push(` ${import_picocolors39.default.dim("--harness <id>")} harness for newly-created member folders (default claude-code)`);
67237
- out.push(` ${import_picocolors39.default.dim("--graph-only")} for push: only update members + edges, skip per-member push`);
67238
- out.push(` ${import_picocolors39.default.dim("--org <id>")} for create/list: org id or slug (CLI vocab — DB teams.id)`);
67239
- out.push(` ${import_picocolors39.default.dim("--team <id>")} for create/list: team id (CLI vocab — DB groups.id)`);
67552
+ out.push(` ${import_picocolors43.default.bold("Flags")}`);
67553
+ out.push(` ${import_picocolors43.default.dim("--yes, -y")} skip confirmations`);
67554
+ out.push(` ${import_picocolors43.default.dim("--harness <id>")} harness for newly-created member folders (default claude-code)`);
67555
+ out.push(` ${import_picocolors43.default.dim("--graph-only")} for push: only update members + edges, skip per-member push`);
67556
+ out.push(` ${import_picocolors43.default.dim("--org <id>")} for create/list: org id or slug (CLI vocab — DB teams.id)`);
67557
+ out.push(` ${import_picocolors43.default.dim("--team <id>")} for create/list: team id (CLI vocab — DB groups.id)`);
67240
67558
  out.push("");
67241
67559
  console.log(out.join(`
67242
67560
  `));
@@ -67281,16 +67599,16 @@ async function runRun(cwd2, args) {
67281
67599
  }
67282
67600
 
67283
67601
  // src/cli/publish.ts
67284
- var import_picocolors40 = __toESM(require_picocolors(), 1);
67602
+ var import_picocolors44 = __toESM(require_picocolors(), 1);
67285
67603
  async function runPublish(cwd2, _args) {
67286
67604
  banner("publish — send your changes to the team");
67287
67605
  const link2 = readLink(cwd2);
67288
67606
  if (!link2) {
67289
67607
  f2.warn("This folder is not linked to any agent.");
67290
- f2.info(`Run ${import_picocolors40.default.cyan("brainbase link")} first.`);
67608
+ f2.info(`Run ${import_picocolors44.default.cyan("brainbase link")} first.`);
67291
67609
  return;
67292
67610
  }
67293
- f2.info(`${import_picocolors40.default.bold("publish")} is coming soon — for now, edit the agent on the web app and run ${import_picocolors40.default.cyan("brainbase sync")} to bring changes here.`);
67611
+ f2.info(`${import_picocolors44.default.bold("publish")} is coming soon — for now, edit the agent on the web app and run ${import_picocolors44.default.cyan("brainbase sync")} to bring changes here.`);
67294
67612
  }
67295
67613
 
67296
67614
  // src/ui/ink/StatusCard.tsx
@@ -67588,7 +67906,7 @@ async function runStatus(cwd2) {
67588
67906
  }
67589
67907
 
67590
67908
  // src/cli/token.ts
67591
- var import_picocolors41 = __toESM(require_picocolors(), 1);
67909
+ var import_picocolors45 = __toESM(require_picocolors(), 1);
67592
67910
 
67593
67911
  // src/ui/ink/TokenCards.tsx
67594
67912
  var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
@@ -67882,7 +68200,7 @@ async function runTokenRevoke(args) {
67882
68200
  }
67883
68201
  if (!autoProceed(args.yes)) {
67884
68202
  const ok = await se({
67885
- message: `Revoke token ${import_picocolors41.default.bold(args.id)}? CIs and machines using it will stop working.`,
68203
+ message: `Revoke token ${import_picocolors45.default.bold(args.id)}? CIs and machines using it will stop working.`,
67886
68204
  initialValue: false
67887
68205
  });
67888
68206
  if (!ensureNotCancelled(ok))
@@ -67897,7 +68215,7 @@ async function runTokenRevoke(args) {
67897
68215
  }
67898
68216
  async function runTokenClear() {
67899
68217
  if (!readToken()) {
67900
- console.log(import_picocolors41.default.dim("No local token stored."));
68218
+ console.log(import_picocolors45.default.dim("No local token stored."));
67901
68219
  return;
67902
68220
  }
67903
68221
  clearToken();
@@ -67948,24 +68266,24 @@ async function runToken(sub, rest2, args) {
67948
68266
  function printTokenHelp() {
67949
68267
  const out = [];
67950
68268
  out.push("");
67951
- out.push(` ${import_picocolors41.default.bold("brainbase token")} ${import_picocolors41.default.dim("<command>")}`);
68269
+ out.push(` ${import_picocolors45.default.bold("brainbase token")} ${import_picocolors45.default.dim("<command>")}`);
67952
68270
  out.push("");
67953
- out.push(` ${import_picocolors41.default.cyan("create")} ${import_picocolors41.default.dim("issue a new long-lived CLI key (PAT)")}`);
67954
- out.push(` ${import_picocolors41.default.cyan("list")} ${import_picocolors41.default.dim("show your active tokens")}`);
67955
- out.push(` ${import_picocolors41.default.cyan("revoke")} ${import_picocolors41.default.dim("<id>")} ${import_picocolors41.default.dim("revoke a token by id")}`);
67956
- out.push(` ${import_picocolors41.default.cyan("clear")} ${import_picocolors41.default.dim("forget the local token (does not revoke)")}`);
68271
+ out.push(` ${import_picocolors45.default.cyan("create")} ${import_picocolors45.default.dim("issue a new long-lived CLI key (PAT)")}`);
68272
+ out.push(` ${import_picocolors45.default.cyan("list")} ${import_picocolors45.default.dim("show your active tokens")}`);
68273
+ out.push(` ${import_picocolors45.default.cyan("revoke")} ${import_picocolors45.default.dim("<id>")} ${import_picocolors45.default.dim("revoke a token by id")}`);
68274
+ out.push(` ${import_picocolors45.default.cyan("clear")} ${import_picocolors45.default.dim("forget the local token (does not revoke)")}`);
67957
68275
  out.push("");
67958
- out.push(` ${import_picocolors41.default.bold("create flags")}`);
67959
- out.push(` ${import_picocolors41.default.cyan("--name, -n")} ${import_picocolors41.default.dim("<label>")} ${import_picocolors41.default.dim("token label (prompted if omitted)")}`);
67960
- out.push(` ${import_picocolors41.default.cyan("--scopes")} ${import_picocolors41.default.dim("<list>")} ${import_picocolors41.default.dim("comma-separated; allowed: read, publish, admin")}`);
67961
- out.push(` ${import_picocolors41.default.dim("default: read,publish")}`);
68276
+ out.push(` ${import_picocolors45.default.bold("create flags")}`);
68277
+ out.push(` ${import_picocolors45.default.cyan("--name, -n")} ${import_picocolors45.default.dim("<label>")} ${import_picocolors45.default.dim("token label (prompted if omitted)")}`);
68278
+ out.push(` ${import_picocolors45.default.cyan("--scopes")} ${import_picocolors45.default.dim("<list>")} ${import_picocolors45.default.dim("comma-separated; allowed: read, publish, admin")}`);
68279
+ out.push(` ${import_picocolors45.default.dim("default: read,publish")}`);
67962
68280
  out.push("");
67963
68281
  console.log(out.join(`
67964
68282
  `));
67965
68283
  }
67966
68284
 
67967
68285
  // src/cli/mcp.ts
67968
- var import_picocolors42 = __toESM(require_picocolors(), 1);
68286
+ var import_picocolors46 = __toESM(require_picocolors(), 1);
67969
68287
 
67970
68288
  // src/core/mcp-check/collect-servers.ts
67971
68289
  import path86 from "node:path";
@@ -76313,17 +76631,17 @@ async function runMcpCheck(cwd2, options) {
76313
76631
  function renderHuman(report) {
76314
76632
  const lines = [];
76315
76633
  if (report.check_status === "skipped") {
76316
- lines.push(import_picocolors42.default.dim("No MCP servers configured — nothing to check."));
76634
+ lines.push(import_picocolors46.default.dim("No MCP servers configured — nothing to check."));
76317
76635
  return lines.join(`
76318
76636
  `) + `
76319
76637
  `;
76320
76638
  }
76321
76639
  for (const s3 of report.servers) {
76322
- const mark = s3.status === "ok" ? import_picocolors42.default.green("✓") : s3.status === "auth_failed" ? import_picocolors42.default.red("✗") : import_picocolors42.default.yellow("⚠");
76323
- const detail = s3.status === "ok" ? import_picocolors42.default.dim(`${s3.tool_count} tool${s3.tool_count === 1 ? "" : "s"}`) : import_picocolors42.default.dim(s3.status + (s3.error ? ` — ${s3.error}` : ""));
76640
+ const mark = s3.status === "ok" ? import_picocolors46.default.green("✓") : s3.status === "auth_failed" ? import_picocolors46.default.red("✗") : import_picocolors46.default.yellow("⚠");
76641
+ const detail = s3.status === "ok" ? import_picocolors46.default.dim(`${s3.tool_count} tool${s3.tool_count === 1 ? "" : "s"}`) : import_picocolors46.default.dim(s3.status + (s3.error ? ` — ${s3.error}` : ""));
76324
76642
  lines.push(` ${mark} ${s3.name} ${detail}`);
76325
76643
  }
76326
- const summary = report.check_status === "ok" ? import_picocolors42.default.green("All MCP servers connected.") : import_picocolors42.default.yellow("Some MCP servers are unhealthy.");
76644
+ const summary = report.check_status === "ok" ? import_picocolors46.default.green("All MCP servers connected.") : import_picocolors46.default.yellow("Some MCP servers are unhealthy.");
76327
76645
  lines.push("", summary);
76328
76646
  return lines.join(`
76329
76647
  `) + `
@@ -76345,6 +76663,210 @@ async function runMcp(cwd2, sub, _argv, options) {
76345
76663
  }
76346
76664
  }
76347
76665
 
76666
+ // src/cli/task.ts
76667
+ var import_picocolors47 = __toESM(require_picocolors(), 1);
76668
+
76669
+ // src/cli/task-create.ts
76670
+ import { randomUUID as randomUUID2 } from "node:crypto";
76671
+ async function createTask(input, options) {
76672
+ return await masApi.createTask(input, options);
76673
+ }
76674
+ function requiredValue(value, flag) {
76675
+ const normalized = value?.trim();
76676
+ if (!normalized) {
76677
+ throw new Error(`${flag} is required and must not be blank.`);
76678
+ }
76679
+ return normalized;
76680
+ }
76681
+ function optionalValue(value, flag) {
76682
+ if (value === undefined)
76683
+ return;
76684
+ const normalized = value.trim();
76685
+ if (!normalized) {
76686
+ throw new Error(`${flag} must not be blank when provided.`);
76687
+ }
76688
+ return normalized;
76689
+ }
76690
+ function resolveAgentId(cwd2, agentId, readLocalManifest) {
76691
+ if (agentId !== undefined) {
76692
+ return requiredValue(agentId, "--agent");
76693
+ }
76694
+ const manifest = readLocalManifest(cwd2);
76695
+ if (!manifest?.id) {
76696
+ throw new Error("No claimed agent found in brainbase.agent.yaml. Run `brainbase agent create` first, or pass --agent <id>.");
76697
+ }
76698
+ return manifest.id;
76699
+ }
76700
+ function isPublishScopeError(error2) {
76701
+ const message = error2 instanceof Error ? error2.message : String(error2);
76702
+ const body = error2 && typeof error2 === "object" && "body" in error2 ? JSON.stringify(error2.body) : "";
76703
+ return /PAT lacks required scope:\s*publish/i.test(`${message} ${body}`);
76704
+ }
76705
+ async function runTaskCreate(cwd2, options, dependencies = {}) {
76706
+ const idempotencyKey = (dependencies.randomUUID ?? randomUUID2)();
76707
+ const message = requiredValue(options.message, "--message");
76708
+ const agentId = resolveAgentId(cwd2, options.agentId, dependencies.readManifest ?? readManifest);
76709
+ const title = optionalValue(options.title, "--title");
76710
+ const model = optionalValue(options.model, "--model");
76711
+ const input = {
76712
+ agent_id: agentId,
76713
+ initial_messages: [{ role: "user", content: message }],
76714
+ auto_run: true,
76715
+ ...title ? { title } : {},
76716
+ ...model ? { default_model: model } : {}
76717
+ };
76718
+ let created;
76719
+ try {
76720
+ created = await (dependencies.createTask ?? createTask)(input, {
76721
+ idempotencyKey
76722
+ });
76723
+ } catch (error2) {
76724
+ if (isPublishScopeError(error2)) {
76725
+ throw new Error("PAT lacks required scope: publish. Mint a replacement with `brainbase token create --scopes read,publish` and try again.");
76726
+ }
76727
+ throw error2;
76728
+ }
76729
+ if (options.json) {
76730
+ console.log(JSON.stringify({
76731
+ task_id: created.id,
76732
+ agent_id: created.agent_id,
76733
+ status: created.status
76734
+ }));
76735
+ return;
76736
+ }
76737
+ console.log([
76738
+ `Task ID: ${created.id}`,
76739
+ `Agent ID: ${created.agent_id}`,
76740
+ `Status: ${created.status}`,
76741
+ "First run accepted."
76742
+ ].join(`
76743
+ `));
76744
+ }
76745
+
76746
+ // src/cli/task.ts
76747
+ var VALUE_FLAGS = [
76748
+ ["--agent", "agentId"],
76749
+ ["--message", "message"],
76750
+ ["--title", "title"],
76751
+ ["--model", "model"]
76752
+ ];
76753
+ var TASK_OPTION_NAMES = new Set([
76754
+ ...VALUE_FLAGS.map(([flag]) => flag),
76755
+ "--json"
76756
+ ]);
76757
+ var HELP_FLAGS = new Set(["--help", "-h"]);
76758
+ function missingValueError(flag) {
76759
+ if (flag === "--message" || flag === "--agent") {
76760
+ return new Error(`${flag} is required and must not be blank.`);
76761
+ }
76762
+ return new Error(`${flag} must not be blank when provided.`);
76763
+ }
76764
+ function flagLikeValueError(flag, value) {
76765
+ return new Error(`${flag} requires a value. If you meant the literal "${value}", use ${flag}=${value} or ${flag} -- ${value}.`);
76766
+ }
76767
+ function parseCreateArgs(args) {
76768
+ const options = {};
76769
+ const seen = new Set;
76770
+ for (let index = 0;index < args.length; index += 1) {
76771
+ const arg = args[index];
76772
+ if (HELP_FLAGS.has(arg)) {
76773
+ return { help: true, options };
76774
+ }
76775
+ if (arg === "--json") {
76776
+ if (seen.has(arg)) {
76777
+ throw new Error(`Duplicate task create option: ${arg}`);
76778
+ }
76779
+ seen.add(arg);
76780
+ options.json = true;
76781
+ continue;
76782
+ }
76783
+ let matched = false;
76784
+ for (const [flag, option] of VALUE_FLAGS) {
76785
+ if (arg === flag) {
76786
+ if (seen.has(flag)) {
76787
+ throw new Error(`Duplicate task create option: ${flag}`);
76788
+ }
76789
+ seen.add(flag);
76790
+ let value = args[index + 1];
76791
+ if (value === undefined) {
76792
+ throw missingValueError(flag);
76793
+ }
76794
+ if (value === "--") {
76795
+ value = args[index + 2];
76796
+ if (value === undefined)
76797
+ throw missingValueError(flag);
76798
+ index += 1;
76799
+ } else if (HELP_FLAGS.has(value) && (option === "agentId" || option === "model")) {
76800
+ return { help: true, options };
76801
+ } else if (TASK_OPTION_NAMES.has(value)) {
76802
+ throw flagLikeValueError(flag, value);
76803
+ }
76804
+ options[option] = value;
76805
+ index += 1;
76806
+ matched = true;
76807
+ break;
76808
+ }
76809
+ const prefix = `${flag}=`;
76810
+ if (arg.startsWith(prefix)) {
76811
+ if (seen.has(flag)) {
76812
+ throw new Error(`Duplicate task create option: ${flag}`);
76813
+ }
76814
+ seen.add(flag);
76815
+ options[option] = arg.slice(prefix.length);
76816
+ matched = true;
76817
+ break;
76818
+ }
76819
+ }
76820
+ if (!matched) {
76821
+ throw new Error(`Unknown task create argument: ${arg}`);
76822
+ }
76823
+ }
76824
+ return { help: false, options };
76825
+ }
76826
+ async function runTask(cwd2, sub, args) {
76827
+ switch (sub) {
76828
+ case "create": {
76829
+ const parsed = parseCreateArgs(args);
76830
+ if (parsed.help) {
76831
+ printHelp4();
76832
+ return;
76833
+ }
76834
+ await runTaskCreate(cwd2, parsed.options);
76835
+ return;
76836
+ }
76837
+ case undefined:
76838
+ case "help":
76839
+ case "-h":
76840
+ case "--help":
76841
+ printHelp4();
76842
+ return;
76843
+ default:
76844
+ console.error(`Unknown task subcommand: ${sub}
76845
+ `);
76846
+ printHelp4();
76847
+ process.exit(1);
76848
+ }
76849
+ }
76850
+ function printHelp4() {
76851
+ const out = [];
76852
+ out.push("");
76853
+ out.push(` ${import_picocolors47.default.bold("brainbase task")} ${import_picocolors47.default.dim("<sub> [options]")}`);
76854
+ out.push("");
76855
+ out.push(` ${import_picocolors47.default.cyan("create")} ${import_picocolors47.default.dim("--message <text>")} ${import_picocolors47.default.dim("create a task and start its first run")}`);
76856
+ out.push("");
76857
+ out.push(` ${import_picocolors47.default.bold("create flags")}`);
76858
+ out.push(` ${import_picocolors47.default.dim("--message <text>")} required first user message`);
76859
+ out.push(` ${import_picocolors47.default.dim("--agent <id>")} override the claimed agent in brainbase.agent.yaml`);
76860
+ out.push(` ${import_picocolors47.default.dim("--title <text>")} optional task title`);
76861
+ out.push(` ${import_picocolors47.default.dim("--model <id>")} optional model override`);
76862
+ out.push(` ${import_picocolors47.default.dim("--json")} print task_id, agent_id, and status as JSON`);
76863
+ out.push("");
76864
+ out.push(` ${import_picocolors47.default.dim("Flag-like values:")} use ${import_picocolors47.default.cyan("--flag=value")} or ${import_picocolors47.default.cyan("--flag -- <value>")}`);
76865
+ out.push("");
76866
+ console.log(out.join(`
76867
+ `));
76868
+ }
76869
+
76348
76870
  // src/index.ts
76349
76871
  var PROTECTED = new Set([
76350
76872
  "template",
@@ -76365,100 +76887,115 @@ var STORED_PAT_COMMANDS = new Set([
76365
76887
  function help() {
76366
76888
  const out = [];
76367
76889
  out.push("");
76368
- out.push(` ${brandTint("◆")} ${import_picocolors43.default.bold("brainbase")} ${import_picocolors43.default.dim(`v${VERSION}`)}`);
76369
- out.push(` ${import_picocolors43.default.dim("connect your local agent to the brainbase platform")}`);
76890
+ out.push(` ${brandTint("◆")} ${import_picocolors48.default.bold("brainbase")} ${import_picocolors48.default.dim(`v${VERSION}`)}`);
76891
+ out.push(` ${import_picocolors48.default.dim("connect your local agent to the brainbase platform")}`);
76370
76892
  out.push("");
76371
76893
  out.push(divider("USAGE"));
76372
76894
  out.push("");
76373
- out.push(` ${import_picocolors43.default.bold("brainbase")} ${import_picocolors43.default.dim("<command> [options]")}`);
76895
+ out.push(` ${import_picocolors48.default.bold("brainbase")} ${import_picocolors48.default.dim("<command> [options]")}`);
76374
76896
  out.push("");
76375
76897
  out.push(divider("AUTH"));
76376
76898
  out.push("");
76377
- out.push(` ${import_picocolors43.default.cyan("login")} ${import_picocolors43.default.dim(" open the web app and connect this device")}`);
76378
- out.push(` ${import_picocolors43.default.cyan("logout")} ${import_picocolors43.default.dim(" clear the local session")}`);
76379
- out.push(` ${import_picocolors43.default.cyan("whoami")} ${import_picocolors43.default.dim(" show the current user")}`);
76899
+ out.push(` ${import_picocolors48.default.cyan("login")} ${import_picocolors48.default.dim(" open the web app and connect this device")}`);
76900
+ out.push(` ${import_picocolors48.default.cyan("logout")} ${import_picocolors48.default.dim(" clear the local session")}`);
76901
+ out.push(` ${import_picocolors48.default.cyan("whoami")} ${import_picocolors48.default.dim(" show the current user")}`);
76902
+ out.push("");
76903
+ out.push(divider("DISCOVERY"));
76904
+ out.push("");
76905
+ out.push(` ${import_picocolors48.default.cyan("team list")} ${import_picocolors48.default.dim("show the teams you can create agents in")}`);
76906
+ out.push(` ${import_picocolors48.default.cyan("agent list")} ${import_picocolors48.default.dim("show a team's agents and their ids")}`);
76380
76907
  out.push("");
76381
76908
  out.push(divider("LINKED AGENT"));
76382
76909
  out.push("");
76383
- out.push(` ${import_picocolors43.default.cyan("agent create")} ${import_picocolors43.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
76384
- out.push(` ${import_picocolors43.default.cyan("agent pull")} ${import_picocolors43.default.dim("[<id>]")} ${import_picocolors43.default.dim("bring cloud changes into this folder (--force to override; --run-entrypoint to also execute the agent entrypoint)")}`);
76385
- out.push(` ${import_picocolors43.default.cyan("agent push")} ${import_picocolors43.default.dim("send local changes to the cloud (--force to overwrite cloud-side conflicts with local)")}`);
76386
- out.push(` ${import_picocolors43.default.cyan("agent unpack")} ${import_picocolors43.default.dim("install the claimed agent into a harness layout")}`);
76387
- out.push(` ${import_picocolors43.default.cyan("link")} ${import_picocolors43.default.dim("attach this folder to an existing agent")}`);
76388
- out.push(` ${import_picocolors43.default.cyan("agent status")} ${import_picocolors43.default.dim("show what would pull and what would push")}`);
76389
- out.push(` ${import_picocolors43.default.cyan("agent env")} ${import_picocolors43.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
76390
- out.push(` ${import_picocolors43.default.cyan("run")} ${import_picocolors43.default.dim("<cmd> [args...]")} ${import_picocolors43.default.dim("run <cmd> with secrets.env loaded into env")}`);
76391
- out.push(` ${import_picocolors43.default.cyan("status")} ${import_picocolors43.default.dim("show what this folder is linked to")}`);
76392
- out.push(` ${import_picocolors43.default.cyan("unlink")} ${import_picocolors43.default.dim("disconnect this folder")}`);
76910
+ out.push(` ${import_picocolors48.default.cyan("agent create")} ${import_picocolors48.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
76911
+ out.push(` ${import_picocolors48.default.cyan("agent pull")} ${import_picocolors48.default.dim("[<id>]")} ${import_picocolors48.default.dim("bring cloud changes into this folder (--force to override; --run-entrypoint to also execute the agent entrypoint)")}`);
76912
+ out.push(` ${import_picocolors48.default.cyan("agent push")} ${import_picocolors48.default.dim("send local changes to the cloud (--force to overwrite cloud-side conflicts with local)")}`);
76913
+ out.push(` ${import_picocolors48.default.cyan("agent unpack")} ${import_picocolors48.default.dim("install the claimed agent into a harness layout")}`);
76914
+ out.push(` ${import_picocolors48.default.cyan("link")} ${import_picocolors48.default.dim("attach this folder to an existing agent")}`);
76915
+ out.push(` ${import_picocolors48.default.cyan("agent status")} ${import_picocolors48.default.dim("show what would pull and what would push")}`);
76916
+ out.push(` ${import_picocolors48.default.cyan("agent env")} ${import_picocolors48.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
76917
+ out.push(` ${import_picocolors48.default.cyan("run")} ${import_picocolors48.default.dim("<cmd> [args...]")} ${import_picocolors48.default.dim("run <cmd> with secrets.env loaded into env")}`);
76918
+ out.push(` ${import_picocolors48.default.cyan("status")} ${import_picocolors48.default.dim("show what this folder is linked to")}`);
76919
+ out.push(` ${import_picocolors48.default.cyan("unlink")} ${import_picocolors48.default.dim("disconnect this folder")}`);
76920
+ out.push("");
76921
+ out.push(divider("TASKS"));
76922
+ out.push("");
76923
+ out.push(` ${import_picocolors48.default.cyan("task create")} ${import_picocolors48.default.dim("--message <text>")} ${import_picocolors48.default.dim("create a managed task and start its first run")}`);
76393
76924
  out.push("");
76394
76925
  out.push(divider("ORCHESTRATIONS"));
76395
76926
  out.push("");
76396
- out.push(` ${import_picocolors43.default.cyan("orchestration create")} ${import_picocolors43.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
76397
- out.push(` ${import_picocolors43.default.cyan("orchestration list")} ${import_picocolors43.default.dim("list orchestrations under a team")}`);
76398
- out.push(` ${import_picocolors43.default.cyan("orchestration pull")} ${import_picocolors43.default.dim("<id>")} ${import_picocolors43.default.dim("recursively fetch an orchestration + every member agent")}`);
76399
- out.push(` ${import_picocolors43.default.cyan("orchestration push")} ${import_picocolors43.default.dim("recursively push each member, then update the graph")}`);
76400
- out.push(` ${import_picocolors43.default.cyan("orchestration status")} ${import_picocolors43.default.dim("show what would push and what would pull")}`);
76927
+ out.push(` ${import_picocolors48.default.cyan("orchestration create")} ${import_picocolors48.default.dim("claim a local orchestration manifest and create it in the cloud")}`);
76928
+ out.push(` ${import_picocolors48.default.cyan("orchestration list")} ${import_picocolors48.default.dim("list orchestrations under a team")}`);
76929
+ out.push(` ${import_picocolors48.default.cyan("orchestration pull")} ${import_picocolors48.default.dim("<id>")} ${import_picocolors48.default.dim("recursively fetch an orchestration + every member agent")}`);
76930
+ out.push(` ${import_picocolors48.default.cyan("orchestration push")} ${import_picocolors48.default.dim("recursively push each member, then update the graph")}`);
76931
+ out.push(` ${import_picocolors48.default.cyan("orchestration status")} ${import_picocolors48.default.dim("show what would push and what would pull")}`);
76401
76932
  out.push("");
76402
76933
  out.push(divider("TEMPLATES"));
76403
76934
  out.push("");
76404
- out.push(` ${import_picocolors43.default.cyan("template pack")} ${import_picocolors43.default.dim("bundle the current agent into a template")}`);
76405
- out.push(` ${import_picocolors43.default.cyan("template publish")} ${import_picocolors43.default.dim("upload a template to the registry")}`);
76406
- out.push(` ${import_picocolors43.default.cyan("template search")} ${import_picocolors43.default.dim("[query]")} ${import_picocolors43.default.dim("search the registry")}`);
76407
- out.push(` ${import_picocolors43.default.cyan("template info")} ${import_picocolors43.default.dim("<creator/slug>")} ${import_picocolors43.default.dim("show registry details for a template")}`);
76408
- out.push(` ${import_picocolors43.default.cyan("template onboard")} ${import_picocolors43.default.dim("<creator/slug>")} ${import_picocolors43.default.dim("install (or refresh) a template")}`);
76409
- out.push(` ${import_picocolors43.default.cyan("template list")} ${import_picocolors43.default.dim("show installed templates")}`);
76410
- out.push(` ${import_picocolors43.default.cyan("template remove")} ${import_picocolors43.default.dim("<creator/slug>")} ${import_picocolors43.default.dim("uninstall a template")}`);
76935
+ out.push(` ${import_picocolors48.default.cyan("template pack")} ${import_picocolors48.default.dim("bundle the current agent into a template")}`);
76936
+ out.push(` ${import_picocolors48.default.cyan("template publish")} ${import_picocolors48.default.dim("upload a template to the registry")}`);
76937
+ out.push(` ${import_picocolors48.default.cyan("template search")} ${import_picocolors48.default.dim("[query]")} ${import_picocolors48.default.dim("search the registry")}`);
76938
+ out.push(` ${import_picocolors48.default.cyan("template info")} ${import_picocolors48.default.dim("<creator/slug>")} ${import_picocolors48.default.dim("show registry details for a template")}`);
76939
+ out.push(` ${import_picocolors48.default.cyan("template onboard")} ${import_picocolors48.default.dim("<creator/slug>")} ${import_picocolors48.default.dim("install (or refresh) a template")}`);
76940
+ out.push(` ${import_picocolors48.default.cyan("template list")} ${import_picocolors48.default.dim("show installed templates")}`);
76941
+ out.push(` ${import_picocolors48.default.cyan("template remove")} ${import_picocolors48.default.dim("<creator/slug>")} ${import_picocolors48.default.dim("uninstall a template")}`);
76411
76942
  out.push("");
76412
76943
  out.push(divider("SKILLS"));
76413
76944
  out.push("");
76414
- out.push(` ${import_picocolors43.default.cyan("skill add")} ${import_picocolors43.default.dim("<source>")} ${import_picocolors43.default.dim("install a skill (github / git / brainbase)")}`);
76415
- out.push(` ${import_picocolors43.default.cyan("skill list")} ${import_picocolors43.default.dim("show locally installed skills + their source")}`);
76416
- out.push(` ${import_picocolors43.default.cyan("skill update")} ${import_picocolors43.default.dim("<slug>")} ${import_picocolors43.default.dim("re-fetch a skill from its recorded source")}`);
76417
- out.push(` ${import_picocolors43.default.cyan("skill remove")} ${import_picocolors43.default.dim("<slug>")} ${import_picocolors43.default.dim("uninstall a skill")}`);
76418
- out.push(` ${import_picocolors43.default.cyan("skill search")} ${import_picocolors43.default.dim("[query]")} ${import_picocolors43.default.dim("search the brainbase skill registry")}`);
76419
- out.push(` ${import_picocolors43.default.cyan("skill info")} ${import_picocolors43.default.dim("<creator/slug>")} ${import_picocolors43.default.dim("show registry details for a skill")}`);
76420
- out.push(` ${import_picocolors43.default.cyan("skill publish")} ${import_picocolors43.default.dim("[dir]")} ${import_picocolors43.default.dim("publish a SKILL.md folder (defaults to .)")}`);
76945
+ out.push(` ${import_picocolors48.default.cyan("skill add")} ${import_picocolors48.default.dim("<source>")} ${import_picocolors48.default.dim("install a skill (github / git / brainbase)")}`);
76946
+ out.push(` ${import_picocolors48.default.cyan("skill list")} ${import_picocolors48.default.dim("show locally installed skills + their source")}`);
76947
+ out.push(` ${import_picocolors48.default.cyan("skill update")} ${import_picocolors48.default.dim("<slug>")} ${import_picocolors48.default.dim("re-fetch a skill from its recorded source")}`);
76948
+ out.push(` ${import_picocolors48.default.cyan("skill remove")} ${import_picocolors48.default.dim("<slug>")} ${import_picocolors48.default.dim("uninstall a skill")}`);
76949
+ out.push(` ${import_picocolors48.default.cyan("skill search")} ${import_picocolors48.default.dim("[query]")} ${import_picocolors48.default.dim("search the brainbase skill registry")}`);
76950
+ out.push(` ${import_picocolors48.default.cyan("skill info")} ${import_picocolors48.default.dim("<creator/slug>")} ${import_picocolors48.default.dim("show registry details for a skill")}`);
76951
+ out.push(` ${import_picocolors48.default.cyan("skill publish")} ${import_picocolors48.default.dim("[dir]")} ${import_picocolors48.default.dim("publish a SKILL.md folder (defaults to .)")}`);
76421
76952
  out.push("");
76422
76953
  out.push(divider("CLI TOKENS"));
76423
76954
  out.push("");
76424
- out.push(` ${import_picocolors43.default.cyan("token create")} ${import_picocolors43.default.dim("issue a long-lived CLI key for CI / scripts")}`);
76425
- out.push(` ${import_picocolors43.default.cyan("token list")} ${import_picocolors43.default.dim("show your active tokens")}`);
76426
- out.push(` ${import_picocolors43.default.cyan("token revoke")} ${import_picocolors43.default.dim("<id>")} ${import_picocolors43.default.dim("revoke a token")}`);
76955
+ out.push(` ${import_picocolors48.default.cyan("token create")} ${import_picocolors48.default.dim("issue a long-lived CLI key for CI / scripts")}`);
76956
+ out.push(` ${import_picocolors48.default.cyan("token list")} ${import_picocolors48.default.dim("show your active tokens")}`);
76957
+ out.push(` ${import_picocolors48.default.cyan("token revoke")} ${import_picocolors48.default.dim("<id>")} ${import_picocolors48.default.dim("revoke a token")}`);
76427
76958
  out.push("");
76428
76959
  out.push(divider("MCP"));
76429
76960
  out.push("");
76430
- out.push(` ${import_picocolors43.default.cyan("mcp check")} ${import_picocolors43.default.dim("[--json]")} ${import_picocolors43.default.dim("verify MCP server connectivity through the brainbase proxy (runs at sandbox bootstrap)")}`);
76961
+ out.push(` ${import_picocolors48.default.cyan("mcp check")} ${import_picocolors48.default.dim("[--json]")} ${import_picocolors48.default.dim("verify MCP server connectivity through the brainbase proxy (runs at sandbox bootstrap)")}`);
76431
76962
  out.push("");
76432
76963
  out.push(divider("FLAGS"));
76433
76964
  out.push("");
76434
- out.push(` ${import_picocolors43.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
76435
- out.push(` ${import_picocolors43.default.dim("--scope <s>")} force scope: global | project`);
76436
- out.push(` ${import_picocolors43.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
76437
- out.push(` ${import_picocolors43.default.dim("--agent <id>")} for link: attach this folder to an existing agent non-interactively`);
76438
- out.push(` ${import_picocolors43.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
76439
- out.push(` ${import_picocolors43.default.dim("--track")} for agent create: enable tracking non-interactively (off without a TTY)`);
76440
- out.push(` ${import_picocolors43.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
76441
- out.push(` ${import_picocolors43.default.dim("--all")} for template list: include installs from other folders`);
76442
- out.push(` ${import_picocolors43.default.dim("--web <url>")} for login: web app URL (default https://app.brainbaselabs.com)`);
76965
+ out.push(` ${import_picocolors48.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
76966
+ out.push(` ${import_picocolors48.default.dim("--scope <s>")} force scope: global | project`);
76967
+ out.push(` ${import_picocolors48.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
76968
+ out.push(` ${import_picocolors48.default.dim("--agent <id>")} for link/task create: use this agent id explicitly`);
76969
+ out.push(` ${import_picocolors48.default.dim("--message <text>")} for task create: required first user message`);
76970
+ out.push(` ${import_picocolors48.default.dim("--title <text>")} for task create: optional task title`);
76971
+ out.push(` ${import_picocolors48.default.dim("--model <id>")} for task create: optional model override`);
76972
+ out.push(` ${import_picocolors48.default.dim("--org <id-or-slug>")} pick the organization (team/agent list, agent create, orchestration create/list)`);
76973
+ out.push(` ${import_picocolors48.default.dim("--team <id>")} pick the team, same commands (works without --org)`);
76974
+ out.push(` ${import_picocolors48.default.dim("--json")} for team/agent list, task create, mcp check: machine-readable output`);
76975
+ out.push(` ${import_picocolors48.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
76976
+ out.push(` ${import_picocolors48.default.dim("--track")} for agent create: enable tracking non-interactively (off without a TTY)`);
76977
+ out.push(` ${import_picocolors48.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
76978
+ out.push(` ${import_picocolors48.default.dim("--all")} for template list: include installs from other folders`);
76979
+ out.push(` ${import_picocolors48.default.dim("--web <url>")} for login: web app URL (default https://app.brainbaselabs.com)`);
76443
76980
  out.push("");
76444
76981
  out.push(divider("ENV"));
76445
76982
  out.push("");
76446
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
76447
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
76448
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_CONTROL_PLANE_URL")} override the MAS control-plane host (uses /v2/cli)`);
76449
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_API_URL")} legacy KLS host override (uses /api/cli; proxy/registry fallback)`);
76450
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_PROXY_URL")} override the model-proxy URL used by harness traffic (default https://api.v1.brainbaselabs.com)`);
76451
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL (default https://api.v1.brainbaselabs.com)`);
76452
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
76453
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
76454
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_NON_INTERACTIVE")} force non-interactive mode — skip/auto-default prompts (CI & agents)`);
76455
- out.push(` ${import_picocolors43.default.dim("BRAINBASE_RUN_ENTRYPOINT")} =1 → agent pull executes the agent entrypoint (sandbox boots; or pass --run-entrypoint)`);
76983
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
76984
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
76985
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_CONTROL_PLANE_URL")} override the MAS host (/v2/cli; task create uses /v2/tasks)`);
76986
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_API_URL")} legacy KLS host override (uses /api/cli; proxy/registry fallback)`);
76987
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_PROXY_URL")} override the model-proxy URL used by harness traffic (default https://api.v1.brainbaselabs.com)`);
76988
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL (default https://api.v1.brainbaselabs.com)`);
76989
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
76990
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
76991
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_NON_INTERACTIVE")} force non-interactive mode — skip/auto-default prompts (CI & agents)`);
76992
+ out.push(` ${import_picocolors48.default.dim("BRAINBASE_RUN_ENTRYPOINT")} =1 → agent pull executes the agent entrypoint (sandbox boots; or pass --run-entrypoint)`);
76456
76993
  out.push("");
76457
76994
  out.push(divider("HARNESSES"));
76458
76995
  out.push("");
76459
- out.push(` ${import_picocolors43.default.dim("•")} ${import_picocolors43.default.bold("claude-code")} ${import_picocolors43.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
76460
- out.push(` ${import_picocolors43.default.dim("•")} ${import_picocolors43.default.bold("codex")} ${import_picocolors43.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
76461
- out.push(` ${import_picocolors43.default.dim("•")} ${import_picocolors43.default.bold("kafka")} ${import_picocolors43.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
76996
+ out.push(` ${import_picocolors48.default.dim("•")} ${import_picocolors48.default.bold("claude-code")} ${import_picocolors48.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
76997
+ out.push(` ${import_picocolors48.default.dim("•")} ${import_picocolors48.default.bold("codex")} ${import_picocolors48.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
76998
+ out.push(` ${import_picocolors48.default.dim("•")} ${import_picocolors48.default.bold("kafka")} ${import_picocolors48.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
76462
76999
  out.push("");
76463
77000
  console.log(out.join(`
76464
77001
  `));
@@ -76522,13 +77059,13 @@ async function requireAuth(cmd) {
76522
77059
  if (STORED_PAT_COMMANDS.has(cmd) && readToken())
76523
77060
  return;
76524
77061
  console.error("");
76525
- console.error(` ${brandTint("◆")} ${import_picocolors43.default.bold("brainbase")}`);
77062
+ console.error(` ${brandTint("◆")} ${import_picocolors48.default.bold("brainbase")}`);
76526
77063
  console.error("");
76527
- console.error(` ${import_picocolors43.default.red("✗")} You need to sign in to use ${import_picocolors43.default.bold("brainbase " + cmd)}.`);
77064
+ console.error(` ${import_picocolors48.default.red("✗")} You need to sign in to use ${import_picocolors48.default.bold("brainbase " + cmd)}.`);
76528
77065
  if (status.reason)
76529
- console.error(` ${import_picocolors43.default.dim(status.reason)}`);
77066
+ console.error(` ${import_picocolors48.default.dim(status.reason)}`);
76530
77067
  console.error("");
76531
- console.error(` Run ${import_picocolors43.default.cyan("brainbase login")} to connect this device.`);
77068
+ console.error(` Run ${import_picocolors48.default.cyan("brainbase login")} to connect this device.`);
76532
77069
  console.error("");
76533
77070
  process14.exit(1);
76534
77071
  }
@@ -76551,36 +77088,37 @@ async function main() {
76551
77088
  await runRun(cwd2, argv);
76552
77089
  return;
76553
77090
  }
76554
- const yes = hasFlag2(argv, "--yes", "-y");
76555
- const all = hasFlag2(argv, "--all");
76556
- const harness = getFlag(argv, "--harness");
76557
- const scopeFlag = getFlag(argv, "--scope");
76558
- const web = getFlag(argv, "--web");
76559
- const visibility = getFlag(argv, "--visibility");
76560
- const category = getFlag(argv, "--category");
76561
- const target = getFlag(argv, "--target");
76562
- const pageRaw = getFlag(argv, "--page");
77091
+ const sharedArgs = cmd === "task" ? [] : argv;
77092
+ const yes = hasFlag2(sharedArgs, "--yes", "-y");
77093
+ const all = hasFlag2(sharedArgs, "--all");
77094
+ const harness = getFlag(sharedArgs, "--harness");
77095
+ const scopeFlag = getFlag(sharedArgs, "--scope");
77096
+ const web = getFlag(sharedArgs, "--web");
77097
+ const visibility = getFlag(sharedArgs, "--visibility");
77098
+ const category = getFlag(sharedArgs, "--category");
77099
+ const target = getFlag(sharedArgs, "--target");
77100
+ const pageRaw = getFlag(sharedArgs, "--page");
76563
77101
  const page = pageRaw && /^\d+$/.test(pageRaw) ? Number(pageRaw) : undefined;
76564
- const asSlug = getFlag(argv, "--as");
76565
- const agentFlag = getFlag(argv, "--agent");
76566
- const shellFlag = getFlag(argv, "--shell");
76567
- const noTracking = hasFlag2(argv, "--no-tracking");
76568
- const track = hasFlag2(argv, "--track");
76569
- const forceFlag = hasFlag2(argv, "--force");
76570
- const runEntrypointFlag = hasFlag2(argv, "--run-entrypoint");
76571
- const graphOnlyFlag = hasFlag2(argv, "--graph-only");
76572
- const nameFlag = getFlag(argv, "--name");
76573
- const skillVersionFlag = getFlag(argv, "--skill-version");
76574
- const taglineFlag = getFlag(argv, "--tagline");
76575
- const orgIdFlag = getFlag(argv, "--org");
76576
- const teamIdFlag = getFlag(argv, "--team");
76577
- const fromFlags = getFlagAll(argv, "--from");
76578
- const toFlags = getFlagAll(argv, "--to");
76579
- const descriptionFlag = getFlag(argv, "--description");
76580
- const schemaFlag = getFlag(argv, "--schema");
76581
- const noPushFlag = hasFlag2(argv, "--no-push");
76582
- const jsonFlag = hasFlag2(argv, "--json");
76583
- const acpFlag = hasFlag2(argv, "--acp");
77102
+ const asSlug = getFlag(sharedArgs, "--as");
77103
+ const agentFlag = getFlag(sharedArgs, "--agent");
77104
+ const shellFlag = getFlag(sharedArgs, "--shell");
77105
+ const noTracking = hasFlag2(sharedArgs, "--no-tracking");
77106
+ const track = hasFlag2(sharedArgs, "--track");
77107
+ const forceFlag = hasFlag2(sharedArgs, "--force");
77108
+ const runEntrypointFlag = hasFlag2(sharedArgs, "--run-entrypoint");
77109
+ const graphOnlyFlag = hasFlag2(sharedArgs, "--graph-only");
77110
+ const nameFlag = getFlag(sharedArgs, "--name");
77111
+ const skillVersionFlag = getFlag(sharedArgs, "--skill-version");
77112
+ const taglineFlag = getFlag(sharedArgs, "--tagline");
77113
+ const orgIdFlag = getFlag(sharedArgs, "--org");
77114
+ const teamIdFlag = getFlag(sharedArgs, "--team");
77115
+ const fromFlags = getFlagAll(sharedArgs, "--from");
77116
+ const toFlags = getFlagAll(sharedArgs, "--to");
77117
+ const descriptionFlag = getFlag(sharedArgs, "--description");
77118
+ const schemaFlag = getFlag(sharedArgs, "--schema");
77119
+ const noPushFlag = hasFlag2(sharedArgs, "--no-push");
77120
+ const jsonFlag = hasFlag2(sharedArgs, "--json");
77121
+ const acpFlag = hasFlag2(sharedArgs, "--acp");
76584
77122
  ensureSkillResolversRegistered();
76585
77123
  await requireAuth(cmd);
76586
77124
  try {
@@ -76652,6 +77190,7 @@ async function main() {
76652
77190
  const sub = argv.shift();
76653
77191
  await runAgent(cwd2, sub, argv, {
76654
77192
  yes,
77193
+ json: jsonFlag,
76655
77194
  scope: scopeFlag,
76656
77195
  shell: shellFlag,
76657
77196
  harness,
@@ -76667,6 +77206,17 @@ async function main() {
76667
77206
  });
76668
77207
  break;
76669
77208
  }
77209
+ case "team":
77210
+ case "teams": {
77211
+ const sub = argv.shift();
77212
+ await runTeam(sub, argv, { orgId: orgIdFlag, json: jsonFlag });
77213
+ break;
77214
+ }
77215
+ case "task": {
77216
+ const sub = argv.shift();
77217
+ await runTask(cwd2, sub, argv);
77218
+ break;
77219
+ }
76670
77220
  case "orchestration":
76671
77221
  case "orch": {
76672
77222
  const sub = argv.shift();
@@ -76706,8 +77256,11 @@ async function main() {
76706
77256
  process14.exit(1);
76707
77257
  }
76708
77258
  } catch (err) {
76709
- console.error(import_picocolors43.default.red(`
77259
+ console.error(import_picocolors48.default.red(`
76710
77260
  ${err.message}`));
77261
+ if (err instanceof ApiError && err.status === 401) {
77262
+ console.error(` Run ${import_picocolors48.default.cyan("brainbase login")} to connect this device.`);
77263
+ }
76711
77264
  if (process14.env.BRAINBASE_DEBUG)
76712
77265
  console.error(err.stack);
76713
77266
  process14.exit(1);