skilldrop-cli 1.12.0 → 1.13.0
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/bin/skilldrop.js +46 -3
- package/package.json +1 -1
- package/packs/ai-engineering/skills/agent-config-review/evals/files/1/dot.gitignore +5 -0
- package/packs/ai-engineering/skills/agent-config-review/examples/inputs/tidewater-ingest/dot.gitignore +3 -0
- package/packs/ai-engineering/skills/agent-config-review/examples/python-repo-tighten.md +3 -3
- package/packs/dev-team/skills/dependency-upgrade-review/evals/files/7/dot.npmrc +3 -0
- package/packs/experience-design/skills/locale-check/SKILL.md +1 -1
- package/packs/experience-design/skills/locale-check/manifest.json +2 -2
- package/packs/frontend/skills/bundle-size-review/evals/files/9/dot.gitignore +5 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/1/{.claude → dot.claude}/agents/db-migrator.md +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/1/{.claude → dot.claude}/agents/reviewer.md +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/1/{.claude → dot.claude}/settings.json +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/1/{.claude → dot.claude}/settings.local.json +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/1/{.mcp.json → dot.mcp.json} +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/2/{.cursor → dot.cursor}/mcp.json +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/4/quillstack/{.claude → dot.claude}/agents/release-notes.md +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/4/quillstack/{.claude → dot.claude}/settings.json +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/4/quillstack/{.mcp.json → dot.mcp.json} +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/evals/files/5/{.github → dot.github}/workflows/codex-triage.yml.fixture +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/examples/inputs/tidewater-ingest/{.claude → dot.claude}/settings.json +0 -0
- /package/packs/ai-engineering/skills/agent-config-review/examples/inputs/tidewater-ingest/{.mcp.json → dot.mcp.json} +0 -0
- /package/packs/ai-engineering/skills/agent-incident-response/evals/files/6/{.mcp.json → dot.mcp.json} +0 -0
- /package/packs/ai-engineering/skills/agent-incident-response/evals/files/7/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/ai-engineering/skills/mcp-pairing/evals/files/4/{.mcp.json → dot.mcp.json} +0 -0
- /package/packs/api-builder/skills/eval-harness-generator/evals/files/1/{SKILL.md → SKILL.md.fixture} +0 -0
- /package/packs/api-builder/skills/eval-harness-generator/evals/files/2/{SKILL.md → SKILL.md.fixture} +0 -0
- /package/packs/core/skills/context-graph/evals/files/9/{.env.example → dot.env.example} +0 -0
- /package/packs/dev-team/skills/agents-md-generator/evals/files/1/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/agents-md-generator/evals/files/5/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/codebase-tour/evals/files/1/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/codebase-tour/evals/files/2/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/codebase-tour/evals/files/3/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/codebase-tour/evals/files/4/{.env.example → dot.env.example} +0 -0
- /package/packs/dev-team/skills/codebase-tour/evals/files/4/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/codebase-tour/evals/files/5/{.env.example → dot.env.example} +0 -0
- /package/packs/dev-team/skills/codebase-tour/evals/files/5/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/1/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/2/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/2/{.github → dot.github}/workflows/release.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/4/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/5/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/5/{.github → dot.github}/workflows/release.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/5/{.nvmrc → dot.nvmrc} +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/6/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/6/{.github → dot.github}/workflows/integration.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/7/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/7/{.lintwright.json → dot.lintwright.json} +0 -0
- /package/packs/dev-team/skills/dependency-upgrade-review/evals/files/7/{.nvmrc → dot.nvmrc} +0 -0
- /package/packs/dev-team/skills/sonar-onboard/evals/files/2/{.github → dot.github}/workflows/ci.yml.fixture +0 -0
- /package/packs/dev-team/skills/sonar-onboard/evals/files/2/{.gitlab-ci.yml → dot.gitlab-ci.yml} +0 -0
- /package/packs/frontend/skills/bundle-size-review/evals/files/5/{.browserslistrc → dot.browserslistrc} +0 -0
- /package/packs/frontend/skills/bundle-size-review/evals/files/6/{.browserslistrc → dot.browserslistrc} +0 -0
- /package/packs/frontend/skills/bundle-size-review/evals/files/8/{.browserslistrc → dot.browserslistrc} +0 -0
- /package/packs/frontend/skills/bundle-size-review/evals/files/9/{.github → dot.github}/workflows/size.yml.fixture +0 -0
- /package/packs/skill-engineering/skills/skill-review/evals/files/1/skills/changelog-writer/{SKILL.md → SKILL.md.fixture} +0 -0
- /package/packs/skill-engineering/skills/skill-review/evals/files/1/skills/pr-summary/{SKILL.md → SKILL.md.fixture} +0 -0
- /package/packs/skill-engineering/skills/skill-review/evals/files/2/invoice-chaser/{SKILL.md → SKILL.md.fixture} +0 -0
package/bin/skilldrop.js
CHANGED
|
@@ -133,6 +133,8 @@ Options:
|
|
|
133
133
|
--json machine-readable output for list | info | packs | agents | outdated | doctor —
|
|
134
134
|
one JSON object on stdout, nothing else (for agents, scripts, CI)
|
|
135
135
|
--with-related also install each skill's related companions (one level)
|
|
136
|
+
--replace replace a skill installed from a different catalogue that has the same
|
|
137
|
+
name (install refuses otherwise); the old folder is removed first
|
|
136
138
|
--with-hooks also wire any hooks a skill declares (RFC-0006) — git pre-commit
|
|
137
139
|
reminders and Claude Code session-start context; degrades where the
|
|
138
140
|
target has no hook mechanism. Off by default so installs never touch
|
|
@@ -189,6 +191,15 @@ function splitSource(source) {
|
|
|
189
191
|
const i = source.lastIndexOf("#");
|
|
190
192
|
return i > 0 ? [source.slice(0, i), source.slice(i + 1)] : [source, ""];
|
|
191
193
|
}
|
|
194
|
+
/* Two catalogue sources are the same catalogue when they name the same place, whatever ref or
|
|
195
|
+
spelling: git+https://host/o/r.git#abc, https://host/o/r and https://host/o/r/ are one source. */
|
|
196
|
+
function sourceId(source) {
|
|
197
|
+
if (!source || source === BUNDLED) return BUNDLED;
|
|
198
|
+
let s = splitSource(String(source))[0].trim().replace(/^git\+/, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
199
|
+
if (/^[a-z]+:\/\//i.test(s)) s = s.replace(/^([a-z]+:\/\/[^/]+)/i, (h) => h.toLowerCase());
|
|
200
|
+
else s = path.resolve(s);
|
|
201
|
+
return s;
|
|
202
|
+
}
|
|
192
203
|
function isPinned(source) { return !!source && SHA_RE.test(splitSource(source)[1]); }
|
|
193
204
|
|
|
194
205
|
function fetchCatalog(source) {
|
|
@@ -1471,11 +1482,15 @@ function installUnits(args) {
|
|
|
1471
1482
|
const policy = enforcePolicy(args.flags, cat, names, "skill");
|
|
1472
1483
|
const { dest, ide } = target(args.flags);
|
|
1473
1484
|
const contain = containmentFor(args.flags, cat, names, dest, ide, policy);
|
|
1474
|
-
|
|
1485
|
+
const clashes = sourceClashes(cat, names, dest);
|
|
1486
|
+
if (args.flags["dry-run"]) { planInstall(cat, names, dest, ide, args.flags, clashes); if (contain) applyContainment(contain, true); return; }
|
|
1487
|
+
if (clashes.length && !args.flags.replace) die(clashMessage(clashes, cat, dest));
|
|
1475
1488
|
fs.mkdirSync(dest, { recursive: true });
|
|
1476
1489
|
const l = ledger(dest);
|
|
1477
1490
|
const pipDeps = [], suggestions = new Set(), notes = [];
|
|
1478
1491
|
for (const s of names) {
|
|
1492
|
+
// A replaced skill's folder goes first, so no file of the other catalogue's skill is left mixed in.
|
|
1493
|
+
if (clashes.some((c) => c.name === s)) fs.rmSync(path.join(dest, s), { recursive: true, force: true });
|
|
1479
1494
|
const m = copyOne(cat, s, dest, ide, l, notes);
|
|
1480
1495
|
if (fs.existsSync(path.join(skillDir(cat, s), "requirements.txt"))) pipDeps.push(s);
|
|
1481
1496
|
for (const r of m.related || []) if (!names.includes(r) && !l.data[r]) suggestions.add(r);
|
|
@@ -1537,14 +1552,39 @@ function installUnits(args) {
|
|
|
1537
1552
|
if (pk && pk["first-value"]) console.log("\n" + firstValueLines(pk).join("\n"));
|
|
1538
1553
|
}
|
|
1539
1554
|
|
|
1555
|
+
/* Two catalogues can each ship a skill with the same name, and they are different skills. Copying
|
|
1556
|
+
one over the other would replace it silently and leave the first one's extra files mixed in, so
|
|
1557
|
+
install refuses unless asked (--replace), and says where each came from. */
|
|
1558
|
+
function sourceClashes(cat, names, dest) {
|
|
1559
|
+
const l = ledger(dest), out = [];
|
|
1560
|
+
for (const s of names) {
|
|
1561
|
+
const have = l.data[s];
|
|
1562
|
+
if (!have || isLoopEntry(have)) continue;
|
|
1563
|
+
if (sourceId(lsrc(have)) !== sourceId(cat.source)) out.push({ name: s, from: lsrc(have) });
|
|
1564
|
+
}
|
|
1565
|
+
return out;
|
|
1566
|
+
}
|
|
1567
|
+
function clashMessage(clashes, cat, dest) {
|
|
1568
|
+
const what = (src) => src === BUNDLED ? "skilldrop" : `'${src}'`;
|
|
1569
|
+
return clashes.map((c) => `'${c.name}' in ${dest} came from ${what(c.from)}; this install is from ${what(cat.source)}, a different skill with the same name.`).join("\n ") +
|
|
1570
|
+
"\n Nothing was installed. Keep the one you have, or replace it: rerun with --replace (the old folder is removed first)," +
|
|
1571
|
+
"\n or install into a separate folder with --dest <dir>.";
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1540
1574
|
/* install --dry-run: everything install would write, and nothing written. */
|
|
1541
|
-
function planInstall(cat, names, dest, ide, flags) {
|
|
1575
|
+
function planInstall(cat, names, dest, ide, flags, clashes = []) {
|
|
1542
1576
|
const l = ledger(dest);
|
|
1543
1577
|
console.log(`dry run — nothing will be written. Target: ${dest} (${ide})\n`);
|
|
1544
1578
|
for (const s of names) {
|
|
1545
1579
|
const m = manifestOf(cat, s);
|
|
1546
1580
|
const have = l.data[s];
|
|
1547
|
-
const
|
|
1581
|
+
const clash = clashes.find((c) => c.name === s);
|
|
1582
|
+
if (clash && !flags.replace) {
|
|
1583
|
+
console.log(`would refuse ${s}: installed from ${clash.from === BUNDLED ? "skilldrop" : clash.from}, a different catalogue (add --replace to replace it)`);
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
const verb = clash ? `replace ${clash.from === BUNDLED ? "skilldrop" : clash.from}'s ${s} with` :
|
|
1587
|
+
!have ? "install" : lver(have) === m.version ? "reinstall" : `replace ${lver(have)} with`;
|
|
1548
1588
|
const edits = editedFiles(dest, s, have);
|
|
1549
1589
|
console.log(`would ${verb} ${s}@${m.version} -> ${path.join(dest, s)}`);
|
|
1550
1590
|
if (edits.length) console.log(` overwrites your edits in: ${edits.join(", ")} (update keeps them; install does not)`);
|
|
@@ -1818,6 +1858,9 @@ function doctor(args) {
|
|
|
1818
1858
|
for (const n of names) {
|
|
1819
1859
|
const note = lsrc(data[n]) === BUNDLED && retiredNote(resolveCatalog(), n, isLoopEntry(data[n]));
|
|
1820
1860
|
if (note) add("warn", note, `skilldrop uninstall ${n}${targetHint(args.flags)}, or keep it as it is; it will not update`);
|
|
1861
|
+
if (lsrc(data[n]) !== BUNDLED && !isLoopEntry(data[n]) && skillExists(resolveCatalog(), n))
|
|
1862
|
+
add("info", `${n} here came from '${lsrc(data[n])}'; skilldrop has its own ${n}, a different skill with the same name`,
|
|
1863
|
+
`keep it, or switch with: skilldrop install ${n} --replace${targetHint(args.flags)} (or install skilldrop's into another --dest)`);
|
|
1821
1864
|
if (!fs.existsSync(path.join(dest, n))) add("error", `${n} is in the ledger but its folder is gone`, `skilldrop install ${n} (or uninstall ${n} to drop the record)`);
|
|
1822
1865
|
else if (!data[n].file) {
|
|
1823
1866
|
const loop = isLoopEntry(data[n]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skilldrop-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Portable AI-agent skills, measured against the agent without them. ADRs, PRDs, runbooks, decks and reviews, installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Sanjay Ananthanarayan",
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
> We're about to roll this Claude Code setup out to the whole data team for tidewater-ingest.
|
|
6
6
|
> Anything we should change first?
|
|
7
7
|
|
|
8
|
-
Files: [`inputs/tidewater-ingest
|
|
9
|
-
[`inputs/tidewater-ingest/.mcp.json`](inputs/tidewater-ingest
|
|
10
|
-
[`inputs/tidewater-ingest/.gitignore`](inputs/tidewater-ingest
|
|
8
|
+
Files: [`inputs/tidewater-ingest/dot.claude/settings.json`](inputs/tidewater-ingest/dot.claude/settings.json),
|
|
9
|
+
[`inputs/tidewater-ingest/.mcp.json`](inputs/tidewater-ingest/dot.mcp.json),
|
|
10
|
+
[`inputs/tidewater-ingest/.gitignore`](inputs/tidewater-ingest/dot.gitignore).
|
|
11
11
|
|
|
12
12
|
## What the scan listed (abridged, real output)
|
|
13
13
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: locale-check
|
|
3
|
-
description: Check a product's translations against the source strings before they ship — every key present, every placeholder (
|
|
3
|
+
description: Check a product's translations against the source strings before they ship — every key present, every placeholder (named, %s, %1$d, ICU plural and select) carried over intact, the plural forms each language needs, markup tags balanced, and strings over their character budget — with a script that reads JSON, ARB, gettext .po, Android strings.xml and iOS .strings, and lists each problem with its key and locale. Use when someone asks to "check the translations", "QA these locale files", "will the German fit", "why does the French build crash on this string", or hands over locale files before a release.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# locale-check
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "locale-check",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Check a product's translations against the source strings before they ship — every key present, every placeholder (
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Check a product's translations against the source strings before they ship — every key present, every placeholder (named, %s, %1$d, ICU plural and select) carried over intact, the plural forms each language needs, markup tags balanced, and strings over their character budget — with a script that reads JSON, ARB, gettext .po, Android strings.xml and iOS .strings, and lists each problem with its key and locale. Use when someone asks to \"check the translations\", \"QA these locale files\", \"will the German fit\", \"why does the French build crash on this string\", or hands over locale files before a release.",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": {
|
|
7
7
|
"npm": [],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/packs/ai-engineering/skills/agent-config-review/evals/files/1/{.mcp.json → dot.mcp.json}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/packs/api-builder/skills/eval-harness-generator/evals/files/1/{SKILL.md → SKILL.md.fixture}
RENAMED
|
File without changes
|
/package/packs/api-builder/skills/eval-harness-generator/evals/files/2/{SKILL.md → SKILL.md.fixture}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/packs/dev-team/skills/sonar-onboard/evals/files/2/{.gitlab-ci.yml → dot.gitlab-ci.yml}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|