skill-forger 0.1.0 โ 0.1.2
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 +28 -11
- package/dist/cli.mjs +3 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# โ๏ธ skill-forger
|
|
2
2
|
|
|
3
3
|
Manage project Agent [skills](https://skills.sh/) from `skills.json`. Uses [`skills`](https://github.com/vercel-labs/skills) CLI under the hood.
|
|
4
4
|
|
|
5
|
+
The `sf` shorthand is also available:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx sf add vercel-labs/skills
|
|
9
|
+
```
|
|
10
|
+
|
|
5
11
|
## Usage
|
|
6
12
|
|
|
7
13
|
**Install all skills from `skills.json`:**
|
|
@@ -26,7 +32,11 @@ npx skill-forger add anthropics/skills:skill-creator
|
|
|
26
32
|
<img src="./assets/add.svg" alt="Install preview">
|
|
27
33
|
</p>
|
|
28
34
|
|
|
29
|
-
This creates a `skills.json` file:
|
|
35
|
+
This creates a `skills.json` file that you commit to your repo โ so your whole team shares the same skills:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
git add skills.json
|
|
39
|
+
```
|
|
30
40
|
|
|
31
41
|
```json
|
|
32
42
|
{
|
|
@@ -117,9 +127,22 @@ npx skill-forger install --global
|
|
|
117
127
|
npx skill-forger install --agent claude-code --agent cursor
|
|
118
128
|
```
|
|
119
129
|
|
|
120
|
-
|
|
130
|
+
### Supported Agents
|
|
131
|
+
|
|
132
|
+
skill-forger passes the `--agent` flag to the underlying [skills CLI](https://github.com/vercel-labs/skills). Supported agents include:
|
|
121
133
|
|
|
122
|
-
|
|
134
|
+
- `claude-code` (default)
|
|
135
|
+
- `cursor`
|
|
136
|
+
- `codex`
|
|
137
|
+
- `github-copilot`
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
# Install for a specific agent
|
|
141
|
+
npx skill-forger install --agent cursor
|
|
142
|
+
|
|
143
|
+
# Install for multiple agents
|
|
144
|
+
npx skill-forger install --agent claude-code --agent cursor
|
|
145
|
+
```
|
|
123
146
|
|
|
124
147
|
<details>
|
|
125
148
|
|
|
@@ -132,12 +155,6 @@ npx skill-forger install --agent claude-code --agent cursor
|
|
|
132
155
|
|
|
133
156
|
</details>
|
|
134
157
|
|
|
135
|
-
## Alternatives
|
|
136
|
-
|
|
137
|
-
- Proposal PR for adding `skill-lock.json` ([vercel-labs/skills#234](https://github.com/vercel-labs/skills/pull/234))
|
|
138
|
-
- Proposal PR for adding `.skills` ([vercel-labs/skills#134](https://github.com/vercel-labs/skills/pull/134))
|
|
139
|
-
- [hairyf/skills-manifest](https://github.com/hairyf/skills-manifest)
|
|
140
|
-
|
|
141
158
|
## License
|
|
142
159
|
|
|
143
|
-
Published under the [MIT](https://github.com/
|
|
160
|
+
Published under the [MIT](https://github.com/marcm8793/skill-forger/blob/main/LICENSE) license ๐ฅ.
|
package/dist/cli.mjs
CHANGED
|
@@ -103,41 +103,6 @@ const c = {
|
|
|
103
103
|
cyan: code(36)
|
|
104
104
|
};
|
|
105
105
|
//#endregion
|
|
106
|
-
//#region src/utils/gitignore.ts
|
|
107
|
-
function findGitignore(cwd = process.cwd()) {
|
|
108
|
-
let dir = resolve(cwd);
|
|
109
|
-
const root = dirname(dir);
|
|
110
|
-
while (dir !== root) {
|
|
111
|
-
const candidate = join(dir, ".gitignore");
|
|
112
|
-
if (existsSync(candidate)) return candidate;
|
|
113
|
-
const parent = dirname(dir);
|
|
114
|
-
if (parent === dir) break;
|
|
115
|
-
dir = parent;
|
|
116
|
-
}
|
|
117
|
-
const rootCandidate = join(dir, ".gitignore");
|
|
118
|
-
if (existsSync(rootCandidate)) return rootCandidate;
|
|
119
|
-
}
|
|
120
|
-
async function addGitignoreEntry(entries, options = {}) {
|
|
121
|
-
const { cwd, createIfNotExists = true } = options;
|
|
122
|
-
const resolvedCwd = resolve(cwd ?? process.cwd());
|
|
123
|
-
const uniqueEntries = [...new Set((Array.isArray(entries) ? entries : [entries]).map((e) => e.trim()).filter(Boolean))];
|
|
124
|
-
if (uniqueEntries.length === 0) return;
|
|
125
|
-
let gitignorePath = findGitignore(resolvedCwd);
|
|
126
|
-
if (!gitignorePath) {
|
|
127
|
-
if (!createIfNotExists) return;
|
|
128
|
-
gitignorePath = join(resolvedCwd, ".gitignore");
|
|
129
|
-
await writeFile(gitignorePath, `${uniqueEntries.join("\n")}\n`, "utf8");
|
|
130
|
-
return gitignorePath;
|
|
131
|
-
}
|
|
132
|
-
const content = await readFile(gitignorePath, "utf8");
|
|
133
|
-
const existingLines = new Set(content.split("\n").map((line) => line.trim()));
|
|
134
|
-
const newEntries = uniqueEntries.filter((entry) => !existingLines.has(entry));
|
|
135
|
-
if (newEntries.length === 0) return gitignorePath;
|
|
136
|
-
const newContent = `${content}${content.endsWith("\n") ? "" : "\n"}${newEntries.join("\n")}\n`;
|
|
137
|
-
await writeFile(gitignorePath, newContent, "utf8");
|
|
138
|
-
return gitignorePath;
|
|
139
|
-
}
|
|
140
|
-
//#endregion
|
|
141
106
|
//#region src/skills.ts
|
|
142
107
|
let _skillsBinaryCache = null;
|
|
143
108
|
function findSkillsBinary(options) {
|
|
@@ -156,12 +121,11 @@ function findSkillsBinary(options) {
|
|
|
156
121
|
_skillsBinaryCache = void 0;
|
|
157
122
|
}
|
|
158
123
|
async function installSkills(options = {}) {
|
|
159
|
-
const { config
|
|
160
|
-
await addGitignoreEntry(".agents", { cwd: dirname(configPath) });
|
|
124
|
+
const { config } = await readSkillsConfig({ cwd: options.cwd });
|
|
161
125
|
const total = config.skills.length;
|
|
162
126
|
const totalStart = performance.now();
|
|
163
127
|
const globalPrefix = options.global ? `${c.magenta}[ global ]${c.reset} ` : "";
|
|
164
|
-
console.log(`${globalPrefix}
|
|
128
|
+
console.log(`${globalPrefix}๐ ๏ธ Installing ${total} skill${total === 1 ? "" : "s"}...\n`);
|
|
165
129
|
let i = 0;
|
|
166
130
|
for (const entry of config.skills) {
|
|
167
131
|
i++;
|
|
@@ -171,7 +135,7 @@ async function installSkills(options = {}) {
|
|
|
171
135
|
});
|
|
172
136
|
}
|
|
173
137
|
const totalDuration = formatDuration(performance.now() - totalStart);
|
|
174
|
-
console.log(`${globalPrefix}
|
|
138
|
+
console.log(`${globalPrefix}๐ฅ Done! ${total} skill${total === 1 ? "" : "s"} installed in ${c.green}${totalDuration}${c.reset}.`);
|
|
175
139
|
}
|
|
176
140
|
async function installSkillSource(entry, options) {
|
|
177
141
|
const skillsBinary = findSkillsBinary();
|