skilldex-cli 1.1.2 → 1.2.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/README.md +42 -8
- package/dist/cli/commands/install-action.d.ts +1 -0
- package/dist/cli/commands/install-action.d.ts.map +1 -1
- package/dist/cli/commands/install-action.js +27 -7
- package/dist/cli/commands/install-action.js.map +1 -1
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +1 -0
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/list-action.js.map +1 -1
- package/dist/cli/commands/search-action.js +1 -1
- package/dist/cli/commands/search-action.js.map +1 -1
- package/dist/cli/commands/skillset-validate-action.d.ts +1 -0
- package/dist/cli/commands/skillset-validate-action.d.ts.map +1 -1
- package/dist/cli/commands/skillset-validate-action.js +61 -2
- package/dist/cli/commands/skillset-validate-action.js.map +1 -1
- package/dist/cli/commands/skillset.d.ts.map +1 -1
- package/dist/cli/commands/skillset.js +1 -0
- package/dist/cli/commands/skillset.js.map +1 -1
- package/dist/cli/commands/suggest-action.d.ts.map +1 -1
- package/dist/cli/commands/suggest-action.js +0 -1
- package/dist/cli/commands/suggest-action.js.map +1 -1
- package/dist/cli/commands/uninstall-action.js.map +1 -1
- package/dist/cli/commands/update-action.d.ts.map +1 -1
- package/dist/cli/commands/update-action.js +1 -1
- package/dist/cli/commands/update-action.js.map +1 -1
- package/dist/cli/ui/prompts.js.map +1 -1
- package/dist/core/harness-bridge.d.ts +61 -0
- package/dist/core/harness-bridge.d.ts.map +1 -0
- package/dist/core/harness-bridge.js +126 -0
- package/dist/core/harness-bridge.js.map +1 -0
- package/dist/core/installer.d.ts +5 -0
- package/dist/core/installer.d.ts.map +1 -1
- package/dist/core/installer.js +15 -0
- package/dist/core/installer.js.map +1 -1
- package/dist/core/resolver.js.map +1 -1
- package/dist/core/skillset-coherence.d.ts +27 -0
- package/dist/core/skillset-coherence.d.ts.map +1 -0
- package/dist/core/skillset-coherence.js +466 -0
- package/dist/core/skillset-coherence.js.map +1 -0
- package/dist/core/skillset-installer.js +1 -1
- package/dist/core/skillset-installer.js.map +1 -1
- package/dist/core/skillset-validator.d.ts +1 -1
- package/dist/core/skillset-validator.d.ts.map +1 -1
- package/dist/core/skillset-validator.js +22 -1
- package/dist/core/skillset-validator.js.map +1 -1
- package/dist/core/suggest-agent.d.ts.map +1 -1
- package/dist/core/suggest-agent.js +14 -4
- package/dist/core/suggest-agent.js.map +1 -1
- package/dist/core/validator.js +1 -1
- package/dist/core/validator.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +1 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/registry/sources/github.d.ts +1 -2
- package/dist/registry/sources/github.d.ts.map +1 -1
- package/dist/registry/sources/github.js +6 -4
- package/dist/registry/sources/github.js.map +1 -1
- package/dist/registry/sources/registry.d.ts.map +1 -1
- package/dist/registry/sources/registry.js +3 -1
- package/dist/registry/sources/registry.js.map +1 -1
- package/dist/types/skillset.d.ts +41 -0
- package/dist/types/skillset.d.ts.map +1 -1
- package/package.json +8 -2
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { mkdir, symlink, lstat, readlink, rm, cp, realpath, stat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
const AGENTS_READERS = 'Codex, Gemini CLI, Cursor, Copilot, OpenCode, Windsurf, Antigravity, Amp, Crush';
|
|
5
|
+
const CLAUDE_READERS = 'Claude Code, Cursor, Copilot, Cline, OpenCode, Amp, Crush';
|
|
6
|
+
/**
|
|
7
|
+
* Harnesses read at two tiers, project and user, so the three Skilldex scopes collapse to
|
|
8
|
+
* two: `project` bridges beside the project, `global` and `shared` both bridge into $HOME.
|
|
9
|
+
*/
|
|
10
|
+
export function bridgeTargets(scope, projectRoot) {
|
|
11
|
+
const base = scope === 'project' ? projectRoot : os.homedir();
|
|
12
|
+
const j = (...parts) => path.join(base, ...parts);
|
|
13
|
+
const targets = [
|
|
14
|
+
{ dir: j('.agents', 'skills'), readers: AGENTS_READERS },
|
|
15
|
+
{ dir: j('.claude', 'skills'), readers: CLAUDE_READERS },
|
|
16
|
+
];
|
|
17
|
+
// Harnesses that read neither shared convention at this tier. Guarded on the harness's own
|
|
18
|
+
// config directory, so they cost nothing for users who do not have that harness.
|
|
19
|
+
if (scope === 'project') {
|
|
20
|
+
targets.push({ dir: j('.qwen', 'skills'), readers: 'Qwen Code', requires: j('.qwen') });
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
targets.push({ dir: j('.qwen', 'skills'), readers: 'Qwen Code', requires: j('.qwen') }, { dir: j('.cline', 'skills'), readers: 'Cline', requires: j('.cline') },
|
|
24
|
+
// Antigravity reads ~/.gemini/config/skills; ~/.gemini is shared with Gemini CLI, and its
|
|
25
|
+
// presence means one of the two is installed.
|
|
26
|
+
{ dir: j('.gemini', 'config', 'skills'), readers: 'Antigravity', requires: j('.gemini') });
|
|
27
|
+
}
|
|
28
|
+
return targets;
|
|
29
|
+
}
|
|
30
|
+
/** The subset of {@link bridgeTargets} whose guard is satisfied on this machine. */
|
|
31
|
+
export async function applicableTargets(scope, projectRoot) {
|
|
32
|
+
const targets = bridgeTargets(scope, projectRoot);
|
|
33
|
+
const keep = await Promise.all(targets.map(async (t) => {
|
|
34
|
+
if (!t.requires)
|
|
35
|
+
return true;
|
|
36
|
+
try {
|
|
37
|
+
return (await stat(t.requires)).isDirectory();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
return targets.filter((_, i) => keep[i]);
|
|
44
|
+
}
|
|
45
|
+
/** Does `entry` already point at `source`? Only then is it ours to replace or remove. */
|
|
46
|
+
async function pointsAt(entry, source) {
|
|
47
|
+
try {
|
|
48
|
+
const stats = await lstat(entry);
|
|
49
|
+
if (!stats.isSymbolicLink())
|
|
50
|
+
return false;
|
|
51
|
+
const dest = path.resolve(path.dirname(entry), await readlink(entry));
|
|
52
|
+
return path.resolve(dest) === path.resolve(source) || (await realpath(dest)) === (await realpath(source));
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Link an installed skill into every harness directory for its scope.
|
|
60
|
+
*
|
|
61
|
+
* Symlinks rather than copies: `.skilldex/` stays the single source of truth, so scoping
|
|
62
|
+
* still decides what a session sees and uninstall stays coherent. Both major harnesses
|
|
63
|
+
* document following them — Claude Code "follows the symlink and reads SKILL.md from the
|
|
64
|
+
* target directory", Codex "supports symlinked skill folders". Windows without developer
|
|
65
|
+
* mode cannot create them unprivileged, so fall back to copying there.
|
|
66
|
+
*
|
|
67
|
+
* An entry that exists and is not ours is **never** overwritten: it is somebody's
|
|
68
|
+
* hand-authored skill, and silently replacing it would be the worst possible failure.
|
|
69
|
+
*/
|
|
70
|
+
export async function bridgeSkill(skillName, installedPath, scope, projectRoot) {
|
|
71
|
+
const results = [];
|
|
72
|
+
for (const { dir } of await applicableTargets(scope, projectRoot)) {
|
|
73
|
+
const link = path.join(dir, skillName);
|
|
74
|
+
if (await pointsAt(link, installedPath)) {
|
|
75
|
+
results.push({ target: link, linked: true });
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
let occupied = false;
|
|
79
|
+
try {
|
|
80
|
+
await lstat(link);
|
|
81
|
+
occupied = true;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// free
|
|
85
|
+
}
|
|
86
|
+
if (occupied) {
|
|
87
|
+
results.push({
|
|
88
|
+
target: link,
|
|
89
|
+
linked: false,
|
|
90
|
+
conflict: 'exists and was not created by skilldex',
|
|
91
|
+
});
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
await mkdir(dir, { recursive: true });
|
|
95
|
+
try {
|
|
96
|
+
await symlink(installedPath, link, 'dir');
|
|
97
|
+
results.push({ target: link, linked: true });
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
// EPERM is the Windows-without-developer-mode case: copy so the skill still loads.
|
|
101
|
+
if (e.code === 'EPERM') {
|
|
102
|
+
await cp(installedPath, link, { recursive: true });
|
|
103
|
+
results.push({ target: link, linked: true });
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
/** Remove only links that point at this install; leave anything else alone. */
|
|
113
|
+
export async function unbridgeSkill(skillName, installedPath, scope, projectRoot) {
|
|
114
|
+
const removed = [];
|
|
115
|
+
// Every candidate, not just the applicable ones: a guard may have gone false since install
|
|
116
|
+
// (the harness was removed), and a link we created must still be ours to clean up.
|
|
117
|
+
for (const { dir } of bridgeTargets(scope, projectRoot)) {
|
|
118
|
+
const link = path.join(dir, skillName);
|
|
119
|
+
if (await pointsAt(link, installedPath)) {
|
|
120
|
+
await rm(link, { recursive: true, force: true });
|
|
121
|
+
removed.push(link);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return removed;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=harness-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-bridge.js","sourceRoot":"","sources":["../../src/core/harness-bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/core/installer.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ScopeLevel } from '../types/scope.js';
|
|
2
2
|
import type { ValidationResult } from '../types/skill.js';
|
|
3
|
+
import { type BridgeLink } from './harness-bridge.js';
|
|
3
4
|
export interface InstallOptions {
|
|
4
5
|
scope: ScopeLevel;
|
|
5
6
|
force?: boolean;
|
|
@@ -7,6 +8,8 @@ export interface InstallOptions {
|
|
|
7
8
|
sourceUrl?: string;
|
|
8
9
|
/** Called when a repo contains multiple skill folders. Return the name of the folder to install. */
|
|
9
10
|
onMultipleSkills?: (names: string[]) => Promise<string>;
|
|
11
|
+
/** Link the skill into the harness directories for its scope. Default true. */
|
|
12
|
+
bridge?: boolean;
|
|
10
13
|
}
|
|
11
14
|
export interface InstallResult {
|
|
12
15
|
skillName: string;
|
|
@@ -14,6 +17,8 @@ export interface InstallResult {
|
|
|
14
17
|
installedPath: string;
|
|
15
18
|
validation: ValidationResult;
|
|
16
19
|
alreadyExisted: boolean;
|
|
20
|
+
/** Harness directories linked, and any left alone because something else owned them. */
|
|
21
|
+
bridged: BridgeLink[];
|
|
17
22
|
}
|
|
18
23
|
export declare function installFromPath(sourcePath: string, options: InstallOptions): Promise<InstallResult>;
|
|
19
24
|
export declare function uninstallSkill(skillName: string, scope: ScopeLevel): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/core/installer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/core/installer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzD,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEjF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,UAAU,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oGAAoG;IACpG,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACvD,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,UAAU,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,cAAc,EAAE,OAAO,CAAA;IACvB,wFAAwF;IACxF,OAAO,EAAE,UAAU,EAAE,CAAA;CACtB;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAqExB;AAOD,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAexF"}
|
package/dist/core/installer.js
CHANGED
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { validateSkill, SPEC_VERSION } from './validator.js';
|
|
4
4
|
import { resolveScope, resolveAllScopes } from './resolver.js';
|
|
5
5
|
import { addSkillToManifest, removeSkillFromManifest, readManifest } from './manifest.js';
|
|
6
|
+
import { bridgeSkill, unbridgeSkill } from './harness-bridge.js';
|
|
6
7
|
export async function installFromPath(sourcePath, options) {
|
|
7
8
|
const absSource = path.resolve(sourcePath);
|
|
8
9
|
const validation = await validateSkill(absSource);
|
|
@@ -47,14 +48,26 @@ export async function installFromPath(sourcePath, options) {
|
|
|
47
48
|
};
|
|
48
49
|
await addSkillToManifest(scopeConfig, installed);
|
|
49
50
|
}
|
|
51
|
+
// Bridging is what makes an install visible to an agent: `.skilldex/` is ours alone, and
|
|
52
|
+
// no harness reads it. Do it after the manifest write so nothing is ever linked before it
|
|
53
|
+
// is really installed.
|
|
54
|
+
let bridged = [];
|
|
55
|
+
if (!options.dryRun && options.bridge !== false) {
|
|
56
|
+
bridged = await bridgeSkill(skillName, targetDir, options.scope, projectRootFor(scopeConfig));
|
|
57
|
+
}
|
|
50
58
|
return {
|
|
51
59
|
skillName,
|
|
52
60
|
scope: options.scope,
|
|
53
61
|
installedPath: targetDir,
|
|
54
62
|
validation,
|
|
55
63
|
alreadyExisted,
|
|
64
|
+
bridged,
|
|
56
65
|
};
|
|
57
66
|
}
|
|
67
|
+
/** For project scope, `rootPath` is `<projectRoot>/.skilldex`; other scopes ignore this. */
|
|
68
|
+
function projectRootFor(scopeConfig) {
|
|
69
|
+
return path.dirname(scopeConfig.rootPath);
|
|
70
|
+
}
|
|
58
71
|
export async function uninstallSkill(skillName, scope) {
|
|
59
72
|
const scopeConfig = await resolveScope(scope);
|
|
60
73
|
const manifest = await readManifest(scopeConfig);
|
|
@@ -62,6 +75,8 @@ export async function uninstallSkill(skillName, scope) {
|
|
|
62
75
|
throw new Error(`Skill "${skillName}" is not installed at ${scope} scope`);
|
|
63
76
|
}
|
|
64
77
|
const skillDir = path.join(scopeConfig.skillsDir, skillName);
|
|
78
|
+
// Unlink before removing the target, so the check that a link is ours can still resolve it.
|
|
79
|
+
await unbridgeSkill(skillName, skillDir, scope, projectRootFor(scopeConfig));
|
|
65
80
|
await rm(skillDir, { recursive: true, force: true });
|
|
66
81
|
await removeSkillFromManifest(scopeConfig, skillName);
|
|
67
82
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/core/installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,IAAI,MAAM,WAAW,CAAA;AAI5B,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/core/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/core/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/core/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DeclaredConvention, SkillsetCoherenceResult, MarkdownTable } from '../types/skillset.js';
|
|
2
|
+
/**
|
|
3
|
+
* Checks that a skillset's member skills agree with the conventions its shared assets declare.
|
|
4
|
+
*
|
|
5
|
+
* Structural validation (see skillset-validator.ts) establishes that a skillset is well-formed.
|
|
6
|
+
* It cannot express agreement *between* members, which is the property skillsets exist to provide:
|
|
7
|
+
* conventions live in one shared asset so independently authored members cannot drift apart.
|
|
8
|
+
*
|
|
9
|
+
* Agreement is checked against conventions the shared asset *declares* in a fenced
|
|
10
|
+
* ```yaml skilldex-conventions``` block, not inferred from prose. A member that restates a
|
|
11
|
+
* declared mapping and contradicts it is an error. A member that appears to restate a convention
|
|
12
|
+
* nobody declared is a warning — the fix is to declare it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function checkSkillsetCoherence(skillsetPath: string, embeddedSkills: string[]): Promise<SkillsetCoherenceResult>;
|
|
15
|
+
/** Extracts ```yaml skilldex-conventions fenced blocks. Exported for tests. */
|
|
16
|
+
export declare function parseDeclaredConventions(content: string, assetFile: string): DeclaredConvention[];
|
|
17
|
+
interface AssetReference {
|
|
18
|
+
rawPath: string;
|
|
19
|
+
line: number;
|
|
20
|
+
isSkillsetLevel: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Finds backticked paths pointing into assets/ or references/. Exported for tests. */
|
|
23
|
+
export declare function extractAssetReferences(content: string): AssetReference[];
|
|
24
|
+
/** Parses pipe tables into header + rows. Exported for tests. */
|
|
25
|
+
export declare function parseMarkdownTables(content: string): MarkdownTable[];
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=skillset-coherence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skillset-coherence.d.ts","sourceRoot":"","sources":["../../src/core/skillset-coherence.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,kBAAkB,EAElB,uBAAuB,EACvB,aAAa,EACd,MAAM,sBAAsB,CAAA;AAS7B;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,uBAAuB,CAAC,CAgDlC;AA2ND,+EAA+E;AAC/E,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,kBAAkB,EAAE,CA4CjG;AAeD,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,OAAO,CAAA;CACzB;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAqBxE;AAID,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAqBpE"}
|