code-review-pro-skill 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +216 -0
- package/bin/codepro.js +3 -0
- package/install.sh +5 -0
- package/package.json +26 -0
- package/skill.json +14 -0
- package/skills/clean-code-enforcer/SKILL.md +125 -0
- package/skills/clean-code-enforcer/agents/openai.yaml +3 -0
- package/skills/clean-code-enforcer/references/rules.md +181 -0
- package/skills/senior-code-reviewer/SKILL.md +80 -0
- package/skills/senior-code-reviewer/agents/openai.yaml +3 -0
- package/src/cli.js +103 -0
- package/src/installers.js +366 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Adrian Garcia
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Code Review Pro
|
|
2
|
+
|
|
3
|
+
A modular code review toolkit that separates:
|
|
4
|
+
|
|
5
|
+
- **Enforcement** → deterministic clean code transformations
|
|
6
|
+
- **Review** → high-signal, risk-based feedback
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 🧠 Why This Exists
|
|
11
|
+
|
|
12
|
+
Most AI code review tools are:
|
|
13
|
+
|
|
14
|
+
- noisy
|
|
15
|
+
- inconsistent
|
|
16
|
+
- overly mechanical
|
|
17
|
+
|
|
18
|
+
This system separates responsibilities to produce:
|
|
19
|
+
|
|
20
|
+
- high-signal feedback
|
|
21
|
+
- predictable transformations
|
|
22
|
+
- consistent behavior
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## ⚙️ Skills
|
|
27
|
+
|
|
28
|
+
### 1. clean-code-enforcer
|
|
29
|
+
Deterministic refactoring engine for clean code enforcement.
|
|
30
|
+
|
|
31
|
+
- rule-driven
|
|
32
|
+
- consistent output
|
|
33
|
+
- safe for automation
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### 2. senior-code-reviewer
|
|
38
|
+
Senior-level reviewer focused on:
|
|
39
|
+
|
|
40
|
+
- architecture
|
|
41
|
+
- risk
|
|
42
|
+
- prioritization
|
|
43
|
+
|
|
44
|
+
Surfaces only what actually matters.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Supported Assistants
|
|
49
|
+
|
|
50
|
+
- Codex
|
|
51
|
+
- Claude
|
|
52
|
+
- GitHub Copilot
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git clone https://github.com/agarc179/code-review-system
|
|
58
|
+
cd code-review-system
|
|
59
|
+
npm install
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Local Development
|
|
63
|
+
|
|
64
|
+
Link the CLI locally:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm link
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Then install the skills you want:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
codepro init --ai codex --global
|
|
74
|
+
codepro init --ai claude
|
|
75
|
+
codepro init --ai githubcopilot
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
You can also install all supported assistants in one command:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
codepro init --ai all
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Codex Shortcut
|
|
85
|
+
|
|
86
|
+
If you only want the old Codex global install behavior:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
./install.sh
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Published Usage
|
|
93
|
+
|
|
94
|
+
After you publish this package to npm under your chosen package name, the install flow becomes:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npm install -g <your-package-name>
|
|
98
|
+
codepro init --ai codex --global
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Install Targets
|
|
102
|
+
|
|
103
|
+
- Codex: `~/.codex/skills` with `--global`, or `.codex/skills` in the target project
|
|
104
|
+
- Claude: `~/.claude/skills` with `--global`, or `.claude/skills` in the target project
|
|
105
|
+
- GitHub Copilot: `.github/prompts/*.prompt.md` and `.github/copilot-instructions.md` in the target project
|
|
106
|
+
|
|
107
|
+
Each assistant is installed through its native route. This project does not force one fake universal format across Codex, Claude, and GitHub Copilot.
|
|
108
|
+
|
|
109
|
+
GitHub Copilot is intentionally project-scoped in this CLI. Pretending there is one clean global file-based install path would be sloppy.
|
|
110
|
+
|
|
111
|
+
## Authoring Model
|
|
112
|
+
|
|
113
|
+
Skills default to one canonical source:
|
|
114
|
+
|
|
115
|
+
- `skills/<skill-name>/SKILL.md`
|
|
116
|
+
|
|
117
|
+
Optional assistant-native overrides are supported when a target needs its own artifact:
|
|
118
|
+
|
|
119
|
+
- `skills/<skill-name>/overrides/codex/skill/...`
|
|
120
|
+
- `skills/<skill-name>/overrides/claude/skill/...`
|
|
121
|
+
- `skills/<skill-name>/overrides/githubcopilot/prompt.md`
|
|
122
|
+
- `skills/<skill-name>/overrides/githubcopilot/instructions.md`
|
|
123
|
+
|
|
124
|
+
Installer behavior:
|
|
125
|
+
|
|
126
|
+
- Codex: installs the override skill directory if present, otherwise installs the canonical skill folder
|
|
127
|
+
- Claude: installs the override skill directory if present, otherwise installs the canonical skill folder
|
|
128
|
+
- GitHub Copilot: uses `prompt.md` if present, otherwise generates a native prompt file from the canonical skill content
|
|
129
|
+
|
|
130
|
+
Use overrides only when an assistant needs materially different instructions or a different native file format.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 🧪 Usage
|
|
135
|
+
|
|
136
|
+
### Choose the skill directly
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
Use the senior-code-reviewer.
|
|
140
|
+
|
|
141
|
+
[describe what you want + paste code]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### Example — Review
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
Use the senior-code-reviewer.
|
|
150
|
+
|
|
151
|
+
review this code
|
|
152
|
+
|
|
153
|
+
function getUserScore(user) {
|
|
154
|
+
if (!user) return null;
|
|
155
|
+
|
|
156
|
+
return user.actions.reduce((total, action) => {
|
|
157
|
+
return total + action.value;
|
|
158
|
+
}, 0);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### Example — Refactor
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
Use the clean-code-enforcer.
|
|
168
|
+
|
|
169
|
+
refactor this function
|
|
170
|
+
|
|
171
|
+
function getUserScore(user) {
|
|
172
|
+
if (!user) return null;
|
|
173
|
+
|
|
174
|
+
return user.actions.reduce((total, action) => {
|
|
175
|
+
return total + action.value;
|
|
176
|
+
}, 0);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### Direct Usage (optional)
|
|
183
|
+
|
|
184
|
+
You can call skills directly:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
Use the senior-code-reviewer.
|
|
188
|
+
Use the clean-code-enforcer.
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 🧱 Architecture
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
User Request
|
|
197
|
+
↓
|
|
198
|
+
┌─────────────────────┬─────────────────────┐
|
|
199
|
+
│ │ │
|
|
200
|
+
clean-code-enforcer senior-code-reviewer
|
|
201
|
+
(transform) (evaluate)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## ⚠️ Important Notes
|
|
207
|
+
|
|
208
|
+
- Skills are used directly based on intent
|
|
209
|
+
- Designed for JavaScript, TypeScript, and Python
|
|
210
|
+
- Default behavior prioritizes evaluation over transformation
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## 📄 License
|
|
215
|
+
|
|
216
|
+
MIT License
|
package/bin/codepro.js
ADDED
package/install.sh
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "code-review-pro-skill",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Portable code review skills for Codex, Claude, and GitHub Copilot.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"codepro": "bin/codepro.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"src",
|
|
13
|
+
"skills",
|
|
14
|
+
"skill.json",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"install.sh"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"init:codex": "node ./src/cli.js init --ai codex",
|
|
21
|
+
"test:smoke": "node ./src/cli.js --help"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/skill.json
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clean-code-enforcer
|
|
3
|
+
description: Enforce strict clean code standards for Python, Java, and TypeScript during code review, refactoring, and full rewrites. Use when requests include review code, refactor, clean this code, rewrite this function, strict cleanup, aggressive rewrite, or when Codex must produce deterministic clean-code transformations with structured critique or rewritten code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Clean Code Enforcer
|
|
7
|
+
|
|
8
|
+
Load [references/rules.md](references/rules.md) before producing output. That file is the source of truth for enforcement criteria and failure conditions.
|
|
9
|
+
|
|
10
|
+
## Operating Directive
|
|
11
|
+
|
|
12
|
+
Enforce the rules by default. Do not negotiate them away. Override a rule only when it conflicts with clarity, correctness, or clearly intentional well-structured code. This override takes precedence over [references/rules.md](references/rules.md). Prefer rewriting over patching whenever the current structure fails the rule set.
|
|
13
|
+
|
|
14
|
+
Be deterministic. For the same input, use the same cleanup order, decomposition strategy, naming pattern, and output shape.
|
|
15
|
+
|
|
16
|
+
Do not explain clean-code theory. Diagnose, transform, and enforce.
|
|
17
|
+
|
|
18
|
+
Prefer clarity over mechanical compliance.
|
|
19
|
+
|
|
20
|
+
Do not rewrite across boundaries that may affect external contracts unless explicitly requested.
|
|
21
|
+
|
|
22
|
+
## Severity Model
|
|
23
|
+
|
|
24
|
+
Use severity labels exactly as follows:
|
|
25
|
+
|
|
26
|
+
- High: correctness or major structural risk
|
|
27
|
+
- Medium: maintainability issue
|
|
28
|
+
- Low: minor clarity issue
|
|
29
|
+
|
|
30
|
+
## Mode Selection
|
|
31
|
+
|
|
32
|
+
Choose exactly one mode from the request and context.
|
|
33
|
+
|
|
34
|
+
### Review Mode
|
|
35
|
+
|
|
36
|
+
Use when the user asks to review, critique, audit, or identify problems without asking for rewritten code.
|
|
37
|
+
|
|
38
|
+
Behavior:
|
|
39
|
+
- Inspect the full provided scope before judging parts.
|
|
40
|
+
- Identify architectural issues first: coupling, layering, and data flow, before local or stylistic issues.
|
|
41
|
+
- Detect business rules embedded in transformation or mapping logic, including inline domain calculations and hardcoded behavioral thresholds. Treat these as structural issues and prioritize them before local issues, with Medium or High severity based on impact.
|
|
42
|
+
- Report violations against the rule set only.
|
|
43
|
+
- Do not rewrite code.
|
|
44
|
+
- For each issue, include a short reason and impact. Reason must describe a concrete property of the code, such as duplication, mixed responsibilities, or unclear naming. Impact must describe a real engineering risk, such as harder changes, increased bug risk, or duplicated logic drift. Avoid rule-based phrasing.
|
|
45
|
+
- If the file exceeds 150 lines, review by logical sections while keeping file-wide consistency in the critique.
|
|
46
|
+
|
|
47
|
+
Required output:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
Issues:
|
|
51
|
+
1. [High] ... Reason: ... Impact: ...
|
|
52
|
+
2. [Medium] ... Reason: ... Impact: ...
|
|
53
|
+
|
|
54
|
+
Fixes:
|
|
55
|
+
- ...
|
|
56
|
+
- ...
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Refactor Mode
|
|
60
|
+
|
|
61
|
+
Use when the user asks to refactor, clean up, simplify, or enforce clean code while still wanting an explanation.
|
|
62
|
+
|
|
63
|
+
Behavior:
|
|
64
|
+
- Rewrite aggressively enough to satisfy every applicable rule.
|
|
65
|
+
- Preserve external behavior unless the original behavior depends on mixed responsibilities or dead code.
|
|
66
|
+
- If the file exceeds 150 lines, refactor by logical sections while keeping one naming, layering, and helper strategy across the file.
|
|
67
|
+
|
|
68
|
+
Required output:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
Refactored Code:
|
|
72
|
+
<code>
|
|
73
|
+
|
|
74
|
+
Key Improvements:
|
|
75
|
+
- ...
|
|
76
|
+
- ...
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Rewrite Mode
|
|
80
|
+
|
|
81
|
+
Use when the user asks to rewrite code, fully rewrite, or aggressively rewrite.
|
|
82
|
+
|
|
83
|
+
Behavior:
|
|
84
|
+
- Perform a full rewrite when needed to satisfy the rule set.
|
|
85
|
+
- Optimize for clarity, separation of concerns, and deterministic structure.
|
|
86
|
+
- Output code only.
|
|
87
|
+
|
|
88
|
+
Required output:
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
<code only>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Execution Workflow
|
|
95
|
+
|
|
96
|
+
Apply this sequence in every mode:
|
|
97
|
+
|
|
98
|
+
1. Detect language and scope.
|
|
99
|
+
2. Inspect the entire provided unit or file.
|
|
100
|
+
3. Identify major architectural issues first: coupling, layering, data flow, and boundary leakage.
|
|
101
|
+
4. Remove dead code, unreachable paths, and unused helpers.
|
|
102
|
+
5. Split mixed responsibilities by boundary: parsing, validation, processing, formatting, output, IO.
|
|
103
|
+
6. Extract duplicated logic, repeated predicates, and repeated formatting or validation steps.
|
|
104
|
+
7. Flatten control flow to satisfy the nesting limit.
|
|
105
|
+
8. Split oversized or multi-purpose units until each unit passes the responsibility test.
|
|
106
|
+
9. Rename every surviving unit and variable to match domain role and effect.
|
|
107
|
+
10. Normalize patterns so one problem uses one solution style per scope.
|
|
108
|
+
11. Recheck the rule set and emit only the selected mode output.
|
|
109
|
+
|
|
110
|
+
## Scope Rules
|
|
111
|
+
|
|
112
|
+
For input larger than 150 lines:
|
|
113
|
+
- Review or refactor the entire file unless the user explicitly limits scope.
|
|
114
|
+
- Partition the file into logical sections.
|
|
115
|
+
- Remove duplication across sections, not only within sections.
|
|
116
|
+
- Keep one naming and structural strategy across the whole scope.
|
|
117
|
+
|
|
118
|
+
## Failure Handling
|
|
119
|
+
|
|
120
|
+
If code is incomplete or ambiguous:
|
|
121
|
+
- In Review Mode, report violations visible in the provided code only.
|
|
122
|
+
- In Refactor Mode, refactor the visible code conservatively while still enforcing every applicable rule.
|
|
123
|
+
- In Rewrite Mode, produce the cleanest valid rewrite that can be justified from the visible intent.
|
|
124
|
+
|
|
125
|
+
Do not block on missing context unless correctness depends on an external contract that cannot be inferred.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Clean Code Rules
|
|
2
|
+
|
|
3
|
+
## Enforcement Model
|
|
4
|
+
|
|
5
|
+
Apply every rule strictly. A unit fails if any applicable rule fails. Do not preserve violations for convenience, backward familiarity, or local style preference.
|
|
6
|
+
|
|
7
|
+
Prefer deletion, extraction, and decomposition over commentary. If code can only be justified by explanation, the code is not clean enough.
|
|
8
|
+
|
|
9
|
+
## Readability
|
|
10
|
+
|
|
11
|
+
Code must be understandable in one pass.
|
|
12
|
+
|
|
13
|
+
Fail when any of these are true:
|
|
14
|
+
- A name does not reveal domain role, business meaning, or side effect.
|
|
15
|
+
- A reader must inspect distant code to understand the basic purpose of a unit.
|
|
16
|
+
- A unit mixes multiple abstraction levels, such as policy decisions beside low-level data shuffling.
|
|
17
|
+
- A comment explains what the code should already make obvious.
|
|
18
|
+
|
|
19
|
+
Enforce:
|
|
20
|
+
- Use explicit, intention-revealing names for functions, classes, variables, predicates, and types.
|
|
21
|
+
- Keep each unit at one abstraction level.
|
|
22
|
+
- Prefer direct control flow over clever shortcuts.
|
|
23
|
+
|
|
24
|
+
Forbidden placeholder names:
|
|
25
|
+
- `data`
|
|
26
|
+
- `temp`
|
|
27
|
+
- `value`
|
|
28
|
+
- `obj`
|
|
29
|
+
- `item`
|
|
30
|
+
- `stuff`
|
|
31
|
+
- `thing`
|
|
32
|
+
|
|
33
|
+
## Maintainability
|
|
34
|
+
|
|
35
|
+
Code must have one authoritative implementation per behavior.
|
|
36
|
+
|
|
37
|
+
Fail when any of these are true:
|
|
38
|
+
- The same multi-step logic appears more than once.
|
|
39
|
+
- The same predicate appears more than once without extraction.
|
|
40
|
+
- Dead code, unreachable branches, unused helpers, or obsolete flags remain.
|
|
41
|
+
- A change to one behavior would require edits in multiple places.
|
|
42
|
+
|
|
43
|
+
Enforce:
|
|
44
|
+
- Extract duplicated behavior the second time it appears.
|
|
45
|
+
- Delete dead code instead of preserving it "just in case".
|
|
46
|
+
- Centralize shared formatting, validation, mapping, and branching logic.
|
|
47
|
+
|
|
48
|
+
## Modularity
|
|
49
|
+
|
|
50
|
+
Each unit must own one responsibility.
|
|
51
|
+
|
|
52
|
+
Responsibility test:
|
|
53
|
+
- A unit must be describable in one sentence with one primary verb.
|
|
54
|
+
- If that sentence requires `and`, the unit is too broad and must be split.
|
|
55
|
+
|
|
56
|
+
Fail when any of these are true:
|
|
57
|
+
- Parsing, validation, processing, formatting, output, or IO are mixed in one unit.
|
|
58
|
+
- One class or module coordinates unrelated workflows.
|
|
59
|
+
- A helper exists only to hide a mixed-responsibility block.
|
|
60
|
+
|
|
61
|
+
Enforce:
|
|
62
|
+
- Separate parsing, validation, processing, formatting, output, and IO into distinct units or layers.
|
|
63
|
+
- Keep orchestration thin and domain logic focused.
|
|
64
|
+
- Assign one reason to change per unit.
|
|
65
|
+
|
|
66
|
+
## Function Design
|
|
67
|
+
|
|
68
|
+
Functions and methods must be small, explicit, and side-effect-aware.
|
|
69
|
+
|
|
70
|
+
Fail when any of these are true:
|
|
71
|
+
- A function cannot be described plainly without mentioning multiple jobs.
|
|
72
|
+
- A function mutates external state, performs IO, or changes shared data without making that effect obvious from its name and role.
|
|
73
|
+
- A helper both decides policy and performs mechanics.
|
|
74
|
+
- A function relies on hidden inputs or writes to hidden outputs.
|
|
75
|
+
|
|
76
|
+
Enforce:
|
|
77
|
+
- Default to pure helpers; isolate side effects at clear boundaries.
|
|
78
|
+
- Keep parameters and return values explicit.
|
|
79
|
+
- Use focused helpers instead of broad coordinators.
|
|
80
|
+
|
|
81
|
+
Global length limits:
|
|
82
|
+
- Functions and methods: maximum 20 lines
|
|
83
|
+
- Nesting depth: maximum 3 levels
|
|
84
|
+
|
|
85
|
+
## Complexity
|
|
86
|
+
|
|
87
|
+
Control flow must stay linear enough to reason about locally.
|
|
88
|
+
|
|
89
|
+
Fail when any of these are true:
|
|
90
|
+
- Nesting exceeds 3 levels.
|
|
91
|
+
- A function requires multiple passes to trace normal flow.
|
|
92
|
+
- Boolean logic is dense enough that extracting a named predicate would improve understanding.
|
|
93
|
+
- A long function remains intact after responsibilities and duplication have been identified.
|
|
94
|
+
|
|
95
|
+
Enforce:
|
|
96
|
+
- Flatten with guard clauses and early returns.
|
|
97
|
+
- Extract named predicates for repeated or dense conditions.
|
|
98
|
+
- Break large functions before performing local polish.
|
|
99
|
+
|
|
100
|
+
## Consistency
|
|
101
|
+
|
|
102
|
+
Equivalent problems must use equivalent solutions within the same scope.
|
|
103
|
+
|
|
104
|
+
Fail when any of these are true:
|
|
105
|
+
- The same kind of work is implemented with multiple patterns in the same file or module.
|
|
106
|
+
- Naming conventions change without a domain reason.
|
|
107
|
+
- Similar validation, mapping, or error-handling flows use different structures.
|
|
108
|
+
- Helper boundaries are inconsistent for equivalent operations.
|
|
109
|
+
|
|
110
|
+
Enforce:
|
|
111
|
+
- Use one pattern per problem type within a scope.
|
|
112
|
+
- Apply one naming scheme and one decomposition strategy across the file.
|
|
113
|
+
- Normalize similar workflows to the same structure unless an external API forces a difference.
|
|
114
|
+
|
|
115
|
+
## Transformation Order
|
|
116
|
+
|
|
117
|
+
Fix violations in this order:
|
|
118
|
+
1. Delete dead code and unreachable paths.
|
|
119
|
+
2. Separate mixed responsibilities.
|
|
120
|
+
3. Extract duplication and repeated predicates.
|
|
121
|
+
4. Reduce nesting and control-flow complexity.
|
|
122
|
+
5. Split oversized or multi-purpose units.
|
|
123
|
+
6. Rename for clarity and consistency.
|
|
124
|
+
7. Recheck language-specific rules.
|
|
125
|
+
|
|
126
|
+
## Scope Enforcement
|
|
127
|
+
|
|
128
|
+
For code over 150 lines:
|
|
129
|
+
- Review or refactor the full file unless the user explicitly limits scope.
|
|
130
|
+
- Partition work by logical sections, then normalize across the whole file.
|
|
131
|
+
- Remove cross-section duplication.
|
|
132
|
+
- Do not leave one section on a different naming or structural pattern from the rest.
|
|
133
|
+
|
|
134
|
+
## Language-Specific Rules
|
|
135
|
+
|
|
136
|
+
### Python
|
|
137
|
+
|
|
138
|
+
Fail when any of these are true:
|
|
139
|
+
- Nesting exceeds 3 levels.
|
|
140
|
+
- A comprehension hides branching or multi-step transformation.
|
|
141
|
+
- Dense one-liners reduce clarity.
|
|
142
|
+
|
|
143
|
+
Enforce:
|
|
144
|
+
- Prefer explicit control flow once a comprehension stops being immediately readable.
|
|
145
|
+
- Keep data flow obvious from names and statement order.
|
|
146
|
+
|
|
147
|
+
### Java
|
|
148
|
+
|
|
149
|
+
Fail when any of these are true:
|
|
150
|
+
- A class exceeds 300 lines.
|
|
151
|
+
- A method exceeds 20 lines.
|
|
152
|
+
- Method visibility is implicit or omitted.
|
|
153
|
+
- Service, utility, and model responsibilities are mixed.
|
|
154
|
+
|
|
155
|
+
Enforce:
|
|
156
|
+
- Use small private helpers.
|
|
157
|
+
- Keep classes narrowly scoped.
|
|
158
|
+
- Keep validation and formatting outside core business methods.
|
|
159
|
+
|
|
160
|
+
### TypeScript
|
|
161
|
+
|
|
162
|
+
Fail when any of these are true:
|
|
163
|
+
- `any` is used.
|
|
164
|
+
- Parameter types are implicit.
|
|
165
|
+
- Return types are implicit.
|
|
166
|
+
- Reused object shapes remain anonymous.
|
|
167
|
+
|
|
168
|
+
Enforce:
|
|
169
|
+
- Use explicit function signatures.
|
|
170
|
+
- Prefer named interfaces or type aliases for reused shapes.
|
|
171
|
+
- Keep transformation logic in typed helpers.
|
|
172
|
+
|
|
173
|
+
## Determinism
|
|
174
|
+
|
|
175
|
+
For the same input, produce the same:
|
|
176
|
+
- violation ordering
|
|
177
|
+
- extraction strategy
|
|
178
|
+
- naming pattern
|
|
179
|
+
- output structure
|
|
180
|
+
|
|
181
|
+
Do not vary the result for style, novelty, or personal preference.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: senior-code-reviewer
|
|
3
|
+
description: Senior-level code review for JavaScript, TypeScript, and Python with balanced strictness. Use for pull request review or local snippet review when the goal is to identify the highest-risk issues, prioritize architectural and systemic problems, and give concise, judgment-based feedback instead of mechanical rule enforcement.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Senior Code Reviewer
|
|
7
|
+
|
|
8
|
+
Use this skill for JavaScript, TypeScript, and Python review when impact matters more than completeness.
|
|
9
|
+
|
|
10
|
+
## Operating Directive
|
|
11
|
+
|
|
12
|
+
Think like a senior engineer reviewing a pull request.
|
|
13
|
+
|
|
14
|
+
Prioritize judgment over coverage.
|
|
15
|
+
|
|
16
|
+
Prefer depth over breadth.
|
|
17
|
+
|
|
18
|
+
Prefer impact over completeness.
|
|
19
|
+
|
|
20
|
+
Prefer reasoning over rules.
|
|
21
|
+
|
|
22
|
+
Do not behave like a clean-code enforcer.
|
|
23
|
+
|
|
24
|
+
Do not rewrite full code.
|
|
25
|
+
|
|
26
|
+
Do not hallucinate problems.
|
|
27
|
+
|
|
28
|
+
## Review Scope
|
|
29
|
+
|
|
30
|
+
Prefer full-file or module context when available.
|
|
31
|
+
|
|
32
|
+
If only a snippet is provided, limit conclusions to visible code and avoid assumptions about missing architecture, intent, or surrounding systems.
|
|
33
|
+
|
|
34
|
+
## Severity Model
|
|
35
|
+
|
|
36
|
+
- Critical: correctness, security, scalability, or major design flaw
|
|
37
|
+
- Warning: maintainability, coupling, or unclear structure
|
|
38
|
+
- Suggestion: optional improvement
|
|
39
|
+
|
|
40
|
+
## Review Behavior
|
|
41
|
+
|
|
42
|
+
- Report at most 3 to 5 issues total unless there is a critical failure.
|
|
43
|
+
- Always list the highest-risk issues first.
|
|
44
|
+
- Architectural or systemic issues must appear before local issues.
|
|
45
|
+
- If one issue dominates the risk, focus on it instead of listing smaller issues.
|
|
46
|
+
- Classify issues as Critical when they affect correctness, error visibility, or observable system behavior. Treat silent failures, ambiguous return values, and loss of error information as Critical. Do not default to lower severity when the risk is high.
|
|
47
|
+
- Ignore style unless it affects correctness or maintainability.
|
|
48
|
+
- Do not flag trivial issues unless they contribute to real risk.
|
|
49
|
+
- Consider architecture and boundaries, data flow clarity, coupling and cohesion, testability, error handling strategy, performance risks, and security risks.
|
|
50
|
+
- Each issue must reference the code, explain why it is a problem, describe the risk it creates, and suggest a direction without rewriting the code.
|
|
51
|
+
- If context is incomplete, limit conclusions to what can be confidently inferred.
|
|
52
|
+
|
|
53
|
+
## Output Format
|
|
54
|
+
|
|
55
|
+
Omit any empty severity section instead of rendering it with no items.
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
Critical
|
|
59
|
+
- [code reference] Why: ... Risk: ... Direction: ...
|
|
60
|
+
|
|
61
|
+
Warnings
|
|
62
|
+
- [code reference] Why: ... Risk: ... Direction: ...
|
|
63
|
+
|
|
64
|
+
Suggestions
|
|
65
|
+
- [code reference] Why: ... Risk: ... Direction: ...
|
|
66
|
+
|
|
67
|
+
Structural Risk
|
|
68
|
+
- ...
|
|
69
|
+
|
|
70
|
+
Summary
|
|
71
|
+
- ...
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Structural Risk Requirement
|
|
75
|
+
|
|
76
|
+
Identify the single biggest design issue and explain why it matters at scale.
|
|
77
|
+
|
|
78
|
+
## Summary Requirement
|
|
79
|
+
|
|
80
|
+
End with a 2 to 3 sentence summary that states the most important takeaway.
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const {
|
|
2
|
+
installSkills,
|
|
3
|
+
listSupportedAssistants,
|
|
4
|
+
printHelp,
|
|
5
|
+
} = require("./installers");
|
|
6
|
+
|
|
7
|
+
function parseArgs(argv) {
|
|
8
|
+
let command;
|
|
9
|
+
const rest = [];
|
|
10
|
+
const options = {
|
|
11
|
+
ai: "all",
|
|
12
|
+
cwd: process.cwd(),
|
|
13
|
+
global: false,
|
|
14
|
+
force: false,
|
|
15
|
+
help: false,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
for (const arg of argv) {
|
|
19
|
+
if (!command && !arg.startsWith("-")) {
|
|
20
|
+
command = arg;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
rest.push(arg);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
for (let index = 0; index < rest.length; index += 1) {
|
|
28
|
+
const arg = rest[index];
|
|
29
|
+
|
|
30
|
+
if (arg === "--help" || arg === "-h") {
|
|
31
|
+
options.help = true;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (arg === "--global" || arg === "-g") {
|
|
36
|
+
options.global = true;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (arg === "--force" || arg === "-f") {
|
|
41
|
+
options.force = true;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (arg === "--ai" || arg === "-a") {
|
|
46
|
+
const value = rest[index + 1];
|
|
47
|
+
if (!value) {
|
|
48
|
+
throw new Error("Missing value for --ai");
|
|
49
|
+
}
|
|
50
|
+
options.ai = value;
|
|
51
|
+
index += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (arg === "--dir" || arg === "-d") {
|
|
56
|
+
const value = rest[index + 1];
|
|
57
|
+
if (!value) {
|
|
58
|
+
throw new Error("Missing value for --dir");
|
|
59
|
+
}
|
|
60
|
+
options.cwd = value;
|
|
61
|
+
index += 1;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
throw new Error(`Unknown argument: ${arg}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
command,
|
|
70
|
+
options,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function main() {
|
|
75
|
+
try {
|
|
76
|
+
const { command, options } = parseArgs(process.argv.slice(2));
|
|
77
|
+
|
|
78
|
+
if (!command || options.help) {
|
|
79
|
+
printHelp();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (command !== "init") {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Unsupported command "${command}". Supported commands: init`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const supportedAssistants = listSupportedAssistants();
|
|
90
|
+
await installSkills({
|
|
91
|
+
ai: options.ai,
|
|
92
|
+
cwd: options.cwd,
|
|
93
|
+
globalInstall: options.global,
|
|
94
|
+
force: options.force,
|
|
95
|
+
supportedAssistants,
|
|
96
|
+
});
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(`Error: ${error.message}`);
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
main();
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
const REPO_ROOT = path.resolve(__dirname, "..");
|
|
6
|
+
const SKILLS_DIR = path.join(REPO_ROOT, "skills");
|
|
7
|
+
const SKILL_MANIFEST_PATH = path.join(REPO_ROOT, "skill.json");
|
|
8
|
+
|
|
9
|
+
function readManifest() {
|
|
10
|
+
return JSON.parse(fs.readFileSync(SKILL_MANIFEST_PATH, "utf8"));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function listSkillDirectories() {
|
|
14
|
+
return fs
|
|
15
|
+
.readdirSync(SKILLS_DIR, { withFileTypes: true })
|
|
16
|
+
.filter((entry) => entry.isDirectory())
|
|
17
|
+
.filter((entry) =>
|
|
18
|
+
fs.existsSync(path.join(SKILLS_DIR, entry.name, "SKILL.md"))
|
|
19
|
+
)
|
|
20
|
+
.map((entry) => entry.name)
|
|
21
|
+
.sort();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function listSupportedAssistants() {
|
|
25
|
+
return readManifest().assistants;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function parseAiTargets(aiValue, supportedAssistants) {
|
|
29
|
+
if (!aiValue || aiValue === "all") {
|
|
30
|
+
return supportedAssistants;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const targets = aiValue
|
|
34
|
+
.split(",")
|
|
35
|
+
.map((value) => value.trim().toLowerCase())
|
|
36
|
+
.filter(Boolean);
|
|
37
|
+
|
|
38
|
+
const invalidTargets = targets.filter(
|
|
39
|
+
(target) => !supportedAssistants.includes(target)
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (invalidTargets.length > 0) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Unsupported assistant(s): ${invalidTargets.join(
|
|
45
|
+
", "
|
|
46
|
+
)}. Supported assistants: ${supportedAssistants.join(", ")}`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return [...new Set(targets)];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function ensureDirectory(targetDirectory) {
|
|
54
|
+
fs.mkdirSync(targetDirectory, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function copyDirectory(sourceDirectory, targetDirectory, force, excludedNames = []) {
|
|
58
|
+
ensureDirectory(targetDirectory);
|
|
59
|
+
|
|
60
|
+
for (const entry of fs.readdirSync(sourceDirectory, { withFileTypes: true })) {
|
|
61
|
+
if (entry.name === ".DS_Store" || excludedNames.includes(entry.name)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const sourcePath = path.join(sourceDirectory, entry.name);
|
|
66
|
+
const targetPath = path.join(targetDirectory, entry.name);
|
|
67
|
+
|
|
68
|
+
if (entry.isDirectory()) {
|
|
69
|
+
copyDirectory(sourcePath, targetPath, force, excludedNames);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!force && fs.existsSync(targetPath)) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Refusing to overwrite existing file without --force: ${targetPath}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function writeFile(targetPath, content, force) {
|
|
84
|
+
ensureDirectory(path.dirname(targetPath));
|
|
85
|
+
|
|
86
|
+
if (!force && fs.existsSync(targetPath)) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Refusing to overwrite existing file without --force: ${targetPath}`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fs.writeFileSync(targetPath, content, "utf8");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function pathExists(targetPath) {
|
|
96
|
+
return fs.existsSync(targetPath);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function stripFrontMatter(markdownContent) {
|
|
100
|
+
if (!markdownContent.startsWith("---")) {
|
|
101
|
+
return markdownContent.trim();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const match = markdownContent.match(/^---\n[\s\S]*?\n---\n?/);
|
|
105
|
+
if (!match) {
|
|
106
|
+
return markdownContent.trim();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return markdownContent.slice(match[0].length).trim();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function readSkill(skillName) {
|
|
113
|
+
const skillDirectory = path.join(SKILLS_DIR, skillName);
|
|
114
|
+
const skillPath = path.join(skillDirectory, "SKILL.md");
|
|
115
|
+
const skillContent = fs.readFileSync(skillPath, "utf8");
|
|
116
|
+
|
|
117
|
+
const descriptionMatch = skillContent.match(/description:\s*(.+)/);
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
name: skillName,
|
|
121
|
+
directory: skillDirectory,
|
|
122
|
+
description: descriptionMatch ? descriptionMatch[1].trim() : skillName,
|
|
123
|
+
content: skillContent,
|
|
124
|
+
body: stripFrontMatter(skillContent),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function readRelativeFile(skillName, relativePath) {
|
|
129
|
+
return fs.readFileSync(path.join(SKILLS_DIR, skillName, relativePath), "utf8").trim();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function resolveAssistantOverridePath(skillName, assistant, fileName) {
|
|
133
|
+
return path.join(SKILLS_DIR, skillName, "overrides", assistant, fileName);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function readAssistantOverride(skillName, assistant, fileName) {
|
|
137
|
+
const overridePath = resolveAssistantOverridePath(skillName, assistant, fileName);
|
|
138
|
+
|
|
139
|
+
if (!pathExists(overridePath)) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return fs.readFileSync(overridePath, "utf8");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function buildCopilotPromptBody(skill) {
|
|
147
|
+
if (skill.name !== "clean-code-enforcer") {
|
|
148
|
+
return skill.body;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const rulesContent = readRelativeFile(skill.name, "references/rules.md");
|
|
152
|
+
const normalizedBody = skill.body.replace(
|
|
153
|
+
"Load [references/rules.md](references/rules.md) before producing output. That file is the source of truth for enforcement criteria and failure conditions.",
|
|
154
|
+
"Use the inlined `references/rules.md` content below as the source of truth for enforcement criteria and failure conditions."
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return `${normalizedBody}
|
|
158
|
+
|
|
159
|
+
## Inlined Reference
|
|
160
|
+
|
|
161
|
+
The following content is inlined for GitHub Copilot because prompt files do not load repository-relative markdown dependencies automatically.
|
|
162
|
+
|
|
163
|
+
### references/rules.md
|
|
164
|
+
|
|
165
|
+
\`\`\`md
|
|
166
|
+
${rulesContent}
|
|
167
|
+
\`\`\`
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function resolveCodexTarget(globalInstall, cwd) {
|
|
172
|
+
return globalInstall
|
|
173
|
+
? path.join(os.homedir(), ".codex", "skills")
|
|
174
|
+
: path.join(cwd, ".codex", "skills");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function resolveClaudeTarget(globalInstall, cwd) {
|
|
178
|
+
return globalInstall
|
|
179
|
+
? path.join(os.homedir(), ".claude", "skills")
|
|
180
|
+
: path.join(cwd, ".claude", "skills");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function resolveCopilotTarget(globalInstall, cwd) {
|
|
184
|
+
if (globalInstall) {
|
|
185
|
+
throw new Error(
|
|
186
|
+
"GitHub Copilot installation is project-scoped in this CLI. Remove --global or install Codex and Claude separately."
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return path.join(cwd, ".github");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function buildCopilotPrompt(skill) {
|
|
194
|
+
const explicitPrompt = readAssistantOverride(
|
|
195
|
+
skill.name,
|
|
196
|
+
"githubcopilot",
|
|
197
|
+
"prompt.md"
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
if (explicitPrompt) {
|
|
201
|
+
return explicitPrompt;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return `---
|
|
205
|
+
agent: 'agent'
|
|
206
|
+
description: '${skill.description.replace(/'/g, "''")}'
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
${buildCopilotPromptBody(skill)}
|
|
210
|
+
`;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function buildCopilotInstructions(skillNames) {
|
|
214
|
+
const instructionOverrides = skillNames
|
|
215
|
+
.map((skillName) =>
|
|
216
|
+
readAssistantOverride(skillName, "githubcopilot", "instructions.md")
|
|
217
|
+
)
|
|
218
|
+
.filter(Boolean)
|
|
219
|
+
.join("\n\n");
|
|
220
|
+
|
|
221
|
+
const slashCommands = skillNames
|
|
222
|
+
.map((skillName) => `- \`/${skillName}\``)
|
|
223
|
+
.join("\n");
|
|
224
|
+
|
|
225
|
+
return `# Code Review Pro Instructions
|
|
226
|
+
|
|
227
|
+
Use the installed prompts for task-specific behavior:
|
|
228
|
+
|
|
229
|
+
${slashCommands}
|
|
230
|
+
|
|
231
|
+
Default operating rules:
|
|
232
|
+
|
|
233
|
+
- Separate evaluation from transformation.
|
|
234
|
+
- Prefer high-signal review over broad, noisy checklists.
|
|
235
|
+
- When the user asks for critique, use the reviewer behavior.
|
|
236
|
+
- When the user asks for refactoring or rewriting, use the clean-code behavior.
|
|
237
|
+
|
|
238
|
+
${instructionOverrides ? `Skill-specific notes:\n\n${instructionOverrides}\n` : ""}`;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function installNativeSkillDirectory(skillName, assistant, targetRoot, force) {
|
|
242
|
+
const overrideDirectory = resolveAssistantOverridePath(skillName, assistant, "skill");
|
|
243
|
+
const targetDirectory = path.join(targetRoot, skillName);
|
|
244
|
+
|
|
245
|
+
if (pathExists(overrideDirectory)) {
|
|
246
|
+
copyDirectory(overrideDirectory, targetDirectory, force);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
copyDirectory(path.join(SKILLS_DIR, skillName), targetDirectory, force, ["overrides"]);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function installForCodex(skillNames, cwd, globalInstall, force) {
|
|
254
|
+
const targetRoot = resolveCodexTarget(globalInstall, cwd);
|
|
255
|
+
ensureDirectory(targetRoot);
|
|
256
|
+
|
|
257
|
+
for (const skillName of skillNames) {
|
|
258
|
+
installNativeSkillDirectory(skillName, "codex", targetRoot, force);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return targetRoot;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function installForClaude(skillNames, cwd, globalInstall, force) {
|
|
265
|
+
const targetRoot = resolveClaudeTarget(globalInstall, cwd);
|
|
266
|
+
ensureDirectory(targetRoot);
|
|
267
|
+
|
|
268
|
+
for (const skillName of skillNames) {
|
|
269
|
+
installNativeSkillDirectory(skillName, "claude", targetRoot, force);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return targetRoot;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function installForGitHubCopilot(skillNames, cwd, globalInstall, force) {
|
|
276
|
+
const targetRoot = resolveCopilotTarget(globalInstall, cwd);
|
|
277
|
+
const promptsDirectory = path.join(targetRoot, "prompts");
|
|
278
|
+
|
|
279
|
+
ensureDirectory(promptsDirectory);
|
|
280
|
+
|
|
281
|
+
for (const skillName of skillNames) {
|
|
282
|
+
const skill = readSkill(skillName);
|
|
283
|
+
writeFile(
|
|
284
|
+
path.join(promptsDirectory, `${skillName}.prompt.md`),
|
|
285
|
+
buildCopilotPrompt(skill),
|
|
286
|
+
force
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
writeFile(
|
|
291
|
+
path.join(targetRoot, "copilot-instructions.md"),
|
|
292
|
+
buildCopilotInstructions(skillNames),
|
|
293
|
+
force
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
return targetRoot;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async function installSkills({
|
|
300
|
+
ai,
|
|
301
|
+
cwd,
|
|
302
|
+
globalInstall,
|
|
303
|
+
force,
|
|
304
|
+
supportedAssistants,
|
|
305
|
+
}) {
|
|
306
|
+
const targets = parseAiTargets(ai, supportedAssistants);
|
|
307
|
+
const skillNames = listSkillDirectories();
|
|
308
|
+
const results = [];
|
|
309
|
+
|
|
310
|
+
for (const target of targets) {
|
|
311
|
+
if (target === "codex") {
|
|
312
|
+
results.push({
|
|
313
|
+
assistant: target,
|
|
314
|
+
path: installForCodex(skillNames, cwd, globalInstall, force),
|
|
315
|
+
});
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (target === "claude") {
|
|
320
|
+
results.push({
|
|
321
|
+
assistant: target,
|
|
322
|
+
path: installForClaude(skillNames, cwd, globalInstall, force),
|
|
323
|
+
});
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (target === "githubcopilot") {
|
|
328
|
+
results.push({
|
|
329
|
+
assistant: target,
|
|
330
|
+
path: installForGitHubCopilot(skillNames, cwd, globalInstall, force),
|
|
331
|
+
});
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
for (const result of results) {
|
|
337
|
+
console.log(`Installed ${readManifest().name} for ${result.assistant}: ${result.path}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function printHelp() {
|
|
342
|
+
const assistants = listSupportedAssistants().join(", ");
|
|
343
|
+
|
|
344
|
+
console.log(`codepro init [options]
|
|
345
|
+
|
|
346
|
+
Install code review skills for supported AI assistants.
|
|
347
|
+
|
|
348
|
+
Options:
|
|
349
|
+
-a, --ai <targets> Assistant target(s): ${assistants}, or all
|
|
350
|
+
-d, --dir <path> Project directory for project-scoped installs
|
|
351
|
+
-f, --force Overwrite existing generated files
|
|
352
|
+
-g, --global Install to home-directory targets when supported
|
|
353
|
+
-h, --help Show this help message
|
|
354
|
+
|
|
355
|
+
Examples:
|
|
356
|
+
codepro init --ai codex --global
|
|
357
|
+
codepro init --ai claude,githubcopilot
|
|
358
|
+
codepro init --ai all --dir /tmp/demo
|
|
359
|
+
`);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
module.exports = {
|
|
363
|
+
installSkills,
|
|
364
|
+
listSupportedAssistants,
|
|
365
|
+
printHelp,
|
|
366
|
+
};
|