@dosu/cli 0.37.0-alpha.3 → 0.37.0-alpha.5

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/bin/dosu.js +153 -107
  2. package/package.json +1 -1
package/bin/dosu.js CHANGED
@@ -4759,7 +4759,7 @@ var init_dist4 = __esm(() => {
4759
4759
  function getVersionString() {
4760
4760
  return `v${VERSION}`;
4761
4761
  }
4762
- var VERSION = "0.37.0-alpha.3", INSTALL_CHANNEL = "npm";
4762
+ var VERSION = "0.37.0-alpha.5", INSTALL_CHANNEL = "npm";
4763
4763
 
4764
4764
  // src/debug/logger.ts
4765
4765
  import {
@@ -7143,6 +7143,16 @@ var init_installation_server = __esm(() => {
7143
7143
  function dim(msg) {
7144
7144
  return import_picocolors7.default.dim(msg);
7145
7145
  }
7146
+ function formatSetupSummary(title, items, marker = IconAdd) {
7147
+ const lines = items.map((item) => {
7148
+ const path2 = `${item.path}${item.status ? ` (${item.status})` : ""}`;
7149
+ return item.label ? `${marker} ${item.label}
7150
+ ${dim(path2)}` : `${marker} ${dim(path2)}`;
7151
+ });
7152
+ return `${title}
7153
+ ${lines.join(`
7154
+ `)}`;
7155
+ }
7146
7156
  function browserFallbackHint(url) {
7147
7157
  return dim(`If your browser doesn't open automatically, visit:
7148
7158
  ${url}`);
@@ -7150,7 +7160,7 @@ ${url}`);
7150
7160
  function info(msg) {
7151
7161
  return import_picocolors7.default.cyan(msg);
7152
7162
  }
7153
- var import_picocolors7;
7163
+ var import_picocolors7, IconAdd = "+", IconRemove = "-";
7154
7164
  var init_styles = __esm(() => {
7155
7165
  import_picocolors7 = __toESM(require_picocolors(), 1);
7156
7166
  });
@@ -10448,16 +10458,47 @@ var init_skill_update_check = __esm(() => {
10448
10458
  });
10449
10459
 
10450
10460
  // src/commands/skill.ts
10451
- import { execSync as execSync2 } from "node:child_process";
10461
+ import { exec as exec2, execSync as execSync2 } from "node:child_process";
10462
+ import { homedir } from "node:os";
10463
+ import { join as join11 } from "node:path";
10452
10464
  function skillAgentIDsForProviders(providerIDs) {
10453
10465
  return [
10454
10466
  ...new Set(providerIDs.map((providerID) => SKILL_AGENT_BY_PROVIDER[providerID]).filter((agent) => Boolean(agent)))
10455
10467
  ];
10456
10468
  }
10469
+ function skillInstallTargetForProvider(providerID) {
10470
+ const agentID = SKILL_AGENT_BY_PROVIDER[providerID];
10471
+ if (!agentID)
10472
+ return null;
10473
+ if (agentID === "claude-code") {
10474
+ const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join11(homedir(), ".claude");
10475
+ return { path: join11(claudeConfigDir, "skills", SKILL_NAME), symlink: true };
10476
+ }
10477
+ if (agentID === "windsurf") {
10478
+ return {
10479
+ path: join11(homedir(), ".codeium", "windsurf", "skills", SKILL_NAME),
10480
+ symlink: true
10481
+ };
10482
+ }
10483
+ return {
10484
+ path: join11(homedir(), ".agents", "skills", SKILL_NAME),
10485
+ symlink: false
10486
+ };
10487
+ }
10457
10488
  function skillAgentArgs(providerIDs) {
10458
10489
  const agents = providerIDs === undefined ? SUPPORTED_SKILL_AGENTS : skillAgentIDsForProviders(providerIDs);
10459
10490
  return agents.map((agent) => `-a ${agent}`).join(" ");
10460
10491
  }
10492
+ function execQuiet(command) {
10493
+ return new Promise((resolve, reject) => {
10494
+ exec2(command, { windowsHide: true }, (error) => {
10495
+ if (error)
10496
+ reject(error);
10497
+ else
10498
+ resolve();
10499
+ });
10500
+ });
10501
+ }
10461
10502
  async function installSkill(providerIDs, options = {}) {
10462
10503
  const agentArgs = skillAgentArgs(providerIDs);
10463
10504
  if (!agentArgs) {
@@ -10465,9 +10506,11 @@ async function installSkill(providerIDs, options = {}) {
10465
10506
  return { success: true };
10466
10507
  }
10467
10508
  try {
10468
- execSync2(`npx skills add ${SKILL_REPO} -g ${agentArgs} -s ${SKILL_NAME} -y`, {
10469
- stdio: options.quiet ? "pipe" : "inherit"
10470
- });
10509
+ const command = `npx skills add ${SKILL_REPO} -g ${agentArgs} -s ${SKILL_NAME} -y`;
10510
+ if (options.quiet)
10511
+ await execQuiet(command);
10512
+ else
10513
+ execSync2(command, { stdio: "inherit" });
10471
10514
  } catch (err) {
10472
10515
  logger.error("skill", `Failed to install skill: ${err}`);
10473
10516
  return { success: false };
@@ -10564,20 +10607,20 @@ var MCP_PROVIDER_SLUG = "dosu_mcp";
10564
10607
 
10565
10608
  // src/mcp/detect.ts
10566
10609
  import { existsSync as existsSync13 } from "node:fs";
10567
- import { homedir, platform as platform2 } from "node:os";
10568
- import { join as join11 } from "node:path";
10610
+ import { homedir as homedir2, platform as platform2 } from "node:os";
10611
+ import { join as join12 } from "node:path";
10569
10612
  function isInstalled(paths) {
10570
10613
  return paths.some((p2) => existsSync13(expandHome(p2)));
10571
10614
  }
10572
10615
  function expandHome(path3) {
10573
10616
  if (!path3.startsWith("~"))
10574
10617
  return path3;
10575
- return join11(homedir(), path3.slice(1));
10618
+ return join12(homedir2(), path3.slice(1));
10576
10619
  }
10577
10620
  function appSupportDir() {
10578
10621
  switch (platform2()) {
10579
10622
  case "darwin": {
10580
- return join11(homedir(), "Library", "Application Support");
10623
+ return join12(homedir2(), "Library", "Application Support");
10581
10624
  }
10582
10625
  case "win32": {
10583
10626
  return process.env.APPDATA ?? "";
@@ -10586,7 +10629,7 @@ function appSupportDir() {
10586
10629
  const xdg = process.env.XDG_CONFIG_HOME;
10587
10630
  if (xdg)
10588
10631
  return xdg;
10589
- return join11(homedir(), ".config");
10632
+ return join12(homedir2(), ".config");
10590
10633
  }
10591
10634
  }
10592
10635
  }
@@ -10667,7 +10710,7 @@ var init_antigravity = __esm(() => {
10667
10710
  });
10668
10711
 
10669
10712
  // src/mcp/providers/claude.ts
10670
- import { join as join12 } from "node:path";
10713
+ import { join as join13 } from "node:path";
10671
10714
  var ClaudeProvider = () => createJSONProvider({
10672
10715
  providerName: "Claude Code",
10673
10716
  providerID: "claude",
@@ -10676,22 +10719,22 @@ var ClaudeProvider = () => createJSONProvider({
10676
10719
  paths: ["~/.claude"],
10677
10720
  globalPath: "~/.claude.json",
10678
10721
  topKey: "mcpServers",
10679
- localConfigPath: (cwd) => join12(cwd, ".mcp.json")
10722
+ localConfigPath: (cwd) => join13(cwd, ".mcp.json")
10680
10723
  });
10681
10724
  var init_claude = __esm(() => {
10682
10725
  init_base();
10683
10726
  });
10684
10727
 
10685
10728
  // src/mcp/providers/claude-desktop.ts
10686
- import { join as join13 } from "node:path";
10729
+ import { join as join14 } from "node:path";
10687
10730
  var ClaudeDesktopProvider = () => ({
10688
10731
  name: () => "Claude Desktop",
10689
10732
  id: () => "claude-desktop",
10690
10733
  supportsLocal: () => false,
10691
10734
  priority: () => 2,
10692
- detectPaths: () => [join13(appSupportDir(), "Claude")],
10693
- isInstalled: () => isInstalled([join13(appSupportDir(), "Claude")]),
10694
- globalConfigPath: () => join13(appSupportDir(), "Claude", "claude_desktop_config.json"),
10735
+ detectPaths: () => [join14(appSupportDir(), "Claude")],
10736
+ isInstalled: () => isInstalled([join14(appSupportDir(), "Claude")]),
10737
+ globalConfigPath: () => join14(appSupportDir(), "Claude", "claude_desktop_config.json"),
10695
10738
  isConfigured: () => false,
10696
10739
  install() {
10697
10740
  throw new Error("this tool only supports local (stdio) servers and cannot be configured for remote MCP");
@@ -10705,14 +10748,14 @@ var init_claude_desktop = __esm(() => {
10705
10748
  });
10706
10749
 
10707
10750
  // src/mcp/providers/cline.ts
10708
- import { join as join14 } from "node:path";
10709
- var extensionDir = () => join14(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
10751
+ import { join as join15 } from "node:path";
10752
+ var extensionDir = () => join15(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
10710
10753
  providerName: "Cline",
10711
10754
  providerID: "cline",
10712
10755
  local: false,
10713
10756
  priorityValue: 11,
10714
10757
  paths: [extensionDir()],
10715
- globalPath: join14(extensionDir(), "settings", "cline_mcp_settings.json"),
10758
+ globalPath: join15(extensionDir(), "settings", "cline_mcp_settings.json"),
10716
10759
  topKey: "mcpServers",
10717
10760
  buildServer: (cfg) => ({
10718
10761
  url: mcpURL(cfg.active_account.target.deployment_id),
@@ -10728,7 +10771,7 @@ var init_cline = __esm(() => {
10728
10771
  });
10729
10772
 
10730
10773
  // src/mcp/providers/cline-cli.ts
10731
- import { join as join15 } from "node:path";
10774
+ import { join as join16 } from "node:path";
10732
10775
  function clineDir() {
10733
10776
  return process.env.CLINE_DIR ?? expandHome("~/.cline");
10734
10777
  }
@@ -10738,7 +10781,7 @@ var ClineCliProvider = () => createJSONProvider({
10738
10781
  local: false,
10739
10782
  priorityValue: 12,
10740
10783
  paths: [clineDir()],
10741
- globalPath: join15(clineDir(), "data", "settings", "cline_mcp_settings.json"),
10784
+ globalPath: join16(clineDir(), "data", "settings", "cline_mcp_settings.json"),
10742
10785
  topKey: "mcpServers",
10743
10786
  buildServer: (cfg) => ({
10744
10787
  url: mcpURL(cfg.active_account.target.deployment_id),
@@ -10755,14 +10798,14 @@ var init_cline_cli = __esm(() => {
10755
10798
 
10756
10799
  // src/mcp/providers/codex.ts
10757
10800
  import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
10758
- import { join as join16 } from "node:path";
10801
+ import { join as join17 } from "node:path";
10759
10802
  function codexHome() {
10760
10803
  return process.env.CODEX_HOME ?? expandHome("~/.codex");
10761
10804
  }
10762
10805
  function getConfigPath2(global) {
10763
10806
  if (global)
10764
- return join16(codexHome(), "config.toml");
10765
- return join16(process.cwd(), ".codex", "config.toml");
10807
+ return join17(codexHome(), "config.toml");
10808
+ return join17(process.cwd(), ".codex", "config.toml");
10766
10809
  }
10767
10810
  function readTOML(path3) {
10768
10811
  if (!existsSync14(path3))
@@ -10825,9 +10868,9 @@ var CodexProvider = () => ({
10825
10868
  priority: () => 8,
10826
10869
  detectPaths: () => ["~/.codex"],
10827
10870
  isInstalled: () => isInstalled(["~/.codex"]),
10828
- globalConfigPath: () => join16(codexHome(), "config.toml"),
10871
+ globalConfigPath: () => join17(codexHome(), "config.toml"),
10829
10872
  isConfigured: () => {
10830
- const content = readTOML(join16(codexHome(), "config.toml"));
10873
+ const content = readTOML(join17(codexHome(), "config.toml"));
10831
10874
  return content.includes("[mcp_servers.dosu]");
10832
10875
  },
10833
10876
  install(cfg, global) {
@@ -10849,10 +10892,10 @@ var init_codex2 = __esm(() => {
10849
10892
  });
10850
10893
 
10851
10894
  // src/mcp/providers/copilot.ts
10852
- import { join as join17 } from "node:path";
10895
+ import { join as join18 } from "node:path";
10853
10896
  function globalPath() {
10854
10897
  if (process.env.XDG_CONFIG_HOME) {
10855
- return join17(process.env.XDG_CONFIG_HOME, "mcp-config.json");
10898
+ return join18(process.env.XDG_CONFIG_HOME, "mcp-config.json");
10856
10899
  }
10857
10900
  return expandHome("~/.copilot/mcp-config.json");
10858
10901
  }
@@ -10883,7 +10926,7 @@ var CopilotProvider = () => ({
10883
10926
  };
10884
10927
  installJSONServer(globalPath(), "mcpServers", server);
10885
10928
  } else {
10886
- const configPath = join17(process.cwd(), ".vscode", "mcp.json");
10929
+ const configPath = join18(process.cwd(), ".vscode", "mcp.json");
10887
10930
  const server = {
10888
10931
  type: "http",
10889
10932
  url,
@@ -10896,7 +10939,7 @@ var CopilotProvider = () => ({
10896
10939
  if (global) {
10897
10940
  removeJSONServer(globalPath(), "mcpServers");
10898
10941
  } else {
10899
- const configPath = join17(process.cwd(), ".vscode", "mcp.json");
10942
+ const configPath = join18(process.cwd(), ".vscode", "mcp.json");
10900
10943
  removeJSONServer(configPath, "servers");
10901
10944
  }
10902
10945
  }
@@ -10908,7 +10951,7 @@ var init_copilot = __esm(() => {
10908
10951
  });
10909
10952
 
10910
10953
  // src/mcp/providers/cursor.ts
10911
- import { join as join18 } from "node:path";
10954
+ import { join as join19 } from "node:path";
10912
10955
  var CursorProvider = () => createJSONProvider({
10913
10956
  providerName: "Cursor",
10914
10957
  providerID: "cursor",
@@ -10921,7 +10964,7 @@ var CursorProvider = () => createJSONProvider({
10921
10964
  url: mcpURL(cfg.active_account.target.deployment_id),
10922
10965
  headers: mcpHeaders(cfg.active_account.target.api_key)
10923
10966
  }),
10924
- localConfigPath: (cwd) => join18(cwd, ".cursor", "mcp.json")
10967
+ localConfigPath: (cwd) => join19(cwd, ".cursor", "mcp.json")
10925
10968
  });
10926
10969
  var init_cursor = __esm(() => {
10927
10970
  init_config_helpers();
@@ -10929,7 +10972,7 @@ var init_cursor = __esm(() => {
10929
10972
  });
10930
10973
 
10931
10974
  // src/mcp/providers/factory.ts
10932
- import { join as join19 } from "node:path";
10975
+ import { join as join20 } from "node:path";
10933
10976
  var FactoryProvider = () => createJSONProvider({
10934
10977
  providerName: "Factory",
10935
10978
  providerID: "factory",
@@ -10938,14 +10981,14 @@ var FactoryProvider = () => createJSONProvider({
10938
10981
  paths: ["~/.factory"],
10939
10982
  globalPath: "~/.factory/mcp.json",
10940
10983
  topKey: "mcpServers",
10941
- localConfigPath: (cwd) => join19(cwd, ".factory", "mcp.json")
10984
+ localConfigPath: (cwd) => join20(cwd, ".factory", "mcp.json")
10942
10985
  });
10943
10986
  var init_factory2 = __esm(() => {
10944
10987
  init_base();
10945
10988
  });
10946
10989
 
10947
10990
  // src/mcp/providers/gemini.ts
10948
- import { join as join20 } from "node:path";
10991
+ import { join as join21 } from "node:path";
10949
10992
  var GeminiProvider = () => createJSONProvider({
10950
10993
  providerName: "Gemini CLI",
10951
10994
  providerID: "gemini",
@@ -10954,7 +10997,7 @@ var GeminiProvider = () => createJSONProvider({
10954
10997
  paths: ["~/.gemini"],
10955
10998
  globalPath: "~/.gemini/settings.json",
10956
10999
  topKey: "mcpServers",
10957
- localConfigPath: (cwd) => join20(cwd, ".gemini", "settings.json")
11000
+ localConfigPath: (cwd) => join21(cwd, ".gemini", "settings.json")
10958
11001
  });
10959
11002
  var init_gemini = __esm(() => {
10960
11003
  init_base();
@@ -11005,7 +11048,7 @@ var init_manual = __esm(() => {
11005
11048
 
11006
11049
  // src/mcp/providers/mcporter.ts
11007
11050
  import { existsSync as existsSync15 } from "node:fs";
11008
- import { join as join21 } from "node:path";
11051
+ import { join as join22 } from "node:path";
11009
11052
  function resolveGlobalConfigPath() {
11010
11053
  const jsonPath = expandHome("~/.mcporter/mcporter.json");
11011
11054
  if (existsSync15(jsonPath))
@@ -11032,7 +11075,7 @@ var MCPorterProvider = () => ({
11032
11075
  globalConfigPath: () => resolveGlobalConfigPath(),
11033
11076
  isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
11034
11077
  install(cfg, global) {
11035
- const configPath = global ? resolveGlobalConfigPath() : join21(process.cwd(), "config", "mcporter.json");
11078
+ const configPath = global ? resolveGlobalConfigPath() : join22(process.cwd(), "config", "mcporter.json");
11036
11079
  const server = {
11037
11080
  type: "http",
11038
11081
  url: mcpEndpoint4(cfg),
@@ -11041,7 +11084,7 @@ var MCPorterProvider = () => ({
11041
11084
  installJSONServer(configPath, "mcpServers", server);
11042
11085
  },
11043
11086
  remove(global) {
11044
- const configPath = global ? resolveGlobalConfigPath() : join21(process.cwd(), "config", "mcporter.json");
11087
+ const configPath = global ? resolveGlobalConfigPath() : join22(process.cwd(), "config", "mcporter.json");
11045
11088
  removeJSONServer(configPath, "mcpServers");
11046
11089
  }
11047
11090
  });
@@ -11052,7 +11095,7 @@ var init_mcporter = __esm(() => {
11052
11095
  });
11053
11096
 
11054
11097
  // src/mcp/providers/opencode.ts
11055
- import { join as join22 } from "node:path";
11098
+ import { join as join23 } from "node:path";
11056
11099
  var OpenCodeProvider = () => createJSONProvider({
11057
11100
  providerName: "OpenCode",
11058
11101
  providerID: "opencode",
@@ -11067,7 +11110,7 @@ var OpenCodeProvider = () => createJSONProvider({
11067
11110
  enabled: true,
11068
11111
  headers: mcpHeaders(cfg.active_account.target.api_key)
11069
11112
  }),
11070
- localConfigPath: (cwd) => join22(cwd, "opencode.json")
11113
+ localConfigPath: (cwd) => join23(cwd, "opencode.json")
11071
11114
  });
11072
11115
  var init_opencode = __esm(() => {
11073
11116
  init_config_helpers();
@@ -11075,16 +11118,16 @@ var init_opencode = __esm(() => {
11075
11118
  });
11076
11119
 
11077
11120
  // src/mcp/providers/vscode.ts
11078
- import { join as join23 } from "node:path";
11121
+ import { join as join24 } from "node:path";
11079
11122
  var VSCodeProvider = () => createJSONProvider({
11080
11123
  providerName: "VS Code",
11081
11124
  providerID: "vscode",
11082
11125
  local: true,
11083
11126
  priorityValue: 6,
11084
- paths: [join23(appSupportDir(), "Code")],
11085
- globalPath: join23(appSupportDir(), "Code", "User", "mcp.json"),
11127
+ paths: [join24(appSupportDir(), "Code")],
11128
+ globalPath: join24(appSupportDir(), "Code", "User", "mcp.json"),
11086
11129
  topKey: "servers",
11087
- localConfigPath: (cwd) => join23(cwd, ".vscode", "mcp.json")
11130
+ localConfigPath: (cwd) => join24(cwd, ".vscode", "mcp.json")
11088
11131
  });
11089
11132
  var init_vscode = __esm(() => {
11090
11133
  init_detect();
@@ -11092,15 +11135,15 @@ var init_vscode = __esm(() => {
11092
11135
  });
11093
11136
 
11094
11137
  // src/mcp/providers/windsurf.ts
11095
- import { homedir as homedir2 } from "node:os";
11096
- import { join as join24 } from "node:path";
11138
+ import { homedir as homedir3 } from "node:os";
11139
+ import { join as join25 } from "node:path";
11097
11140
  var WindsurfProvider = () => createJSONProvider({
11098
11141
  providerName: "Windsurf",
11099
11142
  providerID: "windsurf",
11100
11143
  local: false,
11101
11144
  priorityValue: 9,
11102
- paths: [join24(homedir2(), ".codeium", "windsurf")],
11103
- globalPath: join24(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
11145
+ paths: [join25(homedir3(), ".codeium", "windsurf")],
11146
+ globalPath: join25(homedir3(), ".codeium", "windsurf", "mcp_config.json"),
11104
11147
  topKey: "mcpServers"
11105
11148
  });
11106
11149
  var init_windsurf = __esm(() => {
@@ -11109,12 +11152,12 @@ var init_windsurf = __esm(() => {
11109
11152
 
11110
11153
  // src/mcp/providers/zed.ts
11111
11154
  import { platform as platform3 } from "node:os";
11112
- import { join as join25 } from "node:path";
11155
+ import { join as join26 } from "node:path";
11113
11156
  function zedConfigDir() {
11114
11157
  const os2 = platform3();
11115
11158
  if (os2 === "darwin" || os2 === "win32")
11116
- return join25(appSupportDir(), "Zed");
11117
- return join25(appSupportDir(), "zed");
11159
+ return join26(appSupportDir(), "Zed");
11160
+ return join26(appSupportDir(), "zed");
11118
11161
  }
11119
11162
  var ZedProvider = () => createJSONProvider({
11120
11163
  providerName: "Zed",
@@ -11122,7 +11165,7 @@ var ZedProvider = () => createJSONProvider({
11122
11165
  local: true,
11123
11166
  priorityValue: 10,
11124
11167
  paths: [zedConfigDir()],
11125
- globalPath: join25(zedConfigDir(), "settings.json"),
11168
+ globalPath: join26(zedConfigDir(), "settings.json"),
11126
11169
  topKey: "context_servers",
11127
11170
  buildServer: (cfg) => ({
11128
11171
  source: "custom",
@@ -11130,7 +11173,7 @@ var ZedProvider = () => createJSONProvider({
11130
11173
  url: mcpURL(cfg.active_account.target.deployment_id),
11131
11174
  headers: mcpHeaders(cfg.active_account.target.api_key)
11132
11175
  }),
11133
- localConfigPath: (cwd) => join25(cwd, ".zed", "settings.json")
11176
+ localConfigPath: (cwd) => join26(cwd, ".zed", "settings.json")
11134
11177
  });
11135
11178
  var init_zed = __esm(() => {
11136
11179
  init_config_helpers();
@@ -11190,13 +11233,13 @@ var init_providers = __esm(() => {
11190
11233
 
11191
11234
  // src/rules/installer.ts
11192
11235
  import { existsSync as existsSync16, mkdirSync as mkdirSync8, readFileSync as readFileSync14, unlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
11193
- import { homedir as homedir3 } from "node:os";
11194
- import { dirname as dirname5, join as join26 } from "node:path";
11236
+ import { homedir as homedir4 } from "node:os";
11237
+ import { dirname as dirname5, join as join27 } from "node:path";
11195
11238
  function claudeConfigDir() {
11196
- return process.env.CLAUDE_CONFIG_DIR || join26(homedir3(), ".claude");
11239
+ return process.env.CLAUDE_CONFIG_DIR || join27(homedir4(), ".claude");
11197
11240
  }
11198
11241
  function codexHome2() {
11199
- return process.env.CODEX_HOME || join26(homedir3(), ".codex");
11242
+ return process.env.CODEX_HOME || join27(homedir4(), ".codex");
11200
11243
  }
11201
11244
  function isRuleAgent(agent) {
11202
11245
  return Object.hasOwn(RULE_TARGETS, agent);
@@ -11336,28 +11379,28 @@ var init_installer = __esm(() => {
11336
11379
  RULE_TARGETS = {
11337
11380
  claude: {
11338
11381
  kind: "file",
11339
- path: () => join26(claudeConfigDir(), "rules", "dosu.md")
11382
+ path: () => join27(claudeConfigDir(), "rules", "dosu.md")
11340
11383
  },
11341
11384
  cursor: {
11342
11385
  kind: "file",
11343
- path: () => join26(homedir3(), ".cursor", "rules", "dosu.mdc"),
11386
+ path: () => join27(homedir4(), ".cursor", "rules", "dosu.mdc"),
11344
11387
  cursorFrontmatter: true
11345
11388
  },
11346
11389
  codex: {
11347
11390
  kind: "section",
11348
- path: () => join26(codexHome2(), "AGENTS.md")
11391
+ path: () => join27(codexHome2(), "AGENTS.md")
11349
11392
  },
11350
11393
  opencode: {
11351
11394
  kind: "section",
11352
- path: () => join26(homedir3(), ".config", "opencode", "AGENTS.md")
11395
+ path: () => join27(homedir4(), ".config", "opencode", "AGENTS.md")
11353
11396
  },
11354
11397
  gemini: {
11355
11398
  kind: "section",
11356
- path: () => join26(homedir3(), ".gemini", "GEMINI.md")
11399
+ path: () => join27(homedir4(), ".gemini", "GEMINI.md")
11357
11400
  },
11358
11401
  antigravity: {
11359
11402
  kind: "section",
11360
- path: () => join26(homedir3(), ".gemini", "GEMINI.md")
11403
+ path: () => join27(homedir4(), ".gemini", "GEMINI.md")
11361
11404
  }
11362
11405
  };
11363
11406
  SUPPORTED_RULE_AGENT_IDS = Object.keys(RULE_TARGETS);
@@ -11366,7 +11409,7 @@ var init_installer = __esm(() => {
11366
11409
  // src/setup/agents-md-step.ts
11367
11410
  import { execSync as execSync3 } from "node:child_process";
11368
11411
  import { existsSync as existsSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
11369
- import { join as join27 } from "node:path";
11412
+ import { join as join28 } from "node:path";
11370
11413
  function inGitWorkTree(cwd = process.cwd()) {
11371
11414
  try {
11372
11415
  const stdout2 = execSync3("git rev-parse --is-inside-work-tree", {
@@ -11404,7 +11447,7 @@ function findSection2(content) {
11404
11447
  return { start, end };
11405
11448
  }
11406
11449
  function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
11407
- const path3 = join27(cwd, "AGENTS.md");
11450
+ const path3 = join28(cwd, "AGENTS.md");
11408
11451
  if (!existsSync17(path3)) {
11409
11452
  const section2 = buildDosuAgentsSection(content);
11410
11453
  writeFileSync8(path3, `${section2}
@@ -11431,13 +11474,8 @@ async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
11431
11474
  try {
11432
11475
  const result = upsertDosuAgentsSection(cwd, content ?? await fetchDosuRule());
11433
11476
  logger.info("setup", `AGENTS.md ${result.action} at ${result.path}`);
11434
- if (result.action === "unchanged") {
11435
- log.success(`AGENTS.md
11436
- ${dim("Dosu section already up to date")}`);
11437
- } else {
11438
- log.success(`AGENTS.md
11439
- ${dim(`Dosu section ${result.action} — ${result.path}`)}`);
11440
- }
11477
+ const status = result.action === "unchanged" ? "already up to date" : result.action;
11478
+ log.success(formatSetupSummary("AGENTS.md", [{ path: result.path, status }]));
11441
11479
  return true;
11442
11480
  } catch (err) {
11443
11481
  const msg = err instanceof Error ? err.message : String(err);
@@ -11618,18 +11656,10 @@ function logRuleResults(results) {
11618
11656
  const ready = results.filter((result) => !result.error && (result.action === "created" || result.action === "updated" || result.action === "unchanged"));
11619
11657
  const removed = results.filter((result) => !result.error && result.action === "removed");
11620
11658
  if (ready.length > 0) {
11621
- const lines = ready.map((result) => `+ ${result.provider.name()}
11622
- ${dim(result.path)}`).join(`
11623
- `);
11624
- log.success(`Rules ready for ${ready.length} agent(s):
11625
- ${lines}`);
11659
+ log.success(formatSetupSummary(`Rules ready for ${ready.length} agent(s):`, ready.map((result) => ({ label: result.provider.name(), path: result.path }))));
11626
11660
  }
11627
11661
  if (removed.length > 0) {
11628
- const lines = removed.map((result) => `- ${result.provider.name()}
11629
- ${dim(result.path)}`).join(`
11630
- `);
11631
- log.info(`Rules removed from ${removed.length} agent(s):
11632
- ${lines}`);
11662
+ log.info(formatSetupSummary(`Rules removed from ${removed.length} agent(s):`, removed.map((result) => ({ label: result.provider.name(), path: result.path })), IconRemove));
11633
11663
  }
11634
11664
  }
11635
11665
  async function stepConfigureAgentRules(selection, mcpResults) {
@@ -12292,9 +12322,9 @@ async function runSetup(opts = {}) {
12292
12322
  });
12293
12323
  }
12294
12324
  let skillCompleted = false;
12295
- const selectedProviderIDs = configuredProviders.map((result) => result.provider.id());
12296
- if (skillAgentIDsForProviders(selectedProviderIDs).length > 0) {
12297
- skillCompleted = await runInstallSkill(selectedProviderIDs);
12325
+ const skillProviders = configuredProviders.map((result) => result.provider).filter((provider) => skillInstallTargetForProvider(provider.id()) !== null);
12326
+ if (skillProviders.length > 0) {
12327
+ skillCompleted = await runInstallSkill(skillProviders);
12298
12328
  if (skillCompleted) {
12299
12329
  await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_skill_installed");
12300
12330
  }
@@ -12357,20 +12387,38 @@ Run ${info("dosu mcp add <agent>")} to manually configure an agent.`);
12357
12387
  await stepConfigureAgentRules(selection, results);
12358
12388
  return results;
12359
12389
  }
12360
- async function runInstallSkill(providerIDs) {
12390
+ async function runInstallSkill(providers) {
12361
12391
  logger.info("setup", "Step: install skill");
12392
+ const spinner2 = spinner();
12393
+ const agentLabel = providers.length === 1 ? "agent" : "agents";
12394
+ spinner2.start(`Installing skill for ${providers.length} ${agentLabel}`);
12362
12395
  try {
12363
- const result = await installSkill(providerIDs, { quiet: true });
12396
+ const result = await installSkill(providers.map((provider) => provider.id()), { quiet: true });
12364
12397
  if (result.success) {
12365
12398
  logger.info("setup", `Skill installed${result.sha ? ` sha=${result.sha}` : ""}`);
12366
- log.success("Skill installed");
12399
+ const items = providers.flatMap((provider) => {
12400
+ const target = skillInstallTargetForProvider(provider.id());
12401
+ if (!target)
12402
+ return [];
12403
+ return [
12404
+ {
12405
+ label: provider.name(),
12406
+ path: target.path,
12407
+ status: target.symlink ? "symlink" : undefined
12408
+ }
12409
+ ];
12410
+ });
12411
+ spinner2.clear();
12412
+ log.success(formatSetupSummary(`Skill ready for ${items.length} agent(s):`, items));
12367
12413
  return true;
12368
12414
  }
12415
+ spinner2.clear();
12369
12416
  log.error("Failed to install skill. Run `dosu skill install` to retry.");
12370
12417
  return false;
12371
12418
  } catch (err) {
12372
12419
  const msg = err instanceof Error ? err.message : String(err);
12373
12420
  logger.error("setup", `Skill install failed: ${msg}`);
12421
+ spinner2.clear();
12374
12422
  log.error(`Skill install failed: ${msg}`);
12375
12423
  return false;
12376
12424
  }
@@ -12794,18 +12842,16 @@ function stepShowSummary(results) {
12794
12842
  const removed = results.filter((r2) => r2.action === "remove" && !r2.error);
12795
12843
  const skipped = results.filter((r2) => r2.action === "skip");
12796
12844
  if (installed.length > 0) {
12797
- const lines = installed.map((r2) => `+ ${r2.provider.name()}
12798
- ${dim(r2.provider.globalConfigPath())}`).join(`
12799
- `);
12800
- log.success(`Configured ${installed.length} agent(s):
12801
- ${lines}`);
12845
+ log.success(formatSetupSummary(`Configured ${installed.length} agent(s):`, installed.map((result) => ({
12846
+ label: result.provider.name(),
12847
+ path: result.provider.globalConfigPath()
12848
+ }))));
12802
12849
  }
12803
12850
  if (removed.length > 0) {
12804
- const lines = removed.map((r2) => `- ${r2.provider.name()}
12805
- ${dim(r2.provider.globalConfigPath())}`).join(`
12806
- `);
12807
- log.info(`Removed from ${removed.length} agent(s):
12808
- ${lines}`);
12851
+ log.info(formatSetupSummary(`Removed from ${removed.length} agent(s):`, removed.map((result) => ({
12852
+ label: result.provider.name(),
12853
+ path: result.provider.globalConfigPath()
12854
+ })), IconRemove));
12809
12855
  }
12810
12856
  if (installed.length === 0 && removed.length === 0 && skipped.length > 0) {
12811
12857
  log.success("All agents already configured. No changes needed.");
@@ -12827,7 +12873,7 @@ var init_flow2 = __esm(() => {
12827
12873
 
12828
12874
  // src/commands/insights.ts
12829
12875
  import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
12830
- import { dirname as dirname6, join as join28 } from "node:path";
12876
+ import { dirname as dirname6, join as join29 } from "node:path";
12831
12877
  function shuffled(arr) {
12832
12878
  const copy2 = [...arr];
12833
12879
  for (let i2 = copy2.length - 1;i2 > 0; i2--) {
@@ -12931,14 +12977,14 @@ function makeAskFn(cfg) {
12931
12977
  };
12932
12978
  }
12933
12979
  function insightsDir() {
12934
- return join28(getConfigDir(), "insights");
12980
+ return join29(getConfigDir(), "insights");
12935
12981
  }
12936
12982
  function reportPath(timestamp) {
12937
12983
  const dir = insightsDir();
12938
12984
  if (!timestamp)
12939
- return join28(dir, "latest.html");
12985
+ return join29(dir, "latest.html");
12940
12986
  const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
12941
- return join28(dir, `report-${iso}Z.html`);
12987
+ return join29(dir, `report-${iso}Z.html`);
12942
12988
  }
12943
12989
  function pruneOldReports(dir, keepN) {
12944
12990
  if (!existsSync18(dir))
@@ -12953,7 +12999,7 @@ function pruneOldReports(dir, keepN) {
12953
12999
  const reports = entries.filter((f2) => REPORT_FILE_PATTERN.test(f2)).sort().reverse();
12954
13000
  for (const f2 of reports.slice(keepN)) {
12955
13001
  try {
12956
- unlinkSync2(join28(dir, f2));
13002
+ unlinkSync2(join29(dir, f2));
12957
13003
  } catch (err) {
12958
13004
  logger.debug("insights", `failed to prune ${f2}: ${err instanceof Error ? err.message : err}`);
12959
13005
  }
@@ -16619,7 +16665,7 @@ init_config();
16619
16665
  init_logger();
16620
16666
  var import_picocolors24 = __toESM(require_picocolors(), 1);
16621
16667
  import { existsSync as existsSync19, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
16622
- import { join as join29 } from "node:path";
16668
+ import { join as join30 } from "node:path";
16623
16669
  var CACHE_FILENAME3 = "update-check.json";
16624
16670
  var CHECK_INTERVAL_MS3 = 24 * 60 * 60 * 1000;
16625
16671
  var FETCH_TIMEOUT_MS3 = 5000;
@@ -16642,7 +16688,7 @@ function isNewerVersion(latest, current) {
16642
16688
  return false;
16643
16689
  }
16644
16690
  function getCachePath3() {
16645
- return join29(getConfigDir(), CACHE_FILENAME3);
16691
+ return join30(getConfigDir(), CACHE_FILENAME3);
16646
16692
  }
16647
16693
  function readCache() {
16648
16694
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.37.0-alpha.3",
3
+ "version": "0.37.0-alpha.5",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",