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

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 +131 -103
  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.4", 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
  });
@@ -10449,11 +10459,32 @@ var init_skill_update_check = __esm(() => {
10449
10459
 
10450
10460
  // src/commands/skill.ts
10451
10461
  import { 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(" ");
@@ -10564,20 +10595,20 @@ var MCP_PROVIDER_SLUG = "dosu_mcp";
10564
10595
 
10565
10596
  // src/mcp/detect.ts
10566
10597
  import { existsSync as existsSync13 } from "node:fs";
10567
- import { homedir, platform as platform2 } from "node:os";
10568
- import { join as join11 } from "node:path";
10598
+ import { homedir as homedir2, platform as platform2 } from "node:os";
10599
+ import { join as join12 } from "node:path";
10569
10600
  function isInstalled(paths) {
10570
10601
  return paths.some((p2) => existsSync13(expandHome(p2)));
10571
10602
  }
10572
10603
  function expandHome(path3) {
10573
10604
  if (!path3.startsWith("~"))
10574
10605
  return path3;
10575
- return join11(homedir(), path3.slice(1));
10606
+ return join12(homedir2(), path3.slice(1));
10576
10607
  }
10577
10608
  function appSupportDir() {
10578
10609
  switch (platform2()) {
10579
10610
  case "darwin": {
10580
- return join11(homedir(), "Library", "Application Support");
10611
+ return join12(homedir2(), "Library", "Application Support");
10581
10612
  }
10582
10613
  case "win32": {
10583
10614
  return process.env.APPDATA ?? "";
@@ -10586,7 +10617,7 @@ function appSupportDir() {
10586
10617
  const xdg = process.env.XDG_CONFIG_HOME;
10587
10618
  if (xdg)
10588
10619
  return xdg;
10589
- return join11(homedir(), ".config");
10620
+ return join12(homedir2(), ".config");
10590
10621
  }
10591
10622
  }
10592
10623
  }
@@ -10667,7 +10698,7 @@ var init_antigravity = __esm(() => {
10667
10698
  });
10668
10699
 
10669
10700
  // src/mcp/providers/claude.ts
10670
- import { join as join12 } from "node:path";
10701
+ import { join as join13 } from "node:path";
10671
10702
  var ClaudeProvider = () => createJSONProvider({
10672
10703
  providerName: "Claude Code",
10673
10704
  providerID: "claude",
@@ -10676,22 +10707,22 @@ var ClaudeProvider = () => createJSONProvider({
10676
10707
  paths: ["~/.claude"],
10677
10708
  globalPath: "~/.claude.json",
10678
10709
  topKey: "mcpServers",
10679
- localConfigPath: (cwd) => join12(cwd, ".mcp.json")
10710
+ localConfigPath: (cwd) => join13(cwd, ".mcp.json")
10680
10711
  });
10681
10712
  var init_claude = __esm(() => {
10682
10713
  init_base();
10683
10714
  });
10684
10715
 
10685
10716
  // src/mcp/providers/claude-desktop.ts
10686
- import { join as join13 } from "node:path";
10717
+ import { join as join14 } from "node:path";
10687
10718
  var ClaudeDesktopProvider = () => ({
10688
10719
  name: () => "Claude Desktop",
10689
10720
  id: () => "claude-desktop",
10690
10721
  supportsLocal: () => false,
10691
10722
  priority: () => 2,
10692
- detectPaths: () => [join13(appSupportDir(), "Claude")],
10693
- isInstalled: () => isInstalled([join13(appSupportDir(), "Claude")]),
10694
- globalConfigPath: () => join13(appSupportDir(), "Claude", "claude_desktop_config.json"),
10723
+ detectPaths: () => [join14(appSupportDir(), "Claude")],
10724
+ isInstalled: () => isInstalled([join14(appSupportDir(), "Claude")]),
10725
+ globalConfigPath: () => join14(appSupportDir(), "Claude", "claude_desktop_config.json"),
10695
10726
  isConfigured: () => false,
10696
10727
  install() {
10697
10728
  throw new Error("this tool only supports local (stdio) servers and cannot be configured for remote MCP");
@@ -10705,14 +10736,14 @@ var init_claude_desktop = __esm(() => {
10705
10736
  });
10706
10737
 
10707
10738
  // 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({
10739
+ import { join as join15 } from "node:path";
10740
+ var extensionDir = () => join15(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
10710
10741
  providerName: "Cline",
10711
10742
  providerID: "cline",
10712
10743
  local: false,
10713
10744
  priorityValue: 11,
10714
10745
  paths: [extensionDir()],
10715
- globalPath: join14(extensionDir(), "settings", "cline_mcp_settings.json"),
10746
+ globalPath: join15(extensionDir(), "settings", "cline_mcp_settings.json"),
10716
10747
  topKey: "mcpServers",
10717
10748
  buildServer: (cfg) => ({
10718
10749
  url: mcpURL(cfg.active_account.target.deployment_id),
@@ -10728,7 +10759,7 @@ var init_cline = __esm(() => {
10728
10759
  });
10729
10760
 
10730
10761
  // src/mcp/providers/cline-cli.ts
10731
- import { join as join15 } from "node:path";
10762
+ import { join as join16 } from "node:path";
10732
10763
  function clineDir() {
10733
10764
  return process.env.CLINE_DIR ?? expandHome("~/.cline");
10734
10765
  }
@@ -10738,7 +10769,7 @@ var ClineCliProvider = () => createJSONProvider({
10738
10769
  local: false,
10739
10770
  priorityValue: 12,
10740
10771
  paths: [clineDir()],
10741
- globalPath: join15(clineDir(), "data", "settings", "cline_mcp_settings.json"),
10772
+ globalPath: join16(clineDir(), "data", "settings", "cline_mcp_settings.json"),
10742
10773
  topKey: "mcpServers",
10743
10774
  buildServer: (cfg) => ({
10744
10775
  url: mcpURL(cfg.active_account.target.deployment_id),
@@ -10755,14 +10786,14 @@ var init_cline_cli = __esm(() => {
10755
10786
 
10756
10787
  // src/mcp/providers/codex.ts
10757
10788
  import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
10758
- import { join as join16 } from "node:path";
10789
+ import { join as join17 } from "node:path";
10759
10790
  function codexHome() {
10760
10791
  return process.env.CODEX_HOME ?? expandHome("~/.codex");
10761
10792
  }
10762
10793
  function getConfigPath2(global) {
10763
10794
  if (global)
10764
- return join16(codexHome(), "config.toml");
10765
- return join16(process.cwd(), ".codex", "config.toml");
10795
+ return join17(codexHome(), "config.toml");
10796
+ return join17(process.cwd(), ".codex", "config.toml");
10766
10797
  }
10767
10798
  function readTOML(path3) {
10768
10799
  if (!existsSync14(path3))
@@ -10825,9 +10856,9 @@ var CodexProvider = () => ({
10825
10856
  priority: () => 8,
10826
10857
  detectPaths: () => ["~/.codex"],
10827
10858
  isInstalled: () => isInstalled(["~/.codex"]),
10828
- globalConfigPath: () => join16(codexHome(), "config.toml"),
10859
+ globalConfigPath: () => join17(codexHome(), "config.toml"),
10829
10860
  isConfigured: () => {
10830
- const content = readTOML(join16(codexHome(), "config.toml"));
10861
+ const content = readTOML(join17(codexHome(), "config.toml"));
10831
10862
  return content.includes("[mcp_servers.dosu]");
10832
10863
  },
10833
10864
  install(cfg, global) {
@@ -10849,10 +10880,10 @@ var init_codex2 = __esm(() => {
10849
10880
  });
10850
10881
 
10851
10882
  // src/mcp/providers/copilot.ts
10852
- import { join as join17 } from "node:path";
10883
+ import { join as join18 } from "node:path";
10853
10884
  function globalPath() {
10854
10885
  if (process.env.XDG_CONFIG_HOME) {
10855
- return join17(process.env.XDG_CONFIG_HOME, "mcp-config.json");
10886
+ return join18(process.env.XDG_CONFIG_HOME, "mcp-config.json");
10856
10887
  }
10857
10888
  return expandHome("~/.copilot/mcp-config.json");
10858
10889
  }
@@ -10883,7 +10914,7 @@ var CopilotProvider = () => ({
10883
10914
  };
10884
10915
  installJSONServer(globalPath(), "mcpServers", server);
10885
10916
  } else {
10886
- const configPath = join17(process.cwd(), ".vscode", "mcp.json");
10917
+ const configPath = join18(process.cwd(), ".vscode", "mcp.json");
10887
10918
  const server = {
10888
10919
  type: "http",
10889
10920
  url,
@@ -10896,7 +10927,7 @@ var CopilotProvider = () => ({
10896
10927
  if (global) {
10897
10928
  removeJSONServer(globalPath(), "mcpServers");
10898
10929
  } else {
10899
- const configPath = join17(process.cwd(), ".vscode", "mcp.json");
10930
+ const configPath = join18(process.cwd(), ".vscode", "mcp.json");
10900
10931
  removeJSONServer(configPath, "servers");
10901
10932
  }
10902
10933
  }
@@ -10908,7 +10939,7 @@ var init_copilot = __esm(() => {
10908
10939
  });
10909
10940
 
10910
10941
  // src/mcp/providers/cursor.ts
10911
- import { join as join18 } from "node:path";
10942
+ import { join as join19 } from "node:path";
10912
10943
  var CursorProvider = () => createJSONProvider({
10913
10944
  providerName: "Cursor",
10914
10945
  providerID: "cursor",
@@ -10921,7 +10952,7 @@ var CursorProvider = () => createJSONProvider({
10921
10952
  url: mcpURL(cfg.active_account.target.deployment_id),
10922
10953
  headers: mcpHeaders(cfg.active_account.target.api_key)
10923
10954
  }),
10924
- localConfigPath: (cwd) => join18(cwd, ".cursor", "mcp.json")
10955
+ localConfigPath: (cwd) => join19(cwd, ".cursor", "mcp.json")
10925
10956
  });
10926
10957
  var init_cursor = __esm(() => {
10927
10958
  init_config_helpers();
@@ -10929,7 +10960,7 @@ var init_cursor = __esm(() => {
10929
10960
  });
10930
10961
 
10931
10962
  // src/mcp/providers/factory.ts
10932
- import { join as join19 } from "node:path";
10963
+ import { join as join20 } from "node:path";
10933
10964
  var FactoryProvider = () => createJSONProvider({
10934
10965
  providerName: "Factory",
10935
10966
  providerID: "factory",
@@ -10938,14 +10969,14 @@ var FactoryProvider = () => createJSONProvider({
10938
10969
  paths: ["~/.factory"],
10939
10970
  globalPath: "~/.factory/mcp.json",
10940
10971
  topKey: "mcpServers",
10941
- localConfigPath: (cwd) => join19(cwd, ".factory", "mcp.json")
10972
+ localConfigPath: (cwd) => join20(cwd, ".factory", "mcp.json")
10942
10973
  });
10943
10974
  var init_factory2 = __esm(() => {
10944
10975
  init_base();
10945
10976
  });
10946
10977
 
10947
10978
  // src/mcp/providers/gemini.ts
10948
- import { join as join20 } from "node:path";
10979
+ import { join as join21 } from "node:path";
10949
10980
  var GeminiProvider = () => createJSONProvider({
10950
10981
  providerName: "Gemini CLI",
10951
10982
  providerID: "gemini",
@@ -10954,7 +10985,7 @@ var GeminiProvider = () => createJSONProvider({
10954
10985
  paths: ["~/.gemini"],
10955
10986
  globalPath: "~/.gemini/settings.json",
10956
10987
  topKey: "mcpServers",
10957
- localConfigPath: (cwd) => join20(cwd, ".gemini", "settings.json")
10988
+ localConfigPath: (cwd) => join21(cwd, ".gemini", "settings.json")
10958
10989
  });
10959
10990
  var init_gemini = __esm(() => {
10960
10991
  init_base();
@@ -11005,7 +11036,7 @@ var init_manual = __esm(() => {
11005
11036
 
11006
11037
  // src/mcp/providers/mcporter.ts
11007
11038
  import { existsSync as existsSync15 } from "node:fs";
11008
- import { join as join21 } from "node:path";
11039
+ import { join as join22 } from "node:path";
11009
11040
  function resolveGlobalConfigPath() {
11010
11041
  const jsonPath = expandHome("~/.mcporter/mcporter.json");
11011
11042
  if (existsSync15(jsonPath))
@@ -11032,7 +11063,7 @@ var MCPorterProvider = () => ({
11032
11063
  globalConfigPath: () => resolveGlobalConfigPath(),
11033
11064
  isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
11034
11065
  install(cfg, global) {
11035
- const configPath = global ? resolveGlobalConfigPath() : join21(process.cwd(), "config", "mcporter.json");
11066
+ const configPath = global ? resolveGlobalConfigPath() : join22(process.cwd(), "config", "mcporter.json");
11036
11067
  const server = {
11037
11068
  type: "http",
11038
11069
  url: mcpEndpoint4(cfg),
@@ -11041,7 +11072,7 @@ var MCPorterProvider = () => ({
11041
11072
  installJSONServer(configPath, "mcpServers", server);
11042
11073
  },
11043
11074
  remove(global) {
11044
- const configPath = global ? resolveGlobalConfigPath() : join21(process.cwd(), "config", "mcporter.json");
11075
+ const configPath = global ? resolveGlobalConfigPath() : join22(process.cwd(), "config", "mcporter.json");
11045
11076
  removeJSONServer(configPath, "mcpServers");
11046
11077
  }
11047
11078
  });
@@ -11052,7 +11083,7 @@ var init_mcporter = __esm(() => {
11052
11083
  });
11053
11084
 
11054
11085
  // src/mcp/providers/opencode.ts
11055
- import { join as join22 } from "node:path";
11086
+ import { join as join23 } from "node:path";
11056
11087
  var OpenCodeProvider = () => createJSONProvider({
11057
11088
  providerName: "OpenCode",
11058
11089
  providerID: "opencode",
@@ -11067,7 +11098,7 @@ var OpenCodeProvider = () => createJSONProvider({
11067
11098
  enabled: true,
11068
11099
  headers: mcpHeaders(cfg.active_account.target.api_key)
11069
11100
  }),
11070
- localConfigPath: (cwd) => join22(cwd, "opencode.json")
11101
+ localConfigPath: (cwd) => join23(cwd, "opencode.json")
11071
11102
  });
11072
11103
  var init_opencode = __esm(() => {
11073
11104
  init_config_helpers();
@@ -11075,16 +11106,16 @@ var init_opencode = __esm(() => {
11075
11106
  });
11076
11107
 
11077
11108
  // src/mcp/providers/vscode.ts
11078
- import { join as join23 } from "node:path";
11109
+ import { join as join24 } from "node:path";
11079
11110
  var VSCodeProvider = () => createJSONProvider({
11080
11111
  providerName: "VS Code",
11081
11112
  providerID: "vscode",
11082
11113
  local: true,
11083
11114
  priorityValue: 6,
11084
- paths: [join23(appSupportDir(), "Code")],
11085
- globalPath: join23(appSupportDir(), "Code", "User", "mcp.json"),
11115
+ paths: [join24(appSupportDir(), "Code")],
11116
+ globalPath: join24(appSupportDir(), "Code", "User", "mcp.json"),
11086
11117
  topKey: "servers",
11087
- localConfigPath: (cwd) => join23(cwd, ".vscode", "mcp.json")
11118
+ localConfigPath: (cwd) => join24(cwd, ".vscode", "mcp.json")
11088
11119
  });
11089
11120
  var init_vscode = __esm(() => {
11090
11121
  init_detect();
@@ -11092,15 +11123,15 @@ var init_vscode = __esm(() => {
11092
11123
  });
11093
11124
 
11094
11125
  // src/mcp/providers/windsurf.ts
11095
- import { homedir as homedir2 } from "node:os";
11096
- import { join as join24 } from "node:path";
11126
+ import { homedir as homedir3 } from "node:os";
11127
+ import { join as join25 } from "node:path";
11097
11128
  var WindsurfProvider = () => createJSONProvider({
11098
11129
  providerName: "Windsurf",
11099
11130
  providerID: "windsurf",
11100
11131
  local: false,
11101
11132
  priorityValue: 9,
11102
- paths: [join24(homedir2(), ".codeium", "windsurf")],
11103
- globalPath: join24(homedir2(), ".codeium", "windsurf", "mcp_config.json"),
11133
+ paths: [join25(homedir3(), ".codeium", "windsurf")],
11134
+ globalPath: join25(homedir3(), ".codeium", "windsurf", "mcp_config.json"),
11104
11135
  topKey: "mcpServers"
11105
11136
  });
11106
11137
  var init_windsurf = __esm(() => {
@@ -11109,12 +11140,12 @@ var init_windsurf = __esm(() => {
11109
11140
 
11110
11141
  // src/mcp/providers/zed.ts
11111
11142
  import { platform as platform3 } from "node:os";
11112
- import { join as join25 } from "node:path";
11143
+ import { join as join26 } from "node:path";
11113
11144
  function zedConfigDir() {
11114
11145
  const os2 = platform3();
11115
11146
  if (os2 === "darwin" || os2 === "win32")
11116
- return join25(appSupportDir(), "Zed");
11117
- return join25(appSupportDir(), "zed");
11147
+ return join26(appSupportDir(), "Zed");
11148
+ return join26(appSupportDir(), "zed");
11118
11149
  }
11119
11150
  var ZedProvider = () => createJSONProvider({
11120
11151
  providerName: "Zed",
@@ -11122,7 +11153,7 @@ var ZedProvider = () => createJSONProvider({
11122
11153
  local: true,
11123
11154
  priorityValue: 10,
11124
11155
  paths: [zedConfigDir()],
11125
- globalPath: join25(zedConfigDir(), "settings.json"),
11156
+ globalPath: join26(zedConfigDir(), "settings.json"),
11126
11157
  topKey: "context_servers",
11127
11158
  buildServer: (cfg) => ({
11128
11159
  source: "custom",
@@ -11130,7 +11161,7 @@ var ZedProvider = () => createJSONProvider({
11130
11161
  url: mcpURL(cfg.active_account.target.deployment_id),
11131
11162
  headers: mcpHeaders(cfg.active_account.target.api_key)
11132
11163
  }),
11133
- localConfigPath: (cwd) => join25(cwd, ".zed", "settings.json")
11164
+ localConfigPath: (cwd) => join26(cwd, ".zed", "settings.json")
11134
11165
  });
11135
11166
  var init_zed = __esm(() => {
11136
11167
  init_config_helpers();
@@ -11190,13 +11221,13 @@ var init_providers = __esm(() => {
11190
11221
 
11191
11222
  // src/rules/installer.ts
11192
11223
  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";
11224
+ import { homedir as homedir4 } from "node:os";
11225
+ import { dirname as dirname5, join as join27 } from "node:path";
11195
11226
  function claudeConfigDir() {
11196
- return process.env.CLAUDE_CONFIG_DIR || join26(homedir3(), ".claude");
11227
+ return process.env.CLAUDE_CONFIG_DIR || join27(homedir4(), ".claude");
11197
11228
  }
11198
11229
  function codexHome2() {
11199
- return process.env.CODEX_HOME || join26(homedir3(), ".codex");
11230
+ return process.env.CODEX_HOME || join27(homedir4(), ".codex");
11200
11231
  }
11201
11232
  function isRuleAgent(agent) {
11202
11233
  return Object.hasOwn(RULE_TARGETS, agent);
@@ -11336,28 +11367,28 @@ var init_installer = __esm(() => {
11336
11367
  RULE_TARGETS = {
11337
11368
  claude: {
11338
11369
  kind: "file",
11339
- path: () => join26(claudeConfigDir(), "rules", "dosu.md")
11370
+ path: () => join27(claudeConfigDir(), "rules", "dosu.md")
11340
11371
  },
11341
11372
  cursor: {
11342
11373
  kind: "file",
11343
- path: () => join26(homedir3(), ".cursor", "rules", "dosu.mdc"),
11374
+ path: () => join27(homedir4(), ".cursor", "rules", "dosu.mdc"),
11344
11375
  cursorFrontmatter: true
11345
11376
  },
11346
11377
  codex: {
11347
11378
  kind: "section",
11348
- path: () => join26(codexHome2(), "AGENTS.md")
11379
+ path: () => join27(codexHome2(), "AGENTS.md")
11349
11380
  },
11350
11381
  opencode: {
11351
11382
  kind: "section",
11352
- path: () => join26(homedir3(), ".config", "opencode", "AGENTS.md")
11383
+ path: () => join27(homedir4(), ".config", "opencode", "AGENTS.md")
11353
11384
  },
11354
11385
  gemini: {
11355
11386
  kind: "section",
11356
- path: () => join26(homedir3(), ".gemini", "GEMINI.md")
11387
+ path: () => join27(homedir4(), ".gemini", "GEMINI.md")
11357
11388
  },
11358
11389
  antigravity: {
11359
11390
  kind: "section",
11360
- path: () => join26(homedir3(), ".gemini", "GEMINI.md")
11391
+ path: () => join27(homedir4(), ".gemini", "GEMINI.md")
11361
11392
  }
11362
11393
  };
11363
11394
  SUPPORTED_RULE_AGENT_IDS = Object.keys(RULE_TARGETS);
@@ -11366,7 +11397,7 @@ var init_installer = __esm(() => {
11366
11397
  // src/setup/agents-md-step.ts
11367
11398
  import { execSync as execSync3 } from "node:child_process";
11368
11399
  import { existsSync as existsSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
11369
- import { join as join27 } from "node:path";
11400
+ import { join as join28 } from "node:path";
11370
11401
  function inGitWorkTree(cwd = process.cwd()) {
11371
11402
  try {
11372
11403
  const stdout2 = execSync3("git rev-parse --is-inside-work-tree", {
@@ -11404,7 +11435,7 @@ function findSection2(content) {
11404
11435
  return { start, end };
11405
11436
  }
11406
11437
  function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
11407
- const path3 = join27(cwd, "AGENTS.md");
11438
+ const path3 = join28(cwd, "AGENTS.md");
11408
11439
  if (!existsSync17(path3)) {
11409
11440
  const section2 = buildDosuAgentsSection(content);
11410
11441
  writeFileSync8(path3, `${section2}
@@ -11431,13 +11462,8 @@ async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
11431
11462
  try {
11432
11463
  const result = upsertDosuAgentsSection(cwd, content ?? await fetchDosuRule());
11433
11464
  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
- }
11465
+ const status = result.action === "unchanged" ? "already up to date" : result.action;
11466
+ log.success(formatSetupSummary("AGENTS.md", [{ path: result.path, status }]));
11441
11467
  return true;
11442
11468
  } catch (err) {
11443
11469
  const msg = err instanceof Error ? err.message : String(err);
@@ -11618,18 +11644,10 @@ function logRuleResults(results) {
11618
11644
  const ready = results.filter((result) => !result.error && (result.action === "created" || result.action === "updated" || result.action === "unchanged"));
11619
11645
  const removed = results.filter((result) => !result.error && result.action === "removed");
11620
11646
  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}`);
11647
+ log.success(formatSetupSummary(`Rules ready for ${ready.length} agent(s):`, ready.map((result) => ({ label: result.provider.name(), path: result.path }))));
11626
11648
  }
11627
11649
  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}`);
11650
+ log.info(formatSetupSummary(`Rules removed from ${removed.length} agent(s):`, removed.map((result) => ({ label: result.provider.name(), path: result.path })), IconRemove));
11633
11651
  }
11634
11652
  }
11635
11653
  async function stepConfigureAgentRules(selection, mcpResults) {
@@ -12292,9 +12310,9 @@ async function runSetup(opts = {}) {
12292
12310
  });
12293
12311
  }
12294
12312
  let skillCompleted = false;
12295
- const selectedProviderIDs = configuredProviders.map((result) => result.provider.id());
12296
- if (skillAgentIDsForProviders(selectedProviderIDs).length > 0) {
12297
- skillCompleted = await runInstallSkill(selectedProviderIDs);
12313
+ const skillProviders = configuredProviders.map((result) => result.provider).filter((provider) => skillInstallTargetForProvider(provider.id()) !== null);
12314
+ if (skillProviders.length > 0) {
12315
+ skillCompleted = await runInstallSkill(skillProviders);
12298
12316
  if (skillCompleted) {
12299
12317
  await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_skill_installed");
12300
12318
  }
@@ -12357,13 +12375,25 @@ Run ${info("dosu mcp add <agent>")} to manually configure an agent.`);
12357
12375
  await stepConfigureAgentRules(selection, results);
12358
12376
  return results;
12359
12377
  }
12360
- async function runInstallSkill(providerIDs) {
12378
+ async function runInstallSkill(providers) {
12361
12379
  logger.info("setup", "Step: install skill");
12362
12380
  try {
12363
- const result = await installSkill(providerIDs, { quiet: true });
12381
+ const result = await installSkill(providers.map((provider) => provider.id()), { quiet: true });
12364
12382
  if (result.success) {
12365
12383
  logger.info("setup", `Skill installed${result.sha ? ` sha=${result.sha}` : ""}`);
12366
- log.success("Skill installed");
12384
+ const items = providers.flatMap((provider) => {
12385
+ const target = skillInstallTargetForProvider(provider.id());
12386
+ if (!target)
12387
+ return [];
12388
+ return [
12389
+ {
12390
+ label: provider.name(),
12391
+ path: target.path,
12392
+ status: target.symlink ? "symlink" : undefined
12393
+ }
12394
+ ];
12395
+ });
12396
+ log.success(formatSetupSummary(`Skill ready for ${items.length} agent(s):`, items));
12367
12397
  return true;
12368
12398
  }
12369
12399
  log.error("Failed to install skill. Run `dosu skill install` to retry.");
@@ -12794,18 +12824,16 @@ function stepShowSummary(results) {
12794
12824
  const removed = results.filter((r2) => r2.action === "remove" && !r2.error);
12795
12825
  const skipped = results.filter((r2) => r2.action === "skip");
12796
12826
  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}`);
12827
+ log.success(formatSetupSummary(`Configured ${installed.length} agent(s):`, installed.map((result) => ({
12828
+ label: result.provider.name(),
12829
+ path: result.provider.globalConfigPath()
12830
+ }))));
12802
12831
  }
12803
12832
  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}`);
12833
+ log.info(formatSetupSummary(`Removed from ${removed.length} agent(s):`, removed.map((result) => ({
12834
+ label: result.provider.name(),
12835
+ path: result.provider.globalConfigPath()
12836
+ })), IconRemove));
12809
12837
  }
12810
12838
  if (installed.length === 0 && removed.length === 0 && skipped.length > 0) {
12811
12839
  log.success("All agents already configured. No changes needed.");
@@ -12827,7 +12855,7 @@ var init_flow2 = __esm(() => {
12827
12855
 
12828
12856
  // src/commands/insights.ts
12829
12857
  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";
12858
+ import { dirname as dirname6, join as join29 } from "node:path";
12831
12859
  function shuffled(arr) {
12832
12860
  const copy2 = [...arr];
12833
12861
  for (let i2 = copy2.length - 1;i2 > 0; i2--) {
@@ -12931,14 +12959,14 @@ function makeAskFn(cfg) {
12931
12959
  };
12932
12960
  }
12933
12961
  function insightsDir() {
12934
- return join28(getConfigDir(), "insights");
12962
+ return join29(getConfigDir(), "insights");
12935
12963
  }
12936
12964
  function reportPath(timestamp) {
12937
12965
  const dir = insightsDir();
12938
12966
  if (!timestamp)
12939
- return join28(dir, "latest.html");
12967
+ return join29(dir, "latest.html");
12940
12968
  const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
12941
- return join28(dir, `report-${iso}Z.html`);
12969
+ return join29(dir, `report-${iso}Z.html`);
12942
12970
  }
12943
12971
  function pruneOldReports(dir, keepN) {
12944
12972
  if (!existsSync18(dir))
@@ -12953,7 +12981,7 @@ function pruneOldReports(dir, keepN) {
12953
12981
  const reports = entries.filter((f2) => REPORT_FILE_PATTERN.test(f2)).sort().reverse();
12954
12982
  for (const f2 of reports.slice(keepN)) {
12955
12983
  try {
12956
- unlinkSync2(join28(dir, f2));
12984
+ unlinkSync2(join29(dir, f2));
12957
12985
  } catch (err) {
12958
12986
  logger.debug("insights", `failed to prune ${f2}: ${err instanceof Error ? err.message : err}`);
12959
12987
  }
@@ -16619,7 +16647,7 @@ init_config();
16619
16647
  init_logger();
16620
16648
  var import_picocolors24 = __toESM(require_picocolors(), 1);
16621
16649
  import { existsSync as existsSync19, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
16622
- import { join as join29 } from "node:path";
16650
+ import { join as join30 } from "node:path";
16623
16651
  var CACHE_FILENAME3 = "update-check.json";
16624
16652
  var CHECK_INTERVAL_MS3 = 24 * 60 * 60 * 1000;
16625
16653
  var FETCH_TIMEOUT_MS3 = 5000;
@@ -16642,7 +16670,7 @@ function isNewerVersion(latest, current) {
16642
16670
  return false;
16643
16671
  }
16644
16672
  function getCachePath3() {
16645
- return join29(getConfigDir(), CACHE_FILENAME3);
16673
+ return join30(getConfigDir(), CACHE_FILENAME3);
16646
16674
  }
16647
16675
  function readCache() {
16648
16676
  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.4",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",