skill-tags 1.2.0 → 1.3.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 +96 -36
- package/bin/categories.js +6 -44
- package/bin/postinstall.js +11 -5
- package/bin/setup.js +218 -0
- package/bin/skill-tags.js +20 -80
- package/bin/st-skills.js +36 -0
- package/package.json +3 -2
- package/sync.sh +84 -35
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ If you're interested in contributing to Cursor Kits, please let me know!
|
|
|
16
16
|
- [Agent Setup Prompt](#agent-setup-prompt)
|
|
17
17
|
- [Install Options](#install-options)
|
|
18
18
|
- [How It Works](#how-it-works)
|
|
19
|
+
- [Project-Level Install](#project-level-install)
|
|
19
20
|
- [CLI Reference](#cli-reference)
|
|
20
21
|
- [Manual Sync](#manual-sync)
|
|
21
22
|
- [Skill Sources Scanned](#skill-sources-scanned)
|
|
@@ -29,23 +30,38 @@ If you're interested in contributing to Cursor Kits, please let me know!
|
|
|
29
30
|
|
|
30
31
|
## Quick Start
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
# Install (global, recommended)
|
|
34
|
-
npm install -g skill-tags
|
|
33
|
+
### Global (recommended for most users)
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
skill-tags --setup
|
|
38
|
-
|
|
35
|
+
1. **Install:** `npm install skill-tags -g`
|
|
36
|
+
2. **Setup:** `skill-tags --setup` → choose **Global** → `source ~/.zshrc`
|
|
37
|
+
3. **Sync:** `skill-tags` (generates the command file)
|
|
38
|
+
4. **Use:** Reference `@skill-tags.md` in any Cursor chat
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
```bash
|
|
41
|
+
npm install skill-tags -g
|
|
42
|
+
skill-tags --setup # choose: Global
|
|
43
|
+
source ~/.zshrc
|
|
41
44
|
skill-tags
|
|
42
45
|
```
|
|
43
46
|
|
|
47
|
+
### Project-level
|
|
48
|
+
|
|
49
|
+
1. **Install:** `npm install skill-tags --save-dev`
|
|
50
|
+
2. **Setup:** `npx skill-tags --setup` → choose **Project**
|
|
51
|
+
3. **Use:** Reference `@project-skill-tags.md` in Cursor chat
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm install skill-tags --save-dev
|
|
55
|
+
npx skill-tags --setup # choose: Project — adds "skills" script to package.json
|
|
56
|
+
|
|
57
|
+
npm run skills add owner/repo/skill-name # adds skill + auto-syncs
|
|
58
|
+
```
|
|
59
|
+
|
|
44
60
|
## Usage
|
|
45
61
|
|
|
46
62
|
In any Cursor chat, attach the full index of your skills by referencing the generated command file:
|
|
47
63
|
|
|
48
|
-
- `@skill-tags.md`
|
|
64
|
+
- `@skill-tags.md` (global) or `@project-skill-tags.md` (local, from `skill-tags --local`)
|
|
49
65
|
|
|
50
66
|
Example:
|
|
51
67
|
|
|
@@ -90,17 +106,13 @@ Copy and paste this into your Cursor agent to autoconfigure skill-tags:
|
|
|
90
106
|
```text
|
|
91
107
|
Install and configure the `skill-tags` package (npm: https://www.npmjs.com/package/skill-tags, github: https://github.com/steve-piece/skill-tags) for me.
|
|
92
108
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
Once confirmed, use a terminal that runs outside the sandbox with full permissions to avoid permission errors during install. In Cursor, this means using a non-sandboxed terminal session if available (required_permissions: ["all"] if running via agent shell tools).
|
|
109
|
+
Use a terminal that runs outside the sandbox with full permissions to avoid permission errors during install. In Cursor, this means using a non-sandboxed terminal session if available (required_permissions: ["all"] if running via agent shell tools).
|
|
96
110
|
|
|
97
111
|
Steps to perform:
|
|
98
|
-
1. Install the package
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
3. Run `skill-tags` to perform an initial sync of all installed skills
|
|
103
|
-
4. Source my shell rc file or instruct me to do so manually
|
|
112
|
+
1. Install the package: `npm install skill-tags -g`
|
|
113
|
+
2. Run `skill-tags --setup` — when prompted, choose Global and Auto (recommended)
|
|
114
|
+
3. Source my shell rc file or instruct me to do so manually
|
|
115
|
+
4. Run `skill-tags` to perform an initial sync of all installed skills
|
|
104
116
|
|
|
105
117
|
When complete, output a summary that includes:
|
|
106
118
|
- Where the command file was generated (~/.cursor/commands/skill-tags.md)
|
|
@@ -108,6 +120,7 @@ When complete, output a summary that includes:
|
|
|
108
120
|
- How the auto-trigger works: `skills add/remove <pkg>` now automatically syncs after every install/removal
|
|
109
121
|
- How to manually re-sync at any time: run `skill-tags`
|
|
110
122
|
- The total number of skills that were indexed
|
|
123
|
+
- (Optional) To create category-specific indexes for more focused context, run `skill-tags --categories`
|
|
111
124
|
```
|
|
112
125
|
|
|
113
126
|
</details>
|
|
@@ -116,24 +129,27 @@ When complete, output a summary that includes:
|
|
|
116
129
|
|
|
117
130
|
## Install Options
|
|
118
131
|
|
|
119
|
-
###
|
|
132
|
+
### Global install (npm)
|
|
120
133
|
|
|
121
134
|
```bash
|
|
122
|
-
|
|
123
|
-
|
|
135
|
+
npm install skill-tags -g
|
|
136
|
+
skill-tags --setup # choose: Global
|
|
137
|
+
source ~/.zshrc
|
|
138
|
+
```
|
|
124
139
|
|
|
125
|
-
|
|
126
|
-
npx skill-tags
|
|
140
|
+
### Project install (npm)
|
|
127
141
|
|
|
128
|
-
|
|
129
|
-
npm install --save-dev
|
|
142
|
+
```bash
|
|
143
|
+
npm install skill-tags --save-dev
|
|
144
|
+
npx skill-tags --setup # choose: Project
|
|
130
145
|
```
|
|
131
146
|
|
|
132
|
-
|
|
147
|
+
Adds `"skills": "st-skills"` to `package.json`. Use `npm run skills add <pkg>` to add project skills — auto-syncs `.cursor/commands/project-skill-tags.md` on every change.
|
|
148
|
+
|
|
149
|
+
### One-off run (no install)
|
|
133
150
|
|
|
134
151
|
```bash
|
|
135
|
-
skill-tags
|
|
136
|
-
source ~/.zshrc
|
|
152
|
+
npx skill-tags
|
|
137
153
|
```
|
|
138
154
|
|
|
139
155
|
### Install via curl
|
|
@@ -150,30 +166,74 @@ source ~/.zshrc # or ~/.bash_profile / ~/.bashrc
|
|
|
150
166
|
|
|
151
167
|
## How It Works
|
|
152
168
|
|
|
153
|
-
After setup, the `skills` command wraps `npx skills` and automatically runs a sync after every `skills add` or `skills remove`:
|
|
169
|
+
After global setup, the `skills` command wraps `npx skills` and automatically runs a sync after every `skills add` or `skills remove`:
|
|
154
170
|
|
|
155
171
|
```bash
|
|
156
172
|
# Install (or remove) a skill — sync runs automatically
|
|
157
173
|
skills add vercel-labs/agent-skills/vercel-react-best-practices
|
|
158
174
|
|
|
159
|
-
# The
|
|
175
|
+
# The command file is updated:
|
|
160
176
|
# ~/.cursor/commands/skill-tags.md
|
|
161
177
|
|
|
162
178
|
# Use it in Cursor chat:
|
|
163
179
|
# @skill-tags.md
|
|
164
180
|
```
|
|
165
181
|
|
|
182
|
+
## Project-Level Install
|
|
183
|
+
|
|
184
|
+
Install skill-tags as a dev dependency to manage project-specific skills without touching your global shell config. The `--setup` wizard adds a `"skills"` npm script backed by the bundled `st-skills` binary.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
npm install skill-tags --save-dev
|
|
188
|
+
npx skill-tags --setup # choose: Project
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
After setup, `package.json` will include:
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
"scripts": {
|
|
195
|
+
"skills": "st-skills"
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Use `npm run skills` to add, remove, or update project skills:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
npm run skills add owner/repo/skill-name # adds skill + auto-syncs
|
|
203
|
+
npm run skills remove owner/repo/skill-name # removes skill + auto-syncs
|
|
204
|
+
npm run skills update owner/repo/skill-name # updates skill + auto-syncs
|
|
205
|
+
|
|
206
|
+
# Manual re-sync:
|
|
207
|
+
skill-tags --local
|
|
208
|
+
|
|
209
|
+
# Use in Cursor chat:
|
|
210
|
+
# @project-skill-tags.md
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The `st-skills` binary (from this package) wraps `npx skills`, then automatically runs `skill-tags --local` on every successful `add`, `remove`, or `update`, writing the index to `.cursor/commands/project-skill-tags.md`.
|
|
214
|
+
|
|
166
215
|
## CLI Reference
|
|
167
216
|
|
|
168
217
|
```bash
|
|
169
|
-
skill-tags
|
|
170
|
-
skill-tags --categories
|
|
171
|
-
skill-tags --setup
|
|
172
|
-
skill-tags --global
|
|
173
|
-
skill-tags --
|
|
174
|
-
skill-tags --
|
|
218
|
+
skill-tags # sync all skills, generate/update the command file
|
|
219
|
+
skill-tags --categories # open interactive category wizard (CRUD)
|
|
220
|
+
skill-tags --setup # interactive setup: choose Global (shell profile) or Project (package.json)
|
|
221
|
+
skill-tags --global # skip local skills (.agents/skills in CWD); scan global sources only
|
|
222
|
+
skill-tags --local # scan only .agents/skills in CWD; write to .cursor/commands/project-skill-tags.md
|
|
223
|
+
skill-tags --version # print version
|
|
224
|
+
skill-tags --help # show usage
|
|
175
225
|
```
|
|
176
226
|
|
|
227
|
+
### `st-skills` (project binary)
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
npm run skills add <pkg> # install a project skill + auto-sync
|
|
231
|
+
npm run skills remove <pkg> # remove a project skill + auto-sync
|
|
232
|
+
npm run skills update <pkg> # update a project skill + auto-sync
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
`st-skills` is registered in `package.json` by `skill-tags --setup` (local mode). It wraps `npx skills` and calls `skill-tags --local` after every mutating command.
|
|
236
|
+
|
|
177
237
|
## Manual Sync
|
|
178
238
|
|
|
179
239
|
Run at any time to regenerate the command file:
|
|
@@ -200,7 +260,7 @@ Skills are discovered from all of these locations automatically. When the same s
|
|
|
200
260
|
|
|
201
261
|
## Generated File Format
|
|
202
262
|
|
|
203
|
-
The `~/.cursor/commands/skill-tags.md`
|
|
263
|
+
The `~/.cursor/commands/skill-tags.md` (global) and `./.cursor/commands/project-skill-tags.md` (local) contain:
|
|
204
264
|
|
|
205
265
|
- An opening instruction for the agent to assess all skills and apply them autonomously.
|
|
206
266
|
- Instructions for the agent on how to plan with skills when in Plan Mode.
|
package/bin/categories.js
CHANGED
|
@@ -212,11 +212,6 @@ function toTitleCase(str) {
|
|
|
212
212
|
return str.replace(/[-_]/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
function truncate(str, len) {
|
|
216
|
-
if (!str || str.length <= len) return str || '';
|
|
217
|
-
return str.slice(0, len - 1) + '…';
|
|
218
|
-
}
|
|
219
|
-
|
|
220
215
|
// ─── Wizard actions ──────────────────────────────────────────────────────────
|
|
221
216
|
|
|
222
217
|
async function addCategories(skills, config) {
|
|
@@ -256,25 +251,9 @@ async function addCategories(skills, config) {
|
|
|
256
251
|
}
|
|
257
252
|
|
|
258
253
|
for (const cat of selected) {
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
return {
|
|
263
|
-
name: `${s.name}${hint}`,
|
|
264
|
-
value: s.name,
|
|
265
|
-
checked: !!match,
|
|
266
|
-
description: truncate(s.description, 60),
|
|
267
|
-
};
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
const selectedSkills = await checkbox({
|
|
271
|
-
message: `Select skills for "${cat}" (space to toggle)`,
|
|
272
|
-
choices: skillChoices,
|
|
273
|
-
pageSize: 15,
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
config[cat] = selectedSkills;
|
|
277
|
-
console.log(` ✓ ${toTitleCase(cat)}: ${selectedSkills.length} skill(s)\n`);
|
|
254
|
+
const matched = skills.filter(s => matchKeywords(s, cat));
|
|
255
|
+
config[cat] = matched.map(s => s.name);
|
|
256
|
+
console.log(` ✓ ${toTitleCase(cat)}: ${matched.length} skill(s) auto-assigned\n`);
|
|
278
257
|
}
|
|
279
258
|
}
|
|
280
259
|
|
|
@@ -293,26 +272,9 @@ async function editCategory(skills, config) {
|
|
|
293
272
|
})),
|
|
294
273
|
});
|
|
295
274
|
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const hint = match ? ` — ${match.reason}` : '';
|
|
300
|
-
return {
|
|
301
|
-
name: `${s.name}${hint}`,
|
|
302
|
-
value: s.name,
|
|
303
|
-
checked: currentSet.has(s.name),
|
|
304
|
-
description: truncate(s.description, 60),
|
|
305
|
-
};
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
const selectedSkills = await checkbox({
|
|
309
|
-
message: `Select skills for "${cat}" (space to toggle)`,
|
|
310
|
-
choices: skillChoices,
|
|
311
|
-
pageSize: 15,
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
config[cat] = selectedSkills;
|
|
315
|
-
console.log(` ✓ Updated ${toTitleCase(cat)}: ${selectedSkills.length} skill(s)\n`);
|
|
275
|
+
const matched = skills.filter(s => matchKeywords(s, cat));
|
|
276
|
+
config[cat] = matched.map(s => s.name);
|
|
277
|
+
console.log(` ✓ Re-generated ${toTitleCase(cat)}: ${matched.length} skill(s) auto-assigned\n`);
|
|
316
278
|
}
|
|
317
279
|
|
|
318
280
|
async function deleteCategory(config) {
|
package/bin/postinstall.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// bin/postinstall.js
|
|
3
|
-
// Runs automatically after `npm install
|
|
4
|
-
//
|
|
3
|
+
// Runs automatically after `npm install skill-tags`.
|
|
4
|
+
// Global installs: perform initial sync. Local installs: print setup guidance.
|
|
5
5
|
// Never throws — a failed postinstall should never break npm install.
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
@@ -15,12 +15,18 @@ if (process.platform === 'win32') {
|
|
|
15
15
|
process.exit(0);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (
|
|
18
|
+
const isGlobal = process.env.npm_config_global === 'true';
|
|
19
|
+
|
|
20
|
+
if (!isGlobal) {
|
|
21
|
+
// Project (local) install — print setup guidance and exit cleanly
|
|
22
|
+
console.log('\n skill-tags installed as a project dependency.');
|
|
23
|
+
console.log(' Run setup to add the "skills" npm script to your package.json:\n');
|
|
24
|
+
console.log(' npx skill-tags --setup\n');
|
|
21
25
|
process.exit(0);
|
|
22
26
|
}
|
|
23
27
|
|
|
28
|
+
// ─── Global install: run initial sync ────────────────────────────────────────
|
|
29
|
+
|
|
24
30
|
const syncScript = path.join(__dirname, '..', 'sync.sh');
|
|
25
31
|
|
|
26
32
|
if (!fs.existsSync(syncScript)) {
|
package/bin/setup.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// bin/setup.js
|
|
3
|
+
// Interactive setup wizard: global/project install mode + auto/manual sync preference.
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { spawnSync } = require('child_process');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
const HOME = os.homedir();
|
|
13
|
+
const SYNC_SCRIPT = path.join(__dirname, '..', 'sync.sh');
|
|
14
|
+
const WRAPPER_MARKER = '# ─── skill-tags / Cursor Skill Command Sync';
|
|
15
|
+
|
|
16
|
+
module.exports = async function runSetup() {
|
|
17
|
+
const { select, confirm } = require('@inquirer/prompts');
|
|
18
|
+
|
|
19
|
+
console.log('\n skill-tags: setup\n');
|
|
20
|
+
|
|
21
|
+
const isGlobal = process.env.npm_config_global === 'true';
|
|
22
|
+
|
|
23
|
+
const mode = await select({
|
|
24
|
+
message: 'How are you using skill-tags?',
|
|
25
|
+
choices: [
|
|
26
|
+
{
|
|
27
|
+
name: 'Global — add skills() wrapper to shell profile (recommended for most users)',
|
|
28
|
+
value: 'global',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'Project — add "skills" npm script to this project\'s package.json',
|
|
32
|
+
value: 'project',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
default: isGlobal ? 'global' : 'project',
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const syncMode = await select({
|
|
39
|
+
message: 'How should skill-tags sync?',
|
|
40
|
+
choices: [
|
|
41
|
+
{
|
|
42
|
+
name: 'Auto (recommended) — sync automatically whenever you add or remove a skill',
|
|
43
|
+
value: 'auto',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'Manual — run skill-tags yourself to sync when needed',
|
|
47
|
+
value: 'manual',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
default: 'auto',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (mode === 'global') {
|
|
54
|
+
await setupGlobal(confirm, syncMode);
|
|
55
|
+
} else {
|
|
56
|
+
await setupProject(confirm, syncMode);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// ─── Global setup ─────────────────────────────────────────────────────────────
|
|
61
|
+
|
|
62
|
+
async function setupGlobal(confirm, syncMode) {
|
|
63
|
+
const shellName = path.basename(process.env.SHELL || 'bash');
|
|
64
|
+
let rcFile;
|
|
65
|
+
if (shellName === 'zsh') rcFile = path.join(HOME, '.zshrc');
|
|
66
|
+
else if (process.platform === 'darwin') rcFile = path.join(HOME, '.bash_profile');
|
|
67
|
+
else rcFile = path.join(HOME, '.bashrc');
|
|
68
|
+
|
|
69
|
+
const displayRc = rcFile.replace(HOME, '~');
|
|
70
|
+
|
|
71
|
+
if (syncMode === 'manual') {
|
|
72
|
+
console.log('\n Manual sync selected.');
|
|
73
|
+
console.log(' Run skill-tags at any time to regenerate ~/.cursor/commands/skill-tags.md\n');
|
|
74
|
+
console.log(' Running initial sync...\n');
|
|
75
|
+
spawnSync('bash', [SYNC_SCRIPT], { stdio: 'inherit' });
|
|
76
|
+
console.log(`\n Done! Run skill-tags manually to re-sync.\n`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Auto sync: add shell wrapper
|
|
81
|
+
let alreadyInstalled = false;
|
|
82
|
+
try {
|
|
83
|
+
const content = fs.readFileSync(rcFile, 'utf-8');
|
|
84
|
+
if (content.includes(WRAPPER_MARKER)) alreadyInstalled = true;
|
|
85
|
+
} catch {}
|
|
86
|
+
|
|
87
|
+
if (alreadyInstalled) {
|
|
88
|
+
console.log(`\n ✓ Shell wrapper already installed in ${displayRc}\n`);
|
|
89
|
+
process.exit(0);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log(`\n This will add a skills() shell wrapper to ${displayRc}`);
|
|
93
|
+
console.log(` It auto-syncs skill-tags.md after every skills add/remove.\n`);
|
|
94
|
+
|
|
95
|
+
const yes = await confirm({
|
|
96
|
+
message: `Add the wrapper to ${displayRc}?`,
|
|
97
|
+
default: true,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (!yes) {
|
|
101
|
+
console.log('\n Skipped.\n');
|
|
102
|
+
process.exit(0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const syncPath = fs.existsSync(path.join(HOME, '.cursor', 'sync-skill-commands.sh'))
|
|
106
|
+
? path.join(HOME, '.cursor', 'sync-skill-commands.sh')
|
|
107
|
+
: SYNC_SCRIPT;
|
|
108
|
+
|
|
109
|
+
const wrapper = `
|
|
110
|
+
${WRAPPER_MARKER} ────────────────────────────────────────────────
|
|
111
|
+
# Wraps \`npx skills\` to auto-generate skill-tags.md after install/removal.
|
|
112
|
+
# Run manually: skill-tags (or: bash ${syncPath})
|
|
113
|
+
function skills() {
|
|
114
|
+
npx skills "$@"
|
|
115
|
+
local exit_code=$?
|
|
116
|
+
if [[ "$1" == "add" || "$1" == "remove" ]] && [[ $exit_code -eq 0 ]]; then
|
|
117
|
+
bash "${syncPath}"
|
|
118
|
+
fi
|
|
119
|
+
return $exit_code
|
|
120
|
+
}
|
|
121
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
122
|
+
`;
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
fs.appendFileSync(rcFile, wrapper);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.error(`\n Failed to write to ${displayRc}: ${err.message}\n`);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
console.log(`\n ✓ Added skills() wrapper to ${displayRc}`);
|
|
132
|
+
console.log(` Reload with: source ${displayRc}\n`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ─── Project setup ────────────────────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
async function setupProject(confirm, syncMode) {
|
|
138
|
+
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
139
|
+
|
|
140
|
+
if (!fs.existsSync(pkgPath)) {
|
|
141
|
+
console.error('\n No package.json found in current directory.');
|
|
142
|
+
console.error(' Run skill-tags --setup from your project root.\n');
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let pkg;
|
|
147
|
+
try {
|
|
148
|
+
pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
149
|
+
} catch (err) {
|
|
150
|
+
console.error(`\n Failed to read package.json: ${err.message}\n`);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const scripts = pkg.scripts || {};
|
|
155
|
+
|
|
156
|
+
if (syncMode === 'manual') {
|
|
157
|
+
console.log('\n Manual sync selected.');
|
|
158
|
+
console.log(' Run skill-tags --local at any time to regenerate .cursor/commands/project-skill-tags.md\n');
|
|
159
|
+
console.log(' Running initial project sync...\n');
|
|
160
|
+
spawnSync(
|
|
161
|
+
'node',
|
|
162
|
+
[path.join(__dirname, 'skill-tags.js'), '--local'],
|
|
163
|
+
{ stdio: 'inherit', cwd: process.cwd() }
|
|
164
|
+
);
|
|
165
|
+
console.log(`\n Done! Run skill-tags --local manually to re-sync.\n`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Auto sync: add "skills" npm script
|
|
170
|
+
if (scripts.skills === 'st-skills') {
|
|
171
|
+
console.log('\n ✓ Already configured — "skills": "st-skills" is in package.json\n');
|
|
172
|
+
console.log(' Add a skill: npm run skills add <owner/repo/skill-name>');
|
|
173
|
+
console.log(' Remove: npm run skills remove <owner/repo/skill-name>\n');
|
|
174
|
+
process.exit(0);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
console.log('\n This will add a "skills" script to your package.json:');
|
|
178
|
+
console.log(' "scripts": { "skills": "st-skills" }');
|
|
179
|
+
console.log('\n Then use: npm run skills add <owner/repo/skill-name>');
|
|
180
|
+
console.log(' Auto-syncs .cursor/commands/project-skill-tags.md after every add/remove.\n');
|
|
181
|
+
|
|
182
|
+
const yes = await confirm({
|
|
183
|
+
message: 'Add the "skills" script to package.json?',
|
|
184
|
+
default: true,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
if (!yes) {
|
|
188
|
+
console.log('\n Skipped.\n');
|
|
189
|
+
process.exit(0);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
pkg.scripts = { ...scripts, skills: 'st-skills' };
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
|
196
|
+
} catch (err) {
|
|
197
|
+
console.error(`\n Failed to write package.json: ${err.message}\n`);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
console.log('\n ✓ Added "skills": "st-skills" to package.json');
|
|
202
|
+
console.log('\n Running initial project sync...\n');
|
|
203
|
+
|
|
204
|
+
const result = spawnSync(
|
|
205
|
+
'node',
|
|
206
|
+
[path.join(__dirname, 'skill-tags.js'), '--local'],
|
|
207
|
+
{ stdio: 'inherit', cwd: process.cwd() }
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
if (result.error) {
|
|
211
|
+
console.error(`\n Warning: initial sync failed — ${result.error.message}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
console.log('\n Setup complete!\n');
|
|
215
|
+
console.log(' Add a skill: npm run skills add <owner/repo/skill-name>');
|
|
216
|
+
console.log(' Remove: npm run skills remove <owner/repo/skill-name>');
|
|
217
|
+
console.log(' Manual sync: skill-tags --local\n');
|
|
218
|
+
}
|
package/bin/skill-tags.js
CHANGED
|
@@ -7,12 +7,9 @@
|
|
|
7
7
|
const { spawnSync } = require('child_process');
|
|
8
8
|
const path = require('path');
|
|
9
9
|
const fs = require('fs');
|
|
10
|
-
const os = require('os');
|
|
11
10
|
|
|
12
11
|
const VERSION = require('../package.json').version;
|
|
13
|
-
const HOME = os.homedir();
|
|
14
12
|
const SYNC_SCRIPT = path.join(__dirname, '..', 'sync.sh');
|
|
15
|
-
const WRAPPER_MARKER = '# ─── skill-tags / Cursor Skill Command Sync';
|
|
16
13
|
|
|
17
14
|
// ─── --version ───────────────────────────────────────────────────────────────
|
|
18
15
|
|
|
@@ -38,12 +35,13 @@ if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
|
38
35
|
Usage: skill-tags [options]
|
|
39
36
|
|
|
40
37
|
Options:
|
|
41
|
-
(none)
|
|
42
|
-
--categories
|
|
43
|
-
--global
|
|
44
|
-
--
|
|
45
|
-
--
|
|
46
|
-
--
|
|
38
|
+
(none) Scan all skill sources and generate skill-tags.md
|
|
39
|
+
--categories Interactive category wizard (arrow keys + space to toggle)
|
|
40
|
+
--global Skip local skills (.agents/skills in CWD); scan global sources only
|
|
41
|
+
--local Scan only .agents/skills in CWD; write to .cursor/commands/project-skill-tags.md
|
|
42
|
+
--setup Interactive setup: choose Global (shell profile) or Project (package.json)
|
|
43
|
+
--version, -v Print version
|
|
44
|
+
--help, -h Show this help
|
|
47
45
|
|
|
48
46
|
Skill sources (priority order):
|
|
49
47
|
~/.agents/skills/ skills installed via npx skills add
|
|
@@ -54,11 +52,21 @@ if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
|
54
52
|
./.agents/skills/ project-level skills (current directory)
|
|
55
53
|
|
|
56
54
|
Output:
|
|
57
|
-
~/.cursor/commands/skill-tags.md
|
|
58
|
-
~/.cursor/commands/skills-<category>.md
|
|
55
|
+
~/.cursor/commands/skill-tags.md full index of all skills (global)
|
|
56
|
+
~/.cursor/commands/skills-<category>.md generated by --categories
|
|
57
|
+
./.cursor/commands/project-skill-tags.md generated by --local
|
|
59
58
|
|
|
60
59
|
Config:
|
|
61
60
|
~/.cursor/skill-tags-categories.conf
|
|
61
|
+
|
|
62
|
+
Setup modes:
|
|
63
|
+
Global Adds skills() wrapper to ~/.zshrc — use: skills add <pkg>
|
|
64
|
+
Project Adds "skills": "st-skills" to package.json — use: npm run skills add <pkg>
|
|
65
|
+
|
|
66
|
+
Project binary (st-skills):
|
|
67
|
+
st-skills add <pkg> Install a project skill and auto-sync
|
|
68
|
+
st-skills remove <pkg> Remove a project skill and auto-sync
|
|
69
|
+
st-skills update <pkg> Update a project skill and auto-sync
|
|
62
70
|
`);
|
|
63
71
|
process.exit(0);
|
|
64
72
|
}
|
|
@@ -72,6 +80,7 @@ if (process.argv.includes('--categories')) {
|
|
|
72
80
|
// ─── --setup ─────────────────────────────────────────────────────────────────
|
|
73
81
|
|
|
74
82
|
else if (process.argv.includes('--setup')) {
|
|
83
|
+
const runSetup = require('./setup');
|
|
75
84
|
runSetup().catch(err => {
|
|
76
85
|
if (err.name === 'ExitPromptError') { console.log(); process.exit(0); }
|
|
77
86
|
console.error(' Error:', err.message);
|
|
@@ -98,72 +107,3 @@ else {
|
|
|
98
107
|
|
|
99
108
|
process.exit(result.status ?? 0);
|
|
100
109
|
}
|
|
101
|
-
|
|
102
|
-
// ─── Setup implementation ────────────────────────────────────────────────────
|
|
103
|
-
|
|
104
|
-
async function runSetup() {
|
|
105
|
-
const { confirm } = require('@inquirer/prompts');
|
|
106
|
-
|
|
107
|
-
const shellName = path.basename(process.env.SHELL || 'bash');
|
|
108
|
-
let rcFile;
|
|
109
|
-
if (shellName === 'zsh') rcFile = path.join(HOME, '.zshrc');
|
|
110
|
-
else if (process.platform === 'darwin') rcFile = path.join(HOME, '.bash_profile');
|
|
111
|
-
else rcFile = path.join(HOME, '.bashrc');
|
|
112
|
-
|
|
113
|
-
const displayRc = rcFile.replace(HOME, '~');
|
|
114
|
-
|
|
115
|
-
console.log(`\n skill-tags: shell setup\n`);
|
|
116
|
-
|
|
117
|
-
let alreadyInstalled = false;
|
|
118
|
-
try {
|
|
119
|
-
const content = fs.readFileSync(rcFile, 'utf-8');
|
|
120
|
-
if (content.includes(WRAPPER_MARKER)) alreadyInstalled = true;
|
|
121
|
-
} catch {}
|
|
122
|
-
|
|
123
|
-
if (alreadyInstalled) {
|
|
124
|
-
console.log(` ✓ Shell wrapper already installed in ${displayRc}\n`);
|
|
125
|
-
process.exit(0);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
console.log(` This will add a skills() shell wrapper to ${displayRc}`);
|
|
129
|
-
console.log(` It auto-syncs skill-tags.md after every skills add/remove.\n`);
|
|
130
|
-
|
|
131
|
-
const yes = await confirm({
|
|
132
|
-
message: `Add the wrapper to ${displayRc}?`,
|
|
133
|
-
default: true,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
if (!yes) {
|
|
137
|
-
console.log('\n Skipped.\n');
|
|
138
|
-
process.exit(0);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const syncPath = fs.existsSync(path.join(HOME, '.cursor', 'sync-skill-commands.sh'))
|
|
142
|
-
? path.join(HOME, '.cursor', 'sync-skill-commands.sh')
|
|
143
|
-
: SYNC_SCRIPT;
|
|
144
|
-
|
|
145
|
-
const wrapper = `
|
|
146
|
-
${WRAPPER_MARKER} ────────────────────────────────────────────────
|
|
147
|
-
# Wraps \`npx skills\` to auto-generate skill-tags.md after install/removal.
|
|
148
|
-
# Run manually: skill-tags (or: bash ${syncPath})
|
|
149
|
-
function skills() {
|
|
150
|
-
npx skills "$@"
|
|
151
|
-
local exit_code=$?
|
|
152
|
-
if [[ "$1" == "add" || "$1" == "remove" ]] && [[ $exit_code -eq 0 ]]; then
|
|
153
|
-
bash "${syncPath}"
|
|
154
|
-
fi
|
|
155
|
-
return $exit_code
|
|
156
|
-
}
|
|
157
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
158
|
-
`;
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
fs.appendFileSync(rcFile, wrapper);
|
|
162
|
-
} catch (err) {
|
|
163
|
-
console.error(`\n Failed to write to ${displayRc}: ${err.message}\n`);
|
|
164
|
-
process.exit(1);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
console.log(`\n ✓ Added skills() wrapper to ${displayRc}`);
|
|
168
|
-
console.log(` Reload with: source ${displayRc}\n`);
|
|
169
|
-
}
|
package/bin/st-skills.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// bin/st-skills.js
|
|
3
|
+
// Project-level skills wrapper: runs npx skills and auto-syncs project-skill-tags.md on add/remove/update.
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { spawnSync } = require('child_process');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const subcommand = args[0];
|
|
12
|
+
|
|
13
|
+
// Run npx skills with all forwarded arguments
|
|
14
|
+
const result = spawnSync('npx', ['skills', ...args], { stdio: 'inherit', shell: false });
|
|
15
|
+
|
|
16
|
+
if (result.error) {
|
|
17
|
+
console.error(`\n st-skills: failed to run npx skills — ${result.error.message}\n`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const exitCode = result.status ?? 1;
|
|
22
|
+
|
|
23
|
+
// Auto-sync project-skill-tags.md on successful mutating subcommands
|
|
24
|
+
if (['add', 'remove', 'update'].includes(subcommand) && exitCode === 0) {
|
|
25
|
+
const syncResult = spawnSync(
|
|
26
|
+
'node',
|
|
27
|
+
[path.join(__dirname, 'skill-tags.js'), '--local'],
|
|
28
|
+
{ stdio: 'inherit', cwd: process.cwd() }
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
if (syncResult.error) {
|
|
32
|
+
console.error(`\n st-skills: sync failed — ${syncResult.error.message}\n`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
process.exit(exitCode);
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skill-tags",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Generates consolidated command files (@skill-tags.md and custom @skills-<category>.md indexes) for all installed Cursor skills.",
|
|
5
5
|
"bin": {
|
|
6
|
-
"skill-tags": "bin/skill-tags.js"
|
|
6
|
+
"skill-tags": "bin/skill-tags.js",
|
|
7
|
+
"st-skills": "bin/st-skills.js"
|
|
7
8
|
},
|
|
8
9
|
"scripts": {
|
|
9
10
|
"postinstall": "node ./bin/postinstall.js"
|
package/sync.sh
CHANGED
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
set -euo pipefail
|
|
9
9
|
|
|
10
|
-
VERSION="1.
|
|
10
|
+
VERSION="1.3.0"
|
|
11
11
|
|
|
12
12
|
GLOBAL_COMMANDS_DIR="${HOME}/.cursor/commands"
|
|
13
13
|
OUTPUT_FILE="${GLOBAL_COMMANDS_DIR}/skill-tags.md"
|
|
14
14
|
CATEGORIES_CONFIG="${HOME}/.cursor/skill-tags-categories.conf"
|
|
15
|
+
PROJECT_COMMANDS_DIR="$(pwd)/.cursor/commands"
|
|
16
|
+
PROJECT_OUTPUT_FILE="${PROJECT_COMMANDS_DIR}/project-skill-tags.md"
|
|
15
17
|
|
|
16
18
|
# ─── Priority-ordered skill source directories ─────────────────────────────────
|
|
17
19
|
# Earlier entries take priority when the same skill name exists in multiple locations.
|
|
@@ -33,10 +35,12 @@ trap 'rm -f "$SKILLS_TEMP"; rm -rf "$SKILLS_META_DIR"' EXIT
|
|
|
33
35
|
# ─── Flags ─────────────────────────────────────────────────────────────────────
|
|
34
36
|
|
|
35
37
|
GLOBAL_ONLY=false
|
|
38
|
+
PROJECT_ONLY=false
|
|
36
39
|
|
|
37
40
|
for arg in "$@"; do
|
|
38
41
|
case "$arg" in
|
|
39
|
-
--global
|
|
42
|
+
--global) GLOBAL_ONLY=true ;;
|
|
43
|
+
--local) PROJECT_ONLY=true ;;
|
|
40
44
|
esac
|
|
41
45
|
done
|
|
42
46
|
|
|
@@ -254,27 +258,72 @@ EOF
|
|
|
254
258
|
|
|
255
259
|
printf "\n skill-tags v%s — syncing skills\n\n" "$VERSION"
|
|
256
260
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if [[ -d "$
|
|
262
|
-
|
|
263
|
-
|
|
261
|
+
if [[ "$PROJECT_ONLY" == "true" ]]; then
|
|
262
|
+
# ─── --local: scan only .agents/skills in CWD ───────────────────────────────
|
|
263
|
+
PROJECT_SKILLS_DIR="$(pwd)/.agents/skills"
|
|
264
|
+
|
|
265
|
+
if [[ ! -d "$PROJECT_SKILLS_DIR" ]]; then
|
|
266
|
+
printf " No project skills found at %s/.agents/skills\n\n" "$(pwd)"
|
|
267
|
+
exit 0
|
|
264
268
|
fi
|
|
265
|
-
done
|
|
266
269
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
log "Scanning project skills: ${PROJECT_SKILLS_DIR}"
|
|
271
|
+
scan_tree "$PROJECT_SKILLS_DIR"
|
|
272
|
+
|
|
273
|
+
OPENING="Assess the following project-level skills and apply any that are relevant to completing the user's request at the highest level of efficiency, quality, and completeness. When skills overlap in scope, assess the overlapping skills in greater detail and autonomously determine which is the best match for the project or the specific request — do not prompt the user to resolve overlaps.
|
|
274
|
+
|
|
275
|
+
CRITICAL REQUIREMENT: Before applying any skill, you MUST use the Read tool to read the full contents of the skill file at the provided path. Do not assume the skill's behavior from its title or description alone.
|
|
276
|
+
|
|
277
|
+
If operating in Plan Mode, explicitly include references to specific skills to use and (if applicable) subagents to utilize for efficient programming within the contents of the plan and the plan's TODOs.
|
|
278
|
+
|
|
279
|
+
Examples:
|
|
280
|
+
- \"Use the \`responsive-design/SKILL.md\` to apply advanced clamp-based responsiveness to the new navigation bar.\"
|
|
281
|
+
- \"Delegate to the \`frontend-designer\` subagent using \`ui-ux-pro-max/SKILL.md\` to build the polished component.\"
|
|
282
|
+
- \"Utilize \`supabase-postgres-best-practices/SKILL.md\` when designing the database schema for the user profiles.\""
|
|
283
|
+
|
|
284
|
+
mkdir -p "$PROJECT_COMMANDS_DIR"
|
|
285
|
+
|
|
286
|
+
is_update=false
|
|
287
|
+
[[ -f "$PROJECT_OUTPUT_FILE" ]] && is_update=true
|
|
288
|
+
|
|
289
|
+
cat > "$PROJECT_OUTPUT_FILE" <<EOF
|
|
290
|
+
# Skill Tags Command
|
|
291
|
+
|
|
292
|
+
<!-- Auto-generated by sync.sh (skill-tags) v${VERSION} — do not edit manually -->
|
|
293
|
+
|
|
294
|
+
${OPENING}
|
|
295
|
+
|
|
296
|
+
## Available Skills
|
|
297
|
+
$(cat "$SKILLS_TEMP")
|
|
298
|
+
EOF
|
|
299
|
+
|
|
300
|
+
printf "\n"
|
|
301
|
+
if [[ "$is_update" == "true" ]]; then
|
|
302
|
+
printf " ✓ Updated: .cursor/commands/project-skill-tags.md\n"
|
|
303
|
+
else
|
|
304
|
+
printf " ✓ Generated: .cursor/commands/project-skill-tags.md\n"
|
|
305
|
+
fi
|
|
306
|
+
printf " Skills: %d indexed\n" "$count_found"
|
|
307
|
+
printf "\n Tip: type @project-skill-tags.md in Cursor chat to load the project skills reference.\n\n"
|
|
272
308
|
|
|
273
|
-
|
|
309
|
+
else
|
|
310
|
+
# ─── Default: scan all sources ───────────────────────────────────────────────
|
|
311
|
+
|
|
312
|
+
for entry in "${GLOBAL_SKILL_SOURCES[@]}"; do
|
|
313
|
+
dir="${entry%%:*}"
|
|
314
|
+
label="${entry##*:}"
|
|
315
|
+
if [[ -d "$dir" ]]; then
|
|
316
|
+
log "Scanning ${label}: ${dir/#$HOME/~}"
|
|
317
|
+
scan_tree "$dir"
|
|
318
|
+
fi
|
|
319
|
+
done
|
|
274
320
|
|
|
275
|
-
|
|
321
|
+
if [[ "$GLOBAL_ONLY" == "false" && -d ".agents/skills" ]]; then
|
|
322
|
+
log "Scanning project skills: $(pwd)/.agents/skills"
|
|
323
|
+
scan_tree "$(pwd)/.agents/skills"
|
|
324
|
+
fi
|
|
276
325
|
|
|
277
|
-
OPENING="Assess the following skills available in this workspace and apply any that are relevant to completing the user's request at the highest level of efficiency, quality, and completeness. When skills overlap in scope, assess the overlapping skills in greater detail and autonomously determine which is the best match for the project or the specific request — do not prompt the user to resolve overlaps.
|
|
326
|
+
OPENING="Assess the following skills available in this workspace and apply any that are relevant to completing the user's request at the highest level of efficiency, quality, and completeness. When skills overlap in scope, assess the overlapping skills in greater detail and autonomously determine which is the best match for the project or the specific request — do not prompt the user to resolve overlaps.
|
|
278
327
|
|
|
279
328
|
CRITICAL REQUIREMENT: Before applying any skill, you MUST use the Read tool to read the full contents of the skill file at the provided path. Do not assume the skill's behavior from its title or description alone.
|
|
280
329
|
|
|
@@ -285,10 +334,12 @@ Examples:
|
|
|
285
334
|
- \"Delegate to the \`frontend-designer\` subagent using \`ui-ux-pro-max/SKILL.md\` to build the polished component.\"
|
|
286
335
|
- \"Utilize \`supabase-postgres-best-practices/SKILL.md\` when designing the database schema for the user profiles.\""
|
|
287
336
|
|
|
288
|
-
|
|
289
|
-
[[ -f "$OUTPUT_FILE" ]] && is_update=true
|
|
337
|
+
mkdir -p "$GLOBAL_COMMANDS_DIR"
|
|
290
338
|
|
|
291
|
-
|
|
339
|
+
is_update=false
|
|
340
|
+
[[ -f "$OUTPUT_FILE" ]] && is_update=true
|
|
341
|
+
|
|
342
|
+
cat > "$OUTPUT_FILE" <<EOF
|
|
292
343
|
# Skill Tags Command
|
|
293
344
|
|
|
294
345
|
<!-- Auto-generated by sync.sh (skill-tags) v${VERSION} — do not edit manually -->
|
|
@@ -299,20 +350,18 @@ ${OPENING}
|
|
|
299
350
|
$(cat "$SKILLS_TEMP")
|
|
300
351
|
EOF
|
|
301
352
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
generate_category_files
|
|
353
|
+
generate_category_files
|
|
305
354
|
|
|
306
|
-
|
|
355
|
+
printf "\n"
|
|
356
|
+
if [[ "$is_update" == "true" ]]; then
|
|
357
|
+
printf " ✓ Updated: %s\n" "${OUTPUT_FILE/#$HOME/~}"
|
|
358
|
+
else
|
|
359
|
+
printf " ✓ Generated: %s\n" "${OUTPUT_FILE/#$HOME/~}"
|
|
360
|
+
fi
|
|
361
|
+
printf " Skills: %d indexed\n" "$count_found"
|
|
362
|
+
if [[ $count_dupes -gt 0 ]]; then
|
|
363
|
+
printf " Duplicates: %d skipped (covered by higher-priority source)\n" "$count_dupes"
|
|
364
|
+
fi
|
|
365
|
+
printf "\n Tip: type @skill-tags.md in Cursor chat to load the full skills reference.\n\n"
|
|
307
366
|
|
|
308
|
-
printf "\n"
|
|
309
|
-
if [[ "$is_update" == "true" ]]; then
|
|
310
|
-
printf " ✓ Updated: %s\n" "${OUTPUT_FILE/#$HOME/~}"
|
|
311
|
-
else
|
|
312
|
-
printf " ✓ Generated: %s\n" "${OUTPUT_FILE/#$HOME/~}"
|
|
313
|
-
fi
|
|
314
|
-
printf " Skills: %d indexed\n" "$count_found"
|
|
315
|
-
if [[ $count_dupes -gt 0 ]]; then
|
|
316
|
-
printf " Duplicates: %d skipped (covered by higher-priority source)\n" "$count_dupes"
|
|
317
367
|
fi
|
|
318
|
-
printf "\n Tip: type @skill-tags.md in Cursor chat to load the full skills reference.\n\n"
|