@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.
- package/CHANGELOG.md +16 -0
- package/README.md +92 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/commands/audit-collisions.d.ts +71 -0
- package/dist/src/commands/audit-collisions.d.ts.map +1 -0
- package/dist/src/commands/audit-collisions.js +300 -0
- package/dist/src/commands/audit-collisions.js.map +1 -0
- package/dist/src/commands/audit.d.ts +27 -2
- package/dist/src/commands/audit.d.ts.map +1 -1
- package/dist/src/commands/audit.js +73 -13
- package/dist/src/commands/audit.js.map +1 -1
- package/dist/src/commands/audit.test.js +2 -2
- package/dist/src/commands/audit.test.js.map +1 -1
- package/dist/src/commands/config.d.ts +55 -0
- package/dist/src/commands/config.d.ts.map +1 -0
- package/dist/src/commands/config.js +211 -0
- package/dist/src/commands/config.js.map +1 -0
- package/dist/src/commands/create.d.ts +3 -3
- package/dist/src/commands/create.d.ts.map +1 -1
- package/dist/src/commands/create.js +11 -9
- package/dist/src/commands/create.js.map +1 -1
- package/dist/src/commands/diff.js +2 -2
- package/dist/src/commands/diff.js.map +1 -1
- package/dist/src/commands/import-local.d.ts +21 -0
- package/dist/src/commands/import-local.d.ts.map +1 -0
- package/dist/src/commands/import-local.helpers.d.ts +28 -0
- package/dist/src/commands/import-local.helpers.d.ts.map +1 -0
- package/dist/src/commands/import-local.helpers.js +166 -0
- package/dist/src/commands/import-local.helpers.js.map +1 -0
- package/dist/src/commands/import-local.js +264 -0
- package/dist/src/commands/import-local.js.map +1 -0
- package/dist/src/commands/import-local.types.d.ts +59 -0
- package/dist/src/commands/import-local.types.d.ts.map +1 -0
- package/dist/src/commands/import-local.types.js +2 -0
- package/dist/src/commands/import-local.types.js.map +1 -0
- package/dist/src/{import.d.ts → commands/import.d.ts} +11 -0
- package/dist/src/commands/import.d.ts.map +1 -0
- package/dist/src/{import.js → commands/import.js} +39 -4
- package/dist/src/commands/import.js.map +1 -0
- package/dist/src/commands/index.d.ts +3 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +6 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/info.d.ts.map +1 -1
- package/dist/src/commands/info.js +3 -3
- package/dist/src/commands/info.js.map +1 -1
- package/dist/src/commands/install-skill.d.ts.map +1 -1
- package/dist/src/commands/install-skill.js +6 -3
- package/dist/src/commands/install-skill.js.map +1 -1
- package/dist/src/commands/install.d.ts.map +1 -1
- package/dist/src/commands/install.js +81 -7
- package/dist/src/commands/install.js.map +1 -1
- package/dist/src/commands/login.d.ts.map +1 -1
- package/dist/src/commands/login.js +37 -0
- package/dist/src/commands/login.js.map +1 -1
- package/dist/src/commands/login.post-login-sync.test.d.ts +2 -0
- package/dist/src/commands/login.post-login-sync.test.d.ts.map +1 -0
- package/dist/src/commands/login.post-login-sync.test.js +120 -0
- package/dist/src/commands/login.post-login-sync.test.js.map +1 -0
- package/dist/src/commands/login.test-helpers.d.ts +7 -0
- package/dist/src/commands/login.test-helpers.d.ts.map +1 -0
- package/dist/src/commands/login.test-helpers.js +44 -0
- package/dist/src/commands/login.test-helpers.js.map +1 -0
- package/dist/src/commands/login.test.js +30 -31
- package/dist/src/commands/login.test.js.map +1 -1
- package/dist/src/commands/manage.d.ts.map +1 -1
- package/dist/src/commands/manage.js +17 -4
- package/dist/src/commands/manage.js.map +1 -1
- package/dist/src/commands/recommend.helpers.d.ts +5 -1
- package/dist/src/commands/recommend.helpers.d.ts.map +1 -1
- package/dist/src/commands/recommend.helpers.js +9 -3
- package/dist/src/commands/recommend.helpers.js.map +1 -1
- package/dist/src/commands/run-registry-sync.d.ts +31 -0
- package/dist/src/commands/run-registry-sync.d.ts.map +1 -0
- package/dist/src/commands/run-registry-sync.js +45 -0
- package/dist/src/commands/run-registry-sync.js.map +1 -0
- package/dist/src/commands/search.d.ts.map +1 -1
- package/dist/src/commands/search.helpers.d.ts +23 -0
- package/dist/src/commands/search.helpers.d.ts.map +1 -0
- package/dist/src/commands/search.helpers.js +57 -0
- package/dist/src/commands/search.helpers.js.map +1 -0
- package/dist/src/commands/search.js +12 -5
- package/dist/src/commands/search.js.map +1 -1
- package/dist/src/commands/sync.d.ts.map +1 -1
- package/dist/src/commands/sync.js +10 -21
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/config.d.ts +6 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +8 -2
- package/dist/src/config.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +10 -28
- package/dist/src/index.js.map +1 -1
- package/dist/src/templates/mcp-server.template.d.ts +1 -1
- package/dist/src/templates/mcp-server.template.d.ts.map +1 -1
- package/dist/src/templates/mcp-server.template.js +13 -13
- package/dist/src/templates/mcp-server.template.js.map +1 -1
- package/dist/src/templates/mcp-server.template.snippets.d.ts +51 -0
- package/dist/src/templates/mcp-server.template.snippets.d.ts.map +1 -0
- package/dist/src/templates/mcp-server.template.snippets.js +162 -0
- package/dist/src/templates/mcp-server.template.snippets.js.map +1 -0
- package/dist/src/templates/readme.md.template.d.ts +1 -1
- package/dist/src/templates/readme.md.template.d.ts.map +1 -1
- package/dist/src/templates/readme.md.template.js +2 -2
- package/dist/src/utils/open-database.d.ts +27 -0
- package/dist/src/utils/open-database.d.ts.map +1 -0
- package/dist/src/utils/open-database.js +31 -0
- package/dist/src/utils/open-database.js.map +1 -0
- package/dist/src/utils/skills-directory.d.ts +26 -7
- package/dist/src/utils/skills-directory.d.ts.map +1 -1
- package/dist/src/utils/skills-directory.js +78 -33
- package/dist/src/utils/skills-directory.js.map +1 -1
- package/dist/tests/audit-collisions.test.d.ts +42 -0
- package/dist/tests/audit-collisions.test.d.ts.map +1 -0
- package/dist/tests/audit-collisions.test.js +370 -0
- package/dist/tests/audit-collisions.test.js.map +1 -0
- package/dist/tests/audit-restructure.test.d.ts +15 -0
- package/dist/tests/audit-restructure.test.d.ts.map +1 -0
- package/dist/tests/audit-restructure.test.js +151 -0
- package/dist/tests/audit-restructure.test.js.map +1 -0
- package/dist/tests/config.test.d.ts +33 -0
- package/dist/tests/config.test.d.ts.map +1 -0
- package/dist/tests/config.test.js +240 -0
- package/dist/tests/config.test.js.map +1 -0
- package/dist/tests/install-multi-client.test.d.ts +2 -0
- package/dist/tests/install-multi-client.test.d.ts.map +1 -0
- package/dist/tests/install-multi-client.test.js +202 -0
- package/dist/tests/install-multi-client.test.js.map +1 -0
- package/dist/tests/integration/import-local.test.d.ts +2 -0
- package/dist/tests/integration/import-local.test.d.ts.map +1 -0
- package/dist/tests/integration/import-local.test.js +158 -0
- package/dist/tests/integration/import-local.test.js.map +1 -0
- package/dist/tests/mcp-server-template.test.js +21 -0
- package/dist/tests/mcp-server-template.test.js.map +1 -1
- package/dist/tests/open-database.test.d.ts +2 -0
- package/dist/tests/open-database.test.d.ts.map +1 -0
- package/dist/tests/open-database.test.js +52 -0
- package/dist/tests/open-database.test.js.map +1 -0
- package/dist/tests/search-helpers.test.d.ts +2 -0
- package/dist/tests/search-helpers.test.d.ts.map +1 -0
- package/dist/tests/search-helpers.test.js +110 -0
- package/dist/tests/search-helpers.test.js.map +1 -0
- package/dist/tests/skills-directory.test.d.ts +2 -0
- package/dist/tests/skills-directory.test.d.ts.map +1 -0
- package/dist/tests/skills-directory.test.js +97 -0
- package/dist/tests/skills-directory.test.js.map +1 -0
- package/dist/tests/unit/commands/install.test.js +75 -1
- package/dist/tests/unit/commands/install.test.js.map +1 -1
- package/dist/tests/unit/import-local.helpers.test.d.ts +2 -0
- package/dist/tests/unit/import-local.helpers.test.d.ts.map +1 -0
- package/dist/tests/unit/import-local.helpers.test.js +96 -0
- package/dist/tests/unit/import-local.helpers.test.js.map +1 -0
- package/package.json +10 -4
- package/dist/src/import.d.ts.map +0 -1
- 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
|
|
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,
|
|
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
|
|
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
|
|
22
|
-
* @param dbPath
|
|
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
|
|
27
|
-
* local (.claude/skills) directories.
|
|
36
|
+
* Get list of installed skills across every client directory.
|
|
28
37
|
*
|
|
29
|
-
* SMI-
|
|
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
|
-
*
|
|
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;
|
|
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 {
|
|
9
|
-
import {
|
|
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
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
|
35
|
-
* @param dbPath
|
|
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
|
|
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
|
-
*
|
|
133
|
-
*
|
|
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-
|
|
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
|
-
*
|
|
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
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
]
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
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
|
|
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":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;
|
|
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"}
|