@hopla/claude-setup 1.3.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/cli.js +165 -0
- package/files/commands/hopla-plan-feature.md +14 -3
- package/files/hooks/env-protect.js +24 -0
- package/files/hooks/session-prime.js +50 -0
- package/files/hooks/tsc-check.js +35 -0
- package/files/skills/hopla-code-review/SKILL.md +79 -0
- package/files/skills/hopla-execution-report/SKILL.md +68 -0
- package/files/skills/hopla-git/SKILL.md +24 -0
- package/files/skills/hopla-git/commit.md +57 -0
- package/files/skills/hopla-git/pr.md +79 -0
- package/files/skills/hopla-prime/SKILL.md +59 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,6 +72,8 @@ This system is built on two core concepts from the Agentic Coding Course:
|
|
|
72
72
|
| **Global Rules** | Always-loaded context: language, git flow, tech defaults, autonomy rules | `~/.claude/CLAUDE.md` |
|
|
73
73
|
| **On-Demand Context** | Task-specific guides loaded when needed (e.g. "how to add an API endpoint") | `.agents/guides/*.md` |
|
|
74
74
|
| **Commands** | Reusable processes that tell the agent *how* to work | `~/.claude/commands/hopla-*.md` |
|
|
75
|
+
| **Skills** | Auto-activate by semantic matching — no slash command needed | `~/.claude/skills/hopla-*/SKILL.md` |
|
|
76
|
+
| **Hooks** | Run automatically before/after tool use for type checking and protection | `~/.claude/hooks/*.js` |
|
|
75
77
|
|
|
76
78
|
The key insight: **commands inject on-demand context deterministically** — when you run `/hopla-plan-feature`, it automatically reads the relevant guide from `.agents/guides/` before planning.
|
|
77
79
|
|
|
@@ -112,6 +114,42 @@ After each PIV loop, run `/hopla-execution-report` + `/hopla-system-review` to f
|
|
|
112
114
|
| `/hopla-execution-report` | Generate an implementation report for system review |
|
|
113
115
|
| `/hopla-system-review` | Analyze implementation against plan to find process improvements |
|
|
114
116
|
|
|
117
|
+
**`~/.claude/skills/`** — Auto-activate by semantic matching, no slash command needed:
|
|
118
|
+
|
|
119
|
+
| Skill | Auto-activates when you say... |
|
|
120
|
+
|---|---|
|
|
121
|
+
| `hopla-git` | "commit this", "create a PR", "guarda los cambios" |
|
|
122
|
+
| `hopla-prime` | "orient yourself", "ponte al día", "what is this project" |
|
|
123
|
+
| `hopla-code-review` | "review the code", "code review", "analiza los cambios" |
|
|
124
|
+
| `hopla-execution-report` | "generate the report", "genera el reporte", "document what was done" |
|
|
125
|
+
|
|
126
|
+
**`~/.claude/hooks/`** — Run automatically before/after tool use (configured in `~/.claude/settings.json`):
|
|
127
|
+
|
|
128
|
+
| Hook | Type | What it does |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| `tsc-check.js` | PostToolUse | Runs `tsc --noEmit` after file edits; feeds errors back to Claude |
|
|
131
|
+
| `env-protect.js` | PreToolUse | Blocks reads/greps targeting `.env` files |
|
|
132
|
+
| `session-prime.js` | SessionStart (opt-in) | Loads git context + CLAUDE.md summary at session start |
|
|
133
|
+
|
|
134
|
+
**Installed layout:**
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
~/.claude/
|
|
138
|
+
├── CLAUDE.md ← Global rules
|
|
139
|
+
├── commands/
|
|
140
|
+
│ └── hopla-*.md ← Slash commands (/hopla-prime, /hopla-execute, etc.)
|
|
141
|
+
├── skills/
|
|
142
|
+
│ ├── hopla-git/ ← Auto-activates for commit/PR requests
|
|
143
|
+
│ ├── hopla-prime/ ← Auto-activates for orientation requests
|
|
144
|
+
│ ├── hopla-code-review/ ← Auto-activates for review requests
|
|
145
|
+
│ └── hopla-execution-report/ ← Auto-activates for report requests
|
|
146
|
+
├── hooks/
|
|
147
|
+
│ ├── tsc-check.js ← TypeScript type checking after edits
|
|
148
|
+
│ ├── env-protect.js ← .env file protection
|
|
149
|
+
│ └── session-prime.js ← Session context loader (opt-in)
|
|
150
|
+
└── settings.json ← Permissions + hooks config (auto-updated)
|
|
151
|
+
```
|
|
152
|
+
|
|
115
153
|
---
|
|
116
154
|
|
|
117
155
|
## Recommended Workflow
|
|
@@ -141,6 +179,8 @@ After each PIV loop, run `/hopla-execution-report` + `/hopla-system-review` to f
|
|
|
141
179
|
/hopla-system-review → analyze plan vs. actual for process improvements
|
|
142
180
|
```
|
|
143
181
|
|
|
182
|
+
> **Tip:** `hopla-prime`, `hopla-git-commit`, `hopla-git-pr`, `hopla-code-review`, and `hopla-execution-report` also exist as skills — they auto-activate when you describe what you want in natural language, without typing the slash command.
|
|
183
|
+
|
|
144
184
|
---
|
|
145
185
|
|
|
146
186
|
## Command Chaining
|
package/cli.js
CHANGED
|
@@ -17,6 +17,8 @@ if (VERSION) {
|
|
|
17
17
|
}
|
|
18
18
|
const CLAUDE_DIR = path.join(os.homedir(), ".claude");
|
|
19
19
|
const COMMANDS_DIR = path.join(CLAUDE_DIR, "commands");
|
|
20
|
+
const SKILLS_DIR = path.join(CLAUDE_DIR, "skills");
|
|
21
|
+
const HOOKS_DIR = path.join(CLAUDE_DIR, "hooks");
|
|
20
22
|
const FILES_DIR = path.join(import.meta.dirname, "files");
|
|
21
23
|
|
|
22
24
|
const GREEN = "\x1b[32m";
|
|
@@ -226,6 +228,169 @@ async function install() {
|
|
|
226
228
|
}
|
|
227
229
|
|
|
228
230
|
await setupPermissions();
|
|
231
|
+
await installSkills();
|
|
232
|
+
await installHooks();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Skills to install in planning mode (subset)
|
|
236
|
+
const PLANNING_SKILLS = ["hopla-prime"];
|
|
237
|
+
|
|
238
|
+
async function installSkills() {
|
|
239
|
+
const skillsSrcDir = path.join(FILES_DIR, "skills");
|
|
240
|
+
if (!fs.existsSync(skillsSrcDir)) return;
|
|
241
|
+
|
|
242
|
+
fs.mkdirSync(SKILLS_DIR, { recursive: true });
|
|
243
|
+
|
|
244
|
+
const skillDirs = fs.readdirSync(skillsSrcDir).filter((entry) => {
|
|
245
|
+
return fs.statSync(path.join(skillsSrcDir, entry)).isDirectory();
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
const skillsToInstall = PLANNING
|
|
249
|
+
? skillDirs.filter((d) => PLANNING_SKILLS.includes(d))
|
|
250
|
+
: skillDirs;
|
|
251
|
+
|
|
252
|
+
if (skillsToInstall.length === 0) return;
|
|
253
|
+
|
|
254
|
+
log(`\n${CYAN}Installing skills...${RESET}`);
|
|
255
|
+
for (const skillName of skillsToInstall.sort()) {
|
|
256
|
+
const srcDir = path.join(skillsSrcDir, skillName);
|
|
257
|
+
const destDir = path.join(SKILLS_DIR, skillName);
|
|
258
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
259
|
+
for (const file of fs.readdirSync(srcDir).sort()) {
|
|
260
|
+
await installFile(
|
|
261
|
+
path.join(srcDir, file),
|
|
262
|
+
path.join(destDir, file),
|
|
263
|
+
`~/.claude/skills/${skillName}/${file}`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
log(`\n${GREEN}${BOLD}Skills installed!${RESET} Auto-activate without a slash command:\n`);
|
|
269
|
+
for (const skillName of skillsToInstall.sort()) {
|
|
270
|
+
log(` ${CYAN}${skillName}${RESET}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function installHooks() {
|
|
275
|
+
const hooksSrcDir = path.join(FILES_DIR, "hooks");
|
|
276
|
+
if (!fs.existsSync(hooksSrcDir)) return;
|
|
277
|
+
|
|
278
|
+
const hookFiles = fs.readdirSync(hooksSrcDir).filter((f) => f.endsWith(".js"));
|
|
279
|
+
if (hookFiles.length === 0) return;
|
|
280
|
+
|
|
281
|
+
const settingsPath = path.join(CLAUDE_DIR, "settings.json");
|
|
282
|
+
|
|
283
|
+
// Read existing settings
|
|
284
|
+
let settings = {};
|
|
285
|
+
if (fs.existsSync(settingsPath)) {
|
|
286
|
+
try {
|
|
287
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
288
|
+
} catch {
|
|
289
|
+
// keep defaults
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const existingHooks = settings.hooks || {};
|
|
294
|
+
const tscHookCmd = `${HOOKS_DIR}/tsc-check.js`;
|
|
295
|
+
const envHookCmd = `${HOOKS_DIR}/env-protect.js`;
|
|
296
|
+
const sessionHookCmd = `${HOOKS_DIR}/session-prime.js`;
|
|
297
|
+
|
|
298
|
+
// Check what's already configured
|
|
299
|
+
const postToolUseHooks = existingHooks.PostToolUse || [];
|
|
300
|
+
const preToolUseHooks = existingHooks.PreToolUse || [];
|
|
301
|
+
const sessionStartHooks = existingHooks.SessionStart || [];
|
|
302
|
+
|
|
303
|
+
const hasTsc = postToolUseHooks.some((h) =>
|
|
304
|
+
h.hooks?.some((hh) => hh.command === tscHookCmd)
|
|
305
|
+
);
|
|
306
|
+
const hasEnv = preToolUseHooks.some((h) =>
|
|
307
|
+
h.hooks?.some((hh) => hh.command === envHookCmd)
|
|
308
|
+
);
|
|
309
|
+
const hasSession = sessionStartHooks.some((h) =>
|
|
310
|
+
h.hooks?.some((hh) => hh.command === sessionHookCmd)
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
const toAdd = [];
|
|
314
|
+
if (!hasTsc) toAdd.push(`PostToolUse(Write|Edit|MultiEdit) → tsc-check.js`);
|
|
315
|
+
if (!hasEnv) toAdd.push(`PreToolUse(Read|Grep) → env-protect.js`);
|
|
316
|
+
|
|
317
|
+
log(`\n${CYAN}Configuring hooks...${RESET}`);
|
|
318
|
+
|
|
319
|
+
if (toAdd.length === 0 && hasSession) {
|
|
320
|
+
log(`${GREEN}✓${RESET} Hooks already configured.\n`);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (toAdd.length > 0) {
|
|
325
|
+
log(` The following hooks will be added to ~/.claude/settings.json:\n`);
|
|
326
|
+
for (const h of toAdd) {
|
|
327
|
+
log(` ${CYAN}+${RESET} ${h}`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Ask about session-prime separately (opt-in)
|
|
332
|
+
let installSessionPrime = false;
|
|
333
|
+
if (!hasSession) {
|
|
334
|
+
log(`\n ${YELLOW}Optional:${RESET} session-prime.js auto-loads project context on session start.`);
|
|
335
|
+
installSessionPrime = await confirm(` Enable session-prime hook? (y/N) `);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (toAdd.length === 0 && !installSessionPrime) {
|
|
339
|
+
log(` ${YELLOW}↷${RESET} Skipped hooks — you can configure ~/.claude/settings.json manually\n`);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const ok = toAdd.length > 0
|
|
344
|
+
? await confirm(`\n Install these hooks? (y/N) `)
|
|
345
|
+
: true;
|
|
346
|
+
|
|
347
|
+
if (!ok) {
|
|
348
|
+
log(` ${YELLOW}↷${RESET} Skipped hooks — you can configure ~/.claude/settings.json manually\n`);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Copy hook files
|
|
353
|
+
fs.mkdirSync(HOOKS_DIR, { recursive: true });
|
|
354
|
+
for (const file of hookFiles) {
|
|
355
|
+
await installFile(
|
|
356
|
+
path.join(hooksSrcDir, file),
|
|
357
|
+
path.join(HOOKS_DIR, file),
|
|
358
|
+
`~/.claude/hooks/${file}`
|
|
359
|
+
);
|
|
360
|
+
// Make executable
|
|
361
|
+
try {
|
|
362
|
+
fs.chmodSync(path.join(HOOKS_DIR, file), 0o755);
|
|
363
|
+
} catch {
|
|
364
|
+
// Non-critical
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Build updated hooks config
|
|
369
|
+
if (!settings.hooks) settings.hooks = {};
|
|
370
|
+
|
|
371
|
+
if (!hasTsc) {
|
|
372
|
+
if (!settings.hooks.PostToolUse) settings.hooks.PostToolUse = [];
|
|
373
|
+
settings.hooks.PostToolUse.push({
|
|
374
|
+
matcher: "Write|Edit|MultiEdit",
|
|
375
|
+
hooks: [{ type: "command", command: tscHookCmd }],
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
if (!hasEnv) {
|
|
379
|
+
if (!settings.hooks.PreToolUse) settings.hooks.PreToolUse = [];
|
|
380
|
+
settings.hooks.PreToolUse.push({
|
|
381
|
+
matcher: "Read|Grep",
|
|
382
|
+
hooks: [{ type: "command", command: envHookCmd }],
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
if (installSessionPrime && !hasSession) {
|
|
386
|
+
if (!settings.hooks.SessionStart) settings.hooks.SessionStart = [];
|
|
387
|
+
settings.hooks.SessionStart.push({
|
|
388
|
+
hooks: [{ type: "command", command: sessionHookCmd }],
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
393
|
+
log(` ${GREEN}✓${RESET} Hooks configured.\n`);
|
|
229
394
|
}
|
|
230
395
|
|
|
231
396
|
const HOPLA_PERMISSIONS = [
|
|
@@ -139,6 +139,16 @@ Before saving the draft, review the plan against these criteria:
|
|
|
139
139
|
|
|
140
140
|
## Phase 7: Save Draft and Enter Review Loop
|
|
141
141
|
|
|
142
|
+
**Before saving, identify the target file:**
|
|
143
|
+
|
|
144
|
+
1. List all files in `.agents/plans/` (both `*.draft.md` and `*.md`)
|
|
145
|
+
2. Determine the target filename from the feature name derived in Phase 1: `[kebab-case-feature-name].draft.md`
|
|
146
|
+
3. If a file with that name already exists → **overwrite it**
|
|
147
|
+
4. If a file with a similar name exists (e.g. same feature, slight variation) → **overwrite it and confirm which file was updated**
|
|
148
|
+
5. Never create versioned files (e.g. `-v2`, `-updated`, `-new`) — always update in place
|
|
149
|
+
|
|
150
|
+
**Save and notify:**
|
|
151
|
+
|
|
142
152
|
1. Save the plan to `.agents/plans/[kebab-case-feature-name].draft.md`
|
|
143
153
|
2. Tell the user:
|
|
144
154
|
> "Plan draft saved to `.agents/plans/[feature-name].draft.md` — open it in your editor and review it carefully. If you want changes, add comments like `<? change this >` anywhere in the file and tell me 'apply comments'. You can also request changes directly in the chat. When it's ready, say 'done' to create the final file."
|
|
@@ -147,10 +157,11 @@ Before saving the draft, review the plan against these criteria:
|
|
|
147
157
|
- Any open questions or decisions that require human input before execution
|
|
148
158
|
|
|
149
159
|
**Review loop:** Stay in this loop until the user finalizes:
|
|
150
|
-
- If the user says **"apply comments"** →
|
|
151
|
-
- If the user requests changes in chat → apply directly to the draft, confirm what changed
|
|
160
|
+
- If the user says **"apply comments"** → identify the active draft (the one saved in this session, or ask if unclear), scan it for `<? ... >`, apply each one, remove the comment tags, update the file, report what changed
|
|
161
|
+
- If the user requests changes in chat → apply directly to the active draft, confirm the filename and what changed
|
|
162
|
+
- If the user references a specific plan file (e.g. passes a path) → treat that file as the active draft
|
|
152
163
|
- If the user says the plan is ready → proceed to finalize
|
|
153
164
|
|
|
154
165
|
**Finalize:**
|
|
155
|
-
1. Rename `.agents/plans/[feature-name].draft.md` → `.agents/plans/[feature-name].md`
|
|
166
|
+
1. Rename `.agents/plans/[feature-name].draft.md` → `.agents/plans/[feature-name].md` (overwrite if it already exists)
|
|
156
167
|
2. Confirm: "✅ Plan saved to `.agents/plans/[feature-name].md`. Run `/hopla-git-commit` to commit it, then share with the team to execute with `/hopla-execute .agents/plans/[feature-name].md`."
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PreToolUse hook: blocks reads/greps targeting .env files
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
const chunks = [];
|
|
6
|
+
for await (const chunk of process.stdin) {
|
|
7
|
+
chunks.push(chunk);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const toolCall = JSON.parse(Buffer.concat(chunks).toString());
|
|
11
|
+
const filePath = toolCall.tool_input?.file_path || toolCall.tool_input?.path || "";
|
|
12
|
+
|
|
13
|
+
if (filePath.includes(".env")) {
|
|
14
|
+
process.stderr.write(
|
|
15
|
+
`Access denied: Reading .env files is blocked to prevent accidental secret exposure. ` +
|
|
16
|
+
`If you need environment variable names, check the README or ask the user.\n`
|
|
17
|
+
);
|
|
18
|
+
process.exit(2);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
main();
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SessionStart hook: provides initial project context when a session begins
|
|
3
|
+
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
function run(cmd) {
|
|
9
|
+
try {
|
|
10
|
+
return execSync(cmd, { cwd: process.cwd(), stdio: "pipe" }).toString().trim();
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
const lines = [];
|
|
18
|
+
|
|
19
|
+
// Git context
|
|
20
|
+
const branch = run("git branch --show-current");
|
|
21
|
+
const log = run("git log --oneline -5");
|
|
22
|
+
const status = run("git status --short");
|
|
23
|
+
|
|
24
|
+
if (branch) {
|
|
25
|
+
lines.push(`Current branch: ${branch}`);
|
|
26
|
+
}
|
|
27
|
+
if (log) {
|
|
28
|
+
lines.push(`Recent commits:\n${log}`);
|
|
29
|
+
}
|
|
30
|
+
if (status) {
|
|
31
|
+
lines.push(`Uncommitted changes:\n${status}`);
|
|
32
|
+
} else if (branch) {
|
|
33
|
+
lines.push("Working tree is clean.");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// CLAUDE.md summary (first 20 lines)
|
|
37
|
+
const claudeMdPath = path.join(process.cwd(), "CLAUDE.md");
|
|
38
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
39
|
+
const content = fs.readFileSync(claudeMdPath, "utf8").split("\n").slice(0, 20).join("\n");
|
|
40
|
+
lines.push(`Project rules (CLAUDE.md excerpt):\n${content}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (lines.length > 0) {
|
|
44
|
+
process.stdout.write("=== Session Context ===\n" + lines.join("\n\n") + "\n======================\n");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
main();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PostToolUse hook: runs tsc --noEmit after file edits and feeds errors back to Claude
|
|
3
|
+
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
const chunks = [];
|
|
10
|
+
for await (const chunk of process.stdin) {
|
|
11
|
+
chunks.push(chunk);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// If no tsconfig.json in cwd, exit silently (non-TS project)
|
|
15
|
+
const tsconfigPath = path.join(process.cwd(), "tsconfig.json");
|
|
16
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let result;
|
|
21
|
+
try {
|
|
22
|
+
execSync("tsc --noEmit", { cwd: process.cwd(), stdio: "pipe" });
|
|
23
|
+
// No errors — exit silently
|
|
24
|
+
process.exit(0);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
const output = (err.stdout || "").toString() + (err.stderr || "").toString();
|
|
27
|
+
if (output.trim()) {
|
|
28
|
+
process.stdout.write("TypeScript errors detected:\n" + output + "\n");
|
|
29
|
+
}
|
|
30
|
+
// Exit 0: PostToolUse hooks cannot block, but stdout is fed back to Claude
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
main();
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hopla-code-review
|
|
3
|
+
description: Performs a technical code review on recently changed files. Use when the user says "review the code", "revisar el código", "code review", "analiza los cambios", "check my code", "revisa mi código", "look for issues", or asks for feedback on their implementation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Perform a technical code review focused on finding real bugs and issues.
|
|
7
|
+
|
|
8
|
+
## Step 1: Load Context
|
|
9
|
+
|
|
10
|
+
Read `CLAUDE.md` or `AGENTS.md` to understand project standards and patterns.
|
|
11
|
+
|
|
12
|
+
If `.agents/guides/` exists, read any guides relevant to the files being reviewed (e.g. `@.agents/guides/api-guide.md` when reviewing API changes). These guides define the expected patterns for specific task types.
|
|
13
|
+
|
|
14
|
+
## Step 2: Identify Changed Files
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git diff --stat HEAD
|
|
18
|
+
git diff HEAD
|
|
19
|
+
git ls-files --others --exclude-standard
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Read each changed or new file in its entirety — not just the diff.
|
|
23
|
+
|
|
24
|
+
## Step 3: Analyze for Issues
|
|
25
|
+
|
|
26
|
+
For each changed file, look for:
|
|
27
|
+
|
|
28
|
+
**1. Logic Errors**
|
|
29
|
+
- Off-by-one errors, incorrect conditionals
|
|
30
|
+
- Missing error handling, unhandled edge cases
|
|
31
|
+
- Race conditions or async issues
|
|
32
|
+
|
|
33
|
+
**2. Security Issues**
|
|
34
|
+
- Exposed secrets or API keys
|
|
35
|
+
- SQL/command injection vulnerabilities
|
|
36
|
+
- Insecure data handling or missing input validation
|
|
37
|
+
- XSS vulnerabilities (frontend)
|
|
38
|
+
|
|
39
|
+
**3. Performance Problems**
|
|
40
|
+
- Unnecessary re-renders (React)
|
|
41
|
+
- N+1 queries or redundant API calls
|
|
42
|
+
- Memory leaks
|
|
43
|
+
|
|
44
|
+
**4. Code Quality**
|
|
45
|
+
- DRY violations
|
|
46
|
+
- Poor naming or overly complex functions
|
|
47
|
+
- Missing TypeScript types or `any` usage
|
|
48
|
+
|
|
49
|
+
**5. Pattern Adherence**
|
|
50
|
+
- Follows project conventions from CLAUDE.md
|
|
51
|
+
- Consistent with existing codebase style
|
|
52
|
+
|
|
53
|
+
## Step 4: Verify Issues Are Real
|
|
54
|
+
|
|
55
|
+
Before reporting, confirm each issue is legitimate:
|
|
56
|
+
- Run relevant tests if applicable
|
|
57
|
+
- Check if the pattern is intentional based on context
|
|
58
|
+
|
|
59
|
+
## Step 5: Output Report
|
|
60
|
+
|
|
61
|
+
Save to `.agents/code-reviews/[descriptive-name].md`
|
|
62
|
+
|
|
63
|
+
**Format for each issue:**
|
|
64
|
+
```
|
|
65
|
+
severity: critical | high | medium | low
|
|
66
|
+
file: path/to/file.ts
|
|
67
|
+
line: 42
|
|
68
|
+
issue: [one-line description]
|
|
69
|
+
detail: [why this is a problem]
|
|
70
|
+
suggestion: [how to fix it]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If no issues found: "Code review passed. No technical issues detected."
|
|
74
|
+
|
|
75
|
+
**Rules:**
|
|
76
|
+
- Be specific — line numbers, not vague complaints
|
|
77
|
+
- Focus on real bugs, not style preferences (linting handles that)
|
|
78
|
+
- Flag security issues as `critical`
|
|
79
|
+
- Suggest fixes, don't just identify problems
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hopla-execution-report
|
|
3
|
+
description: Generates an implementation report documenting what was built. Use when the user says "generate the report", "genera el reporte", "documenta lo implementado", "execution report", "document what was done", "write the implementation report", or after finishing a feature before committing.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Review and document the implementation you just completed. Run this immediately after finishing a feature — before committing or starting the next task.
|
|
7
|
+
|
|
8
|
+
## Step 1: Gather Implementation Data
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git diff HEAD --stat
|
|
12
|
+
git diff HEAD
|
|
13
|
+
git ls-files --others --exclude-standard
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Step 2: Generate Report
|
|
17
|
+
|
|
18
|
+
Save to: `.agents/execution-reports/[feature-name].md`
|
|
19
|
+
|
|
20
|
+
Use the following structure:
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
### Meta Information
|
|
25
|
+
|
|
26
|
+
- **Plan file:** [path to the plan that guided this implementation]
|
|
27
|
+
- **Files added:** [list with paths]
|
|
28
|
+
- **Files modified:** [list with paths]
|
|
29
|
+
- **Lines changed:** +X -Y
|
|
30
|
+
|
|
31
|
+
### Validation Results
|
|
32
|
+
|
|
33
|
+
- Syntax & Linting: ✓/✗ [details if failed]
|
|
34
|
+
- Type Checking: ✓/✗ [details if failed]
|
|
35
|
+
- Unit Tests: ✓/✗ [X passed, Y failed]
|
|
36
|
+
- Integration Tests: ✓/✗ [X passed, Y failed]
|
|
37
|
+
|
|
38
|
+
### What Went Well
|
|
39
|
+
|
|
40
|
+
List specific things that worked smoothly:
|
|
41
|
+
- [concrete examples]
|
|
42
|
+
|
|
43
|
+
### Challenges Encountered
|
|
44
|
+
|
|
45
|
+
List specific difficulties encountered:
|
|
46
|
+
- [what was difficult and why]
|
|
47
|
+
|
|
48
|
+
### Divergences from Plan
|
|
49
|
+
|
|
50
|
+
For each divergence from the original plan:
|
|
51
|
+
|
|
52
|
+
**[Divergence Title]**
|
|
53
|
+
- **Planned:** [what the plan specified]
|
|
54
|
+
- **Actual:** [what was implemented instead]
|
|
55
|
+
- **Reason:** [why this divergence occurred]
|
|
56
|
+
- **Type:** Better approach found | Plan assumption wrong | Security concern | Performance issue | Other
|
|
57
|
+
|
|
58
|
+
### Skipped Items
|
|
59
|
+
|
|
60
|
+
List anything from the plan that was not implemented:
|
|
61
|
+
- [what was skipped] — Reason: [why]
|
|
62
|
+
|
|
63
|
+
### Recommendations
|
|
64
|
+
|
|
65
|
+
Based on this implementation, what should change for next time?
|
|
66
|
+
- Plan command improvements: [suggestions]
|
|
67
|
+
- Execute command improvements: [suggestions]
|
|
68
|
+
- CLAUDE.md additions: [suggestions]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hopla-git
|
|
3
|
+
description: Handles git operations: creating commits, making pull requests, pushing branches. Use when the user asks to commit, create a commit, save changes to git, make a PR, create a pull request, push the branch, or any git workflow action.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Detect the user's intent and execute the appropriate git workflow.
|
|
7
|
+
|
|
8
|
+
## Intent Detection
|
|
9
|
+
|
|
10
|
+
**If the user wants to commit** (keywords: "commit", "comitea", "guarda los cambios", "save changes", "crear commit", "hacer commit"):
|
|
11
|
+
- Read and follow the instructions in `commit.md` (located in the same directory as this skill)
|
|
12
|
+
|
|
13
|
+
**If the user wants to create a PR or push** (keywords: "PR", "pull request", "crea un PR", "abre un PR", "push", "merge request"):
|
|
14
|
+
- Read and follow the instructions in `pr.md` (located in the same directory as this skill)
|
|
15
|
+
|
|
16
|
+
**If unclear**, ask the user one short question: "¿Commit o Pull Request?" / "Commit or Pull Request?"
|
|
17
|
+
|
|
18
|
+
## File References
|
|
19
|
+
|
|
20
|
+
The full step-by-step instructions for each workflow are in:
|
|
21
|
+
- `~/.claude/skills/hopla-git/commit.md` — conventional commit with Git Flow awareness
|
|
22
|
+
- `~/.claude/skills/hopla-git/pr.md` — GitHub PR creation with structured description
|
|
23
|
+
|
|
24
|
+
Read the relevant file now and follow its instructions completely.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Hopla Git Commit — Full Workflow
|
|
2
|
+
|
|
3
|
+
Review the current git state and create an appropriate conventional commit.
|
|
4
|
+
|
|
5
|
+
## Step 1: Gather Context
|
|
6
|
+
|
|
7
|
+
Run these commands to understand what changed:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git status
|
|
11
|
+
git diff --staged
|
|
12
|
+
git diff
|
|
13
|
+
git log --oneline -5
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Step 2: Analyze Changes
|
|
17
|
+
|
|
18
|
+
- Identify what was added, modified, or deleted
|
|
19
|
+
- Determine the appropriate commit type: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `style`
|
|
20
|
+
- Identify the scope if relevant (e.g., `auth`, `api`, `ui`)
|
|
21
|
+
- Check current branch — confirm it follows Git Flow naming (`feature/`, `fix/`, `hotfix/`, `develop`, `dev`)
|
|
22
|
+
|
|
23
|
+
## Step 3: Stage Files
|
|
24
|
+
|
|
25
|
+
Stage only the relevant files for this commit (avoid `git add -A` unless all changes belong together):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git add <specific files>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Step 4: Propose Commit
|
|
32
|
+
|
|
33
|
+
Present the proposed commit message to the user **before executing**:
|
|
34
|
+
|
|
35
|
+
> "Proposed commit:
|
|
36
|
+
> `feat(products): add price filter to search endpoint`
|
|
37
|
+
>
|
|
38
|
+
> Files included: [list files]
|
|
39
|
+
> Shall I proceed?"
|
|
40
|
+
|
|
41
|
+
Wait for explicit approval before running `git commit`.
|
|
42
|
+
|
|
43
|
+
## Step 5: Execute Commit
|
|
44
|
+
|
|
45
|
+
Once approved, create the commit:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git commit -m "<type>(<scope>): <description>"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Step 6: Push Reminder
|
|
52
|
+
|
|
53
|
+
After committing, remind the user:
|
|
54
|
+
|
|
55
|
+
> "Commit created locally. Do you want to push to `origin/<branch>`?"
|
|
56
|
+
|
|
57
|
+
**Never push automatically** — wait for explicit confirmation.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Hopla Git PR — Full Workflow
|
|
2
|
+
|
|
3
|
+
Create a Pull Request on GitHub for the current branch.
|
|
4
|
+
|
|
5
|
+
## Step 1: Gather Context
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git status
|
|
9
|
+
git branch --show-current
|
|
10
|
+
git log --oneline origin/$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null | sed 's|.*/||' || echo 'develop')..HEAD
|
|
11
|
+
git diff --stat origin/$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null | sed 's|.*/||' || echo 'develop')..HEAD
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Read the following if they exist:
|
|
15
|
+
- The plan file in `.agents/plans/` related to this feature
|
|
16
|
+
- `CLAUDE.md` — for project context
|
|
17
|
+
|
|
18
|
+
## Step 2: Determine Base Branch
|
|
19
|
+
|
|
20
|
+
- If the user specified a base branch, use it
|
|
21
|
+
- Otherwise default to `develop` (or `dev` if that's what the project uses)
|
|
22
|
+
- If on `main` or `develop` directly, warn the user: "You're on `[branch]` — PRs should come from feature branches."
|
|
23
|
+
|
|
24
|
+
## Step 3: Check Push Status
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git status
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If the branch hasn't been pushed yet:
|
|
31
|
+
> "Branch not pushed yet. Push to origin first?"
|
|
32
|
+
|
|
33
|
+
Wait for confirmation before pushing:
|
|
34
|
+
```bash
|
|
35
|
+
git push -u origin <branch>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Step 4: Build PR Description
|
|
39
|
+
|
|
40
|
+
Using the commits and plan context, draft:
|
|
41
|
+
|
|
42
|
+
**Title:** `[type(scope)]: short description` — match the main commit or feature name, max 70 chars
|
|
43
|
+
|
|
44
|
+
**Body:**
|
|
45
|
+
```markdown
|
|
46
|
+
## Summary
|
|
47
|
+
- [What was built — 2-3 bullets max]
|
|
48
|
+
|
|
49
|
+
## Changes
|
|
50
|
+
- [Key files modified and why]
|
|
51
|
+
|
|
52
|
+
## Test Plan
|
|
53
|
+
- [ ] [How to verify this works]
|
|
54
|
+
- [ ] [Edge cases to check]
|
|
55
|
+
|
|
56
|
+
## Related
|
|
57
|
+
- Plan: `.agents/plans/[feature-name].md` (if exists)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Step 5: Propose and Confirm
|
|
61
|
+
|
|
62
|
+
Show the proposed PR title and body to the user:
|
|
63
|
+
> "Proposed PR:
|
|
64
|
+
> Title: `[title]`
|
|
65
|
+
> Base: `[base branch]`
|
|
66
|
+
> [body preview]
|
|
67
|
+
> Shall I create it?"
|
|
68
|
+
|
|
69
|
+
Wait for explicit approval before creating.
|
|
70
|
+
|
|
71
|
+
## Step 6: Create PR
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
gh pr create --title "[title]" --body "[body]" --base [base-branch]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
After creating, show the PR URL to the user.
|
|
78
|
+
|
|
79
|
+
**Never merge automatically** — the PR is for human review.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hopla-prime
|
|
3
|
+
description: Orients Claude in a project at the start of a session. Use when the user says "orient yourself", "get oriented", "prime yourself", "ponte al día", "qué es este proyecto", "what is this project", "load context", or asks Claude to familiarize itself with the codebase before starting work.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Get oriented in this project before doing any work.
|
|
7
|
+
|
|
8
|
+
## Step 1: Project Structure
|
|
9
|
+
|
|
10
|
+
Use the Glob tool to list project files (up to 60):
|
|
11
|
+
- Pattern: `**/*` with head_limit: 60
|
|
12
|
+
|
|
13
|
+
Use the Glob tool to find key config files:
|
|
14
|
+
- `**/CLAUDE.md`
|
|
15
|
+
- `**/AGENTS.md`
|
|
16
|
+
- `**/README.md`
|
|
17
|
+
|
|
18
|
+
## Step 2: Read Key Files
|
|
19
|
+
|
|
20
|
+
Read in this order:
|
|
21
|
+
1. `CLAUDE.md` or `AGENTS.md` at project root (project-specific rules)
|
|
22
|
+
2. `README.md` (project overview)
|
|
23
|
+
3. `package.json` or `pyproject.toml` (dependencies and scripts)
|
|
24
|
+
|
|
25
|
+
## Step 3: Understand Git State
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git branch --show-current
|
|
29
|
+
git log --oneline -10
|
|
30
|
+
git status
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Step 4: Check Pending Work
|
|
34
|
+
|
|
35
|
+
Use the Glob tool to check for pending plans:
|
|
36
|
+
- Pattern: `.agents/plans/*.md`
|
|
37
|
+
|
|
38
|
+
If `.agents/plans/` exists, identify:
|
|
39
|
+
- `.draft.md` files — unfinished drafts waiting for review
|
|
40
|
+
- `.md` files (without `.draft`) — finalized plans ready to execute
|
|
41
|
+
|
|
42
|
+
## Step 5: Summary Report
|
|
43
|
+
|
|
44
|
+
Write a short, conversational message addressed directly to the user. Mention:
|
|
45
|
+
- What the project is and what it does
|
|
46
|
+
- The current branch and what it's for
|
|
47
|
+
- Whether there are uncommitted changes or pending work
|
|
48
|
+
- The command to start the project (if available)
|
|
49
|
+
|
|
50
|
+
If there are pending plans, list them clearly after the prose summary:
|
|
51
|
+
```
|
|
52
|
+
Pending plans:
|
|
53
|
+
- inventory-page.draft.md ← draft, not finalized yet
|
|
54
|
+
- add-user-authentication.md ← ready to execute with /hopla-execute
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
End with a sentence like: "Listo para continuar — ¿por dónde empezamos?" or "All caught up — what are we working on today?" depending on the language the user writes in.
|
|
58
|
+
|
|
59
|
+
Do NOT use headers in the prose summary. Write it as natural, friendly prose, then the pending plans list if applicable.
|