@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,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Helpers for `skillsmith import-local` (SMI-4665)
|
|
3
|
+
*
|
|
4
|
+
* Pulled out of `import-local.ts` to keep the action handler under the
|
|
5
|
+
* 500-line standard and isolate filesystem I/O for unit testing.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { promises as fs } from 'node:fs';
|
|
9
|
+
import { join, resolve, dirname, basename, sep, relative } from 'node:path';
|
|
10
|
+
import matter from 'gray-matter';
|
|
11
|
+
const SKILL_FILENAME = 'SKILL.md';
|
|
12
|
+
const MAX_DEPTH = 8;
|
|
13
|
+
/**
|
|
14
|
+
* Compute the deterministic local-skill id from a canonical absolute path.
|
|
15
|
+
* Re-running `import-local` on the same directory produces the same id, so
|
|
16
|
+
* the row upserts in place rather than duplicating.
|
|
17
|
+
*/
|
|
18
|
+
export function localSkillId(canonicalPath) {
|
|
19
|
+
return createHash('sha256').update(canonicalPath).digest('hex').slice(0, 32);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Walk `rootDir` and yield every `SKILL.md` file path. Symlinks are followed
|
|
23
|
+
* via `fs.realpath`, but any link whose realpath escapes `rootDir` is skipped
|
|
24
|
+
* (see SMI-4287 — LocalFilesystemAdapter convention).
|
|
25
|
+
*
|
|
26
|
+
* Returns an array of canonical absolute paths.
|
|
27
|
+
*/
|
|
28
|
+
export async function walkSkillFiles(rootDir) {
|
|
29
|
+
const canonicalRoot = await fs.realpath(rootDir).catch(() => resolve(rootDir));
|
|
30
|
+
const files = [];
|
|
31
|
+
const skipped = [];
|
|
32
|
+
const visited = new Set();
|
|
33
|
+
async function walk(dir, depth) {
|
|
34
|
+
if (depth > MAX_DEPTH)
|
|
35
|
+
return;
|
|
36
|
+
let entries;
|
|
37
|
+
try {
|
|
38
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const entryPath = join(dir, entry.name);
|
|
45
|
+
if (entry.isSymbolicLink()) {
|
|
46
|
+
let realPath;
|
|
47
|
+
try {
|
|
48
|
+
realPath = await fs.realpath(entryPath);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// Refuse symlinks whose target escapes the canonical root. Same
|
|
54
|
+
// policy as LocalFilesystemAdapter (SMI-4287). Authors who need to
|
|
55
|
+
// import skills outside `~/.claude/skills/` can pass an explicit
|
|
56
|
+
// path or `--client agents` instead.
|
|
57
|
+
const rel = relative(canonicalRoot, realPath);
|
|
58
|
+
if (rel.startsWith('..') || rel === '..' || rel.startsWith(`..${sep}`)) {
|
|
59
|
+
skipped.push({ path: entryPath, reason: 'symlink-escapes-root' });
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (visited.has(realPath))
|
|
63
|
+
continue;
|
|
64
|
+
visited.add(realPath);
|
|
65
|
+
const stat = await fs.stat(realPath).catch(() => null);
|
|
66
|
+
if (stat?.isDirectory()) {
|
|
67
|
+
await walk(realPath, depth + 1);
|
|
68
|
+
}
|
|
69
|
+
else if (stat?.isFile() && basename(realPath) === SKILL_FILENAME) {
|
|
70
|
+
files.push(realPath);
|
|
71
|
+
}
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (entry.isDirectory()) {
|
|
75
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.'))
|
|
76
|
+
continue;
|
|
77
|
+
await walk(entryPath, depth + 1);
|
|
78
|
+
}
|
|
79
|
+
else if (entry.isFile() && entry.name === SKILL_FILENAME) {
|
|
80
|
+
try {
|
|
81
|
+
const real = await fs.realpath(entryPath);
|
|
82
|
+
files.push(real);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
files.push(entryPath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
await walk(canonicalRoot, 0);
|
|
91
|
+
return { files, skipped };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Parse the YAML frontmatter of a SKILL.md file. Returns a partial record;
|
|
95
|
+
* malformed frontmatter is reported via the `error` field rather than thrown
|
|
96
|
+
* so a single broken file does not abort the whole import.
|
|
97
|
+
*/
|
|
98
|
+
export async function parseSkillFile(filePath) {
|
|
99
|
+
const id = localSkillId(filePath);
|
|
100
|
+
const fallbackName = basename(dirname(filePath));
|
|
101
|
+
let content;
|
|
102
|
+
try {
|
|
103
|
+
content = await fs.readFile(filePath, 'utf8');
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
return {
|
|
107
|
+
id,
|
|
108
|
+
path: filePath,
|
|
109
|
+
name: fallbackName,
|
|
110
|
+
description: null,
|
|
111
|
+
triggers: [],
|
|
112
|
+
tags: [],
|
|
113
|
+
error: `read-failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
let parsed;
|
|
117
|
+
try {
|
|
118
|
+
parsed = matter(content);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
return {
|
|
122
|
+
id,
|
|
123
|
+
path: filePath,
|
|
124
|
+
name: fallbackName,
|
|
125
|
+
description: null,
|
|
126
|
+
triggers: [],
|
|
127
|
+
tags: [],
|
|
128
|
+
error: `frontmatter-parse-failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const data = (parsed.data ?? {});
|
|
132
|
+
const name = typeof data['name'] === 'string' && data['name'].length > 0
|
|
133
|
+
? data['name']
|
|
134
|
+
: fallbackName;
|
|
135
|
+
let description = null;
|
|
136
|
+
if (typeof data['description'] === 'string') {
|
|
137
|
+
description = data['description'];
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// Fall back to the first non-blank, non-heading paragraph in the body.
|
|
141
|
+
for (const line of parsed.content.split('\n')) {
|
|
142
|
+
const trimmed = line.trim();
|
|
143
|
+
if (!trimmed)
|
|
144
|
+
continue;
|
|
145
|
+
if (trimmed.startsWith('#'))
|
|
146
|
+
continue;
|
|
147
|
+
description = trimmed;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const triggers = toStringArray(data['triggers']);
|
|
152
|
+
const tags = toStringArray(data['tags']);
|
|
153
|
+
return { id, path: filePath, name, description, triggers, tags };
|
|
154
|
+
}
|
|
155
|
+
function toStringArray(value) {
|
|
156
|
+
if (Array.isArray(value))
|
|
157
|
+
return value.filter((v) => typeof v === 'string');
|
|
158
|
+
if (typeof value === 'string') {
|
|
159
|
+
return value
|
|
160
|
+
.split(',')
|
|
161
|
+
.map((s) => s.trim())
|
|
162
|
+
.filter(Boolean);
|
|
163
|
+
}
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=import-local.helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-local.helpers.js","sourceRoot":"","sources":["../../../src/commands/import-local.helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `skillsmith import-local` — walk a directory tree of `SKILL.md`
|
|
3
|
+
* files and upsert them into the local skills DB with `source='local'` so
|
|
4
|
+
* subsequent registry sync (with or without `--force`) leaves them alone.
|
|
5
|
+
*
|
|
6
|
+
* @see SMI-4665
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import { SkillRepository } from '@skillsmith/core';
|
|
10
|
+
import { openCliDatabase } from '../utils/open-database.js';
|
|
11
|
+
import { getCanonicalInstallPath, getInstallPath, resolveClientId, } from '@skillsmith/core/install';
|
|
12
|
+
import { resolve } from 'node:path';
|
|
13
|
+
import { promises as fs } from 'node:fs';
|
|
14
|
+
import { DEFAULT_DB_PATH } from '../config.js';
|
|
15
|
+
import { sanitizeError } from '../utils/sanitize.js';
|
|
16
|
+
import { walkSkillFiles, parseSkillFile, localSkillId } from './import-local.helpers.js';
|
|
17
|
+
const WATCH_DEBOUNCE_MS = 500;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve the directory the importer should walk. Precedence:
|
|
20
|
+
* 1. Positional `[path]`
|
|
21
|
+
* 2. `--client <id>` → multi-client install path
|
|
22
|
+
* 3. Canonical `~/.claude/skills/`
|
|
23
|
+
*/
|
|
24
|
+
function resolveRoot(opts) {
|
|
25
|
+
if (opts.path)
|
|
26
|
+
return resolve(opts.path);
|
|
27
|
+
if (opts.client)
|
|
28
|
+
return getInstallPath(opts.client);
|
|
29
|
+
return getCanonicalInstallPath();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Run a single pass of the importer. Returns the summary; never throws on
|
|
33
|
+
* per-file errors (those land in `result.errors`).
|
|
34
|
+
*/
|
|
35
|
+
export async function runImportLocal(opts) {
|
|
36
|
+
const start = Date.now();
|
|
37
|
+
const rootDir = resolveRoot(opts);
|
|
38
|
+
const dbPath = opts.dbPath ?? DEFAULT_DB_PATH;
|
|
39
|
+
const result = {
|
|
40
|
+
rootDir,
|
|
41
|
+
scanned: 0,
|
|
42
|
+
imported: 0,
|
|
43
|
+
updated: 0,
|
|
44
|
+
unchanged: 0,
|
|
45
|
+
errors: [],
|
|
46
|
+
skipped: [],
|
|
47
|
+
durationMs: 0,
|
|
48
|
+
dryRun: !!opts.dryRun,
|
|
49
|
+
};
|
|
50
|
+
// Preflight: rootDir must exist. Surface as a single error rather than
|
|
51
|
+
// letting the walker silently return zero files.
|
|
52
|
+
try {
|
|
53
|
+
const stat = await fs.stat(rootDir);
|
|
54
|
+
if (!stat.isDirectory()) {
|
|
55
|
+
result.errors.push({ path: rootDir, message: 'not-a-directory' });
|
|
56
|
+
result.durationMs = Date.now() - start;
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
result.errors.push({
|
|
62
|
+
path: rootDir,
|
|
63
|
+
message: `stat-failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
64
|
+
});
|
|
65
|
+
result.durationMs = Date.now() - start;
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
const { files, skipped } = await walkSkillFiles(rootDir);
|
|
69
|
+
result.scanned = files.length;
|
|
70
|
+
result.skipped = skipped;
|
|
71
|
+
const records = [];
|
|
72
|
+
for (const file of files) {
|
|
73
|
+
const record = await parseSkillFile(file);
|
|
74
|
+
if (record.error) {
|
|
75
|
+
result.errors.push({ path: record.path, message: record.error });
|
|
76
|
+
}
|
|
77
|
+
records.push(record);
|
|
78
|
+
}
|
|
79
|
+
if (opts.dryRun) {
|
|
80
|
+
// Tally without writing.
|
|
81
|
+
const db = await openCliDatabase(dbPath);
|
|
82
|
+
try {
|
|
83
|
+
const repo = new SkillRepository(db);
|
|
84
|
+
for (const record of records) {
|
|
85
|
+
if (record.error)
|
|
86
|
+
continue;
|
|
87
|
+
const existing = repo.findById(record.id);
|
|
88
|
+
if (existing) {
|
|
89
|
+
// A re-import of the same path always updates (id is path-derived).
|
|
90
|
+
// Counted separately from `imported` so the summary distinguishes
|
|
91
|
+
// first-time imports from idempotent re-runs.
|
|
92
|
+
result.updated++;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
result.imported++;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
db.close();
|
|
101
|
+
}
|
|
102
|
+
result.durationMs = Date.now() - start;
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
// Real import.
|
|
106
|
+
const db = await openCliDatabase(dbPath);
|
|
107
|
+
try {
|
|
108
|
+
const repo = new SkillRepository(db);
|
|
109
|
+
for (const record of records) {
|
|
110
|
+
if (record.error)
|
|
111
|
+
continue;
|
|
112
|
+
const input = {
|
|
113
|
+
id: record.id,
|
|
114
|
+
name: record.name,
|
|
115
|
+
description: record.description,
|
|
116
|
+
author: null,
|
|
117
|
+
repoUrl: null,
|
|
118
|
+
qualityScore: null,
|
|
119
|
+
trustTier: 'local',
|
|
120
|
+
source: 'local',
|
|
121
|
+
tags: record.tags,
|
|
122
|
+
};
|
|
123
|
+
const existing = repo.findById(record.id);
|
|
124
|
+
if (existing) {
|
|
125
|
+
repo.update(record.id, input);
|
|
126
|
+
result.updated++;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
repo.create(input);
|
|
130
|
+
result.imported++;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
result.unchanged = result.scanned - result.imported - result.updated - result.errors.length;
|
|
134
|
+
if (result.unchanged < 0)
|
|
135
|
+
result.unchanged = 0;
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
db.close();
|
|
139
|
+
}
|
|
140
|
+
result.durationMs = Date.now() - start;
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Watch mode: chokidar-based debounced re-import. Lazy-loaded so the
|
|
145
|
+
* dependency cost is paid only when `--watch` is used.
|
|
146
|
+
*/
|
|
147
|
+
async function startWatchMode(opts, jsonOutput) {
|
|
148
|
+
// chokidar 4.x exposes `watch` as a named export. Lazy-loaded so the
|
|
149
|
+
// dependency cost is paid only when `--watch` is used.
|
|
150
|
+
const chokidar = await import('chokidar');
|
|
151
|
+
const rootDir = resolveRoot(opts);
|
|
152
|
+
let pending = null;
|
|
153
|
+
let inFlight = false;
|
|
154
|
+
const trigger = async () => {
|
|
155
|
+
if (inFlight)
|
|
156
|
+
return;
|
|
157
|
+
inFlight = true;
|
|
158
|
+
try {
|
|
159
|
+
const result = await runImportLocal(opts);
|
|
160
|
+
if (jsonOutput) {
|
|
161
|
+
console.log(JSON.stringify(result));
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
console.log(`[import-local] ${result.scanned} scanned, ${result.imported} added, ${result.updated} updated, ${result.errors.length} errors`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
console.error('[import-local] watch pass failed:', sanitizeError(error));
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
inFlight = false;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
await trigger();
|
|
175
|
+
const watcher = chokidar.watch(`${rootDir}/**/SKILL.md`, {
|
|
176
|
+
ignoreInitial: true,
|
|
177
|
+
persistent: true,
|
|
178
|
+
});
|
|
179
|
+
const onEvent = (_event, _path) => {
|
|
180
|
+
if (pending)
|
|
181
|
+
clearTimeout(pending);
|
|
182
|
+
pending = setTimeout(() => {
|
|
183
|
+
pending = null;
|
|
184
|
+
void trigger();
|
|
185
|
+
}, WATCH_DEBOUNCE_MS);
|
|
186
|
+
};
|
|
187
|
+
watcher.on('add', (p) => onEvent('add', p));
|
|
188
|
+
watcher.on('change', (p) => onEvent('change', p));
|
|
189
|
+
watcher.on('unlink', (p) => onEvent('unlink', p));
|
|
190
|
+
console.log(`[import-local] watching ${rootDir} (Ctrl-C to stop)`);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Build the Commander subcommand. Wired into `index.ts` via `addCommand`.
|
|
194
|
+
*/
|
|
195
|
+
export function createImportLocalCommand() {
|
|
196
|
+
return new Command('import-local')
|
|
197
|
+
.description('Walk a directory of SKILL.md files and import them into the local skills DB. ' +
|
|
198
|
+
"Imported rows are tagged source='local' so registry sync (including --force) " +
|
|
199
|
+
'leaves them alone.')
|
|
200
|
+
.argument('[path]', 'Directory to walk (default: ~/.claude/skills/)')
|
|
201
|
+
.option('--client <id>', 'Walk a different client install path (claude-code, cursor, copilot, windsurf, agents)')
|
|
202
|
+
.option('--watch', 'Watch the directory and re-import on change (debounced 500ms)')
|
|
203
|
+
.option('--dry-run', 'List what would be imported without writing to the DB')
|
|
204
|
+
.option('--json', 'Emit a single machine-readable summary object on stdout')
|
|
205
|
+
.option('-d, --db <path>', 'Database file path', DEFAULT_DB_PATH)
|
|
206
|
+
.action(async (path, cliOptions) => {
|
|
207
|
+
try {
|
|
208
|
+
let resolvedClient;
|
|
209
|
+
if (cliOptions.client !== undefined) {
|
|
210
|
+
resolvedClient = resolveClientId(cliOptions.client);
|
|
211
|
+
}
|
|
212
|
+
const opts = {
|
|
213
|
+
...(path !== undefined && { path }),
|
|
214
|
+
...(resolvedClient !== undefined && { client: resolvedClient }),
|
|
215
|
+
...(cliOptions.watch !== undefined && { watch: cliOptions.watch }),
|
|
216
|
+
...(cliOptions.dryRun !== undefined && { dryRun: cliOptions.dryRun }),
|
|
217
|
+
...(cliOptions.json !== undefined && { json: cliOptions.json }),
|
|
218
|
+
...(cliOptions.db !== undefined && { dbPath: cliOptions.db }),
|
|
219
|
+
};
|
|
220
|
+
if (opts.watch) {
|
|
221
|
+
await startWatchMode(opts, !!opts.json);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const result = await runImportLocal(opts);
|
|
225
|
+
if (opts.json) {
|
|
226
|
+
console.log(JSON.stringify(result));
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
printHumanSummary(result);
|
|
230
|
+
}
|
|
231
|
+
if (result.errors.length > 0 && opts.json) {
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
console.error('import-local failed:', sanitizeError(error));
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
function printHumanSummary(result) {
|
|
242
|
+
console.log(`\n--- import-local ${result.dryRun ? '(dry run)' : ''} ---`);
|
|
243
|
+
console.log(`Root: ${result.rootDir}`);
|
|
244
|
+
console.log(`Scanned: ${result.scanned}`);
|
|
245
|
+
console.log(`Imported: ${result.imported}`);
|
|
246
|
+
console.log(`Updated: ${result.updated}`);
|
|
247
|
+
console.log(`Unchanged:${result.unchanged}`);
|
|
248
|
+
if (result.skipped.length > 0) {
|
|
249
|
+
console.log(`Skipped: ${result.skipped.length}`);
|
|
250
|
+
for (const s of result.skipped) {
|
|
251
|
+
console.log(` - ${s.path} (${s.reason})`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (result.errors.length > 0) {
|
|
255
|
+
console.log(`Errors: ${result.errors.length}`);
|
|
256
|
+
for (const e of result.errors) {
|
|
257
|
+
console.log(` - ${e.path}: ${e.message}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
console.log(`Duration: ${(result.durationMs / 1000).toFixed(2)}s`);
|
|
261
|
+
}
|
|
262
|
+
// Re-export helpers for unit tests.
|
|
263
|
+
export { walkSkillFiles, parseSkillFile, localSkillId };
|
|
264
|
+
//# sourceMappingURL=import-local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-local.js","sourceRoot":"","sources":["../../../src/commands/import-local.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Types for `skillsmith import-local` (SMI-4665)
|
|
3
|
+
*/
|
|
4
|
+
import type { ClientId } from '@skillsmith/core/install';
|
|
5
|
+
export interface ImportLocalOptions {
|
|
6
|
+
/** Optional positional path. Defaults to the canonical install path. */
|
|
7
|
+
path?: string;
|
|
8
|
+
/** Walk a different client's install directory (`cursor`, `copilot`, etc). */
|
|
9
|
+
client?: ClientId;
|
|
10
|
+
/** Watch the target directory for changes and re-import on change. */
|
|
11
|
+
watch?: boolean;
|
|
12
|
+
/** Print what would be imported without writing to the DB. */
|
|
13
|
+
dryRun?: boolean;
|
|
14
|
+
/** Emit a single machine-readable summary object on stdout. */
|
|
15
|
+
json?: boolean;
|
|
16
|
+
/** Database file path override (test injection). */
|
|
17
|
+
dbPath?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Per-skill record extracted from a `SKILL.md` on disk.
|
|
21
|
+
*/
|
|
22
|
+
export interface LocalSkillRecord {
|
|
23
|
+
/** Deterministic id: sha256(canonicalPath).slice(0, 32). */
|
|
24
|
+
id: string;
|
|
25
|
+
/** Canonical absolute path to the SKILL.md. */
|
|
26
|
+
path: string;
|
|
27
|
+
/** Name from frontmatter (or fallback to parent dir basename). */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Description from frontmatter (or first non-heading paragraph). */
|
|
30
|
+
description: string | null;
|
|
31
|
+
/** Trigger phrases from frontmatter (`triggers:` array). */
|
|
32
|
+
triggers: string[];
|
|
33
|
+
/** Tags from frontmatter (`tags:` array). */
|
|
34
|
+
tags: string[];
|
|
35
|
+
/** Set when frontmatter parsing failed. The walker still yields the record
|
|
36
|
+
* so the action handler can surface the error in the summary. */
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* End-of-run summary. Stable shape — `--json` emits exactly this.
|
|
41
|
+
*/
|
|
42
|
+
export interface ImportLocalResult {
|
|
43
|
+
rootDir: string;
|
|
44
|
+
scanned: number;
|
|
45
|
+
imported: number;
|
|
46
|
+
updated: number;
|
|
47
|
+
unchanged: number;
|
|
48
|
+
errors: Array<{
|
|
49
|
+
path: string;
|
|
50
|
+
message: string;
|
|
51
|
+
}>;
|
|
52
|
+
skipped: Array<{
|
|
53
|
+
path: string;
|
|
54
|
+
reason: string;
|
|
55
|
+
}>;
|
|
56
|
+
durationMs: number;
|
|
57
|
+
dryRun: boolean;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=import-local.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-local.types.d.ts","sourceRoot":"","sources":["../../../src/commands/import-local.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAExD,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAA;IACV,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,EAAE,CAAA;IACd;sEACkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChD,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChD,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,OAAO,CAAA;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-local.types.js","sourceRoot":"","sources":["../../../src/commands/import-local.types.ts"],"names":[],"mappings":""}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* SMI-580: GitHub Skill Import Script
|
|
4
|
+
* SMI-4665: Moved into `commands/` and wrapped in a `createImportCommand`
|
|
5
|
+
* factory so the verb is registered via `program.addCommand(...)` like every
|
|
6
|
+
* other CLI command. The new sibling `skillsmith import-local` walks the
|
|
7
|
+
* local filesystem instead of GitHub topics.
|
|
4
8
|
*
|
|
5
9
|
* Discovers and imports Claude skills from GitHub:
|
|
6
10
|
* - Searches for repos with topic:claude-skill
|
|
@@ -8,6 +12,7 @@
|
|
|
8
12
|
* - Handles rate limiting with exponential backoff
|
|
9
13
|
* - Supports batch import of 1000+ skills
|
|
10
14
|
*/
|
|
15
|
+
import { Command } from 'commander';
|
|
11
16
|
interface ImportOptions {
|
|
12
17
|
token?: string;
|
|
13
18
|
topic?: string;
|
|
@@ -26,5 +31,11 @@ interface ImportResult {
|
|
|
26
31
|
* Import skills from GitHub into the database
|
|
27
32
|
*/
|
|
28
33
|
export declare function importSkills(options?: ImportOptions): Promise<ImportResult>;
|
|
34
|
+
/**
|
|
35
|
+
* SMI-4665: Build the `skillsmith import` Commander subcommand. Pulled out of
|
|
36
|
+
* `index.ts` (where it was inline) so registration uses the same `addCommand`
|
|
37
|
+
* pattern as every other verb.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createImportCommand(): Command;
|
|
29
40
|
export {};
|
|
30
41
|
//# sourceMappingURL=import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../src/commands/import.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA2BnC,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAEhB,kBAAkB,EAAE,MAAM,CAAA;CAC3B;AAoMD;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiGrF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAoB7C"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* SMI-580: GitHub Skill Import Script
|
|
4
|
+
* SMI-4665: Moved into `commands/` and wrapped in a `createImportCommand`
|
|
5
|
+
* factory so the verb is registered via `program.addCommand(...)` like every
|
|
6
|
+
* other CLI command. The new sibling `skillsmith import-local` walks the
|
|
7
|
+
* local filesystem instead of GitHub topics.
|
|
4
8
|
*
|
|
5
9
|
* Discovers and imports Claude skills from GitHub:
|
|
6
10
|
* - Searches for repos with topic:claude-skill
|
|
@@ -8,8 +12,11 @@
|
|
|
8
12
|
* - Handles rate limiting with exponential backoff
|
|
9
13
|
* - Supports batch import of 1000+ skills
|
|
10
14
|
*/
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
import { SkillRepository } from '@skillsmith/core';
|
|
17
|
+
import { openCliDatabase } from '../utils/open-database.js';
|
|
18
|
+
import { DEFAULT_DB_PATH } from '../config.js';
|
|
19
|
+
import { sanitizeError } from '../utils/sanitize.js';
|
|
13
20
|
const DEFAULT_TOPIC = 'claude-skill';
|
|
14
21
|
const GITHUB_API = 'https://api.github.com';
|
|
15
22
|
const MAX_PER_PAGE = 100;
|
|
@@ -183,7 +190,7 @@ export async function importSkills(options = {}) {
|
|
|
183
190
|
skillMdFetchFailed: 0,
|
|
184
191
|
};
|
|
185
192
|
// Initialize database
|
|
186
|
-
const db = await
|
|
193
|
+
const db = await openCliDatabase(dbPath);
|
|
187
194
|
const skillRepo = new SkillRepository(db);
|
|
188
195
|
console.log(`Searching for repositories with topic: ${topic}...`);
|
|
189
196
|
try {
|
|
@@ -252,7 +259,35 @@ export async function importSkills(options = {}) {
|
|
|
252
259
|
console.log(`Duration: ${(result.duration / 1000).toFixed(1)}s`);
|
|
253
260
|
return result;
|
|
254
261
|
}
|
|
255
|
-
|
|
262
|
+
/**
|
|
263
|
+
* SMI-4665: Build the `skillsmith import` Commander subcommand. Pulled out of
|
|
264
|
+
* `index.ts` (where it was inline) so registration uses the same `addCommand`
|
|
265
|
+
* pattern as every other verb.
|
|
266
|
+
*/
|
|
267
|
+
export function createImportCommand() {
|
|
268
|
+
return new Command('import')
|
|
269
|
+
.description('Import skills from GitHub')
|
|
270
|
+
.option('-t, --topic <topic>', 'GitHub topic to search', 'claude-skill')
|
|
271
|
+
.option('-m, --max <number>', 'Maximum skills to import', '1000')
|
|
272
|
+
.option('-d, --db <path>', 'Database file path', DEFAULT_DB_PATH)
|
|
273
|
+
.option('-v, --verbose', 'Verbose output')
|
|
274
|
+
.action(async (options) => {
|
|
275
|
+
try {
|
|
276
|
+
await importSkills({
|
|
277
|
+
topic: options.topic,
|
|
278
|
+
maxSkills: parseInt(options.max),
|
|
279
|
+
dbPath: options.db,
|
|
280
|
+
...(options.verbose !== undefined && { verbose: options.verbose }),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
console.error('Import failed:', sanitizeError(error));
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
// CLI entry point — preserved so `node packages/cli/dist/src/commands/import.js`
|
|
290
|
+
// still works for ad-hoc batch runs invoked outside the main `skillsmith` shell.
|
|
256
291
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
257
292
|
const args = process.argv.slice(2);
|
|
258
293
|
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../../src/commands/import.ts"],"names":[],"mappings":"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"}
|