@skillsmith/cli 0.5.12 → 0.6.1

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 (155) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +92 -2
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/commands/audit-collisions.d.ts +71 -0
  5. package/dist/src/commands/audit-collisions.d.ts.map +1 -0
  6. package/dist/src/commands/audit-collisions.js +300 -0
  7. package/dist/src/commands/audit-collisions.js.map +1 -0
  8. package/dist/src/commands/audit.d.ts +27 -2
  9. package/dist/src/commands/audit.d.ts.map +1 -1
  10. package/dist/src/commands/audit.js +73 -13
  11. package/dist/src/commands/audit.js.map +1 -1
  12. package/dist/src/commands/audit.test.js +2 -2
  13. package/dist/src/commands/audit.test.js.map +1 -1
  14. package/dist/src/commands/config.d.ts +55 -0
  15. package/dist/src/commands/config.d.ts.map +1 -0
  16. package/dist/src/commands/config.js +211 -0
  17. package/dist/src/commands/config.js.map +1 -0
  18. package/dist/src/commands/create.d.ts +3 -3
  19. package/dist/src/commands/create.d.ts.map +1 -1
  20. package/dist/src/commands/create.js +11 -9
  21. package/dist/src/commands/create.js.map +1 -1
  22. package/dist/src/commands/diff.js +2 -2
  23. package/dist/src/commands/diff.js.map +1 -1
  24. package/dist/src/commands/import-local.d.ts +21 -0
  25. package/dist/src/commands/import-local.d.ts.map +1 -0
  26. package/dist/src/commands/import-local.helpers.d.ts +28 -0
  27. package/dist/src/commands/import-local.helpers.d.ts.map +1 -0
  28. package/dist/src/commands/import-local.helpers.js +166 -0
  29. package/dist/src/commands/import-local.helpers.js.map +1 -0
  30. package/dist/src/commands/import-local.js +264 -0
  31. package/dist/src/commands/import-local.js.map +1 -0
  32. package/dist/src/commands/import-local.types.d.ts +59 -0
  33. package/dist/src/commands/import-local.types.d.ts.map +1 -0
  34. package/dist/src/commands/import-local.types.js +2 -0
  35. package/dist/src/commands/import-local.types.js.map +1 -0
  36. package/dist/src/{import.d.ts → commands/import.d.ts} +11 -0
  37. package/dist/src/commands/import.d.ts.map +1 -0
  38. package/dist/src/{import.js → commands/import.js} +39 -4
  39. package/dist/src/commands/import.js.map +1 -0
  40. package/dist/src/commands/index.d.ts +3 -0
  41. package/dist/src/commands/index.d.ts.map +1 -1
  42. package/dist/src/commands/index.js +6 -0
  43. package/dist/src/commands/index.js.map +1 -1
  44. package/dist/src/commands/info.d.ts.map +1 -1
  45. package/dist/src/commands/info.js +3 -3
  46. package/dist/src/commands/info.js.map +1 -1
  47. package/dist/src/commands/install-skill.d.ts.map +1 -1
  48. package/dist/src/commands/install-skill.js +6 -3
  49. package/dist/src/commands/install-skill.js.map +1 -1
  50. package/dist/src/commands/install.d.ts.map +1 -1
  51. package/dist/src/commands/install.js +81 -7
  52. package/dist/src/commands/install.js.map +1 -1
  53. package/dist/src/commands/login.d.ts.map +1 -1
  54. package/dist/src/commands/login.js +37 -0
  55. package/dist/src/commands/login.js.map +1 -1
  56. package/dist/src/commands/login.post-login-sync.test.d.ts +2 -0
  57. package/dist/src/commands/login.post-login-sync.test.d.ts.map +1 -0
  58. package/dist/src/commands/login.post-login-sync.test.js +120 -0
  59. package/dist/src/commands/login.post-login-sync.test.js.map +1 -0
  60. package/dist/src/commands/login.test-helpers.d.ts +7 -0
  61. package/dist/src/commands/login.test-helpers.d.ts.map +1 -0
  62. package/dist/src/commands/login.test-helpers.js +44 -0
  63. package/dist/src/commands/login.test-helpers.js.map +1 -0
  64. package/dist/src/commands/login.test.js +30 -31
  65. package/dist/src/commands/login.test.js.map +1 -1
  66. package/dist/src/commands/manage.d.ts.map +1 -1
  67. package/dist/src/commands/manage.js +17 -4
  68. package/dist/src/commands/manage.js.map +1 -1
  69. package/dist/src/commands/recommend.helpers.d.ts +5 -1
  70. package/dist/src/commands/recommend.helpers.d.ts.map +1 -1
  71. package/dist/src/commands/recommend.helpers.js +9 -3
  72. package/dist/src/commands/recommend.helpers.js.map +1 -1
  73. package/dist/src/commands/run-registry-sync.d.ts +31 -0
  74. package/dist/src/commands/run-registry-sync.d.ts.map +1 -0
  75. package/dist/src/commands/run-registry-sync.js +45 -0
  76. package/dist/src/commands/run-registry-sync.js.map +1 -0
  77. package/dist/src/commands/search.d.ts.map +1 -1
  78. package/dist/src/commands/search.helpers.d.ts +23 -0
  79. package/dist/src/commands/search.helpers.d.ts.map +1 -0
  80. package/dist/src/commands/search.helpers.js +57 -0
  81. package/dist/src/commands/search.helpers.js.map +1 -0
  82. package/dist/src/commands/search.js +12 -5
  83. package/dist/src/commands/search.js.map +1 -1
  84. package/dist/src/commands/sync.d.ts.map +1 -1
  85. package/dist/src/commands/sync.js +10 -21
  86. package/dist/src/commands/sync.js.map +1 -1
  87. package/dist/src/config.d.ts +6 -1
  88. package/dist/src/config.d.ts.map +1 -1
  89. package/dist/src/config.js +8 -2
  90. package/dist/src/config.js.map +1 -1
  91. package/dist/src/index.d.ts +1 -1
  92. package/dist/src/index.js +10 -28
  93. package/dist/src/index.js.map +1 -1
  94. package/dist/src/templates/mcp-server.template.d.ts +1 -1
  95. package/dist/src/templates/mcp-server.template.d.ts.map +1 -1
  96. package/dist/src/templates/mcp-server.template.js +13 -13
  97. package/dist/src/templates/mcp-server.template.js.map +1 -1
  98. package/dist/src/templates/mcp-server.template.snippets.d.ts +51 -0
  99. package/dist/src/templates/mcp-server.template.snippets.d.ts.map +1 -0
  100. package/dist/src/templates/mcp-server.template.snippets.js +162 -0
  101. package/dist/src/templates/mcp-server.template.snippets.js.map +1 -0
  102. package/dist/src/templates/readme.md.template.d.ts +1 -1
  103. package/dist/src/templates/readme.md.template.d.ts.map +1 -1
  104. package/dist/src/templates/readme.md.template.js +2 -2
  105. package/dist/src/utils/open-database.d.ts +27 -0
  106. package/dist/src/utils/open-database.d.ts.map +1 -0
  107. package/dist/src/utils/open-database.js +31 -0
  108. package/dist/src/utils/open-database.js.map +1 -0
  109. package/dist/src/utils/skills-directory.d.ts +26 -7
  110. package/dist/src/utils/skills-directory.d.ts.map +1 -1
  111. package/dist/src/utils/skills-directory.js +78 -33
  112. package/dist/src/utils/skills-directory.js.map +1 -1
  113. package/dist/tests/audit-collisions.test.d.ts +42 -0
  114. package/dist/tests/audit-collisions.test.d.ts.map +1 -0
  115. package/dist/tests/audit-collisions.test.js +370 -0
  116. package/dist/tests/audit-collisions.test.js.map +1 -0
  117. package/dist/tests/audit-restructure.test.d.ts +15 -0
  118. package/dist/tests/audit-restructure.test.d.ts.map +1 -0
  119. package/dist/tests/audit-restructure.test.js +151 -0
  120. package/dist/tests/audit-restructure.test.js.map +1 -0
  121. package/dist/tests/config.test.d.ts +33 -0
  122. package/dist/tests/config.test.d.ts.map +1 -0
  123. package/dist/tests/config.test.js +240 -0
  124. package/dist/tests/config.test.js.map +1 -0
  125. package/dist/tests/install-multi-client.test.d.ts +2 -0
  126. package/dist/tests/install-multi-client.test.d.ts.map +1 -0
  127. package/dist/tests/install-multi-client.test.js +202 -0
  128. package/dist/tests/install-multi-client.test.js.map +1 -0
  129. package/dist/tests/integration/import-local.test.d.ts +2 -0
  130. package/dist/tests/integration/import-local.test.d.ts.map +1 -0
  131. package/dist/tests/integration/import-local.test.js +158 -0
  132. package/dist/tests/integration/import-local.test.js.map +1 -0
  133. package/dist/tests/mcp-server-template.test.js +21 -0
  134. package/dist/tests/mcp-server-template.test.js.map +1 -1
  135. package/dist/tests/open-database.test.d.ts +2 -0
  136. package/dist/tests/open-database.test.d.ts.map +1 -0
  137. package/dist/tests/open-database.test.js +52 -0
  138. package/dist/tests/open-database.test.js.map +1 -0
  139. package/dist/tests/search-helpers.test.d.ts +2 -0
  140. package/dist/tests/search-helpers.test.d.ts.map +1 -0
  141. package/dist/tests/search-helpers.test.js +110 -0
  142. package/dist/tests/search-helpers.test.js.map +1 -0
  143. package/dist/tests/skills-directory.test.d.ts +2 -0
  144. package/dist/tests/skills-directory.test.d.ts.map +1 -0
  145. package/dist/tests/skills-directory.test.js +97 -0
  146. package/dist/tests/skills-directory.test.js.map +1 -0
  147. package/dist/tests/unit/commands/install.test.js +75 -1
  148. package/dist/tests/unit/commands/install.test.js.map +1 -1
  149. package/dist/tests/unit/import-local.helpers.test.d.ts +2 -0
  150. package/dist/tests/unit/import-local.helpers.test.d.ts.map +1 -0
  151. package/dist/tests/unit/import-local.helpers.test.js +96 -0
  152. package/dist/tests/unit/import-local.helpers.test.js.map +1 -0
  153. package/package.json +10 -4
  154. package/dist/src/import.d.ts.map +0 -1
  155. package/dist/src/import.js.map +0 -1
