@xelandernt/skilly 0.0.22 → 0.0.25

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 CHANGED
@@ -1,20 +1,219 @@
1
- # @xelandernt/skilly
1
+ # skilly
2
2
 
3
- Run the native `skilly` CLI through `npx` without a separate TypeScript or
4
- JavaScript CLI implementation.
3
+ Manage [Agent Skills](https://agentskills.io/specification) from the command line
4
+ or Python.
5
5
 
6
- ## Usage
6
+ `skilly` creates specification-compliant skills, installs skills from GitHub or
7
+ Python dependencies, and keeps managed skills up to date.
8
+
9
+ ## Installation
10
+
11
+ Run the CLI without installing it:
7
12
 
8
13
  ```shell
14
+ uvx skilly --help
9
15
  npx @xelandernt/skilly --help
10
16
  ```
11
17
 
12
- The package preserves the native CLI's stdio behavior so interactive TUI flows
13
- and non-interactive automation keep using the same Rust implementation.
18
+ Or install the CLI and Python package:
19
+
20
+ ```shell
21
+ pip install skilly
22
+ ```
23
+
24
+ The npm package ships the same native Rust CLI behind the executable name
25
+ `skilly`. The current npm support matrix is macOS arm64/x64, Linux x64
26
+ (glibc), and Windows x64.
27
+
28
+ ## Quick Start
29
+
30
+ Scan the current Python project for skills shipped by its dependencies:
31
+
32
+ ```shell
33
+ uvx skilly scan
34
+ ```
35
+
36
+ Download a skill from GitHub:
37
+
38
+ ```shell
39
+ uvx skilly download https://github.com/example/project/tree/main/skills/code-review
40
+ ```
41
+
42
+ Inspect installed skills:
43
+
44
+ ```shell
45
+ uvx skilly list
46
+ ```
47
+
48
+ ## CLI Commands
49
+
50
+ | Command | Purpose |
51
+ | --- | --- |
52
+ | `uvx skilly scan` | Find skills provided by the project's Python dependencies. |
53
+ | `uvx skilly download <github-url>` | Install one or more skills from GitHub. |
54
+ | `uvx skilly list` | Browse, update, or remove installed skills. |
55
+ | `uvx skilly update` | Preview available updates; add `--yes` to apply all updates. |
56
+ | `uvx skilly remove <name>` | Remove an installed skill by directory name. |
57
+ | `uvx skilly skillsmp search <query>` | Search SkillsMP and install a selected result. |
58
+ | `uvx skilly create` | Create a valid skill through a terminal wizard or explicit options. |
59
+
60
+ Use `uvx skilly <command> --help` for all options.
61
+
62
+ ### Create Skills
63
+
64
+ Interactive terminals open a full-screen editor for the required and optional
65
+ Agent Skills fields. `Ctrl+S` creates the skill, `Ctrl+X` cancels, and `Enter`
66
+ in the multi-line editors inserts real line breaks.
67
+
68
+ For scripts and automation, provide the required name and description:
69
+
70
+ ```shell
71
+ uvx skilly create deployment-checks \
72
+ --description "Validate deployment readiness before a production release." \
73
+ --instructions "# Instructions
74
+
75
+ Run the deployment checklist and report blockers." \
76
+ --metadata owner=platform \
77
+ --with-scripts \
78
+ --yes
79
+ ```
80
+
81
+ Existing skills are rejected by default. Use `--overwrite` to replace one
82
+ atomically. See `uvx skilly create --help` for the complete contract.
83
+
84
+ ### Install Dependency Skills
85
+
86
+ `uvx skilly scan` reads `pyproject.toml` and the project's `.venv`, then offers
87
+ skills shipped by direct, development, and optional dependencies:
88
+
89
+ ```shell
90
+ uvx skilly scan
91
+ ```
92
+
93
+ Exclude dependency categories when needed:
94
+
95
+ ```shell
96
+ uvx skilly scan --no-dependency-groups --no-optional-dependencies
97
+ ```
98
+
99
+ ### Install GitHub Skills
100
+
101
+ ```shell
102
+ uvx skilly download https://github.com/example/project
103
+ ```
104
+
105
+ When a repository contains multiple skills, select one or install all:
106
+
107
+ ```shell
108
+ uvx skilly download https://github.com/example/project --skill-name code-review
109
+ uvx skilly download https://github.com/example/project --all
110
+ ```
111
+
112
+ ### Destinations
113
+
114
+ Management commands accept the same destination options:
115
+
116
+ | Option | Destination |
117
+ | --- | --- |
118
+ | `--local` | Project-local skills directory. |
119
+ | `--global` | User-global skills directory. |
120
+ | `--claude` | Claude skills directory. |
121
+ | `--codex` | Codex skills directory. |
122
+ | `--copilot` | GitHub Copilot skills directory. |
123
+ | `--directory <path>` | Explicit directory; overrides all other destination options. |
124
+
125
+ Without destination options, `skilly` uses `.agents/skills`.
126
+
127
+ ```shell
128
+ uvx skilly download https://github.com/example/project --global --codex
129
+ uvx skilly list --local --claude
130
+ ```
131
+
132
+ ### GitHub Authentication
133
+
134
+ Authenticated requests have higher GitHub API rate limits. Use the first
135
+ available token:
136
+
137
+ ```shell
138
+ export SKILLY_GITHUB_TOKEN=ghp_your_token
139
+ # or GITHUB_TOKEN / GH_TOKEN
140
+ ```
141
+
142
+ GitHub-fetching commands also accept `--github-token`.
143
+
144
+ ## Python API
145
+
146
+ `SkillRepository` is the stateful management interface. Bind a destination,
147
+ project settings, or custom filesystem once and reuse it:
148
+
149
+ ```python
150
+ from pathlib import Path
151
+
152
+ from skilly import ProjectSettings, Skill, SkillRepository
153
+
154
+ repository = SkillRepository(
155
+ directory=Path(".agents/skills"),
156
+ project=ProjectSettings(include_dependency_groups=True),
157
+ )
158
+
159
+ created = repository.install(
160
+ Skill(
161
+ name="code-review",
162
+ description="Review code for correctness and maintainability.",
163
+ content="# Instructions\n\nReview the proposed change.",
164
+ )
165
+ )
166
+
167
+ for match in repository.scan_project():
168
+ print(match.available.name, match.status)
169
+ ```
170
+
171
+ Use focused discovery functions when no repository state is needed:
172
+
173
+ ```python
174
+ from skilly import discover_installed_skills, discover_venv_skills
175
+
176
+ installed = discover_installed_skills()
177
+ dependency_skills = discover_venv_skills()
178
+ ```
179
+
180
+ The SkillsMP client returns typed results directly. Async methods expose the
181
+ same result types without blocking the event loop:
182
+
183
+ ```python
184
+ from skilly.skillsmp import ClientSettings, SkillsMp, SkillsMpSearchQuery
185
+
186
+ client = SkillsMp(settings=ClientSettings(base_url="https://skillsmp.com/api/v1"))
187
+ result = client.search(SkillsMpSearchQuery(text="python", limit=5))
188
+ print(result.data.skills[0].github_url)
189
+ ```
190
+
191
+ ## Development
192
+
193
+ Install development dependencies and the editable extension:
194
+
195
+ ```shell
196
+ just install
197
+ ```
198
+
199
+ Run the required quality gates:
200
+
201
+ ```shell
202
+ just lint
203
+ just test
204
+ just typecheck
205
+ ```
206
+
207
+ The TypeScript launcher package also has dedicated helpers:
208
+
209
+ ```shell
210
+ just ts::build
211
+ just ts::test
212
+ just ts::typecheck
213
+ just ts::smoke
214
+ just ts::publish-dry-run
215
+ ```
14
216
 
15
- ## Supported targets
217
+ ## License
16
218
 
17
- - macOS arm64
18
- - macOS x64
19
- - Linux x64 (glibc)
20
- - Windows x64
219
+ [MIT](LICENSE)
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const launcher_1 = require("../lib/launcher");
5
+ (0, launcher_1.run)(process.argv.slice(2));
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveBinaryPath = resolveBinaryPath;
7
+ exports.ensureBinaryExists = ensureBinaryExists;
8
+ exports.launch = launch;
9
+ exports.run = run;
10
+ const node_fs_1 = __importDefault(require("node:fs"));
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const node_child_process_1 = require("node:child_process");
13
+ const targets_1 = require("./targets");
14
+ function resolveBinaryPath(options = {}) {
15
+ const rootDir = options.rootDir ?? node_path_1.default.resolve(__dirname, "..", "..", "..");
16
+ const processLike = options.processLike ?? process;
17
+ const target = (0, targets_1.resolveTarget)(processLike);
18
+ return node_path_1.default.join(rootDir, (0, targets_1.vendorRelativePath)(target));
19
+ }
20
+ function ensureBinaryExists(binaryPath) {
21
+ if (node_fs_1.default.existsSync(binaryPath)) {
22
+ return;
23
+ }
24
+ const error = new Error(`No packaged skilly binary was found at ${binaryPath}. Reinstall ${targets_1.PACKAGE_NAME} or rebuild the npm package with staged native binaries.`);
25
+ error.code = "ERR_MISSING_BINARY";
26
+ throw error;
27
+ }
28
+ function launch(argv, options = {}) {
29
+ const processLike = options.processLike ?? process;
30
+ const spawnImpl = options.spawnImpl ?? node_child_process_1.spawn;
31
+ const binaryPath = resolveBinaryPath(options);
32
+ ensureBinaryExists(binaryPath);
33
+ const child = spawnImpl(binaryPath, argv, {
34
+ env: processLike.env,
35
+ stdio: "inherit",
36
+ windowsHide: false
37
+ });
38
+ return { child, binaryPath };
39
+ }
40
+ function writeError(processLike, message) {
41
+ if (processLike.stderr && typeof processLike.stderr.write === "function") {
42
+ processLike.stderr.write(`${message}\n`);
43
+ return;
44
+ }
45
+ console.error(message);
46
+ }
47
+ function run(argv, options = {}) {
48
+ const processLike = options.processLike ?? process;
49
+ const { child, binaryPath } = launch(argv, options);
50
+ child.once("error", (error) => {
51
+ writeError(processLike, `Failed to launch skilly from ${binaryPath}: ${error.message}`);
52
+ processLike.exit(1);
53
+ });
54
+ child.once("close", (code, signal) => {
55
+ if (signal) {
56
+ processLike.kill(processLike.pid, signal);
57
+ return;
58
+ }
59
+ processLike.exit(code ?? 1);
60
+ });
61
+ return child;
62
+ }
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TARGETS = exports.PACKAGE_NAME = void 0;
7
+ exports.supportedTargetLabels = supportedTargetLabels;
8
+ exports.detectLinuxLibc = detectLinuxLibc;
9
+ exports.executableName = executableName;
10
+ exports.vendorRelativePath = vendorRelativePath;
11
+ exports.unsupportedPlatformError = unsupportedPlatformError;
12
+ exports.resolveTarget = resolveTarget;
13
+ const node_path_1 = __importDefault(require("node:path"));
14
+ exports.PACKAGE_NAME = "@xelandernt/skilly";
15
+ exports.TARGETS = [
16
+ {
17
+ platform: "darwin",
18
+ arch: "arm64",
19
+ triple: "aarch64-apple-darwin",
20
+ label: "macOS arm64"
21
+ },
22
+ {
23
+ platform: "darwin",
24
+ arch: "x64",
25
+ triple: "x86_64-apple-darwin",
26
+ label: "macOS x64"
27
+ },
28
+ {
29
+ platform: "linux",
30
+ arch: "x64",
31
+ libc: "glibc",
32
+ triple: "x86_64-unknown-linux-gnu",
33
+ label: "Linux x64 (glibc)"
34
+ },
35
+ {
36
+ platform: "win32",
37
+ arch: "x64",
38
+ triple: "x86_64-pc-windows-msvc",
39
+ label: "Windows x64"
40
+ }
41
+ ];
42
+ function supportedTargetLabels() {
43
+ return exports.TARGETS.map((target) => target.label);
44
+ }
45
+ function detectLinuxLibc(processLike = process) {
46
+ if (processLike.platform !== "linux") {
47
+ return null;
48
+ }
49
+ const report = processLike.report;
50
+ if (!report || typeof report.getReport !== "function") {
51
+ return "unknown";
52
+ }
53
+ const glibcVersionRuntime = report.getReport()?.header?.glibcVersionRuntime;
54
+ return glibcVersionRuntime ? "glibc" : "musl";
55
+ }
56
+ function executableName(target) {
57
+ return target.platform === "win32" ? "skilly.exe" : "skilly";
58
+ }
59
+ function vendorRelativePath(target) {
60
+ return node_path_1.default.posix.join("vendor", target.triple, executableName(target));
61
+ }
62
+ function unsupportedPlatformError(processLike = process) {
63
+ const libc = detectLinuxLibc(processLike);
64
+ const details = libc
65
+ ? `${processLike.platform} ${processLike.arch} (${libc})`
66
+ : `${processLike.platform} ${processLike.arch}`;
67
+ const supported = supportedTargetLabels().join(", ");
68
+ const hint = processLike.platform === "linux" && libc !== "glibc"
69
+ ? "Linux builds currently require glibc."
70
+ : "No packaged binary matches this platform.";
71
+ const error = new Error(`Unsupported platform for ${exports.PACKAGE_NAME}: ${details}. Supported targets: ${supported}. ${hint}`);
72
+ error.code = "ERR_UNSUPPORTED_PLATFORM";
73
+ return error;
74
+ }
75
+ function resolveTarget(processLike = process) {
76
+ const libc = detectLinuxLibc(processLike);
77
+ const target = exports.TARGETS.find((candidate) => {
78
+ if (candidate.platform !== processLike.platform || candidate.arch !== processLike.arch) {
79
+ return false;
80
+ }
81
+ if (candidate.platform !== "linux") {
82
+ return true;
83
+ }
84
+ return candidate.libc === libc;
85
+ });
86
+ if (!target) {
87
+ throw unsupportedPlatformError(processLike);
88
+ }
89
+ return target;
90
+ }
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@xelandernt/skilly",
3
- "version": "0.0.22",
3
+ "version": "0.0.25",
4
4
  "description": "Native npm launcher for the skilly CLI.",
5
5
  "license": "MIT",
6
6
  "bin": {
7
- "skilly": "dist/bin/skilly.js"
7
+ "skilly": "dist/src/bin/skilly.js"
8
8
  },
9
9
  "type": "commonjs",
10
10
  "files": [
11
11
  "README.md",
12
- "dist/bin",
13
- "dist/lib",
12
+ "dist/src/bin",
13
+ "dist/src/lib",
14
14
  "vendor"
15
15
  ],
16
16
  "engines": {
@@ -22,9 +22,10 @@
22
22
  "scripts": {
23
23
  "build": "tsc -p tsconfig.json",
24
24
  "stage-local-binary": "npm run build && node ./dist/scripts/stage-local-binary.js",
25
+ "sync-readme": "node ./dist/scripts/sync-readme.js",
25
26
  "test": "npm run build && node --test ./dist/test/targets.test.js ./dist/test/launcher.test.js",
26
27
  "typecheck": "tsc --noEmit -p tsconfig.json",
27
- "prepack": "npm run build"
28
+ "prepack": "npm run build && npm run sync-readme"
28
29
  },
29
30
  "devDependencies": {
30
31
  "@types/node": "^22.16.5",
Binary file