perf-skill 0.2.1 → 0.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/.claude-plugin/README.md +53 -0
- package/.claude-plugin/marketplace.json +58 -0
- package/.claude-plugin/plugin.json +40 -0
- package/CLAUDE.md +164 -0
- package/README.md +128 -109
- package/SKILL.md +86 -130
- package/dist/cli/init.d.ts +19 -3
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +107 -10
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/main.js +72 -49
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/platforms.d.ts +28 -0
- package/dist/cli/platforms.d.ts.map +1 -0
- package/dist/cli/platforms.js +238 -0
- package/dist/cli/platforms.js.map +1 -0
- package/dist/cli/template.d.ts +16 -0
- package/dist/cli/template.d.ts.map +1 -0
- package/dist/cli/template.js +157 -0
- package/dist/cli/template.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -36
- package/dist/index.js.map +1 -1
- package/dist/llm/client.d.ts +6 -0
- package/dist/llm/client.d.ts.map +1 -1
- package/dist/llm/client.js +11 -2
- package/dist/llm/client.js.map +1 -1
- package/dist/llm/index.d.ts +1 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +1 -1
- package/dist/llm/index.js.map +1 -1
- package/dist/skill/handler.d.ts +7 -0
- package/dist/skill/handler.d.ts.map +1 -1
- package/dist/skill/handler.js +24 -1
- package/dist/skill/handler.js.map +1 -1
- package/dist/skill/manifest.d.ts +4 -0
- package/dist/skill/manifest.d.ts.map +1 -1
- package/dist/skill/manifest.js +60 -39
- package/dist/skill/manifest.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -9
- package/dist/server/http.d.ts +0 -27
- package/dist/server/http.d.ts.map +0 -1
- package/dist/server/http.js +0 -285
- package/dist/server/http.js.map +0 -1
- package/dist/server/utils.d.ts +0 -15
- package/dist/server/utils.d.ts.map +0 -1
- package/dist/server/utils.js +0 -71
- package/dist/server/utils.js.map +0 -1
package/SKILL.md
CHANGED
|
@@ -1,85 +1,80 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: perf-skill
|
|
3
|
-
description:
|
|
4
|
-
argument-hint: [profile.pb.gz
|
|
3
|
+
description: Convert pprof CPU and heap profiles to structured Markdown and JSON evidence. Use when the user has a .pb.gz profile file and wants to understand performance bottlenecks or compare profiles.
|
|
4
|
+
argument-hint: [profile.pb.gz] [options]
|
|
5
5
|
allowed-tools: Bash(node *), Bash(npx *), Read, Glob
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# perf-skill: Performance Profile
|
|
8
|
+
# perf-skill: Performance Profile Evidence Extractor
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Convert pprof profiles (.pb.gz) to structured Markdown and JSON for performance analysis. This tool produces **deterministic, evidence-based output** that you (the agent) can use to generate optimization recommendations.
|
|
11
|
+
|
|
12
|
+
## Design Philosophy
|
|
13
|
+
|
|
14
|
+
- **Deterministic by default**: No external API calls or LLM dependencies
|
|
15
|
+
- **Evidence-first**: Produces structured hotspots, call paths, and metrics
|
|
16
|
+
- **Agent-friendly**: You (Claude/Cursor/any coding agent) provide the analysis and recommendations based on the evidence
|
|
11
17
|
|
|
12
18
|
## Quick Start
|
|
13
19
|
|
|
14
20
|
### Analyze a Single Profile
|
|
15
21
|
|
|
16
22
|
```bash
|
|
17
|
-
#
|
|
18
|
-
npx perf-skill convert $ARGUMENTS
|
|
19
|
-
|
|
20
|
-
# Full analysis with AI recommendations
|
|
21
|
-
npx perf-skill analyze $ARGUMENTS --mode analyze
|
|
22
|
-
|
|
23
|
-
# Output to file
|
|
23
|
+
# Convert profile to structured markdown and JSON (default, no LLM required)
|
|
24
24
|
npx perf-skill analyze $ARGUMENTS -o analysis.md -j results.json
|
|
25
|
+
|
|
26
|
+
# Or use the convert command (explicitly no LLM)
|
|
27
|
+
npx perf-skill convert $ARGUMENTS -o report.md
|
|
25
28
|
```
|
|
26
29
|
|
|
27
|
-
###
|
|
30
|
+
### Compare Two Profiles (Diff)
|
|
28
31
|
|
|
29
32
|
```bash
|
|
30
|
-
#
|
|
31
|
-
npx perf-skill
|
|
32
|
-
|
|
33
|
-
# Customize duration and output
|
|
34
|
-
npx perf-skill run slow.mjs --duration 10s -o analysis.md
|
|
35
|
-
|
|
36
|
-
# CPU + Heap profiling (separate reports)
|
|
37
|
-
npx perf-skill run slow.mjs --heap --output cpu.md --heap-output heap.md
|
|
33
|
+
# Compare base vs current profile
|
|
34
|
+
npx perf-skill diff base.pb.gz current.pb.gz -o diff.md -j diff.json
|
|
38
35
|
```
|
|
39
36
|
|
|
40
|
-
###
|
|
37
|
+
### Profile a Node.js Application
|
|
41
38
|
|
|
42
39
|
```bash
|
|
43
|
-
#
|
|
44
|
-
npx perf-skill
|
|
40
|
+
# Profile and convert in one step
|
|
41
|
+
npx perf-skill run slow.mjs --duration 10s -o cpu.md -j cpu.json
|
|
45
42
|
|
|
46
|
-
# With
|
|
47
|
-
npx perf-skill
|
|
43
|
+
# With heap profiling
|
|
44
|
+
npx perf-skill run slow.mjs --heap --output cpu.md --heap-output heap.md
|
|
48
45
|
```
|
|
49
46
|
|
|
47
|
+
## Workflow for Performance Analysis
|
|
48
|
+
|
|
49
|
+
1. **Run perf-skill** to generate evidence (markdown + JSON)
|
|
50
|
+
2. **Read the output** to understand hotspots and call paths
|
|
51
|
+
3. **Generate recommendations** based on the evidence (this is YOUR job as the agent)
|
|
52
|
+
4. **Implement changes** and re-run profiling to verify improvements
|
|
53
|
+
|
|
50
54
|
## When to Use This Skill
|
|
51
55
|
|
|
52
56
|
Use `perf-skill` when:
|
|
53
57
|
- User provides a `.pb.gz` pprof profile file
|
|
54
|
-
- User provides a Node.js entry file (`.js/.mjs/.cjs`) and wants an end-to-end performance report
|
|
55
58
|
- User asks "why is my app slow?" with a profile attached
|
|
56
59
|
- User wants to compare performance before/after a change
|
|
57
60
|
- User needs help interpreting profile data
|
|
58
61
|
- User asks about CPU or memory hotspots
|
|
59
62
|
|
|
60
|
-
## Routing
|
|
61
|
-
|
|
62
|
-
- If the argument ends with `.pb`, `.pb.gz`, or `.pprof`, run `analyze` or `diff` directly.
|
|
63
|
-
- If the argument ends with `.js`, `.mjs`, or `.cjs`, run `perf-skill run <entry>` to generate a CPU profile and analyze it.
|
|
64
|
-
- If the user asks for both CPU and heap (including misspellings like "heep" or terms like "memory"/"heap"), add `--heap` and save separate reports (`--output` + `--heap-output`).
|
|
65
|
-
|
|
66
63
|
## Available Commands
|
|
67
64
|
|
|
68
65
|
### `analyze` (default)
|
|
69
66
|
|
|
70
|
-
|
|
67
|
+
Convert a profile to structured Markdown. Default mode is `convert-only` (no external dependencies).
|
|
71
68
|
|
|
72
69
|
```bash
|
|
73
70
|
perf-skill analyze profile.pb.gz [options]
|
|
74
71
|
```
|
|
75
72
|
|
|
76
|
-
**Options:**
|
|
73
|
+
**Key Options:**
|
|
77
74
|
- `-f, --format <format>`: Output format (`summary`, `detailed`, `adaptive`)
|
|
78
75
|
- `-t, --type <type>`: Profile type (`cpu`, `heap`, `auto`)
|
|
79
76
|
- `-o, --output <file>`: Save markdown to file
|
|
80
|
-
- `-j, --json <file>`: Save JSON results to file
|
|
81
|
-
- `-m, --mode <mode>`: `convert-only` (no LLM) or `analyze` (with LLM)
|
|
82
|
-
- `-s, --source-dir <path>`: Include source code context
|
|
77
|
+
- `-j, --json <file>`: Save JSON results to file (for programmatic access)
|
|
83
78
|
- `--max-hotspots <n>`: Limit hotspots shown (default: 10)
|
|
84
79
|
- `--service <name>`: Service name for context
|
|
85
80
|
- `--scenario <desc>`: Scenario description
|
|
@@ -92,15 +87,17 @@ Compare two profiles to find performance regressions.
|
|
|
92
87
|
perf-skill diff base.pb.gz current.pb.gz [options]
|
|
93
88
|
```
|
|
94
89
|
|
|
95
|
-
**Options:**
|
|
90
|
+
**Key Options:**
|
|
96
91
|
- `-f, --format <format>`: `diff-summary`, `diff-detailed`, `diff-adaptive`
|
|
97
92
|
- `-n, --normalize <mode>`: `none`, `scale-to-base-total`, `per-second`
|
|
93
|
+
- `-o, --output <file>`: Save markdown to file
|
|
94
|
+
- `-j, --json <file>`: Save JSON results to file
|
|
98
95
|
- `--max-regressions <n>`: Limit regressions shown (default: 10)
|
|
99
96
|
- `--max-improvements <n>`: Limit improvements shown (default: 5)
|
|
100
97
|
|
|
101
98
|
### `convert`
|
|
102
99
|
|
|
103
|
-
|
|
100
|
+
Explicitly convert profile to markdown (same as analyze with default settings).
|
|
104
101
|
|
|
105
102
|
```bash
|
|
106
103
|
perf-skill convert profile.pb.gz -o report.md
|
|
@@ -108,125 +105,84 @@ perf-skill convert profile.pb.gz -o report.md
|
|
|
108
105
|
|
|
109
106
|
### `run`
|
|
110
107
|
|
|
111
|
-
Profile a Node entry file
|
|
108
|
+
Profile a Node.js entry file and convert the results.
|
|
112
109
|
|
|
113
110
|
```bash
|
|
114
|
-
perf-skill run
|
|
111
|
+
perf-skill run slow.mjs --duration 10s -o cpu.md
|
|
115
112
|
```
|
|
116
113
|
|
|
117
|
-
**Options:**
|
|
118
|
-
- `-d, --duration <duration>`: Profiling duration (default: `10s`)
|
|
119
|
-
- `--profile-out <file>`: Profile output file (default: `cpu.pb.gz`)
|
|
120
|
-
- `--heap`: Also capture heap profile
|
|
121
|
-
- `--heap-profile-out <file>`: Heap profile output file (default: `heap.pb.gz`)
|
|
122
|
-
- `--heap-output <file>`: Heap markdown output file (default: derived from CPU output or `heap.md`)
|
|
123
|
-
- `--heap-json <file>`: Heap JSON output file (optional)
|
|
124
|
-
- `--heap-interval-bytes <n>`: Heap sampling interval (bytes, default: `524288`)
|
|
125
|
-
- `--heap-stack-depth <n>`: Heap sampling stack depth (default: `64`)
|
|
126
|
-
- All `analyze` options (`--format`, `--mode`, `--output`, etc.)
|
|
127
|
-
|
|
128
|
-
When `--heap` is enabled and `--output` is omitted, the CLI writes `cpu.md` and `heap.md` instead of printing to stdout.
|
|
129
|
-
|
|
130
114
|
### `profile`
|
|
131
115
|
|
|
132
|
-
|
|
116
|
+
Only generate profile files without conversion.
|
|
133
117
|
|
|
134
118
|
```bash
|
|
135
|
-
perf-skill profile
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
**Options:**
|
|
139
|
-
- `-d, --duration <duration>`: Profiling duration (default: `10s`)
|
|
140
|
-
- `-o, --output <file>`: Profile output file (default: `cpu.pb.gz`)
|
|
141
|
-
- `--heap`: Also capture heap profile
|
|
142
|
-
- `--heap-profile-out <file>`: Heap profile output file (default: `heap.pb.gz`)
|
|
143
|
-
- `--heap-interval-bytes <n>`: Heap sampling interval (bytes, default: `524288`)
|
|
144
|
-
- `--heap-stack-depth <n>`: Heap sampling stack depth (default: `64`)
|
|
145
|
-
|
|
146
|
-
## Programmatic Usage
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
import { analyze, diff } from 'perf-skill';
|
|
150
|
-
|
|
151
|
-
// Analyze with AI
|
|
152
|
-
const result = await analyze('cpu.pb.gz', {
|
|
153
|
-
mode: 'analyze',
|
|
154
|
-
context: { serviceName: 'api-server' }
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
console.log(result.markdown);
|
|
158
|
-
console.log(result.recommendations);
|
|
159
|
-
|
|
160
|
-
// Compare profiles
|
|
161
|
-
const diffResult = await diff('base.pb.gz', 'current.pb.gz');
|
|
162
|
-
console.log(diffResult.regressions);
|
|
119
|
+
perf-skill profile slow.mjs --duration 10s -o cpu.pb.gz
|
|
163
120
|
```
|
|
164
121
|
|
|
165
122
|
## Understanding the Output
|
|
166
123
|
|
|
167
|
-
### Hotspots
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
124
|
+
### Hotspots (JSON structure)
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"hotspots": [
|
|
129
|
+
{
|
|
130
|
+
"rank": 1,
|
|
131
|
+
"function": "processRequest",
|
|
132
|
+
"selfPct": 23.4,
|
|
133
|
+
"cumPct": 67.8,
|
|
134
|
+
"location": "src/handler.ts:142",
|
|
135
|
+
"callPath": ["main", "handleHttp", "processRequest"]
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
```
|
|
175
140
|
|
|
176
|
-
|
|
177
|
-
- **
|
|
178
|
-
- **
|
|
179
|
-
- **Steps**: How to implement
|
|
180
|
-
- **Impact/Risk/Confidence**: Prioritization info
|
|
141
|
+
- **selfPct**: Time/memory spent in this function only (high = expensive work)
|
|
142
|
+
- **cumPct**: Time/memory including callees (high = hot path entry point)
|
|
143
|
+
- **callPath**: Call stack from root to this function
|
|
181
144
|
|
|
182
|
-
### Diff Analysis
|
|
145
|
+
### Diff Analysis (JSON structure)
|
|
183
146
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"regressions": [...],
|
|
150
|
+
"improvements": [...],
|
|
151
|
+
"summary": ["Overall performance regressed by ~5%", "..."]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
188
154
|
|
|
189
|
-
##
|
|
155
|
+
## Tips for Analysis
|
|
190
156
|
|
|
191
|
-
|
|
157
|
+
1. **High self%** = function is doing expensive work directly → optimize the function body
|
|
158
|
+
2. **High cum%** = function is on a hot path → may need to call faster alternatives or cache
|
|
159
|
+
3. **Native functions** (like `JSON.parse`) at top → consider streaming/binary alternatives
|
|
160
|
+
4. **Compare profiles** to find the cause of regressions after code changes
|
|
161
|
+
5. **Low sample count** → run profiler longer for statistical significance
|
|
192
162
|
|
|
193
|
-
|
|
194
|
-
import * as pprof from '@datadog/pprof';
|
|
195
|
-
import { writeFileSync } from 'fs';
|
|
196
|
-
import { gzipSync } from 'zlib';
|
|
163
|
+
## Example Agent Workflow
|
|
197
164
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
// ... run your workload ...
|
|
201
|
-
const profile = await pprof.time.stop();
|
|
202
|
-
writeFileSync('cpu.pb.gz', gzipSync(profile.encode()));
|
|
165
|
+
```markdown
|
|
166
|
+
User: "My API is slow, here's the profile: cpu.pb.gz"
|
|
203
167
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
168
|
+
Agent:
|
|
169
|
+
1. Run: `npx perf-skill analyze cpu.pb.gz -o analysis.md -j results.json`
|
|
170
|
+
2. Read the output files
|
|
171
|
+
3. Analyze hotspots and generate recommendations:
|
|
172
|
+
- "JSON.parse at 23% - consider streaming JSON parser"
|
|
173
|
+
- "processRequest has high cumulative time - trace callees"
|
|
174
|
+
4. Implement changes
|
|
175
|
+
5. Re-profile and use `perf-skill diff` to verify improvement
|
|
209
176
|
```
|
|
210
177
|
|
|
211
|
-
## Tips
|
|
212
|
-
|
|
213
|
-
1. **Start with `--format summary`** for quick triage
|
|
214
|
-
2. **Use `--mode convert-only`** when you just need the markdown
|
|
215
|
-
3. **Compare profiles** to find the cause of regressions
|
|
216
|
-
4. **Provide context** (`--service`, `--scenario`) for better AI recommendations
|
|
217
|
-
5. **High self%** = function is doing expensive work directly
|
|
218
|
-
6. **High cum%** = function is on a hot path (may be calling slow functions)
|
|
219
|
-
|
|
220
178
|
## Requirements
|
|
221
179
|
|
|
222
|
-
- Node.js >=
|
|
223
|
-
- For AI analysis: Set `OPENAI_API_KEY` or configure LLM provider
|
|
224
|
-
- CPU profiling uses bundled `@datadog/pprof` (native module); supported on common platforms
|
|
180
|
+
- Node.js >= 20
|
|
225
181
|
|
|
226
182
|
## Troubleshooting
|
|
227
183
|
|
|
228
184
|
### "No symbols found"
|
|
229
|
-
The profile may be from a production build without debug info.
|
|
185
|
+
The profile may be from a production build without debug info. Analysis still works but function names may be mangled.
|
|
230
186
|
|
|
231
187
|
### "Native code dominates"
|
|
232
188
|
If native functions (like `JSON.parse`) are top hotspots, consider:
|
package/dist/cli/init.d.ts
CHANGED
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI init command helpers - install SKILL.md into
|
|
2
|
+
* CLI init command helpers - install SKILL.md into target directories for multiple AI platforms
|
|
3
3
|
*/
|
|
4
|
+
import { type AIPlatform } from "./platforms.js";
|
|
4
5
|
export type CursorScope = "user" | "project";
|
|
5
6
|
export interface InitOptions {
|
|
6
7
|
target?: string;
|
|
7
8
|
cursor?: boolean;
|
|
9
|
+
platform?: AIPlatform;
|
|
8
10
|
scope?: CursorScope;
|
|
9
11
|
force?: boolean;
|
|
10
12
|
dryRun?: boolean;
|
|
13
|
+
offline?: boolean;
|
|
11
14
|
}
|
|
12
15
|
export interface InstallTarget {
|
|
13
|
-
|
|
16
|
+
platform: string;
|
|
17
|
+
layout: "cursor" | "flat" | "file" | "platform";
|
|
14
18
|
rootDir: string;
|
|
15
19
|
destDir: string;
|
|
16
20
|
destFile: string;
|
|
17
21
|
}
|
|
22
|
+
export interface InitResult {
|
|
23
|
+
success: boolean;
|
|
24
|
+
targets: InstallTarget[];
|
|
25
|
+
errors: Array<{
|
|
26
|
+
platform: string;
|
|
27
|
+
error: string;
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
18
30
|
export declare function parseSkillFrontmatterName(markdown: string): string | null;
|
|
19
31
|
export declare function isReservedCursorDir(targetPath: string): boolean;
|
|
20
32
|
export declare function resolveInstallTarget(options: {
|
|
@@ -25,5 +37,9 @@ export declare function resolveInstallTarget(options: {
|
|
|
25
37
|
cwd: string;
|
|
26
38
|
homeDir: string;
|
|
27
39
|
}): InstallTarget;
|
|
28
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Run init command - supports multiple platforms
|
|
42
|
+
*/
|
|
43
|
+
export declare function runInit(options: InitOptions): Promise<InitResult>;
|
|
44
|
+
export { AI_PLATFORMS, type AIPlatform } from "./platforms.js";
|
|
29
45
|
//# sourceMappingURL=init.d.ts.map
|
package/dist/cli/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EACL,KAAK,UAAU,EAKhB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAaD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAczE;AAUD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE/D;AASD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,aAAa,CAuDhB;AA4ED;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA4FvE;AAGD,OAAO,EAAE,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/cli/init.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI init command helpers - install SKILL.md into
|
|
2
|
+
* CLI init command helpers - install SKILL.md into target directories for multiple AI platforms
|
|
3
3
|
*/
|
|
4
4
|
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { basename, dirname, extname, join, resolve, sep } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { AI_PLATFORMS, PLATFORM_CONFIGS, getAllPlatforms, isPlatformValid, } from "./platforms.js";
|
|
9
|
+
import { renderSkillForPlatform, getDestinationPath } from "./template.js";
|
|
8
10
|
function normalizeFrontmatterValue(value) {
|
|
9
11
|
const trimmed = value.trim();
|
|
10
12
|
if ((trimmed.startsWith("\"") && trimmed.endsWith("\"")) ||
|
|
@@ -54,6 +56,7 @@ export function resolveInstallTarget(options) {
|
|
|
54
56
|
if (target && isMarkdownFile(target)) {
|
|
55
57
|
const destDir = dirname(target);
|
|
56
58
|
return {
|
|
59
|
+
platform: "cursor",
|
|
57
60
|
layout: "file",
|
|
58
61
|
rootDir: destDir,
|
|
59
62
|
destDir,
|
|
@@ -66,6 +69,7 @@ export function resolveInstallTarget(options) {
|
|
|
66
69
|
: target
|
|
67
70
|
: join(root, options.name);
|
|
68
71
|
return {
|
|
72
|
+
platform: "cursor",
|
|
69
73
|
layout: "cursor",
|
|
70
74
|
rootDir: root,
|
|
71
75
|
destDir,
|
|
@@ -78,6 +82,7 @@ export function resolveInstallTarget(options) {
|
|
|
78
82
|
if (isMarkdownFile(target)) {
|
|
79
83
|
const destDir = dirname(target);
|
|
80
84
|
return {
|
|
85
|
+
platform: "custom",
|
|
81
86
|
layout: "file",
|
|
82
87
|
rootDir: destDir,
|
|
83
88
|
destDir,
|
|
@@ -85,6 +90,7 @@ export function resolveInstallTarget(options) {
|
|
|
85
90
|
};
|
|
86
91
|
}
|
|
87
92
|
return {
|
|
93
|
+
platform: "custom",
|
|
88
94
|
layout: "flat",
|
|
89
95
|
rootDir: target,
|
|
90
96
|
destDir: target,
|
|
@@ -110,30 +116,121 @@ async function loadSkillSource() {
|
|
|
110
116
|
const name = parseSkillFrontmatterName(markdown) ?? "perf-skill";
|
|
111
117
|
return { markdown, name, path: skillPath };
|
|
112
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Install skill for a single platform
|
|
121
|
+
*/
|
|
122
|
+
async function installForPlatform(platform, options) {
|
|
123
|
+
const config = PLATFORM_CONFIGS[platform];
|
|
124
|
+
const { destDir, destFile } = getDestinationPath(config, options.cwd, options.scope, options.homeDir);
|
|
125
|
+
const target = {
|
|
126
|
+
platform,
|
|
127
|
+
layout: "platform",
|
|
128
|
+
rootDir: resolve(options.scope === "project" ? options.cwd : options.homeDir, config.folderStructure.root),
|
|
129
|
+
destDir,
|
|
130
|
+
destFile,
|
|
131
|
+
};
|
|
132
|
+
if (options.dryRun) {
|
|
133
|
+
return target;
|
|
134
|
+
}
|
|
135
|
+
// Check for reserved directories
|
|
136
|
+
if (isReservedCursorDir(destDir) || isReservedCursorDir(destFile)) {
|
|
137
|
+
throw new Error("Refusing to install into Cursor's reserved skills-cursor directory.");
|
|
138
|
+
}
|
|
139
|
+
// Create directory
|
|
140
|
+
await mkdir(destDir, { recursive: true });
|
|
141
|
+
// Check if file exists
|
|
142
|
+
if (!options.force && await fileExists(destFile)) {
|
|
143
|
+
throw new Error(`Skill already exists at ${destFile}. Use --force to overwrite.`);
|
|
144
|
+
}
|
|
145
|
+
// Render and write the skill file
|
|
146
|
+
const content = await renderSkillForPlatform(config);
|
|
147
|
+
await writeFile(destFile, content, "utf-8");
|
|
148
|
+
return target;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Run init command - supports multiple platforms
|
|
152
|
+
*/
|
|
113
153
|
export async function runInit(options) {
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
154
|
+
const cwd = process.cwd();
|
|
155
|
+
const home = homedir();
|
|
156
|
+
const scope = options.scope ?? "project";
|
|
157
|
+
const force = options.force ?? false;
|
|
158
|
+
const dryRun = options.dryRun ?? false;
|
|
159
|
+
// Legacy --cursor flag support (maps to cursor platform)
|
|
160
|
+
if (options.cursor && !options.platform) {
|
|
161
|
+
options.platform = "cursor";
|
|
162
|
+
}
|
|
163
|
+
// If platform specified
|
|
164
|
+
if (options.platform) {
|
|
165
|
+
if (!isPlatformValid(options.platform)) {
|
|
166
|
+
return {
|
|
167
|
+
success: false,
|
|
168
|
+
targets: [],
|
|
169
|
+
errors: [{ platform: options.platform, error: `Invalid platform: ${options.platform}. Valid: ${AI_PLATFORMS.join(", ")}` }],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
// Handle "all" platform
|
|
173
|
+
if (options.platform === "all") {
|
|
174
|
+
const platforms = getAllPlatforms();
|
|
175
|
+
const targets = [];
|
|
176
|
+
const errors = [];
|
|
177
|
+
for (const platform of platforms) {
|
|
178
|
+
try {
|
|
179
|
+
const target = await installForPlatform(platform, { scope, force, dryRun, cwd, homeDir: home });
|
|
180
|
+
targets.push(target);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
errors.push({
|
|
184
|
+
platform,
|
|
185
|
+
error: error instanceof Error ? error.message : String(error),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
success: errors.length === 0,
|
|
191
|
+
targets,
|
|
192
|
+
errors,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
// Single platform
|
|
196
|
+
try {
|
|
197
|
+
const target = await installForPlatform(options.platform, { scope, force, dryRun, cwd, homeDir: home });
|
|
198
|
+
return { success: true, targets: [target], errors: [] };
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
return {
|
|
202
|
+
success: false,
|
|
203
|
+
targets: [],
|
|
204
|
+
errors: [{ platform: options.platform, error: error instanceof Error ? error.message : String(error) }],
|
|
205
|
+
};
|
|
206
|
+
}
|
|
117
207
|
}
|
|
208
|
+
// Legacy: no platform specified, use target path or cursor flag
|
|
209
|
+
if (options.scope && !options.cursor && !options.platform) {
|
|
210
|
+
throw new Error("--scope is only supported with --cursor or --platform.");
|
|
211
|
+
}
|
|
212
|
+
const { markdown, name } = await loadSkillSource();
|
|
118
213
|
const target = resolveInstallTarget({
|
|
119
214
|
target: options.target,
|
|
120
215
|
cursor: options.cursor,
|
|
121
216
|
scope: options.scope,
|
|
122
217
|
name,
|
|
123
|
-
cwd
|
|
124
|
-
homeDir:
|
|
218
|
+
cwd,
|
|
219
|
+
homeDir: home,
|
|
125
220
|
});
|
|
126
221
|
if (isReservedCursorDir(target.destDir) || isReservedCursorDir(target.destFile)) {
|
|
127
222
|
throw new Error("Refusing to install into Cursor's reserved skills-cursor directory.");
|
|
128
223
|
}
|
|
129
|
-
if (
|
|
130
|
-
return target;
|
|
224
|
+
if (dryRun) {
|
|
225
|
+
return { success: true, targets: [target], errors: [] };
|
|
131
226
|
}
|
|
132
227
|
await mkdir(target.destDir, { recursive: true });
|
|
133
|
-
if (!
|
|
228
|
+
if (!force && await fileExists(target.destFile)) {
|
|
134
229
|
throw new Error(`Skill already exists at ${target.destFile}. Use --force to overwrite.`);
|
|
135
230
|
}
|
|
136
231
|
await writeFile(target.destFile, markdown, "utf-8");
|
|
137
|
-
return target;
|
|
232
|
+
return { success: true, targets: [target], errors: [] };
|
|
138
233
|
}
|
|
234
|
+
// Re-export types and constants for convenience
|
|
235
|
+
export { AI_PLATFORMS } from "./platforms.js";
|
|
139
236
|
//# sourceMappingURL=init.js.map
|
package/dist/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|