@@ -0,0 +1,162 @@
1
+ /**
2
+ * SMI-4580: Per-client MCP config snippets.
3
+ *
4
+ * Single source of truth for the install-time configuration block each
5
+ * agent expects. Same source feeds:
6
+ * - the scaffolded mcp-server README (via mcp-server.template.ts)
7
+ * - the website docs (`getting-started.astro`, `quickstart.astro`)
8
+ * - the root README + packages/mcp-server/README.md
9
+ *
10
+ * Four of five clients accept the same `mcpServers` JSON shape.
11
+ * Codex needs TOML (separate `[mcp_servers.<name>]` table).
12
+ *
13
+ * @module @skillsmith/cli/templates/mcp-server.template.snippets
14
+ */
15
+ /**
16
+ * Per-client snippet matrix. `name` placeholder is interpolated when the
17
+ * snippet is rendered; pass `'@skillsmith/mcp-server'` for the published
18
+ * package, or any other server name when scaffolding via the template.
19
+ */
20
+ export const CLIENT_SNIPPETS = {
21
+ 'claude-code': {
22
+ label: 'Claude Code',
23
+ configPath: '~/.claude/settings.json',
24
+ format: 'json',
25
+ body: `{
26
+ "mcpServers": {
27
+ "{{name}}": {
28
+ "command": "npx",
29
+ "args": ["-y", "{{name}}"],
30
+ "env": {
31
+ "SKILLSMITH_API_KEY": "sk_live_..."
32
+ }
33
+ }
34
+ }
35
+ }`,
36
+ notes: 'Restart Claude Code after editing settings.json.',
37
+ },
38
+ cursor: {
39
+ label: 'Cursor',
40
+ configPath: '~/.cursor/mcp.json',
41
+ format: 'json',
42
+ body: `{
43
+ "mcpServers": {
44
+ "{{name}}": {
45
+ "command": "npx",
46
+ "args": ["-y", "{{name}}"],
47
+ "env": {
48
+ "SKILLSMITH_API_KEY": "sk_live_..."
49
+ }
50
+ }
51
+ }
52
+ }`,
53
+ notes: 'Cursor 2.4+ required. Reload the window after saving.',
54
+ },
55
+ copilot: {
56
+ label: 'GitHub Copilot (VS Code)',
57
+ configPath: '.vscode/mcp.json (workspace)',
58
+ format: 'json',
59
+ body: `{
60
+ "mcpServers": {
61
+ "{{name}}": {
62
+ "command": "npx",
63
+ "args": ["-y", "{{name}}"],
64
+ "env": {
65
+ "SKILLSMITH_API_KEY": "sk_live_..."
66
+ }
67
+ }
68
+ }
69
+ }`,
70
+ notes: 'VS Code 1.108+ required. Workspace-scoped config (commit to repo if team-shared, or use user settings.json instead).',
71
+ },
72
+ windsurf: {
73
+ label: 'Windsurf',
74
+ configPath: '~/.codeium/windsurf/mcp_config.json',
75
+ format: 'json',
76
+ body: `{
77
+ "mcpServers": {
78
+ "{{name}}": {
79
+ "command": "npx",
80
+ "args": ["-y", "{{name}}"],
81
+ "env": {
82
+ "SKILLSMITH_API_KEY": "\${env:SKILLSMITH_API_KEY}"
83
+ }
84
+ }
85
+ }
86
+ }`,
87
+ notes: 'Supports `${env:VAR}` interpolation; export SKILLSMITH_API_KEY in your shell instead of inlining the secret.',
88
+ },
89
+ agents: {
90
+ label: 'Cross-agent (open standard)',
91
+ configPath: '~/.agents/mcp.json',
92
+ format: 'json',
93
+ body: `{
94
+ "mcpServers": {
95
+ "{{name}}": {
96
+ "command": "npx",
97
+ "args": ["-y", "{{name}}"],
98
+ "env": {
99
+ "SKILLSMITH_API_KEY": "sk_live_..."
100
+ }
101
+ }
102
+ }
103
+ }`,
104
+ notes: 'Read by any agent honouring the cross-agent skill convention. Codex CLI users prefer the Codex-native TOML snippet below.',
105
+ },
106
+ codex: {
107
+ label: 'Codex CLI',
108
+ configPath: '~/.codex/config.toml',
109
+ format: 'toml',
110
+ body: `[mcp_servers.{{name}}]
111
+ command = "npx"
112
+ args = ["-y", "{{name}}"]
113
+
114
+ [mcp_servers.{{name}}.env]
115
+ SKILLSMITH_API_KEY = "sk_live_..."`,
116
+ notes: 'Codex uses TOML, not JSON. Skill discovery still reads ~/.agents/skills (set --client agents when installing via Skillsmith CLI).',
117
+ },
118
+ };
119
+ /**
120
+ * Render a single client snippet with the package name interpolated.
121
+ */
122
+ export function renderSnippet(client, packageName) {
123
+ const snippet = CLIENT_SNIPPETS[client];
124
+ return snippet.body.replace(/\{\{name\}\}/g, packageName);
125
+ }
126
+ /**
127
+ * Render every snippet as a markdown section sequence — labelled with
128
+ * `<details>` + `<summary>` so the docs surface stays compact when no
129
+ * dedicated tabs component is available. Used by both the website
130
+ * markdown surfaces and the scaffolded mcp-server README.
131
+ */
132
+ export function renderAllSnippetsAsMarkdown(packageName) {
133
+ const sections = Object.keys(CLIENT_SNIPPETS).map((id) => {
134
+ const snippet = CLIENT_SNIPPETS[id];
135
+ const body = renderSnippet(id, packageName);
136
+ const notes = snippet.notes ? `\n\n${snippet.notes}` : '';
137
+ return [
138
+ `<details>`,
139
+ `<summary><strong>${snippet.label}</strong> — \`${snippet.configPath}\`</summary>`,
140
+ ``,
141
+ `\`\`\`${snippet.format}`,
142
+ body,
143
+ `\`\`\`${notes}`,
144
+ ``,
145
+ `</details>`,
146
+ ].join('\n');
147
+ });
148
+ return sections.join('\n\n');
149
+ }
150
+ /**
151
+ * Snippet IDs in display order. Use when a docs surface needs to
152
+ * render snippets without a `<details>` accordion (e.g. printable PDF).
153
+ */
154
+ export const SNIPPET_DISPLAY_ORDER = Object.freeze([
155
+ 'claude-code',
156
+ 'cursor',
157
+ 'copilot',
158
+ 'windsurf',
159
+ 'codex',
160
+ 'agents',
161
+ ]);
162
+ //# sourceMappingURL=mcp-server.template.snippets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.template.snippets.js","sourceRoot":"","sources":["../../../src/templates/mcp-server.template.snippets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAmBH;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAA2C;IACrE,aAAa,EAAE;QACb,KAAK,EAAE,aAAa;QACpB,UAAU,EAAE,yBAAyB;QACrC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE;;;;;;;;;;EAUR;QACE,KAAK,EAAE,kDAAkD;KAC1D;IACD,MAAM,EAAE;QACN,KAAK,EAAE,QAAQ;QACf,UAAU,EAAE,oBAAoB;QAChC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE;;;;;;;;;;EAUR;QACE,KAAK,EAAE,uDAAuD;KAC/D;IACD,OAAO,EAAE;QACP,KAAK,EAAE,0BAA0B;QACjC,UAAU,EAAE,8BAA8B;QAC1C,MAAM,EAAE,MAAM;QACd,IAAI,EAAE;;;;;;;;;;EAUR;QACE,KAAK,EACH,sHAAsH;KACzH;IACD,QAAQ,EAAE;QACR,KAAK,EAAE,UAAU;QACjB,UAAU,EAAE,qCAAqC;QACjD,MAAM,EAAE,MAAM;QACd,IAAI,EAAE;;;;;;;;;;EAUR;QACE,KAAK,EACH,8GAA8G;KACjH;IACD,MAAM,EAAE;QACN,KAAK,EAAE,6BAA6B;QACpC,UAAU,EAAE,oBAAoB;QAChC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE;;;;;;;;;;EAUR;QACE,KAAK,EACH,2HAA2H;KAC9H;IACD,KAAK,EAAE;QACL,KAAK,EAAE,WAAW;QAClB,UAAU,EAAE,sBAAsB;QAClC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE;;;;;mCAKyB;QAC/B,KAAK,EACH,mIAAmI;KACtI;CACF,CAAA;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAAuB,EAAE,WAAmB;IACxE,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;IACvC,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,WAAW,CAAC,CAAA;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CAAC,WAAmB;IAC7D,MAAM,QAAQ,GAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAuB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QAC9E,MAAM,OAAO,GAAG,eAAe,CAAC,EAAE,CAAC,CAAA;QACnC,MAAM,IAAI,GAAG,aAAa,CAAC,EAAE,EAAE,WAAW,CAAC,CAAA;QAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACzD,OAAO;YACL,WAAW;YACX,oBAAoB,OAAO,CAAC,KAAK,iBAAiB,OAAO,CAAC,UAAU,cAAc;YAClF,EAAE;YACF,SAAS,OAAO,CAAC,MAAM,EAAE;YACzB,IAAI;YACJ,SAAS,KAAK,EAAE;YAChB,EAAE;YACF,YAAY;SACb,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACd,CAAC,CAAC,CAAA;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAmC,MAAM,CAAC,MAAM,CAAC;IACjF,aAAa;IACb,QAAQ;IACR,SAAS;IACT,UAAU;IACV,OAAO;IACP,QAAQ;CACT,CAAC,CAAA"}
@@ -3,6 +3,6 @@
3
3
  *
