@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 +210 -11
- package/dist/src/bin/skilly.js +5 -0
- package/dist/src/lib/launcher.js +62 -0
- package/dist/src/lib/targets.js +90 -0
- package/package.json +6 -5
- package/vendor/aarch64-apple-darwin/skilly +0 -0
- package/vendor/x86_64-apple-darwin/skilly +0 -0
- package/vendor/x86_64-pc-windows-msvc/skilly.exe +0 -0
- package/vendor/x86_64-unknown-linux-gnu/skilly +0 -0
package/README.md
CHANGED
|
@@ -1,20 +1,219 @@
|
|
|
1
|
-
#
|
|
1
|
+
# skilly
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Manage [Agent Skills](https://agentskills.io/specification) from the command line
|
|
4
|
+
or Python.
|
|
5
5
|
|
|
6
|
-
|
|
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
|
-
|
|
13
|
-
|
|
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
|
-
##
|
|
217
|
+
## License
|
|
16
218
|
|
|
17
|
-
|
|
18
|
-
- macOS x64
|
|
19
|
-
- Linux x64 (glibc)
|
|
20
|
-
- Windows x64
|
|
219
|
+
[MIT](LICENSE)
|
|
@@ -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.
|
|
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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|