crewkit 1.1.3 → 1.1.5
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/package.json +1 -1
- package/skill/SKILL.md +109 -36
- package/skill/adapters/copilot.md +13 -10
- package/skill/adapters/cursor.md +10 -7
- package/skill/copilot-agent.md +142 -0
- package/skill/cursor-global.md +157 -0
- package/skill/packs/analytics/pack.json +7 -0
- package/skill/packs/quality/pack.json +7 -0
- package/skill/packs/security/pack.json +7 -0
- package/src/add.js +85 -21
- package/src/cli.js +14 -6
- package/src/constants.js +1 -0
- package/src/detect.js +25 -0
- package/src/install.js +50 -28
- package/src/list.js +75 -0
- package/src/prompt.js +32 -0
- package/src/update.js +13 -8
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -51,16 +51,36 @@ If `.claude/` or `CLAUDE.md` or `.ai/memory/` exists:
|
|
|
51
51
|
3. Report: "Existing setup backed up to `.crewkit-backup/`"
|
|
52
52
|
|
|
53
53
|
### Create directory structure
|
|
54
|
+
Create directories based on the **selected IDE targets** from Phase 1:
|
|
55
|
+
|
|
56
|
+
**Always:**
|
|
57
|
+
```
|
|
58
|
+
.ai/
|
|
59
|
+
memory/
|
|
60
|
+
plans/
|
|
61
|
+
.crewkit/
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**If Claude Code is a selected target:**
|
|
54
65
|
```
|
|
55
66
|
.claude/
|
|
56
67
|
agents/
|
|
57
68
|
hooks/
|
|
58
69
|
rules/
|
|
59
70
|
skills/
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**If GitHub Copilot is a selected target:**
|
|
74
|
+
```
|
|
75
|
+
.github/
|
|
76
|
+
agents/
|
|
77
|
+
instructions/
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**If Cursor is a selected target:**
|
|
81
|
+
```
|
|
82
|
+
.cursor/
|
|
83
|
+
rules/
|
|
64
84
|
```
|
|
65
85
|
|
|
66
86
|
### Version tracking
|
|
@@ -144,22 +164,38 @@ Read `package.json` scripts, CI configs, or Makefiles to find the actual command
|
|
|
144
164
|
|
|
145
165
|
### IDE Target Detection
|
|
146
166
|
|
|
147
|
-
Detect which IDEs are
|
|
167
|
+
Detect which IDEs are available. Check **two sources**: project-level signals AND global install markers.
|
|
148
168
|
|
|
149
|
-
| IDE |
|
|
150
|
-
|
|
151
|
-
| Claude Code |
|
|
152
|
-
| GitHub Copilot | `.github/` directory exists OR `.github/copilot-instructions.md` found |
|
|
153
|
-
| Cursor | `.cursor/` directory exists OR `.cursorrules` file found |
|
|
169
|
+
| IDE | Project signals | Global install marker |
|
|
170
|
+
|-----|----------------|----------------------|
|
|
171
|
+
| Claude Code | `.claude/` directory exists | `~/.claude/skills/crewkit-setup/` exists |
|
|
172
|
+
| GitHub Copilot | `.github/` directory exists OR `.github/copilot-instructions.md` found | `~/.copilot/agents/crewkit-setup.md` exists |
|
|
173
|
+
| Cursor | `.cursor/` directory exists OR `.cursorrules` file found | `~/.cursor/crewkit-setup.md` exists |
|
|
154
174
|
|
|
155
|
-
|
|
175
|
+
An IDE is **available** if ANY of its signals match (project OR global).
|
|
176
|
+
|
|
177
|
+
**IDE target selection (exception to zero-questions rule):**
|
|
178
|
+
|
|
179
|
+
If more than one IDE is available, present the user with a choice:
|
|
180
|
+
|
|
181
|
+
> "Multiple IDEs detected. Generate context for which?"
|
|
182
|
+
> - **[1] Claude Code**
|
|
183
|
+
> - **[2] GitHub Copilot**
|
|
184
|
+
> - **[3] Cursor**
|
|
185
|
+
> - **[4] All detected**
|
|
186
|
+
>
|
|
187
|
+
> (Only show IDEs that were detected. Default: all detected.)
|
|
188
|
+
|
|
189
|
+
If only one IDE is available, use it without asking.
|
|
190
|
+
|
|
191
|
+
Save the **selected** IDE targets to scan data. Example:
|
|
156
192
|
```
|
|
157
|
-
IDE targets:
|
|
193
|
+
IDE targets selected: GitHub Copilot
|
|
158
194
|
```
|
|
159
195
|
|
|
160
196
|
**Store results as: `ReconProfile`** — write to `.crewkit/scan-phase1-recon.md` for persistence.
|
|
161
197
|
|
|
162
|
-
Report: "Phase 1 complete. Detected: [stacks], [CI], [DBs], [build/test commands]."
|
|
198
|
+
Report: "Phase 1 complete. Detected: [stacks], [CI], [DBs], [build/test commands]. IDE target: [selected IDEs]."
|
|
163
199
|
|
|
164
200
|
---
|
|
165
201
|
|
|
@@ -409,8 +445,8 @@ Compile all profiles into a single summary and present it to the user.
|
|
|
409
445
|
- Test: `[command]`
|
|
410
446
|
- Dev server: `[command]` (if detected)
|
|
411
447
|
|
|
412
|
-
## IDE Targets
|
|
413
|
-
- [list
|
|
448
|
+
## IDE Targets (selected)
|
|
449
|
+
- [list selected IDE targets — e.g., "GitHub Copilot" or "Claude Code, Cursor"]
|
|
414
450
|
```
|
|
415
451
|
|
|
416
452
|
### Save profile
|
|
@@ -437,9 +473,16 @@ This step is critical for large projects where context compaction may have evict
|
|
|
437
473
|
|
|
438
474
|
---
|
|
439
475
|
|
|
440
|
-
Generate
|
|
476
|
+
Generate files based on the **selected IDE targets** from Phase 1. The generation order is designed for **graceful failure** — if the process is interrupted, the user has the most valuable files first.
|
|
441
477
|
|
|
442
|
-
**
|
|
478
|
+
**IDE-conditional generation:**
|
|
479
|
+
- **Step 1** (`.ai/memory/`): ALWAYS — shared across all IDEs.
|
|
480
|
+
- **Steps 2-9** (CLAUDE.md, `.claude/agents/`, `.claude/rules/`, `.claude/settings.json`, `.claude/hooks/`, `.claude/skills/`, `.claude/QUICKSTART.md`, `.mcp.json`): ONLY if **Claude Code** is a selected target.
|
|
481
|
+
- **Step 10** (IDE Adapters): Runs for each non-Claude IDE in the selected targets. Adapters generate directly from scan data + `.ai/memory/` — they do NOT depend on Claude files existing.
|
|
482
|
+
|
|
483
|
+
If the only selected target is GitHub Copilot or Cursor, Steps 2-9 are **skipped entirely**. The adapter generates the IDE-native files directly.
|
|
484
|
+
|
|
485
|
+
**If the user chose [M] (memory only):** generate Step 1 (memory) + the project rules file for the selected IDE (CLAUDE.md / copilot-instructions.md / .cursor/rules/project.md), then update context headers in existing agents. Stop after that.
|
|
443
486
|
|
|
444
487
|
### Templates directory
|
|
445
488
|
Templates are located at `~/.claude/skills/crewkit-setup/templates/`. Read them from disk.
|
|
@@ -591,6 +634,8 @@ Create empty `lessons-{stack}.md` files for each detected stack.
|
|
|
591
634
|
|
|
592
635
|
### Step 2 — `CLAUDE.md` (AI-generated from scan)
|
|
593
636
|
|
|
637
|
+
> **Conditional:** Skip this step if Claude Code is NOT a selected IDE target. Jump to Step 10.
|
|
638
|
+
|
|
594
639
|
Generate the project's root `CLAUDE.md`. This is the most important generated file — it defines the AI's behavior for this project.
|
|
595
640
|
|
|
596
641
|
**Structure:**
|
|
@@ -1001,15 +1046,20 @@ For any placeholder tokens, add a comment in the profile or tell the user to fil
|
|
|
1001
1046
|
|
|
1002
1047
|
### Step 10 — IDE Adapters
|
|
1003
1048
|
|
|
1004
|
-
|
|
1049
|
+
For each **non-Claude IDE** in the selected targets (GitHub Copilot, Cursor):
|
|
1005
1050
|
|
|
1006
|
-
1. For each
|
|
1051
|
+
1. For each selected non-Claude IDE target:
|
|
1007
1052
|
a. Determine the adapter file path: `~/.claude/skills/crewkit-setup/adapters/{ide}.md`
|
|
1008
1053
|
- GitHub Copilot → `adapters/copilot.md`
|
|
1009
1054
|
- Cursor → `adapters/cursor.md`
|
|
1010
1055
|
b. If the adapter file does not exist: WARN the user ("Adapter file not found for [IDE] — skipping") and continue to the next IDE. Do not fail.
|
|
1011
|
-
c. If the adapter file exists: read it completely, then MANDATORY: follow ALL instructions in it.
|
|
1012
|
-
|
|
1056
|
+
c. If the adapter file exists: read it completely, then MANDATORY: follow ALL instructions in it.
|
|
1057
|
+
|
|
1058
|
+
**Source of truth for adapters (in priority order):**
|
|
1059
|
+
1. If Claude Code files exist (Steps 2-9 were generated): use them as the primary source, converting content to the target IDE format.
|
|
1060
|
+
2. If Claude Code files do NOT exist (Claude was not a selected target): generate IDE-native files directly from `.crewkit/last-scan.md` + `.ai/memory/` (Step 1). The adapter instructions describe the expected output format — use scan data to fill in the content instead of reformatting Claude files.
|
|
1061
|
+
|
|
1062
|
+
If no non-Claude IDE targets were selected, skip this step entirely.
|
|
1013
1063
|
|
|
1014
1064
|
**Note:** The adapters do NOT duplicate `.ai/memory/` — that directory is shared across all IDEs without transformation.
|
|
1015
1065
|
|
|
@@ -1022,8 +1072,12 @@ After all generation steps, run the **Completion Checklist** (at the bottom of t
|
|
|
1022
1072
|
```markdown
|
|
1023
1073
|
# crewkit setup complete
|
|
1024
1074
|
|
|
1025
|
-
##
|
|
1075
|
+
## IDE target: [selected IDE(s)]
|
|
1076
|
+
|
|
1077
|
+
## Generated files (shared)
|
|
1026
1078
|
- `.ai/memory/` — [N] files (architecture, conventions, commands, testing, lessons, state)
|
|
1079
|
+
|
|
1080
|
+
## Generated files (Claude Code) — only if selected
|
|
1027
1081
|
- `CLAUDE.md` — project rules ([N] hard rules)
|
|
1028
1082
|
- `.claude/agents/` — 5 agents (explorer, architect, coder, tester, reviewer)
|
|
1029
1083
|
- `.claude/rules/` — [N] rule files ([list stacks])
|
|
@@ -1033,20 +1087,29 @@ After all generation steps, run the **Completion Checklist** (at the bottom of t
|
|
|
1033
1087
|
- `.claude/napkin.md` — priorities board
|
|
1034
1088
|
- `.claude/QUICKSTART.md` — onboarding guide
|
|
1035
1089
|
- `.mcp.json` — [N] MCP servers
|
|
1036
|
-
|
|
1090
|
+
|
|
1091
|
+
## Generated files (GitHub Copilot) — only if selected
|
|
1092
|
+
- `.github/copilot-instructions.md` — project rules
|
|
1093
|
+
- `.github/instructions/` — [N] per-stack instruction files
|
|
1094
|
+
- `.github/agents/` — 5 agent files
|
|
1095
|
+
|
|
1096
|
+
## Generated files (Cursor) — only if selected
|
|
1097
|
+
- `.cursor/rules/project.md` — project rules
|
|
1098
|
+
- `.cursor/rules/` — [N] per-stack rule files
|
|
1099
|
+
- `AGENTS.md` — all agents
|
|
1100
|
+
|
|
1101
|
+
## Validation: [X]/[Y] checks passed
|
|
1037
1102
|
|
|
1038
1103
|
## Commands detected
|
|
1039
1104
|
- Build: `[command]`
|
|
1040
1105
|
- Test: `[command]`
|
|
1041
1106
|
|
|
1042
|
-
## Recommended MCPs to configure
|
|
1043
|
-
[List MCPs with placeholder tokens that need user input]
|
|
1044
|
-
|
|
1045
1107
|
## Next steps
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1108
|
+
[Adapt next steps to the selected IDE:]
|
|
1109
|
+
- Claude Code: "Review CLAUDE.md → run /full-workflow"
|
|
1110
|
+
- Copilot: "Review .github/copilot-instructions.md → open Copilot Chat"
|
|
1111
|
+
- Cursor: "Review .cursor/rules/project.md → start coding"
|
|
1112
|
+
- All: "Commit the setup"
|
|
1050
1113
|
```
|
|
1051
1114
|
|
|
1052
1115
|
---
|
|
@@ -1065,27 +1128,37 @@ After all generation steps, run the **Completion Checklist** (at the bottom of t
|
|
|
1065
1128
|
|
|
1066
1129
|
Before presenting the Final Report, go through EVERY item. Fix failures before reporting.
|
|
1067
1130
|
|
|
1068
|
-
### Content checks
|
|
1131
|
+
### Content checks (shared — always verify)
|
|
1069
1132
|
- [ ] `.ai/memory/architecture.md` — has constructor/DI signatures table (if project uses DI)
|
|
1070
1133
|
- [ ] `.ai/memory/conventions.md` — has Design System section (if frontend detected)
|
|
1071
1134
|
- [ ] `.ai/memory/testing.md` — has Fakes/Stubs inventory table (if test doubles detected)
|
|
1072
1135
|
- [ ] `.ai/memory/commands.md` — has build + test + dev commands for ALL detected stacks
|
|
1136
|
+
|
|
1137
|
+
### Content checks (Claude Code — only if Claude is a selected target)
|
|
1073
1138
|
- [ ] `CLAUDE.md` — hard rules present, all in English
|
|
1074
1139
|
- [ ] `.claude/agents/` — all 5 have `crewkit:context-start` header with real project data
|
|
1075
1140
|
- [ ] `.claude/QUICKSTART.md` — exists with workflow guide
|
|
1076
1141
|
|
|
1077
|
-
### Validation checks (
|
|
1142
|
+
### Validation checks (Claude Code — only if Claude is a selected target)
|
|
1078
1143
|
- [ ] `.claude/settings.json` — read back, verify valid JSON, has Write(.ai/memory/*), has stack permissions, has MCP permissions (Layer 4)
|
|
1079
1144
|
- [ ] `.mcp.json` — read back, verify valid JSON, has context7
|
|
1080
1145
|
- [ ] `.claude/hooks/*.sh` — run `bash -n` on each, all 4 pass syntax check
|
|
1081
1146
|
- [ ] `.claude/rules/` — at least 1 per detected stack, glob patterns match real files in project
|
|
1082
1147
|
- [ ] `.claude/skills/` — all 4 core skills have SKILL.md
|
|
1083
1148
|
|
|
1084
|
-
###
|
|
1149
|
+
### Content checks (Copilot — only if Copilot is a selected target)
|
|
1150
|
+
- [ ] `.github/copilot-instructions.md` — exists, contains project hard rules, no Claude-specific sections
|
|
1151
|
+
- [ ] `.github/instructions/` — at least 1 per detected stack with `applyTo:` frontmatter
|
|
1152
|
+
- [ ] `.github/agents/` — 5 agent files with `.agent.md` extension, no `model:` lines
|
|
1153
|
+
|
|
1154
|
+
### Content checks (Cursor — only if Cursor is a selected target)
|
|
1155
|
+
- [ ] `.cursor/rules/project.md` — exists, has `alwaysApply: true` frontmatter, no Claude-specific sections
|
|
1156
|
+
- [ ] `.cursor/rules/` — at least 1 per detected stack with `globs:` frontmatter
|
|
1157
|
+
- [ ] `AGENTS.md` — exists at project root with all 5 agents as `##` sections
|
|
1158
|
+
|
|
1159
|
+
### Integrity checks (always)
|
|
1085
1160
|
- [ ] `.crewkit/last-scan.md` — exists with full profile including Domain section
|
|
1086
1161
|
- [ ] `.crewkit/scan-phase*.md` — all 4 phase files exist with content
|
|
1087
1162
|
- [ ] No Portuguese in any generated file (only in user-facing output)
|
|
1088
|
-
- [ ] If Copilot target detected: `.github/copilot-instructions.md` exists and contains the project hard rules
|
|
1089
|
-
- [ ] If Cursor target detected: `.cursor/rules/project.md` exists and has `alwaysApply: true` frontmatter
|
|
1090
1163
|
|
|
1091
|
-
|
|
1164
|
+
Count only the checks applicable to the selected IDE targets. Report as: "Validation: X/Y checks passed." If any failed, list which ones and why.
|
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
This adapter is executed during Phase 7, Step 10 of `/crewkit-setup`.
|
|
4
4
|
You are the AI. Follow every instruction in this file to generate GitHub Copilot-compatible context files.
|
|
5
5
|
|
|
6
|
-
**Input
|
|
7
|
-
**
|
|
6
|
+
**Input (two modes):**
|
|
7
|
+
- **With Claude files:** If `CLAUDE.md` and `.claude/` exist (Claude Code was also a target), use them as primary source and reformat for Copilot.
|
|
8
|
+
- **Standalone:** If Claude files do NOT exist, generate directly from `.crewkit/last-scan.md` (project profile) + `.ai/memory/` (architecture, conventions, commands). This is the primary source of truth.
|
|
9
|
+
|
|
10
|
+
**Output:** Files under `.github/` — GitHub Copilot-native context files.
|
|
8
11
|
|
|
9
12
|
---
|
|
10
13
|
|
|
@@ -20,15 +23,15 @@ You are the AI. Follow every instruction in this file to generate GitHub Copilot
|
|
|
20
23
|
|
|
21
24
|
## Step C1 — `.github/copilot-instructions.md`
|
|
22
25
|
|
|
23
|
-
**Source:** `CLAUDE.md`
|
|
24
|
-
**Transformation:**
|
|
26
|
+
**Source:** `CLAUDE.md` if it exists, otherwise `.crewkit/last-scan.md` + `.ai/memory/conventions.md`
|
|
27
|
+
**Transformation:** If using CLAUDE.md, reformat for Copilot — remove Agent Discipline, Skills (slash commands), Architect Decision Gate, and Test Safety Loop sections (Claude Code-specific). Keep hard rules, overview, memory loading instructions, and output format. If generating from scan data, create the content directly using the project profile and conventions.
|
|
25
28
|
|
|
26
29
|
**Expected output format:**
|
|
27
30
|
```markdown
|
|
28
31
|
# [PROJECT NAME] — Copilot Instructions
|
|
29
32
|
|
|
30
33
|
## Overview
|
|
31
|
-
[1-2 sentences
|
|
34
|
+
[1-2 sentences — what the project is, main stack]
|
|
32
35
|
[Business domain: what it does, core entities, risk profile]
|
|
33
36
|
|
|
34
37
|
**Stack:** [stacks]
|
|
@@ -38,7 +41,7 @@ You are the AI. Follow every instruction in this file to generate GitHub Copilot
|
|
|
38
41
|
|
|
39
42
|
## Hard rules (apply to every response)
|
|
40
43
|
|
|
41
|
-
[Numbered list —
|
|
44
|
+
[Numbered list of non-negotiable rules — from CLAUDE.md or from HIGH confidence patterns in scan data.]
|
|
42
45
|
|
|
43
46
|
1. [Rule 1]
|
|
44
47
|
2. [Rule 2]
|
|
@@ -85,8 +88,8 @@ Always return:
|
|
|
85
88
|
|
|
86
89
|
## Step C2 — `.github/instructions/*.instructions.md`
|
|
87
90
|
|
|
88
|
-
**Source:** `.claude/rules/*.md`
|
|
89
|
-
**Transformation:**
|
|
91
|
+
**Source:** `.claude/rules/*.md` if they exist, otherwise generate directly from scan data (detected stacks + HIGH/MEDIUM confidence patterns).
|
|
92
|
+
**Transformation:** If using Claude rules, convert frontmatter to Copilot format — keep glob patterns and rule content unchanged. If generating from scan data, create one instructions file per detected stack with appropriate glob patterns and rules.
|
|
90
93
|
|
|
91
94
|
Claude Code frontmatter format:
|
|
92
95
|
```markdown
|
|
@@ -142,8 +145,8 @@ applyTo: "src/**/*.{js,ts}"
|
|
|
142
145
|
|
|
143
146
|
## Step C3 — `.github/agents/*.agent.md`
|
|
144
147
|
|
|
145
|
-
**Source:** `.claude/agents/*.md`
|
|
146
|
-
**Transformation:** Strip `model:` frontmatter line. Keep `name:` and `description:`. Remove the `<!-- crewkit:context-start -->...<!-- crewkit:context-end -->` block — Copilot agents do not use this inline context injection. Keep the full agent role description and instructions.
|
|
148
|
+
**Source:** `.claude/agents/*.md` if they exist, otherwise generate directly from the agent templates at `~/.claude/skills/crewkit-setup/templates/agents/` (or from scan data if templates are unavailable).
|
|
149
|
+
**Transformation:** Strip `model:` frontmatter line. Keep `name:` and `description:`. Remove the `<!-- crewkit:context-start -->...<!-- crewkit:context-end -->` block — Copilot agents do not use this inline context injection. Keep the full agent role description and instructions. When generating from templates, inject project context from `.crewkit/last-scan.md` into each agent.
|
|
147
150
|
|
|
148
151
|
**Copilot agent frontmatter format:**
|
|
149
152
|
```markdown
|
package/skill/adapters/cursor.md
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
This adapter is executed during Phase 7, Step 10 of `/crewkit-setup`.
|
|
4
4
|
You are the AI. Follow every instruction in this file to generate Cursor-compatible context files.
|
|
5
5
|
|
|
6
|
-
**Input
|
|
6
|
+
**Input (two modes):**
|
|
7
|
+
- **With Claude files:** If `CLAUDE.md` and `.claude/` exist (Claude Code was also a target), use them as primary source and reformat for Cursor.
|
|
8
|
+
- **Standalone:** If Claude files do NOT exist, generate directly from `.crewkit/last-scan.md` (project profile) + `.ai/memory/` (architecture, conventions, commands). This is the primary source of truth.
|
|
9
|
+
|
|
7
10
|
**Output:** Files under `.cursor/rules/` and `AGENTS.md` at the project root.
|
|
8
11
|
|
|
9
12
|
---
|
|
@@ -20,8 +23,8 @@ You are the AI. Follow every instruction in this file to generate Cursor-compati
|
|
|
20
23
|
|
|
21
24
|
## Step U1 — `.cursor/rules/project.md`
|
|
22
25
|
|
|
23
|
-
**Source:** `CLAUDE.md`
|
|
24
|
-
**Transformation:**
|
|
26
|
+
**Source:** `CLAUDE.md` if it exists, otherwise `.crewkit/last-scan.md` + `.ai/memory/conventions.md`
|
|
27
|
+
**Transformation:** If using CLAUDE.md, reformat for Cursor — add required frontmatter, remove agent/skill/hook sections. If generating from scan data, create the content directly using the project profile and conventions.
|
|
25
28
|
|
|
26
29
|
**Required Cursor frontmatter:**
|
|
27
30
|
```markdown
|
|
@@ -93,8 +96,8 @@ Always return:
|
|
|
93
96
|
|
|
94
97
|
## Step U2 — `.cursor/rules/*.md`
|
|
95
98
|
|
|
96
|
-
**Source:** `.claude/rules/*.md`
|
|
97
|
-
**Transformation:**
|
|
99
|
+
**Source:** `.claude/rules/*.md` if they exist, otherwise generate directly from scan data (detected stacks + HIGH/MEDIUM confidence patterns).
|
|
100
|
+
**Transformation:** If using Claude rules, convert frontmatter to Cursor format — keep glob patterns and rule content unchanged. If generating from scan data, create one rules file per detected stack with appropriate glob patterns and rules.
|
|
98
101
|
|
|
99
102
|
Claude Code frontmatter format:
|
|
100
103
|
```markdown
|
|
@@ -150,8 +153,8 @@ globs: "**/*.py"
|
|
|
150
153
|
|
|
151
154
|
## Step U3 — `AGENTS.md` (project root)
|
|
152
155
|
|
|
153
|
-
**Source:**
|
|
154
|
-
**Transformation:** Concatenate all agents into a single markdown file with `##` sections. Strip `model:` frontmatter from each. Remove the `<!-- crewkit:context-start -->...<!-- crewkit:context-end -->` block from each agent. Keep the `name:` and `description:` from frontmatter and all agent instructions.
|
|
156
|
+
**Source:** `.claude/agents/*.md` if they exist, otherwise generate directly from the agent templates at `~/.claude/skills/crewkit-setup/templates/agents/` (or from scan data if templates are unavailable).
|
|
157
|
+
**Transformation:** Concatenate all agents into a single markdown file with `##` sections. Strip `model:` frontmatter from each. Remove the `<!-- crewkit:context-start -->...<!-- crewkit:context-end -->` block from each agent. Keep the `name:` and `description:` from frontmatter and all agent instructions. When generating from templates, inject project context from `.crewkit/last-scan.md` into each agent.
|
|
155
158
|
|
|
156
159
|
**Output format:**
|
|
157
160
|
```markdown
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crewkit-setup
|
|
3
|
+
description: "Scan your codebase and generate a complete context engineering setup: agents, instructions, memory files, and copilot-instructions.md."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# crewkit-setup
|
|
7
|
+
|
|
8
|
+
Scan the current project and generate a complete context engineering setup tailored to this codebase.
|
|
9
|
+
|
|
10
|
+
**You are the AI executing this.** Follow each phase in order. Do not ask the user questions. Scan, generate, report.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Phase 1 — Reconnaissance
|
|
15
|
+
|
|
16
|
+
Scan the project to identify:
|
|
17
|
+
- **Stack & frameworks**: languages, build tools, test frameworks, package managers
|
|
18
|
+
- **Architecture**: monolith/microservices, key directories, entry points
|
|
19
|
+
- **Existing AI context**: any `.github/`, `.ai/`, `CLAUDE.md`, `AGENTS.md` files
|
|
20
|
+
|
|
21
|
+
Write findings to `.crewkit/scan-phase1-recon.md`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Phase 2 — Codebase Mapping
|
|
26
|
+
|
|
27
|
+
Read representative source files (3-5 per layer: models, services, controllers, tests). Identify:
|
|
28
|
+
- Naming conventions, code style
|
|
29
|
+
- Core domain concepts and entities
|
|
30
|
+
- Test patterns and coverage approach
|
|
31
|
+
- CI/CD and build commands
|
|
32
|
+
|
|
33
|
+
Write findings to `.crewkit/scan-phase2-map.md`.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Phase 3 — Profile Compilation
|
|
38
|
+
|
|
39
|
+
Synthesize phases 1-2 into a project profile:
|
|
40
|
+
- Stack summary
|
|
41
|
+
- Architecture summary
|
|
42
|
+
- Key commands (build, test, lint)
|
|
43
|
+
- Domain concepts
|
|
44
|
+
- Hard rules to enforce
|
|
45
|
+
|
|
46
|
+
Write profile to `.crewkit/last-scan.md`.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Phase 4 — File Generation
|
|
51
|
+
|
|
52
|
+
Generate all files using the profile from `.crewkit/last-scan.md`.
|
|
53
|
+
|
|
54
|
+
### Step 1 — `.ai/memory/`
|
|
55
|
+
|
|
56
|
+
Create these files (all in English):
|
|
57
|
+
- `architecture.md` — system design, key components, data flow
|
|
58
|
+
- `conventions.md` — naming rules, patterns, anti-patterns
|
|
59
|
+
- `commands.md` — build, test, lint, run commands with flags
|
|
60
|
+
- `testing.md` — test strategy, frameworks, coverage approach
|
|
61
|
+
- `lessons.md` — known gotchas, non-obvious behaviors
|
|
62
|
+
- `state.md` — current sprint goal, recent changes, open issues
|
|
63
|
+
|
|
64
|
+
### Step 2 — `.github/copilot-instructions.md`
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
# [PROJECT NAME] — Copilot Instructions
|
|
68
|
+
|
|
69
|
+
## Overview
|
|
70
|
+
[1-2 sentences: what the project is, main stack]
|
|
71
|
+
|
|
72
|
+
**Stack:** [stacks]
|
|
73
|
+
**Architecture:** [key patterns]
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Hard rules (apply to every response)
|
|
78
|
+
|
|
79
|
+
[Numbered list of non-negotiable rules]
|
|
80
|
+
|
|
81
|
+
Details → `.ai/memory/conventions.md`
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Memory
|
|
86
|
+
|
|
87
|
+
- `.ai/memory/architecture.md` — system design
|
|
88
|
+
- `.ai/memory/conventions.md` — coding conventions
|
|
89
|
+
- `.ai/memory/commands.md` — build/test commands
|
|
90
|
+
- `.ai/memory/lessons.md` — known gotchas
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Step 3 — `.github/instructions/` (per-stack rules)
|
|
94
|
+
|
|
95
|
+
For each detected stack, create `[stack].instructions.md`:
|
|
96
|
+
```markdown
|
|
97
|
+
---
|
|
98
|
+
applyTo: "**/*.ts"
|
|
99
|
+
---
|
|
100
|
+
[Stack-specific rules: error handling, imports, typing, testing patterns]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Step 4 — `.github/agents/` (agent definitions)
|
|
104
|
+
|
|
105
|
+
Create one file per agent: `explorer.agent.md`, `architect.agent.md`, `coder.agent.md`, `tester.agent.md`, `reviewer.agent.md`.
|
|
106
|
+
|
|
107
|
+
Each file:
|
|
108
|
+
```markdown
|
|
109
|
+
---
|
|
110
|
+
name: [Agent Name]
|
|
111
|
+
description: "[One-line role description]"
|
|
112
|
+
---
|
|
113
|
+
# [Agent Name]
|
|
114
|
+
|
|
115
|
+
**Role:** [role]
|
|
116
|
+
**Responsibilities:** [responsibilities]
|
|
117
|
+
**Approach:** [how it works]
|
|
118
|
+
**Output:** [what it produces]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Phase 5 — Completion Report
|
|
124
|
+
|
|
125
|
+
After all files are generated, report to the user:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
crewkit-setup complete
|
|
129
|
+
|
|
130
|
+
Generated:
|
|
131
|
+
.ai/memory/ (6 files)
|
|
132
|
+
.github/copilot-instructions.md
|
|
133
|
+
.github/instructions/ (per-stack rules)
|
|
134
|
+
.github/agents/ (5 agents)
|
|
135
|
+
|
|
136
|
+
Stack detected: [stack]
|
|
137
|
+
Architecture: [pattern]
|
|
138
|
+
|
|
139
|
+
Next steps:
|
|
140
|
+
1. Review .github/copilot-instructions.md — adjust hard rules if needed
|
|
141
|
+
2. Open Copilot Chat — context is now active
|
|
142
|
+
```
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Context engineering setup — scan codebase and generate AI context files (.cursor/rules, AGENTS.md, .ai/memory)"
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# crewkit-setup
|
|
7
|
+
|
|
8
|
+
Scan the current project and generate a complete context engineering setup tailored to this codebase.
|
|
9
|
+
|
|
10
|
+
**You are the AI executing this.** Follow each phase in order. Do not ask the user questions. Scan, generate, report.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Phase 1 — Reconnaissance
|
|
15
|
+
|
|
16
|
+
Scan the project to identify:
|
|
17
|
+
- **Stack & frameworks**: languages, build tools, test frameworks, package managers
|
|
18
|
+
- **Architecture**: monolith/microservices, key directories, entry points
|
|
19
|
+
- **Existing AI context**: any `.cursor/`, `.github/`, `.ai/`, `CLAUDE.md`, `AGENTS.md` files
|
|
20
|
+
|
|
21
|
+
Write findings to `.crewkit/scan-phase1-recon.md`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Phase 2 — Codebase Mapping
|
|
26
|
+
|
|
27
|
+
Read representative source files (3-5 per layer: models, services, controllers, tests). Identify:
|
|
28
|
+
- Naming conventions, code style
|
|
29
|
+
- Core domain concepts and entities
|
|
30
|
+
- Test patterns and coverage approach
|
|
31
|
+
- CI/CD and build commands
|
|
32
|
+
|
|
33
|
+
Write findings to `.crewkit/scan-phase2-map.md`.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Phase 3 — Profile Compilation
|
|
38
|
+
|
|
39
|
+
Synthesize phases 1-2 into a project profile:
|
|
40
|
+
- Stack summary
|
|
41
|
+
- Architecture summary
|
|
42
|
+
- Key commands (build, test, lint)
|
|
43
|
+
- Domain concepts
|
|
44
|
+
- Hard rules to enforce
|
|
45
|
+
|
|
46
|
+
Write profile to `.crewkit/last-scan.md`.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Phase 4 — File Generation
|
|
51
|
+
|
|
52
|
+
Generate all files using the profile from `.crewkit/last-scan.md`.
|
|
53
|
+
|
|
54
|
+
### Step 1 — `.ai/memory/`
|
|
55
|
+
|
|
56
|
+
Create these files (all in English):
|
|
57
|
+
- `architecture.md` — system design, key components, data flow
|
|
58
|
+
- `conventions.md` — naming rules, patterns, anti-patterns
|
|
59
|
+
- `commands.md` — build, test, lint, run commands with flags
|
|
60
|
+
- `testing.md` — test strategy, frameworks, coverage approach
|
|
61
|
+
- `lessons.md` — known gotchas, non-obvious behaviors
|
|
62
|
+
- `state.md` — current sprint goal, recent changes, open issues
|
|
63
|
+
|
|
64
|
+
### Step 2 — `.cursor/rules/project.md`
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
---
|
|
68
|
+
description: "Project rules"
|
|
69
|
+
alwaysApply: true
|
|
70
|
+
---
|
|
71
|
+
# [PROJECT NAME] — Project Rules
|
|
72
|
+
|
|
73
|
+
## Overview
|
|
74
|
+
[1-2 sentences: what the project is, main stack]
|
|
75
|
+
|
|
76
|
+
**Stack:** [stacks]
|
|
77
|
+
**Architecture:** [key patterns]
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Hard rules
|
|
82
|
+
|
|
83
|
+
[Numbered list of non-negotiable rules from the profile]
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Memory
|
|
88
|
+
|
|
89
|
+
Reference files in `.ai/memory/` for detailed context:
|
|
90
|
+
- `.ai/memory/architecture.md` — system design
|
|
91
|
+
- `.ai/memory/conventions.md` — coding conventions
|
|
92
|
+
- `.ai/memory/commands.md` — build/test commands
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Step 3 — `.cursor/rules/` (per-stack rules)
|
|
96
|
+
|
|
97
|
+
For each detected stack (e.g., `typescript.md`, `python.md`), generate a rules file with:
|
|
98
|
+
```
|
|
99
|
+
---
|
|
100
|
+
description: "[Stack] coding rules"
|
|
101
|
+
globs: ["**/*.ts"] (or appropriate glob)
|
|
102
|
+
alwaysApply: false
|
|
103
|
+
---
|
|
104
|
+
[Stack-specific rules: error handling, imports, typing, testing patterns]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Step 4 — `AGENTS.md`
|
|
108
|
+
|
|
109
|
+
Create a single `AGENTS.md` at the project root with all agents as `##` sections:
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
# Agents
|
|
113
|
+
|
|
114
|
+
## Explorer
|
|
115
|
+
Role: Codebase reconnaissance and research.
|
|
116
|
+
[...]
|
|
117
|
+
|
|
118
|
+
## Architect
|
|
119
|
+
Role: System design and planning.
|
|
120
|
+
[...]
|
|
121
|
+
|
|
122
|
+
## Coder
|
|
123
|
+
Role: Implementation.
|
|
124
|
+
[...]
|
|
125
|
+
|
|
126
|
+
## Tester
|
|
127
|
+
Role: Test writing and validation.
|
|
128
|
+
[...]
|
|
129
|
+
|
|
130
|
+
## Reviewer
|
|
131
|
+
Role: Code review and quality.
|
|
132
|
+
[...]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Each agent section should include: Role, Responsibilities, Approach, Output format.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Phase 5 — Completion Report
|
|
140
|
+
|
|
141
|
+
After all files are generated, report to the user:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
crewkit-setup complete
|
|
145
|
+
|
|
146
|
+
Generated:
|
|
147
|
+
.ai/memory/ (6 files)
|
|
148
|
+
.cursor/rules/ (project.md + per-stack rules)
|
|
149
|
+
AGENTS.md (5 agents)
|
|
150
|
+
|
|
151
|
+
Stack detected: [stack]
|
|
152
|
+
Architecture: [pattern]
|
|
153
|
+
|
|
154
|
+
Next steps:
|
|
155
|
+
1. Review .cursor/rules/project.md — adjust hard rules if needed
|
|
156
|
+
2. Open Cursor and start coding — context is active
|
|
157
|
+
```
|
package/src/add.js
CHANGED
|
@@ -1,45 +1,109 @@
|
|
|
1
|
-
import { cpSync, mkdirSync, existsSync } from 'node:fs';
|
|
1
|
+
import { cpSync, mkdirSync, existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
|
+
import { CORE_SKILLS } from './constants.js';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
function getOptionalSkills() {
|
|
7
|
+
const skillsDir = join(homedir(), '.claude', 'skills', 'crewkit-setup', 'templates', 'skills');
|
|
8
|
+
if (!existsSync(skillsDir)) return [];
|
|
9
|
+
return readdirSync(skillsDir, { withFileTypes: true })
|
|
10
|
+
.filter(d => d.isDirectory() && !CORE_SKILLS.includes(d.name))
|
|
11
|
+
.map(d => d.name);
|
|
12
|
+
}
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
function getAvailablePacks() {
|
|
15
|
+
const packsDir = join(homedir(), '.claude', 'skills', 'crewkit-setup', 'packs');
|
|
16
|
+
if (!existsSync(packsDir)) return [];
|
|
17
|
+
return readdirSync(packsDir, { withFileTypes: true })
|
|
18
|
+
.filter(d => d.isDirectory() && existsSync(join(packsDir, d.name, 'pack.json')))
|
|
19
|
+
.map(d => d.name);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function installSkill(skillName) {
|
|
23
|
+
const sourceDir = join(homedir(), '.claude', 'skills', 'crewkit-setup', 'templates', 'skills', skillName);
|
|
24
|
+
|
|
25
|
+
if (!existsSync(sourceDir)) {
|
|
26
|
+
console.error(`Error: source not found at ${sourceDir}`);
|
|
27
|
+
console.log(' Make sure crewkit is installed first: npx crewkit install');
|
|
11
28
|
process.exit(1);
|
|
12
29
|
}
|
|
13
30
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
31
|
+
const targetDir = join(process.cwd(), '.claude', 'skills', skillName);
|
|
32
|
+
|
|
33
|
+
if (existsSync(targetDir)) {
|
|
34
|
+
console.log(` Warning: ${targetDir} already exists. Overwriting.`);
|
|
18
35
|
}
|
|
19
36
|
|
|
20
|
-
|
|
37
|
+
mkdirSync(targetDir, { recursive: true });
|
|
38
|
+
cpSync(sourceDir, targetDir, { recursive: true, force: true });
|
|
39
|
+
|
|
40
|
+
return targetDir;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function installPack(packName) {
|
|
44
|
+
const packJson = join(homedir(), '.claude', 'skills', 'crewkit-setup', 'packs', packName, 'pack.json');
|
|
45
|
+
let pack;
|
|
46
|
+
try {
|
|
47
|
+
pack = JSON.parse(readFileSync(packJson, 'utf8'));
|
|
48
|
+
} catch {
|
|
49
|
+
console.error(`Error: invalid pack.json for "${packName}".`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const skills = pack.components?.skills ?? [];
|
|
21
53
|
|
|
22
|
-
|
|
23
|
-
|
|
54
|
+
const templatesDir = join(homedir(), '.claude', 'skills', 'crewkit-setup', 'templates', 'skills');
|
|
55
|
+
const missing = skills.filter(s => !existsSync(join(templatesDir, s)));
|
|
56
|
+
if (missing.length) {
|
|
57
|
+
console.error(`Error: pack "${packName}" references missing skills: ${missing.join(', ')}`);
|
|
24
58
|
console.log(' Make sure crewkit is installed first: npx crewkit install');
|
|
25
59
|
process.exit(1);
|
|
26
60
|
}
|
|
27
61
|
|
|
28
|
-
const
|
|
29
|
-
const
|
|
62
|
+
const installed = [];
|
|
63
|
+
for (const skillName of skills) {
|
|
64
|
+
const targetDir = installSkill(skillName);
|
|
65
|
+
installed.push({ name: skillName, path: targetDir });
|
|
66
|
+
}
|
|
30
67
|
|
|
31
|
-
|
|
32
|
-
|
|
68
|
+
console.log(`
|
|
69
|
+
✓ Pack "${packName}" installed (${installed.length} skill${installed.length !== 1 ? 's' : ''})
|
|
70
|
+
`);
|
|
71
|
+
for (const { name, path } of installed) {
|
|
72
|
+
console.log(` /${name} → ${path}`);
|
|
33
73
|
}
|
|
74
|
+
console.log('');
|
|
75
|
+
}
|
|
34
76
|
|
|
35
|
-
|
|
36
|
-
|
|
77
|
+
export function add(skillName) {
|
|
78
|
+
const availablePacks = getAvailablePacks();
|
|
79
|
+
const optionalSkills = getOptionalSkills();
|
|
37
80
|
|
|
38
|
-
|
|
81
|
+
if (!skillName) {
|
|
82
|
+
console.error('Error: skill name is required.');
|
|
83
|
+
console.log(`\n Available packs:\n${availablePacks.map(p => ` - ${p}`).join('\n')}`);
|
|
84
|
+
console.log(`\n Available optional skills:\n${optionalSkills.map(s => ` - ${s}`).join('\n')}\n`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (availablePacks.includes(skillName)) {
|
|
89
|
+
installPack(skillName);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (optionalSkills.includes(skillName)) {
|
|
94
|
+
const targetDir = installSkill(skillName);
|
|
95
|
+
console.log(`
|
|
39
96
|
✓ Skill "${skillName}" installed
|
|
40
97
|
|
|
41
|
-
Copied to: ${
|
|
98
|
+
Copied to: ${targetDir}
|
|
42
99
|
|
|
43
100
|
Use /${skillName} in Claude Code to run it.
|
|
44
101
|
`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.error(`Error: "${skillName}" is not a known pack or optional skill.`);
|
|
106
|
+
console.log(`\n Available packs:\n${availablePacks.map(p => ` - ${p}`).join('\n')}`);
|
|
107
|
+
console.log(`\n Available optional skills:\n${optionalSkills.map(s => ` - ${s}`).join('\n')}\n`);
|
|
108
|
+
process.exit(1);
|
|
45
109
|
}
|
package/src/cli.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { install } from './install.js';
|
|
2
2
|
import { update } from './update.js';
|
|
3
3
|
import { add } from './add.js';
|
|
4
|
+
import { list } from './list.js';
|
|
4
5
|
|
|
5
6
|
const HELP = `
|
|
6
7
|
crewkit — Context engineering for AI-assisted development
|
|
7
8
|
|
|
8
9
|
Commands:
|
|
9
|
-
install Install crewkit
|
|
10
|
+
install Install crewkit globally (Claude Code, Copilot, Cursor)
|
|
10
11
|
update Update to latest version (re-run install)
|
|
11
|
-
add <
|
|
12
|
+
add <name> Add an optional skill or pack to the current project
|
|
13
|
+
list List all available skills and packs (core + add-ons)
|
|
12
14
|
help Show this message
|
|
13
15
|
|
|
14
16
|
Usage:
|
|
15
17
|
npx crewkit install # one-time setup
|
|
18
|
+
npx crewkit list # see all available skills and packs
|
|
16
19
|
npx crewkit add retro # add optional skill to project
|
|
20
|
+
npx crewkit add quality # add a pack (multiple skills)
|
|
17
21
|
/crewkit-setup # run in your IDE to scan & calibrate a project
|
|
18
22
|
`;
|
|
19
23
|
|
|
@@ -22,14 +26,18 @@ export function run(args) {
|
|
|
22
26
|
|
|
23
27
|
switch (command) {
|
|
24
28
|
case 'install':
|
|
25
|
-
install();
|
|
26
|
-
|
|
29
|
+
install().catch(err => { console.error(err.message); process.exit(1); });
|
|
30
|
+
return;
|
|
31
|
+
|
|
27
32
|
case 'update':
|
|
28
|
-
update();
|
|
29
|
-
|
|
33
|
+
update().catch(err => { console.error(err.message); process.exit(1); });
|
|
34
|
+
return;
|
|
30
35
|
case 'add':
|
|
31
36
|
add(args[1]);
|
|
32
37
|
break;
|
|
38
|
+
case 'list':
|
|
39
|
+
list();
|
|
40
|
+
break;
|
|
33
41
|
case 'help':
|
|
34
42
|
case '--help':
|
|
35
43
|
case '-h':
|
package/src/constants.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CORE_SKILLS = ['full-workflow', 'hotfix', 'explore-and-plan', 'review-pr'];
|
package/src/detect.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
|
|
5
|
+
export function detectTools() {
|
|
6
|
+
const tools = [];
|
|
7
|
+
const home = homedir();
|
|
8
|
+
|
|
9
|
+
if (existsSync(join(home, '.claude'))) {
|
|
10
|
+
const dest = join(home, '.claude', 'skills', 'crewkit-setup');
|
|
11
|
+
tools.push({ id: 'claude', name: 'Claude Code', dest, versionFile: join(dest, '.version') });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (existsSync(join(home, '.copilot'))) {
|
|
15
|
+
const dest = join(home, '.copilot', 'agents');
|
|
16
|
+
tools.push({ id: 'copilot', name: 'GitHub Copilot', dest, versionFile: join(dest, 'crewkit-setup.version') });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (existsSync(join(home, '.cursor'))) {
|
|
20
|
+
const dest = join(home, '.cursor');
|
|
21
|
+
tools.push({ id: 'cursor', name: 'Cursor', dest, versionFile: join(dest, 'crewkit-setup.version') });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return tools;
|
|
25
|
+
}
|
package/src/install.js
CHANGED
|
@@ -1,43 +1,65 @@
|
|
|
1
|
-
import { cpSync, mkdirSync,
|
|
1
|
+
import { cpSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from 'node:fs';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { detectTools } from './detect.js';
|
|
5
|
+
import { selectTargets } from './prompt.js';
|
|
5
6
|
|
|
6
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
8
|
const __dirname = dirname(__filename);
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// Verify source exists
|
|
14
|
-
if (!existsSync(skillSource)) {
|
|
15
|
-
console.error('Error: skill/ directory not found. Package may be corrupted.');
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Create destination
|
|
20
|
-
mkdirSync(skillDest, { recursive: true });
|
|
10
|
+
function readVersion() {
|
|
11
|
+
return JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8')).version;
|
|
12
|
+
}
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
function installClaude(target, version) {
|
|
15
|
+
const skillSource = join(__dirname, '..', 'skill');
|
|
16
|
+
mkdirSync(target.dest, { recursive: true });
|
|
17
|
+
cpSync(skillSource, target.dest, { recursive: true, force: true });
|
|
18
|
+
writeFileSync(target.versionFile, version, 'utf8');
|
|
19
|
+
console.log(` ✓ Claude Code → ${target.dest}`);
|
|
20
|
+
console.log(` Run /crewkit-setup in any project\n`);
|
|
21
|
+
}
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
const
|
|
23
|
+
function installSingleFile(target, templateFile, outputFile, label, hint, version) {
|
|
24
|
+
const template = join(__dirname, '..', 'skill', templateFile);
|
|
25
|
+
mkdirSync(target.dest, { recursive: true });
|
|
26
|
+
copyFileSync(template, join(target.dest, outputFile));
|
|
27
|
+
writeFileSync(target.versionFile, version, 'utf8');
|
|
28
|
+
console.log(` ✓ ${label} → ${join(target.dest, outputFile)}`);
|
|
29
|
+
console.log(` ${hint}\n`);
|
|
30
|
+
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
export async function install() {
|
|
33
|
+
const version = readVersion();
|
|
34
|
+
const tools = detectTools();
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
if (tools.length === 0) {
|
|
37
|
+
console.log(`
|
|
38
|
+
No supported AI tools detected.
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
crewkit looks for: ~/.claude, ~/.copilot, ~/.cursor
|
|
41
|
+
Install one of these tools and re-run.
|
|
42
|
+
`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
const targets = await selectTargets(tools);
|
|
37
47
|
|
|
38
|
-
|
|
48
|
+
console.log(`\n Installing crewkit v${version}...\n`);
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
for (const target of targets) {
|
|
51
|
+
switch (target.id) {
|
|
52
|
+
case 'claude':
|
|
53
|
+
installClaude(target, version);
|
|
54
|
+
break;
|
|
55
|
+
case 'copilot':
|
|
56
|
+
installSingleFile(target, 'copilot-agent.md', 'crewkit-setup.md',
|
|
57
|
+
'GitHub Copilot ', 'Use @crewkit-setup in Copilot CLI or Chat', version);
|
|
58
|
+
break;
|
|
59
|
+
case 'cursor':
|
|
60
|
+
installSingleFile(target, 'cursor-global.md', 'crewkit-setup.md',
|
|
61
|
+
'Cursor ', 'Copy to .cursor/rules/ in your projects', version);
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
43
65
|
}
|
package/src/list.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { CORE_SKILLS } from './constants.js';
|
|
5
|
+
|
|
6
|
+
function readDescription(skillDir) {
|
|
7
|
+
const skillMd = join(skillDir, 'SKILL.md');
|
|
8
|
+
if (!existsSync(skillMd)) return '';
|
|
9
|
+
const content = readFileSync(skillMd, 'utf8');
|
|
10
|
+
const match = content.match(/^---[\s\S]*?^description:\s*"?(.+?)"?\s*$/m);
|
|
11
|
+
if (!match) return '';
|
|
12
|
+
const desc = match[1].trim();
|
|
13
|
+
return desc.length > 45 ? desc.slice(0, 44) + '…' : desc;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getAvailablePacks() {
|
|
17
|
+
const packsDir = join(homedir(), '.claude', 'skills', 'crewkit-setup', 'packs');
|
|
18
|
+
if (!existsSync(packsDir)) return [];
|
|
19
|
+
return readdirSync(packsDir, { withFileTypes: true })
|
|
20
|
+
.filter(d => d.isDirectory() && existsSync(join(packsDir, d.name, 'pack.json')))
|
|
21
|
+
.map(d => {
|
|
22
|
+
try {
|
|
23
|
+
const pack = JSON.parse(readFileSync(join(packsDir, d.name, 'pack.json'), 'utf8'));
|
|
24
|
+
return { name: d.name, description: pack.description ?? '', skills: pack.components?.skills ?? [] };
|
|
25
|
+
} catch {
|
|
26
|
+
return { name: d.name, description: '(invalid pack.json)', skills: [] };
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function list() {
|
|
32
|
+
const skillsDir = join(homedir(), '.claude', 'skills', 'crewkit-setup', 'templates', 'skills');
|
|
33
|
+
|
|
34
|
+
if (!existsSync(skillsDir)) {
|
|
35
|
+
console.error('Error: crewkit templates not found.');
|
|
36
|
+
console.log(' Make sure crewkit is installed first: npx crewkit install');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const allDirs = readdirSync(skillsDir, { withFileTypes: true })
|
|
41
|
+
.filter(d => d.isDirectory())
|
|
42
|
+
.map(d => d.name);
|
|
43
|
+
|
|
44
|
+
const coreSkills = CORE_SKILLS.filter(s => allDirs.includes(s));
|
|
45
|
+
const addonSkills = allDirs.filter(s => !CORE_SKILLS.includes(s)).sort();
|
|
46
|
+
const packs = getAvailablePacks();
|
|
47
|
+
|
|
48
|
+
const pad = (name, width) => name + ' '.repeat(Math.max(1, width - name.length));
|
|
49
|
+
const nameWidth = Math.max(...[...coreSkills, ...addonSkills, ...packs.map(p => p.name)].map(s => s.length)) + 2;
|
|
50
|
+
|
|
51
|
+
console.log('\ncrewkit — available components\n');
|
|
52
|
+
|
|
53
|
+
console.log(' Core skills (installed by /crewkit-setup):');
|
|
54
|
+
for (const name of coreSkills) {
|
|
55
|
+
const desc = readDescription(join(skillsDir, name));
|
|
56
|
+
console.log(` ${pad(name, nameWidth)}${desc}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log('\n Add-on skills (install with: npx crewkit add <name>):');
|
|
60
|
+
for (const name of addonSkills) {
|
|
61
|
+
const desc = readDescription(join(skillsDir, name));
|
|
62
|
+
console.log(` ${pad(name, nameWidth)}${desc}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (packs.length > 0) {
|
|
66
|
+
console.log('\n Packs (install with: npx crewkit add <name>):');
|
|
67
|
+
for (const { name, description, skills } of packs) {
|
|
68
|
+
const desc = description.length > 45 ? description.slice(0, 44) + '…' : description;
|
|
69
|
+
const contents = skills.length > 0 ? ` [${skills.join(', ')}]` : '';
|
|
70
|
+
console.log(` ${pad(name, nameWidth)}${desc}${contents}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log('');
|
|
75
|
+
}
|
package/src/prompt.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline';
|
|
2
|
+
|
|
3
|
+
function ask(question) {
|
|
4
|
+
return new Promise(resolve => {
|
|
5
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
6
|
+
rl.question(question, answer => {
|
|
7
|
+
rl.close();
|
|
8
|
+
resolve(answer.trim());
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function selectTargets(tools) {
|
|
14
|
+
if (tools.length === 0) return [];
|
|
15
|
+
if (tools.length === 1) return [tools[0]];
|
|
16
|
+
|
|
17
|
+
console.log('\n Multiple AI tools detected. Where do you want to install crewkit?\n');
|
|
18
|
+
tools.forEach((tool, i) => {
|
|
19
|
+
console.log(` [${i + 1}] ${tool.name}`);
|
|
20
|
+
});
|
|
21
|
+
console.log(` [${tools.length + 1}] All of the above`);
|
|
22
|
+
console.log();
|
|
23
|
+
|
|
24
|
+
const answer = await ask(' Your choice: ');
|
|
25
|
+
const num = parseInt(answer, 10);
|
|
26
|
+
|
|
27
|
+
if (num === tools.length + 1) return tools;
|
|
28
|
+
if (num >= 1 && num <= tools.length) return [tools[num - 1]];
|
|
29
|
+
|
|
30
|
+
console.log(' Invalid choice. Installing to all detected tools.');
|
|
31
|
+
return tools;
|
|
32
|
+
}
|
package/src/update.js
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { detectTools } from './detect.js';
|
|
5
5
|
import { install } from './install.js';
|
|
6
6
|
|
|
7
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
8
|
const __dirname = dirname(__filename);
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
10
|
+
function getInstalledVersion() {
|
|
11
|
+
for (const tool of detectTools()) {
|
|
12
|
+
if (existsSync(tool.versionFile)) {
|
|
13
|
+
return readFileSync(tool.versionFile, 'utf8').trim();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return 'unknown';
|
|
17
|
+
}
|
|
13
18
|
|
|
19
|
+
export async function update() {
|
|
20
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
|
|
14
21
|
const newVersion = pkg.version;
|
|
15
|
-
const currentVersion =
|
|
16
|
-
? readFileSync(versionFile, 'utf8').trim()
|
|
17
|
-
: 'unknown';
|
|
22
|
+
const currentVersion = getInstalledVersion();
|
|
18
23
|
|
|
19
24
|
if (currentVersion === newVersion) {
|
|
20
25
|
console.log(` Already up to date (v${newVersion})`);
|
|
21
26
|
return;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
install();
|
|
29
|
+
await install();
|
|
25
30
|
|
|
26
31
|
const fromLabel = currentVersion === 'unknown' ? 'v0.1 (untracked)' : `v${currentVersion}`;
|
|
27
32
|
console.log(` Updated: ${fromLabel} → v${newVersion}`);
|