@hopla/claude-setup 1.14.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/.mcp.json.example +41 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +23 -1
- package/cli.js +19 -2
- package/commands/code-review-fix.md +1 -1
- package/commands/create-prd.md +1 -1
- package/commands/execute.md +5 -5
- package/commands/guide.md +8 -8
- package/commands/guides/ai-optimized-codebase.md +1 -1
- package/commands/guides/mcp-integration.md +3 -3
- package/commands/guides/remote-coding.md +3 -3
- package/commands/guides/review-checklist.md +5 -5
- package/commands/guides/scaling-beyond-engineering.md +6 -9
- package/commands/init-project.md +10 -10
- package/commands/plan-feature.md +2 -2
- package/commands/rca.md +2 -2
- package/commands/review-plan.md +2 -2
- package/commands/validate.md +2 -2
- package/global-rules.md +15 -5
- package/hooks/env-protect.js +39 -8
- package/hooks/hooks.json +23 -1
- package/hooks/precompact-snapshot.js +65 -0
- package/hooks/prompt-route.js +125 -0
- package/hooks/session-prime.js +20 -0
- package/hooks/statusline.js +83 -0
- package/hooks/tsc-check.js +21 -10
- package/package.json +1 -1
- package/skills/brainstorm/SKILL.md +3 -3
- package/skills/code-review/SKILL.md +1 -1
- package/skills/debug/SKILL.md +2 -2
- package/skills/execution-report/SKILL.md +1 -1
- package/skills/git/commit.md +1 -1
- package/skills/git/pr.md +1 -1
- package/skills/prime/SKILL.md +1 -1
- package/skills/subagent-execution/SKILL.md +1 -1
- package/skills/tdd/SKILL.md +1 -1
- package/skills/verify/SKILL.md +1 -1
- package/skills/worktree/SKILL.md +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Copy this file to your project root as .mcp.json and uncomment the servers you want Claude Code to use. Each server is standalone — enable only what you need. Set the required env vars in your shell or .envrc (NOT committed). Restart Claude Code after editing.",
|
|
3
|
+
|
|
4
|
+
"mcpServers": {
|
|
5
|
+
"_playwright_example": {
|
|
6
|
+
"_note": "Browser automation for E2E testing and UI inspection. No credentials needed.",
|
|
7
|
+
"command": "npx",
|
|
8
|
+
"args": ["-y", "@playwright/mcp"]
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
"_github_example": {
|
|
12
|
+
"_note": "GitHub API access for reading repos, issues, PRs. Requires a token with the scopes you need.",
|
|
13
|
+
"command": "npx",
|
|
14
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
15
|
+
"env": {
|
|
16
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
"_linear_example": {
|
|
21
|
+
"_note": "Linear workspace access (issues, projects, cycles). Get an API key at linear.app/settings/api.",
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["-y", "@tacticlaunch/mcp-linear"],
|
|
24
|
+
"env": {
|
|
25
|
+
"LINEAR_API_KEY": "${LINEAR_API_KEY}"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
"_postgres_example": {
|
|
30
|
+
"_note": "Read-only Postgres access for database introspection and ad-hoc queries.",
|
|
31
|
+
"command": "npx",
|
|
32
|
+
"args": ["-y", "@modelcontextprotocol/server-postgres", "${DATABASE_URL}"]
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
"_filesystem_example": {
|
|
36
|
+
"_note": "Constrained filesystem access outside the current workspace (e.g. to inspect ~/Documents/specs).",
|
|
37
|
+
"command": "npx",
|
|
38
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/ABSOLUTE/PATH/TO/ALLOWED/DIR"]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hopla",
|
|
3
3
|
"description": "Agentic coding system for Claude Code: PIV loop (Plan → Implement → Validate), TDD, debugging, brainstorming, subagent execution, and team workflows",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.15.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Hopla Tools",
|
|
7
7
|
"email": "julio@hopla.tools"
|
package/README.md
CHANGED
|
@@ -101,10 +101,32 @@ Removes `~/.claude/CLAUDE.md` plus legacy `hopla-*` files from older installs.
|
|
|
101
101
|
| `claude-setup --force` | Install without prompts |
|
|
102
102
|
| `claude-setup --migrate` | Remove legacy CLI-installed duplicates only |
|
|
103
103
|
| `claude-setup --uninstall` | Remove global rules + legacy files |
|
|
104
|
+
| `claude-setup --dry-run` | Preview changes without touching disk (composes with other flags) |
|
|
104
105
|
| `claude-setup --version` | Print package version |
|
|
105
106
|
|
|
106
107
|
---
|
|
107
108
|
|
|
109
|
+
## Optional: Hopla statusline
|
|
110
|
+
|
|
111
|
+
The plugin ships a statusline script that shows your branch, worktree indicator, uncommitted count, and active plan file (`📋 plan-name`) in Claude Code's status bar.
|
|
112
|
+
|
|
113
|
+
Enable it by adding to `~/.claude/settings.json`:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"statusLine": {
|
|
118
|
+
"type": "command",
|
|
119
|
+
"command": "node ~/.claude/plugins/marketplaces/hopla-marketplace/hooks/statusline.js"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Then run `/reload-plugins` or restart Claude Code.
|
|
125
|
+
|
|
126
|
+
Sample output: ` feature/auth · 3M · 📋 add-authentication`
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
108
130
|
## Naming Convention
|
|
109
131
|
|
|
110
132
|
Skills and commands use short names in source (e.g., `prime`, `execute`, `git`). The plugin namespaces them automatically:
|
|
@@ -168,7 +190,7 @@ Plan → Implement → Validate → (repeat)
|
|
|
168
190
|
|
|
169
191
|
### System Evolution
|
|
170
192
|
|
|
171
|
-
After each PIV loop, run
|
|
193
|
+
After each PIV loop, run the `execution-report` skill + `/hopla:system-review` to find process improvements. Don't just fix bugs — fix the system that allowed them.
|
|
172
194
|
|
|
173
195
|
---
|
|
174
196
|
|
package/cli.js
CHANGED
|
@@ -50,14 +50,31 @@ function safeRm(target, opts = {}) {
|
|
|
50
50
|
fs.rmSync(target, opts);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// Atomic write: stage to a tmp file and rename over the target.
|
|
54
|
+
// Protects ~/.claude/settings.json from corruption if the process crashes mid-write.
|
|
53
55
|
function safeWrite(target, content) {
|
|
54
56
|
if (DRY_RUN) return;
|
|
55
|
-
|
|
57
|
+
const tmp = `${target}.tmp.${process.pid}.${Date.now()}`;
|
|
58
|
+
try {
|
|
59
|
+
fs.writeFileSync(tmp, content);
|
|
60
|
+
fs.renameSync(tmp, target);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
try { fs.rmSync(tmp, { force: true }); } catch { /* ignore */ }
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
56
65
|
}
|
|
57
66
|
|
|
67
|
+
// Atomic copy: copy to a tmp path and rename over the destination.
|
|
58
68
|
function safeCopy(src, dest) {
|
|
59
69
|
if (DRY_RUN) return;
|
|
60
|
-
|
|
70
|
+
const tmp = `${dest}.tmp.${process.pid}.${Date.now()}`;
|
|
71
|
+
try {
|
|
72
|
+
fs.copyFileSync(src, tmp);
|
|
73
|
+
fs.renameSync(tmp, dest);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
try { fs.rmSync(tmp, { force: true }); } catch { /* ignore */ }
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
61
78
|
}
|
|
62
79
|
|
|
63
80
|
function safeMkdir(dir, opts) {
|
|
@@ -58,4 +58,4 @@ Provide a summary of:
|
|
|
58
58
|
## Next Step
|
|
59
59
|
|
|
60
60
|
After all fixes pass validation, suggest:
|
|
61
|
-
> "All review issues fixed and validation passed. Run
|
|
61
|
+
> "All review issues fixed and validation passed. Run the `execution-report` skill to document the implementation, then the `git` skill (say "commit") to commit."
|
package/commands/create-prd.md
CHANGED
|
@@ -222,4 +222,4 @@ Do not ask clarifying questions about changes — just apply them and confirm wh
|
|
|
222
222
|
1. Rename `PRD.draft.md` → `PRD.md` (overwrite if it existed)
|
|
223
223
|
2. Rename any `.draft` context documents to their final names
|
|
224
224
|
3. Delete all `.draft` files
|
|
225
|
-
4. Confirm: "✅ `PRD.md` saved. Run
|
|
225
|
+
4. Confirm: "✅ `PRD.md` saved. Run the `git` skill (say "commit") to save it to the repository."
|
package/commands/execute.md
CHANGED
|
@@ -166,7 +166,7 @@ Run integration tests or manual verification as specified in the plan (e.g. `npm
|
|
|
166
166
|
Verify the feature works end-to-end.
|
|
167
167
|
|
|
168
168
|
### Level 5 — Code Review
|
|
169
|
-
Run a code review on all changed files following the
|
|
169
|
+
Run a code review on all changed files following the the `code-review` skill process. This catches bugs that linting, types, and tests miss (security issues, logic errors, pattern violations).
|
|
170
170
|
|
|
171
171
|
If the review finds critical or high severity issues, **fix them before proceeding**.
|
|
172
172
|
|
|
@@ -220,7 +220,7 @@ Provide a summary of what was done:
|
|
|
220
220
|
## Step 7: Suggest Next Steps
|
|
221
221
|
|
|
222
222
|
After the summary, suggest:
|
|
223
|
-
1. Run
|
|
224
|
-
2. If issues are found, run `/hopla
|
|
225
|
-
3. Run
|
|
226
|
-
4. Run
|
|
223
|
+
1. Run the `code-review` skill for a standalone review of the changes (recommended — a fresh review catches issues the executing agent may have missed)
|
|
224
|
+
2. If issues are found, run `/hopla:code-review-fix` to fix them
|
|
225
|
+
3. Run the `execution-report` skill to document the implementation
|
|
226
|
+
4. Run the `git` skill (say "commit") to commit the changes
|
package/commands/guide.md
CHANGED
|
@@ -45,19 +45,19 @@ Three categories for every task:
|
|
|
45
45
|
## Your Available Commands
|
|
46
46
|
|
|
47
47
|
### For Planning & Product
|
|
48
|
-
- `/hopla
|
|
49
|
-
- `/hopla
|
|
50
|
-
- `/hopla
|
|
48
|
+
- `/hopla:create-prd` — Create a Product Requirements Document through guided conversation
|
|
49
|
+
- `/hopla:plan-feature` — Create an implementation plan (AI researches, you approve)
|
|
50
|
+
- `/hopla:review-plan` — Review a plan before execution
|
|
51
51
|
|
|
52
52
|
### For Oversight
|
|
53
|
-
- `/hopla
|
|
54
|
-
- `/hopla
|
|
53
|
+
- `/hopla:system-review` — Analyze how well the AI followed the plan
|
|
54
|
+
- `/hopla:guide` — Show this guide again
|
|
55
55
|
|
|
56
56
|
## Getting Started
|
|
57
57
|
|
|
58
|
-
1. Start with `/hopla
|
|
59
|
-
2. Use `/hopla
|
|
60
|
-
3. Review the plan with `/hopla
|
|
58
|
+
1. Start with `/hopla:create-prd` to define your project scope
|
|
59
|
+
2. Use `/hopla:plan-feature "your feature idea"` to plan each feature
|
|
60
|
+
3. Review the plan with `/hopla:review-plan`
|
|
61
61
|
4. Hand off to a developer for execution, or ask the AI to execute
|
|
62
62
|
|
|
63
63
|
## Tips for Better Results
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AI-Optimized Codebase Guide
|
|
2
2
|
|
|
3
3
|
## When to Use This Guide
|
|
4
|
-
Reference this guide when initializing a project with `/hopla
|
|
4
|
+
Reference this guide when initializing a project with `/hopla:init-project` or when optimizing an existing codebase for better AI-assisted development.
|
|
5
5
|
|
|
6
6
|
## Principles
|
|
7
7
|
|
|
@@ -5,17 +5,17 @@ Reference this guide when planning features that involve external tools or servi
|
|
|
5
5
|
|
|
6
6
|
## MCP in the PIV Loop
|
|
7
7
|
|
|
8
|
-
### During Planning (`/hopla
|
|
8
|
+
### During Planning (`/hopla:plan-feature`)
|
|
9
9
|
- Check what MCP servers are configured (listed in CLAUDE.md under "MCP Servers")
|
|
10
10
|
- For each external integration point, specify which MCP tool to use
|
|
11
11
|
- Example: "Step 3: Use Playwright MCP to verify the component renders correctly"
|
|
12
12
|
|
|
13
|
-
### During Execution (`/hopla
|
|
13
|
+
### During Execution (`/hopla:execute`)
|
|
14
14
|
- Before starting, verify MCP servers are available and responsive
|
|
15
15
|
- When a task involves an MCP tool, use it explicitly (don't fall back to manual alternatives)
|
|
16
16
|
- If an MCP server is unavailable, document it and skip that validation step
|
|
17
17
|
|
|
18
|
-
### During Validation (`/hopla
|
|
18
|
+
### During Validation (`/hopla:validate`)
|
|
19
19
|
- Use Playwright MCP for E2E browser validation if configured
|
|
20
20
|
- Use database MCPs to verify data state after migrations
|
|
21
21
|
- Document which validations were done via MCP vs. manual
|
|
@@ -50,9 +50,9 @@ jobs:
|
|
|
50
50
|
run: |
|
|
51
51
|
npx claude-code --print "
|
|
52
52
|
Read issue #${{ github.event.issue.number }}.
|
|
53
|
-
/hopla
|
|
54
|
-
/hopla
|
|
55
|
-
/hopla
|
|
53
|
+
/hopla:plan-feature based on the issue requirements.
|
|
54
|
+
/hopla:execute the plan.
|
|
55
|
+
/hopla:validate
|
|
56
56
|
Create a PR with the results.
|
|
57
57
|
"
|
|
58
58
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Guide: Creating a Project-Specific Review Checklist
|
|
2
2
|
|
|
3
|
-
Use this guide to create a `.agents/guides/review-checklist.md` file in your project with code review checks specific to your tech stack, domain, and known anti-patterns. The
|
|
3
|
+
Use this guide to create a `.agents/guides/review-checklist.md` file in your project with code review checks specific to your tech stack, domain, and known anti-patterns. The the `code-review` skill command loads this file automatically when it exists, applying your custom checks alongside the standard review categories.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -9,8 +9,8 @@ Use this guide to create a `.agents/guides/review-checklist.md` file in your pro
|
|
|
9
9
|
Create a review checklist when:
|
|
10
10
|
- The same bug pattern appears in **2+ code reviews** (e.g., stale closures in grid callbacks)
|
|
11
11
|
- Your project uses a framework with non-obvious gotchas (AG Grid, Hono, Prisma, D3, etc.)
|
|
12
|
-
- A `/hopla
|
|
13
|
-
- A
|
|
12
|
+
- A `/hopla:system-review` flags a recurring issue that should be caught during code review
|
|
13
|
+
- A the `execution-report` skill documents a new technical pattern in its "Technical Patterns Discovered" section
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
@@ -67,8 +67,8 @@ Patterns that have caused bugs in this project before:
|
|
|
67
67
|
## Maintenance
|
|
68
68
|
|
|
69
69
|
Update this file when:
|
|
70
|
-
- `/hopla
|
|
71
|
-
-
|
|
70
|
+
- `/hopla:system-review` flags a recurring bug pattern (3+ occurrences across reviews)
|
|
71
|
+
- the `execution-report` skill discovers a new technical pattern in "Technical Patterns Discovered"
|
|
72
72
|
- A code review finds a bug that should have been caught by a checklist item
|
|
73
73
|
- A framework is upgraded and known gotchas change
|
|
74
74
|
|
|
@@ -10,21 +10,18 @@ According to Anthropic's 2026 Agentic Coding Trends Report:
|
|
|
10
10
|
- The barrier between "people who code" and "people who don't" is becoming permeable
|
|
11
11
|
- Domain experts implementing solutions directly removes bottlenecks
|
|
12
12
|
|
|
13
|
-
## HOPLA
|
|
13
|
+
## HOPLA for Non-Technical Users
|
|
14
14
|
|
|
15
|
-
HOPLA
|
|
16
|
-
- Restricted command set (planning and review only)
|
|
17
|
-
- Limited git permissions (read-only)
|
|
18
|
-
- Focus on product decisions, not implementation
|
|
15
|
+
Non-technical users can adopt HOPLA today by installing the plugin and focusing on product-planning commands. The 4D Framework guide (`/hopla:guide`) walks them through Description → Discernment → Delegation → Diligence without requiring them to write or review code directly.
|
|
19
16
|
|
|
20
17
|
## Expanding the Model
|
|
21
18
|
|
|
22
19
|
### Phase 1: Product Planning (Current)
|
|
23
20
|
Non-technical users can:
|
|
24
|
-
- Create PRDs with `/hopla
|
|
25
|
-
- Plan features with `/hopla
|
|
26
|
-
- Review plans with `/hopla
|
|
27
|
-
- Guide workflow with `/hopla
|
|
21
|
+
- Create PRDs with `/hopla:create-prd`
|
|
22
|
+
- Plan features with `/hopla:plan-feature`
|
|
23
|
+
- Review plans with `/hopla:review-plan`
|
|
24
|
+
- Guide workflow with `/hopla:guide` (4D Framework)
|
|
28
25
|
|
|
29
26
|
### Phase 2: Assisted Creation (Future)
|
|
30
27
|
Non-technical users could:
|
package/commands/init-project.md
CHANGED
|
@@ -427,15 +427,15 @@ Create the following directories (with `.gitkeep` where needed):
|
|
|
427
427
|
|
|
428
428
|
```
|
|
429
429
|
.agents/
|
|
430
|
-
├── plans/ <- /hopla
|
|
431
|
-
│ ├── done/ <- /hopla
|
|
432
|
-
│ └── backlog/ <- /hopla
|
|
430
|
+
├── plans/ <- /hopla:plan-feature saves here (commit)
|
|
431
|
+
│ ├── done/ <- /hopla:system-review archives completed plans here (commit)
|
|
432
|
+
│ └── backlog/ <- /hopla:execute Scope Guard defers ideas here (commit)
|
|
433
433
|
├── specs/ <- brainstorm skill saves design docs here (commit)
|
|
434
434
|
├── guides/ <- on-demand reference guides (commit)
|
|
435
|
-
├── rca/ <- /hopla
|
|
436
|
-
├── execution-reports/ <-
|
|
437
|
-
├── system-reviews/ <- /hopla
|
|
438
|
-
└── code-reviews/ <-
|
|
435
|
+
├── rca/ <- /hopla:rca saves root cause analysis docs here (commit)
|
|
436
|
+
├── execution-reports/ <- the `execution-report` skill saves here (commit — needed for cross-session learning)
|
|
437
|
+
├── system-reviews/ <- /hopla:system-review saves here (commit — needed for feedback loop)
|
|
438
|
+
└── code-reviews/ <- the `code-review` skill saves here (do NOT commit — ephemeral, consumed by code-review-fix)
|
|
439
439
|
```
|
|
440
440
|
|
|
441
441
|
Add to `.gitignore` (create if it doesn't exist):
|
|
@@ -476,6 +476,6 @@ Once confirmed:
|
|
|
476
476
|
1. Save `CLAUDE.md` to the project root
|
|
477
477
|
2. Create `.agents/` directory structure
|
|
478
478
|
3. Update `.gitignore`
|
|
479
|
-
4. If no PRD exists yet, tell the user: "Project initialized. Run `/hopla
|
|
480
|
-
If a PRD already exists, tell the user: "Project initialized. Run `/hopla
|
|
481
|
-
5. Suggest running
|
|
479
|
+
4. If no PRD exists yet, tell the user: "Project initialized. Run `/hopla:create-prd` next to define the product scope, or `/hopla:plan-feature` to start planning a feature."
|
|
480
|
+
If a PRD already exists, tell the user: "Project initialized. Run `/hopla:plan-feature` to start planning the first feature."
|
|
481
|
+
5. Suggest running the `git` skill (say "commit") to save everything
|
package/commands/plan-feature.md
CHANGED
|
@@ -170,7 +170,7 @@ Run in this order — do not proceed if a level fails:
|
|
|
170
170
|
|
|
171
171
|
- [ ] **Level 1 — Lint & Format:** `[project lint command]`
|
|
172
172
|
- [ ] **Level 2 — Type Check:** `[project type check command]`
|
|
173
|
-
- [ ] **Level 2.5 — Code Review:** Run
|
|
173
|
+
- [ ] **Level 2.5 — Code Review:** Run the `code-review` skill on changed files
|
|
174
174
|
- [ ] **Level 3 — Unit Tests:** `[project unit test command]`
|
|
175
175
|
- [ ] **Level 4 — Integration Tests:** `[project integration test or manual curl/check]`
|
|
176
176
|
- [ ] **Level 5 — Human Review:** Verify behavior matches requirements above
|
|
@@ -260,4 +260,4 @@ Before saving the draft, review the plan against these criteria:
|
|
|
260
260
|
|
|
261
261
|
**Finalize:**
|
|
262
262
|
1. Rename `.agents/plans/[feature-name].draft.md` → `.agents/plans/[feature-name].md` (overwrite if it already exists)
|
|
263
|
-
2. Confirm: "✅ Plan saved to `.agents/plans/[feature-name].md`. Run `/hopla
|
|
263
|
+
2. Confirm: "✅ Plan saved to `.agents/plans/[feature-name].md`. Run `/hopla:review-plan .agents/plans/[feature-name].md` to review it, then `/hopla:execute .agents/plans/[feature-name].md` to implement it."
|
package/commands/rca.md
CHANGED
|
@@ -60,9 +60,9 @@ What needs to change to resolve this
|
|
|
60
60
|
How to prevent similar issues in the future
|
|
61
61
|
|
|
62
62
|
## Next Steps
|
|
63
|
-
- [ ] Implement fix (run `/hopla
|
|
63
|
+
- [ ] Implement fix (run `/hopla:execute` with a plan, or fix directly if simple)
|
|
64
64
|
- [ ] Add regression test
|
|
65
|
-
- [ ] Validate with `/hopla
|
|
65
|
+
- [ ] Validate with `/hopla:validate`
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
## Output
|
package/commands/review-plan.md
CHANGED
|
@@ -48,5 +48,5 @@ After the summary, ask (in the user's language):
|
|
|
48
48
|
|
|
49
49
|
**Review loop:**
|
|
50
50
|
- If the user has questions → answer them based on the plan content
|
|
51
|
-
- If the user requests changes → note them and
|
|
52
|
-
- If the user approves → confirm: "✅ Plan approved. Run `/hopla
|
|
51
|
+
- If the user requests changes → note them and suggest re-running `/hopla:plan-feature` to update the plan, or apply minor clarifications directly if they are unambiguous
|
|
52
|
+
- If the user approves → confirm: "✅ Plan approved. Run `/hopla:execute $1` to start."
|
package/commands/validate.md
CHANGED
|
@@ -66,10 +66,10 @@ If anything failed and could not be fixed, list the remaining issues and suggest
|
|
|
66
66
|
|
|
67
67
|
## After Validation Passes
|
|
68
68
|
|
|
69
|
-
- Suggest running
|
|
69
|
+
- Suggest running the `code-review` skill if not already done
|
|
70
70
|
- Remind that completion claims must be backed by this fresh validation evidence (see hopla-verify skill)
|
|
71
71
|
|
|
72
72
|
## Next Step
|
|
73
73
|
|
|
74
74
|
After validation passes, suggest:
|
|
75
|
-
> "All validation levels passed. Consider running
|
|
75
|
+
> "All validation levels passed. Consider running the `code-review` skill for a deeper analysis — code review catches bugs in 79% of implementations that pass automated validation (stale closures, missing input validation, route shadowing, unhandled promise rejections). Run the `code-review` skill to check, or the `git` skill (say "commit") to commit directly."
|
package/global-rules.md
CHANGED
|
@@ -85,11 +85,21 @@ When suggesting a commit, explain in plain language why it's a good moment, adap
|
|
|
85
85
|
---
|
|
86
86
|
|
|
87
87
|
## 🔌 MCP Servers
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
|
|
89
|
+
Declare MCP servers in your project's `.mcp.json` so Claude Code picks them up automatically. Copy the starter template from the plugin:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Inside your project root
|
|
93
|
+
cp ~/.claude/plugins/marketplaces/hopla-marketplace/.claude-plugin/.mcp.json.example .mcp.json
|
|
94
|
+
# Then edit — uncomment the servers you need, set env vars in your shell
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
List the servers you actually enabled here so the agent knows what tools are available, e.g.:
|
|
98
|
+
- Playwright — browser automation for E2E testing and UI inspection
|
|
99
|
+
- GitHub — PR/issue access (read and write depending on token scope)
|
|
100
|
+
- Linear — workspace tickets, cycles, projects
|
|
101
|
+
|
|
102
|
+
When planning features, explicitly include MCP integration points in the plan.
|
|
93
103
|
|
|
94
104
|
---
|
|
95
105
|
|
package/hooks/env-protect.js
CHANGED
|
@@ -1,19 +1,50 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// PreToolUse hook: blocks reads/greps
|
|
2
|
+
// PreToolUse hook: blocks reads/greps/Bash commands that expose .env secrets.
|
|
3
|
+
// Hooks.json matcher must include Bash so Bash calls reach this script.
|
|
4
|
+
|
|
5
|
+
function isEnvPath(p) {
|
|
6
|
+
if (typeof p !== "string" || !p) return false;
|
|
7
|
+
// Matches: .env, ./.env, path/.env, .env.local, .env.production, path/.env.X
|
|
8
|
+
return /(^|\/)\.env(\.\w+)?$/.test(p);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function commandReadsEnv(cmd) {
|
|
12
|
+
if (typeof cmd !== "string" || !cmd) return false;
|
|
13
|
+
// Split on shell word separators so we inspect each argument/path token
|
|
14
|
+
const tokens = cmd.split(/[\s<>|&;"'`()]+/);
|
|
15
|
+
return tokens.some(isEnvPath);
|
|
16
|
+
}
|
|
3
17
|
|
|
4
18
|
async function main() {
|
|
5
19
|
const chunks = [];
|
|
6
|
-
for await (const chunk of process.stdin)
|
|
7
|
-
|
|
20
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
21
|
+
|
|
22
|
+
let toolCall;
|
|
23
|
+
try {
|
|
24
|
+
toolCall = JSON.parse(Buffer.concat(chunks).toString());
|
|
25
|
+
} catch {
|
|
26
|
+
// Malformed input — fail open so we never block legitimate tool use
|
|
27
|
+
process.exit(0);
|
|
8
28
|
}
|
|
9
29
|
|
|
10
|
-
const
|
|
11
|
-
const
|
|
30
|
+
const name = toolCall.tool_name || "";
|
|
31
|
+
const input = toolCall.tool_input || {};
|
|
32
|
+
|
|
33
|
+
// Read / Grep / Glob / Edit / Write — check file_path or path
|
|
34
|
+
const filePath = input.file_path || input.path || "";
|
|
35
|
+
if (isEnvPath(filePath)) {
|
|
36
|
+
process.stderr.write(
|
|
37
|
+
`Access denied: reading or editing .env files is blocked to prevent accidental secret exposure. ` +
|
|
38
|
+
`If you need env var names, check the README or ask the user.\n`
|
|
39
|
+
);
|
|
40
|
+
process.exit(2);
|
|
41
|
+
}
|
|
12
42
|
|
|
13
|
-
|
|
43
|
+
// Bash — inspect the command string for tokens that read an .env file
|
|
44
|
+
if (name === "Bash" && commandReadsEnv(input.command)) {
|
|
14
45
|
process.stderr.write(
|
|
15
|
-
`Access denied:
|
|
16
|
-
`If you need
|
|
46
|
+
`Access denied: this Bash command reads a .env file, which is blocked to prevent secret exposure. ` +
|
|
47
|
+
`If you need env var names, ask the user.\n`
|
|
17
48
|
);
|
|
18
49
|
process.exit(2);
|
|
19
50
|
}
|
package/hooks/hooks.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"PreToolUse": [
|
|
16
16
|
{
|
|
17
|
-
"matcher": "Read|Grep",
|
|
17
|
+
"matcher": "Read|Grep|Glob|Edit|Write|Bash",
|
|
18
18
|
"hooks": [
|
|
19
19
|
{
|
|
20
20
|
"type": "command",
|
|
@@ -35,6 +35,28 @@
|
|
|
35
35
|
}
|
|
36
36
|
]
|
|
37
37
|
}
|
|
38
|
+
],
|
|
39
|
+
"UserPromptSubmit": [
|
|
40
|
+
{
|
|
41
|
+
"hooks": [
|
|
42
|
+
{
|
|
43
|
+
"type": "command",
|
|
44
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/prompt-route.js\"",
|
|
45
|
+
"async": false
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"PreCompact": [
|
|
51
|
+
{
|
|
52
|
+
"hooks": [
|
|
53
|
+
{
|
|
54
|
+
"type": "command",
|
|
55
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/precompact-snapshot.js\"",
|
|
56
|
+
"async": false
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
38
60
|
]
|
|
39
61
|
}
|
|
40
62
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PreCompact hook: snapshot the session's work state so it survives /compact.
|
|
3
|
+
// The SessionStart hook (session-prime.js) re-injects this when it exists and is recent.
|
|
4
|
+
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
|
|
9
|
+
function run(cmd) {
|
|
10
|
+
try {
|
|
11
|
+
return execSync(cmd, { cwd: process.cwd(), stdio: "pipe" }).toString().trim();
|
|
12
|
+
} catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function findActivePlan() {
|
|
18
|
+
const plansDir = path.join(process.cwd(), ".agents", "plans");
|
|
19
|
+
if (!fs.existsSync(plansDir)) return null;
|
|
20
|
+
try {
|
|
21
|
+
const files = fs
|
|
22
|
+
.readdirSync(plansDir)
|
|
23
|
+
.filter((f) => f.endsWith(".md") && !f.startsWith("."))
|
|
24
|
+
.map((f) => ({ name: f, mtime: fs.statSync(path.join(plansDir, f)).mtimeMs }))
|
|
25
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
26
|
+
return files[0]?.name || null;
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function detectWorktree() {
|
|
33
|
+
const gitDir = run("git rev-parse --git-dir");
|
|
34
|
+
const commonDir = run("git rev-parse --git-common-dir");
|
|
35
|
+
if (!gitDir || !commonDir) return false;
|
|
36
|
+
return path.resolve(gitDir) !== path.resolve(commonDir);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function main() {
|
|
40
|
+
// Drain stdin (hook contract)
|
|
41
|
+
const chunks = [];
|
|
42
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
43
|
+
|
|
44
|
+
const snapshot = {
|
|
45
|
+
timestamp: new Date().toISOString(),
|
|
46
|
+
branch: run("git branch --show-current"),
|
|
47
|
+
uncommitted: run("git status --short"),
|
|
48
|
+
activePlan: findActivePlan(),
|
|
49
|
+
inWorktree: detectWorktree(),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const targetDir = path.join(process.cwd(), ".claude");
|
|
53
|
+
try {
|
|
54
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
55
|
+
fs.writeFileSync(
|
|
56
|
+
path.join(targetDir, "compact-snapshot.json"),
|
|
57
|
+
JSON.stringify(snapshot, null, 2) + "\n"
|
|
58
|
+
);
|
|
59
|
+
} catch {
|
|
60
|
+
// Best-effort — never block /compact
|
|
61
|
+
}
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
main();
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// UserPromptSubmit hook: scan the user's prompt for skill keywords and inject
|
|
3
|
+
// a short routing hint. Keeps skill suggestions visible mid-session even after
|
|
4
|
+
// compaction or long conversations where the initial skill list gets buried.
|
|
5
|
+
|
|
6
|
+
const SKILL_TRIGGERS = [
|
|
7
|
+
{
|
|
8
|
+
skill: "git",
|
|
9
|
+
patterns: [
|
|
10
|
+
/\bcommit\b/i,
|
|
11
|
+
/save (my |the )?changes/i,
|
|
12
|
+
/\bcreate (a )?pr\b/i,
|
|
13
|
+
/pull request/i,
|
|
14
|
+
/\bpush\b/i,
|
|
15
|
+
/merge request/i,
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
skill: "worktree",
|
|
20
|
+
patterns: [
|
|
21
|
+
/\bworktree\b/i,
|
|
22
|
+
/isolated branch/i,
|
|
23
|
+
/parallel (feature|development)/i,
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
skill: "prime",
|
|
28
|
+
patterns: [
|
|
29
|
+
/\borient(\b| yourself)/i,
|
|
30
|
+
/catch me up/i,
|
|
31
|
+
/get context/i,
|
|
32
|
+
/load project/i,
|
|
33
|
+
/what is this project/i,
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
skill: "brainstorm",
|
|
38
|
+
patterns: [
|
|
39
|
+
/\bbrainstorm\b/i,
|
|
40
|
+
/explore (options|approaches)/i,
|
|
41
|
+
/how should we/i,
|
|
42
|
+
/trade[- ]offs?/i,
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
skill: "debug",
|
|
47
|
+
patterns: [
|
|
48
|
+
/\bbug\b/i,
|
|
49
|
+
/\berror\b/i,
|
|
50
|
+
/\bdebug\b/i,
|
|
51
|
+
/not working/i,
|
|
52
|
+
/\bfailing\b/i,
|
|
53
|
+
/\bbroken\b/i,
|
|
54
|
+
/\bno funciona\b/i,
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
skill: "verify",
|
|
59
|
+
patterns: [
|
|
60
|
+
/\bverify\b/i,
|
|
61
|
+
/all tests? pass/i,
|
|
62
|
+
/\blisto\b/i,
|
|
63
|
+
/\bterminé\b/i,
|
|
64
|
+
/\bya está\b/i,
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
skill: "code-review",
|
|
69
|
+
patterns: [
|
|
70
|
+
/review (the |my )?code/i,
|
|
71
|
+
/code review/i,
|
|
72
|
+
/audit (the |my )?code/i,
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
skill: "execution-report",
|
|
77
|
+
patterns: [
|
|
78
|
+
/generate (the |a )?report/i,
|
|
79
|
+
/document what was done/i,
|
|
80
|
+
/execution report/i,
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
skill: "tdd",
|
|
85
|
+
patterns: [
|
|
86
|
+
/\btdd\b/i,
|
|
87
|
+
/test[- ]first/i,
|
|
88
|
+
/red[- ]green[- ]refactor/i,
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
async function main() {
|
|
94
|
+
const chunks = [];
|
|
95
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
96
|
+
|
|
97
|
+
let input;
|
|
98
|
+
try {
|
|
99
|
+
input = JSON.parse(Buffer.concat(chunks).toString());
|
|
100
|
+
} catch {
|
|
101
|
+
// Malformed payload — skip silently so we never block legitimate prompts
|
|
102
|
+
process.exit(0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Cap prompt length so regex matching stays cheap on large paste-ins
|
|
106
|
+
const prompt = (input.prompt || "").slice(0, 4000);
|
|
107
|
+
if (!prompt) process.exit(0);
|
|
108
|
+
|
|
109
|
+
const matched = [];
|
|
110
|
+
for (const { skill, patterns } of SKILL_TRIGGERS) {
|
|
111
|
+
if (patterns.some((p) => p.test(prompt))) matched.push(skill);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (matched.length === 0) process.exit(0);
|
|
115
|
+
|
|
116
|
+
const list = matched.map((s) => `\`${s}\``).join(", ");
|
|
117
|
+
const plural = matched.length > 1;
|
|
118
|
+
process.stdout.write(
|
|
119
|
+
`📦 HOPLA routing hint: this prompt matches skill${plural ? "s" : ""} ${list}. ` +
|
|
120
|
+
`Use ${plural ? "them" : "it"} if applicable to the current task.`
|
|
121
|
+
);
|
|
122
|
+
process.exit(0);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
main();
|
package/hooks/session-prime.js
CHANGED
|
@@ -65,6 +65,26 @@ async function main() {
|
|
|
65
65
|
lines.push("Working tree is clean.");
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// Re-inject pre-compact snapshot if recent (< 2 hours old)
|
|
69
|
+
const snapshotPath = path.join(process.cwd(), ".claude", "compact-snapshot.json");
|
|
70
|
+
if (fs.existsSync(snapshotPath)) {
|
|
71
|
+
try {
|
|
72
|
+
const snap = JSON.parse(fs.readFileSync(snapshotPath, "utf8"));
|
|
73
|
+
const ageMs = Date.now() - Date.parse(snap.timestamp);
|
|
74
|
+
if (Number.isFinite(ageMs) && ageMs < 2 * 60 * 60 * 1000) {
|
|
75
|
+
const parts = [
|
|
76
|
+
`Resuming from pre-compact snapshot (${Math.round(ageMs / 60000)} min ago):`,
|
|
77
|
+
];
|
|
78
|
+
if (snap.branch) parts.push(`- branch: ${snap.branch}${snap.inWorktree ? " (worktree)" : ""}`);
|
|
79
|
+
if (snap.activePlan) parts.push(`- active plan: .agents/plans/${snap.activePlan}`);
|
|
80
|
+
if (snap.uncommitted) parts.push(`- uncommitted at snapshot:\n${snap.uncommitted}`);
|
|
81
|
+
lines.push(parts.join("\n"));
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
// Ignore malformed snapshot
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
68
88
|
// CLAUDE.md summary (first 20 lines)
|
|
69
89
|
const claudeMdPath = path.join(process.cwd(), "CLAUDE.md");
|
|
70
90
|
if (fs.existsSync(claudeMdPath)) {
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Hopla statusline: branch · worktree indicator · uncommitted count · active plan.
|
|
3
|
+
// Wire it up by adding to ~/.claude/settings.json:
|
|
4
|
+
// "statusLine": {
|
|
5
|
+
// "type": "command",
|
|
6
|
+
// "command": "node ~/.claude/plugins/marketplaces/hopla-marketplace/hooks/statusline.js"
|
|
7
|
+
// }
|
|
8
|
+
|
|
9
|
+
import { execSync } from "child_process";
|
|
10
|
+
import fs from "fs";
|
|
11
|
+
import path from "path";
|
|
12
|
+
|
|
13
|
+
const CYAN = "\x1b[36m";
|
|
14
|
+
const YELLOW = "\x1b[33m";
|
|
15
|
+
const MAGENTA = "\x1b[35m";
|
|
16
|
+
const DIM = "\x1b[2m";
|
|
17
|
+
const RESET = "\x1b[0m";
|
|
18
|
+
|
|
19
|
+
function run(cmd, cwd) {
|
|
20
|
+
try {
|
|
21
|
+
return execSync(cmd, { cwd, stdio: "pipe" }).toString().trim();
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function findActivePlan(cwd) {
|
|
28
|
+
const plansDir = path.join(cwd, ".agents", "plans");
|
|
29
|
+
if (!fs.existsSync(plansDir)) return null;
|
|
30
|
+
try {
|
|
31
|
+
const files = fs
|
|
32
|
+
.readdirSync(plansDir)
|
|
33
|
+
.filter((f) => f.endsWith(".md") && !f.startsWith("."))
|
|
34
|
+
.map((f) => ({ name: f, mtime: fs.statSync(path.join(plansDir, f)).mtimeMs }))
|
|
35
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
36
|
+
return files[0]?.name.replace(/\.md$/, "") || null;
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function main() {
|
|
43
|
+
const chunks = [];
|
|
44
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
45
|
+
|
|
46
|
+
let input = {};
|
|
47
|
+
try {
|
|
48
|
+
input = JSON.parse(Buffer.concat(chunks).toString());
|
|
49
|
+
} catch {
|
|
50
|
+
// Malformed payload — render nothing
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const cwd = input.workspace?.current_dir || input.cwd || process.cwd();
|
|
55
|
+
const parts = [];
|
|
56
|
+
|
|
57
|
+
const branch = run("git branch --show-current", cwd);
|
|
58
|
+
if (branch) {
|
|
59
|
+
const gitDir = run("git rev-parse --git-dir", cwd);
|
|
60
|
+
const commonDir = run("git rev-parse --git-common-dir", cwd);
|
|
61
|
+
const isWorktree =
|
|
62
|
+
gitDir && commonDir && path.resolve(cwd, gitDir) !== path.resolve(cwd, commonDir);
|
|
63
|
+
parts.push(`${CYAN}${isWorktree ? "⎇ " : " "}${branch}${RESET}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const status = run("git status --short", cwd);
|
|
67
|
+
if (status) {
|
|
68
|
+
const count = status.split("\n").length;
|
|
69
|
+
parts.push(`${YELLOW}${count}M${RESET}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const plan = findActivePlan(cwd);
|
|
73
|
+
if (plan) {
|
|
74
|
+
parts.push(`${MAGENTA}📋 ${plan}${RESET}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (parts.length === 0) process.exit(0);
|
|
78
|
+
|
|
79
|
+
process.stdout.write(parts.join(` ${DIM}·${RESET} `));
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
main();
|
package/hooks/tsc-check.js
CHANGED
|
@@ -1,33 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// PostToolUse hook: runs tsc --noEmit after file edits and feeds errors back to Claude
|
|
2
|
+
// PostToolUse hook: runs tsc --noEmit after file edits and feeds errors back to Claude.
|
|
3
|
+
// Prefers the project-local tsc (node_modules/.bin/tsc) over a global install so
|
|
4
|
+
// the hook reports real results even when the user does not have tsc on PATH.
|
|
3
5
|
|
|
4
6
|
import { execSync } from "child_process";
|
|
5
7
|
import fs from "fs";
|
|
6
8
|
import path from "path";
|
|
7
9
|
|
|
10
|
+
function resolveTscCommand(cwd) {
|
|
11
|
+
const localBin = path.join(cwd, "node_modules", ".bin", "tsc");
|
|
12
|
+
if (fs.existsSync(localBin)) return `"${localBin}"`;
|
|
13
|
+
// Fall back to npx --no-install so we never trigger a network install;
|
|
14
|
+
// if tsc is not available anywhere, npx exits non-zero with a clear error.
|
|
15
|
+
return "npx --no-install tsc";
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
async function main() {
|
|
19
|
+
// Drain stdin (hook contract) but we don't need the payload for tsc --noEmit
|
|
9
20
|
const chunks = [];
|
|
10
|
-
for await (const chunk of process.stdin)
|
|
11
|
-
chunks.push(chunk);
|
|
12
|
-
}
|
|
21
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
13
22
|
|
|
14
|
-
|
|
15
|
-
const tsconfigPath = path.join(
|
|
23
|
+
const cwd = process.cwd();
|
|
24
|
+
const tsconfigPath = path.join(cwd, "tsconfig.json");
|
|
16
25
|
if (!fs.existsSync(tsconfigPath)) {
|
|
26
|
+
// Not a TypeScript project — skip silently
|
|
17
27
|
process.exit(0);
|
|
18
28
|
}
|
|
19
29
|
|
|
20
|
-
|
|
30
|
+
const tsc = resolveTscCommand(cwd);
|
|
31
|
+
|
|
21
32
|
try {
|
|
22
|
-
execSync(
|
|
23
|
-
//
|
|
33
|
+
execSync(`${tsc} --noEmit`, { cwd, stdio: "pipe" });
|
|
34
|
+
// Compile clean — exit silently
|
|
24
35
|
process.exit(0);
|
|
25
36
|
} catch (err) {
|
|
26
37
|
const output = (err.stdout || "").toString() + (err.stderr || "").toString();
|
|
27
38
|
if (output.trim()) {
|
|
28
39
|
process.stdout.write("TypeScript errors detected:\n" + output + "\n");
|
|
29
40
|
}
|
|
30
|
-
//
|
|
41
|
+
// PostToolUse hooks cannot block; stdout is fed back to Claude
|
|
31
42
|
process.exit(0);
|
|
32
43
|
}
|
|
33
44
|
}
|
package/package.json
CHANGED
|
@@ -72,14 +72,14 @@ Conceptual design details
|
|
|
72
72
|
- Anything still unclear
|
|
73
73
|
|
|
74
74
|
## Next Step
|
|
75
|
-
Run `/hopla
|
|
75
|
+
Run `/hopla:plan-feature` to create the implementation plan from this design
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
### Step 6: Review Loop
|
|
79
79
|
Present the design document for user review.
|
|
80
80
|
- Accept feedback using the `<? ... >` comment syntax
|
|
81
81
|
- Iterate until the user approves
|
|
82
|
-
- Only then suggest: "Design approved! Ready to create the plan with `/hopla
|
|
82
|
+
- Only then suggest: "Design approved! Ready to create the plan with `/hopla:plan-feature`?"
|
|
83
83
|
|
|
84
84
|
## Rules
|
|
85
85
|
- Never skip to planning without design approval
|
|
@@ -90,5 +90,5 @@ Present the design document for user review.
|
|
|
90
90
|
|
|
91
91
|
## Integration
|
|
92
92
|
|
|
93
|
-
- If the user hasn't defined requirements yet, suggest: "Before brainstorming, consider running `/hopla
|
|
93
|
+
- If the user hasn't defined requirements yet, suggest: "Before brainstorming, consider running `/hopla:create-prd` to define the product requirements. This gives us clearer constraints to design against."
|
|
94
94
|
- If the user is brainstorming a bug fix rather than a new feature, suggest: "This sounds like a bug rather than a new feature. Consider running the `debug` skill for systematic root cause analysis instead."
|
|
@@ -96,4 +96,4 @@ If no issues found: "Code review passed. No technical issues detected."
|
|
|
96
96
|
## Next Step
|
|
97
97
|
|
|
98
98
|
After the review, suggest:
|
|
99
|
-
> "Code review saved to `.agents/code-reviews/[name].md`. If issues were found, run `/hopla
|
|
99
|
+
> "Code review saved to `.agents/code-reviews/[name].md`. If issues were found, run `/hopla:code-review-fix .agents/code-reviews/[name].md` to fix them. If the review passed clean, proceed to the `execution-report` skill."
|
package/skills/debug/SKILL.md
CHANGED
|
@@ -75,7 +75,7 @@ When the bug is fixed, briefly report:
|
|
|
75
75
|
## Escalation
|
|
76
76
|
|
|
77
77
|
If the 3-Strike Rule activates (3 fixes failed), suggest:
|
|
78
|
-
> "This bug may need deeper investigation. Run `/hopla
|
|
78
|
+
> "This bug may need deeper investigation. Run `/hopla:rca` to produce a structured Root Cause Analysis document with evidence, proposed fix, and prevention steps."
|
|
79
79
|
|
|
80
80
|
If the bug is fixed, suggest:
|
|
81
|
-
> "Bug fixed. Run `/hopla
|
|
81
|
+
> "Bug fixed. Run `/hopla:validate` to verify no regressions, then the `git` skill (say "commit") to save the fix."
|
|
@@ -115,4 +115,4 @@ Based on this implementation, what should change for next time?
|
|
|
115
115
|
## Next Step
|
|
116
116
|
|
|
117
117
|
After the report is saved, suggest:
|
|
118
|
-
> "Execution report saved to `.agents/execution-reports/[name].md`. Run
|
|
118
|
+
> "Execution report saved to `.agents/execution-reports/[name].md`. Run the `git` skill (say "commit") to commit your changes."
|
package/skills/git/commit.md
CHANGED
|
@@ -73,4 +73,4 @@ After committing, remind the user:
|
|
|
73
73
|
**Never push automatically** — wait for explicit confirmation.
|
|
74
74
|
|
|
75
75
|
If the user confirms the push (or if the branch was already pushed), suggest:
|
|
76
|
-
> "Ready to create a Pull Request? Run
|
|
76
|
+
> "Ready to create a Pull Request? Run the `git` skill (say "create PR") to create one."
|
package/skills/git/pr.md
CHANGED
|
@@ -90,7 +90,7 @@ After creating, show the PR URL to the user.
|
|
|
90
90
|
**Never merge automatically** — the PR is for human review.
|
|
91
91
|
|
|
92
92
|
After showing the PR URL, suggest:
|
|
93
|
-
> "PR created. To complete the cycle, run
|
|
93
|
+
> "PR created. To complete the cycle, run the `execution-report` skill (if not done yet) and `/hopla:system-review` after the PR is merged."
|
|
94
94
|
|
|
95
95
|
## Step 7: Post-Merge Cleanup
|
|
96
96
|
|
package/skills/prime/SKILL.md
CHANGED
|
@@ -54,7 +54,7 @@ If there are pending plans, list them clearly after the prose summary:
|
|
|
54
54
|
```
|
|
55
55
|
Pending plans:
|
|
56
56
|
- inventory-page.draft.md ← draft, not finalized yet
|
|
57
|
-
- add-user-authentication.md ← ready to execute with /hopla
|
|
57
|
+
- add-user-authentication.md ← ready to execute with /hopla:execute
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
End with a sentence like: "All caught up — what are we working on today?"
|
|
@@ -63,7 +63,7 @@ Report your status as DONE, DONE_WITH_CONCERNS, NEEDS_CONTEXT, or BLOCKED.
|
|
|
63
63
|
- Commit at phase boundaries (every 3-5 tasks)
|
|
64
64
|
- Always validate before committing
|
|
65
65
|
|
|
66
|
-
## Integration with /hopla
|
|
66
|
+
## Integration with /hopla:execute
|
|
67
67
|
This skill is an ALTERNATIVE to inline execution. Suggest it when:
|
|
68
68
|
- The plan has 5+ tasks
|
|
69
69
|
- The user expresses concern about quality in long sessions
|
package/skills/tdd/SKILL.md
CHANGED
|
@@ -44,7 +44,7 @@ description: "Test-driven development workflow using the RED-GREEN-REFACTOR cycl
|
|
|
44
44
|
- Boilerplate with no logic
|
|
45
45
|
- Legacy code without existing test infrastructure
|
|
46
46
|
|
|
47
|
-
## Integration with /hopla
|
|
47
|
+
## Integration with /hopla:execute
|
|
48
48
|
|
|
49
49
|
When executing a plan with TDD:
|
|
50
50
|
1. For each implementation task that has associated tests:
|
package/skills/verify/SKILL.md
CHANGED
|
@@ -55,7 +55,7 @@ When completing a feature (not just a single file edit), run the full validation
|
|
|
55
55
|
4. **Level 4**: Integration tests (if applicable)
|
|
56
56
|
5. **Level 5**: Human review suggestion
|
|
57
57
|
|
|
58
|
-
Reference `/hopla
|
|
58
|
+
Reference `/hopla:validate` for project-specific validation commands.
|
|
59
59
|
|
|
60
60
|
## Scope
|
|
61
61
|
|
package/skills/worktree/SKILL.md
CHANGED
|
@@ -113,6 +113,6 @@ git branch -D <prefix>/<name>
|
|
|
113
113
|
|
|
114
114
|
## Integration
|
|
115
115
|
|
|
116
|
-
- Combine with `/hopla
|
|
116
|
+
- Combine with `/hopla:execute` — run execution from inside the worktree
|
|
117
117
|
- Combine with the `git` skill — commit and PR from inside the worktree; cleanup happens post-merge
|
|
118
118
|
- Combine with parallel dispatch — multiple worktrees active simultaneously
|