4
4
  * Template for new skill README files.
5
5
  */
6
- export declare const README_MD_TEMPLATE = "# {{name}}\n\n{{description}}\n\n## Overview\n\nThis is a Claude Code skill that provides [describe functionality].\n\n## Installation\n\n### Via Skillsmith\n\n```bash\nskillsmith install {{author}}/{{name}}\n```\n\n### Manual Installation\n\n1. Clone or download this repository\n2. Copy to your skills directory:\n\n```bash\ncp -r {{name}} ~/.claude/skills/\n```\n\n## Quick Start\n\n1. Install the skill\n2. Start Claude Code\n3. Use the skill by [describe how to trigger]\n\n## Documentation\n\nSee [SKILL.md](./SKILL.md) for detailed documentation.\n\n## Development\n\n### Prerequisites\n\n- Node.js 18+\n- npm or pnpm\n\n### Setup\n\n```bash\n# Install dependencies (if any)\nnpm install\n\n# Run tests\nnpm test\n```\n\n### Project Structure\n\n```\n{{name}}/\n\u251C\u2500\u2500 SKILL.md # Skill definition and documentation\n\u251C\u2500\u2500 README.md # This file\n\u251C\u2500\u2500 scripts/ # Automation scripts\n\u2502 \u2514\u2500\u2500 example.js # Example script\n\u251C\u2500\u2500 resources/ # Static resources\n\u2514\u2500\u2500 .gitignore # Git ignore rules\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Submit a pull request\n\n## License\n\nMIT License\n\n## Author\n\nCreated with [Skillsmith](https://github.com/skillsmith/skillsmith)\n";
6
+ export declare const README_MD_TEMPLATE = "# {{name}}\n\n{{description}}\n\n## Overview\n\nThis is an agent skill (SKILL.md format, MCP-compatible) that provides [describe functionality].\n\n## Installation\n\n### Via Skillsmith\n\n```bash\nskillsmith install {{author}}/{{name}}\n```\n\n### Manual Installation\n\n1. Clone or download this repository\n2. Copy to your skills directory:\n\n```bash\ncp -r {{name}} ~/.claude/skills/\n```\n\n## Quick Start\n\n1. Install the skill\n2. Start your MCP-compatible agent (Claude Code, Cursor, Copilot, Codex, Windsurf, etc.)\n3. Use the skill by [describe how to trigger]\n\n## Documentation\n\nSee [SKILL.md](./SKILL.md) for detailed documentation.\n\n## Development\n\n### Prerequisites\n\n- Node.js 18+\n- npm or pnpm\n\n### Setup\n\n```bash\n# Install dependencies (if any)\nnpm install\n\n# Run tests\nnpm test\n```\n\n### Project Structure\n\n```\n{{name}}/\n\u251C\u2500\u2500 SKILL.md # Skill definition and documentation\n\u251C\u2500\u2500 README.md # This file\n\u251C\u2500\u2500 scripts/ # Automation scripts\n\u2502 \u2514\u2500\u2500 example.js # Example script\n\u251C\u2500\u2500 resources/ # Static resources\n\u2514\u2500\u2500 .gitignore # Git ignore rules\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Submit a pull request\n\n## License\n\nMIT License\n\n## Author\n\nCreated with [Skillsmith](https://github.com/skillsmith/skillsmith)\n";
7
7
  export default README_MD_TEMPLATE;
