@braid-cloud/cli 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -322,7 +322,7 @@ var init_config = __esm({
322
322
 
323
323
  // src/lib/api.ts
324
324
  import { Data as Data2, Effect as Effect2, pipe as pipe2 } from "effect";
325
- var TRAILING_SLASH_REGEX, ApiError, AuthenticationError, NetworkError, resolveApiKey, resolveServerUrl, parseResponse, buildApiUrl, buildExportUrl, executeApiRequest, parseScopeOptionsResponse, fetchScopeOptions, buildRuleOptionsUrl, fetchRuleOptions, fetchSkills, validateApiKey, fetchSkillsAsync, validateApiKeyAsync, fetchScopeOptionsAsync, fetchRuleOptionsAsync;
325
+ var TRAILING_SLASH_REGEX, ApiError, AuthenticationError, NetworkError, resolveApiKey, resolveServerUrl, parseResponse, buildApiUrl, buildExportUrl, executeApiRequest, parseScopeOptionsResponse, fetchScopeOptions, buildRuleOptionsUrl, fetchRuleOptions, fetchSkills, runLifecycleCommand, DEFAULT_PUBLIC_SERVER_URL, NotFoundError, RateLimitedError, handlePublicApiResponse, fetchPublicMetadata, fetchPublicExport, fetchPublicMetadataAsync, fetchPublicExportAsync, validateApiKey, fetchSkillsAsync, validateApiKeyAsync, fetchScopeOptionsAsync, fetchRuleOptionsAsync, runLifecycleCommandAsync;
326
326
  var init_api = __esm({
327
327
  "src/lib/api.ts"() {
328
328
  "use strict";
@@ -579,6 +579,145 @@ var init_api = __esm({
579
579
  return executeApiRequest(url, apiKey, serverUrl);
580
580
  })
581
581
  );
582
+ runLifecycleCommand = (request, options = {}) => pipe2(
583
+ Effect2.all({
584
+ apiKey: resolveApiKey(options.apiKey),
585
+ serverUrl: resolveServerUrl(options.serverUrl)
586
+ }),
587
+ Effect2.flatMap(
588
+ ({ apiKey, serverUrl }) => Effect2.tryPromise({
589
+ try: async () => {
590
+ const response = await fetch(
591
+ buildApiUrl(serverUrl, "/api/lifecycle").toString(),
592
+ {
593
+ method: "POST",
594
+ headers: {
595
+ Authorization: `Bearer ${apiKey}`,
596
+ "Content-Type": "application/json"
597
+ },
598
+ body: JSON.stringify(request)
599
+ }
600
+ );
601
+ const json = await response.json();
602
+ if (!response.ok) {
603
+ const errorResponse = json;
604
+ if (response.status === 401) {
605
+ throw new AuthenticationError({
606
+ message: errorResponse.error || "Invalid or expired API key. Run 'braid auth' to re-authenticate."
607
+ });
608
+ }
609
+ throw new ApiError({
610
+ message: errorResponse.error || "API request failed",
611
+ code: errorResponse.code || "UNKNOWN_ERROR",
612
+ status: response.status
613
+ });
614
+ }
615
+ return json;
616
+ },
617
+ catch: (error) => {
618
+ if (error instanceof ApiError || error instanceof AuthenticationError || error instanceof NetworkError) {
619
+ return error;
620
+ }
621
+ return new NetworkError({
622
+ message: `Failed to connect to ${serverUrl}`,
623
+ cause: error
624
+ });
625
+ }
626
+ })
627
+ )
628
+ );
629
+ DEFAULT_PUBLIC_SERVER_URL = "https://braid.cloud";
630
+ NotFoundError = class extends Data2.TaggedError("NotFoundError") {
631
+ };
632
+ RateLimitedError = class extends Data2.TaggedError("RateLimitedError") {
633
+ };
634
+ handlePublicApiResponse = (response, json) => {
635
+ if (response.ok) {
636
+ return Effect2.succeed(json);
637
+ }
638
+ if (response.status === 404) {
639
+ return Effect2.fail(
640
+ new NotFoundError({ message: "Public content not found" })
641
+ );
642
+ }
643
+ if (response.status === 429) {
644
+ const retryAfter = response.headers.get("Retry-After");
645
+ const retryMs = retryAfter ? Number(retryAfter) * 1e3 : null;
646
+ return Effect2.fail(
647
+ new RateLimitedError({
648
+ message: "Rate limited. Please try again later.",
649
+ ...retryMs !== null ? { retryAfterMs: retryMs } : {}
650
+ })
651
+ );
652
+ }
653
+ const errorResponse = json;
654
+ return Effect2.fail(
655
+ new ApiError({
656
+ message: errorResponse.error || "API request failed",
657
+ code: errorResponse.code || "UNKNOWN_ERROR",
658
+ status: response.status
659
+ })
660
+ );
661
+ };
662
+ fetchPublicMetadata = (handle, slug, serverUrl) => {
663
+ const baseUrl = (serverUrl ?? DEFAULT_PUBLIC_SERVER_URL).replace(
664
+ TRAILING_SLASH_REGEX,
665
+ ""
666
+ );
667
+ const url = `${baseUrl}/api/public/@${handle}/${slug}`;
668
+ return pipe2(
669
+ Effect2.tryPromise({
670
+ try: () => fetch(url, { method: "GET" }),
671
+ catch: (e) => new NetworkError({
672
+ message: `Failed to connect to ${baseUrl}`,
673
+ cause: e
674
+ })
675
+ }),
676
+ Effect2.flatMap(
677
+ (response) => pipe2(
678
+ Effect2.tryPromise({
679
+ try: () => response.json(),
680
+ catch: () => new NetworkError({ message: "Failed to parse API response" })
681
+ }),
682
+ Effect2.flatMap(
683
+ (json) => handlePublicApiResponse(response, json)
684
+ )
685
+ )
686
+ )
687
+ );
688
+ };
689
+ fetchPublicExport = (handle, slug, ruleIds, serverUrl) => {
690
+ const baseUrl = (serverUrl ?? DEFAULT_PUBLIC_SERVER_URL).replace(
691
+ TRAILING_SLASH_REGEX,
692
+ ""
693
+ );
694
+ const url = new URL(`${baseUrl}/api/public/@${handle}/${slug}/export`);
695
+ if (ruleIds && ruleIds.length > 0) {
696
+ url.searchParams.set("ruleIds", ruleIds.join(","));
697
+ }
698
+ return pipe2(
699
+ Effect2.tryPromise({
700
+ try: () => fetch(url.toString(), { method: "GET" }),
701
+ catch: (e) => new NetworkError({
702
+ message: `Failed to connect to ${baseUrl}`,
703
+ cause: e
704
+ })
705
+ }),
706
+ Effect2.flatMap(
707
+ (response) => pipe2(
708
+ Effect2.tryPromise({
709
+ try: () => response.json(),
710
+ catch: () => new NetworkError({ message: "Failed to parse API response" })
711
+ }),
712
+ Effect2.flatMap(
713
+ (json) => handlePublicApiResponse(response, json)
714
+ )
715
+ )
716
+ )
717
+ );
718
+ };
719
+ fetchPublicMetadataAsync = (handle, slug, serverUrl) => Effect2.runPromise(fetchPublicMetadata(handle, slug, serverUrl));
720
+ fetchPublicExportAsync = (handle, slug, ruleIds, serverUrl) => Effect2.runPromise(fetchPublicExport(handle, slug, ruleIds, serverUrl));
582
721
  validateApiKey = (apiKey, serverUrl) => pipe2(
583
722
  Effect2.tryPromise({
584
723
  try: async () => {
@@ -604,6 +743,7 @@ var init_api = __esm({
604
743
  validateApiKeyAsync = (apiKey, serverUrl) => Effect2.runPromise(validateApiKey(apiKey, serverUrl));
605
744
  fetchScopeOptionsAsync = (options = {}) => Effect2.runPromise(fetchScopeOptions(options));
606
745
  fetchRuleOptionsAsync = (options = {}) => Effect2.runPromise(fetchRuleOptions(options));
746
+ runLifecycleCommandAsync = (request, options = {}) => Effect2.runPromise(runLifecycleCommand(request, options));
607
747
  }
608
748
  });
609
749
 
@@ -922,10 +1062,10 @@ async function selectProjects(organizationContext, scopeOptions) {
922
1062
  }
923
1063
  return selected.length > 0 ? selected : void 0;
924
1064
  }
925
- async function pickRuleIds(message, rules) {
1065
+ async function pickRuleIds(message, rules2) {
926
1066
  const selected = await multiselect({
927
1067
  message,
928
- options: rules.map((rule) => ({
1068
+ options: rules2.map((rule) => ({
929
1069
  value: rule.id,
930
1070
  label: rule.title,
931
1071
  hint: rule.id
@@ -1191,7 +1331,7 @@ async function authCommand(options) {
1191
1331
  return;
1192
1332
  }
1193
1333
  }
1194
- const apiKey = await password({
1334
+ const apiKey = options.token ? options.token : await password({
1195
1335
  message: "Enter your braid API key:",
1196
1336
  validate: (value) => {
1197
1337
  if (!value) {
@@ -1233,7 +1373,9 @@ async function authCommand(options) {
1233
1373
  await saveUserConfigAsync({ ...existingUserConfig, token: apiKey });
1234
1374
  }
1235
1375
  stopAuthSpinner("API key validated and saved");
1236
- await configureDefaultScopeAsync(serverUrl);
1376
+ if (options.scope !== false) {
1377
+ await configureDefaultScopeAsync(serverUrl);
1378
+ }
1237
1379
  log.success(`Config saved to ${CONFIG_FILE}`);
1238
1380
  outro(
1239
1381
  "You're authenticated! Run 'braid install --profile <name>' to install skills."
@@ -1301,6 +1443,142 @@ async function authLogoutCommand() {
1301
1443
  log.success("Logged out. API key removed from config.");
1302
1444
  }
1303
1445
 
1446
+ // src/commands/discover.ts
1447
+ init_esm_shims();
1448
+ init_api();
1449
+ init_config();
1450
+ init_tui();
1451
+ import process6 from "process";
1452
+ var parseCsv = (input) => {
1453
+ if (!input) {
1454
+ return void 0;
1455
+ }
1456
+ const values = input.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
1457
+ return values.length > 0 ? values : void 0;
1458
+ };
1459
+ var writeJson = (value) => {
1460
+ process6.stdout.write(`${JSON.stringify(value, null, 2)}
1461
+ `);
1462
+ };
1463
+ var exitWithError = (error) => {
1464
+ const message = error instanceof Error ? error.message : String(error);
1465
+ log.error(message);
1466
+ process6.exit(1);
1467
+ };
1468
+ var applyCommonOptions = (base, options) => ({
1469
+ ...base,
1470
+ ...options.server ? { serverUrl: options.server } : {},
1471
+ ...options.apiKey ? { apiKey: options.apiKey } : {}
1472
+ });
1473
+ var applyOptionalString = (target, key, value) => {
1474
+ if (value) {
1475
+ target[key] = value;
1476
+ }
1477
+ };
1478
+ var applyOptionalArray = (target, key, value) => {
1479
+ if (value && value.length > 0) {
1480
+ target[key] = value;
1481
+ }
1482
+ };
1483
+ var applyOptionalBoolean = (target, key, value) => {
1484
+ if (value !== void 0) {
1485
+ target[key] = value;
1486
+ }
1487
+ };
1488
+ async function projectsListCommand(options) {
1489
+ try {
1490
+ const result = await fetchScopeOptionsAsync(
1491
+ applyCommonOptions({}, options)
1492
+ );
1493
+ if (options.json) {
1494
+ writeJson(result);
1495
+ return;
1496
+ }
1497
+ log.info("Personal projects:");
1498
+ if (result.personalProjects.length === 0) {
1499
+ log.info(" (none)");
1500
+ }
1501
+ for (const project of result.personalProjects) {
1502
+ log.info(` ${project.id} ${project.name}`);
1503
+ }
1504
+ for (const orgProjects of result.orgProjects) {
1505
+ log.info(`
1506
+ Organization: ${orgProjects.orgName} (${orgProjects.orgId})`);
1507
+ if (orgProjects.projects.length === 0) {
1508
+ log.info(" (none)");
1509
+ continue;
1510
+ }
1511
+ for (const project of orgProjects.projects) {
1512
+ log.info(` ${project.id} ${project.name}`);
1513
+ }
1514
+ }
1515
+ } catch (error) {
1516
+ exitWithError(error);
1517
+ }
1518
+ }
1519
+ var buildRulesRequest = async (options) => {
1520
+ const config = await loadMergedConfigAsync();
1521
+ const orgProjects = parseCsv(options.orgProjects) ?? config.orgProjects;
1522
+ const personalProjects = parseCsv(options.personalProjects) ?? config.personalProjects;
1523
+ const request = applyCommonOptions({}, options);
1524
+ applyOptionalString(request, "orgId", options.orgId ?? config.org);
1525
+ applyOptionalArray(request, "orgProjects", orgProjects);
1526
+ applyOptionalArray(request, "personalProjects", personalProjects);
1527
+ applyOptionalBoolean(request, "includeUserGlobal", options.includeUserGlobal);
1528
+ applyOptionalBoolean(request, "includeOrgGlobal", options.includeOrgGlobal);
1529
+ return request;
1530
+ };
1531
+ async function rulesListCommand(options) {
1532
+ try {
1533
+ const result = await fetchRuleOptionsAsync(
1534
+ await buildRulesRequest(options)
1535
+ );
1536
+ if (options.json) {
1537
+ writeJson(result);
1538
+ return;
1539
+ }
1540
+ if (result.rules.length === 0) {
1541
+ log.info("No rules found.");
1542
+ return;
1543
+ }
1544
+ for (const rule of result.rules) {
1545
+ log.info(`${rule.id} ${rule.title}`);
1546
+ }
1547
+ } catch (error) {
1548
+ exitWithError(error);
1549
+ }
1550
+ }
1551
+ var buildSkillsRequest = async (options) => {
1552
+ const config = await loadMergedConfigAsync();
1553
+ const orgProjects = parseCsv(options.orgProjects) ?? config.orgProjects;
1554
+ const personalProjects = parseCsv(options.personalProjects) ?? config.personalProjects;
1555
+ const request = applyCommonOptions({}, options);
1556
+ applyOptionalString(request, "profile", options.profile ?? config.profile);
1557
+ applyOptionalArray(request, "orgProjects", orgProjects);
1558
+ applyOptionalArray(request, "personalProjects", personalProjects);
1559
+ applyOptionalBoolean(request, "includeUserGlobal", options.includeUserGlobal);
1560
+ applyOptionalBoolean(request, "includeOrgGlobal", options.includeOrgGlobal);
1561
+ return request;
1562
+ };
1563
+ async function skillsListCommand(options) {
1564
+ try {
1565
+ const result = await fetchSkillsAsync(await buildSkillsRequest(options));
1566
+ if (options.json) {
1567
+ writeJson(result);
1568
+ return;
1569
+ }
1570
+ if (result.skills.length === 0) {
1571
+ log.info("No skills found.");
1572
+ return;
1573
+ }
1574
+ for (const skill of result.skills) {
1575
+ log.info(`${skill.name}`);
1576
+ }
1577
+ } catch (error) {
1578
+ exitWithError(error);
1579
+ }
1580
+ }
1581
+
1304
1582
  // src/commands/install.ts
1305
1583
  init_esm_shims();
1306
1584
 
@@ -1309,11 +1587,11 @@ init_esm_shims();
1309
1587
  import { access, constants } from "fs/promises";
1310
1588
  import { homedir as homedir2 } from "os";
1311
1589
  import { join as join2 } from "path";
1312
- import process6 from "process";
1590
+ import process7 from "process";
1313
1591
  import { Effect as Effect3, pipe as pipe3 } from "effect";
1314
1592
  var home = homedir2();
1315
1593
  var vscodeExtSettingsPath = (extensionId, filename) => {
1316
- if (process6.platform === "darwin") {
1594
+ if (process7.platform === "darwin") {
1317
1595
  return join2(
1318
1596
  home,
1319
1597
  "Library",
@@ -1326,8 +1604,8 @@ var vscodeExtSettingsPath = (extensionId, filename) => {
1326
1604
  filename
1327
1605
  );
1328
1606
  }
1329
- if (process6.platform === "win32") {
1330
- const appData = process6.env.APPDATA ?? join2(home, "AppData", "Roaming");
1607
+ if (process7.platform === "win32") {
1608
+ const appData = process7.env.APPDATA ?? join2(home, "AppData", "Roaming");
1331
1609
  return join2(
1332
1610
  appData,
1333
1611
  "Code",
@@ -1350,7 +1628,7 @@ var vscodeExtSettingsPath = (extensionId, filename) => {
1350
1628
  );
1351
1629
  };
1352
1630
  var claudeDesktopConfigPath = () => {
1353
- if (process6.platform === "darwin") {
1631
+ if (process7.platform === "darwin") {
1354
1632
  return join2(
1355
1633
  home,
1356
1634
  "Library",
@@ -1359,8 +1637,8 @@ var claudeDesktopConfigPath = () => {
1359
1637
  "claude_desktop_config.json"
1360
1638
  );
1361
1639
  }
1362
- if (process6.platform === "win32") {
1363
- const appData = process6.env.APPDATA ?? join2(home, "AppData", "Roaming");
1640
+ if (process7.platform === "win32") {
1641
+ const appData = process7.env.APPDATA ?? join2(home, "AppData", "Roaming");
1364
1642
  return join2(appData, "Claude", "claude_desktop_config.json");
1365
1643
  }
1366
1644
  return join2(home, ".config", "Claude", "claude_desktop_config.json");
@@ -1685,7 +1963,7 @@ var directoryExists = (path2) => pipe3(
1685
1963
  Effect3.orElseSucceed(() => false)
1686
1964
  );
1687
1965
  var detectAgents = (projectRoot) => {
1688
- const cwd = projectRoot ?? process6.cwd();
1966
+ const cwd = projectRoot ?? process7.cwd();
1689
1967
  return pipe3(
1690
1968
  Effect3.forEach(
1691
1969
  AGENTS,
@@ -1730,7 +2008,7 @@ var resolveInstallPath = (agent, options) => {
1730
2008
  if (!agent.projectPath) {
1731
2009
  return void 0;
1732
2010
  }
1733
- const cwd = options.projectRoot ?? process6.cwd();
2011
+ const cwd = options.projectRoot ?? process7.cwd();
1734
2012
  return join2(cwd, agent.projectPath);
1735
2013
  };
1736
2014
  var resolveRulesInstallPath = (agent, options) => {
@@ -1740,7 +2018,7 @@ var resolveRulesInstallPath = (agent, options) => {
1740
2018
  if (!agent.rulesProjectPath) {
1741
2019
  return void 0;
1742
2020
  }
1743
- const cwd = options.projectRoot ?? process6.cwd();
2021
+ const cwd = options.projectRoot ?? process7.cwd();
1744
2022
  return join2(cwd, agent.rulesProjectPath);
1745
2023
  };
1746
2024
  var hasMcpConfig = (agent) => Boolean(agent.mcpProjectConfigPath) || Boolean(agent.mcpGlobalConfigPath);
@@ -1749,7 +2027,7 @@ var resolveMcpConfigPath = (agent, options) => {
1749
2027
  return agent.mcpGlobalConfigPath;
1750
2028
  }
1751
2029
  if (agent.mcpProjectConfigPath) {
1752
- const cwd = options.projectRoot ?? process6.cwd();
2030
+ const cwd = options.projectRoot ?? process7.cwd();
1753
2031
  return join2(cwd, agent.mcpProjectConfigPath);
1754
2032
  }
1755
2033
  return agent.mcpGlobalConfigPath;
@@ -1908,9 +2186,9 @@ function buildMdcContent(rule) {
1908
2186
  lines.push(rule.content);
1909
2187
  return lines.join("\n");
1910
2188
  }
1911
- function buildAppendContent(rules) {
2189
+ function buildAppendContent(rules2) {
1912
2190
  const lines = [BRAID_SECTION_START, ""];
1913
- for (const rule of rules) {
2191
+ for (const rule of rules2) {
1914
2192
  lines.push(`## ${rule.title}`);
1915
2193
  lines.push("");
1916
2194
  lines.push(rule.content);
@@ -1919,11 +2197,11 @@ function buildAppendContent(rules) {
1919
2197
  lines.push(BRAID_SECTION_END);
1920
2198
  return lines.join("\n");
1921
2199
  }
1922
- var writeMdcRules = (basePath, rules) => pipe5(
2200
+ var writeMdcRules = (basePath, rules2) => pipe5(
1923
2201
  createDirectory(basePath),
1924
2202
  Effect5.flatMap(
1925
2203
  () => Effect5.forEach(
1926
- rules,
2204
+ rules2,
1927
2205
  (rule) => pipe5(
1928
2206
  assertRulePathWithinBase(basePath, `${rule.name}.mdc`),
1929
2207
  Effect5.flatMap(
@@ -1935,11 +2213,11 @@ var writeMdcRules = (basePath, rules) => pipe5(
1935
2213
  ),
1936
2214
  Effect5.asVoid
1937
2215
  );
1938
- var writeMarkdownDirRules = (basePath, rules) => pipe5(
2216
+ var writeMarkdownDirRules = (basePath, rules2) => pipe5(
1939
2217
  createDirectory(basePath),
1940
2218
  Effect5.flatMap(
1941
2219
  () => Effect5.forEach(
1942
- rules,
2220
+ rules2,
1943
2221
  (rule) => pipe5(
1944
2222
  assertRulePathWithinBase(basePath, `${rule.name}.md`),
1945
2223
  Effect5.flatMap(
@@ -1953,7 +2231,7 @@ ${rule.content}`)
1953
2231
  ),
1954
2232
  Effect5.asVoid
1955
2233
  );
1956
- var writeAppendSingleRules = (filePath, rules) => pipe5(
2234
+ var writeAppendSingleRules = (filePath, rules2) => pipe5(
1957
2235
  createDirectory(dirname2(filePath)),
1958
2236
  Effect5.flatMap(
1959
2237
  () => pipe5(
@@ -1962,7 +2240,7 @@ var writeAppendSingleRules = (filePath, rules) => pipe5(
1962
2240
  )
1963
2241
  ),
1964
2242
  Effect5.flatMap((existing) => {
1965
- const braidContent = buildAppendContent(rules);
2243
+ const braidContent = buildAppendContent(rules2);
1966
2244
  const startIdx = existing.indexOf(BRAID_SECTION_START);
1967
2245
  const endIdx = existing.indexOf(BRAID_SECTION_END);
1968
2246
  let newContent;
@@ -1976,26 +2254,26 @@ ${braidContent}` : braidContent;
1976
2254
  return writeTextFile(filePath, newContent);
1977
2255
  })
1978
2256
  );
1979
- var writeRulesForFormat = (basePath, rules, format) => {
2257
+ var writeRulesForFormat = (basePath, rules2, format) => {
1980
2258
  switch (format) {
1981
2259
  case "mdc":
1982
- return writeMdcRules(basePath, rules);
2260
+ return writeMdcRules(basePath, rules2);
1983
2261
  case "markdown-dir":
1984
- return writeMarkdownDirRules(basePath, rules);
2262
+ return writeMarkdownDirRules(basePath, rules2);
1985
2263
  case "append-single":
1986
- return writeAppendSingleRules(basePath, rules);
2264
+ return writeAppendSingleRules(basePath, rules2);
1987
2265
  default:
1988
2266
  return Effect5.void;
1989
2267
  }
1990
2268
  };
1991
- var writeRulesForAgent = (agent, rules, rulesPath) => {
1992
- if (!agent.ruleFormat || rules.length === 0) {
2269
+ var writeRulesForAgent = (agent, rules2, rulesPath) => {
2270
+ if (!agent.ruleFormat || rules2.length === 0) {
1993
2271
  return Effect5.succeed({ written: 0, errors: [] });
1994
2272
  }
1995
2273
  return pipe5(
1996
- writeRulesForFormat(rulesPath, rules, agent.ruleFormat),
2274
+ writeRulesForFormat(rulesPath, rules2, agent.ruleFormat),
1997
2275
  Effect5.map(() => ({
1998
- written: rules.length,
2276
+ written: rules2.length,
1999
2277
  errors: []
2000
2278
  })),
2001
2279
  Effect5.catchAll(
@@ -2011,7 +2289,7 @@ var writeRulesForAgent = (agent, rules, rulesPath) => {
2011
2289
  )
2012
2290
  );
2013
2291
  };
2014
- var writeRulesForAgentAsync = (agent, rules, rulesPath) => Effect5.runPromise(writeRulesForAgent(agent, rules, rulesPath));
2292
+ var writeRulesForAgentAsync = (agent, rules2, rulesPath) => Effect5.runPromise(writeRulesForAgent(agent, rules2, rulesPath));
2015
2293
 
2016
2294
  // src/lib/skill-writer.ts
2017
2295
  init_esm_shims();
@@ -2120,9 +2398,9 @@ var writeSkill = (basePath, skill, agentId) => pipe6(
2120
2398
  )
2121
2399
  )
2122
2400
  );
2123
- var writeSkills = (basePath, skills, agentId) => pipe6(
2401
+ var writeSkills = (basePath, skills2, agentId) => pipe6(
2124
2402
  Effect6.forEach(
2125
- skills,
2403
+ skills2,
2126
2404
  (skill) => pipe6(
2127
2405
  writeSkill(basePath, skill, agentId),
2128
2406
  Effect6.map(() => ({ success: true, skill: skill.name })),
@@ -2143,7 +2421,7 @@ var writeSkills = (basePath, skills, agentId) => pipe6(
2143
2421
  ).map((r) => ({ skill: r.skill, error: r.error }))
2144
2422
  }))
2145
2423
  );
2146
- var writeSkillsAsync = (basePath, skills, agentId) => Effect6.runPromise(writeSkills(basePath, skills, agentId));
2424
+ var writeSkillsAsync = (basePath, skills2, agentId) => Effect6.runPromise(writeSkills(basePath, skills2, agentId));
2147
2425
 
2148
2426
  // src/commands/install.ts
2149
2427
  init_tui();
@@ -2220,9 +2498,9 @@ function buildFetchOptions(resolved) {
2220
2498
  }
2221
2499
  return fetchOptions;
2222
2500
  }
2223
- function displaySkillsAndExit(skills) {
2501
+ function displaySkillsAndExit(skills2) {
2224
2502
  log.info("\nSkills:");
2225
- for (const skill of skills) {
2503
+ for (const skill of skills2) {
2226
2504
  const fileCount = skill.files.length;
2227
2505
  log.info(
2228
2506
  ` ${skill.name} (${fileCount} file${fileCount !== 1 ? "s" : ""})`
@@ -2330,14 +2608,14 @@ async function installSkillsToAgent(agent, response, installPath) {
2330
2608
  return { written: result.written.length, errors: result.errors.length };
2331
2609
  }
2332
2610
  async function installRulesToAgent(agent, response, options) {
2333
- const rules = response.rules ?? [];
2611
+ const rules2 = response.rules ?? [];
2334
2612
  const rulesPath = resolveRulesInstallPath(agent, {
2335
2613
  global: options.global === true
2336
2614
  });
2337
- if (rules.length === 0 || !rulesPath || !agent.ruleFormat) {
2615
+ if (rules2.length === 0 || !rulesPath || !agent.ruleFormat) {
2338
2616
  return { written: 0, errors: 0 };
2339
2617
  }
2340
- const result = await writeRulesForAgentAsync(agent, rules, rulesPath);
2618
+ const result = await writeRulesForAgentAsync(agent, rules2, rulesPath);
2341
2619
  for (const err of result.errors) {
2342
2620
  log.warn(` Failed rules: ${err.agent} - ${err.error}`);
2343
2621
  }
@@ -2358,17 +2636,17 @@ async function installToAgent(agent, response, serverUrl, options, installSpinne
2358
2636
  global: options.global === true
2359
2637
  });
2360
2638
  installSpinner.start(`Installing to ${agent.name}...`);
2361
- const skills = installPath ? await installSkillsToAgent(agent, response, installPath) : { written: 0, errors: 0 };
2362
- const rules = await installRulesToAgent(agent, response, options);
2363
- const totalWritten = skills.written + rules.written;
2364
- const totalErrors = skills.errors + rules.errors;
2639
+ const skills2 = installPath ? await installSkillsToAgent(agent, response, installPath) : { written: 0, errors: 0 };
2640
+ const rules2 = await installRulesToAgent(agent, response, options);
2641
+ const totalWritten = skills2.written + rules2.written;
2642
+ const totalErrors = skills2.errors + rules2.errors;
2365
2643
  if (totalErrors > 0) {
2366
2644
  installSpinner.stop(
2367
2645
  `${agent.name}: ${totalWritten} installed, ${totalErrors} failed`
2368
2646
  );
2369
2647
  } else {
2370
2648
  installSpinner.stop(
2371
- formatInstallSummary(agent.name, skills.written, rules.written)
2649
+ formatInstallSummary(agent.name, skills2.written, rules2.written)
2372
2650
  );
2373
2651
  }
2374
2652
  if (response.skills.length > 0 && installPath) {
@@ -2384,7 +2662,180 @@ async function installToAgent(agent, response, serverUrl, options, installSpinne
2384
2662
  }
2385
2663
  return { written: totalWritten, errors: totalErrors };
2386
2664
  }
2387
- async function installCommand(options) {
2665
+ var PUBLIC_SOURCE_REGEX = /^@([a-z0-9-]+)\/([a-z0-9-]+)$/;
2666
+ function parsePublicSource(source) {
2667
+ const match = source.match(PUBLIC_SOURCE_REGEX);
2668
+ if (!(match?.[1] && match[2])) {
2669
+ return null;
2670
+ }
2671
+ return { handle: match[1], slug: match[2] };
2672
+ }
2673
+ function displayPublicMetadata(metadata) {
2674
+ if (metadata.type === "project") {
2675
+ const { project, rules: rules2 } = metadata;
2676
+ log.info(`
2677
+ Project: ${project.name}`);
2678
+ if (project.description) {
2679
+ log.info(` ${project.description}`);
2680
+ }
2681
+ log.info(` ${rules2.length} rule(s) available`);
2682
+ } else {
2683
+ const { rule } = metadata;
2684
+ log.info(`
2685
+ Rule: ${rule.title}`);
2686
+ log.info(` Type: ${rule.type}`);
2687
+ if (rule.tags.length > 0) {
2688
+ log.info(` Tags: ${rule.tags.join(", ")}`);
2689
+ }
2690
+ if (rule.description) {
2691
+ log.info(` ${rule.description}`);
2692
+ }
2693
+ }
2694
+ }
2695
+ async function selectPublicRules(metadata, options) {
2696
+ if (metadata.type !== "project") {
2697
+ return null;
2698
+ }
2699
+ if (options.yes) {
2700
+ return metadata.rules.map((r) => r.id);
2701
+ }
2702
+ const selected = await multiselect({
2703
+ message: "Select rules to install:",
2704
+ options: metadata.rules.map((r) => ({
2705
+ value: r.id,
2706
+ label: r.title,
2707
+ hint: r.type
2708
+ })),
2709
+ initialValues: metadata.rules.map((r) => r.id),
2710
+ required: true
2711
+ });
2712
+ if (isCancel(selected)) {
2713
+ cancel("Install cancelled.");
2714
+ process.exit(0);
2715
+ }
2716
+ return selected;
2717
+ }
2718
+ async function confirmRuleInstall(metadata, options) {
2719
+ if (metadata.type !== "rule") {
2720
+ return true;
2721
+ }
2722
+ if (options.yes) {
2723
+ return true;
2724
+ }
2725
+ const confirmed = await confirm({
2726
+ message: `Install "${metadata.rule.title}"?`
2727
+ });
2728
+ if (isCancel(confirmed)) {
2729
+ cancel("Install cancelled.");
2730
+ process.exit(0);
2731
+ }
2732
+ return confirmed === true;
2733
+ }
2734
+ function summarizeContent(response) {
2735
+ const ruleCount = response.rules?.length ?? 0;
2736
+ const skillCount = response.skills.length;
2737
+ const parts = [];
2738
+ if (skillCount > 0) {
2739
+ parts.push(`${skillCount} skills`);
2740
+ }
2741
+ if (ruleCount > 0) {
2742
+ parts.push(`${ruleCount} rules`);
2743
+ }
2744
+ return parts.join(", ") || "nothing";
2745
+ }
2746
+ function hasNoContent(response) {
2747
+ return response.skills.length === 0 && (response.rules?.length ?? 0) === 0;
2748
+ }
2749
+ async function installToSelectedAgents(response, serverUrl, options, installSpinner) {
2750
+ const agentResolution = await resolveAgents(options, installSpinner);
2751
+ const selectedAgents = await selectAgents(
2752
+ agentResolution.availableAgents,
2753
+ agentResolution.preselectedAgents,
2754
+ options
2755
+ );
2756
+ let totalWritten = 0;
2757
+ let totalErrors = 0;
2758
+ for (const agent of selectedAgents) {
2759
+ const result = await installToAgent(
2760
+ agent,
2761
+ response,
2762
+ serverUrl,
2763
+ options,
2764
+ installSpinner
2765
+ );
2766
+ totalWritten += result.written;
2767
+ totalErrors += result.errors;
2768
+ }
2769
+ return { totalWritten, totalErrors };
2770
+ }
2771
+ function showInstallOutro(totalWritten, totalErrors, suffix) {
2772
+ if (totalErrors > 0) {
2773
+ outro(`Installed ${totalWritten} items with ${totalErrors} errors.`);
2774
+ } else {
2775
+ outro(`Successfully installed ${totalWritten} items${suffix}.`);
2776
+ }
2777
+ }
2778
+ async function fetchPublicContent(handle, slug, options, installSpinner) {
2779
+ const metadata = await fetchPublicMetadataAsync(handle, slug, options.server);
2780
+ installSpinner.stop("Found public content");
2781
+ displayPublicMetadata(metadata);
2782
+ let ruleIds;
2783
+ if (metadata.type === "project") {
2784
+ const selected = await selectPublicRules(metadata, options);
2785
+ ruleIds = selected ?? void 0;
2786
+ } else {
2787
+ const confirmed = await confirmRuleInstall(metadata, options);
2788
+ if (!confirmed) {
2789
+ outro("Install cancelled.");
2790
+ process.exit(0);
2791
+ }
2792
+ }
2793
+ installSpinner.start("Downloading content...");
2794
+ return fetchPublicExportAsync(handle, slug, ruleIds, options.server);
2795
+ }
2796
+ async function publicInstallCommand(source, options) {
2797
+ const parsed = parsePublicSource(source);
2798
+ if (!parsed) {
2799
+ log.error(`Invalid public source: ${source}`);
2800
+ log.info("Expected format: @handle/slug (e.g., @acme/coding-standards)");
2801
+ process.exit(1);
2802
+ }
2803
+ const { handle, slug } = parsed;
2804
+ intro(`Installing from @${handle}/${slug}`);
2805
+ const installSpinner = spinner();
2806
+ installSpinner.start("Fetching public content...");
2807
+ try {
2808
+ const response = await fetchPublicContent(
2809
+ handle,
2810
+ slug,
2811
+ options,
2812
+ installSpinner
2813
+ );
2814
+ installSpinner.stop(`Downloaded ${summarizeContent(response)}`);
2815
+ if (hasNoContent(response)) {
2816
+ log.warn("No content to install.");
2817
+ process.exit(0);
2818
+ }
2819
+ const serverUrl = options.server ?? "https://braid.cloud";
2820
+ const { totalWritten, totalErrors } = await installToSelectedAgents(
2821
+ response,
2822
+ serverUrl,
2823
+ options,
2824
+ installSpinner
2825
+ );
2826
+ showInstallOutro(totalWritten, totalErrors, ` from @${handle}/${slug}`);
2827
+ } catch (error) {
2828
+ installSpinner.stop("Install failed");
2829
+ const message = error instanceof Error ? error.message : String(error);
2830
+ log.error(message);
2831
+ process.exit(1);
2832
+ }
2833
+ }
2834
+ async function installCommand(sourceOrOptions, maybeOptions) {
2835
+ if (typeof sourceOrOptions === "string") {
2836
+ return handlePublicSource(sourceOrOptions, maybeOptions ?? {});
2837
+ }
2838
+ const options = sourceOrOptions;
2388
2839
  const config = await loadMergedConfigAsync();
2389
2840
  const resolved = resolveInstallConfig(options, config);
2390
2841
  validateInstallOptions(resolved);
@@ -2395,17 +2846,8 @@ async function installCommand(options) {
2395
2846
  try {
2396
2847
  const fetchOptions = buildFetchOptions(resolved);
2397
2848
  const response = await fetchSkillsAsync(fetchOptions);
2398
- const ruleCount = response.rules?.length ?? 0;
2399
- const skillCount = response.skills.length;
2400
- const foundParts = [];
2401
- if (skillCount > 0) {
2402
- foundParts.push(`${skillCount} skills`);
2403
- }
2404
- if (ruleCount > 0) {
2405
- foundParts.push(`${ruleCount} rules`);
2406
- }
2407
- installSpinner.stop(`Found ${foundParts.join(", ") || "nothing"}`);
2408
- if (skillCount === 0 && ruleCount === 0) {
2849
+ installSpinner.stop(`Found ${summarizeContent(response)}`);
2850
+ if (hasNoContent(response)) {
2409
2851
  log.warn(
2410
2852
  "No skills or rules found. Check that your profile/project has enabled prompts."
2411
2853
  );
@@ -2414,32 +2856,13 @@ async function installCommand(options) {
2414
2856
  if (options.list) {
2415
2857
  displaySkillsAndExit(response.skills);
2416
2858
  }
2417
- const agentResolution = await resolveAgents(options, installSpinner);
2418
- const selectedAgents = await selectAgents(
2419
- agentResolution.availableAgents,
2420
- agentResolution.preselectedAgents,
2421
- options
2859
+ const { totalWritten, totalErrors } = await installToSelectedAgents(
2860
+ response,
2861
+ resolved.serverUrl,
2862
+ options,
2863
+ installSpinner
2422
2864
  );
2423
- let totalWritten = 0;
2424
- let totalErrors = 0;
2425
- for (const agent of selectedAgents) {
2426
- const result = await installToAgent(
2427
- agent,
2428
- response,
2429
- resolved.serverUrl,
2430
- options,
2431
- installSpinner
2432
- );
2433
- totalWritten += result.written;
2434
- totalErrors += result.errors;
2435
- }
2436
- if (totalErrors > 0) {
2437
- outro(`Installed ${totalWritten} items with ${totalErrors} errors.`);
2438
- } else {
2439
- outro(
2440
- `Successfully installed ${totalWritten} items to ${selectedAgents.length} agent(s).`
2441
- );
2442
- }
2865
+ showInstallOutro(totalWritten, totalErrors, ` to ${totalWritten} agent(s)`);
2443
2866
  log.info("Run 'braid list' to see installed skills.");
2444
2867
  } catch (error) {
2445
2868
  installSpinner.stop("Install failed");
@@ -2448,6 +2871,15 @@ async function installCommand(options) {
2448
2871
  process.exit(1);
2449
2872
  }
2450
2873
  }
2874
+ function handlePublicSource(source, options) {
2875
+ const publicParsed = parsePublicSource(source);
2876
+ if (publicParsed) {
2877
+ return publicInstallCommand(source, options);
2878
+ }
2879
+ log.error(`Unknown source: ${source}`);
2880
+ log.info("Public sources use format: @handle/slug");
2881
+ process.exit(1);
2882
+ }
2451
2883
 
2452
2884
  // src/commands/list.ts
2453
2885
  init_esm_shims();
@@ -2545,7 +2977,7 @@ async function listCommand(options) {
2545
2977
 
2546
2978
  // src/commands/mcp.ts
2547
2979
  init_esm_shims();
2548
- import process7 from "process";
2980
+ import process8 from "process";
2549
2981
  init_config();
2550
2982
 
2551
2983
  // src/lib/mcp-config.ts
@@ -2630,7 +3062,7 @@ async function selectTool(mcpAgents, toolFlag) {
2630
3062
  if (!agent) {
2631
3063
  log.error(`Unknown or unsupported tool: ${toolFlag}`);
2632
3064
  log.info(`Supported tools: ${mcpAgents.map((a) => a.id).join(", ")}`);
2633
- process7.exit(1);
3065
+ process8.exit(1);
2634
3066
  }
2635
3067
  return agent;
2636
3068
  }
@@ -2649,12 +3081,12 @@ async function selectTool(mcpAgents, toolFlag) {
2649
3081
  });
2650
3082
  if (isCancel(toolChoice)) {
2651
3083
  cancel("MCP setup cancelled.");
2652
- process7.exit(0);
3084
+ process8.exit(0);
2653
3085
  }
2654
3086
  const found = mcpAgents.find((a) => a.id === toolChoice);
2655
3087
  if (!found) {
2656
3088
  log.error("Agent not found.");
2657
- process7.exit(1);
3089
+ process8.exit(1);
2658
3090
  }
2659
3091
  return found;
2660
3092
  }
@@ -2680,7 +3112,7 @@ async function selectScope(agent, options) {
2680
3112
  });
2681
3113
  if (isCancel(scopeChoice)) {
2682
3114
  cancel("MCP setup cancelled.");
2683
- process7.exit(0);
3115
+ process8.exit(0);
2684
3116
  }
2685
3117
  return scopeChoice;
2686
3118
  }
@@ -2711,7 +3143,7 @@ async function resolveToken(options, existingToken) {
2711
3143
  });
2712
3144
  if (isCancel(authChoice)) {
2713
3145
  cancel("MCP setup cancelled.");
2714
- process7.exit(0);
3146
+ process8.exit(0);
2715
3147
  }
2716
3148
  if (authChoice === "existing") {
2717
3149
  return existingToken;
@@ -2734,7 +3166,7 @@ async function resolveToken(options, existingToken) {
2734
3166
  });
2735
3167
  if (isCancel(token)) {
2736
3168
  cancel("MCP setup cancelled.");
2737
- process7.exit(0);
3169
+ process8.exit(0);
2738
3170
  }
2739
3171
  return token;
2740
3172
  }
@@ -2765,7 +3197,7 @@ async function addFlow(options) {
2765
3197
  const mcpAgents = getMcpAgents();
2766
3198
  if (mcpAgents.length === 0) {
2767
3199
  log.error("No agents with MCP configuration support found.");
2768
- process7.exit(1);
3200
+ process8.exit(1);
2769
3201
  }
2770
3202
  const selectedAgent = await selectTool(mcpAgents, options.tool);
2771
3203
  const scope = await selectScope(selectedAgent, options);
@@ -2774,7 +3206,7 @@ async function addFlow(options) {
2774
3206
  });
2775
3207
  if (!configPath) {
2776
3208
  log.error(`No ${scope} config path available for ${selectedAgent.name}.`);
2777
- process7.exit(1);
3209
+ process8.exit(1);
2778
3210
  }
2779
3211
  const token = await resolveToken(options, config.token);
2780
3212
  const env = buildEnvVars(token, options.server);
@@ -2799,7 +3231,7 @@ async function addFlow(options) {
2799
3231
  mcpSpinner.stop("Configuration failed");
2800
3232
  const message = error instanceof Error ? error.message : String(error);
2801
3233
  log.error(`Failed to write config: ${message}`);
2802
- process7.exit(1);
3234
+ process8.exit(1);
2803
3235
  }
2804
3236
  }
2805
3237
  async function removeFlow(options) {
@@ -2811,7 +3243,7 @@ async function removeFlow(options) {
2811
3243
  });
2812
3244
  if (!configPath) {
2813
3245
  log.error(`No ${scope} config path available for ${selectedAgent.name}.`);
2814
- process7.exit(1);
3246
+ process8.exit(1);
2815
3247
  }
2816
3248
  const removeSpinner = spinner();
2817
3249
  removeSpinner.start(`Removing braid from ${selectedAgent.name}...`);
@@ -2837,7 +3269,7 @@ async function removeFlow(options) {
2837
3269
  removeSpinner.stop("Removal failed");
2838
3270
  const message = error instanceof Error ? error.message : String(error);
2839
3271
  log.error(`Failed to remove config: ${message}`);
2840
- process7.exit(1);
3272
+ process8.exit(1);
2841
3273
  }
2842
3274
  }
2843
3275
  async function statusFlow() {
@@ -2874,7 +3306,27 @@ async function statusFlow() {
2874
3306
  log.info(` ${result.name} (${result.scope}) \u2192 ${result.path}`);
2875
3307
  }
2876
3308
  }
3309
+ function helpCommandsFlow() {
3310
+ log.info("MCP manual command reference:");
3311
+ log.info(" braid projects list --json");
3312
+ log.info(" braid rules list --json");
3313
+ log.info(" braid skills list --profile <name> --json");
3314
+ log.info("");
3315
+ log.info("Common local management commands:");
3316
+ log.info(" braid install --yes --profile <name>");
3317
+ log.info(" braid update --yes");
3318
+ log.info(" braid list");
3319
+ log.info(" braid remove --yes --all");
3320
+ log.info(
3321
+ " braid scope --file user --organization personal --source profile --profile <name>"
3322
+ );
3323
+ }
2877
3324
  async function mcpCommand(options) {
3325
+ if (options.helpCommands) {
3326
+ intro("braid mcp help");
3327
+ helpCommandsFlow();
3328
+ return;
3329
+ }
2878
3330
  if (options.status) {
2879
3331
  intro("braid mcp status");
2880
3332
  await statusFlow();
@@ -2889,11 +3341,306 @@ async function mcpCommand(options) {
2889
3341
  await addFlow(options);
2890
3342
  }
2891
3343
 
3344
+ // src/commands/profiles.ts
3345
+ init_esm_shims();
3346
+ init_api();
3347
+ init_tui();
3348
+ import process9 from "process";
3349
+ var writeJson2 = (value) => {
3350
+ process9.stdout.write(`${JSON.stringify(value, null, 2)}
3351
+ `);
3352
+ };
3353
+ var exitWithError2 = (error) => {
3354
+ const message = error instanceof Error ? error.message : String(error);
3355
+ log.error(message);
3356
+ process9.exit(1);
3357
+ };
3358
+ var fail = (message) => {
3359
+ throw new Error(message);
3360
+ };
3361
+ var parseContext = (contextJson) => {
3362
+ if (!contextJson) {
3363
+ return void 0;
3364
+ }
3365
+ return JSON.parse(contextJson);
3366
+ };
3367
+ var run = async (command, args, options) => {
3368
+ const apiOptions = {
3369
+ ...options.server ? { serverUrl: options.server } : {},
3370
+ ...options.apiKey ? { apiKey: options.apiKey } : {}
3371
+ };
3372
+ const result = await runLifecycleCommandAsync(
3373
+ {
3374
+ domain: "profiles",
3375
+ command,
3376
+ args
3377
+ },
3378
+ apiOptions
3379
+ );
3380
+ if (options.json) {
3381
+ writeJson2(result);
3382
+ return;
3383
+ }
3384
+ log.success(`profiles ${command} completed`);
3385
+ };
3386
+ async function profilesListCommand(options) {
3387
+ try {
3388
+ await run("list", {}, options);
3389
+ } catch (error) {
3390
+ exitWithError2(error);
3391
+ }
3392
+ }
3393
+ async function profilesGetCommand(options) {
3394
+ try {
3395
+ if (!(options.id || options.name)) {
3396
+ fail("profiles get requires --id or --name");
3397
+ }
3398
+ await run("get", { id: options.id, name: options.name }, options);
3399
+ } catch (error) {
3400
+ exitWithError2(error);
3401
+ }
3402
+ }
3403
+ async function profilesCreateCommand(options) {
3404
+ try {
3405
+ const name = options.name ?? fail("profiles create requires --name");
3406
+ await run(
3407
+ "create",
3408
+ { name, context: parseContext(options.contextJson) },
3409
+ options
3410
+ );
3411
+ } catch (error) {
3412
+ exitWithError2(error);
3413
+ }
3414
+ }
3415
+ async function profilesUpdateCommand(options) {
3416
+ try {
3417
+ const id = options.id ?? fail("profiles update requires --id");
3418
+ await run(
3419
+ "update",
3420
+ {
3421
+ id,
3422
+ name: options.name,
3423
+ context: parseContext(options.contextJson)
3424
+ },
3425
+ options
3426
+ );
3427
+ } catch (error) {
3428
+ exitWithError2(error);
3429
+ }
3430
+ }
3431
+ async function profilesRemoveCommand(options) {
3432
+ try {
3433
+ const id = options.id ?? fail("profiles remove requires --id");
3434
+ if (!options.yes) {
3435
+ fail("profiles remove requires --yes");
3436
+ }
3437
+ await run("remove", { id, yes: true }, options);
3438
+ } catch (error) {
3439
+ exitWithError2(error);
3440
+ }
3441
+ }
3442
+ async function profilesSetDefaultCommand(options) {
3443
+ try {
3444
+ const id = options.id ?? fail("profiles set-default requires --id");
3445
+ await run("set-default", { id }, options);
3446
+ } catch (error) {
3447
+ exitWithError2(error);
3448
+ }
3449
+ }
3450
+
3451
+ // src/commands/projects.ts
3452
+ init_esm_shims();
3453
+ init_api();
3454
+ init_tui();
3455
+ import process10 from "process";
3456
+ var writeJson3 = (value) => {
3457
+ process10.stdout.write(`${JSON.stringify(value, null, 2)}
3458
+ `);
3459
+ };
3460
+ var fail2 = (message) => {
3461
+ throw new Error(message);
3462
+ };
3463
+ var run2 = async (command, args, options) => {
3464
+ const apiOptions = {
3465
+ ...options.server ? { serverUrl: options.server } : {},
3466
+ ...options.apiKey ? { apiKey: options.apiKey } : {}
3467
+ };
3468
+ const result = await runLifecycleCommandAsync(
3469
+ {
3470
+ domain: "projects",
3471
+ command,
3472
+ args
3473
+ },
3474
+ apiOptions
3475
+ );
3476
+ if (options.json) {
3477
+ writeJson3(result);
3478
+ return;
3479
+ }
3480
+ log.success(`projects ${command} completed`);
3481
+ };
3482
+ var exitWithError3 = (error) => {
3483
+ const message = error instanceof Error ? error.message : String(error);
3484
+ log.error(message);
3485
+ process10.exit(1);
3486
+ };
3487
+ async function projectsGetCommand(options) {
3488
+ try {
3489
+ const id = options.id ?? fail2("projects get requires --id");
3490
+ await run2("get", { id }, options);
3491
+ } catch (error) {
3492
+ exitWithError3(error);
3493
+ }
3494
+ }
3495
+ async function projectsCreateCommand(options) {
3496
+ try {
3497
+ const name = options.name ?? fail2("projects create requires --name");
3498
+ await run2(
3499
+ "create",
3500
+ { name, description: options.description, orgId: options.orgId },
3501
+ options
3502
+ );
3503
+ } catch (error) {
3504
+ exitWithError3(error);
3505
+ }
3506
+ }
3507
+ async function projectsUpdateCommand(options) {
3508
+ try {
3509
+ const id = options.id ?? fail2("projects update requires --id");
3510
+ await run2(
3511
+ "update",
3512
+ {
3513
+ id,
3514
+ name: options.name,
3515
+ description: options.description
3516
+ },
3517
+ options
3518
+ );
3519
+ } catch (error) {
3520
+ exitWithError3(error);
3521
+ }
3522
+ }
3523
+ async function projectsRemoveCommand(options) {
3524
+ try {
3525
+ const id = options.id ?? fail2("projects remove requires --id");
3526
+ if (!options.yes) {
3527
+ fail2("projects remove requires --yes");
3528
+ }
3529
+ await run2("remove", { id, yes: true }, options);
3530
+ } catch (error) {
3531
+ exitWithError3(error);
3532
+ }
3533
+ }
3534
+
3535
+ // src/commands/references.ts
3536
+ init_esm_shims();
3537
+ init_api();
3538
+ init_tui();
3539
+ import process11 from "process";
3540
+ var writeJson4 = (value) => {
3541
+ process11.stdout.write(`${JSON.stringify(value, null, 2)}
3542
+ `);
3543
+ };
3544
+ var parseCsv2 = (input) => {
3545
+ if (!input) {
3546
+ return void 0;
3547
+ }
3548
+ const values = input.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
3549
+ return values.length > 0 ? values : void 0;
3550
+ };
3551
+ var exitWithError4 = (error) => {
3552
+ const message = error instanceof Error ? error.message : String(error);
3553
+ log.error(message);
3554
+ process11.exit(1);
3555
+ };
3556
+ var fail3 = (message) => {
3557
+ throw new Error(message);
3558
+ };
3559
+ var run3 = async (command, args, options) => {
3560
+ const apiOptions = {
3561
+ ...options.server ? { serverUrl: options.server } : {},
3562
+ ...options.apiKey ? { apiKey: options.apiKey } : {}
3563
+ };
3564
+ const result = await runLifecycleCommandAsync(
3565
+ {
3566
+ domain: "references",
3567
+ command,
3568
+ args
3569
+ },
3570
+ apiOptions
3571
+ );
3572
+ if (options.json) {
3573
+ writeJson4(result);
3574
+ return;
3575
+ }
3576
+ log.success(`references ${command} completed`);
3577
+ };
3578
+ async function referencesListCommand(options) {
3579
+ try {
3580
+ const ruleId = options.ruleId ?? fail3("references list requires --rule-id");
3581
+ await run3("list", { ruleId }, options);
3582
+ } catch (error) {
3583
+ exitWithError4(error);
3584
+ }
3585
+ }
3586
+ async function referencesGetCommand(options) {
3587
+ try {
3588
+ const id = options.id ?? fail3("references get requires --id");
3589
+ await run3("get", { id }, options);
3590
+ } catch (error) {
3591
+ exitWithError4(error);
3592
+ }
3593
+ }
3594
+ async function referencesCreateCommand(options) {
3595
+ try {
3596
+ const ruleId = options.ruleId ?? fail3("references create requires --rule-id");
3597
+ const file = options.file ?? fail3("references create requires --file");
3598
+ await run3("create", { ruleId, file }, options);
3599
+ } catch (error) {
3600
+ exitWithError4(error);
3601
+ }
3602
+ }
3603
+ async function referencesUpdateCommand(options) {
3604
+ try {
3605
+ const id = options.id ?? fail3("references update requires --id");
3606
+ await run3(
3607
+ "update",
3608
+ { id, label: options.label, replaceFile: options.replaceFile },
3609
+ options
3610
+ );
3611
+ } catch (error) {
3612
+ exitWithError4(error);
3613
+ }
3614
+ }
3615
+ async function referencesRemoveCommand(options) {
3616
+ try {
3617
+ const id = options.id ?? fail3("references remove requires --id");
3618
+ if (!options.yes) {
3619
+ fail3("references remove requires --yes");
3620
+ }
3621
+ await run3("remove", { id, yes: true }, options);
3622
+ } catch (error) {
3623
+ exitWithError4(error);
3624
+ }
3625
+ }
3626
+ async function referencesReorderCommand(options) {
3627
+ try {
3628
+ const ruleId = options.ruleId ?? fail3("references reorder requires --rule-id");
3629
+ const orderedIds = parseCsv2(options.orderedIds);
3630
+ if (!orderedIds || orderedIds.length === 0) {
3631
+ fail3("references reorder requires --ordered-ids");
3632
+ }
3633
+ await run3("reorder", { ruleId, orderedIds }, options);
3634
+ } catch (error) {
3635
+ exitWithError4(error);
3636
+ }
3637
+ }
3638
+
2892
3639
  // src/commands/remove.ts
2893
3640
  init_esm_shims();
2894
3641
  import { rm } from "fs/promises";
2895
3642
  import { join as join4, resolve as resolve3 } from "path";
2896
- import process8 from "process";
3643
+ import process12 from "process";
2897
3644
  init_tui();
2898
3645
  async function collectInstalledSkills(detectedAgents, options) {
2899
3646
  const skillsToRemove = [];
@@ -2926,7 +3673,7 @@ async function selectSkillsToRemove(skillsToRemove, options) {
2926
3673
  if (selected.length === 0) {
2927
3674
  log.error(`Skill '${options.skill}' not found.`);
2928
3675
  log.info("Run 'braid list' to see installed skills.");
2929
- process8.exit(1);
3676
+ process12.exit(1);
2930
3677
  }
2931
3678
  return selected;
2932
3679
  }
@@ -2945,7 +3692,7 @@ async function selectSkillsToRemove(skillsToRemove, options) {
2945
3692
  });
2946
3693
  if (isCancel(result)) {
2947
3694
  cancel("Remove cancelled.");
2948
- process8.exit(0);
3695
+ process12.exit(0);
2949
3696
  }
2950
3697
  return result;
2951
3698
  }
@@ -2959,7 +3706,7 @@ async function confirmRemoval(selectedCount, options) {
2959
3706
  });
2960
3707
  if (isCancel(confirmed) || !confirmed) {
2961
3708
  cancel("Remove cancelled.");
2962
- process8.exit(0);
3709
+ process12.exit(0);
2963
3710
  }
2964
3711
  }
2965
3712
  async function removeSkill(skill, removeSpinner) {
@@ -3023,7 +3770,203 @@ async function removeCommand(options) {
3023
3770
  removeSpinner.stop("Remove failed");
3024
3771
  const message = error instanceof Error ? error.message : String(error);
3025
3772
  log.error(message);
3026
- process8.exit(1);
3773
+ process12.exit(1);
3774
+ }
3775
+ }
3776
+
3777
+ // src/commands/rules.ts
3778
+ init_esm_shims();
3779
+ init_api();
3780
+ init_tui();
3781
+ import process13 from "process";
3782
+ var parseCsv3 = (input) => {
3783
+ if (!input) {
3784
+ return void 0;
3785
+ }
3786
+ const values = input.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
3787
+ return values.length > 0 ? values : void 0;
3788
+ };
3789
+ var writeJson5 = (value) => {
3790
+ process13.stdout.write(`${JSON.stringify(value, null, 2)}
3791
+ `);
3792
+ };
3793
+ var exitWithError5 = (error) => {
3794
+ const message = error instanceof Error ? error.message : String(error);
3795
+ log.error(message);
3796
+ process13.exit(1);
3797
+ };
3798
+ var fail4 = (message) => {
3799
+ throw new Error(message);
3800
+ };
3801
+ var run4 = async (command, args, options) => {
3802
+ const apiOptions = {
3803
+ ...options.server ? { serverUrl: options.server } : {},
3804
+ ...options.apiKey ? { apiKey: options.apiKey } : {}
3805
+ };
3806
+ const result = await runLifecycleCommandAsync(
3807
+ {
3808
+ domain: "rules",
3809
+ command,
3810
+ args
3811
+ },
3812
+ apiOptions
3813
+ );
3814
+ if (options.json) {
3815
+ writeJson5(result);
3816
+ return;
3817
+ }
3818
+ log.success(`rules ${command} completed`);
3819
+ };
3820
+ async function rulesGetCommand(options) {
3821
+ try {
3822
+ const id = options.id ?? fail4("rules get requires --id");
3823
+ await run4("get", { id }, options);
3824
+ } catch (error) {
3825
+ exitWithError5(error);
3826
+ }
3827
+ }
3828
+ async function rulesCreateCommand(options) {
3829
+ try {
3830
+ const title = options.title ?? fail4("rules create requires --title");
3831
+ const content = options.content ?? fail4("rules create requires --content");
3832
+ await run4(
3833
+ "create",
3834
+ {
3835
+ title,
3836
+ content,
3837
+ projectId: options.projectId,
3838
+ tags: parseCsv3(options.tags),
3839
+ priority: options.priority
3840
+ },
3841
+ options
3842
+ );
3843
+ } catch (error) {
3844
+ exitWithError5(error);
3845
+ }
3846
+ }
3847
+ async function rulesUpdateCommand(options) {
3848
+ try {
3849
+ const id = options.id ?? fail4("rules update requires --id");
3850
+ await run4(
3851
+ "update",
3852
+ {
3853
+ id,
3854
+ title: options.title,
3855
+ content: options.content,
3856
+ tags: parseCsv3(options.tags),
3857
+ priority: options.priority
3858
+ },
3859
+ options
3860
+ );
3861
+ } catch (error) {
3862
+ exitWithError5(error);
3863
+ }
3864
+ }
3865
+ async function rulesRemoveCommand(options) {
3866
+ try {
3867
+ const id = options.id ?? fail4("rules remove requires --id");
3868
+ if (!options.yes) {
3869
+ fail4("rules remove requires --yes");
3870
+ }
3871
+ await run4("remove", { id, yes: true }, options);
3872
+ } catch (error) {
3873
+ exitWithError5(error);
3874
+ }
3875
+ }
3876
+ async function rulesEnableCommand(options) {
3877
+ try {
3878
+ const id = options.id ?? fail4("rules enable requires --id");
3879
+ await run4("enable", { id }, options);
3880
+ } catch (error) {
3881
+ exitWithError5(error);
3882
+ }
3883
+ }
3884
+ async function rulesDisableCommand(options) {
3885
+ try {
3886
+ const id = options.id ?? fail4("rules disable requires --id");
3887
+ await run4("disable", { id }, options);
3888
+ } catch (error) {
3889
+ exitWithError5(error);
3890
+ }
3891
+ }
3892
+ async function rulesMoveCommand(options) {
3893
+ try {
3894
+ const id = options.id ?? fail4("rules move requires --id");
3895
+ const projectId = options.projectId ?? fail4("rules move requires --project-id");
3896
+ await run4("move", { id, projectId }, options);
3897
+ } catch (error) {
3898
+ exitWithError5(error);
3899
+ }
3900
+ }
3901
+ async function rulesDuplicateCommand(options) {
3902
+ try {
3903
+ const id = options.id ?? fail4("rules duplicate requires --id");
3904
+ await run4(
3905
+ "duplicate",
3906
+ { id, targetProjectId: options.targetProjectId },
3907
+ options
3908
+ );
3909
+ } catch (error) {
3910
+ exitWithError5(error);
3911
+ }
3912
+ }
3913
+ async function rulesForkCommand(options) {
3914
+ try {
3915
+ const id = options.id ?? fail4("rules fork requires --id");
3916
+ await run4(
3917
+ "fork",
3918
+ { id, targetProjectId: options.targetProjectId },
3919
+ options
3920
+ );
3921
+ } catch (error) {
3922
+ exitWithError5(error);
3923
+ }
3924
+ }
3925
+ async function rulesSyncStatusCommand(options) {
3926
+ try {
3927
+ await run4("sync-status", { id: options.id }, options);
3928
+ } catch (error) {
3929
+ exitWithError5(error);
3930
+ }
3931
+ }
3932
+ async function rulesSyncHistoryCommand(options) {
3933
+ try {
3934
+ const id = options.id ?? fail4("rules sync-history requires --id");
3935
+ await run4("sync-history", { id }, options);
3936
+ } catch (error) {
3937
+ exitWithError5(error);
3938
+ }
3939
+ }
3940
+ async function rulesSyncEnableCommand(options) {
3941
+ try {
3942
+ const id = options.id ?? fail4("rules sync-enable requires --id");
3943
+ await run4("sync-enable", { id }, options);
3944
+ } catch (error) {
3945
+ exitWithError5(error);
3946
+ }
3947
+ }
3948
+ async function rulesSyncDisableCommand(options) {
3949
+ try {
3950
+ const id = options.id ?? fail4("rules sync-disable requires --id");
3951
+ await run4("sync-disable", { id }, options);
3952
+ } catch (error) {
3953
+ exitWithError5(error);
3954
+ }
3955
+ }
3956
+ async function rulesSyncCheckCommand(options) {
3957
+ try {
3958
+ const id = options.id ?? fail4("rules sync-check requires --id");
3959
+ await run4("sync-check", { id }, options);
3960
+ } catch (error) {
3961
+ exitWithError5(error);
3962
+ }
3963
+ }
3964
+ async function rulesSyncNowCommand(options) {
3965
+ try {
3966
+ const id = options.id ?? fail4("rules sync-now requires --id");
3967
+ await run4("sync-now", { id }, options);
3968
+ } catch (error) {
3969
+ exitWithError5(error);
3027
3970
  }
3028
3971
  }
3029
3972
 
@@ -3329,10 +4272,12 @@ program.name("braid").description(
3329
4272
  "Install braid prompts as agent skills to your local development environment"
3330
4273
  ).version(PACKAGE_VERSION);
3331
4274
  var auth = program.command("auth").description("Configure API key for braid authentication");
3332
- auth.command("login", { isDefault: true }).description("Configure API key").option("-s, --server <url>", "braid server URL (for review apps, local dev)").action(authCommand);
4275
+ auth.command("login", { isDefault: true }).description("Configure API key").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--token <token>", "API key for non-interactive login").option("--no-scope", "Skip scope setup after login").action(authCommand);
3333
4276
  auth.command("status").description("Show current authentication status").action(authStatusCommand);
3334
4277
  auth.command("logout").description("Remove stored API key").action(authLogoutCommand);
3335
- program.command("install").alias("add").description("Install skills from a profile or project").option("-p, --profile <name>", "Profile name to install from").option(
4278
+ program.command("install").alias("add").description(
4279
+ "Install skills from a profile, project, or public source (@handle/slug)"
4280
+ ).argument("[source]", "Public source to install from (e.g., @handle/slug)").option("-p, --profile <name>", "Profile name to install from").option(
3336
4281
  "--org-projects <ids>",
3337
4282
  "Comma-separated organization project IDs to install from"
3338
4283
  ).option(
@@ -3347,7 +4292,12 @@ program.command("install").alias("add").description("Install skills from a profi
3347
4292
  ).option("--no-include-org-globals", "Exclude organization's global prompts").option(
3348
4293
  "-a, --agents <list>",
3349
4294
  "Comma-separated list of agents (e.g., claude-code,opencode)"
3350
- ).option("-g, --global", "Install to global agent directories").option("-y, --yes", "Skip confirmation prompts").option("-l, --list", "Preview skills without installing").option("-s, --server <url>", "braid server URL (for review apps, local dev)").action(installCommand);
4295
+ ).option("-g, --global", "Install to global agent directories").option("-y, --yes", "Skip confirmation prompts").option("-l, --list", "Preview skills without installing").option("-s, --server <url>", "braid server URL (for review apps, local dev)").action((source, options) => {
4296
+ if (source) {
4297
+ return installCommand(source, options);
4298
+ }
4299
+ return installCommand(options);
4300
+ });
3351
4301
  program.command("scope").description("Interactively configure braid.json or braid.user.json scope").option("--file <target>", "Config file target: user or project").option(
3352
4302
  "--organization <type>",
3353
4303
  "Scope organization for non-interactive mode: personal or organization"
@@ -3371,8 +4321,47 @@ program.command("scope").description("Interactively configure braid.json or brai
3371
4321
  "Include org global rules in non-interactive mode"
3372
4322
  ).option("-s, --server <url>", "braid server URL (for review apps, local dev)").action(scopeCommand);
3373
4323
  program.command("list").alias("ls").description("List installed skills").option("-g, --global", "List skills in global directories only").action(listCommand);
4324
+ var projects = program.command("projects").description("Discover available projects from braid");
4325
+ projects.command("list").description("List available personal and org projects").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(projectsListCommand);
4326
+ projects.command("get").description("Get a project by id").requiredOption("--id <id>", "Project ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(projectsGetCommand);
4327
+ projects.command("create").description("Create a project").requiredOption("--name <name>", "Project name").option("--description <description>", "Project description").option("--org-id <id>", "Organization ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(projectsCreateCommand);
4328
+ projects.command("update").description("Update a project").requiredOption("--id <id>", "Project ID").option("--name <name>", "Project name").option("--description <description>", "Project description").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(projectsUpdateCommand);
4329
+ projects.command("remove").description("Remove a project").requiredOption("--id <id>", "Project ID").option("-y, --yes", "Confirm destructive action").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(projectsRemoveCommand);
4330
+ var rules = program.command("rules").description("Discover available rules from braid");
4331
+ rules.command("list").description("List available rules for a scope").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--org-id <id>", "Organization ID").option("--org-projects <ids>", "Comma-separated organization project IDs").option("--personal-projects <ids>", "Comma-separated personal project IDs").option("--include-user-global", "Include personal global rules").option("--include-org-global", "Include org global rules").option("--json", "Output JSON").action(rulesListCommand);
4332
+ rules.command("get").description("Get a rule by id").requiredOption("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesGetCommand);
4333
+ rules.command("create").description("Create a rule").requiredOption("--title <title>", "Rule title").requiredOption("--content <content>", "Rule content").option("--project-id <id>", "Project ID").option("--tags <list>", "Comma-separated tags").option("--priority <priority>", "Priority").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesCreateCommand);
4334
+ rules.command("update").description("Update a rule").requiredOption("--id <id>", "Rule ID").option("--title <title>", "Rule title").option("--content <content>", "Rule content").option("--tags <list>", "Comma-separated tags").option("--priority <priority>", "Priority").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesUpdateCommand);
4335
+ rules.command("remove").description("Remove a rule").requiredOption("--id <id>", "Rule ID").option("-y, --yes", "Confirm destructive action").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesRemoveCommand);
4336
+ rules.command("enable").description("Enable a rule").requiredOption("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesEnableCommand);
4337
+ rules.command("disable").description("Disable a rule").requiredOption("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesDisableCommand);
4338
+ rules.command("move").description("Move a rule to a project").requiredOption("--id <id>", "Rule ID").requiredOption("--project-id <id>", "Project ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesMoveCommand);
4339
+ rules.command("duplicate").description("Duplicate a rule").requiredOption("--id <id>", "Rule ID").option("--target-project-id <id>", "Target project ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesDuplicateCommand);
4340
+ rules.command("fork").description("Fork a rule").requiredOption("--id <id>", "Rule ID").option("--target-project-id <id>", "Target project ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesForkCommand);
4341
+ rules.command("sync-status").description("Show sync status for one rule or all").option("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesSyncStatusCommand);
4342
+ rules.command("sync-history").description("Show sync history for a rule").requiredOption("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesSyncHistoryCommand);
4343
+ rules.command("sync-enable").description("Enable sync for a rule").requiredOption("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesSyncEnableCommand);
4344
+ rules.command("sync-disable").description("Disable sync for a rule").requiredOption("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesSyncDisableCommand);
4345
+ rules.command("sync-check").description("Check for upstream updates").requiredOption("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesSyncCheckCommand);
4346
+ rules.command("sync-now").description("Run sync now").requiredOption("--id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(rulesSyncNowCommand);
4347
+ var skills = program.command("skills").description("Discover available skills from braid");
4348
+ skills.command("list").description("List available skills for a profile or project scope").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("-p, --profile <name>", "Profile name").option("--org-projects <ids>", "Comma-separated organization project IDs").option("--personal-projects <ids>", "Comma-separated personal project IDs").option("--include-user-global", "Include personal global rules").option("--include-org-global", "Include org global rules").option("--json", "Output JSON").action(skillsListCommand);
4349
+ var profiles = program.command("profiles").description("Manage scope profiles");
4350
+ profiles.command("list").description("List profiles").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(profilesListCommand);
4351
+ profiles.command("get").description("Get profile by id or name").option("--id <id>", "Profile ID").option("--name <name>", "Profile name").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(profilesGetCommand);
4352
+ profiles.command("create").description("Create profile").requiredOption("--name <name>", "Profile name").option("--context-json <json>", "Context JSON").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(profilesCreateCommand);
4353
+ profiles.command("update").description("Update profile").requiredOption("--id <id>", "Profile ID").option("--name <name>", "Profile name").option("--context-json <json>", "Context JSON").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(profilesUpdateCommand);
4354
+ profiles.command("remove").description("Remove profile").requiredOption("--id <id>", "Profile ID").option("-y, --yes", "Confirm destructive action").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(profilesRemoveCommand);
4355
+ profiles.command("set-default").description("Set default profile").requiredOption("--id <id>", "Profile ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(profilesSetDefaultCommand);
4356
+ var references = program.command("references").description("Manage rule references");
4357
+ references.command("list").description("List references for a rule").requiredOption("--rule-id <id>", "Rule ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(referencesListCommand);
4358
+ references.command("get").description("Get a reference by id").requiredOption("--id <id>", "Reference ID").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(referencesGetCommand);
4359
+ references.command("create").description("Create a reference from file").requiredOption("--rule-id <id>", "Rule ID").requiredOption("--file <path>", "Reference file path").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(referencesCreateCommand);
4360
+ references.command("update").description("Update reference metadata").requiredOption("--id <id>", "Reference ID").option("--label <label>", "Reference label").option("--replace-file <path>", "Replace reference with file").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(referencesUpdateCommand);
4361
+ references.command("remove").description("Remove reference").requiredOption("--id <id>", "Reference ID").option("-y, --yes", "Confirm destructive action").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(referencesRemoveCommand);
4362
+ references.command("reorder").description("Reorder references").requiredOption("--rule-id <id>", "Rule ID").requiredOption("--ordered-ids <ids>", "Comma-separated reference IDs").option("-s, --server <url>", "braid server URL (for review apps, local dev)").option("--api-key <token>", "API key override").option("--json", "Output JSON").action(referencesReorderCommand);
3374
4363
  program.command("update").alias("up").description("Update installed skills to the latest version").option("-g, --global", "Update skills in global directories only").option("-y, --yes", "Skip confirmation prompts").option("-s, --server <url>", "braid server URL (for review apps, local dev)").action(updateCommand);
3375
4364
  program.command("remove").alias("rm").description("Remove installed skills").option("-a, --all", "Remove all installed skills").option("-g, --global", "Remove skills from global directories only").option("-y, --yes", "Skip confirmation prompts").option("--skill <name>", "Remove a specific skill by name").action(removeCommand);
3376
- program.command("mcp").description("Configure braid MCP in your AI coding tools").option("-t, --tool <name>", "Tool to configure").option("-g, --global", "Use global config instead of project").option("--token <token>", "API token to embed").option("--no-auth", "Skip authentication setup").option("--scope", "Run interactive scope configuration").option("--remove", "Remove braid MCP from a tool").option("--status", "Show which tools have braid MCP configured").option("-y, --yes", "Skip confirmation prompts").option("-s, --server <url>", "Custom MCP server URL").action(mcpCommand);
4365
+ program.command("mcp").description("Configure braid MCP in your AI coding tools").option("-t, --tool <name>", "Tool to configure").option("-g, --global", "Use global config instead of project").option("--token <token>", "API token to embed").option("--no-auth", "Skip authentication setup").option("--scope", "Run interactive scope configuration").option("--remove", "Remove braid MCP from a tool").option("--status", "Show which tools have braid MCP configured").option("--help-commands", "Show MCP manual command reference").option("-y, --yes", "Skip confirmation prompts").option("-s, --server <url>", "Custom MCP server URL").action(mcpCommand);
3377
4366
  program.parse();
3378
4367
  //# sourceMappingURL=index.js.map