@skillbase/spm 0.1.4 → 0.2.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 +33 -0
- package/dist/cli/command.d.ts +43 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +8 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/commands/add.d.ts +17 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +348 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/connect.d.ts +2 -0
- package/dist/cli/commands/connect.d.ts.map +1 -1
- package/dist/cli/commands/connect.js +28 -13
- package/dist/cli/commands/connect.js.map +1 -1
- package/dist/cli/commands/convert.d.ts +2 -0
- package/dist/cli/commands/convert.d.ts.map +1 -1
- package/dist/cli/commands/convert.js +55 -39
- package/dist/cli/commands/convert.js.map +1 -1
- package/dist/cli/commands/create.d.ts +3 -3
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +15 -15
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/info.d.ts +2 -0
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +24 -17
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +13 -6
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/install.d.ts +3 -3
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +23 -240
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/link.d.ts +4 -0
- package/dist/cli/commands/link.d.ts.map +1 -0
- package/dist/cli/commands/link.js +56 -0
- package/dist/cli/commands/link.js.map +1 -0
- package/dist/cli/commands/list.d.ts +2 -0
- package/dist/cli/commands/list.d.ts.map +1 -1
- package/dist/cli/commands/list.js +35 -12
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/login.d.ts +2 -0
- package/dist/cli/commands/login.d.ts.map +1 -1
- package/dist/cli/commands/login.js +62 -28
- package/dist/cli/commands/login.js.map +1 -1
- package/dist/cli/commands/persona.d.ts +3 -0
- package/dist/cli/commands/persona.d.ts.map +1 -0
- package/dist/cli/commands/persona.js +253 -0
- package/dist/cli/commands/persona.js.map +1 -0
- package/dist/cli/commands/publish.d.ts +2 -0
- package/dist/cli/commands/publish.d.ts.map +1 -1
- package/dist/cli/commands/publish.js +30 -32
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/commands/rate.d.ts +2 -0
- package/dist/cli/commands/rate.d.ts.map +1 -1
- package/dist/cli/commands/rate.js +15 -5
- package/dist/cli/commands/rate.js.map +1 -1
- package/dist/cli/commands/reindex.d.ts +3 -0
- package/dist/cli/commands/reindex.d.ts.map +1 -0
- package/dist/cli/commands/reindex.js +35 -0
- package/dist/cli/commands/reindex.js.map +1 -0
- package/dist/cli/commands/remove.d.ts +8 -0
- package/dist/cli/commands/remove.d.ts.map +1 -0
- package/dist/cli/commands/remove.js +126 -0
- package/dist/cli/commands/remove.js.map +1 -0
- package/dist/cli/commands/search.d.ts +2 -0
- package/dist/cli/commands/search.d.ts.map +1 -1
- package/dist/cli/commands/search.js +25 -12
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/serve.d.ts +3 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +17 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +2 -0
- package/dist/cli/commands/stats.d.ts.map +1 -1
- package/dist/cli/commands/stats.js +16 -10
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/uninstall.d.ts +2 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.js +50 -14
- package/dist/cli/commands/uninstall.js.map +1 -1
- package/dist/cli/commands/update.d.ts +2 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +27 -32
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +2 -0
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +16 -18
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/help.d.ts +7 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +72 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/index.js +5 -151
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/loader.d.ts +3 -0
- package/dist/cli/loader.d.ts.map +1 -0
- package/dist/cli/loader.js +69 -0
- package/dist/cli/loader.js.map +1 -0
- package/dist/cli/logger.d.ts +9 -0
- package/dist/cli/logger.d.ts.map +1 -0
- package/dist/cli/logger.js +13 -0
- package/dist/cli/logger.js.map +1 -0
- package/dist/cli/theme.d.ts +17 -0
- package/dist/cli/theme.d.ts.map +1 -0
- package/dist/cli/theme.js +29 -0
- package/dist/cli/theme.js.map +1 -0
- package/dist/cli/ui.d.ts +8 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +17 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +4 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/paths.d.ts +2 -0
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +7 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/persona.d.ts +17 -0
- package/dist/core/persona.d.ts.map +1 -0
- package/dist/core/persona.js +118 -0
- package/dist/core/persona.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +91 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/schema/persona-schema.d.ts +6 -0
- package/dist/schema/persona-schema.d.ts.map +1 -0
- package/dist/schema/persona-schema.js +72 -0
- package/dist/schema/persona-schema.js.map +1 -0
- package/dist/types/index.d.ts +25 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.2.1] - 2026-03-14
|
|
6
|
+
|
|
7
|
+
## [0.2.0] - 2026-03-14
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Persona system** — `.person.json` format for defining AI agent personalities with character traits (role, tone, guidelines, instructions), model settings, and skill dependencies
|
|
12
|
+
- **MCP tools**: `persona_list`, `persona_load` — list available personas and activate them in chat
|
|
13
|
+
- **Persona storage**: `~/.skills/personas/` (global) and `.skills/personas/` (project-level, overrides global)
|
|
14
|
+
- **Active persona injection** — active persona's character instructions are injected into MCP server instructions at startup
|
|
15
|
+
- **JSON Schema validation** for `.person.json` manifests
|
|
16
|
+
- **`spm link <path>`** — symlink a local skill directory for development (like `yarn link`)
|
|
17
|
+
- **`spm add <ref> --for [persona]`** — add skill reference to persona file(s) without installing; supports comma-separated names and interactive multiselect when multiple `.person.json` files exist
|
|
18
|
+
- **`spm remove <ref> --from [persona]`** — remove skill reference from persona file(s); supports comma-separated names and interactive multiselect
|
|
19
|
+
- **`spm persona activate <name>`** — activate a persona and auto-install any missing skills from its dependencies
|
|
20
|
+
- **`spm persona remove <name>`** — remove a persona from global installation (auto-deactivates if active)
|
|
21
|
+
- **CLI commands**: `spm persona create/list/activate/deactivate/info/remove/validate` — full persona lifecycle
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **CLI command semantics redesigned** following yarn/pnpm conventions:
|
|
26
|
+
- `spm install skill <ref>` → **`spm add <ref>`** (add a single skill, like `yarn add`)
|
|
27
|
+
- `spm install` (no args) → installs all dependencies from `skill.json` (like `yarn install`)
|
|
28
|
+
- `spm uninstall <name>` / `spm remove <name>` → unified skill removal (accepts bare name or `author/name`)
|
|
29
|
+
- `spm remove <ref> --from [persona]` → remove a skill reference from persona file(s)
|
|
30
|
+
- `spm create <name>` → simplified scaffold (removed `--scope`, skill name is plain)
|
|
31
|
+
- `spm persona use` → **`spm persona activate`** (clearer semantics, auto-installs missing skills)
|
|
32
|
+
- `spm persona off` → **`spm persona deactivate`**
|
|
33
|
+
- **Extensible command architecture** — commands are self-contained modules with declarative `CommandDef` exports; adding a new command = creating a file in `src/cli/commands/` (no `index.ts` changes needed). Entry point reduced from 277 lines to 20 lines.
|
|
34
|
+
- **Brand-themed CLI output** — custom logger with Skillbase brand colors (`#00e5a0` teal, `#22d3ee` cyan, `#ef4444` red) using true-color ANSI; replaces default `@clack/prompts` log styling
|
|
35
|
+
- **Grouped help output** — `spm --help` now shows commands organized by category (Manage skills, Review, Personas, Registry, System) with brand-colored formatting
|
|
36
|
+
- **Auto-discovery command loader** — dynamically imports all command files from `src/cli/commands/` at startup
|
|
37
|
+
|
|
5
38
|
## [0.1.4] - 2026-03-14
|
|
6
39
|
|
|
7
40
|
### Fixed
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface CommandDef {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
group: string;
|
|
5
|
+
aliases?: string[];
|
|
6
|
+
args?: Array<{
|
|
7
|
+
name: string;
|
|
8
|
+
required: boolean;
|
|
9
|
+
description?: string;
|
|
10
|
+
}>;
|
|
11
|
+
options?: Array<{
|
|
12
|
+
flags: string;
|
|
13
|
+
description: string;
|
|
14
|
+
default?: unknown;
|
|
15
|
+
required?: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
subcommands?: CommandDef[];
|
|
18
|
+
handler?: (...args: any[]) => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare const GROUPS: {
|
|
21
|
+
readonly manage: {
|
|
22
|
+
readonly label: "Manage skills";
|
|
23
|
+
readonly order: 0;
|
|
24
|
+
};
|
|
25
|
+
readonly review: {
|
|
26
|
+
readonly label: "Review";
|
|
27
|
+
readonly order: 1;
|
|
28
|
+
};
|
|
29
|
+
readonly personas: {
|
|
30
|
+
readonly label: "Personas";
|
|
31
|
+
readonly order: 2;
|
|
32
|
+
};
|
|
33
|
+
readonly registry: {
|
|
34
|
+
readonly label: "Registry";
|
|
35
|
+
readonly order: 3;
|
|
36
|
+
};
|
|
37
|
+
readonly system: {
|
|
38
|
+
readonly label: "System";
|
|
39
|
+
readonly order: 4;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export type GroupKey = keyof typeof GROUPS;
|
|
43
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/cli/command.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC,CAAC;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAE3B,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;CAMT,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,MAAM,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const GROUPS = {
|
|
2
|
+
manage: { label: "Manage skills", order: 0 },
|
|
3
|
+
review: { label: "Review", order: 1 },
|
|
4
|
+
personas: { label: "Personas", order: 2 },
|
|
5
|
+
registry: { label: "Registry", order: 3 },
|
|
6
|
+
system: { label: "System", order: 4 },
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/cli/command.ts"],"names":[],"mappings":"AAiBA,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,MAAM,EAAI,EAAE,KAAK,EAAE,eAAe,EAAG,KAAK,EAAE,CAAC,EAAE;IAC/C,MAAM,EAAI,EAAE,KAAK,EAAE,QAAQ,EAAU,KAAK,EAAE,CAAC,EAAE;IAC/C,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAQ,KAAK,EAAE,CAAC,EAAE;IAC/C,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAQ,KAAK,EAAE,CAAC,EAAE;IAC/C,MAAM,EAAI,EAAE,KAAK,EAAE,QAAQ,EAAU,KAAK,EAAE,CAAC,EAAE;CACvC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RegistryClient } from "../../core/registry-client.js";
|
|
2
|
+
import type { SkillManifest } from "../../types/index.js";
|
|
3
|
+
import type { CommandDef } from "../command.js";
|
|
4
|
+
export declare const command: CommandDef;
|
|
5
|
+
declare function resolveSkillsDir(forceGlobal?: boolean): Promise<{
|
|
6
|
+
skillsDir: string;
|
|
7
|
+
isProject: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
declare function installSingleFromRegistry(author: string, skillName: string, skillsDir: string, client: RegistryClient, version?: string): Promise<SkillManifest>;
|
|
10
|
+
export declare function addCommand(source: string, options: {
|
|
11
|
+
global?: boolean;
|
|
12
|
+
version?: string;
|
|
13
|
+
github?: string;
|
|
14
|
+
for?: string | boolean;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
export { installSingleFromRegistry, resolveSkillsDir };
|
|
17
|
+
//# sourceMappingURL=add.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAUlF,OAAO,KAAK,EAAE,aAAa,EAAmB,MAAM,sBAAsB,CAAC;AAE3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,OAAO,EAAE,UAYrB,CAAC;AAuJF,iBAAe,gBAAgB,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAiBzG;AAwCD,iBAAe,yBAAyB,CACtC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAqCxB;AA6HD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACvF,OAAO,CAAC,IAAI,CAAC,CAwBf;AAGD,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { readConfig } from "../../core/config.js";
|
|
4
|
+
import { getClientForSkill } from "../../core/registry-client.js";
|
|
5
|
+
import { validatePersonaManifest } from "../../schema/persona-schema.js";
|
|
6
|
+
import { validateSkillManifest } from "../../schema/skill-schema.js";
|
|
7
|
+
import { writeIndex } from "../../core/indexer.js";
|
|
8
|
+
import { writeLock } from "../../core/lock.js";
|
|
9
|
+
import { getGlobalSkillsDir, getProjectSkillsDir, getInstalledDir } from "../../core/paths.js";
|
|
10
|
+
import { downloadSkillFiles, parseGitHubUrl } from "../../core/github/client.js";
|
|
11
|
+
import { unpackSkill, computeIntegrity } from "../../core/storage/packager.js";
|
|
12
|
+
import { resolveDependencies } from "../../core/resolver.js";
|
|
13
|
+
import { addDependency } from "../../core/manifest.js";
|
|
14
|
+
import { log, spinner, multiselect, isCancel, cancel, exitError } from "../ui.js";
|
|
15
|
+
export const command = {
|
|
16
|
+
name: "add",
|
|
17
|
+
description: "Add a skill",
|
|
18
|
+
group: "manage",
|
|
19
|
+
args: [{ name: "skill", required: true }],
|
|
20
|
+
options: [
|
|
21
|
+
{ flags: "-g, --global", description: "Install globally instead of project-local" },
|
|
22
|
+
{ flags: "-v, --version <version>", description: "Specific version to install" },
|
|
23
|
+
{ flags: "--github <token>", description: "GitHub personal access token for private repos" },
|
|
24
|
+
{ flags: "--for [personas]", description: "Add skill reference to persona file(s) (comma-separated, no install)" },
|
|
25
|
+
],
|
|
26
|
+
handler: addCommand,
|
|
27
|
+
};
|
|
28
|
+
// --- Persona ref mode ---
|
|
29
|
+
function parseSkillRef(ref) {
|
|
30
|
+
const match = ref.match(/^([a-z0-9-]+)\/([a-z0-9-]+)$/);
|
|
31
|
+
if (!match)
|
|
32
|
+
return null;
|
|
33
|
+
return { author: match[1], name: match[2] };
|
|
34
|
+
}
|
|
35
|
+
async function findPersonaFiles() {
|
|
36
|
+
const cwd = process.cwd();
|
|
37
|
+
const entries = await fs.readdir(cwd, { withFileTypes: true });
|
|
38
|
+
return entries
|
|
39
|
+
.filter((e) => e.isFile() && e.name.endsWith(".person.json"))
|
|
40
|
+
.map((e) => e.name);
|
|
41
|
+
}
|
|
42
|
+
async function findPersonaFile(name) {
|
|
43
|
+
const fileName = `${name}.person.json`;
|
|
44
|
+
const filePath = path.resolve(fileName);
|
|
45
|
+
try {
|
|
46
|
+
await fs.access(filePath);
|
|
47
|
+
return filePath;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function getLatestVersion(client, author, name) {
|
|
54
|
+
const versions = await client.getVersions(author, name);
|
|
55
|
+
if (versions.length === 0)
|
|
56
|
+
return null;
|
|
57
|
+
return versions[versions.length - 1].version;
|
|
58
|
+
}
|
|
59
|
+
async function addRefToPersona(skillRef, personaName) {
|
|
60
|
+
const filePath = await findPersonaFile(personaName);
|
|
61
|
+
if (!filePath) {
|
|
62
|
+
exitError(`"${personaName}.person.json" not found in current directory.`);
|
|
63
|
+
}
|
|
64
|
+
const raw = await fs.readFile(filePath, "utf-8");
|
|
65
|
+
let persona;
|
|
66
|
+
try {
|
|
67
|
+
persona = JSON.parse(raw);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
exitError(`Failed to parse "${path.basename(filePath)}".`);
|
|
71
|
+
}
|
|
72
|
+
const validation = validatePersonaManifest(persona);
|
|
73
|
+
if (!validation.valid) {
|
|
74
|
+
exitError(`Invalid persona manifest.\n${validation.errors.map((e) => ` ${e}`).join("\n")}`);
|
|
75
|
+
}
|
|
76
|
+
if (persona.skills && skillRef in persona.skills) {
|
|
77
|
+
log.info(`Skill "${skillRef}" already in persona "${personaName}".`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const parsed = parseSkillRef(skillRef);
|
|
81
|
+
const config = await readConfig();
|
|
82
|
+
let versionRange = "*";
|
|
83
|
+
if (parsed) {
|
|
84
|
+
const client = getClientForSkill(config, skillRef);
|
|
85
|
+
if (client) {
|
|
86
|
+
try {
|
|
87
|
+
const latest = await getLatestVersion(client, parsed.author, parsed.name);
|
|
88
|
+
if (latest) {
|
|
89
|
+
versionRange = `^${latest}`;
|
|
90
|
+
log.info(`Found ${skillRef}@${latest} in registry.`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
log.warning(`Could not query registry. Adding with "*".`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!persona.skills)
|
|
99
|
+
persona.skills = {};
|
|
100
|
+
persona.skills[skillRef] = versionRange;
|
|
101
|
+
await fs.writeFile(filePath, JSON.stringify(persona, null, 2) + "\n", "utf-8");
|
|
102
|
+
log.success(`Added "${skillRef}": "${versionRange}" to ${path.basename(filePath)}.`);
|
|
103
|
+
}
|
|
104
|
+
async function addToPersonas(skillRef, personasArg) {
|
|
105
|
+
if (personasArg) {
|
|
106
|
+
const names = personasArg.split(",").map((n) => n.trim());
|
|
107
|
+
for (const name of names) {
|
|
108
|
+
await addRefToPersona(skillRef, name);
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Interactive: find .person.json files in cwd
|
|
113
|
+
const files = await findPersonaFiles();
|
|
114
|
+
if (files.length === 0) {
|
|
115
|
+
exitError("No .person.json files found in current directory. Specify --for <persona>.");
|
|
116
|
+
}
|
|
117
|
+
if (files.length === 1) {
|
|
118
|
+
const name = files[0].replace(".person.json", "");
|
|
119
|
+
await addRefToPersona(skillRef, name);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const choices = await multiselect({
|
|
123
|
+
message: "Add to which persona(s)?",
|
|
124
|
+
options: files.map((f) => ({
|
|
125
|
+
value: f.replace(".person.json", ""),
|
|
126
|
+
label: f,
|
|
127
|
+
})),
|
|
128
|
+
required: true,
|
|
129
|
+
});
|
|
130
|
+
if (isCancel(choices)) {
|
|
131
|
+
cancel("Cancelled.");
|
|
132
|
+
process.exit(0);
|
|
133
|
+
}
|
|
134
|
+
for (const name of choices) {
|
|
135
|
+
await addRefToPersona(skillRef, name);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// --- Install mode (from old install.ts) ---
|
|
139
|
+
async function copyDir(src, dest) {
|
|
140
|
+
await fs.mkdir(dest, { recursive: true });
|
|
141
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
142
|
+
for (const entry of entries) {
|
|
143
|
+
const srcPath = path.join(src, entry.name);
|
|
144
|
+
const destPath = path.join(dest, entry.name);
|
|
145
|
+
if (entry.isDirectory()) {
|
|
146
|
+
await copyDir(srcPath, destPath);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
await fs.copyFile(srcPath, destPath);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function isRemoteSource(source) {
|
|
154
|
+
if (/^[a-z0-9-]+\/[a-z0-9-]+$/.test(source))
|
|
155
|
+
return true;
|
|
156
|
+
if (source.includes("github.com") || source.startsWith("github:"))
|
|
157
|
+
return true;
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
async function resolveSkillsDir(forceGlobal) {
|
|
161
|
+
if (forceGlobal) {
|
|
162
|
+
return { skillsDir: getGlobalSkillsDir(), isProject: false };
|
|
163
|
+
}
|
|
164
|
+
const cwd = process.cwd();
|
|
165
|
+
const projectDir = getProjectSkillsDir(cwd);
|
|
166
|
+
try {
|
|
167
|
+
const stat = await fs.stat(projectDir);
|
|
168
|
+
if (stat.isDirectory()) {
|
|
169
|
+
return { skillsDir: projectDir, isProject: true };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// no project .skills/ — fall through to global
|
|
174
|
+
}
|
|
175
|
+
return { skillsDir: getGlobalSkillsDir(), isProject: false };
|
|
176
|
+
}
|
|
177
|
+
async function installFromLocal(skillPath, skillsDir) {
|
|
178
|
+
const src = path.resolve(skillPath);
|
|
179
|
+
const manifestPath = path.join(src, "skill.json");
|
|
180
|
+
let manifest;
|
|
181
|
+
try {
|
|
182
|
+
const raw = await fs.readFile(manifestPath, "utf-8");
|
|
183
|
+
const data = JSON.parse(raw);
|
|
184
|
+
const result = validateSkillManifest(data);
|
|
185
|
+
if (!result.valid) {
|
|
186
|
+
exitError(`Invalid skill.json:\n${result.errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
187
|
+
}
|
|
188
|
+
manifest = data;
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
if (err instanceof Error && "code" in err) {
|
|
192
|
+
exitError(`Cannot read skill.json in "${skillPath}".`);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const author = manifest.author;
|
|
199
|
+
const installedDir = getInstalledDir(skillsDir);
|
|
200
|
+
const dest = path.join(installedDir, author, manifest.name);
|
|
201
|
+
await fs.rm(dest, { recursive: true, force: true });
|
|
202
|
+
await copyDir(src, dest);
|
|
203
|
+
const index = await writeIndex(skillsDir);
|
|
204
|
+
const lock = await writeLock(skillsDir);
|
|
205
|
+
log.success(`Installed ${author}/${manifest.name}@${manifest.version}`);
|
|
206
|
+
log.info(`${index.skills.length} skill(s) indexed, ${lock.total_tokens_estimate} tokens total`);
|
|
207
|
+
}
|
|
208
|
+
async function installSingleFromRegistry(author, skillName, skillsDir, client, version) {
|
|
209
|
+
const s = spinner();
|
|
210
|
+
s.start(`Fetching ${author}/${skillName}${version ? `@${version}` : ""}...`);
|
|
211
|
+
const downloadResult = await client.getDownloadUrl(author, skillName, version);
|
|
212
|
+
const manifest = downloadResult.manifest;
|
|
213
|
+
const installedDir = getInstalledDir(skillsDir);
|
|
214
|
+
const dest = path.join(installedDir, author, manifest.name);
|
|
215
|
+
await fs.rm(dest, { recursive: true, force: true });
|
|
216
|
+
if (!downloadResult.download_url) {
|
|
217
|
+
s.stop("Failed");
|
|
218
|
+
exitError("Registry returned no download URL. The skill may have been published without an archive.");
|
|
219
|
+
}
|
|
220
|
+
s.message("Downloading package...");
|
|
221
|
+
const archiveRes = await fetch(downloadResult.download_url);
|
|
222
|
+
if (!archiveRes.ok) {
|
|
223
|
+
s.stop("Failed");
|
|
224
|
+
throw new Error(`Failed to download package: ${archiveRes.status} ${archiveRes.statusText}`);
|
|
225
|
+
}
|
|
226
|
+
const archiveData = Buffer.from(await archiveRes.arrayBuffer());
|
|
227
|
+
if (downloadResult.integrity) {
|
|
228
|
+
const actual = computeIntegrity(archiveData);
|
|
229
|
+
if (actual !== downloadResult.integrity) {
|
|
230
|
+
s.stop("Failed");
|
|
231
|
+
exitError(`Integrity mismatch.\n Expected: ${downloadResult.integrity}\n Got: ${actual}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const files = await unpackSkill(archiveData, dest);
|
|
235
|
+
s.stop(`Unpacked ${files.length} file(s), ${(archiveData.length / 1024).toFixed(1)} KB`);
|
|
236
|
+
return manifest;
|
|
237
|
+
}
|
|
238
|
+
async function installFromRegistry(skillRef, skillsDir, isProject, version) {
|
|
239
|
+
const parsed = parseSkillRef(skillRef);
|
|
240
|
+
if (!parsed) {
|
|
241
|
+
exitError(`Invalid skill reference "${skillRef}". Expected author/name.`);
|
|
242
|
+
}
|
|
243
|
+
const config = await readConfig();
|
|
244
|
+
const client = getClientForSkill(config, skillRef);
|
|
245
|
+
if (!client) {
|
|
246
|
+
exitError(`No registry configured for "${skillRef}".\nUse 'spm login <registry-url>' or 'spm registry add <url>' first.`);
|
|
247
|
+
}
|
|
248
|
+
const manifest = await installSingleFromRegistry(parsed.author, parsed.name, skillsDir, client, version);
|
|
249
|
+
// Resolve and install dependencies
|
|
250
|
+
const deps = manifest.dependencies;
|
|
251
|
+
if (deps && Object.keys(deps).length > 0) {
|
|
252
|
+
const visited = new Set([`${parsed.author}/${manifest.name}`]);
|
|
253
|
+
const result = await resolveDependencies(deps, client, visited);
|
|
254
|
+
for (const dep of result.resolved) {
|
|
255
|
+
const depRef = parseSkillRef(dep.name);
|
|
256
|
+
if (!depRef)
|
|
257
|
+
continue;
|
|
258
|
+
log.step(`Dependency: ${dep.name}@${dep.resolved} (${dep.range})`);
|
|
259
|
+
const depClient = getClientForSkill(config, dep.name) ?? client;
|
|
260
|
+
const depManifest = await installSingleFromRegistry(depRef.author, depRef.name, skillsDir, depClient, dep.resolved);
|
|
261
|
+
visited.add(dep.name);
|
|
262
|
+
if (depManifest.dependencies && Object.keys(depManifest.dependencies).length > 0) {
|
|
263
|
+
const nested = await resolveDependencies(depManifest.dependencies, depClient, visited);
|
|
264
|
+
for (const nd of nested.resolved) {
|
|
265
|
+
const ndRef = parseSkillRef(nd.name);
|
|
266
|
+
if (!ndRef)
|
|
267
|
+
continue;
|
|
268
|
+
log.step(`Dependency: ${nd.name}@${nd.resolved} (${nd.range})`);
|
|
269
|
+
const ndClient = getClientForSkill(config, nd.name) ?? client;
|
|
270
|
+
visited.add(nd.name);
|
|
271
|
+
await installSingleFromRegistry(ndRef.author, ndRef.name, skillsDir, ndClient, nd.resolved);
|
|
272
|
+
}
|
|
273
|
+
for (const m of nested.missing) {
|
|
274
|
+
log.warning(`Dependency ${m.name} (${m.range}): ${m.reason}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
for (const m of result.missing) {
|
|
279
|
+
log.warning(`Dependency ${m.name} (${m.range}): ${m.reason}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (isProject) {
|
|
283
|
+
await addDependency(process.cwd(), skillRef, manifest.version);
|
|
284
|
+
}
|
|
285
|
+
const index = await writeIndex(skillsDir);
|
|
286
|
+
const lock = await writeLock(skillsDir);
|
|
287
|
+
log.success(`Installed ${parsed.author}/${manifest.name}@${manifest.version} from registry`);
|
|
288
|
+
log.info(`${index.skills.length} skill(s) indexed, ${lock.total_tokens_estimate} tokens total`);
|
|
289
|
+
}
|
|
290
|
+
async function installFromGitHub(source, skillsDir, githubToken) {
|
|
291
|
+
const ghSource = parseGitHubUrl(source);
|
|
292
|
+
const s = spinner();
|
|
293
|
+
s.start(`Fetching from GitHub: ${ghSource.owner}/${ghSource.repo}${ghSource.path ? `/${ghSource.path}` : ""}...`);
|
|
294
|
+
const config = await readConfig();
|
|
295
|
+
const token = githubToken ?? config.github?.token;
|
|
296
|
+
const files = await downloadSkillFiles(ghSource, token);
|
|
297
|
+
const manifestRaw = files.get("skill.json");
|
|
298
|
+
if (!manifestRaw) {
|
|
299
|
+
s.stop("Failed");
|
|
300
|
+
exitError("skill.json not found in GitHub source.");
|
|
301
|
+
}
|
|
302
|
+
const manifest = JSON.parse(manifestRaw);
|
|
303
|
+
const validation = validateSkillManifest(manifest);
|
|
304
|
+
if (!validation.valid) {
|
|
305
|
+
s.stop("Failed");
|
|
306
|
+
exitError(`Invalid skill.json from GitHub:\n${validation.errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
307
|
+
}
|
|
308
|
+
s.stop("Fetched");
|
|
309
|
+
const author = manifest.author;
|
|
310
|
+
const installedDir = getInstalledDir(skillsDir);
|
|
311
|
+
const dest = path.join(installedDir, author, manifest.name);
|
|
312
|
+
await fs.rm(dest, { recursive: true, force: true });
|
|
313
|
+
await fs.mkdir(dest, { recursive: true });
|
|
314
|
+
for (const [filePath, content] of files) {
|
|
315
|
+
const fullPath = path.join(dest, filePath);
|
|
316
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
317
|
+
await fs.writeFile(fullPath, content, "utf-8");
|
|
318
|
+
}
|
|
319
|
+
const index = await writeIndex(skillsDir);
|
|
320
|
+
const lock = await writeLock(skillsDir);
|
|
321
|
+
log.success(`Installed ${author}/${manifest.name}@${manifest.version} from GitHub`);
|
|
322
|
+
log.info(`${index.skills.length} skill(s) indexed, ${lock.total_tokens_estimate} tokens total`);
|
|
323
|
+
}
|
|
324
|
+
// --- Main command ---
|
|
325
|
+
export async function addCommand(source, options) {
|
|
326
|
+
// --for mode: add ref to persona file(s), no install
|
|
327
|
+
if (options.for !== undefined) {
|
|
328
|
+
const personasArg = typeof options.for === "string" ? options.for : undefined;
|
|
329
|
+
await addToPersonas(source, personasArg);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const { skillsDir, isProject } = await resolveSkillsDir(options.global);
|
|
333
|
+
// GitHub URL
|
|
334
|
+
if (source.includes("github.com") || source.startsWith("github:")) {
|
|
335
|
+
await installFromGitHub(source, skillsDir, options.github);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
// Remote registry (author/name)
|
|
339
|
+
if (isRemoteSource(source)) {
|
|
340
|
+
await installFromRegistry(source, skillsDir, isProject, options.version);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
// Local path
|
|
344
|
+
await installFromLocal(source, skillsDir);
|
|
345
|
+
}
|
|
346
|
+
// Re-export for use by persona activate
|
|
347
|
+
export { installSingleFromRegistry, resolveSkillsDir };
|
|
348
|
+
//# sourceMappingURL=add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { CommandDef } from "../command.js";
|
|
2
|
+
export declare const commands: CommandDef[];
|
|
1
3
|
export declare function connectCommand(client: string): Promise<void>;
|
|
2
4
|
export declare function disconnectCommand(client: string): Promise<void>;
|
|
3
5
|
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/connect.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/connect.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,QAAQ,EAAE,UAAU,EAehC,CAAC;AAgEF,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAoCf;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
|
|
@@ -3,6 +3,23 @@ import { realpathSync } from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import { parse, modify, applyEdits } from "jsonc-parser";
|
|
6
|
+
import { log, exitError } from "../ui.js";
|
|
7
|
+
export const commands = [
|
|
8
|
+
{
|
|
9
|
+
name: "connect",
|
|
10
|
+
description: "Connect skills to an AI client (claude, zed)",
|
|
11
|
+
group: "system",
|
|
12
|
+
args: [{ name: "client", required: true }],
|
|
13
|
+
handler: connectCommand,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: "disconnect",
|
|
17
|
+
description: "Disconnect skills from an AI client (claude, zed)",
|
|
18
|
+
group: "system",
|
|
19
|
+
args: [{ name: "client", required: true }],
|
|
20
|
+
handler: disconnectCommand,
|
|
21
|
+
},
|
|
22
|
+
];
|
|
6
23
|
const MCP_SERVER_KEY = "spm";
|
|
7
24
|
const JSONC_MODIFY_OPTIONS = {
|
|
8
25
|
formattingOptions: { tabSize: 2, insertSpaces: true },
|
|
@@ -56,15 +73,14 @@ export async function connectCommand(client) {
|
|
|
56
73
|
const clients = getClients();
|
|
57
74
|
const config = clients[client];
|
|
58
75
|
if (!config) {
|
|
59
|
-
|
|
60
|
-
process.exit(1);
|
|
76
|
+
exitError(`Unknown client "${client}". Supported: ${Object.keys(clients).join(", ")}`);
|
|
61
77
|
}
|
|
62
78
|
let content = await readRawConfig(config.configPath);
|
|
63
79
|
const data = parse(content);
|
|
64
80
|
const section = data[config.serverSection] ?? {};
|
|
65
81
|
if (section[MCP_SERVER_KEY]) {
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
log.info(`Already connected to ${config.name}.`);
|
|
83
|
+
log.message(`Config: ${config.configPath}`);
|
|
68
84
|
return;
|
|
69
85
|
}
|
|
70
86
|
const serverValue = {
|
|
@@ -74,30 +90,29 @@ export async function connectCommand(client) {
|
|
|
74
90
|
const edits = modify(content, [config.serverSection, MCP_SERVER_KEY], serverValue, JSONC_MODIFY_OPTIONS);
|
|
75
91
|
content = applyEdits(content, edits);
|
|
76
92
|
await writeRawConfig(config.configPath, content);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
log.success(`Connected to ${config.name}.`);
|
|
94
|
+
log.message(`Config: ${config.configPath}`);
|
|
95
|
+
log.info(`Restart ${config.name} to activate.`);
|
|
80
96
|
}
|
|
81
97
|
export async function disconnectCommand(client) {
|
|
82
98
|
const clients = getClients();
|
|
83
99
|
const config = clients[client];
|
|
84
100
|
if (!config) {
|
|
85
|
-
|
|
86
|
-
process.exit(1);
|
|
101
|
+
exitError(`Unknown client "${client}". Supported: ${Object.keys(clients).join(", ")}`);
|
|
87
102
|
}
|
|
88
103
|
let content = await readRawConfig(config.configPath);
|
|
89
104
|
const data = parse(content);
|
|
90
105
|
const section = data[config.serverSection] ?? {};
|
|
91
106
|
if (!section[MCP_SERVER_KEY]) {
|
|
92
|
-
|
|
107
|
+
log.info(`Not connected to ${config.name}.`);
|
|
93
108
|
return;
|
|
94
109
|
}
|
|
95
110
|
const edits = modify(content, [config.serverSection, MCP_SERVER_KEY], undefined, // undefined = remove the key
|
|
96
111
|
JSONC_MODIFY_OPTIONS);
|
|
97
112
|
content = applyEdits(content, edits);
|
|
98
113
|
await writeRawConfig(config.configPath, content);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
114
|
+
log.success(`Disconnected from ${config.name}.`);
|
|
115
|
+
log.message(`Config: ${config.configPath}`);
|
|
116
|
+
log.info(`Restart ${config.name} to apply.`);
|
|
102
117
|
}
|
|
103
118
|
//# sourceMappingURL=connect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/cli/commands/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAA4B,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/cli/commands/connect.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/convert.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/convert.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,OAAO,EAAE,UAYrB,CAAC;AAEF,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAsMD,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
|