@brainbase-labs/cli 0.4.2 → 0.5.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 (2) hide show
  1. package/dist/index.js +1376 -733
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -28564,7 +28564,7 @@ var require_jsx_dev_runtime = __commonJS((exports, module) => {
28564
28564
  });
28565
28565
 
28566
28566
  // src/index.ts
28567
- var import_picocolors38 = __toESM(require_picocolors(), 1);
28567
+ var import_picocolors40 = __toESM(require_picocolors(), 1);
28568
28568
  import process13 from "node:process";
28569
28569
  import fs50 from "node:fs";
28570
28570
 
@@ -50759,11 +50759,164 @@ async function runWhoami() {
50759
50759
  var import_picocolors22 = __toESM(require_picocolors(), 1);
50760
50760
 
50761
50761
  // src/core/link.ts
50762
+ import path43 from "node:path";
50763
+ import fs40 from "node:fs";
50764
+
50765
+ // src/core/agent-manifest.ts
50762
50766
  import path42 from "node:path";
50763
50767
  import fs39 from "node:fs";
50768
+ var import_yaml2 = __toESM(require_dist(), 1);
50769
+ var AGENT_MANIFEST_FILE = "brainbase.agent.yaml";
50770
+ var LEGACY_AGENT_MANIFEST_FILE = "brainbase.yaml";
50771
+ var DEFAULT_INSTRUCTIONS_FILE = "instructions.md";
50772
+ var DEFAULT_ENTRYPOINT_FILE = "entrypoint.sh";
50773
+ var REGISTRY_SOURCE_RE = /^registry:(?:([a-z0-9_-]+)\/)?([a-z0-9_-]+)(?:@(.+))?$/i;
50774
+ function parseSkillSource2(raw) {
50775
+ if (!raw || typeof raw !== "string") {
50776
+ throw new Error("Skill source must be a non-empty string");
50777
+ }
50778
+ const m3 = raw.match(REGISTRY_SOURCE_RE);
50779
+ if (m3) {
50780
+ return {
50781
+ kind: "registry",
50782
+ ...m3[1] ? { creator: m3[1] } : {},
50783
+ slug: m3[2],
50784
+ version: m3[3]
50785
+ };
50786
+ }
50787
+ if (raw.startsWith("./") || raw.startsWith("../") || raw.startsWith("/")) {
50788
+ return { kind: "local", path: raw };
50789
+ }
50790
+ throw new Error(`Unrecognized skill source "${raw}". Expected "registry:creator/slug[@version]", "registry:slug", or a relative path starting with "./".`);
50791
+ }
50792
+ var AgentMetaSchema = exports_external.object({
50793
+ name: exports_external.string().min(1),
50794
+ tagline: exports_external.string().optional()
50795
+ });
50796
+ var InstructionsSchema = exports_external.object({
50797
+ file: exports_external.string().min(1).optional(),
50798
+ text: exports_external.string().optional()
50799
+ }).refine((v3) => v3.file !== undefined || v3.text !== undefined, {
50800
+ message: "instructions must set either `file` or `text`"
50801
+ });
50802
+ var EntrypointSchema = exports_external.object({
50803
+ file: exports_external.string().min(1).optional(),
50804
+ commands: exports_external.array(exports_external.string().min(1)).optional(),
50805
+ text: exports_external.string().optional()
50806
+ }).refine((v3) => {
50807
+ const set = [v3.file, v3.commands, v3.text].filter((x3) => x3 !== undefined);
50808
+ return set.length === 1;
50809
+ }, {
50810
+ message: "entrypoint must set exactly one of `file`, `commands`, or `text`"
50811
+ });
50812
+ var SkillEntrySchema = exports_external.object({
50813
+ source: exports_external.string().min(1)
50814
+ });
50815
+ var McpEntrySchema = exports_external.object({
50816
+ name: exports_external.string().min(1),
50817
+ url: exports_external.string().optional(),
50818
+ command: exports_external.string().optional(),
50819
+ args: exports_external.array(exports_external.string()).optional(),
50820
+ env: exports_external.record(exports_external.string()).optional(),
50821
+ headers: exports_external.record(exports_external.string()).optional(),
50822
+ is_enabled: exports_external.boolean().optional()
50823
+ });
50824
+ var AgentManifestSchema = exports_external.object({
50825
+ schema: exports_external.literal(1),
50826
+ id: exports_external.string().min(1).optional(),
50827
+ harness: exports_external.string().min(1).optional(),
50828
+ agent: AgentMetaSchema,
50829
+ instructions: InstructionsSchema.optional(),
50830
+ entrypoint: EntrypointSchema.optional(),
50831
+ skills: exports_external.array(SkillEntrySchema).default([]),
50832
+ mcp: exports_external.array(McpEntrySchema).default([]),
50833
+ commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
50834
+ hooks: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
50835
+ files: exports_external.array(exports_external.record(exports_external.unknown())).optional()
50836
+ });
50837
+ function manifestPath(cwd2) {
50838
+ return path42.join(cwd2, AGENT_MANIFEST_FILE);
50839
+ }
50840
+ function existingManifestPath(cwd2) {
50841
+ const newPath = path42.join(cwd2, AGENT_MANIFEST_FILE);
50842
+ if (fs39.existsSync(newPath))
50843
+ return newPath;
50844
+ const legacy = path42.join(cwd2, LEGACY_AGENT_MANIFEST_FILE);
50845
+ if (fs39.existsSync(legacy))
50846
+ return legacy;
50847
+ return null;
50848
+ }
50849
+ function hasManifest(cwd2) {
50850
+ return existingManifestPath(cwd2) !== null;
50851
+ }
50852
+ function readManifest(cwd2) {
50853
+ const p2 = existingManifestPath(cwd2);
50854
+ if (!p2)
50855
+ return null;
50856
+ const raw = fs39.readFileSync(p2, "utf8");
50857
+ let parsed;
50858
+ try {
50859
+ parsed = import_yaml2.default.parse(raw);
50860
+ } catch (err) {
50861
+ throw new Error(`${path42.basename(p2)} is not valid YAML: ${err.message}`);
50862
+ }
50863
+ const result = AgentManifestSchema.safeParse(parsed);
50864
+ if (!result.success) {
50865
+ throw new Error(`${path42.basename(p2)} is invalid: ${result.error.issues.map((i) => `${i.path.join(".") || "(root)"} — ${i.message}`).join("; ")}`);
50866
+ }
50867
+ return result.data;
50868
+ }
50869
+ function writeManifest(cwd2, manifest) {
50870
+ const doc = new import_yaml2.default.Document;
50871
+ doc.contents = manifest;
50872
+ doc.commentBefore = ` brainbase.agent.yaml — declarative agent manifest.
50873
+ ` + " Committed to source control. Edit by hand, then `brainbase agent push`.";
50874
+ const out = String(doc);
50875
+ fs39.writeFileSync(manifestPath(cwd2), out, "utf8");
50876
+ }
50877
+ function resolveInstructionsPath(cwd2, manifest) {
50878
+ if (!manifest.instructions?.file)
50879
+ return null;
50880
+ return path42.resolve(cwd2, manifest.instructions.file);
50881
+ }
50882
+ function readInstructions(cwd2, manifest) {
50883
+ if (!manifest.instructions)
50884
+ return null;
50885
+ if (typeof manifest.instructions.text === "string") {
50886
+ return manifest.instructions.text;
50887
+ }
50888
+ const p2 = resolveInstructionsPath(cwd2, manifest);
50889
+ if (!p2 || !fs39.existsSync(p2))
50890
+ return null;
50891
+ return fs39.readFileSync(p2, "utf8");
50892
+ }
50893
+ function resolveEntrypoint(cwd2, manifest) {
50894
+ const ep = manifest.entrypoint;
50895
+ if (!ep)
50896
+ return null;
50897
+ if (typeof ep.text === "string")
50898
+ return ep.text;
50899
+ if (Array.isArray(ep.commands)) {
50900
+ if (ep.commands.length === 0)
50901
+ return null;
50902
+ return ["set -euo pipefail", ...ep.commands].join(`
50903
+ `) + `
50904
+ `;
50905
+ }
50906
+ if (typeof ep.file === "string") {
50907
+ const p2 = path42.resolve(cwd2, ep.file);
50908
+ if (!fs39.existsSync(p2))
50909
+ return null;
50910
+ return fs39.readFileSync(p2, "utf8");
50911
+ }
50912
+ return null;
50913
+ }
50914
+
50915
+ // src/core/link.ts
50764
50916
  var LINK_DIR = ".brainbase";
50765
- var LINK_FILE = "link.json";
50917
+ var STATE_FILE = "state.json";
50766
50918
  var SYNC_STATE_FILE = "sync-state.json";
50919
+ var LEGACY_LINK_FILE = "link.json";
50767
50920
  var TrackingSchema = exports_external.object({
50768
50921
  harness: exports_external.string(),
50769
50922
  key_id: exports_external.string(),
@@ -50786,6 +50939,16 @@ var LinkSchema = exports_external.object({
50786
50939
  harness: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
50787
50940
  tracking: TrackingSchema.nullish().transform((v3) => v3 ?? undefined)
50788
50941
  });
50942
+ var LinkStateSchema = exports_external.object({
50943
+ schemaVersion: exports_external.literal(1),
50944
+ org_id: exports_external.string().default(""),
50945
+ team_id: exports_external.string().default(""),
50946
+ slug: exports_external.string().default(""),
50947
+ url: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
50948
+ linked_at: exports_external.string(),
50949
+ linked_by: exports_external.string().nullish().transform((v3) => v3 ?? undefined),
50950
+ tracking: TrackingSchema.nullish().transform((v3) => v3 ?? undefined)
50951
+ });
50789
50952
  var SyncedComponentSchema = exports_external.object({
50790
50953
  type: exports_external.string(),
50791
50954
  slug: exports_external.string(),
@@ -50795,7 +50958,8 @@ var SyncedComponentSchema = exports_external.object({
50795
50958
  });
50796
50959
  var AgentMetaSnapshotSchema = exports_external.object({
50797
50960
  name: exports_external.string(),
50798
- tagline: exports_external.string().optional()
50961
+ tagline: exports_external.string().optional(),
50962
+ entrypoint: exports_external.string().optional()
50799
50963
  });
50800
50964
  var SyncStateSchema = exports_external.object({
50801
50965
  schemaVersion: exports_external.literal(1),
@@ -50805,39 +50969,157 @@ var SyncStateSchema = exports_external.object({
50805
50969
  components: exports_external.array(SyncedComponentSchema),
50806
50970
  agentMeta: AgentMetaSnapshotSchema.optional()
50807
50971
  });
50808
- function linkPath(cwd2) {
50809
- return path42.join(cwd2, LINK_DIR, LINK_FILE);
50972
+ function statePath(cwd2) {
50973
+ return path43.join(cwd2, LINK_DIR, STATE_FILE);
50810
50974
  }
50811
50975
  function syncStatePath(cwd2) {
50812
- return path42.join(cwd2, LINK_DIR, SYNC_STATE_FILE);
50976
+ return path43.join(cwd2, LINK_DIR, SYNC_STATE_FILE);
50977
+ }
50978
+ function legacyLinkPath(cwd2) {
50979
+ return path43.join(cwd2, LINK_DIR, LEGACY_LINK_FILE);
50980
+ }
50981
+ function readState(cwd2) {
50982
+ const p2 = statePath(cwd2);
50983
+ if (exists(p2)) {
50984
+ try {
50985
+ return LinkStateSchema.parse(readJson(p2));
50986
+ } catch {
50987
+ return null;
50988
+ }
50989
+ }
50990
+ const legacy = legacyLinkPath(cwd2);
50991
+ if (exists(legacy)) {
50992
+ try {
50993
+ const raw = readJson(legacy);
50994
+ const lifted = {
50995
+ schemaVersion: 1,
50996
+ org_id: String(raw.org_id ?? ""),
50997
+ team_id: String(raw.team_id ?? ""),
50998
+ slug: String(raw.slug ?? ""),
50999
+ url: typeof raw.url === "string" ? raw.url : undefined,
51000
+ linked_at: typeof raw.linked_at === "string" ? raw.linked_at : new Date().toISOString(),
51001
+ linked_by: typeof raw.linked_by === "string" ? raw.linked_by : undefined,
51002
+ tracking: (() => {
51003
+ try {
51004
+ return TrackingSchema.parse(raw.tracking);
51005
+ } catch {
51006
+ return;
51007
+ }
51008
+ })()
51009
+ };
51010
+ try {
51011
+ ensureDir(path43.join(cwd2, LINK_DIR));
51012
+ writeJson(statePath(cwd2), lifted);
51013
+ ensureGitignore(cwd2);
51014
+ } catch {}
51015
+ return lifted;
51016
+ } catch {
51017
+ return null;
51018
+ }
51019
+ }
51020
+ return null;
51021
+ }
51022
+ function writeState(cwd2, state) {
51023
+ ensureDir(path43.join(cwd2, LINK_DIR));
51024
+ writeJson(statePath(cwd2), state);
51025
+ ensureGitignore(cwd2);
50813
51026
  }
50814
51027
  function readLink(cwd2) {
50815
- const p2 = linkPath(cwd2);
50816
- if (!exists(p2))
50817
- return null;
51028
+ let manifest = null;
50818
51029
  try {
50819
- return LinkSchema.parse(readJson(p2));
51030
+ manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
50820
51031
  } catch {
50821
- return null;
51032
+ manifest = null;
51033
+ }
51034
+ const state = readState(cwd2);
51035
+ if (manifest?.id) {
51036
+ return {
51037
+ schemaVersion: 1,
51038
+ agent_id: manifest.id,
51039
+ org_id: state?.org_id ?? "",
51040
+ team_id: state?.team_id ?? "",
51041
+ slug: state?.slug ?? "",
51042
+ name: manifest.agent.name,
51043
+ tagline: manifest.agent.tagline,
51044
+ url: state?.url,
51045
+ linked_at: state?.linked_at ?? new Date().toISOString(),
51046
+ linked_by: state?.linked_by,
51047
+ harness: manifest.harness,
51048
+ tracking: state?.tracking
51049
+ };
51050
+ }
51051
+ const legacy = legacyLinkPath(cwd2);
51052
+ if (exists(legacy)) {
51053
+ try {
51054
+ return LinkSchema.parse(readJson(legacy));
51055
+ } catch {
51056
+ return null;
51057
+ }
50822
51058
  }
51059
+ return null;
50823
51060
  }
50824
51061
  function writeLink(cwd2, link2) {
50825
- ensureDir(path42.join(cwd2, LINK_DIR));
50826
- const clean = {};
50827
- for (const [k3, v3] of Object.entries(link2)) {
50828
- if (v3 !== null && v3 !== undefined)
50829
- clean[k3] = v3;
51062
+ let manifest;
51063
+ try {
51064
+ manifest = readManifest(cwd2) ?? {
51065
+ schema: 1,
51066
+ agent: { name: link2.name },
51067
+ skills: [],
51068
+ mcp: []
51069
+ };
51070
+ } catch {
51071
+ manifest = {
51072
+ schema: 1,
51073
+ agent: { name: link2.name },
51074
+ skills: [],
51075
+ mcp: []
51076
+ };
51077
+ }
51078
+ manifest.id = link2.agent_id;
51079
+ if (link2.harness)
51080
+ manifest.harness = link2.harness;
51081
+ manifest.agent.name = link2.name;
51082
+ if (link2.tagline)
51083
+ manifest.agent.tagline = link2.tagline;
51084
+ else
51085
+ delete manifest.agent.tagline;
51086
+ writeManifest(cwd2, manifest);
51087
+ const state = {
51088
+ schemaVersion: 1,
51089
+ org_id: link2.org_id,
51090
+ team_id: link2.team_id,
51091
+ slug: link2.slug,
51092
+ url: link2.url,
51093
+ linked_at: link2.linked_at,
51094
+ linked_by: link2.linked_by,
51095
+ tracking: link2.tracking
51096
+ };
51097
+ writeState(cwd2, state);
51098
+ const legacy = legacyLinkPath(cwd2);
51099
+ if (exists(legacy)) {
51100
+ try {
51101
+ fs40.rmSync(legacy);
51102
+ } catch {}
50830
51103
  }
50831
- writeJson(linkPath(cwd2), clean);
50832
- ensureGitignore(cwd2);
50833
51104
  }
50834
51105
  function clearLink(cwd2) {
50835
- const p2 = linkPath(cwd2);
51106
+ try {
51107
+ const m3 = hasManifest(cwd2) ? readManifest(cwd2) : null;
51108
+ if (m3) {
51109
+ delete m3.id;
51110
+ delete m3.harness;
51111
+ writeManifest(cwd2, m3);
51112
+ }
51113
+ } catch {}
51114
+ const p2 = statePath(cwd2);
50836
51115
  if (exists(p2))
50837
- fs39.rmSync(p2);
51116
+ fs40.rmSync(p2);
50838
51117
  const sp = syncStatePath(cwd2);
50839
51118
  if (exists(sp))
50840
- fs39.rmSync(sp);
51119
+ fs40.rmSync(sp);
51120
+ const legacy = legacyLinkPath(cwd2);
51121
+ if (exists(legacy))
51122
+ fs40.rmSync(legacy);
50841
51123
  }
50842
51124
  function readSyncState(cwd2) {
50843
51125
  const p2 = syncStatePath(cwd2);
@@ -50850,22 +51132,22 @@ function readSyncState(cwd2) {
50850
51132
  }
50851
51133
  }
50852
51134
  function writeSyncState(cwd2, state) {
50853
- ensureDir(path42.join(cwd2, LINK_DIR));
51135
+ ensureDir(path43.join(cwd2, LINK_DIR));
50854
51136
  writeJson(syncStatePath(cwd2), state);
50855
51137
  ensureGitignore(cwd2);
50856
51138
  }
50857
51139
  function ensureGitignore(cwd2) {
50858
- const ignorePath = path42.join(cwd2, LINK_DIR, ".gitignore");
50859
- const desired = `${SYNC_STATE_FILE}
50860
- `;
51140
+ const ignorePath = path43.join(cwd2, LINK_DIR, ".gitignore");
51141
+ const desired = ["*", `!.gitignore`, ""].join(`
51142
+ `);
50861
51143
  try {
50862
51144
  if (!exists(ignorePath)) {
50863
- fs39.writeFileSync(ignorePath, desired);
51145
+ fs40.writeFileSync(ignorePath, desired);
50864
51146
  return;
50865
51147
  }
50866
- const current = fs39.readFileSync(ignorePath, "utf8");
50867
- if (!current.split(/\r?\n/).some((l2) => l2.trim() === SYNC_STATE_FILE)) {
50868
- fs39.writeFileSync(ignorePath, current.endsWith(`
51148
+ const current = fs40.readFileSync(ignorePath, "utf8");
51149
+ if (!current.split(/\r?\n/).some((l2) => l2.trim() === "*")) {
51150
+ fs40.writeFileSync(ignorePath, current.endsWith(`
50869
51151
  `) ? current + desired : current + `
50870
51152
  ` + desired);
50871
51153
  }
@@ -50873,15 +51155,15 @@ function ensureGitignore(cwd2) {
50873
51155
  }
50874
51156
 
50875
51157
  // src/core/route-adapters.ts
50876
- import path43 from "node:path";
51158
+ import path44 from "node:path";
50877
51159
  import os10 from "node:os";
50878
- import fs40 from "node:fs";
51160
+ import fs41 from "node:fs";
50879
51161
  var CLAUDE_ENV_KEYS = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN"];
50880
51162
  function claudeSettingsPath(cwd2) {
50881
- return path43.join(cwd2, ".claude", "settings.json");
51163
+ return path44.join(cwd2, ".claude", "settings.json");
50882
51164
  }
50883
51165
  function claudeUserConfigPath() {
50884
- return path43.join(os10.homedir(), ".claude.json");
51166
+ return path44.join(os10.homedir(), ".claude.json");
50885
51167
  }
50886
51168
  function ensureClaudeOnboarded() {
50887
51169
  const file = claudeUserConfigPath();
@@ -50905,7 +51187,7 @@ var claudeRouteAdapter = {
50905
51187
  settings.env = { ...settings.env ?? {} };
50906
51188
  settings.env.ANTHROPIC_BASE_URL = target.apiBase;
50907
51189
  settings.env.ANTHROPIC_AUTH_TOKEN = target.apiKey;
50908
- ensureDir(path43.dirname(file));
51190
+ ensureDir(path44.dirname(file));
50909
51191
  writeJson(file, settings);
50910
51192
  const notes = [];
50911
51193
  if (ensureClaudeOnboarded()) {
@@ -50932,11 +51214,11 @@ var claudeRouteAdapter = {
50932
51214
  delete settings.env;
50933
51215
  }
50934
51216
  if (snap && !snap.fileExisted && Object.keys(settings).length === 0) {
50935
- fs40.rmSync(file);
50936
- const dir = path43.dirname(file);
51217
+ fs41.rmSync(file);
51218
+ const dir = path44.dirname(file);
50937
51219
  try {
50938
- if (fs40.readdirSync(dir).length === 0)
50939
- fs40.rmdirSync(dir);
51220
+ if (fs41.readdirSync(dir).length === 0)
51221
+ fs41.rmdirSync(dir);
50940
51222
  } catch {}
50941
51223
  return;
50942
51224
  }
@@ -50946,20 +51228,20 @@ var claudeRouteAdapter = {
50946
51228
  var CODEX_PROVIDER_KEY = "brainbase";
50947
51229
  var CODEX_AUTH_HEADER = "Authorization";
50948
51230
  function codexConfigPath(cwd2) {
50949
- return path43.join(cwd2, ".codex", "config.toml");
51231
+ return path44.join(cwd2, ".codex", "config.toml");
50950
51232
  }
50951
51233
  function readCodexConfig2(file) {
50952
51234
  if (!exists(file))
50953
51235
  return {};
50954
51236
  try {
50955
- return parse(fs40.readFileSync(file, "utf8"));
51237
+ return parse(fs41.readFileSync(file, "utf8"));
50956
51238
  } catch {
50957
51239
  return {};
50958
51240
  }
50959
51241
  }
50960
51242
  function writeCodexConfig2(file, value) {
50961
- ensureDir(path43.dirname(file));
50962
- fs40.writeFileSync(file, stringify(value) + `
51243
+ ensureDir(path44.dirname(file));
51244
+ fs41.writeFileSync(file, stringify(value) + `
50963
51245
  `);
50964
51246
  }
50965
51247
  function ensureV1(base2) {
@@ -51015,11 +51297,11 @@ var codexRouteAdapter = {
51015
51297
  }
51016
51298
  }
51017
51299
  if (snap && !snap.fileExisted && Object.keys(cfg).length === 0) {
51018
- fs40.rmSync(file);
51019
- const dir = path43.dirname(file);
51300
+ fs41.rmSync(file);
51301
+ const dir = path44.dirname(file);
51020
51302
  try {
51021
- if (fs40.readdirSync(dir).length === 0)
51022
- fs40.rmdirSync(dir);
51303
+ if (fs41.readdirSync(dir).length === 0)
51304
+ fs41.rmdirSync(dir);
51023
51305
  } catch {}
51024
51306
  return;
51025
51307
  }
@@ -51309,8 +51591,8 @@ async function runUnlink(cwd2, args) {
51309
51591
  }
51310
51592
 
51311
51593
  // src/cli/sync.ts
51312
- import path44 from "node:path";
51313
- import fs41 from "node:fs";
51594
+ import path45 from "node:path";
51595
+ import fs42 from "node:fs";
51314
51596
  import os11 from "node:os";
51315
51597
  import crypto3 from "node:crypto";
51316
51598
  var import_picocolors24 = __toESM(require_picocolors(), 1);
@@ -51504,7 +51786,7 @@ async function runSync(cwd2, args) {
51504
51786
  type: c2.type,
51505
51787
  slug: c2.slug,
51506
51788
  scope,
51507
- rootDir: path44.join(stageRoot, c2.type, c2.slug),
51789
+ rootDir: path45.join(stageRoot, c2.type, c2.slug),
51508
51790
  description: c2.description,
51509
51791
  meta: c2.meta,
51510
51792
  payload: c2.meta?.mcp,
@@ -51553,11 +51835,11 @@ async function runSync(cwd2, args) {
51553
51835
  if (!exists(filePath))
51554
51836
  continue;
51555
51837
  try {
51556
- const stat = fs41.statSync(filePath);
51838
+ const stat = fs42.statSync(filePath);
51557
51839
  if (stat.isDirectory())
51558
- fs41.rmSync(filePath, { recursive: true, force: true });
51840
+ fs42.rmSync(filePath, { recursive: true, force: true });
51559
51841
  else
51560
- fs41.rmSync(filePath);
51842
+ fs42.rmSync(filePath);
51561
51843
  } catch (err) {
51562
51844
  f2.warn(`Failed to remove ${filePath}: ${err.message}`);
51563
51845
  }
@@ -51595,7 +51877,7 @@ async function runSync(cwd2, args) {
51595
51877
  $e(`Synced ${link2.name} to revision ${manifest.revision}.`);
51596
51878
  } finally {
51597
51879
  try {
51598
- fs41.rmSync(stageRoot, { recursive: true, force: true });
51880
+ fs42.rmSync(stageRoot, { recursive: true, force: true });
51599
51881
  } catch {}
51600
51882
  }
51601
51883
  }
@@ -51643,14 +51925,14 @@ function computeLocalHash(paths) {
51643
51925
  if (!exists(filePath))
51644
51926
  return null;
51645
51927
  try {
51646
- const stat = fs41.statSync(filePath);
51928
+ const stat = fs42.statSync(filePath);
51647
51929
  if (stat.isFile()) {
51648
51930
  h2.update("F " + filePath + " ");
51649
- h2.update(fs41.readFileSync(filePath));
51931
+ h2.update(fs42.readFileSync(filePath));
51650
51932
  h2.update(`
51651
51933
  `);
51652
51934
  } else if (stat.isDirectory()) {
51653
- for (const name of fs41.readdirSync(filePath).sort()) {
51935
+ for (const name of fs42.readdirSync(filePath).sort()) {
51654
51936
  h2.update("E " + name + `
51655
51937
  `);
51656
51938
  }
@@ -51662,14 +51944,14 @@ function computeLocalHash(paths) {
51662
51944
  return h2.digest("hex");
51663
51945
  }
51664
51946
  function stageManifest(components) {
51665
- const root = fs41.mkdtempSync(path44.join(os11.tmpdir(), "brainbase-sync-"));
51947
+ const root = fs42.mkdtempSync(path45.join(os11.tmpdir(), "brainbase-sync-"));
51666
51948
  for (const c2 of components) {
51667
- const compDir = path44.join(root, c2.type, c2.slug);
51949
+ const compDir = path45.join(root, c2.type, c2.slug);
51668
51950
  ensureDir(compDir);
51669
51951
  for (const f4 of c2.files) {
51670
- const target = path44.join(compDir, f4.path);
51671
- ensureDir(path44.dirname(target));
51672
- fs41.writeFileSync(target, f4.content);
51952
+ const target = path45.join(compDir, f4.path);
51953
+ ensureDir(path45.dirname(target));
51954
+ fs42.writeFileSync(target, f4.content);
51673
51955
  }
51674
51956
  }
51675
51957
  return root;
@@ -51683,111 +51965,15 @@ function runHarnessInstall(harnessId, components, opts, agentName) {
51683
51965
  }
51684
51966
 
51685
51967
  // src/cli/agent.ts
51686
- var import_picocolors30 = __toESM(require_picocolors(), 1);
51968
+ var import_picocolors32 = __toESM(require_picocolors(), 1);
51687
51969
 
51688
51970
  // src/cli/agent-pull.ts
51971
+ import { spawn as spawn2 } from "node:child_process";
51689
51972
  import path48 from "node:path";
51690
51973
  import fs45 from "node:fs";
51691
51974
  import os12 from "node:os";
51692
51975
  var import_picocolors25 = __toESM(require_picocolors(), 1);
51693
51976
 
51694
- // src/core/agent-manifest.ts
51695
- import path45 from "node:path";
51696
- import fs42 from "node:fs";
51697
- var import_yaml2 = __toESM(require_dist(), 1);
51698
- var AGENT_MANIFEST_FILE = "brainbase.yaml";
51699
- var DEFAULT_INSTRUCTIONS_FILE = "instructions.md";
51700
- var REGISTRY_SOURCE_RE = /^registry:(?:([a-z0-9_-]+)\/)?([a-z0-9_-]+)(?:@(.+))?$/i;
51701
- function parseSkillSource2(raw) {
51702
- if (!raw || typeof raw !== "string") {
51703
- throw new Error("Skill source must be a non-empty string");
51704
- }
51705
- const m3 = raw.match(REGISTRY_SOURCE_RE);
51706
- if (m3) {
51707
- return {
51708
- kind: "registry",
51709
- ...m3[1] ? { creator: m3[1] } : {},
51710
- slug: m3[2],
51711
- version: m3[3]
51712
- };
51713
- }
51714
- if (raw.startsWith("./") || raw.startsWith("../") || raw.startsWith("/")) {
51715
- return { kind: "local", path: raw };
51716
- }
51717
- throw new Error(`Unrecognized skill source "${raw}". Expected "registry:creator/slug[@version]", "registry:slug", or a relative path starting with "./".`);
51718
- }
51719
- var AgentMetaSchema = exports_external.object({
51720
- name: exports_external.string().min(1),
51721
- tagline: exports_external.string().optional()
51722
- });
51723
- var InstructionsSchema = exports_external.object({
51724
- file: exports_external.string().min(1)
51725
- });
51726
- var SkillEntrySchema = exports_external.object({
51727
- source: exports_external.string().min(1)
51728
- });
51729
- var McpEntrySchema = exports_external.object({
51730
- name: exports_external.string().min(1),
51731
- url: exports_external.string().optional(),
51732
- command: exports_external.string().optional(),
51733
- args: exports_external.array(exports_external.string()).optional(),
51734
- env: exports_external.record(exports_external.string()).optional(),
51735
- headers: exports_external.record(exports_external.string()).optional(),
51736
- is_enabled: exports_external.boolean().optional()
51737
- });
51738
- var AgentManifestSchema = exports_external.object({
51739
- schema: exports_external.literal(1),
51740
- agent: AgentMetaSchema,
51741
- instructions: InstructionsSchema.optional(),
51742
- skills: exports_external.array(SkillEntrySchema).default([]),
51743
- mcp: exports_external.array(McpEntrySchema).default([]),
51744
- commands: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
51745
- hooks: exports_external.array(exports_external.record(exports_external.unknown())).optional(),
51746
- files: exports_external.array(exports_external.record(exports_external.unknown())).optional()
51747
- });
51748
- function manifestPath(cwd2) {
51749
- return path45.join(cwd2, AGENT_MANIFEST_FILE);
51750
- }
51751
- function hasManifest(cwd2) {
51752
- return fs42.existsSync(manifestPath(cwd2));
51753
- }
51754
- function readManifest(cwd2) {
51755
- const p2 = manifestPath(cwd2);
51756
- if (!fs42.existsSync(p2))
51757
- return null;
51758
- const raw = fs42.readFileSync(p2, "utf8");
51759
- let parsed;
51760
- try {
51761
- parsed = import_yaml2.default.parse(raw);
51762
- } catch (err) {
51763
- throw new Error(`${AGENT_MANIFEST_FILE} is not valid YAML: ${err.message}`);
51764
- }
51765
- const result = AgentManifestSchema.safeParse(parsed);
51766
- if (!result.success) {
51767
- throw new Error(`${AGENT_MANIFEST_FILE} is invalid: ${result.error.issues.map((i) => `${i.path.join(".") || "(root)"} — ${i.message}`).join("; ")}`);
51768
- }
51769
- return result.data;
51770
- }
51771
- function writeManifest(cwd2, manifest) {
51772
- const doc = new import_yaml2.default.Document;
51773
- doc.contents = manifest;
51774
- doc.commentBefore = ` brainbase.yaml — declarative agent manifest.
51775
- ` + " Committed to source control. Edit by hand, then `brainbase agent push`.";
51776
- const out = String(doc);
51777
- fs42.writeFileSync(manifestPath(cwd2), out, "utf8");
51778
- }
51779
- function resolveInstructionsPath(cwd2, manifest) {
51780
- if (!manifest.instructions)
51781
- return null;
51782
- return path45.resolve(cwd2, manifest.instructions.file);
51783
- }
51784
- function readInstructions(cwd2, manifest) {
51785
- const p2 = resolveInstructionsPath(cwd2, manifest);
51786
- if (!p2 || !fs42.existsSync(p2))
51787
- return null;
51788
- return fs42.readFileSync(p2, "utf8");
51789
- }
51790
-
51791
51977
  // src/core/agent-diff.ts
51792
51978
  import path46 from "node:path";
51793
51979
  import fs43 from "node:fs";
@@ -52123,26 +52309,27 @@ function diffSecrets(local, cloud) {
52123
52309
  // src/cli/agent-pull.ts
52124
52310
  async function runAgentPull(cwd2, args) {
52125
52311
  banner("agent pull — bring cloud changes into this folder");
52126
- const link2 = readLink(cwd2);
52127
- if (!link2) {
52128
- f2.warn("This folder is not linked to any agent.");
52129
- f2.info(`Run ${import_picocolors25.default.cyan("brainbase link")} first.`);
52312
+ const resolution = resolveTargetAgentId(cwd2, args);
52313
+ if (!resolution)
52130
52314
  return;
52131
- }
52315
+ const { agentId, override } = resolution;
52132
52316
  const sp = de();
52133
- sp.start(`Fetching ${link2.name}…`);
52317
+ sp.start("Fetching agent…");
52318
+ let cloudAgent;
52134
52319
  let cloud;
52135
52320
  try {
52136
- cloud = await api.getAgentManifest(link2.agent_id);
52321
+ cloudAgent = await api.getAgent(agentId);
52322
+ cloud = await api.getAgentManifest(agentId);
52137
52323
  sp.stop(`Cloud revision ${cloud.revision}.`);
52138
52324
  } catch (err) {
52139
52325
  sp.stop("Failed.");
52140
52326
  handleApiError2(err);
52141
52327
  return;
52142
52328
  }
52143
- const lock = readSyncState(cwd2);
52144
- const localManifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
52145
- const localComponents = localManifest ? readLocalComponents(cwd2, localManifest) : [];
52329
+ const harness = normalizeHarnessId(cloudAgent.harness ?? "claude-code");
52330
+ const existingManifest = !override && hasManifest(cwd2) ? safeReadManifest(cwd2) : null;
52331
+ const lock = override ? null : readSyncState(cwd2);
52332
+ const localComponents = existingManifest ? readLocalComponents(cwd2, existingManifest) : [];
52146
52333
  const rows = threeWayDiff({
52147
52334
  local: localComponents,
52148
52335
  lock: lock?.components ?? [],
@@ -52167,7 +52354,11 @@ async function runAgentPull(cwd2, args) {
52167
52354
  break;
52168
52355
  case "modified-both":
52169
52356
  case "modified-local":
52170
- conflicts.push(r2);
52357
+ if (override) {
52358
+ toInstallKeys.add(r2.key);
52359
+ } else {
52360
+ conflicts.push(r2);
52361
+ }
52171
52362
  break;
52172
52363
  }
52173
52364
  }
@@ -52191,11 +52382,12 @@ async function runAgentPull(cwd2, args) {
52191
52382
  const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
52192
52383
  const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
52193
52384
  const needMemoryMcpInstall = !cloudHasMemoryMcp;
52194
- if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && !needOrchestrationMcpInstall && !needMemoryMcpInstall) {
52385
+ if (toInstallKeys.size === 0 && toRemoveKeys.size === 0 && !needOrchestrationMcpInstall && !needMemoryMcpInstall && !override) {
52195
52386
  f2.info(`You're up to date.`);
52196
- writeSyncState(cwd2, buildLockFromCloud(link2.agent_id, cloud, lock));
52197
- if (!localManifest) {
52198
- writeBrainbaseYamlFromCloud(cwd2, link2, cloud);
52387
+ writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
52388
+ writeSyncState(cwd2, buildLockFromCloud(agentId, cloud, lock, cloudAgent));
52389
+ if (!existingManifest) {
52390
+ writeManifest(cwd2, mergeManifest(cwd2, null, cloud, cloudAgent, harness));
52199
52391
  f2.info(`Wrote ${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)}.`);
52200
52392
  }
52201
52393
  return;
@@ -52225,20 +52417,20 @@ async function runAgentPull(cwd2, args) {
52225
52417
  });
52226
52418
  }
52227
52419
  await showResultCard({
52228
- title: "PULL",
52229
- tone: "info",
52230
- subtitle: `updates for ${link2.name}`,
52420
+ title: override ? "PULL (FORCE)" : "PULL",
52421
+ tone: override ? "warn" : "info",
52422
+ subtitle: `updates for ${cloudAgent.name}`,
52231
52423
  rows: resultRows
52232
52424
  });
52233
52425
  if (!args.yes) {
52234
- const ok = await se({ message: "Apply these changes?", initialValue: true });
52426
+ const msg = override ? "Apply these changes? Local edits to overlapping components will be discarded." : "Apply these changes?";
52427
+ const ok = await se({ message: msg, initialValue: true });
52235
52428
  if (!ensureNotCancelled(ok)) {
52236
52429
  $e("Aborted.");
52237
52430
  return;
52238
52431
  }
52239
52432
  }
52240
- const adapterId = link2.harness ?? link2.tracking?.harness ?? "claude-code";
52241
- const adapter = getAdapter(adapterId);
52433
+ const adapter = getAdapter(harness);
52242
52434
  const scope = args.scope ?? "project";
52243
52435
  const installComponents = cloud.components.filter((c2) => toInstallKeys.has(`${c2.type}/${c2.slug}`));
52244
52436
  const stageRoot = stageManifestComponents(installComponents);
@@ -52270,7 +52462,7 @@ async function runAgentPull(cwd2, args) {
52270
52462
  resolveConflict: async (_c) => "overwrite",
52271
52463
  resolveSecret: async () => null
52272
52464
  };
52273
- const result = await runHarnessInstall2(adapter.id, toInstall, opts, link2.name);
52465
+ const result = await runHarnessInstall2(adapter.id, toInstall, opts, cloudAgent.name);
52274
52466
  installSpinner.stop("Applied.");
52275
52467
  for (const o2 of result.installed) {
52276
52468
  justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
@@ -52298,8 +52490,10 @@ async function runAgentPull(cwd2, args) {
52298
52490
  }
52299
52491
  }
52300
52492
  materializeInstructions(cwd2, cloud, toInstallKeys, keepLocalKeys);
52301
- const yaml = mergeManifest(cwd2, localManifest, cloud, link2);
52493
+ materializeEntrypoint(cwd2, cloudAgent.entrypoint ?? "", existingManifest);
52494
+ const yaml = mergeManifest(cwd2, existingManifest, cloud, cloudAgent, harness);
52302
52495
  writeManifest(cwd2, yaml);
52496
+ writeLink(cwd2, buildLinkFromAgent(cloudAgent, harness, readLink(cwd2)));
52303
52497
  const lockComponents = buildLockComponents({
52304
52498
  cloud,
52305
52499
  prevLock: lock,
@@ -52309,21 +52503,64 @@ async function runAgentPull(cwd2, args) {
52309
52503
  });
52310
52504
  const newState = {
52311
52505
  schemaVersion: 1,
52312
- agent_id: link2.agent_id,
52506
+ agent_id: agentId,
52313
52507
  revision: cloud.revision,
52314
52508
  synced_at: new Date().toISOString(),
52315
52509
  components: lockComponents,
52316
- agentMeta: { name: link2.name, tagline: link2.tagline }
52510
+ agentMeta: {
52511
+ name: cloudAgent.name,
52512
+ tagline: cloudAgent.tagline,
52513
+ ...cloudAgent.entrypoint ? { entrypoint: cloudAgent.entrypoint } : {}
52514
+ }
52317
52515
  };
52318
52516
  writeSyncState(cwd2, newState);
52319
- await pullSecrets(cwd2, link2.agent_id);
52320
- $e(`Pulled ${link2.name} at revision ${cloud.revision}.`);
52517
+ await pullSecrets(cwd2, agentId);
52518
+ await runEntrypointIfPresent(cwd2, yaml);
52519
+ $e(`Pulled ${cloudAgent.name} at revision ${cloud.revision}.`);
52321
52520
  } finally {
52322
52521
  try {
52323
52522
  fs45.rmSync(stageRoot, { recursive: true, force: true });
52324
52523
  } catch {}
52325
52524
  }
52326
52525
  }
52526
+ function resolveTargetAgentId(cwd2, args) {
52527
+ const arg = args.agentIdArg?.trim() || undefined;
52528
+ let manifest = null;
52529
+ try {
52530
+ manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
52531
+ } catch (err) {
52532
+ f2.error(err.message);
52533
+ return null;
52534
+ }
52535
+ const manifestId = manifest?.id;
52536
+ if (arg && manifestId && arg !== manifestId) {
52537
+ if (!args.force) {
52538
+ f2.error(`This folder is already linked to a different agent (${import_picocolors25.default.dim(manifestId)}).`);
52539
+ f2.info(`Run ${import_picocolors25.default.cyan(`brainbase agent pull ${arg} --force`)} to override. ` + import_picocolors25.default.yellow("This will overwrite brainbase.agent.yaml and any local progress will be lost."));
52540
+ return null;
52541
+ }
52542
+ return { agentId: arg, override: true };
52543
+ }
52544
+ if (arg)
52545
+ return { agentId: arg, override: false };
52546
+ if (manifestId)
52547
+ return { agentId: manifestId, override: false };
52548
+ if (manifest) {
52549
+ f2.error(`${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors25.default.cyan("id")}).`);
52550
+ f2.info(`Run ${import_picocolors25.default.cyan("brainbase agent create")} to create a new agent from this manifest, ` + `or ${import_picocolors25.default.cyan("brainbase agent pull <id>")} to pull an existing one.`);
52551
+ } else {
52552
+ f2.error(`No ${import_picocolors25.default.bold(AGENT_MANIFEST_FILE)} here and no ${import_picocolors25.default.cyan("<id>")} given.`);
52553
+ f2.info(`Run ${import_picocolors25.default.cyan("brainbase agent pull <id>")} to pull an existing agent into this folder.`);
52554
+ }
52555
+ return null;
52556
+ }
52557
+ function safeReadManifest(cwd2) {
52558
+ try {
52559
+ return readManifest(cwd2);
52560
+ } catch {
52561
+ return null;
52562
+ }
52563
+ }
52327
52564
  function skillSourceFromMeta(c2) {
52328
52565
  if (c2.type !== "skill")
52329
52566
  return;
@@ -52373,7 +52610,7 @@ function materializeInstructions(cwd2, cloud, toInstall, keepLocal) {
52373
52610
  fs45.writeFileSync(path48.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
52374
52611
  }
52375
52612
  }
52376
- function mergeManifest(cwd2, prev, cloud, link2) {
52613
+ function mergeManifest(cwd2, prev, cloud, cloudAgent, harness) {
52377
52614
  const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
52378
52615
  const localDecl = prev?.skills.find((s3) => {
52379
52616
  try {
@@ -52396,7 +52633,18 @@ function mergeManifest(cwd2, prev, cloud, link2) {
52396
52633
  }
52397
52634
  return { source: `registry:${c2.slug}` };
52398
52635
  });
52399
- const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
52636
+ const cloudInstrComp = cloud.components.find((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
52637
+ const instructions = cloudInstrComp ? prev?.instructions?.text !== undefined ? { text: cloudInstrComp.files[0].content } : { file: prev?.instructions?.file ?? DEFAULT_INSTRUCTIONS_FILE } : undefined;
52638
+ const cloudEntrypoint = (cloudAgent.entrypoint ?? "").trim();
52639
+ let entrypoint;
52640
+ if (cloudEntrypoint.length > 0) {
52641
+ if (prev?.entrypoint?.commands)
52642
+ entrypoint = { commands: prev.entrypoint.commands };
52643
+ else if (prev?.entrypoint?.text !== undefined)
52644
+ entrypoint = { text: cloudAgent.entrypoint };
52645
+ else
52646
+ entrypoint = { file: prev?.entrypoint?.file ?? DEFAULT_ENTRYPOINT_FILE };
52647
+ }
52400
52648
  const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
52401
52649
  const payload = (c2.meta ?? {}).mcp ?? {};
52402
52650
  const entry = { name: c2.slug };
@@ -52416,17 +52664,32 @@ function mergeManifest(cwd2, prev, cloud, link2) {
52416
52664
  });
52417
52665
  return {
52418
52666
  schema: 1,
52667
+ id: cloudAgent.id,
52668
+ harness,
52419
52669
  agent: {
52420
- name: link2.name,
52421
- ...link2.tagline ? { tagline: link2.tagline } : {}
52670
+ name: cloudAgent.name,
52671
+ ...cloudAgent.tagline ? { tagline: cloudAgent.tagline } : {}
52422
52672
  },
52423
- ...hasInstructions ? {
52424
- instructions: { file: prev?.instructions?.file ?? DEFAULT_INSTRUCTIONS_FILE }
52425
- } : {},
52673
+ ...instructions ? { instructions } : {},
52674
+ ...entrypoint ? { entrypoint } : {},
52426
52675
  skills,
52427
52676
  mcp
52428
52677
  };
52429
52678
  }
52679
+ function materializeEntrypoint(cwd2, cloudEntrypoint, prev) {
52680
+ if (!cloudEntrypoint.trim())
52681
+ return;
52682
+ if (prev?.entrypoint?.commands)
52683
+ return;
52684
+ if (prev?.entrypoint?.text !== undefined)
52685
+ return;
52686
+ const filename = prev?.entrypoint?.file ?? DEFAULT_ENTRYPOINT_FILE;
52687
+ const target = path48.resolve(cwd2, filename);
52688
+ fs45.writeFileSync(target, cloudEntrypoint, "utf8");
52689
+ try {
52690
+ fs45.chmodSync(target, 493);
52691
+ } catch {}
52692
+ }
52430
52693
  function parseSourceLoose(raw) {
52431
52694
  const m3 = raw.match(/^registry:[a-z0-9_-]+\/([a-z0-9_-]+)/i);
52432
52695
  if (m3)
@@ -52468,7 +52731,7 @@ function buildLockComponents(input) {
52468
52731
  }
52469
52732
  return out;
52470
52733
  }
52471
- function buildLockFromCloud(agent_id, cloud, prev) {
52734
+ function buildLockFromCloud(agent_id, cloud, prev, cloudAgent) {
52472
52735
  return {
52473
52736
  schemaVersion: 1,
52474
52737
  agent_id,
@@ -52480,11 +52743,73 @@ function buildLockFromCloud(agent_id, cloud, prev) {
52480
52743
  hash: c2.hash,
52481
52744
  installedPaths: []
52482
52745
  })),
52483
- agentMeta: prev?.agentMeta
52746
+ agentMeta: cloudAgent ? {
52747
+ name: cloudAgent.name,
52748
+ tagline: cloudAgent.tagline,
52749
+ ...cloudAgent.entrypoint ? { entrypoint: cloudAgent.entrypoint } : {}
52750
+ } : prev?.agentMeta
52751
+ };
52752
+ }
52753
+ function buildLinkFromAgent(agent, harness, prev) {
52754
+ return {
52755
+ schemaVersion: 1,
52756
+ agent_id: agent.id,
52757
+ org_id: agent.org_id ?? prev?.org_id ?? "",
52758
+ team_id: agent.team_id ?? prev?.team_id ?? "",
52759
+ slug: agent.slug,
52760
+ name: agent.name,
52761
+ tagline: agent.tagline,
52762
+ url: agent.url,
52763
+ linked_at: prev?.linked_at ?? new Date().toISOString(),
52764
+ linked_by: prev?.linked_by,
52765
+ harness,
52766
+ tracking: prev?.tracking
52484
52767
  };
52485
52768
  }
52486
- function writeBrainbaseYamlFromCloud(cwd2, link2, cloud) {
52487
- writeManifest(cwd2, mergeManifest(cwd2, null, cloud, link2));
52769
+ async function runEntrypointIfPresent(cwd2, manifest) {
52770
+ if (!manifest.entrypoint)
52771
+ return;
52772
+ const body = resolveEntrypoint(cwd2, manifest);
52773
+ if (body === null || !body.trim())
52774
+ return;
52775
+ const stateDir = path48.join(cwd2, LINK_DIR);
52776
+ ensureDir(stateDir);
52777
+ const scriptPath = path48.join(stateDir, "entrypoint.sh");
52778
+ const logPath = path48.join(stateDir, "entrypoint.log");
52779
+ fs45.writeFileSync(scriptPath, body, "utf8");
52780
+ try {
52781
+ fs45.chmodSync(scriptPath, 493);
52782
+ } catch {}
52783
+ f2.info(`Running entrypoint ${import_picocolors25.default.dim(`(${path48.relative(cwd2, scriptPath)})`)}`);
52784
+ const secrets = readLocalSecrets(cwd2);
52785
+ const env3 = { ...process.env, ...secrets };
52786
+ const logStream = fs45.createWriteStream(logPath, { flags: "w" });
52787
+ const exitCode = await new Promise((resolve) => {
52788
+ const child = spawn2("bash", [scriptPath], {
52789
+ cwd: cwd2,
52790
+ env: env3,
52791
+ stdio: ["ignore", "pipe", "pipe"]
52792
+ });
52793
+ child.stdout?.on("data", (chunk) => {
52794
+ process.stdout.write(chunk);
52795
+ logStream.write(chunk);
52796
+ });
52797
+ child.stderr?.on("data", (chunk) => {
52798
+ process.stderr.write(chunk);
52799
+ logStream.write(chunk);
52800
+ });
52801
+ child.on("error", (err) => {
52802
+ f2.warn(`entrypoint failed to start: ${err.message}`);
52803
+ resolve(null);
52804
+ });
52805
+ child.on("exit", (code) => resolve(code));
52806
+ });
52807
+ await new Promise((resolve) => logStream.end(resolve));
52808
+ if (exitCode === 0) {
52809
+ f2.info("Entrypoint completed.");
52810
+ } else if (exitCode === null) {} else {
52811
+ f2.warn(`Entrypoint exited ${exitCode} — continuing. Log at ${import_picocolors25.default.dim(path48.relative(cwd2, logPath))}.`);
52812
+ }
52488
52813
  }
52489
52814
  async function pullSecrets(cwd2, agentId) {
52490
52815
  let cloudSecrets;
@@ -52518,6 +52843,8 @@ function handleApiError2(err) {
52518
52843
  if (err instanceof ApiError) {
52519
52844
  if (err.status === 401) {
52520
52845
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
52846
+ } else if (err.status === 404) {
52847
+ f2.error(`Agent not found, or you don't have access. Double-check the id.`);
52521
52848
  } else {
52522
52849
  f2.error(err.message);
52523
52850
  }
@@ -52527,18 +52854,96 @@ function handleApiError2(err) {
52527
52854
  }
52528
52855
 
52529
52856
  // src/cli/agent-push.ts
52857
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
52858
+
52859
+ // src/core/agent-outgoing.ts
52530
52860
  var import_picocolors26 = __toESM(require_picocolors(), 1);
52861
+ async function buildOutgoingComponents(cwd2, manifest, cloud) {
52862
+ const out = [];
52863
+ if (manifest.instructions) {
52864
+ if (manifest.instructions.text !== undefined && manifest.instructions.file !== undefined) {
52865
+ f2.error(`instructions block sets both ${import_picocolors26.default.cyan("text")} and ${import_picocolors26.default.cyan("file")} — pick one.`);
52866
+ return null;
52867
+ }
52868
+ const body = readInstructions(cwd2, manifest);
52869
+ if (body === null) {
52870
+ if (manifest.instructions.file) {
52871
+ f2.error(`Instructions file ${import_picocolors26.default.bold(manifest.instructions.file)} not found.`);
52872
+ } else {
52873
+ f2.error("Instructions block is empty.");
52874
+ }
52875
+ return null;
52876
+ }
52877
+ if (body.trim()) {
52878
+ const fileName = manifest.instructions.file ?? "instructions.md";
52879
+ const fileHash2 = hashString(body);
52880
+ const file = {
52881
+ path: fileName,
52882
+ content: body,
52883
+ hash: fileHash2
52884
+ };
52885
+ out.push({
52886
+ type: "instruction",
52887
+ slug: "agent-instructions",
52888
+ description: "Agent instructions",
52889
+ hash: componentHashFromFileHashes([fileHash2]),
52890
+ files: [file],
52891
+ meta: { source: "global_prompt" }
52892
+ });
52893
+ }
52894
+ }
52895
+ for (const entry of manifest.skills) {
52896
+ const parsed = parseSkillSource2(entry.source);
52897
+ if (parsed.kind === "local") {
52898
+ f2.error(`Skill ${import_picocolors26.default.bold(entry.source)} is a local-authored skill. Local skill push isn't supported yet — publish it to the registry first (\`brainbase skill publish\`).`);
52899
+ return null;
52900
+ }
52901
+ const cloudMatch = cloud?.components.find((c2) => c2.type === "skill" && c2.slug === parsed.slug);
52902
+ out.push({
52903
+ type: "skill",
52904
+ slug: parsed.slug,
52905
+ hash: cloudMatch?.hash ?? "",
52906
+ files: [],
52907
+ meta: {
52908
+ name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
52909
+ ...parsed.version ? { version: parsed.version } : {}
52910
+ }
52911
+ });
52912
+ }
52913
+ for (const entry of manifest.mcp ?? []) {
52914
+ if (!entry.url && !entry.command) {
52915
+ f2.error(`MCP ${import_picocolors26.default.bold(entry.name)} needs either ${import_picocolors26.default.cyan("url")} or ${import_picocolors26.default.cyan("command")}.`);
52916
+ return null;
52917
+ }
52918
+ const payload = {};
52919
+ if (entry.url !== undefined)
52920
+ payload.url = entry.url;
52921
+ if (entry.command !== undefined)
52922
+ payload.command = entry.command;
52923
+ if (entry.args !== undefined)
52924
+ payload.args = entry.args;
52925
+ if (entry.env !== undefined)
52926
+ payload.env = entry.env;
52927
+ if (entry.headers !== undefined)
52928
+ payload.headers = entry.headers;
52929
+ payload.is_enabled = entry.is_enabled ?? true;
52930
+ out.push({
52931
+ type: "mcp",
52932
+ slug: entry.name,
52933
+ hash: "",
52934
+ files: [],
52935
+ meta: { mcp: payload }
52936
+ });
52937
+ }
52938
+ return out;
52939
+ }
52940
+
52941
+ // src/cli/agent-push.ts
52531
52942
  async function runAgentPush(cwd2, args) {
52532
52943
  banner("agent push — send your local changes to the cloud");
52533
- const link2 = readLink(cwd2);
52534
- if (!link2) {
52535
- f2.warn("This folder is not linked to any agent.");
52536
- f2.info(`Run ${import_picocolors26.default.cyan("brainbase link")} first.`);
52537
- return;
52538
- }
52539
52944
  if (!hasManifest(cwd2)) {
52540
- f2.warn(`No ${import_picocolors26.default.bold(AGENT_MANIFEST_FILE)} here.`);
52541
- f2.info(`Run ${import_picocolors26.default.cyan("brainbase agent pull")} to materialize the manifest before pushing.`);
52945
+ f2.warn(`No ${import_picocolors27.default.bold(AGENT_MANIFEST_FILE)} here.`);
52946
+ f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent create")} to claim a new agent from a manifest, ` + `or ${import_picocolors27.default.cyan("brainbase agent pull <id>")} to pull an existing one.`);
52542
52947
  return;
52543
52948
  }
52544
52949
  let manifest;
@@ -52548,11 +52953,17 @@ async function runAgentPush(cwd2, args) {
52548
52953
  f2.error(err.message);
52549
52954
  return;
52550
52955
  }
52956
+ if (!manifest.id) {
52957
+ f2.warn(`${import_picocolors27.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors27.default.cyan("id")}). Nothing to push to.`);
52958
+ f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent create")} first — that creates the cloud agent and stamps an id here.`);
52959
+ return;
52960
+ }
52961
+ const agentId = manifest.id;
52551
52962
  const sp = de();
52552
- sp.start(`Fetching cloud state for ${link2.name}…`);
52963
+ sp.start(`Fetching cloud state…`);
52553
52964
  let cloud;
52554
52965
  try {
52555
- cloud = await api.getAgentManifest(link2.agent_id);
52966
+ cloud = await api.getAgentManifest(agentId);
52556
52967
  sp.stop(`Cloud revision ${cloud.revision}.`);
52557
52968
  } catch (err) {
52558
52969
  sp.stop("Failed.");
@@ -52565,17 +52976,42 @@ async function runAgentPush(cwd2, args) {
52565
52976
  lock: lock?.components ?? [],
52566
52977
  cloud: cloud.components
52567
52978
  });
52568
- const meta = diffAgentMeta(manifest.agent, lock?.agentMeta, { name: link2.name, tagline: link2.tagline });
52979
+ let cloudMeta = lock?.agentMeta;
52980
+ if (!cloudMeta) {
52981
+ try {
52982
+ const a3 = await api.getAgent(agentId);
52983
+ cloudMeta = { name: a3.name, tagline: a3.tagline, entrypoint: a3.entrypoint };
52984
+ } catch {}
52985
+ }
52986
+ const meta = diffAgentMeta(manifest.agent, lock?.agentMeta, cloudMeta);
52987
+ let resolvedEntrypoint;
52988
+ if (manifest.entrypoint) {
52989
+ const body = resolveEntrypoint(cwd2, manifest);
52990
+ if (body === null) {
52991
+ if (manifest.entrypoint.file) {
52992
+ f2.error(`Entrypoint file ${import_picocolors27.default.bold(manifest.entrypoint.file)} not found.`);
52993
+ } else {
52994
+ f2.error("Entrypoint block is empty.");
52995
+ }
52996
+ return;
52997
+ }
52998
+ resolvedEntrypoint = body;
52999
+ } else {
53000
+ if ((lock?.agentMeta?.entrypoint ?? "") !== "") {
53001
+ resolvedEntrypoint = "";
53002
+ }
53003
+ }
53004
+ const entrypointChanged = resolvedEntrypoint !== undefined && resolvedEntrypoint !== (lock?.agentMeta?.entrypoint ?? "");
52569
53005
  for (const r2 of rows) {
52570
53006
  if (r2.type !== "instruction" && r2.type !== "skill" && r2.type !== "mcp") {
52571
- f2.error(`Component ${fmtType(r2.type)} ${import_picocolors26.default.bold(r2.slug)} can't be pushed yet — the server accepts instructions, skills, and mcps in this version.`);
53007
+ f2.error(`Component ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)} can't be pushed yet — the server accepts instructions, skills, and mcps in this version.`);
52572
53008
  return;
52573
53009
  }
52574
53010
  }
52575
53011
  for (const entry of manifest.skills) {
52576
53012
  const parsed = parseSkillSource2(entry.source);
52577
53013
  if (parsed.kind === "local") {
52578
- f2.error(`Skill ${import_picocolors26.default.bold(entry.source)} is a local-authored skill. Local skill push isn't supported yet — publish it to the registry first (\`brainbase skill publish\`).`);
53014
+ f2.error(`Skill ${import_picocolors27.default.bold(entry.source)} is a local-authored skill. Local skill push isn't supported yet — publish it to the registry first (\`brainbase skill publish\`).`);
52579
53015
  return;
52580
53016
  }
52581
53017
  }
@@ -52599,22 +53035,22 @@ async function runAgentPush(cwd2, args) {
52599
53035
  break;
52600
53036
  }
52601
53037
  }
52602
- if (!meta.localChanged && toSend.length === 0 && conflicts.length === 0) {
53038
+ if (!meta.localChanged && !entrypointChanged && toSend.length === 0 && conflicts.length === 0) {
52603
53039
  f2.info("Nothing to push — local is in sync with the cloud.");
52604
53040
  return;
52605
53041
  }
52606
53042
  if (conflicts.length > 0) {
52607
53043
  f2.error(`Cannot push: ${conflicts.length} component${conflicts.length === 1 ? "" : "s"} changed both locally and on the cloud:`);
52608
53044
  for (const r2 of conflicts) {
52609
- console.error(` ${import_picocolors26.default.red("!")} ${fmtType(r2.type)} ${import_picocolors26.default.bold(r2.slug)}`);
53045
+ console.error(` ${import_picocolors27.default.red("!")} ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)}`);
52610
53046
  }
52611
- f2.info(`Run ${import_picocolors26.default.cyan("brainbase agent pull")} first to reconcile, then push again.`);
53047
+ f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent pull")} first to reconcile, then push again.`);
52612
53048
  return;
52613
53049
  }
52614
53050
  if (upstreamOnly.length > 0 && !args.yes) {
52615
53051
  f2.warn(`Cloud has ${upstreamOnly.length} change${upstreamOnly.length === 1 ? "" : "s"} you don't have locally:`);
52616
53052
  for (const r2 of upstreamOnly) {
52617
- console.warn(` ${import_picocolors26.default.cyan("←")} ${fmtType(r2.type)} ${import_picocolors26.default.bold(r2.slug)} ${import_picocolors26.default.dim(`(${r2.status})`)}`);
53053
+ console.warn(` ${import_picocolors27.default.cyan("←")} ${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)} ${import_picocolors27.default.dim(`(${r2.status})`)}`);
52618
53054
  }
52619
53055
  f2.info(`If you push now, your push targets revision ${cloud.revision} and may race. Consider \`brainbase agent pull\` first.`);
52620
53056
  }
@@ -52626,6 +53062,13 @@ async function runAgentPush(cwd2, args) {
52626
53062
  text: "name/tagline"
52627
53063
  });
52628
53064
  }
53065
+ if (entrypointChanged) {
53066
+ resultRows.push({
53067
+ type: "upd",
53068
+ label: "entrypoint",
53069
+ text: resolvedEntrypoint === "" ? "cleared" : "updated"
53070
+ });
53071
+ }
52629
53072
  if (toSend.length) {
52630
53073
  resultRows.push({
52631
53074
  type: "add",
@@ -52636,7 +53079,7 @@ async function runAgentPush(cwd2, args) {
52636
53079
  await showResultCard({
52637
53080
  title: "PUSH",
52638
53081
  tone: "info",
52639
- subtitle: `${link2.name} ← local`,
53082
+ subtitle: `${manifest.agent.name} ← local`,
52640
53083
  rows: resultRows
52641
53084
  });
52642
53085
  if (!args.yes) {
@@ -52646,14 +53089,19 @@ async function runAgentPush(cwd2, args) {
52646
53089
  return;
52647
53090
  }
52648
53091
  }
52649
- if (meta.localChanged) {
53092
+ if (meta.localChanged || entrypointChanged) {
52650
53093
  const metaSpinner = de();
52651
53094
  metaSpinner.start("Updating agent metadata…");
52652
53095
  try {
52653
- await api.updateAgent(link2.agent_id, {
52654
- name: manifest.agent.name,
52655
- tagline: manifest.agent.tagline ?? ""
52656
- });
53096
+ const update = {};
53097
+ if (meta.localChanged) {
53098
+ update.name = manifest.agent.name;
53099
+ update.tagline = manifest.agent.tagline ?? "";
53100
+ }
53101
+ if (entrypointChanged) {
53102
+ update.entrypoint = resolvedEntrypoint;
53103
+ }
53104
+ await api.updateAgent(agentId, update);
52657
53105
  metaSpinner.stop("Metadata updated.");
52658
53106
  } catch (err) {
52659
53107
  metaSpinner.stop("Failed.");
@@ -52667,7 +53115,7 @@ async function runAgentPush(cwd2, args) {
52667
53115
  pushSpinner.start("Pushing…");
52668
53116
  let updatedCloud;
52669
53117
  try {
52670
- updatedCloud = await api.pushAgentManifest(link2.agent_id, {
53118
+ updatedCloud = await api.pushAgentManifest(agentId, {
52671
53119
  components: outgoing,
52672
53120
  base_revision: cloud.revision
52673
53121
  });
@@ -52676,14 +53124,22 @@ async function runAgentPush(cwd2, args) {
52676
53124
  pushSpinner.stop("Failed.");
52677
53125
  if (err instanceof ApiError && err.status === 409) {
52678
53126
  f2.error(err.message);
52679
- f2.info(`Run ${import_picocolors26.default.cyan("brainbase agent pull")} and try again.`);
53127
+ f2.info(`Run ${import_picocolors27.default.cyan("brainbase agent pull")} and try again.`);
52680
53128
  return;
52681
53129
  }
52682
53130
  return handleApiError3(err);
52683
53131
  }
53132
+ const existing = readLink(cwd2);
53133
+ if (existing) {
53134
+ writeLink(cwd2, {
53135
+ ...existing,
53136
+ name: manifest.agent.name,
53137
+ tagline: manifest.agent.tagline
53138
+ });
53139
+ }
52684
53140
  const newLock = {
52685
53141
  schemaVersion: 1,
52686
- agent_id: link2.agent_id,
53142
+ agent_id: agentId,
52687
53143
  revision: updatedCloud.revision,
52688
53144
  synced_at: new Date().toISOString(),
52689
53145
  components: updatedCloud.components.map((c2) => {
@@ -52695,7 +53151,7 @@ async function runAgentPush(cwd2, args) {
52695
53151
  return false;
52696
53152
  }
52697
53153
  })?.source;
52698
- const prior = lock?.components.find((pc25) => pc25.type === c2.type && pc25.slug === c2.slug);
53154
+ const prior = lock?.components.find((pc26) => pc26.type === c2.type && pc26.slug === c2.slug);
52699
53155
  return {
52700
53156
  type: c2.type,
52701
53157
  slug: c2.slug,
@@ -52704,11 +53160,15 @@ async function runAgentPush(cwd2, args) {
52704
53160
  ...decl ? { source: decl } : {}
52705
53161
  };
52706
53162
  }),
52707
- agentMeta: { name: manifest.agent.name, tagline: manifest.agent.tagline }
53163
+ agentMeta: {
53164
+ name: manifest.agent.name,
53165
+ tagline: manifest.agent.tagline,
53166
+ entrypoint: resolvedEntrypoint !== undefined ? resolvedEntrypoint : lock?.agentMeta?.entrypoint
53167
+ }
52708
53168
  };
52709
53169
  writeSyncState(cwd2, newLock);
52710
- await pushSecrets(cwd2, link2.agent_id);
52711
- $e(`Pushed ${link2.name} at revision ${updatedCloud.revision}.`);
53170
+ await pushSecrets(cwd2, agentId);
53171
+ $e(`Pushed ${manifest.agent.name} at revision ${updatedCloud.revision}.`);
52712
53172
  }
52713
53173
  async function pushSecrets(cwd2, agentId) {
52714
53174
  const localSecrets = readLocalSecrets(cwd2);
@@ -52736,74 +53196,6 @@ async function pushSecrets(cwd2, agentId) {
52736
53196
  handleApiError3(err);
52737
53197
  }
52738
53198
  }
52739
- async function buildOutgoingComponents(cwd2, manifest, cloud) {
52740
- const out = [];
52741
- if (manifest.instructions) {
52742
- const body = readInstructions(cwd2, manifest);
52743
- if (body === null) {
52744
- f2.error(`Instructions file ${import_picocolors26.default.bold(manifest.instructions.file)} not found.`);
52745
- return null;
52746
- }
52747
- if (body.trim()) {
52748
- const fileHash2 = hashString(body);
52749
- const file = {
52750
- path: manifest.instructions.file,
52751
- content: body,
52752
- hash: fileHash2
52753
- };
52754
- out.push({
52755
- type: "instruction",
52756
- slug: "agent-instructions",
52757
- description: "Agent instructions",
52758
- hash: componentHashFromFileHashes([fileHash2]),
52759
- files: [file],
52760
- meta: { source: "global_prompt" }
52761
- });
52762
- }
52763
- }
52764
- for (const entry of manifest.skills) {
52765
- const parsed = parseSkillSource2(entry.source);
52766
- if (parsed.kind !== "registry")
52767
- continue;
52768
- const cloudMatch = cloud.components.find((c2) => c2.type === "skill" && c2.slug === parsed.slug);
52769
- out.push({
52770
- type: "skill",
52771
- slug: parsed.slug,
52772
- hash: cloudMatch?.hash ?? "",
52773
- files: [],
52774
- meta: {
52775
- name: parsed.creator ? `${parsed.creator}/${parsed.slug}` : parsed.slug,
52776
- ...parsed.version ? { version: parsed.version } : {}
52777
- }
52778
- });
52779
- }
52780
- for (const entry of manifest.mcp ?? []) {
52781
- if (!entry.url && !entry.command) {
52782
- f2.error(`MCP ${import_picocolors26.default.bold(entry.name)} needs either ${import_picocolors26.default.cyan("url")} or ${import_picocolors26.default.cyan("command")}.`);
52783
- return null;
52784
- }
52785
- const payload = {};
52786
- if (entry.url !== undefined)
52787
- payload.url = entry.url;
52788
- if (entry.command !== undefined)
52789
- payload.command = entry.command;
52790
- if (entry.args !== undefined)
52791
- payload.args = entry.args;
52792
- if (entry.env !== undefined)
52793
- payload.env = entry.env;
52794
- if (entry.headers !== undefined)
52795
- payload.headers = entry.headers;
52796
- payload.is_enabled = entry.is_enabled ?? true;
52797
- out.push({
52798
- type: "mcp",
52799
- slug: entry.name,
52800
- hash: "",
52801
- files: [],
52802
- meta: { mcp: payload }
52803
- });
52804
- }
52805
- return out;
52806
- }
52807
53199
  function handleApiError3(err) {
52808
53200
  if (err instanceof ApiError) {
52809
53201
  if (err.status === 401) {
@@ -52817,13 +53209,13 @@ function handleApiError3(err) {
52817
53209
  }
52818
53210
 
52819
53211
  // src/cli/agent-status.ts
52820
- var import_picocolors27 = __toESM(require_picocolors(), 1);
53212
+ var import_picocolors28 = __toESM(require_picocolors(), 1);
52821
53213
  async function runAgentStatus(cwd2) {
52822
53214
  banner("agent status — what changed locally, remotely, both");
52823
53215
  const link2 = readLink(cwd2);
52824
53216
  if (!link2) {
52825
53217
  f2.warn("This folder is not linked to any agent.");
52826
- f2.info(`Run ${import_picocolors27.default.cyan("brainbase link")} first.`);
53218
+ f2.info(`Run ${import_picocolors28.default.cyan("brainbase link")} first.`);
52827
53219
  return;
52828
53220
  }
52829
53221
  const manifest = hasManifest(cwd2) ? readManifest(cwd2) : null;
@@ -52844,8 +53236,8 @@ async function runAgentStatus(cwd2) {
52844
53236
  return;
52845
53237
  }
52846
53238
  if (!manifest) {
52847
- f2.info(`${import_picocolors27.default.dim("No")} ${import_picocolors27.default.bold("brainbase.yaml")} ${import_picocolors27.default.dim("here yet.")} Run ${import_picocolors27.default.cyan("brainbase agent pull")} to populate this folder.`);
52848
- f2.info(`Cloud has ${import_picocolors27.default.bold(String(cloud.components.length))} component${cloud.components.length === 1 ? "" : "s"} at revision ${cloud.revision}.`);
53239
+ f2.info(`${import_picocolors28.default.dim("No")} ${import_picocolors28.default.bold("brainbase.agent.yaml")} ${import_picocolors28.default.dim("here yet.")} Run ${import_picocolors28.default.cyan("brainbase agent pull")} to populate this folder.`);
53240
+ f2.info(`Cloud has ${import_picocolors28.default.bold(String(cloud.components.length))} component${cloud.components.length === 1 ? "" : "s"} at revision ${cloud.revision}.`);
52849
53241
  return;
52850
53242
  }
52851
53243
  const localComponents = readLocalComponents(cwd2, manifest);
@@ -52884,17 +53276,17 @@ async function runAgentStatus(cwd2) {
52884
53276
  }
52885
53277
  const lines = [];
52886
53278
  lines.push("");
52887
- lines.push(` ${import_picocolors27.default.bold(link2.name)} ${import_picocolors27.default.dim(`(${link2.slug})`)}`);
52888
- lines.push(` ${import_picocolors27.default.dim("agent_id")} ${link2.agent_id}`);
52889
- lines.push(` ${import_picocolors27.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
53279
+ lines.push(` ${import_picocolors28.default.bold(link2.name)} ${import_picocolors28.default.dim(`(${link2.slug})`)}`);
53280
+ lines.push(` ${import_picocolors28.default.dim("agent_id")} ${link2.agent_id}`);
53281
+ lines.push(` ${import_picocolors28.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
52890
53282
  lines.push("");
52891
53283
  if (meta.localChanged || meta.cloudChanged) {
52892
- lines.push(` ${import_picocolors27.default.bold("agent metadata")}`);
53284
+ lines.push(` ${import_picocolors28.default.bold("agent metadata")}`);
52893
53285
  if (meta.localChanged) {
52894
- lines.push(` ${import_picocolors27.default.yellow("→ push")} name/tagline edited in brainbase.yaml`);
53286
+ lines.push(` ${import_picocolors28.default.yellow("→ push")} name/tagline edited in brainbase.agent.yaml`);
52895
53287
  }
52896
53288
  if (meta.cloudChanged) {
52897
- lines.push(` ${import_picocolors27.default.cyan("← pull")} name/tagline changed on cloud`);
53289
+ lines.push(` ${import_picocolors28.default.cyan("← pull")} name/tagline changed on cloud`);
52898
53290
  }
52899
53291
  lines.push("");
52900
53292
  }
@@ -52904,65 +53296,65 @@ async function runAgentStatus(cwd2) {
52904
53296
  const cloudSecrets = cloudRes.secrets ?? {};
52905
53297
  const sd = diffSecrets(localSecrets, cloudSecrets);
52906
53298
  if (sd.localOnly.length || sd.cloudOnly.length || sd.changed.length) {
52907
- lines.push(` ${import_picocolors27.default.bold("secrets")}`);
53299
+ lines.push(` ${import_picocolors28.default.bold("secrets")}`);
52908
53300
  if (sd.localOnly.length)
52909
- lines.push(` ${import_picocolors27.default.yellow("→ push")} new locally: ${sd.localOnly.join(", ")}`);
53301
+ lines.push(` ${import_picocolors28.default.yellow("→ push")} new locally: ${sd.localOnly.join(", ")}`);
52910
53302
  if (sd.changed.length)
52911
- lines.push(` ${import_picocolors27.default.yellow("→ push")} values changed: ${sd.changed.join(", ")}`);
53303
+ lines.push(` ${import_picocolors28.default.yellow("→ push")} values changed: ${sd.changed.join(", ")}`);
52912
53304
  if (sd.cloudOnly.length)
52913
- lines.push(` ${import_picocolors27.default.cyan("← pull")} new on cloud: ${sd.cloudOnly.join(", ")}`);
53305
+ lines.push(` ${import_picocolors28.default.cyan("← pull")} new on cloud: ${sd.cloudOnly.join(", ")}`);
52914
53306
  lines.push("");
52915
53307
  }
52916
53308
  } catch {}
52917
53309
  if (conflicts.length === 0 && toPush.length === 0 && toPull.length === 0) {
52918
- lines.push(` ${import_picocolors27.default.green("✓")} everything is in sync`);
53310
+ lines.push(` ${import_picocolors28.default.green("✓")} everything is in sync`);
52919
53311
  lines.push("");
52920
53312
  console.log(lines.join(`
52921
53313
  `));
52922
53314
  return;
52923
53315
  }
52924
53316
  if (toPush.length) {
52925
- lines.push(` ${import_picocolors27.default.bold("changes to push")} ${import_picocolors27.default.dim(`(${toPush.length})`)}`);
53317
+ lines.push(` ${import_picocolors28.default.bold("changes to push")} ${import_picocolors28.default.dim(`(${toPush.length})`)}`);
52926
53318
  for (const r2 of toPush)
52927
- lines.push(` ${import_picocolors27.default.yellow("→")} ${fmtRow(r2)}`);
53319
+ lines.push(` ${import_picocolors28.default.yellow("→")} ${fmtRow(r2)}`);
52928
53320
  lines.push("");
52929
53321
  }
52930
53322
  if (toPull.length) {
52931
- lines.push(` ${import_picocolors27.default.bold("changes to pull")} ${import_picocolors27.default.dim(`(${toPull.length})`)}`);
53323
+ lines.push(` ${import_picocolors28.default.bold("changes to pull")} ${import_picocolors28.default.dim(`(${toPull.length})`)}`);
52932
53324
  for (const r2 of toPull)
52933
- lines.push(` ${import_picocolors27.default.cyan("←")} ${fmtRow(r2)}`);
53325
+ lines.push(` ${import_picocolors28.default.cyan("←")} ${fmtRow(r2)}`);
52934
53326
  lines.push("");
52935
53327
  }
52936
53328
  if (conflicts.length) {
52937
- lines.push(` ${import_picocolors27.default.bold(import_picocolors27.default.red("conflicts"))} ${import_picocolors27.default.dim(`(${conflicts.length})`)}`);
53329
+ lines.push(` ${import_picocolors28.default.bold(import_picocolors28.default.red("conflicts"))} ${import_picocolors28.default.dim(`(${conflicts.length})`)}`);
52938
53330
  for (const r2 of conflicts)
52939
- lines.push(` ${import_picocolors27.default.red("!")} ${fmtRow(r2)}`);
53331
+ lines.push(` ${import_picocolors28.default.red("!")} ${fmtRow(r2)}`);
52940
53332
  lines.push("");
52941
53333
  }
52942
- lines.push(` ${import_picocolors27.default.dim("run")} ${import_picocolors27.default.cyan("brainbase agent pull")} ${import_picocolors27.default.dim("to apply cloud changes,")} ${import_picocolors27.default.cyan("brainbase agent push")} ${import_picocolors27.default.dim("to send yours")}`);
53334
+ lines.push(` ${import_picocolors28.default.dim("run")} ${import_picocolors28.default.cyan("brainbase agent pull")} ${import_picocolors28.default.dim("to apply cloud changes,")} ${import_picocolors28.default.cyan("brainbase agent push")} ${import_picocolors28.default.dim("to send yours")}`);
52943
53335
  lines.push("");
52944
53336
  console.log(lines.join(`
52945
53337
  `));
52946
53338
  }
52947
53339
  function fmtRow(r2) {
52948
- const head = `${fmtType(r2.type)} ${import_picocolors27.default.bold(r2.slug)}`;
53340
+ const head = `${fmtType(r2.type)} ${import_picocolors28.default.bold(r2.slug)}`;
52949
53341
  switch (r2.status) {
52950
53342
  case "added-only-local":
52951
- return `${head} ${import_picocolors27.default.dim("(new — only in brainbase.yaml)")}`;
53343
+ return `${head} ${import_picocolors28.default.dim("(new — only in brainbase.agent.yaml)")}`;
52952
53344
  case "added-cloud":
52953
- return `${head} ${import_picocolors27.default.dim("(new on cloud)")}`;
53345
+ return `${head} ${import_picocolors28.default.dim("(new on cloud)")}`;
52954
53346
  case "added-local":
52955
- return `${head} ${import_picocolors27.default.dim("(present locally and on cloud, never synced here)")}`;
53347
+ return `${head} ${import_picocolors28.default.dim("(present locally and on cloud, never synced here)")}`;
52956
53348
  case "removed-local":
52957
- return `${head} ${import_picocolors27.default.dim("(removed from brainbase.yaml)")}`;
53349
+ return `${head} ${import_picocolors28.default.dim("(removed from brainbase.agent.yaml)")}`;
52958
53350
  case "removed-cloud":
52959
- return `${head} ${import_picocolors27.default.dim("(removed on cloud)")}`;
53351
+ return `${head} ${import_picocolors28.default.dim("(removed on cloud)")}`;
52960
53352
  case "modified-local":
52961
- return `${head} ${import_picocolors27.default.dim("(you edited it)")}`;
53353
+ return `${head} ${import_picocolors28.default.dim("(you edited it)")}`;
52962
53354
  case "modified-cloud":
52963
- return `${head} ${import_picocolors27.default.dim("(cloud was updated)")}`;
53355
+ return `${head} ${import_picocolors28.default.dim("(cloud was updated)")}`;
52964
53356
  case "modified-both":
52965
- return `${head} ${import_picocolors27.default.dim("(both diverged — needs resolution)")}`;
53357
+ return `${head} ${import_picocolors28.default.dim("(both diverged — needs resolution)")}`;
52966
53358
  default:
52967
53359
  return head;
52968
53360
  }
@@ -52999,10 +53391,11 @@ function formatExport(shell, key2, value) {
52999
53391
  }
53000
53392
 
53001
53393
  // src/cli/agent-create.ts
53002
- var import_picocolors29 = __toESM(require_picocolors(), 1);
53394
+ import path49 from "node:path";
53395
+ var import_picocolors30 = __toESM(require_picocolors(), 1);
53003
53396
 
53004
53397
  // src/ui/box.ts
53005
- var import_picocolors28 = __toESM(require_picocolors(), 1);
53398
+ var import_picocolors29 = __toESM(require_picocolors(), 1);
53006
53399
  var H3 = "─";
53007
53400
  var TINT = {
53008
53401
  ok: COLOR.ok,
@@ -53014,20 +53407,28 @@ var TINT = {
53014
53407
  function divider(label, width = 56, indent = 2) {
53015
53408
  const ind = " ".repeat(indent);
53016
53409
  if (!label)
53017
- return `${ind}${import_picocolors28.default.dim(H3.repeat(width))}`;
53410
+ return `${ind}${import_picocolors29.default.dim(H3.repeat(width))}`;
53018
53411
  const labelText = ` ${label} `;
53019
53412
  const labelLen = visibleLength(labelText);
53020
- const left = import_picocolors28.default.dim(H3.repeat(2));
53021
- const right = import_picocolors28.default.dim(H3.repeat(Math.max(0, width - labelLen - 2)));
53022
- return `${ind}${left}${import_picocolors28.default.bold(import_picocolors28.default.dim(labelText))}${right}`;
53413
+ const left = import_picocolors29.default.dim(H3.repeat(2));
53414
+ const right = import_picocolors29.default.dim(H3.repeat(Math.max(0, width - labelLen - 2)));
53415
+ return `${ind}${left}${import_picocolors29.default.bold(import_picocolors29.default.dim(labelText))}${right}`;
53023
53416
  }
53024
53417
  function tip(text, indent = 2) {
53025
- return " ".repeat(indent) + import_picocolors28.default.dim("›") + " " + import_picocolors28.default.dim(text);
53418
+ return " ".repeat(indent) + import_picocolors29.default.dim("›") + " " + import_picocolors29.default.dim(text);
53026
53419
  }
53027
53420
 
53028
53421
  // src/cli/agent-create.ts
53029
53422
  async function runAgentCreate(cwd2, args) {
53030
- banner("agent create — make a new brainbase agent and link this folder");
53423
+ banner("agent create — claim a brainbase.agent.yaml and link this folder");
53424
+ let manifest = await loadOrScaffoldManifest(cwd2, args);
53425
+ if (!manifest)
53426
+ return;
53427
+ if (manifest.id) {
53428
+ f2.warn(`This folder already belongs to an agent — ${import_picocolors30.default.bold(manifest.agent.name)} (${import_picocolors30.default.dim(manifest.id)}).`);
53429
+ f2.info(`If you want to detach it, run ${import_picocolors30.default.cyan("brainbase unlink")} first; or move to a different directory.`);
53430
+ return;
53431
+ }
53031
53432
  const orgsSpinner = de();
53032
53433
  orgsSpinner.start("Loading your organizations…");
53033
53434
  let orgs;
@@ -53054,7 +53455,7 @@ async function runAgentCreate(cwd2, args) {
53054
53455
  org = found;
53055
53456
  } else if (orgs.length === 1) {
53056
53457
  org = orgs[0];
53057
- f2.info(`Using organization ${import_picocolors29.default.bold(org.name)}.`);
53458
+ f2.info(`Using organization ${import_picocolors30.default.bold(org.name)}.`);
53058
53459
  } else {
53059
53460
  const orgChoice = await ie({
53060
53461
  message: "Pick an organization",
@@ -53102,7 +53503,7 @@ async function runAgentCreate(cwd2, args) {
53102
53503
  createSpinner2.start("Creating team…");
53103
53504
  try {
53104
53505
  team = await api.createTeam(org.id, teamName.trim());
53105
- createSpinner2.stop(`Created team ${import_picocolors29.default.bold(team.name)}.`);
53506
+ createSpinner2.stop(`Created team ${import_picocolors30.default.bold(team.name)}.`);
53106
53507
  } catch (err) {
53107
53508
  createSpinner2.stop("Failed.");
53108
53509
  handleApiError4(err);
@@ -53112,8 +53513,8 @@ async function runAgentCreate(cwd2, args) {
53112
53513
  team = teams.find((t) => t.id === picked);
53113
53514
  }
53114
53515
  }
53115
- const harness = normalizeHarnessId(args.harness ?? await pickHarness(cwd2));
53116
- let agentName = args.name?.trim();
53516
+ const harness = normalizeHarnessId(args.harness ?? manifest.harness ?? await pickHarness(cwd2));
53517
+ let agentName = args.name?.trim() || manifest.agent.name.trim();
53117
53518
  if (!agentName) {
53118
53519
  const ans = await te({
53119
53520
  message: "Agent name",
@@ -53122,7 +53523,7 @@ async function runAgentCreate(cwd2, args) {
53122
53523
  });
53123
53524
  agentName = ensureNotCancelled(ans).trim();
53124
53525
  }
53125
- let tagline = args.tagline?.trim() || undefined;
53526
+ let tagline = (args.tagline ?? manifest.agent.tagline)?.trim() || undefined;
53126
53527
  if (tagline === undefined && !args.yes) {
53127
53528
  const ans = await te({
53128
53529
  message: "Tagline",
@@ -53134,11 +53535,11 @@ async function runAgentCreate(cwd2, args) {
53134
53535
  }
53135
53536
  if (!args.yes) {
53136
53537
  le([
53137
- `${import_picocolors29.default.dim("org")} ${import_picocolors29.default.bold(org.name)}`,
53138
- `${import_picocolors29.default.dim("team")} ${import_picocolors29.default.bold(team.name)}`,
53139
- `${import_picocolors29.default.dim("harness")} ${import_picocolors29.default.bold(harness)}`,
53140
- `${import_picocolors29.default.dim("agent")} ${import_picocolors29.default.bold(agentName)}`,
53141
- ...tagline ? [`${import_picocolors29.default.dim("tagline")} ${tagline}`] : []
53538
+ `${import_picocolors30.default.dim("org")} ${import_picocolors30.default.bold(org.name)}`,
53539
+ `${import_picocolors30.default.dim("team")} ${import_picocolors30.default.bold(team.name)}`,
53540
+ `${import_picocolors30.default.dim("harness")} ${import_picocolors30.default.bold(harness)}`,
53541
+ `${import_picocolors30.default.dim("agent")} ${import_picocolors30.default.bold(agentName)}`,
53542
+ ...tagline ? [`${import_picocolors30.default.dim("tagline")} ${tagline}`] : []
53142
53543
  ].join(`
53143
53544
  `), "Will create");
53144
53545
  const confirmed = await se({ message: "Create this agent?", initialValue: true });
@@ -53147,6 +53548,19 @@ async function runAgentCreate(cwd2, args) {
53147
53548
  return;
53148
53549
  }
53149
53550
  }
53551
+ let resolvedEntrypoint;
53552
+ if (manifest.entrypoint) {
53553
+ const body = resolveEntrypoint(cwd2, manifest);
53554
+ if (body === null) {
53555
+ if (manifest.entrypoint.file) {
53556
+ f2.error(`Entrypoint file ${import_picocolors30.default.bold(manifest.entrypoint.file)} not found.`);
53557
+ } else {
53558
+ f2.error("Entrypoint block is empty.");
53559
+ }
53560
+ return;
53561
+ }
53562
+ resolvedEntrypoint = body;
53563
+ }
53150
53564
  const createSpinner = de();
53151
53565
  createSpinner.start("Creating agent…");
53152
53566
  let agent;
@@ -53156,9 +53570,10 @@ async function runAgentCreate(cwd2, args) {
53156
53570
  team_id: team.id,
53157
53571
  name: agentName,
53158
53572
  tagline,
53159
- harness
53573
+ harness,
53574
+ ...resolvedEntrypoint !== undefined ? { entrypoint: resolvedEntrypoint } : {}
53160
53575
  });
53161
- createSpinner.stop(`Created ${import_picocolors29.default.bold(agent.name)}.`);
53576
+ createSpinner.stop(`Created ${import_picocolors30.default.bold(agent.name)}.`);
53162
53577
  } catch (err) {
53163
53578
  createSpinner.stop("Failed.");
53164
53579
  handleApiError4(err);
@@ -53171,7 +53586,7 @@ async function runAgentCreate(cwd2, args) {
53171
53586
  let wantsTracking = true;
53172
53587
  if (!args.yes) {
53173
53588
  const ans = await se({
53174
- message: `Track ${harness} conversations on the brainbase platform? ${import_picocolors29.default.dim("(routes LLM calls through brainbase so they appear under this agent)")}`,
53589
+ message: `Track ${harness} conversations on the brainbase platform? ${import_picocolors30.default.dim("(routes LLM calls through brainbase so they appear under this agent)")}`,
53175
53590
  initialValue: true
53176
53591
  });
53177
53592
  wantsTracking = ensureNotCancelled(ans);
@@ -53210,71 +53625,455 @@ async function runAgentCreate(cwd2, args) {
53210
53625
  }
53211
53626
  }
53212
53627
  }
53213
- const link2 = {
53214
- schemaVersion: 1,
53215
- agent_id: agent.id,
53216
- org_id: agent.org_id,
53217
- team_id: agent.team_id,
53218
- slug: agent.slug,
53219
- name: agent.name,
53220
- tagline: agent.tagline,
53221
- url: agent.url,
53222
- linked_at: new Date().toISOString(),
53223
- linked_by: session?.email ?? session?.user_id,
53224
- harness,
53225
- tracking
53226
- };
53227
- writeLink(cwd2, link2);
53228
- $e(`Created ${import_picocolors29.default.bold(agent.name)} and linked this folder.`);
53628
+ const link2 = {
53629
+ schemaVersion: 1,
53630
+ agent_id: agent.id,
53631
+ org_id: agent.org_id,
53632
+ team_id: agent.team_id,
53633
+ slug: agent.slug,
53634
+ name: agent.name,
53635
+ tagline: agent.tagline,
53636
+ url: agent.url,
53637
+ linked_at: new Date().toISOString(),
53638
+ linked_by: session?.email ?? session?.user_id,
53639
+ harness,
53640
+ tracking
53641
+ };
53642
+ writeLink(cwd2, link2);
53643
+ manifest = readManifest(cwd2);
53644
+ let updatedCloud = null;
53645
+ const hasContent = !!manifest.instructions || manifest.skills.length > 0 || (manifest.mcp ?? []).length > 0;
53646
+ if (hasContent) {
53647
+ const outgoing = await buildOutgoingComponents(cwd2, manifest, null);
53648
+ if (outgoing === null) {
53649
+ f2.warn(`Agent created, but local content wasn't uploaded. Fix the issue above and run ${import_picocolors30.default.cyan("brainbase agent push")}.`);
53650
+ } else if (outgoing.length > 0) {
53651
+ const pushSpinner = de();
53652
+ pushSpinner.start("Pushing local content…");
53653
+ try {
53654
+ updatedCloud = await api.pushAgentManifest(agent.id, {
53655
+ components: outgoing,
53656
+ base_revision: 0
53657
+ });
53658
+ pushSpinner.stop(`Pushed at revision ${updatedCloud.revision}.`);
53659
+ } catch (err) {
53660
+ pushSpinner.stop("Failed.");
53661
+ if (err instanceof ApiError) {
53662
+ f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors30.default.cyan("brainbase agent push")} to retry.`);
53663
+ } else {
53664
+ f2.warn(`Content upload failed: ${err.message}. Run ${import_picocolors30.default.cyan("brainbase agent push")} to retry.`);
53665
+ }
53666
+ }
53667
+ }
53668
+ }
53669
+ if (updatedCloud) {
53670
+ const syncedComponents = updatedCloud.components.map((c2) => ({
53671
+ type: c2.type,
53672
+ slug: c2.slug,
53673
+ hash: c2.hash,
53674
+ installedPaths: []
53675
+ }));
53676
+ const state = {
53677
+ schemaVersion: 1,
53678
+ agent_id: agent.id,
53679
+ revision: updatedCloud.revision,
53680
+ synced_at: new Date().toISOString(),
53681
+ components: syncedComponents,
53682
+ agentMeta: {
53683
+ name: agent.name,
53684
+ tagline: agent.tagline,
53685
+ ...resolvedEntrypoint ? { entrypoint: resolvedEntrypoint } : {}
53686
+ }
53687
+ };
53688
+ writeSyncState(cwd2, state);
53689
+ }
53690
+ $e(`Created ${import_picocolors30.default.bold(agent.name)} and linked this folder.`);
53691
+ await showResultCard({
53692
+ title: "CREATED",
53693
+ tone: "ok",
53694
+ subtitle: link2.tagline ? `${link2.name} — ${link2.tagline}` : link2.name,
53695
+ meta: [
53696
+ ["slug", link2.slug],
53697
+ ["agent", link2.agent_id],
53698
+ ...link2.url ? [["url", link2.url]] : []
53699
+ ]
53700
+ });
53701
+ console.log();
53702
+ if (tracking && harness === "codex") {
53703
+ console.log(tip(`Run ${import_picocolors30.default.cyan("codex")} once in this folder and approve trust ${import_picocolors30.default.dim("— Codex only loads project-scope config in trusted projects.")}`));
53704
+ }
53705
+ console.log(tip(`brainbase agent unpack ${import_picocolors30.default.dim("— install harness files (skills/mcps) under .claude/, .codex/, …")}`));
53706
+ console.log();
53707
+ }
53708
+ async function loadOrScaffoldManifest(cwd2, args) {
53709
+ if (hasManifest(cwd2)) {
53710
+ try {
53711
+ return readManifest(cwd2);
53712
+ } catch (err) {
53713
+ f2.error(err.message);
53714
+ return null;
53715
+ }
53716
+ }
53717
+ f2.warn(`No ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)} here.`);
53718
+ if (!args.yes) {
53719
+ const ans = await se({
53720
+ message: `Scaffold a minimal ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)} and continue?`,
53721
+ initialValue: true
53722
+ });
53723
+ if (!ensureNotCancelled(ans)) {
53724
+ $e("Aborted.");
53725
+ return null;
53726
+ }
53727
+ }
53728
+ const seedName = args.name?.trim() ?? path49.basename(path49.resolve(cwd2)) ?? "My Agent";
53729
+ const seedHarness = args.harness ? normalizeHarnessId(args.harness) : undefined;
53730
+ const scaffold = {
53731
+ schema: 1,
53732
+ ...seedHarness ? { harness: seedHarness } : {},
53733
+ agent: { name: seedName, ...args.tagline ? { tagline: args.tagline } : {} },
53734
+ skills: [],
53735
+ mcp: []
53736
+ };
53737
+ try {
53738
+ writeManifest(cwd2, scaffold);
53739
+ f2.info(`Wrote ${import_picocolors30.default.bold(AGENT_MANIFEST_FILE)}.`);
53740
+ } catch (err) {
53741
+ f2.error(`Failed to write manifest: ${err.message}`);
53742
+ return null;
53743
+ }
53744
+ return scaffold;
53745
+ }
53746
+ async function pickHarness(cwd2) {
53747
+ const detections = await detectHarnesses(cwd2);
53748
+ const detected = detections.filter((d3) => d3.detection.detected);
53749
+ if (detected.length === 1) {
53750
+ f2.info(`Detected harness: ${import_picocolors30.default.bold(detected[0].adapter.displayName)}.`);
53751
+ return detected[0].adapter.id;
53752
+ }
53753
+ const choice = await ie({
53754
+ message: detected.length > 1 ? "Multiple harnesses detected — which one is this agent for?" : "No harness detected here. Which harness is this agent for?",
53755
+ options: detections.map((d3) => ({
53756
+ value: d3.adapter.id,
53757
+ label: d3.adapter.displayName,
53758
+ hint: d3.detection.detected ? "detected" : undefined
53759
+ }))
53760
+ });
53761
+ return ensureNotCancelled(choice);
53762
+ }
53763
+ function handleApiError4(err) {
53764
+ if (err instanceof ApiError) {
53765
+ if (err.status === 401) {
53766
+ f2.error("Your session is invalid. Run `brainbase login` and try again.");
53767
+ } else {
53768
+ f2.error(err.message);
53769
+ }
53770
+ } else {
53771
+ f2.error(err.message);
53772
+ }
53773
+ $e("Aborted.");
53774
+ }
53775
+
53776
+ // src/cli/agent-unpack.ts
53777
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
53778
+
53779
+ // src/core/agent-fresh-install.ts
53780
+ import path50 from "node:path";
53781
+ import fs46 from "node:fs";
53782
+ import os13 from "node:os";
53783
+ async function installAgentFresh(input) {
53784
+ const { cwd: cwd2, agent, cloud, harness } = input;
53785
+ const scope = input.scope ?? "project";
53786
+ ensureDir(cwd2);
53787
+ const stageRoot = stageManifestComponents2(cloud.components);
53788
+ const justInstalledPaths = new Map;
53789
+ const cloudHasOrchestrationMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === ORCHESTRATION_MCP_SLUG);
53790
+ const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
53791
+ const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
53792
+ const needMemoryMcpInstall = !cloudHasMemoryMcp;
53793
+ try {
53794
+ if (cloud.components.length > 0 || needOrchestrationMcpInstall || needMemoryMcpInstall) {
53795
+ const toInstall = cloud.components.map((c2) => ({
53796
+ type: c2.type,
53797
+ slug: c2.slug,
53798
+ scope,
53799
+ rootDir: path50.join(stageRoot, c2.type, c2.slug),
53800
+ description: c2.description,
53801
+ meta: c2.meta,
53802
+ payload: c2.meta?.mcp,
53803
+ checksum: c2.hash
53804
+ }));
53805
+ if (needOrchestrationMcpInstall) {
53806
+ toInstall.push(buildOrchestrationMcpComponent(scope));
53807
+ }
53808
+ if (needMemoryMcpInstall) {
53809
+ toInstall.push(buildMemoryMcpComponent(scope));
53810
+ }
53811
+ const installOpts = {
53812
+ cwd: cwd2,
53813
+ scope,
53814
+ resolveConflict: async (_c) => "overwrite",
53815
+ resolveSecret: async () => null
53816
+ };
53817
+ const result = await runHarnessInstall3(harness, toInstall, installOpts, agent.name);
53818
+ for (const o2 of result.installed) {
53819
+ justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
53820
+ }
53821
+ }
53822
+ materializeInstructions2(cwd2, cloud);
53823
+ const manifest = input.preserveManifest ? null : buildManifestFromCloud(cloud, agent);
53824
+ if (manifest)
53825
+ writeManifest(cwd2, manifest);
53826
+ writeLink(cwd2, {
53827
+ schemaVersion: 1,
53828
+ agent_id: agent.id,
53829
+ org_id: agent.org_id,
53830
+ team_id: agent.team_id,
53831
+ slug: agent.slug,
53832
+ name: agent.name,
53833
+ tagline: agent.tagline,
53834
+ url: agent.url,
53835
+ linked_at: new Date().toISOString(),
53836
+ harness
53837
+ });
53838
+ const syncedComponents = cloud.components.map((c2) => ({
53839
+ type: c2.type,
53840
+ slug: c2.slug,
53841
+ hash: c2.hash,
53842
+ installedPaths: justInstalledPaths.get(`${c2.type}/${c2.slug}`) ?? []
53843
+ }));
53844
+ writeSyncState(cwd2, {
53845
+ schemaVersion: 1,
53846
+ agent_id: agent.id,
53847
+ revision: cloud.revision,
53848
+ synced_at: new Date().toISOString(),
53849
+ components: syncedComponents,
53850
+ agentMeta: { name: agent.name, tagline: agent.tagline }
53851
+ });
53852
+ if (input.pullSecrets !== false) {
53853
+ await pullAgentSecrets(cwd2, agent.id);
53854
+ }
53855
+ const returnedManifest = manifest ?? buildManifestFromCloud(cloud, agent);
53856
+ return {
53857
+ installedPaths: justInstalledPaths,
53858
+ manifest: returnedManifest,
53859
+ syncedComponents
53860
+ };
53861
+ } finally {
53862
+ try {
53863
+ fs46.rmSync(stageRoot, { recursive: true, force: true });
53864
+ } catch {}
53865
+ }
53866
+ }
53867
+ function stageManifestComponents2(components) {
53868
+ const root = fs46.mkdtempSync(path50.join(os13.tmpdir(), "brainbase-orch-pull-"));
53869
+ for (const c2 of components) {
53870
+ const compDir = path50.join(root, c2.type, c2.slug);
53871
+ ensureDir(compDir);
53872
+ for (const f4 of c2.files) {
53873
+ const target = path50.join(compDir, f4.path);
53874
+ ensureDir(path50.dirname(target));
53875
+ fs46.writeFileSync(target, f4.content);
53876
+ }
53877
+ }
53878
+ return root;
53879
+ }
53880
+ function runHarnessInstall3(harnessId, components, opts, agentName) {
53881
+ if (harnessId === "claude-code")
53882
+ return installClaudeCodeWithCtx(components, opts, agentName);
53883
+ if (harnessId === "codex")
53884
+ return installCodexWithCtx(components, opts, agentName);
53885
+ if (harnessId === "kafka")
53886
+ return installKafkaWithCtx(components, opts, agentName);
53887
+ return getAdapter(harnessId).install(components, opts);
53888
+ }
53889
+ function materializeInstructions2(cwd2, cloud) {
53890
+ for (const c2 of cloud.components) {
53891
+ if (c2.type !== "instruction")
53892
+ continue;
53893
+ const body = c2.files[0]?.content ?? "";
53894
+ if (!body.trim())
53895
+ continue;
53896
+ fs46.writeFileSync(path50.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
53897
+ return;
53898
+ }
53899
+ }
53900
+ function buildManifestFromCloud(cloud, agent) {
53901
+ const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
53902
+ const meta = c2.meta ?? {};
53903
+ if (meta.name && meta.name.includes("/")) {
53904
+ return {
53905
+ source: meta.version ? `registry:${meta.name}@${meta.version}` : `registry:${meta.name}`
53906
+ };
53907
+ }
53908
+ return { source: `registry:${c2.slug}` };
53909
+ });
53910
+ const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
53911
+ const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
53912
+ const payload = (c2.meta ?? {}).mcp ?? {};
53913
+ const entry = { name: c2.slug };
53914
+ if (typeof payload.url === "string")
53915
+ entry.url = payload.url;
53916
+ if (typeof payload.command === "string")
53917
+ entry.command = payload.command;
53918
+ if (Array.isArray(payload.args))
53919
+ entry.args = payload.args.map(String);
53920
+ if (payload.env && typeof payload.env === "object")
53921
+ entry.env = payload.env;
53922
+ if (payload.headers && typeof payload.headers === "object")
53923
+ entry.headers = payload.headers;
53924
+ if (typeof payload.is_enabled === "boolean")
53925
+ entry.is_enabled = payload.is_enabled;
53926
+ return entry;
53927
+ });
53928
+ return {
53929
+ schema: 1,
53930
+ agent: {
53931
+ name: agent.name,
53932
+ ...agent.tagline ? { tagline: agent.tagline } : {}
53933
+ },
53934
+ ...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
53935
+ skills,
53936
+ mcp
53937
+ };
53938
+ }
53939
+ async function pullAgentSecrets(cwd2, agentId) {
53940
+ try {
53941
+ const res = await api.getAgentSecrets(agentId);
53942
+ const secrets = res.secrets ?? {};
53943
+ if (Object.keys(secrets).length > 0) {
53944
+ writeLocalSecrets(cwd2, secrets);
53945
+ }
53946
+ } catch (err) {
53947
+ if (err instanceof ApiError && err.status !== 404) {
53948
+ f2.warn(`Skipped secrets for agent ${agentId}: ${err.message}`);
53949
+ }
53950
+ }
53951
+ }
53952
+
53953
+ // src/cli/agent-unpack.ts
53954
+ async function runAgentUnpack(cwd2, args) {
53955
+ banner("agent unpack — install this agent into a harness layout");
53956
+ if (!hasManifest(cwd2)) {
53957
+ f2.error(`No ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} here.`);
53958
+ f2.info(`Run ${import_picocolors31.default.cyan("brainbase agent pull <id>")} to bring an agent into this folder first.`);
53959
+ return;
53960
+ }
53961
+ let manifest;
53962
+ try {
53963
+ manifest = readManifest(cwd2);
53964
+ } catch (err) {
53965
+ f2.error(err.message);
53966
+ return;
53967
+ }
53968
+ if (!manifest.id) {
53969
+ f2.error(`${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} is unclaimed (no ${import_picocolors31.default.cyan("id")}).`);
53970
+ f2.info(`Run ${import_picocolors31.default.cyan("brainbase agent create")} to claim it, ` + `or ${import_picocolors31.default.cyan("brainbase agent pull <id>")} to link it to an existing agent.`);
53971
+ return;
53972
+ }
53973
+ let harness;
53974
+ if (args.harness) {
53975
+ harness = normalizeHarnessId(args.harness);
53976
+ } else if (args.yes) {
53977
+ if (!manifest.harness) {
53978
+ f2.error(`--yes mode but no harness — set ${import_picocolors31.default.cyan("harness")} in the manifest or pass ${import_picocolors31.default.cyan("--harness")}.`);
53979
+ return;
53980
+ }
53981
+ harness = normalizeHarnessId(manifest.harness);
53982
+ } else {
53983
+ harness = await pickHarness2(manifest.harness);
53984
+ }
53985
+ const sp = de();
53986
+ sp.start("Fetching agent…");
53987
+ let cloudAgent;
53988
+ let cloud;
53989
+ try {
53990
+ cloudAgent = await api.getAgent(manifest.id);
53991
+ cloud = await api.getAgentManifest(manifest.id);
53992
+ sp.stop(`Cloud revision ${cloud.revision}.`);
53993
+ } catch (err) {
53994
+ sp.stop("Failed.");
53995
+ handleApiError5(err);
53996
+ return;
53997
+ }
53998
+ if (!args.yes) {
53999
+ const ok = await se({
54000
+ message: `Install ${import_picocolors31.default.bold(cloudAgent.name)} as ${import_picocolors31.default.bold(harness)} here?`,
54001
+ initialValue: true
54002
+ });
54003
+ if (!ensureNotCancelled(ok)) {
54004
+ $e("Aborted.");
54005
+ return;
54006
+ }
54007
+ }
54008
+ const prevLink = readLink(cwd2);
54009
+ try {
54010
+ await installAgentFresh({
54011
+ cwd: cwd2,
54012
+ agent: {
54013
+ id: cloudAgent.id,
54014
+ name: cloudAgent.name,
54015
+ slug: cloudAgent.slug,
54016
+ tagline: cloudAgent.tagline,
54017
+ org_id: cloudAgent.org_id ?? prevLink?.org_id ?? "",
54018
+ team_id: cloudAgent.team_id ?? prevLink?.team_id ?? "",
54019
+ url: cloudAgent.url,
54020
+ harness
54021
+ },
54022
+ cloud,
54023
+ harness,
54024
+ scope: args.scope ?? "project",
54025
+ preserveManifest: true
54026
+ });
54027
+ } catch (err) {
54028
+ f2.error(`Install failed: ${err.message}`);
54029
+ return;
54030
+ }
54031
+ manifest = readManifest(cwd2);
54032
+ if (manifest.harness !== harness) {
54033
+ manifest.harness = harness;
54034
+ writeManifest(cwd2, manifest);
54035
+ }
54036
+ $e(`Unpacked ${import_picocolors31.default.bold(cloudAgent.name)} as ${import_picocolors31.default.bold(harness)}.`);
53229
54037
  await showResultCard({
53230
- title: "CREATED",
54038
+ title: "UNPACKED",
53231
54039
  tone: "ok",
53232
- subtitle: link2.tagline ? `${link2.name} — ${link2.tagline}` : link2.name,
54040
+ subtitle: cloudAgent.name,
53233
54041
  meta: [
53234
- ["slug", link2.slug],
53235
- ["agent", link2.agent_id],
53236
- ...link2.url ? [["url", link2.url]] : []
54042
+ ["harness", harness],
54043
+ ["agent", cloudAgent.id],
54044
+ ...cloudAgent.url ? [["url", cloudAgent.url]] : []
53237
54045
  ]
53238
54046
  });
53239
- console.log();
53240
- if (tracking && harness === "codex") {
53241
- console.log(tip(`Run ${import_picocolors29.default.cyan("codex")} once in this folder and approve trust ${import_picocolors29.default.dim("— Codex only loads project-scope config in trusted projects.")}`));
53242
- }
53243
- console.log(tip(`brainbase agent pull ${import_picocolors29.default.dim("— pull the agent contents into this folder")}`));
53244
- console.log();
53245
54047
  }
53246
- async function pickHarness(cwd2) {
53247
- const detections = await detectHarnesses(cwd2);
53248
- const detected = detections.filter((d3) => d3.detection.detected);
53249
- if (detected.length === 1) {
53250
- f2.info(`Detected harness: ${import_picocolors29.default.bold(detected[0].adapter.displayName)}.`);
53251
- return detected[0].adapter.id;
53252
- }
54048
+ async function pickHarness2(current) {
54049
+ const initial = current ? normalizeHarnessId(current) : undefined;
53253
54050
  const choice = await ie({
53254
- message: detected.length > 1 ? "Multiple harnesses detected — which one is this agent for?" : "No harness detected here. Which harness is this agent for?",
53255
- options: detections.map((d3) => ({
53256
- value: d3.adapter.id,
53257
- label: d3.adapter.displayName,
53258
- hint: d3.detection.detected ? "detected" : undefined
53259
- }))
54051
+ message: "Pick a harness to install as",
54052
+ options: adapters.map((a3) => ({
54053
+ value: a3.id,
54054
+ label: a3.displayName,
54055
+ hint: a3.id === initial ? "current" : undefined
54056
+ })),
54057
+ initialValue: initial ?? adapters[0].id
53260
54058
  });
53261
54059
  return ensureNotCancelled(choice);
53262
54060
  }
53263
- function handleApiError4(err) {
54061
+ function handleApiError5(err) {
53264
54062
  if (err instanceof ApiError) {
53265
54063
  if (err.status === 401) {
53266
54064
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
54065
+ } else if (err.status === 404) {
54066
+ f2.error(`Agent not found, or you don't have access. The id in ${import_picocolors31.default.bold(AGENT_MANIFEST_FILE)} may be stale.`);
53267
54067
  } else {
53268
54068
  f2.error(err.message);
53269
54069
  }
53270
54070
  } else {
53271
54071
  f2.error(err.message);
53272
54072
  }
53273
- $e("Aborted.");
53274
54073
  }
53275
54074
 
53276
54075
  // src/cli/agent.ts
53277
- async function runAgent(cwd2, sub, _args, opts) {
54076
+ async function runAgent(cwd2, sub, args, opts) {
53278
54077
  switch (sub) {
53279
54078
  case "create":
53280
54079
  await runAgentCreate(cwd2, {
@@ -53288,10 +54087,22 @@ async function runAgent(cwd2, sub, _args, opts) {
53288
54087
  });
53289
54088
  return;
53290
54089
  case "pull":
53291
- await runAgentPull(cwd2, opts);
54090
+ await runAgentPull(cwd2, {
54091
+ yes: opts.yes,
54092
+ scope: opts.scope,
54093
+ agentIdArg: args[0],
54094
+ force: opts.force
54095
+ });
53292
54096
  return;
53293
54097
  case "push":
53294
- await runAgentPush(cwd2, opts);
54098
+ await runAgentPush(cwd2, { yes: opts.yes });
54099
+ return;
54100
+ case "unpack":
54101
+ await runAgentUnpack(cwd2, {
54102
+ yes: opts.yes,
54103
+ scope: opts.scope,
54104
+ harness: opts.harness
54105
+ });
53295
54106
  return;
53296
54107
  case "status":
53297
54108
  await runAgentStatus(cwd2);
@@ -53315,29 +54126,30 @@ async function runAgent(cwd2, sub, _args, opts) {
53315
54126
  function printHelp() {
53316
54127
  const out = [];
53317
54128
  out.push("");
53318
- out.push(` ${import_picocolors30.default.bold("brainbase agent")} ${import_picocolors30.default.dim("<sub> [options]")}`);
54129
+ out.push(` ${import_picocolors32.default.bold("brainbase agent")} ${import_picocolors32.default.dim("<sub> [options]")}`);
53319
54130
  out.push("");
53320
- out.push(` ${import_picocolors30.default.cyan("create")} ${import_picocolors30.default.dim("make a new agent on the cloud and link this folder to it")}`);
53321
- out.push(` ${import_picocolors30.default.cyan("pull")} ${import_picocolors30.default.dim("apply cloud changes into this folder")}`);
53322
- out.push(` ${import_picocolors30.default.cyan("push")} ${import_picocolors30.default.dim("send local changes to the cloud")}`);
53323
- out.push(` ${import_picocolors30.default.cyan("status")} ${import_picocolors30.default.dim("show what would push and what would pull")}`);
53324
- out.push(` ${import_picocolors30.default.cyan("env")} ${import_picocolors30.default.dim('print export statements use with `eval "$(brainbase agent env)"`')}`);
54131
+ out.push(` ${import_picocolors32.default.cyan("create")} ${import_picocolors32.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
54132
+ 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)")}`);
54133
+ out.push(` ${import_picocolors32.default.cyan("push")} ${import_picocolors32.default.dim("send local changes to the cloud")}`);
54134
+ out.push(` ${import_picocolors32.default.cyan("unpack")} ${import_picocolors32.default.dim("install the claimed agent into a harness layout (--harness to override)")}`);
54135
+ out.push(` ${import_picocolors32.default.cyan("status")} ${import_picocolors32.default.dim("show what would push and what would pull")}`);
54136
+ out.push(` ${import_picocolors32.default.cyan("env")} ${import_picocolors32.default.dim('print export statements — use with `eval "$(brainbase agent env)"`')}`);
53325
54137
  out.push("");
53326
54138
  console.log(out.join(`
53327
54139
  `));
53328
54140
  }
53329
54141
 
53330
54142
  // src/cli/orchestration.ts
53331
- var import_picocolors35 = __toESM(require_picocolors(), 1);
54143
+ var import_picocolors37 = __toESM(require_picocolors(), 1);
53332
54144
 
53333
54145
  // src/cli/orchestration-pull.ts
53334
- import path52 from "node:path";
54146
+ import path53 from "node:path";
53335
54147
  import fs49 from "node:fs";
53336
- var import_picocolors31 = __toESM(require_picocolors(), 1);
54148
+ var import_picocolors33 = __toESM(require_picocolors(), 1);
53337
54149
 
53338
54150
  // src/core/orchestration-manifest.ts
53339
- import path49 from "node:path";
53340
- import fs46 from "node:fs";
54151
+ import path51 from "node:path";
54152
+ import fs47 from "node:fs";
53341
54153
  var import_yaml3 = __toESM(require_dist(), 1);
53342
54154
  var ORCH_MANIFEST_FILE = "brainbase-orchestration.yaml";
53343
54155
  var ORCH_MEMBERS_DIR = "agents";
@@ -53365,16 +54177,16 @@ var OrchestrationManifestSchema = exports_external.object({
53365
54177
  edges: exports_external.array(EdgeSchema).default([])
53366
54178
  });
53367
54179
  function orchManifestPath(cwd2) {
53368
- return path49.join(cwd2, ORCH_MANIFEST_FILE);
54180
+ return path51.join(cwd2, ORCH_MANIFEST_FILE);
53369
54181
  }
53370
54182
  function hasOrchManifest(cwd2) {
53371
- return fs46.existsSync(orchManifestPath(cwd2));
54183
+ return fs47.existsSync(orchManifestPath(cwd2));
53372
54184
  }
53373
54185
  function readOrchManifest(cwd2) {
53374
54186
  const p2 = orchManifestPath(cwd2);
53375
- if (!fs46.existsSync(p2))
54187
+ if (!fs47.existsSync(p2))
53376
54188
  return null;
53377
- const raw = fs46.readFileSync(p2, "utf8");
54189
+ const raw = fs47.readFileSync(p2, "utf8");
53378
54190
  let parsed;
53379
54191
  try {
53380
54192
  parsed = import_yaml3.default.parse(raw);
@@ -53393,15 +54205,15 @@ function writeOrchManifest(cwd2, manifest) {
53393
54205
  doc.commentBefore = ` brainbase-orchestration.yaml — declarative orchestration manifest.
53394
54206
  ` + ` Committed to source control. Edit by hand, then
53395
54207
  ` + " `brainbase orchestration push`. Member agents live under ./agents/.";
53396
- fs46.writeFileSync(orchManifestPath(cwd2), String(doc), "utf8");
54208
+ fs47.writeFileSync(orchManifestPath(cwd2), String(doc), "utf8");
53397
54209
  }
53398
54210
  function memberDir(cwd2, slug) {
53399
- return path49.join(cwd2, ORCH_MEMBERS_DIR, slug);
54211
+ return path51.join(cwd2, ORCH_MEMBERS_DIR, slug);
53400
54212
  }
53401
54213
 
53402
54214
  // src/core/orchestration-link.ts
53403
- import path50 from "node:path";
53404
- import fs47 from "node:fs";
54215
+ import path52 from "node:path";
54216
+ import fs48 from "node:fs";
53405
54217
  var ORCH_LINK_FILE = "orchestration-link.json";
53406
54218
  var ORCH_SYNC_STATE_FILE = "orchestration-sync-state.json";
53407
54219
  var OrchestrationLinkSchema = exports_external.object({
@@ -53435,10 +54247,10 @@ var OrchestrationSyncStateSchema = exports_external.object({
53435
54247
  edges: exports_external.array(SyncedEdgeSchema)
53436
54248
  });
53437
54249
  function orchLinkPath(cwd2) {
53438
- return path50.join(cwd2, LINK_DIR, ORCH_LINK_FILE);
54250
+ return path52.join(cwd2, LINK_DIR, ORCH_LINK_FILE);
53439
54251
  }
53440
54252
  function orchSyncStatePath(cwd2) {
53441
- return path50.join(cwd2, LINK_DIR, ORCH_SYNC_STATE_FILE);
54253
+ return path52.join(cwd2, LINK_DIR, ORCH_SYNC_STATE_FILE);
53442
54254
  }
53443
54255
  function readOrchLink(cwd2) {
53444
54256
  const p2 = orchLinkPath(cwd2);
@@ -53451,7 +54263,7 @@ function readOrchLink(cwd2) {
53451
54263
  }
53452
54264
  }
53453
54265
  function writeOrchLink(cwd2, link2) {
53454
- ensureDir(path50.join(cwd2, LINK_DIR));
54266
+ ensureDir(path52.join(cwd2, LINK_DIR));
53455
54267
  const clean = {};
53456
54268
  for (const [k3, v3] of Object.entries(link2)) {
53457
54269
  if (v3 !== null && v3 !== undefined)
@@ -53471,200 +54283,28 @@ function readOrchSyncState(cwd2) {
53471
54283
  }
53472
54284
  }
53473
54285
  function writeOrchSyncState(cwd2, state) {
53474
- ensureDir(path50.join(cwd2, LINK_DIR));
54286
+ ensureDir(path52.join(cwd2, LINK_DIR));
53475
54287
  writeJson(orchSyncStatePath(cwd2), state);
53476
54288
  ensureGitignore2(cwd2);
53477
54289
  }
53478
54290
  function ensureGitignore2(cwd2) {
53479
- const ignorePath = path50.join(cwd2, LINK_DIR, ".gitignore");
54291
+ const ignorePath = path52.join(cwd2, LINK_DIR, ".gitignore");
53480
54292
  const desired = `${ORCH_SYNC_STATE_FILE}
53481
54293
  `;
53482
54294
  try {
53483
54295
  if (!exists(ignorePath)) {
53484
- fs47.writeFileSync(ignorePath, desired);
54296
+ fs48.writeFileSync(ignorePath, desired);
53485
54297
  return;
53486
54298
  }
53487
- const current = fs47.readFileSync(ignorePath, "utf8");
54299
+ const current = fs48.readFileSync(ignorePath, "utf8");
53488
54300
  if (!current.split(/\r?\n/).some((l2) => l2.trim() === ORCH_SYNC_STATE_FILE)) {
53489
- fs47.writeFileSync(ignorePath, current.endsWith(`
54301
+ fs48.writeFileSync(ignorePath, current.endsWith(`
53490
54302
  `) ? current + desired : current + `
53491
54303
  ` + desired);
53492
54304
  }
53493
54305
  } catch {}
53494
54306
  }
53495
54307
 
53496
- // src/core/agent-fresh-install.ts
53497
- import path51 from "node:path";
53498
- import fs48 from "node:fs";
53499
- import os13 from "node:os";
53500
- async function installAgentFresh(input) {
53501
- const { cwd: cwd2, agent, cloud, harness } = input;
53502
- const scope = input.scope ?? "project";
53503
- ensureDir(cwd2);
53504
- const stageRoot = stageManifestComponents2(cloud.components);
53505
- const justInstalledPaths = new Map;
53506
- const cloudHasOrchestrationMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === ORCHESTRATION_MCP_SLUG);
53507
- const needOrchestrationMcpInstall = !cloudHasOrchestrationMcp;
53508
- const cloudHasMemoryMcp = cloud.components.some((c2) => c2.type === "mcp" && c2.slug === MEMORY_MCP_SLUG);
53509
- const needMemoryMcpInstall = !cloudHasMemoryMcp;
53510
- try {
53511
- if (cloud.components.length > 0 || needOrchestrationMcpInstall || needMemoryMcpInstall) {
53512
- const toInstall = cloud.components.map((c2) => ({
53513
- type: c2.type,
53514
- slug: c2.slug,
53515
- scope,
53516
- rootDir: path51.join(stageRoot, c2.type, c2.slug),
53517
- description: c2.description,
53518
- meta: c2.meta,
53519
- payload: c2.meta?.mcp,
53520
- checksum: c2.hash
53521
- }));
53522
- if (needOrchestrationMcpInstall) {
53523
- toInstall.push(buildOrchestrationMcpComponent(scope));
53524
- }
53525
- if (needMemoryMcpInstall) {
53526
- toInstall.push(buildMemoryMcpComponent(scope));
53527
- }
53528
- const installOpts = {
53529
- cwd: cwd2,
53530
- scope,
53531
- resolveConflict: async (_c) => "overwrite",
53532
- resolveSecret: async () => null
53533
- };
53534
- const result = await runHarnessInstall3(harness, toInstall, installOpts, agent.name);
53535
- for (const o2 of result.installed) {
53536
- justInstalledPaths.set(`${o2.type}/${o2.slug}`, o2.installedPaths);
53537
- }
53538
- }
53539
- materializeInstructions2(cwd2, cloud);
53540
- const manifest = buildManifestFromCloud(cloud, agent);
53541
- writeManifest(cwd2, manifest);
53542
- writeLink(cwd2, {
53543
- schemaVersion: 1,
53544
- agent_id: agent.id,
53545
- org_id: agent.org_id,
53546
- team_id: agent.team_id,
53547
- slug: agent.slug,
53548
- name: agent.name,
53549
- tagline: agent.tagline,
53550
- url: agent.url,
53551
- linked_at: new Date().toISOString(),
53552
- harness
53553
- });
53554
- const syncedComponents = cloud.components.map((c2) => ({
53555
- type: c2.type,
53556
- slug: c2.slug,
53557
- hash: c2.hash,
53558
- installedPaths: justInstalledPaths.get(`${c2.type}/${c2.slug}`) ?? []
53559
- }));
53560
- writeSyncState(cwd2, {
53561
- schemaVersion: 1,
53562
- agent_id: agent.id,
53563
- revision: cloud.revision,
53564
- synced_at: new Date().toISOString(),
53565
- components: syncedComponents,
53566
- agentMeta: { name: agent.name, tagline: agent.tagline }
53567
- });
53568
- if (input.pullSecrets !== false) {
53569
- await pullAgentSecrets(cwd2, agent.id);
53570
- }
53571
- return {
53572
- installedPaths: justInstalledPaths,
53573
- manifest,
53574
- syncedComponents
53575
- };
53576
- } finally {
53577
- try {
53578
- fs48.rmSync(stageRoot, { recursive: true, force: true });
53579
- } catch {}
53580
- }
53581
- }
53582
- function stageManifestComponents2(components) {
53583
- const root = fs48.mkdtempSync(path51.join(os13.tmpdir(), "brainbase-orch-pull-"));
53584
- for (const c2 of components) {
53585
- const compDir = path51.join(root, c2.type, c2.slug);
53586
- ensureDir(compDir);
53587
- for (const f4 of c2.files) {
53588
- const target = path51.join(compDir, f4.path);
53589
- ensureDir(path51.dirname(target));
53590
- fs48.writeFileSync(target, f4.content);
53591
- }
53592
- }
53593
- return root;
53594
- }
53595
- function runHarnessInstall3(harnessId, components, opts, agentName) {
53596
- if (harnessId === "claude-code")
53597
- return installClaudeCodeWithCtx(components, opts, agentName);
53598
- if (harnessId === "codex")
53599
- return installCodexWithCtx(components, opts, agentName);
53600
- if (harnessId === "kafka")
53601
- return installKafkaWithCtx(components, opts, agentName);
53602
- return getAdapter(harnessId).install(components, opts);
53603
- }
53604
- function materializeInstructions2(cwd2, cloud) {
53605
- for (const c2 of cloud.components) {
53606
- if (c2.type !== "instruction")
53607
- continue;
53608
- const body = c2.files[0]?.content ?? "";
53609
- if (!body.trim())
53610
- continue;
53611
- fs48.writeFileSync(path51.join(cwd2, DEFAULT_INSTRUCTIONS_FILE), body, "utf8");
53612
- return;
53613
- }
53614
- }
53615
- function buildManifestFromCloud(cloud, agent) {
53616
- const skills = cloud.components.filter((c2) => c2.type === "skill").map((c2) => {
53617
- const meta = c2.meta ?? {};
53618
- if (meta.name && meta.name.includes("/")) {
53619
- return {
53620
- source: meta.version ? `registry:${meta.name}@${meta.version}` : `registry:${meta.name}`
53621
- };
53622
- }
53623
- return { source: `registry:${c2.slug}` };
53624
- });
53625
- const hasInstructions = cloud.components.some((c2) => c2.type === "instruction" && c2.files[0]?.content?.trim());
53626
- const mcp = cloud.components.filter((c2) => c2.type === "mcp").map((c2) => {
53627
- const payload = (c2.meta ?? {}).mcp ?? {};
53628
- const entry = { name: c2.slug };
53629
- if (typeof payload.url === "string")
53630
- entry.url = payload.url;
53631
- if (typeof payload.command === "string")
53632
- entry.command = payload.command;
53633
- if (Array.isArray(payload.args))
53634
- entry.args = payload.args.map(String);
53635
- if (payload.env && typeof payload.env === "object")
53636
- entry.env = payload.env;
53637
- if (payload.headers && typeof payload.headers === "object")
53638
- entry.headers = payload.headers;
53639
- if (typeof payload.is_enabled === "boolean")
53640
- entry.is_enabled = payload.is_enabled;
53641
- return entry;
53642
- });
53643
- return {
53644
- schema: 1,
53645
- agent: {
53646
- name: agent.name,
53647
- ...agent.tagline ? { tagline: agent.tagline } : {}
53648
- },
53649
- ...hasInstructions ? { instructions: { file: DEFAULT_INSTRUCTIONS_FILE } } : {},
53650
- skills,
53651
- mcp
53652
- };
53653
- }
53654
- async function pullAgentSecrets(cwd2, agentId) {
53655
- try {
53656
- const res = await api.getAgentSecrets(agentId);
53657
- const secrets = res.secrets ?? {};
53658
- if (Object.keys(secrets).length > 0) {
53659
- writeLocalSecrets(cwd2, secrets);
53660
- }
53661
- } catch (err) {
53662
- if (err instanceof ApiError && err.status !== 404) {
53663
- f2.warn(`Skipped secrets for agent ${agentId}: ${err.message}`);
53664
- }
53665
- }
53666
- }
53667
-
53668
54308
  // src/cli/orchestration-pull.ts
53669
54309
  async function runOrchestrationPull(cwd2, args) {
53670
54310
  banner("orchestration pull — fetch orchestration + all member agents");
@@ -53676,8 +54316,8 @@ async function runOrchestrationPull(cwd2, args) {
53676
54316
  orchId = args.orchestrationId;
53677
54317
  } else {
53678
54318
  f2.warn("This folder is not linked to any orchestration.");
53679
- f2.info(`Run ${import_picocolors31.default.cyan("brainbase orchestration pull <id>")} with an orchestration id,
53680
- or ${import_picocolors31.default.cyan("brainbase orchestration list")} to find one.`);
54319
+ f2.info(`Run ${import_picocolors33.default.cyan("brainbase orchestration pull <id>")} with an orchestration id,
54320
+ or ${import_picocolors33.default.cyan("brainbase orchestration list")} to find one.`);
53681
54321
  return;
53682
54322
  }
53683
54323
  const sp = de();
@@ -53688,29 +54328,29 @@ async function runOrchestrationPull(cwd2, args) {
53688
54328
  sp.stop(`Cloud revision ${cloud.revision} — ${cloud.members.length} member${cloud.members.length === 1 ? "" : "s"}, ${cloud.edges.length} edge${cloud.edges.length === 1 ? "" : "s"}.`);
53689
54329
  } catch (err) {
53690
54330
  sp.stop("Failed.");
53691
- handleApiError5(err);
54331
+ handleApiError6(err);
53692
54332
  return;
53693
54333
  }
53694
54334
  const planLines = [];
53695
54335
  planLines.push("");
53696
- planLines.push(` ${import_picocolors31.default.bold(cloud.name)} ${import_picocolors31.default.dim(`(${cloud.id})`)}`);
54336
+ planLines.push(` ${import_picocolors33.default.bold(cloud.name)} ${import_picocolors33.default.dim(`(${cloud.id})`)}`);
53697
54337
  if (cloud.description)
53698
- planLines.push(` ${import_picocolors31.default.dim(cloud.description)}`);
54338
+ planLines.push(` ${import_picocolors33.default.dim(cloud.description)}`);
53699
54339
  planLines.push("");
53700
- planLines.push(` ${import_picocolors31.default.dim("members:")}`);
54340
+ planLines.push(` ${import_picocolors33.default.dim("members:")}`);
53701
54341
  for (const m3 of cloud.members) {
53702
54342
  const skipped = !m3.manifest;
53703
- const tail = skipped ? import_picocolors31.default.red(" (manifest unavailable — skipped)") : "";
53704
- planLines.push(` ${import_picocolors31.default.cyan("•")} ${import_picocolors31.default.bold(m3.slug)} ${import_picocolors31.default.dim(`(${m3.name})`)}${tail}`);
54343
+ const tail = skipped ? import_picocolors33.default.red(" (manifest unavailable — skipped)") : "";
54344
+ planLines.push(` ${import_picocolors33.default.cyan("•")} ${import_picocolors33.default.bold(m3.slug)} ${import_picocolors33.default.dim(`(${m3.name})`)}${tail}`);
53705
54345
  }
53706
54346
  if (cloud.edges.length) {
53707
54347
  planLines.push("");
53708
- planLines.push(` ${import_picocolors31.default.dim("edges:")}`);
54348
+ planLines.push(` ${import_picocolors33.default.dim("edges:")}`);
53709
54349
  for (const e2 of cloud.edges) {
53710
54350
  const from = e2.from_slug ?? e2.from_agent_id;
53711
54351
  const to2 = e2.to_slug ?? e2.to_agent_id;
53712
- const desc = e2.description ? ` ${import_picocolors31.default.dim("— " + e2.description)}` : "";
53713
- planLines.push(` ${import_picocolors31.default.cyan(from)} ${import_picocolors31.default.dim("→")} ${import_picocolors31.default.cyan(to2)}${desc}`);
54352
+ const desc = e2.description ? ` ${import_picocolors33.default.dim("— " + e2.description)}` : "";
54353
+ planLines.push(` ${import_picocolors33.default.cyan(from)} ${import_picocolors33.default.dim("→")} ${import_picocolors33.default.cyan(to2)}${desc}`);
53714
54354
  }
53715
54355
  }
53716
54356
  planLines.push("");
@@ -53719,7 +54359,7 @@ async function runOrchestrationPull(cwd2, args) {
53719
54359
  const isRefresh = !!existingLink;
53720
54360
  if (!args.yes && !isRefresh) {
53721
54361
  const ok = await se({
53722
- message: `Pull into ${import_picocolors31.default.bold(cwd2)}?`,
54362
+ message: `Pull into ${import_picocolors33.default.bold(cwd2)}?`,
53723
54363
  initialValue: true
53724
54364
  });
53725
54365
  if (!ensureNotCancelled(ok)) {
@@ -53760,7 +54400,7 @@ async function runOrchestrationPull(cwd2, args) {
53760
54400
  scope: "project",
53761
54401
  pullSecrets: true
53762
54402
  });
53763
- memberSp.stop(`Installed ${import_picocolors31.default.bold(m3.slug)} ${import_picocolors31.default.dim(`(${m3.manifest.components.length} components)`)}.`);
54403
+ memberSp.stop(`Installed ${import_picocolors33.default.bold(m3.slug)} ${import_picocolors33.default.dim(`(${m3.manifest.components.length} components)`)}.`);
53764
54404
  installedMembers.push({
53765
54405
  agent_id: m3.agent_id,
53766
54406
  slug: m3.slug,
@@ -53815,9 +54455,9 @@ async function runOrchestrationPull(cwd2, args) {
53815
54455
  payload_schema: e2.payload_schema ?? {}
53816
54456
  }))
53817
54457
  });
53818
- $e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path52.basename(cwd2)}/ ${import_picocolors31.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
54458
+ $e(`Pulled ${cloud.name} at revision ${cloud.revision} into ${path53.basename(cwd2)}/ ${import_picocolors33.default.dim(`(${installedMembers.length}/${cloud.members.length} members)`)}.`);
53819
54459
  }
53820
- function handleApiError5(err) {
54460
+ function handleApiError6(err) {
53821
54461
  if (err instanceof ApiError) {
53822
54462
  if (err.status === 401) {
53823
54463
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
@@ -53832,18 +54472,18 @@ function handleApiError5(err) {
53832
54472
  }
53833
54473
 
53834
54474
  // src/cli/orchestration-push.ts
53835
- var import_picocolors32 = __toESM(require_picocolors(), 1);
54475
+ var import_picocolors34 = __toESM(require_picocolors(), 1);
53836
54476
  async function runOrchestrationPush(cwd2, args) {
53837
54477
  banner("orchestration push — recursively push each member, then update the graph");
53838
54478
  const link2 = readOrchLink(cwd2);
53839
54479
  if (!link2) {
53840
54480
  f2.warn("This folder is not linked to any orchestration.");
53841
- f2.info(`Run ${import_picocolors32.default.cyan("brainbase orchestration pull <id>")} first.`);
54481
+ f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull <id>")} first.`);
53842
54482
  return;
53843
54483
  }
53844
54484
  if (!hasOrchManifest(cwd2)) {
53845
- f2.warn(`No ${import_picocolors32.default.bold(ORCH_MANIFEST_FILE)} here.`);
53846
- f2.info(`Run ${import_picocolors32.default.cyan("brainbase orchestration pull")} to materialise the manifest before pushing.`);
54485
+ f2.warn(`No ${import_picocolors34.default.bold(ORCH_MANIFEST_FILE)} here.`);
54486
+ f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the manifest before pushing.`);
53847
54487
  return;
53848
54488
  }
53849
54489
  let manifest;
@@ -53856,15 +54496,15 @@ async function runOrchestrationPush(cwd2, args) {
53856
54496
  const memberSlugs = new Set(manifest.members.map((m3) => m3.slug));
53857
54497
  for (const e2 of manifest.edges) {
53858
54498
  if (!memberSlugs.has(e2.from)) {
53859
- f2.error(`Edge from "${import_picocolors32.default.bold(e2.from)}" references a slug that isn't in members.`);
54499
+ f2.error(`Edge from "${import_picocolors34.default.bold(e2.from)}" references a slug that isn't in members.`);
53860
54500
  return;
53861
54501
  }
53862
54502
  if (!memberSlugs.has(e2.to)) {
53863
- f2.error(`Edge to "${import_picocolors32.default.bold(e2.to)}" references a slug that isn't in members.`);
54503
+ f2.error(`Edge to "${import_picocolors34.default.bold(e2.to)}" references a slug that isn't in members.`);
53864
54504
  return;
53865
54505
  }
53866
54506
  if (e2.from === e2.to) {
53867
- f2.error(`Edge ${import_picocolors32.default.bold(e2.from)} → ${import_picocolors32.default.bold(e2.to)}: self-loops are not allowed.`);
54507
+ f2.error(`Edge ${import_picocolors34.default.bold(e2.from)} → ${import_picocolors34.default.bold(e2.to)}: self-loops are not allowed.`);
53868
54508
  return;
53869
54509
  }
53870
54510
  }
@@ -53881,17 +54521,17 @@ async function runOrchestrationPush(cwd2, args) {
53881
54521
  }
53882
54522
  if (missing.length) {
53883
54523
  f2.error(`These members have no local checkout (expected at agents/<slug>/.brainbase/link.json): ${missing.join(", ")}.`);
53884
- f2.info(`Run ${import_picocolors32.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
54524
+ f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to materialise the missing folders.`);
53885
54525
  return;
53886
54526
  }
53887
54527
  const plan = [""];
53888
- plan.push(` ${import_picocolors32.default.bold(link2.name)} ${import_picocolors32.default.dim(`(${link2.orchestration_id})`)}`);
53889
- plan.push(` ${import_picocolors32.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}`)}`);
54528
+ plan.push(` ${import_picocolors34.default.bold(link2.name)} ${import_picocolors34.default.dim(`(${link2.orchestration_id})`)}`);
54529
+ plan.push(` ${import_picocolors34.default.dim(`${manifest.members.length} member${manifest.members.length === 1 ? "" : "s"}, ${manifest.edges.length} edge${manifest.edges.length === 1 ? "" : "s"}`)}`);
53890
54530
  plan.push("");
53891
54531
  if (!args.graphOnly) {
53892
- plan.push(` ${import_picocolors32.default.dim("per-member agent push:")}`);
54532
+ plan.push(` ${import_picocolors34.default.dim("per-member agent push:")}`);
53893
54533
  for (const m3 of manifest.members) {
53894
- plan.push(` ${import_picocolors32.default.cyan("•")} ${import_picocolors32.default.bold(m3.slug)}`);
54534
+ plan.push(` ${import_picocolors34.default.cyan("•")} ${import_picocolors34.default.bold(m3.slug)}`);
53895
54535
  }
53896
54536
  plan.push("");
53897
54537
  }
@@ -53911,7 +54551,7 @@ async function runOrchestrationPush(cwd2, args) {
53911
54551
  for (const m3 of manifest.members) {
53912
54552
  const dir = memberDir(cwd2, m3.slug);
53913
54553
  console.log("");
53914
- console.log(`${import_picocolors32.default.dim("───")} ${import_picocolors32.default.bold(m3.slug)} ${import_picocolors32.default.dim("───")}`);
54554
+ console.log(`${import_picocolors34.default.dim("───")} ${import_picocolors34.default.bold(m3.slug)} ${import_picocolors34.default.dim("───")}`);
53915
54555
  try {
53916
54556
  await runAgentPush(dir, { yes: true });
53917
54557
  } catch (err) {
@@ -53962,10 +54602,10 @@ async function runOrchestrationPush(cwd2, args) {
53962
54602
  $e(`Pushed ${link2.name} at revision ${updated.revision}.`);
53963
54603
  } catch (err) {
53964
54604
  sp.stop("Failed.");
53965
- handleApiError6(err);
54605
+ handleApiError7(err);
53966
54606
  }
53967
54607
  }
53968
- function handleApiError6(err) {
54608
+ function handleApiError7(err) {
53969
54609
  if (err instanceof ApiError) {
53970
54610
  if (err.status === 401) {
53971
54611
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
@@ -53973,7 +54613,7 @@ function handleApiError6(err) {
53973
54613
  f2.error("You do not have access to this orchestration.");
53974
54614
  } else if (err.status === 409) {
53975
54615
  f2.error(err.message);
53976
- f2.info(`Run ${import_picocolors32.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
54616
+ f2.info(`Run ${import_picocolors34.default.cyan("brainbase orchestration pull")} to reconcile, then push again.`);
53977
54617
  } else {
53978
54618
  f2.error(err.message);
53979
54619
  }
@@ -53983,13 +54623,13 @@ function handleApiError6(err) {
53983
54623
  }
53984
54624
 
53985
54625
  // src/cli/orchestration-status.ts
53986
- var import_picocolors33 = __toESM(require_picocolors(), 1);
54626
+ var import_picocolors35 = __toESM(require_picocolors(), 1);
53987
54627
  async function runOrchestrationStatus(cwd2) {
53988
54628
  banner("orchestration status — what changed locally, remotely, both");
53989
54629
  const link2 = readOrchLink(cwd2);
53990
54630
  if (!link2) {
53991
54631
  f2.warn("This folder is not linked to any orchestration.");
53992
- f2.info(`Run ${import_picocolors33.default.cyan("brainbase orchestration pull <id>")} first.`);
54632
+ f2.info(`Run ${import_picocolors35.default.cyan("brainbase orchestration pull <id>")} first.`);
53993
54633
  return;
53994
54634
  }
53995
54635
  const localManifest = hasOrchManifest(cwd2) ? readOrchManifest(cwd2) : null;
@@ -54011,20 +54651,20 @@ async function runOrchestrationStatus(cwd2) {
54011
54651
  }
54012
54652
  const lines = [];
54013
54653
  lines.push("");
54014
- lines.push(` ${import_picocolors33.default.bold(link2.name)} ${import_picocolors33.default.dim(`(${link2.orchestration_id})`)}`);
54015
- lines.push(` ${import_picocolors33.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
54654
+ lines.push(` ${import_picocolors35.default.bold(link2.name)} ${import_picocolors35.default.dim(`(${link2.orchestration_id})`)}`);
54655
+ lines.push(` ${import_picocolors35.default.dim("revision")} cloud ${cloud.revision}${lock ? ` · lock ${lock.revision}` : " · never pulled"}`);
54016
54656
  lines.push("");
54017
54657
  const cloudMemberSet = new Set(cloud.members.map((m3) => m3.slug));
54018
54658
  const localMemberSet = new Set((localManifest?.members ?? []).map((m3) => m3.slug));
54019
54659
  const membersAdded = [...localMemberSet].filter((s3) => !cloudMemberSet.has(s3));
54020
54660
  const membersRemoved = [...cloudMemberSet].filter((s3) => !localMemberSet.has(s3));
54021
54661
  if (membersAdded.length || membersRemoved.length) {
54022
- lines.push(` ${import_picocolors33.default.bold("members")}`);
54662
+ lines.push(` ${import_picocolors35.default.bold("members")}`);
54023
54663
  for (const slug of membersAdded) {
54024
- lines.push(` ${import_picocolors33.default.yellow("→ push")} added in yaml: ${import_picocolors33.default.bold(slug)}`);
54664
+ lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${import_picocolors35.default.bold(slug)}`);
54025
54665
  }
54026
54666
  for (const slug of membersRemoved) {
54027
- lines.push(` ${import_picocolors33.default.cyan("← pull")} added on cloud: ${import_picocolors33.default.bold(slug)}`);
54667
+ lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${import_picocolors35.default.bold(slug)}`);
54028
54668
  }
54029
54669
  lines.push("");
54030
54670
  }
@@ -54039,11 +54679,11 @@ async function runOrchestrationStatus(cwd2) {
54039
54679
  const edgesAdded = [...localEdges.keys()].filter((k3) => !cloudEdges.has(k3));
54040
54680
  const edgesRemoved = [...cloudEdges.keys()].filter((k3) => !localEdges.has(k3));
54041
54681
  if (edgesAdded.length || edgesRemoved.length) {
54042
- lines.push(` ${import_picocolors33.default.bold("edges")}`);
54682
+ lines.push(` ${import_picocolors35.default.bold("edges")}`);
54043
54683
  for (const k3 of edgesAdded)
54044
- lines.push(` ${import_picocolors33.default.yellow("→ push")} added in yaml: ${k3}`);
54684
+ lines.push(` ${import_picocolors35.default.yellow("→ push")} added in yaml: ${k3}`);
54045
54685
  for (const k3 of edgesRemoved)
54046
- lines.push(` ${import_picocolors33.default.cyan("← pull")} added on cloud: ${k3}`);
54686
+ lines.push(` ${import_picocolors35.default.cyan("← pull")} added on cloud: ${k3}`);
54047
54687
  lines.push("");
54048
54688
  }
54049
54689
  const lockByAgentId = new Map((lock?.members ?? []).map((m3) => [m3.agent_id, m3]));
@@ -54065,28 +54705,28 @@ async function runOrchestrationStatus(cwd2) {
54065
54705
  }
54066
54706
  }
54067
54707
  if (memberDrift.length) {
54068
- lines.push(` ${import_picocolors33.default.bold("member content drift")}`);
54708
+ lines.push(` ${import_picocolors35.default.bold("member content drift")}`);
54069
54709
  for (const d3 of memberDrift) {
54070
- lines.push(` ${import_picocolors33.default.cyan("?")} ${import_picocolors33.default.bold(d3.slug)} ${import_picocolors33.default.dim("— " + d3.reason)}`);
54710
+ lines.push(` ${import_picocolors35.default.cyan("?")} ${import_picocolors35.default.bold(d3.slug)} ${import_picocolors35.default.dim("— " + d3.reason)}`);
54071
54711
  }
54072
- lines.push(` ${import_picocolors33.default.dim("cd into each member folder and run")} ${import_picocolors33.default.cyan("brainbase agent status")}`);
54712
+ lines.push(` ${import_picocolors35.default.dim("cd into each member folder and run")} ${import_picocolors35.default.cyan("brainbase agent status")}`);
54073
54713
  lines.push("");
54074
54714
  }
54075
54715
  if (!membersAdded.length && !membersRemoved.length && !edgesAdded.length && !edgesRemoved.length && !memberDrift.length) {
54076
- lines.push(` ${import_picocolors33.default.green("✓")} everything is in sync`);
54716
+ lines.push(` ${import_picocolors35.default.green("✓")} everything is in sync`);
54077
54717
  lines.push("");
54078
54718
  console.log(lines.join(`
54079
54719
  `));
54080
54720
  return;
54081
54721
  }
54082
- lines.push(` ${import_picocolors33.default.dim("run")} ${import_picocolors33.default.cyan("brainbase orchestration pull")} ${import_picocolors33.default.dim("to apply cloud changes,")} ${import_picocolors33.default.cyan("brainbase orchestration push")} ${import_picocolors33.default.dim("to send yours")}`);
54722
+ 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")}`);
54083
54723
  lines.push("");
54084
54724
  console.log(lines.join(`
54085
54725
  `));
54086
54726
  }
54087
54727
 
54088
54728
  // src/cli/orchestration-list.ts
54089
- var import_picocolors34 = __toESM(require_picocolors(), 1);
54729
+ var import_picocolors36 = __toESM(require_picocolors(), 1);
54090
54730
  async function runOrchestrationList(args) {
54091
54731
  banner("orchestration list — orchestrations under a team");
54092
54732
  let orgId = args.orgId;
@@ -54096,7 +54736,7 @@ async function runOrchestrationList(args) {
54096
54736
  try {
54097
54737
  orgs = await api.listOrgs();
54098
54738
  } catch (err) {
54099
- handleApiError7(err);
54739
+ handleApiError8(err);
54100
54740
  return;
54101
54741
  }
54102
54742
  if (orgs.length === 0) {
@@ -54118,7 +54758,7 @@ async function runOrchestrationList(args) {
54118
54758
  try {
54119
54759
  teams = await api.listTeams(orgId);
54120
54760
  } catch (err) {
54121
- handleApiError7(err);
54761
+ handleApiError8(err);
54122
54762
  return;
54123
54763
  }
54124
54764
  if (teams.length === 0) {
@@ -54143,7 +54783,7 @@ async function runOrchestrationList(args) {
54143
54783
  sp.stop(`${items.length} orchestration${items.length === 1 ? "" : "s"}.`);
54144
54784
  } catch (err) {
54145
54785
  sp.stop("Failed.");
54146
- handleApiError7(err);
54786
+ handleApiError8(err);
54147
54787
  return;
54148
54788
  }
54149
54789
  if (items.length === 0) {
@@ -54152,18 +54792,18 @@ async function runOrchestrationList(args) {
54152
54792
  }
54153
54793
  const lines = [""];
54154
54794
  for (const o2 of items) {
54155
- lines.push(` ${import_picocolors34.default.bold(o2.name)} ${import_picocolors34.default.dim(o2.id)}`);
54795
+ lines.push(` ${import_picocolors36.default.bold(o2.name)} ${import_picocolors36.default.dim(o2.id)}`);
54156
54796
  if (o2.description)
54157
- lines.push(` ${import_picocolors34.default.dim(o2.description)}`);
54158
- lines.push(` ${import_picocolors34.default.dim(`${o2.member_count} member${o2.member_count === 1 ? "" : "s"} · ${o2.edge_count} edge${o2.edge_count === 1 ? "" : "s"}`)}`);
54797
+ lines.push(` ${import_picocolors36.default.dim(o2.description)}`);
54798
+ lines.push(` ${import_picocolors36.default.dim(`${o2.member_count} member${o2.member_count === 1 ? "" : "s"} · ${o2.edge_count} edge${o2.edge_count === 1 ? "" : "s"}`)}`);
54159
54799
  lines.push("");
54160
54800
  }
54161
- lines.push(` ${import_picocolors34.default.dim("pull one with")} ${import_picocolors34.default.cyan("brainbase orchestration pull <id>")}`);
54801
+ lines.push(` ${import_picocolors36.default.dim("pull one with")} ${import_picocolors36.default.cyan("brainbase orchestration pull <id>")}`);
54162
54802
  lines.push("");
54163
54803
  console.log(lines.join(`
54164
54804
  `));
54165
54805
  }
54166
- function handleApiError7(err) {
54806
+ function handleApiError8(err) {
54167
54807
  if (err instanceof ApiError) {
54168
54808
  if (err.status === 401) {
54169
54809
  f2.error("Your session is invalid. Run `brainbase login` and try again.");
@@ -54214,26 +54854,26 @@ async function runOrchestration(cwd2, sub, args, opts) {
54214
54854
  function printHelp2() {
54215
54855
  const out = [];
54216
54856
  out.push("");
54217
- out.push(` ${import_picocolors35.default.bold("brainbase orchestration")} ${import_picocolors35.default.dim("<sub> [options]")}`);
54857
+ out.push(` ${import_picocolors37.default.bold("brainbase orchestration")} ${import_picocolors37.default.dim("<sub> [options]")}`);
54218
54858
  out.push("");
54219
- out.push(` ${import_picocolors35.default.cyan("pull")} ${import_picocolors35.default.dim("<id>")} ${import_picocolors35.default.dim("fetch orchestration + every member agent into this folder")}`);
54220
- out.push(` ${import_picocolors35.default.cyan("push")} ${import_picocolors35.default.dim("push each member, then update the orchestration graph")}`);
54221
- out.push(` ${import_picocolors35.default.cyan("status")} ${import_picocolors35.default.dim("show what would push and what would pull")}`);
54222
- out.push(` ${import_picocolors35.default.cyan("list")} ${import_picocolors35.default.dim("list orchestrations under a team")}`);
54859
+ out.push(` ${import_picocolors37.default.cyan("pull")} ${import_picocolors37.default.dim("<id>")} ${import_picocolors37.default.dim("fetch orchestration + every member agent into this folder")}`);
54860
+ out.push(` ${import_picocolors37.default.cyan("push")} ${import_picocolors37.default.dim("push each member, then update the orchestration graph")}`);
54861
+ out.push(` ${import_picocolors37.default.cyan("status")} ${import_picocolors37.default.dim("show what would push and what would pull")}`);
54862
+ out.push(` ${import_picocolors37.default.cyan("list")} ${import_picocolors37.default.dim("list orchestrations under a team")}`);
54223
54863
  out.push("");
54224
- out.push(` ${import_picocolors35.default.bold("Flags")}`);
54225
- out.push(` ${import_picocolors35.default.dim("--yes, -y")} skip confirmations`);
54226
- out.push(` ${import_picocolors35.default.dim("--harness <id>")} harness for newly-created member folders (default claude-code)`);
54227
- out.push(` ${import_picocolors35.default.dim("--graph-only")} for push: only update members + edges, skip per-member push`);
54228
- out.push(` ${import_picocolors35.default.dim("--org <id>")} for list: org id (CLI vocab — DB teams.id)`);
54229
- out.push(` ${import_picocolors35.default.dim("--team <id>")} for list: team id (CLI vocab — DB groups.id)`);
54864
+ out.push(` ${import_picocolors37.default.bold("Flags")}`);
54865
+ out.push(` ${import_picocolors37.default.dim("--yes, -y")} skip confirmations`);
54866
+ out.push(` ${import_picocolors37.default.dim("--harness <id>")} harness for newly-created member folders (default claude-code)`);
54867
+ out.push(` ${import_picocolors37.default.dim("--graph-only")} for push: only update members + edges, skip per-member push`);
54868
+ out.push(` ${import_picocolors37.default.dim("--org <id>")} for list: org id (CLI vocab — DB teams.id)`);
54869
+ out.push(` ${import_picocolors37.default.dim("--team <id>")} for list: team id (CLI vocab — DB groups.id)`);
54230
54870
  out.push("");
54231
54871
  console.log(out.join(`
54232
54872
  `));
54233
54873
  }
54234
54874
 
54235
54875
  // src/cli/run.ts
54236
- import { spawn as spawn2 } from "node:child_process";
54876
+ import { spawn as spawn3 } from "node:child_process";
54237
54877
  async function runRun(cwd2, args) {
54238
54878
  const cleaned = args[0] === "--" ? args.slice(1) : args;
54239
54879
  if (cleaned.length === 0) {
@@ -54245,7 +54885,7 @@ async function runRun(cwd2, args) {
54245
54885
  const [cmd, ...cmdArgs] = cleaned;
54246
54886
  const secrets = readLocalSecrets(cwd2);
54247
54887
  const env3 = { ...process.env, ...secrets };
54248
- const child = spawn2(cmd, cmdArgs, {
54888
+ const child = spawn3(cmd, cmdArgs, {
54249
54889
  cwd: cwd2,
54250
54890
  env: env3,
54251
54891
  stdio: "inherit",
@@ -54271,16 +54911,16 @@ async function runRun(cwd2, args) {
54271
54911
  }
54272
54912
 
54273
54913
  // src/cli/publish.ts
54274
- var import_picocolors36 = __toESM(require_picocolors(), 1);
54914
+ var import_picocolors38 = __toESM(require_picocolors(), 1);
54275
54915
  async function runPublish(cwd2, _args) {
54276
54916
  banner("publish — send your changes to the team");
54277
54917
  const link2 = readLink(cwd2);
54278
54918
  if (!link2) {
54279
54919
  f2.warn("This folder is not linked to any agent.");
54280
- f2.info(`Run ${import_picocolors36.default.cyan("brainbase link")} first.`);
54920
+ f2.info(`Run ${import_picocolors38.default.cyan("brainbase link")} first.`);
54281
54921
  return;
54282
54922
  }
54283
- f2.info(`${import_picocolors36.default.bold("publish")} is coming soon — for now, edit the agent on the web app and run ${import_picocolors36.default.cyan("brainbase sync")} to bring changes here.`);
54923
+ f2.info(`${import_picocolors38.default.bold("publish")} is coming soon — for now, edit the agent on the web app and run ${import_picocolors38.default.cyan("brainbase sync")} to bring changes here.`);
54284
54924
  }
54285
54925
 
54286
54926
  // src/ui/ink/StatusCard.tsx
@@ -54578,7 +55218,7 @@ async function runStatus(cwd2) {
54578
55218
  }
54579
55219
 
54580
55220
  // src/cli/token.ts
54581
- var import_picocolors37 = __toESM(require_picocolors(), 1);
55221
+ var import_picocolors39 = __toESM(require_picocolors(), 1);
54582
55222
 
54583
55223
  // src/ui/ink/TokenCards.tsx
54584
55224
  var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
@@ -54872,7 +55512,7 @@ async function runTokenRevoke(args) {
54872
55512
  }
54873
55513
  if (!args.yes) {
54874
55514
  const ok = await se({
54875
- message: `Revoke token ${import_picocolors37.default.bold(args.id)}? CIs and machines using it will stop working.`,
55515
+ message: `Revoke token ${import_picocolors39.default.bold(args.id)}? CIs and machines using it will stop working.`,
54876
55516
  initialValue: false
54877
55517
  });
54878
55518
  if (!ensureNotCancelled(ok))
@@ -54887,7 +55527,7 @@ async function runTokenRevoke(args) {
54887
55527
  }
54888
55528
  async function runTokenClear() {
54889
55529
  if (!readToken()) {
54890
- console.log(import_picocolors37.default.dim("No local token stored."));
55530
+ console.log(import_picocolors39.default.dim("No local token stored."));
54891
55531
  return;
54892
55532
  }
54893
55533
  clearToken();
@@ -54938,17 +55578,17 @@ async function runToken(sub, rest, args) {
54938
55578
  function printTokenHelp() {
54939
55579
  const out = [];
54940
55580
  out.push("");
54941
- out.push(` ${import_picocolors37.default.bold("brainbase token")} ${import_picocolors37.default.dim("<command>")}`);
55581
+ out.push(` ${import_picocolors39.default.bold("brainbase token")} ${import_picocolors39.default.dim("<command>")}`);
54942
55582
  out.push("");
54943
- out.push(` ${import_picocolors37.default.cyan("create")} ${import_picocolors37.default.dim("issue a new long-lived CLI key (PAT)")}`);
54944
- out.push(` ${import_picocolors37.default.cyan("list")} ${import_picocolors37.default.dim("show your active tokens")}`);
54945
- out.push(` ${import_picocolors37.default.cyan("revoke")} ${import_picocolors37.default.dim("<id>")} ${import_picocolors37.default.dim("revoke a token by id")}`);
54946
- out.push(` ${import_picocolors37.default.cyan("clear")} ${import_picocolors37.default.dim("forget the local token (does not revoke)")}`);
55583
+ out.push(` ${import_picocolors39.default.cyan("create")} ${import_picocolors39.default.dim("issue a new long-lived CLI key (PAT)")}`);
55584
+ out.push(` ${import_picocolors39.default.cyan("list")} ${import_picocolors39.default.dim("show your active tokens")}`);
55585
+ out.push(` ${import_picocolors39.default.cyan("revoke")} ${import_picocolors39.default.dim("<id>")} ${import_picocolors39.default.dim("revoke a token by id")}`);
55586
+ out.push(` ${import_picocolors39.default.cyan("clear")} ${import_picocolors39.default.dim("forget the local token (does not revoke)")}`);
54947
55587
  out.push("");
54948
- out.push(` ${import_picocolors37.default.bold("create flags")}`);
54949
- out.push(` ${import_picocolors37.default.cyan("--name, -n")} ${import_picocolors37.default.dim("<label>")} ${import_picocolors37.default.dim("token label (prompted if omitted)")}`);
54950
- out.push(` ${import_picocolors37.default.cyan("--scopes")} ${import_picocolors37.default.dim("<list>")} ${import_picocolors37.default.dim("comma-separated; allowed: read, publish, admin")}`);
54951
- out.push(` ${import_picocolors37.default.dim("default: read,publish")}`);
55588
+ out.push(` ${import_picocolors39.default.bold("create flags")}`);
55589
+ out.push(` ${import_picocolors39.default.cyan("--name, -n")} ${import_picocolors39.default.dim("<label>")} ${import_picocolors39.default.dim("token label (prompted if omitted)")}`);
55590
+ out.push(` ${import_picocolors39.default.cyan("--scopes")} ${import_picocolors39.default.dim("<list>")} ${import_picocolors39.default.dim("comma-separated; allowed: read, publish, admin")}`);
55591
+ out.push(` ${import_picocolors39.default.dim("default: read,publish")}`);
54952
55592
  out.push("");
54953
55593
  console.log(out.join(`
54954
55594
  `));
@@ -54968,89 +55608,90 @@ var PROTECTED = new Set([
54968
55608
  function help() {
54969
55609
  const out = [];
54970
55610
  out.push("");
54971
- out.push(` ${brandTint("◆")} ${import_picocolors38.default.bold("brainbase")} ${import_picocolors38.default.dim("v0.2.0")}`);
54972
- out.push(` ${import_picocolors38.default.dim("connect your local agent to the brainbase platform")}`);
55611
+ out.push(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("v0.5.0")}`);
55612
+ out.push(` ${import_picocolors40.default.dim("connect your local agent to the brainbase platform")}`);
54973
55613
  out.push("");
54974
55614
  out.push(divider("USAGE"));
54975
55615
  out.push("");
54976
- out.push(` ${import_picocolors38.default.bold("brainbase")} ${import_picocolors38.default.dim("<command> [options]")}`);
55616
+ out.push(` ${import_picocolors40.default.bold("brainbase")} ${import_picocolors40.default.dim("<command> [options]")}`);
54977
55617
  out.push("");
54978
55618
  out.push(divider("AUTH"));
54979
55619
  out.push("");
54980
- out.push(` ${import_picocolors38.default.cyan("login")} ${import_picocolors38.default.dim(" open the web app and connect this device")}`);
54981
- out.push(` ${import_picocolors38.default.cyan("logout")} ${import_picocolors38.default.dim(" clear the local session")}`);
54982
- out.push(` ${import_picocolors38.default.cyan("whoami")} ${import_picocolors38.default.dim(" show the current user")}`);
55620
+ out.push(` ${import_picocolors40.default.cyan("login")} ${import_picocolors40.default.dim(" open the web app and connect this device")}`);
55621
+ out.push(` ${import_picocolors40.default.cyan("logout")} ${import_picocolors40.default.dim(" clear the local session")}`);
55622
+ out.push(` ${import_picocolors40.default.cyan("whoami")} ${import_picocolors40.default.dim(" show the current user")}`);
54983
55623
  out.push("");
54984
55624
  out.push(divider("LINKED AGENT"));
54985
55625
  out.push("");
54986
- out.push(` ${import_picocolors38.default.cyan("agent create")} ${import_picocolors38.default.dim("make a new agent on the cloud and link this folder")}`);
54987
- out.push(` ${import_picocolors38.default.cyan("link")} ${import_picocolors38.default.dim("attach this folder to an existing agent")}`);
54988
- out.push(` ${import_picocolors38.default.cyan("agent pull")} ${import_picocolors38.default.dim("bring cloud changes into this folder")}`);
54989
- out.push(` ${import_picocolors38.default.cyan("agent push")} ${import_picocolors38.default.dim("send local changes to the cloud")}`);
54990
- out.push(` ${import_picocolors38.default.cyan("agent status")} ${import_picocolors38.default.dim("show what would pull and what would push")}`);
54991
- out.push(` ${import_picocolors38.default.cyan("agent env")} ${import_picocolors38.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
54992
- out.push(` ${import_picocolors38.default.cyan("run")} ${import_picocolors38.default.dim("<cmd> [args...]")} ${import_picocolors38.default.dim("run <cmd> with secrets.env loaded into env")}`);
54993
- out.push(` ${import_picocolors38.default.cyan("status")} ${import_picocolors38.default.dim("show what this folder is linked to")}`);
54994
- out.push(` ${import_picocolors38.default.cyan("unlink")} ${import_picocolors38.default.dim("disconnect this folder")}`);
55626
+ out.push(` ${import_picocolors40.default.cyan("agent create")} ${import_picocolors40.default.dim("claim an unclaimed brainbase.agent.yaml and create the cloud agent")}`);
55627
+ out.push(` ${import_picocolors40.default.cyan("agent pull")} ${import_picocolors40.default.dim("[<id>]")} ${import_picocolors40.default.dim("bring cloud changes into this folder (--force to override)")}`);
55628
+ out.push(` ${import_picocolors40.default.cyan("agent push")} ${import_picocolors40.default.dim("send local changes to the cloud")}`);
55629
+ out.push(` ${import_picocolors40.default.cyan("agent unpack")} ${import_picocolors40.default.dim("install the claimed agent into a harness layout")}`);
55630
+ out.push(` ${import_picocolors40.default.cyan("link")} ${import_picocolors40.default.dim("attach this folder to an existing agent")}`);
55631
+ out.push(` ${import_picocolors40.default.cyan("agent status")} ${import_picocolors40.default.dim("show what would pull and what would push")}`);
55632
+ out.push(` ${import_picocolors40.default.cyan("agent env")} ${import_picocolors40.default.dim("print export lines for `eval $(brainbase agent env)`")}`);
55633
+ out.push(` ${import_picocolors40.default.cyan("run")} ${import_picocolors40.default.dim("<cmd> [args...]")} ${import_picocolors40.default.dim("run <cmd> with secrets.env loaded into env")}`);
55634
+ out.push(` ${import_picocolors40.default.cyan("status")} ${import_picocolors40.default.dim("show what this folder is linked to")}`);
55635
+ out.push(` ${import_picocolors40.default.cyan("unlink")} ${import_picocolors40.default.dim("disconnect this folder")}`);
54995
55636
  out.push("");
54996
55637
  out.push(divider("ORCHESTRATIONS"));
54997
55638
  out.push("");
54998
- out.push(` ${import_picocolors38.default.cyan("orchestration list")} ${import_picocolors38.default.dim("list orchestrations under a team")}`);
54999
- out.push(` ${import_picocolors38.default.cyan("orchestration pull")} ${import_picocolors38.default.dim("<id>")} ${import_picocolors38.default.dim("recursively fetch an orchestration + every member agent")}`);
55000
- out.push(` ${import_picocolors38.default.cyan("orchestration push")} ${import_picocolors38.default.dim("recursively push each member, then update the graph")}`);
55001
- out.push(` ${import_picocolors38.default.cyan("orchestration status")} ${import_picocolors38.default.dim("show what would push and what would pull")}`);
55639
+ out.push(` ${import_picocolors40.default.cyan("orchestration list")} ${import_picocolors40.default.dim("list orchestrations under a team")}`);
55640
+ out.push(` ${import_picocolors40.default.cyan("orchestration pull")} ${import_picocolors40.default.dim("<id>")} ${import_picocolors40.default.dim("recursively fetch an orchestration + every member agent")}`);
55641
+ out.push(` ${import_picocolors40.default.cyan("orchestration push")} ${import_picocolors40.default.dim("recursively push each member, then update the graph")}`);
55642
+ out.push(` ${import_picocolors40.default.cyan("orchestration status")} ${import_picocolors40.default.dim("show what would push and what would pull")}`);
55002
55643
  out.push("");
55003
55644
  out.push(divider("TEMPLATES"));
55004
55645
  out.push("");
55005
- out.push(` ${import_picocolors38.default.cyan("template pack")} ${import_picocolors38.default.dim("bundle the current agent into a template")}`);
55006
- out.push(` ${import_picocolors38.default.cyan("template publish")} ${import_picocolors38.default.dim("upload a template to the registry")}`);
55007
- out.push(` ${import_picocolors38.default.cyan("template search")} ${import_picocolors38.default.dim("[query]")} ${import_picocolors38.default.dim("search the registry")}`);
55008
- out.push(` ${import_picocolors38.default.cyan("template info")} ${import_picocolors38.default.dim("<creator/slug>")} ${import_picocolors38.default.dim("show registry details for a template")}`);
55009
- out.push(` ${import_picocolors38.default.cyan("template onboard")} ${import_picocolors38.default.dim("<creator/slug>")} ${import_picocolors38.default.dim("install (or refresh) a template")}`);
55010
- out.push(` ${import_picocolors38.default.cyan("template list")} ${import_picocolors38.default.dim("show installed templates")}`);
55011
- out.push(` ${import_picocolors38.default.cyan("template remove")} ${import_picocolors38.default.dim("<creator/slug>")} ${import_picocolors38.default.dim("uninstall a template")}`);
55646
+ out.push(` ${import_picocolors40.default.cyan("template pack")} ${import_picocolors40.default.dim("bundle the current agent into a template")}`);
55647
+ out.push(` ${import_picocolors40.default.cyan("template publish")} ${import_picocolors40.default.dim("upload a template to the registry")}`);
55648
+ out.push(` ${import_picocolors40.default.cyan("template search")} ${import_picocolors40.default.dim("[query]")} ${import_picocolors40.default.dim("search the registry")}`);
55649
+ out.push(` ${import_picocolors40.default.cyan("template info")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("show registry details for a template")}`);
55650
+ out.push(` ${import_picocolors40.default.cyan("template onboard")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("install (or refresh) a template")}`);
55651
+ out.push(` ${import_picocolors40.default.cyan("template list")} ${import_picocolors40.default.dim("show installed templates")}`);
55652
+ out.push(` ${import_picocolors40.default.cyan("template remove")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("uninstall a template")}`);
55012
55653
  out.push("");
55013
55654
  out.push(divider("SKILLS"));
55014
55655
  out.push("");
55015
- out.push(` ${import_picocolors38.default.cyan("skill add")} ${import_picocolors38.default.dim("<source>")} ${import_picocolors38.default.dim("install a skill (github / git / brainbase)")}`);
55016
- out.push(` ${import_picocolors38.default.cyan("skill list")} ${import_picocolors38.default.dim("show locally installed skills + their source")}`);
55017
- out.push(` ${import_picocolors38.default.cyan("skill update")} ${import_picocolors38.default.dim("<slug>")} ${import_picocolors38.default.dim("re-fetch a skill from its recorded source")}`);
55018
- out.push(` ${import_picocolors38.default.cyan("skill remove")} ${import_picocolors38.default.dim("<slug>")} ${import_picocolors38.default.dim("uninstall a skill")}`);
55019
- out.push(` ${import_picocolors38.default.cyan("skill search")} ${import_picocolors38.default.dim("[query]")} ${import_picocolors38.default.dim("search the brainbase skill registry")}`);
55020
- out.push(` ${import_picocolors38.default.cyan("skill info")} ${import_picocolors38.default.dim("<creator/slug>")} ${import_picocolors38.default.dim("show registry details for a skill")}`);
55021
- out.push(` ${import_picocolors38.default.cyan("skill publish")} ${import_picocolors38.default.dim("[dir]")} ${import_picocolors38.default.dim("publish a SKILL.md folder (defaults to .)")}`);
55656
+ out.push(` ${import_picocolors40.default.cyan("skill add")} ${import_picocolors40.default.dim("<source>")} ${import_picocolors40.default.dim("install a skill (github / git / brainbase)")}`);
55657
+ out.push(` ${import_picocolors40.default.cyan("skill list")} ${import_picocolors40.default.dim("show locally installed skills + their source")}`);
55658
+ out.push(` ${import_picocolors40.default.cyan("skill update")} ${import_picocolors40.default.dim("<slug>")} ${import_picocolors40.default.dim("re-fetch a skill from its recorded source")}`);
55659
+ out.push(` ${import_picocolors40.default.cyan("skill remove")} ${import_picocolors40.default.dim("<slug>")} ${import_picocolors40.default.dim("uninstall a skill")}`);
55660
+ out.push(` ${import_picocolors40.default.cyan("skill search")} ${import_picocolors40.default.dim("[query]")} ${import_picocolors40.default.dim("search the brainbase skill registry")}`);
55661
+ out.push(` ${import_picocolors40.default.cyan("skill info")} ${import_picocolors40.default.dim("<creator/slug>")} ${import_picocolors40.default.dim("show registry details for a skill")}`);
55662
+ out.push(` ${import_picocolors40.default.cyan("skill publish")} ${import_picocolors40.default.dim("[dir]")} ${import_picocolors40.default.dim("publish a SKILL.md folder (defaults to .)")}`);
55022
55663
  out.push("");
55023
55664
  out.push(divider("CLI TOKENS"));
55024
55665
  out.push("");
55025
- out.push(` ${import_picocolors38.default.cyan("token create")} ${import_picocolors38.default.dim("issue a long-lived CLI key for CI / scripts")}`);
55026
- out.push(` ${import_picocolors38.default.cyan("token list")} ${import_picocolors38.default.dim("show your active tokens")}`);
55027
- out.push(` ${import_picocolors38.default.cyan("token revoke")} ${import_picocolors38.default.dim("<id>")} ${import_picocolors38.default.dim("revoke a token")}`);
55666
+ out.push(` ${import_picocolors40.default.cyan("token create")} ${import_picocolors40.default.dim("issue a long-lived CLI key for CI / scripts")}`);
55667
+ out.push(` ${import_picocolors40.default.cyan("token list")} ${import_picocolors40.default.dim("show your active tokens")}`);
55668
+ out.push(` ${import_picocolors40.default.cyan("token revoke")} ${import_picocolors40.default.dim("<id>")} ${import_picocolors40.default.dim("revoke a token")}`);
55028
55669
  out.push("");
55029
55670
  out.push(divider("FLAGS"));
55030
55671
  out.push("");
55031
- out.push(` ${import_picocolors38.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
55032
- out.push(` ${import_picocolors38.default.dim("--scope <s>")} force scope: global | project`);
55033
- out.push(` ${import_picocolors38.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
55034
- out.push(` ${import_picocolors38.default.dim("--agent <id>")} for link: attach this folder to an existing agent non-interactively`);
55035
- out.push(` ${import_picocolors38.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
55036
- out.push(` ${import_picocolors38.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
55037
- out.push(` ${import_picocolors38.default.dim("--all")} for template list: include installs from other folders`);
55038
- out.push(` ${import_picocolors38.default.dim("--web <url>")} for login: web app URL (default https://new.usekafka.com)`);
55672
+ out.push(` ${import_picocolors40.default.dim("--harness <id>")} force harness for onboard / sync (e.g. claude-code)`);
55673
+ out.push(` ${import_picocolors40.default.dim("--scope <s>")} force scope: global | project`);
55674
+ out.push(` ${import_picocolors40.default.dim("--yes, -y")} skip confirmations / auto-overwrite`);
55675
+ out.push(` ${import_picocolors40.default.dim("--agent <id>")} for link: attach this folder to an existing agent non-interactively`);
55676
+ out.push(` ${import_picocolors40.default.dim("--no-tracking")} for link: skip routing LLM traffic through brainbase`);
55677
+ out.push(` ${import_picocolors40.default.dim("--shell <sh|fish>")} for agent env: pick output format (auto-detected from $SHELL)`);
55678
+ out.push(` ${import_picocolors40.default.dim("--all")} for template list: include installs from other folders`);
55679
+ out.push(` ${import_picocolors40.default.dim("--web <url>")} for login: web app URL (default https://new.usekafka.com)`);
55039
55680
  out.push("");
55040
55681
  out.push(divider("ENV"));
55041
55682
  out.push("");
55042
- out.push(` ${import_picocolors38.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
55043
- out.push(` ${import_picocolors38.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
55044
- out.push(` ${import_picocolors38.default.dim("BRAINBASE_API_URL")} override the API URL used by link / sync`);
55045
- out.push(` ${import_picocolors38.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL`);
55046
- out.push(` ${import_picocolors38.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
55047
- out.push(` ${import_picocolors38.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
55683
+ out.push(` ${import_picocolors40.default.dim("BRAINBASE_HOME")} override the local config dir (default ~/.brainbase)`);
55684
+ out.push(` ${import_picocolors40.default.dim("BRAINBASE_WEB_URL")} override the web app URL used by login`);
55685
+ out.push(` ${import_picocolors40.default.dim("BRAINBASE_API_URL")} override the API URL used by link / sync`);
55686
+ out.push(` ${import_picocolors40.default.dim("BRAINBASE_REGISTRY_URL")} override the registry API URL`);
55687
+ out.push(` ${import_picocolors40.default.dim("BRAINBASE_TOKEN")} long-lived CLI PAT (overrides token.json)`);
55688
+ out.push(` ${import_picocolors40.default.dim("BRAINBASE_SKIP_AUTH")} bypass the auth gate for development`);
55048
55689
  out.push("");
55049
55690
  out.push(divider("HARNESSES"));
55050
55691
  out.push("");
55051
- out.push(` ${import_picocolors38.default.dim("•")} ${import_picocolors38.default.bold("claude-code")} ${import_picocolors38.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
55052
- out.push(` ${import_picocolors38.default.dim("•")} ${import_picocolors38.default.bold("codex")} ${import_picocolors38.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
55053
- out.push(` ${import_picocolors38.default.dim("•")} ${import_picocolors38.default.bold("kafka")} ${import_picocolors38.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
55692
+ out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("claude-code")} ${import_picocolors40.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
55693
+ out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("codex")} ${import_picocolors40.default.dim("skills, mcps, commands, playbooks, instructions, files")}`);
55694
+ out.push(` ${import_picocolors40.default.dim("•")} ${import_picocolors40.default.bold("kafka")} ${import_picocolors40.default.dim("skills, mcps, agents, commands, playbooks, instructions, files")}`);
55054
55695
  out.push("");
55055
55696
  console.log(out.join(`
55056
55697
  `));
@@ -55094,13 +55735,13 @@ async function requireAuth(cmd) {
55094
55735
  if (status.ok)
55095
55736
  return;
55096
55737
  console.error("");
55097
- console.error(` ${brandTint("◆")} ${import_picocolors38.default.bold("brainbase")}`);
55738
+ console.error(` ${brandTint("◆")} ${import_picocolors40.default.bold("brainbase")}`);
55098
55739
  console.error("");
55099
- console.error(` ${import_picocolors38.default.red("✗")} You need to sign in to use ${import_picocolors38.default.bold("brainbase " + cmd)}.`);
55740
+ console.error(` ${import_picocolors40.default.red("✗")} You need to sign in to use ${import_picocolors40.default.bold("brainbase " + cmd)}.`);
55100
55741
  if (status.reason)
55101
- console.error(` ${import_picocolors38.default.dim(status.reason)}`);
55742
+ console.error(` ${import_picocolors40.default.dim(status.reason)}`);
55102
55743
  console.error("");
55103
- console.error(` Run ${import_picocolors38.default.cyan("brainbase login")} to connect this device.`);
55744
+ console.error(` Run ${import_picocolors40.default.cyan("brainbase login")} to connect this device.`);
55104
55745
  console.error("");
55105
55746
  process13.exit(1);
55106
55747
  }
@@ -55137,6 +55778,7 @@ async function main() {
55137
55778
  const agentFlag = getFlag(argv, "--agent");
55138
55779
  const shellFlag = getFlag(argv, "--shell");
55139
55780
  const noTracking = hasFlag2(argv, "--no-tracking");
55781
+ const forceFlag = hasFlag2(argv, "--force");
55140
55782
  const graphOnlyFlag = hasFlag2(argv, "--graph-only");
55141
55783
  const nameFlag = getFlag(argv, "--name");
55142
55784
  const skillVersionFlag = getFlag(argv, "--skill-version");
@@ -55221,7 +55863,8 @@ async function main() {
55221
55863
  tagline: taglineFlag,
55222
55864
  orgId: orgIdFlag,
55223
55865
  teamId: teamIdFlag,
55224
- noTracking
55866
+ noTracking,
55867
+ force: forceFlag
55225
55868
  });
55226
55869
  break;
55227
55870
  }
@@ -55252,7 +55895,7 @@ async function main() {
55252
55895
  process13.exit(1);
55253
55896
  }
55254
55897
  } catch (err) {
55255
- console.error(import_picocolors38.default.red(`
55898
+ console.error(import_picocolors40.default.red(`
55256
55899
  ${err.message}`));
55257
55900
  if (process13.env.BRAINBASE_DEBUG)
55258
55901
  console.error(err.stack);