8
8
  //# sourceMappingURL=readme.md.template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"readme.md.template.d.ts","sourceRoot":"","sources":["../../../src/templates/readme.md.template.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,kBAAkB,21CA8E9B,CAAA;AAED,eAAe,kBAAkB,CAAA"}
1
+ {"version":3,"file":"readme.md.template.d.ts","sourceRoot":"","sources":["../../../src/templates/readme.md.template.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,kBAAkB,47CA8E9B,CAAA;AAED,eAAe,kBAAkB,CAAA"}
@@ -9,7 +9,7 @@ export const README_MD_TEMPLATE = `# {{name}}
9
9
 
10
10
  ## Overview
11
11
 
12
- This is a Claude Code skill that provides [describe functionality].
12
+ This is an agent skill (SKILL.md format, MCP-compatible) that provides [describe functionality].
13
13
 
14
14
  ## Installation
15
15
 
@@ -31,7 +31,7 @@ cp -r {{name}} ~/.claude/skills/
31
31
  ## Quick Start
32
32
 
33
33
  1. Install the skill
34
- 2. Start Claude Code
34
+ 2. Start your MCP-compatible agent (Claude Code, Cursor, Copilot, Codex, Windsurf, etc.)
35
35
  3. Use the skill by [describe how to trigger]
36
36
 
37
37
  ## Documentation
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Shared CLI database opener — the single schema-safe entry point.
3
+ * @see SMI-4486, SMI-4917
4
+ *
5
+ * `@skillsmith/core` re-exports the BARE `createDatabaseAsync` factory
6
+ * (`db/createDatabase.js`) — it opens a connection but creates NO tables. Every
7
+ * CLI command that touches a table (`skills`, `cache`, `sync_history`, …) MUST
8
+ * call `initializeSchema` first, or it crashes on a fresh DB with errors like
9
+ * `no such table: cache`.
10
+ *
11
+ * Before this helper, each command repeated `createDatabaseAsync` +
12
+ * `initializeSchema` by hand; any command that forgot the second line shipped a
13
+ * first-time-install crash (Bug 1 of SMI-4917 — `search` did exactly this).
14
+ * `openCliDatabase` makes the footgun structurally impossible: it is the one
15
+ * unmissable way a CLI command opens a database.
16
+ */
17
+ import { type DatabaseType } from '@skillsmith/core';
18
+ /**
19
+ * Open a CLI database with the full schema initialized and all migrations
20
+ * applied. Use this everywhere a CLI command needs a database — never call the
21
+ * bare `createDatabaseAsync` directly.
22
+ *
23
+ * @param path - Filesystem path to the SQLite database (e.g. `DEFAULT_DB_PATH`).
24
+ * @returns A connected, schema-initialized database. Caller owns `db.close()`.
25
+ */
26
+ export declare function openCliDatabase(path: string): Promise<DatabaseType>;
27
+ //# sourceMappingURL=open-database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-database.d.ts","sourceRoot":"","sources":["../../../src/utils/open-database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAyC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE3F;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAIzE"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @fileoverview Shared CLI database opener — the single schema-safe entry point.
3
+ * @see SMI-4486, SMI-4917
4
+ *
5
+ * `@skillsmith/core` re-exports the BARE `createDatabaseAsync` factory
6
+ * (`db/createDatabase.js`) — it opens a connection but creates NO tables. Every
7
+ * CLI command that touches a table (`skills`, `cache`, `sync_history`, …) MUST
8
+ * call `initializeSchema` first, or it crashes on a fresh DB with errors like
9
+ * `no such table: cache`.
10
+ *
11
+ * Before this helper, each command repeated `createDatabaseAsync` +
12
+ * `initializeSchema` by hand; any command that forgot the second line shipped a
13
+ * first-time-install crash (Bug 1 of SMI-4917 — `search` did exactly this).
14
+ * `openCliDatabase` makes the footgun structurally impossible: it is the one
15
+ * unmissable way a CLI command opens a database.
16
+ */
17
+ import { createDatabaseAsync, initializeSchema } from '@skillsmith/core';
18
+ /**
19
+ * Open a CLI database with the full schema initialized and all migrations
20
+ * applied. Use this everywhere a CLI command needs a database — never call the
21
+ * bare `createDatabaseAsync` directly.
22
+ *
23
+ * @param path - Filesystem path to the SQLite database (e.g. `DEFAULT_DB_PATH`).
24
+ * @returns A connected, schema-initialized database. Caller owns `db.close()`.
25
+ */
26
+ export async function openCliDatabase(path) {
27
+ const db = await createDatabaseAsync(path);
28
+ initializeSchema(db);
29
+ return db;
30
+ }
31
+ //# sourceMappingURL=open-database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-database.js","sourceRoot":"","sources":["../../../src/utils/open-database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAqB,MAAM,kBAAkB,CAAA;AAE3F;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,MAAM,EAAE,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAA;IAC1C,gBAAgB,CAAC,EAAE,CAAC,CAAA;IACpB,OAAO,EAAE,CAAA;AACX,CAAC"}
@@ -3,6 +3,7 @@
3
3
  * from the global and local ~/.claude/skills directories.
4
4
  */
5
5
  import { type TrustTier } from '@skillsmith/core';
6
+ import { type ClientId } from '@skillsmith/core/install';
6
7
  export interface InstalledSkill {
7
8
  name: string;
8
9
  path: string;
@@ -10,6 +11,12 @@ export interface InstalledSkill {
10
11
  trustTier: TrustTier;
11
12
  installDate: string;
12
13
  hasUpdates: boolean;
14
+ /**
15
+ * SMI-4578: which client's directory this skill was discovered under.
16
+ * `'local'` = repo-local `./.claude/skills`. Other values are
17
+ * `ClientId` from the multi-client install table.
18
+ */
19
+ installedVia: ClientId | 'local';
13
20
  }
14
21
  /**
15
22
  * Get skills from a specific directory.
@@ -18,17 +25,29 @@ export interface InstalledSkill {
18
25
  * whether a newer content hash has been recorded since the skill was installed.
19
26
  * Falls back to hasUpdates: false when the database is unavailable.
20
27
  *
21
- * @param skillsDir Directory to scan for installed skills
22
- * @param dbPath Optional path to the Skillsmith SQLite database
28
+ * @param skillsDir Directory to scan for installed skills
29
+ * @param dbPath Optional path to the Skillsmith SQLite database
30
+ * @param installedVia SMI-4578: which client (or `'local'`) this directory
31
+ * represents — propagated onto each returned skill so
32
+ * callers can render "installed via Cursor" badges.
23
33
  */
24
- export declare function getSkillsFromDirectory(skillsDir: string, dbPath?: string): Promise<InstalledSkill[]>;
34
+ export declare function getSkillsFromDirectory(skillsDir: string, dbPath?: string, installedVia?: ClientId | 'local'): Promise<InstalledSkill[]>;
25
35
  /**
26
- * Get list of installed skills from both global (~/.claude/skills) and
27
- * local (.claude/skills) directories.
36
+ * Get list of installed skills across every client directory.
28
37
  *
29
- * SMI-1630: Local skills take precedence over global skills with the same name.
38
+ * SMI-4578: scans the union of `CLIENT_NATIVE_PATHS` (claude-code,
39
+ * cursor, copilot, windsurf, agents) plus repo-local
40
+ * `./.claude/skills`. Results are deduplicated by `realpath` so a
41
+ * symlinked `~/.agents/skills/foo` pointing at `~/.claude/skills/foo`
42
+ * is reported once. Each entry carries `installedVia` so the caller
43
+ * can render "installed via Cursor" badges.
30
44
  *
31
- * @param dbPath Optional path to the Skillsmith SQLite database for update detection
45
+ * Precedence (first wins after dedup): local (repo) > claude-code >
46
+ * cursor > copilot > windsurf > agents. This keeps the SMI-1630
47
+ * promise that repo-local overrides global.
48
+ *
49
+ * @param dbPath Optional path to the Skillsmith SQLite database for
50
+ * update detection.
32
51
  */
33
52
  export declare function getInstalledSkills(dbPath?: string): Promise<InstalledSkill[]>;
34
53
  //# sourceMappingURL=skills-directory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skills-directory.d.ts","sourceRoot":"","sources":["../../../src/utils/skills-directory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAA;AAGzB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;CACpB;AAoBD;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,EAAE,CAAC,CAiG3B;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAsBnF"}
1
+ {"version":3,"file":"skills-directory.d.ts","sourceRoot":"","sources":["../../../src/utils/skills-directory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAA;AAGjC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAA;CACjC;AAiBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,GAAE,QAAQ,GAAG,OAA0B,GAClD,OAAO,CAAC,cAAc,EAAE,CAAC,CAkG3B;AAgBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAwCnF"}
@@ -2,21 +2,19 @@
2
2
  * SMI-2713: Extracted from manage.ts — helpers for reading installed skills
3
3
  * from the global and local ~/.claude/skills directories.
4
4
  */
5
- import { readdir, readFile, stat } from 'fs/promises';
5
+ import { readdir, readFile, realpath, stat } from 'fs/promises';
6
6
  import { createHash } from 'crypto';
7
7
  import { join } from 'path';
8
- import { homedir } from 'os';
9
- import { SkillParser, createDatabaseAsync, initializeSchema, SkillVersionRepository, } from '@skillsmith/core';
8
+ import { SkillParser, SkillVersionRepository, } from '@skillsmith/core';
9
+ import { openCliDatabase } from './open-database.js';
10
+ import { CANONICAL_CLIENT, CLIENT_IDS, CLIENT_NATIVE_PATHS, } from '@skillsmith/core/install';
10
11
  import { DEFAULT_DB_PATH } from '../config.js';
11
12
  /**
12
- * SMI-1630: Search both global and local skill directories
13
- *
14
- * Global: ~/.claude/skills/
15
- * Local: ${process.cwd()}/.claude/skills/
16
- *
17
- * Local skills take precedence over global skills with the same name.
13
+ * SMI-1630 + SMI-4578: discovery scans every client directory
14
+ * (`CLIENT_NATIVE_PATHS`) plus repo-local `./.claude/skills`. Local
15
+ * skills take precedence over global; canonical (`claude-code`) takes
16
+ * precedence over secondary clients. See `getInstalledSkills` below.
18
17
  */
19
- const GLOBAL_SKILLS_DIR = join(homedir(), '.claude', 'skills');
20
18
  /**
21
19
  * Returns the local skills directory path.
22
20
  * Computed at call time to handle working directory changes.
@@ -31,18 +29,20 @@ function getLocalSkillsDir() {
31
29
  * whether a newer content hash has been recorded since the skill was installed.
32
30
  * Falls back to hasUpdates: false when the database is unavailable.
33
31
  *
34
- * @param skillsDir Directory to scan for installed skills
35
- * @param dbPath Optional path to the Skillsmith SQLite database
32
+ * @param skillsDir Directory to scan for installed skills
33
+ * @param dbPath Optional path to the Skillsmith SQLite database
34
+ * @param installedVia SMI-4578: which client (or `'local'`) this directory
35
+ * represents — propagated onto each returned skill so
36
+ * callers can render "installed via Cursor" badges.
36
37
  */
37
- export async function getSkillsFromDirectory(skillsDir, dbPath) {
38
+ export async function getSkillsFromDirectory(skillsDir, dbPath, installedVia = CANONICAL_CLIENT) {
38
39
  const skills = [];
39
40
  // Open the version repository if a db path was provided
40
41
  let versionRepo = null;
41
42
  let dbConn = null;
42
43
  if (dbPath) {
43
44
  try {
44
- dbConn = await createDatabaseAsync(dbPath);
45
- initializeSchema(dbConn);
45
+ dbConn = await openCliDatabase(dbPath);
46
46
  versionRepo = new SkillVersionRepository(dbConn);
47
47
  }
48
48
  catch {
@@ -95,6 +95,7 @@ export async function getSkillsFromDirectory(skillsDir, dbPath) {
95
95
  trustTier: parsed ? parser.inferTrustTier(parsed) : 'unknown',
96
96
  installDate: skillMdStat.mtime.toISOString().split('T')[0] || 'Unknown',
97
97
  hasUpdates,
98
+ installedVia,
98
99
  });
99
100
  }
100
101
  catch (error) {
@@ -113,6 +114,7 @@ export async function getSkillsFromDirectory(skillsDir, dbPath) {
113
114
  trustTier: 'unknown',
114
115
  installDate: dirStat.mtime.toISOString().split('T')[0] || 'Unknown',
115
116
  hasUpdates: false,
117
+ installedVia,
116
118
  });
117
119
  }
118
120
  }
@@ -129,30 +131,73 @@ export async function getSkillsFromDirectory(skillsDir, dbPath) {
129
131
  return skills;
130
132
  }
131
133
  /**
132
- * Get list of installed skills from both global (~/.claude/skills) and
133
- * local (.claude/skills) directories.
134
+ * Resolve a path through `realpath` defensively. Returns the resolved
135
+ * path on success, or the input path unchanged if the path is missing
136
+ * or unreadable — dedup keying still works either way (we just won't
137
+ * collapse symlinked aliases when the link is broken).
138
+ */
139
+ async function safeRealpath(p) {
140
+ try {
141
+ return await realpath(p);
142
+ }
143
+ catch {
144
+ return p;
145
+ }
146
+ }
147
+ /**
148
+ * Get list of installed skills across every client directory.
134
149
  *
135
- * SMI-1630: Local skills take precedence over global skills with the same name.
150
+ * SMI-4578: scans the union of `CLIENT_NATIVE_PATHS` (claude-code,
151
+ * cursor, copilot, windsurf, agents) plus repo-local
152
+ * `./.claude/skills`. Results are deduplicated by `realpath` so a
153
+ * symlinked `~/.agents/skills/foo` pointing at `~/.claude/skills/foo`
154
+ * is reported once. Each entry carries `installedVia` so the caller
155
+ * can render "installed via Cursor" badges.
136
156
  *
137
- * @param dbPath Optional path to the Skillsmith SQLite database for update detection
157
+ * Precedence (first wins after dedup): local (repo) > claude-code >
158
+ * cursor > copilot > windsurf > agents. This keeps the SMI-1630
159
+ * promise that repo-local overrides global.
160
+ *
161
+ * @param dbPath Optional path to the Skillsmith SQLite database for
162
+ * update detection.
138
163
  */
139
164
  export async function getInstalledSkills(dbPath) {
140
165
  const resolvedDbPath = dbPath ?? DEFAULT_DB_PATH;
141
- // Get skills from both directories
142
- const [globalSkills, localSkills] = await Promise.all([
143
- getSkillsFromDirectory(GLOBAL_SKILLS_DIR, resolvedDbPath),
144
- getSkillsFromDirectory(getLocalSkillsDir(), resolvedDbPath),
145
- ]);
146
- // Create a map for deduplication, local skills take precedence
147
- const skillMap = new Map();
148
- // Add global skills first
149
- for (const skill of globalSkills) {
150
- skillMap.set(skill.name, skill);
166
+ const localScan = getSkillsFromDirectory(getLocalSkillsDir(), resolvedDbPath, 'local');
167
+ const clientScans = CLIENT_IDS.map((client) => getSkillsFromDirectory(CLIENT_NATIVE_PATHS[client], resolvedDbPath, client));
168
+ const [localSkills, ...clientSkillsLists] = await Promise.all([localScan, ...clientScans]);
169
+ // Precedence order: local first, then canonical, then the rest.
170
+ const ordered = [...localSkills];
171
+ const canonicalIdx = CLIENT_IDS.indexOf(CANONICAL_CLIENT);
172
+ if (canonicalIdx >= 0 && clientSkillsLists[canonicalIdx]) {
173
+ ordered.push(...clientSkillsLists[canonicalIdx]);
174
+ }
175
+ for (let i = 0; i < CLIENT_IDS.length; i++) {
176
+ if (i === canonicalIdx)
177
+ continue;
178
+ const list = clientSkillsLists[i];
179
+ if (list)
180
+ ordered.push(...list);
151
181
  }
152
- // Add local skills (overwrites global skills with same name)
153
- for (const skill of localSkills) {
154
- skillMap.set(skill.name, skill);
182
+ // Dedup by both skill name AND resolved path. Name-keying enforces the
183
+ // precedence rule (local > canonical > others) when two clients carry
184
+ // independently-installed copies of the same skill. Realpath-keying
185
+ // collapses symlinked aliases (e.g. `~/.agents/skills` → `~/.claude/skills`)
186
+ // so the symlinked entry doesn't appear twice when the second hop has a
187
+ // different `installedVia` label.
188
+ const seenNames = new Set();
189
+ const seenPaths = new Set();
190
+ const out = [];
191
+ for (const skill of ordered) {
192
+ if (seenNames.has(skill.name))
193
+ continue;
194
+ const realPath = await safeRealpath(skill.path);
195
+ if (seenPaths.has(realPath))
196
+ continue;
197
+ seenNames.add(skill.name);
198
+ seenPaths.add(realPath);
199
+ out.push(skill);
155
200
  }
156
- return Array.from(skillMap.values());
201
+ return out;
157
202
  }
158
203
  //# sourceMappingURL=skills-directory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"skills-directory.js","sourceRoot":"","sources":["../../../src/utils/skills-directory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skills-directory.js","sourceRoot":"","sources":["../../../src/utils/skills-directory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @fileoverview SMI-4590 Wave 4 PR 5/6 — `sklx audit collisions` tests
3
+ * @module @skillsmith/cli/tests/audit-collisions
4
+ *
5
+ * Coverage:
6
+ *
7
+ * Typed-confirmation gate (`requireConfirmationPhrase`) — load-bearing per
8
+ * plan §235-239. Strict literal equality, NO normalization.
9
+ * 1. Exact phrase ('APPLY ALL') — RESOLVES.
10
+ * 2. Single-letter ('Y') — REJECTS.
11
+ * 3. Lowercase word ('yes') — REJECTS.
12
+ * 4. Lowercase phrase ('apply all') — REJECTS.
13
+ * 5. No-space variant ('APPLYALL') — REJECTS.
14
+ * 6. Trailing whitespace ('APPLY ALL ') — REJECTS (no trim).
15
+ * 7. Empty string — REJECTS.
16
+ *
17
+ * Both interactive (TTY) and piped-stdin paths route through the same
18
+ * `@inquirer/prompts` `input()` call, so the rejection invariant holds for
19
+ * both. We mock `input` to assert the contract — the prompt library
20
+ * receives the answer verbatim and our code applies strict equality.
21
+ *
22
+ * Interactive prompt loop (`runInteractiveLoop`):
23
+ * 8. 'apply' choice → applyOneSuggestion called, status=applied.
24
+ * 9. 'skip' choice → outcome recorded as skipped, no apply call.
25
+ * 10. 'edit' choice → input prompts for custom name, applyRename
26
+ * receives `customName`.
27
+ * 11. 'quit' choice → loop terminates early; remaining suggestions
28
+ * are NOT processed.
29
+ * 12. Empty suggestion list → prints "No collisions found." and returns.
30
+ *
31
+ * Reset-ledger flow (`runResetLedger`):
32
+ * 13. Backs up an existing ledger to `~/.skillsmith/backups/ledger-*.json`
33
+ * BEFORE clearing.
34
+ * 14. No backup file when no prior ledger exists.
35
+ * 15. Confirmation phrase mismatch → throws, NO writeLedger call.
36
+ *
37
+ * `--json` output (`runAuditCollisions`):
38
+ * 16. JSON mode prints `RunInventoryAuditResult` to stdout, no prompts,
39
+ * no apply.
40
+ */
41
+ export {};
42
+ //# sourceMappingURL=audit-collisions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-collisions.test.d.ts","sourceRoot":"","sources":["../../tests/audit-collisions.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG"}