From b633ae81f6757bd34d2d4994ee391c015a0ba266 Mon Sep 17 00:00:00 2001 From: Snider Date: Sun, 1 Feb 2026 19:48:51 +0000 Subject: [PATCH] feat: add README and flesh out all plugins README.md: - GitHub-friendly documentation - Installation instructions - Plugin overview with commands review plugin: - /review:security - Security-focused review - /review:pr - PR review - hooks.json - Post PR create suggestion - scripts/post-pr-create.sh verify plugin: - /verify:ready - Quick readiness check - /verify:tests - Test verification - hooks.json - Pre-push warning - scripts/pre-push-check.sh qa plugin: - /qa:check - Report only, no fixes - /qa:lint - Lint with fix option - hooks.json - QA output filtering ci plugin: - /ci:status - CI status display - /ci:run - Trigger workflows - /ci:fix - Analyse and fix failures - hooks.json - Post-push CI hint - scripts/post-push-ci.sh Co-Authored-By: Claude Opus 4.5 --- README.md | 119 ++++++++++++++++++++++++ claude/ci/commands/fix.md | 97 +++++++++++++++++++ claude/ci/commands/run.md | 76 +++++++++++++++ claude/ci/commands/status.md | 63 +++++++++++++ claude/ci/hooks.json | 17 ++++ claude/ci/scripts/post-push-ci.sh | 23 +++++ claude/qa/commands/check.md | 74 +++++++++++++++ claude/qa/commands/lint.md | 78 ++++++++++++++++ claude/qa/hooks.json | 17 ++++ claude/review/commands/pr.md | 87 +++++++++++++++++ claude/review/commands/security.md | 93 ++++++++++++++++++ claude/review/hooks.json | 17 ++++ claude/review/scripts/post-pr-create.sh | 22 +++++ claude/verify/commands/ready.md | 53 +++++++++++ claude/verify/commands/tests.md | 80 ++++++++++++++++ claude/verify/hooks.json | 17 ++++ claude/verify/scripts/pre-push-check.sh | 21 +++++ 17 files changed, 954 insertions(+) create mode 100644 README.md create mode 100644 claude/ci/commands/fix.md create mode 100644 claude/ci/commands/run.md create mode 100644 claude/ci/commands/status.md create mode 100644 claude/ci/hooks.json create mode 100755 claude/ci/scripts/post-push-ci.sh create mode 100644 claude/qa/commands/check.md create mode 100644 claude/qa/commands/lint.md create mode 100644 claude/qa/hooks.json create mode 100644 claude/review/commands/pr.md create mode 100644 claude/review/commands/security.md create mode 100644 claude/review/hooks.json create mode 100755 claude/review/scripts/post-pr-create.sh create mode 100644 claude/verify/commands/ready.md create mode 100644 claude/verify/commands/tests.md create mode 100644 claude/verify/hooks.json create mode 100755 claude/verify/scripts/pre-push-check.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..8820bec --- /dev/null +++ b/README.md @@ -0,0 +1,119 @@ +# core-agent + +A monorepo of [Claude Code](https://claude.ai/code) plugins for the Host UK federated monorepo. + +## Plugins + +| Plugin | Description | Commands | +|--------|-------------|----------| +| **[code](./claude/code)** | Core development - hooks, scripts, data collection | `/code:remember`, `/code:yes` | +| **[review](./claude/review)** | Code review automation | `/review:review`, `/review:security`, `/review:pr` | +| **[verify](./claude/verify)** | Work verification before commit/push | `/verify:verify`, `/verify:ready` | +| **[qa](./claude/qa)** | Quality assurance fix loops | `/qa:qa`, `/qa:fix`, `/qa:check` | +| **[ci](./claude/ci)** | CI/CD integration | `/ci:ci`, `/ci:workflow`, `/ci:fix` | + +## Installation + +```bash +# Install all plugins via marketplace +claude plugin add host-uk/core-agent + +# Or install individual plugins +claude plugin add host-uk/core-agent/claude/code +claude plugin add host-uk/core-agent/claude/review +claude plugin add host-uk/core-agent/claude/qa +``` + +## Quick Start + +```bash +# Code review staged changes +/review:review + +# Run QA and fix all issues +/qa:qa + +# Verify work is ready to commit +/verify:verify + +# Check CI status +/ci:ci +``` + +## Core CLI Integration + +These plugins enforce the `core` CLI for development commands: + +| Instead of... | Use... | +|---------------|--------| +| `go test` | `core go test` | +| `go build` | `core build` | +| `golangci-lint` | `core go lint` | +| `composer test` | `core php test` | +| `./vendor/bin/pint` | `core php fmt` | + +## Plugin Details + +### code + +The core plugin with hooks and data collection skills: + +- **Hooks**: Auto-format, debug detection, dangerous command blocking +- **Skills**: Data collection for archiving OSS projects (whitepapers, forums, market data) +- **Commands**: `/code:remember` (persist facts), `/code:yes` (auto-approve mode) + +### review + +Code review automation: + +- `/review:review` - Review staged changes or commit range +- `/review:security` - Security-focused review +- `/review:pr [number]` - Review a pull request + +### verify + +Work verification: + +- `/verify:verify` - Full verification (tests, lint, format, debug check) +- `/verify:ready` - Quick check if ready to commit + +### qa + +Quality assurance: + +- `/qa:qa` - Run QA pipeline, fix all issues iteratively +- `/qa:fix ` - Fix a specific issue +- `/qa:check` - Check without fixing + +### ci + +CI/CD integration: + +- `/ci:ci` - Check CI status +- `/ci:workflow ` - Generate GitHub Actions workflow +- `/ci:fix` - Analyse and fix failing CI + +## Development + +### Adding a new plugin + +1. Create `claude//.claude-plugin/plugin.json` +2. Add commands to `claude//commands/` +3. Add hooks to `claude//hooks.json` (optional) +4. Register in `.claude-plugin/marketplace.json` + +### Testing locally + +```bash +claude plugin add /path/to/core-agent +``` + +## License + +EUPL-1.2 + +## Links + +- [Host UK](https://host.uk.com) +- [Claude Code Documentation](https://docs.anthropic.com/claude-code) +- [Issues](https://github.com/host-uk/core-agent/issues) diff --git a/claude/ci/commands/fix.md b/claude/ci/commands/fix.md new file mode 100644 index 0000000..722592d --- /dev/null +++ b/claude/ci/commands/fix.md @@ -0,0 +1,97 @@ +--- +name: fix +description: Analyse and fix failing CI +--- + +# Fix CI + +Analyse failing CI runs and suggest/apply fixes. + +## Process + +1. **Get failing run** + ```bash + gh run list --status failure --limit 1 + gh run view --log-failed + ``` + +2. **Analyse failure** + - Parse error messages + - Identify root cause + - Check if local issue or CI-specific + +3. **Suggest fix** + - Code changes if needed + - CI config changes if needed + +4. **Apply fix** (if approved) + +## Common CI Failures + +### Test Failures +``` +Error: go test failed +--- FAIL: TestFoo +``` +→ Fix the failing test locally, then push + +### Lint Failures +``` +Error: golangci-lint failed +file.go:42: undefined: X +``` +→ Fix lint issue locally + +### Build Failures +``` +Error: go build failed +cannot find package +``` +→ Run `go mod tidy`, check imports + +### Dependency Issues +``` +Error: go mod download failed +``` +→ Check go.mod, clear cache, retry + +### Timeout +``` +Error: Job exceeded time limit +``` +→ Optimise tests or increase timeout in workflow + +## Output + +```markdown +## CI Failure Analysis + +**Run**: #12345 +**Workflow**: Tests +**Failed at**: 2024-01-15 14:30 + +### Error +``` +--- FAIL: TestCreateUser (0.02s) + handler_test.go:45: expected 200, got 500 +``` + +### Analysis +The test expects a 200 response but gets 500. This indicates the handler is returning an error. + +### Root Cause +Looking at recent changes, `ErrNotFound` was removed but still referenced. + +### Fix +Add the missing error definition: +```go +var ErrNotFound = errors.New("not found") +``` + +### Commands +```bash +# Apply fix and push +git add . && git commit -m "fix: add missing ErrNotFound" +git push +``` +``` diff --git a/claude/ci/commands/run.md b/claude/ci/commands/run.md new file mode 100644 index 0000000..7a501ae --- /dev/null +++ b/claude/ci/commands/run.md @@ -0,0 +1,76 @@ +--- +name: run +description: Trigger a CI workflow run +args: [workflow-name] +--- + +# Run Workflow + +Manually trigger a GitHub Actions workflow. + +## Usage + +``` +/ci:run # Run default workflow +/ci:run tests # Run specific workflow +/ci:run release # Trigger release workflow +``` + +## Process + +1. **List available workflows** + ```bash + gh workflow list + ``` + +2. **Trigger workflow** + ```bash + gh workflow run tests.yml + gh workflow run tests.yml --ref feature-branch + ``` + +3. **Watch progress** + ```bash + gh run watch + ``` + +## Common Workflows + +| Workflow | Trigger | Purpose | +|----------|---------|---------| +| `tests.yml` | Push, PR | Run test suite | +| `lint.yml` | Push, PR | Run linters | +| `build.yml` | Push | Build artifacts | +| `release.yml` | Tag | Create release | +| `deploy.yml` | Manual | Deploy to environment | + +## Output + +```markdown +## Workflow Triggered + +**Workflow**: tests.yml +**Branch**: feature/add-auth +**Run ID**: 12345 + +Watching progress... + +``` +⠋ Tests running... + ✓ Setup (12s) + ✓ Install dependencies (45s) + ⠋ Run tests (running) +``` + +**Run completed in 2m 34s** ✓ +``` + +## Options + +```bash +# Run with inputs (for workflows that accept them) +gh workflow run deploy.yml -f environment=staging + +# Run on specific ref +gh workflow run tests.yml --ref main +``` diff --git a/claude/ci/commands/status.md b/claude/ci/commands/status.md new file mode 100644 index 0000000..afd7d99 --- /dev/null +++ b/claude/ci/commands/status.md @@ -0,0 +1,63 @@ +--- +name: status +description: Show CI status for current branch +--- + +# CI Status + +Show GitHub Actions status for the current branch. + +## Usage + +``` +/ci:status +/ci:status --all # All recent runs +/ci:status --branch X # Specific branch +``` + +## Commands + +```bash +# Current branch status +gh run list --branch $(git branch --show-current) --limit 5 + +# Get details of latest run +gh run view --log-failed + +# Watch running workflow +gh run watch +``` + +## Output + +```markdown +## CI Status: feature/add-auth + +| Workflow | Status | Duration | Commit | When | +|----------|--------|----------|--------|------| +| Tests | ✓ pass | 2m 34s | abc123 | 5m ago | +| Lint | ✓ pass | 45s | abc123 | 5m ago | +| Build | ✓ pass | 1m 12s | abc123 | 5m ago | + +**All checks passing** ✓ + +--- + +Or if failing: + +| Workflow | Status | Duration | Commit | When | +|----------|--------|----------|--------|------| +| Tests | ✗ fail | 1m 45s | abc123 | 5m ago | +| Lint | ✓ pass | 45s | abc123 | 5m ago | +| Build | - skip | - | abc123 | 5m ago | + +**1 workflow failing** + +### Tests Failure +``` +--- FAIL: TestCreateUser + expected 200, got 500 +``` + +Run `/ci:fix` to analyse and fix. +``` diff --git a/claude/ci/hooks.json b/claude/ci/hooks.json new file mode 100644 index 0000000..97354d9 --- /dev/null +++ b/claude/ci/hooks.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://claude.ai/schemas/hooks.json", + "hooks": { + "PostToolUse": [ + { + "matcher": "tool == \"Bash\" && tool_input.command matches \"^git push\"", + "hooks": [ + { + "type": "command", + "command": "${CLAUDE_PLUGIN_ROOT}/scripts/post-push-ci.sh" + } + ], + "description": "Show CI status after push" + } + ] + } +} diff --git a/claude/ci/scripts/post-push-ci.sh b/claude/ci/scripts/post-push-ci.sh new file mode 100755 index 0000000..f84797f --- /dev/null +++ b/claude/ci/scripts/post-push-ci.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Show CI status hint after push + +read -r input +EXIT_CODE=$(echo "$input" | jq -r '.tool_response.exit_code // 0') + +if [ "$EXIT_CODE" = "0" ]; then + # Check if repo has workflows + if [ -d ".github/workflows" ]; then + cat << 'EOF' +{ + "hookSpecificOutput": { + "hookEventName": "PostToolUse", + "additionalContext": "Push successful. CI workflows will run shortly.\n\nRun `/ci:status` to check progress or `gh run watch` to follow live." + } +} +EOF + else + echo "$input" + fi +else + echo "$input" +fi diff --git a/claude/qa/commands/check.md b/claude/qa/commands/check.md new file mode 100644 index 0000000..29f34f6 --- /dev/null +++ b/claude/qa/commands/check.md @@ -0,0 +1,74 @@ +--- +name: check +description: Run QA checks without fixing (report only) +args: [--go|--php|--all] +--- + +# QA Check + +Run QA pipeline and report issues without fixing them. + +## Usage + +``` +/qa:check # Auto-detect project type +/qa:check --go # Force Go checks +/qa:check --php # Force PHP checks +/qa:check --all # Run both if applicable +``` + +## Process + +1. **Detect project type** +2. **Run QA pipeline** +3. **Parse and report issues** +4. **Do NOT fix anything** + +## Go Checks + +```bash +core go qa +``` + +Runs: +- `go fmt` - Formatting +- `go vet` - Static analysis +- `golangci-lint` - Linting +- `go test` - Tests + +## PHP Checks + +```bash +core php qa +``` + +Runs: +- `pint` - Formatting +- `phpstan` - Static analysis +- `pest` - Tests + +## Output + +```markdown +## QA Report + +**Project**: Go (go.mod detected) +**Status**: 3 issues found + +### Formatting +✗ 2 files need formatting +- pkg/api/handler.go +- pkg/auth/token.go + +### Linting +✗ 1 issue +- pkg/api/handler.go:42 - undefined: ErrNotFound + +### Tests +✓ All passing (47/47) + +--- +**Summary**: fmt: FAIL | lint: FAIL | test: PASS + +Run `/qa:qa` to fix these issues automatically. +``` diff --git a/claude/qa/commands/lint.md b/claude/qa/commands/lint.md new file mode 100644 index 0000000..7ea8746 --- /dev/null +++ b/claude/qa/commands/lint.md @@ -0,0 +1,78 @@ +--- +name: lint +description: Run linter and fix issues +args: [--check|--fix] +--- + +# Lint + +Run linter and optionally fix issues. + +## Usage + +``` +/qa:lint # Run lint, report issues +/qa:lint --check # Check only, no fixes +/qa:lint --fix # Auto-fix where possible +``` + +## Process + +### Go +```bash +# Check +core go lint + +# Some issues can be auto-fixed +golangci-lint run --fix +``` + +### PHP +```bash +# Check +core php stan + +# PHPStan doesn't auto-fix, but can suggest fixes +``` + +## Common Issues + +### Go + +| Issue | Fix | +|-------|-----| +| `undefined: X` | Add import or define variable | +| `ineffectual assignment` | Use variable or remove | +| `unused parameter` | Use `_` prefix or remove | +| `error return value not checked` | Handle the error | + +### PHP + +| Issue | Fix | +|-------|-----| +| `Undefined variable` | Define or check existence | +| `Parameter $x has no type` | Add type hint | +| `Method has no return type` | Add return type | + +## Output + +```markdown +## Lint Results + +**Linter**: golangci-lint +**Issues**: 3 + +### Errors +1. **pkg/api/handler.go:42** - undefined: ErrNotFound + → Add `var ErrNotFound = errors.New("not found")` + +2. **pkg/api/handler.go:87** - error return value not checked + → Handle error: `if err != nil { return err }` + +### Warnings +1. **pkg/api/handler.go:15** - unused parameter ctx + → Rename to `_` or use it + +--- +Run `/qa:lint --fix` to auto-fix where possible. +``` diff --git a/claude/qa/hooks.json b/claude/qa/hooks.json new file mode 100644 index 0000000..0b463ec --- /dev/null +++ b/claude/qa/hooks.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://claude.ai/schemas/hooks.json", + "hooks": { + "PostToolUse": [ + { + "matcher": "tool == \"Bash\" && tool_input.command matches \"^core (go|php) (qa|test|lint|stan)\"", + "hooks": [ + { + "type": "command", + "command": "${CLAUDE_PLUGIN_ROOT}/scripts/qa-filter.sh" + } + ], + "description": "Filter QA output to show only actionable issues" + } + ] + } +} diff --git a/claude/review/commands/pr.md b/claude/review/commands/pr.md new file mode 100644 index 0000000..ef24934 --- /dev/null +++ b/claude/review/commands/pr.md @@ -0,0 +1,87 @@ +--- +name: pr +description: Review a pull request +args: +--- + +# PR Review + +Review a GitHub pull request. + +## Usage + +``` +/review:pr 123 +/review:pr 123 --security +/review:pr 123 --quick +``` + +## Process + +1. **Fetch PR details** + ```bash + gh pr view 123 --json title,body,author,files,additions,deletions + ``` + +2. **Get PR diff** + ```bash + gh pr diff 123 + ``` + +3. **Check CI status** + ```bash + gh pr checks 123 + ``` + +4. **Review changes** + - Correctness + - Security (if --security) + - Tests coverage + - Documentation + +5. **Provide feedback** + +## Output Format + +```markdown +## PR Review: #123 - Add user authentication + +**Author**: @username +**Files**: 5 changed (+120, -30) +**CI**: ✓ All checks passing + +### Summary +Brief description of what this PR does. + +### Review + +#### Approved ✓ +- Clean implementation +- Good test coverage +- Documentation updated + +#### Changes Requested ✗ +- **src/auth.go:42** - Missing input validation +- **src/auth.go:87** - Error not handled + +#### Comments +- Consider adding rate limiting +- Nice use of middleware pattern + +--- +**Recommendation**: Approve with minor changes +``` + +## Actions + +After review, you can: +```bash +# Approve +gh pr review 123 --approve + +# Request changes +gh pr review 123 --request-changes --body "See comments" + +# Comment only +gh pr review 123 --comment --body "Looks good overall" +``` diff --git a/claude/review/commands/security.md b/claude/review/commands/security.md new file mode 100644 index 0000000..9867c8e --- /dev/null +++ b/claude/review/commands/security.md @@ -0,0 +1,93 @@ +--- +name: security +description: Security-focused code review +args: [commit-range|--pr=N] +--- + +# Security Review + +Perform a security-focused code review. + +## Focus Areas + +### 1. Injection Vulnerabilities +- SQL injection +- Command injection +- XSS (Cross-Site Scripting) +- LDAP injection +- XML injection + +### 2. Authentication & Authorisation +- Hardcoded credentials +- Weak password handling +- Missing auth checks +- Privilege escalation paths + +### 3. Data Exposure +- Sensitive data in logs +- PII in error messages +- Secrets in version control +- Insecure data transmission + +### 4. Cryptography +- Weak algorithms (MD5, SHA1 for security) +- Hardcoded keys/IVs +- Insecure random number generation + +### 5. Dependencies +- Known vulnerable packages +- Outdated dependencies + +## Process + +1. Get diff for specified range +2. Scan for security patterns +3. Check for common vulnerabilities +4. Report findings with severity + +## Patterns to Check + +### Go +```go +// SQL injection +db.Query("SELECT * FROM users WHERE id = " + id) + +// Command injection +exec.Command("bash", "-c", userInput) + +// Hardcoded secrets +apiKey := "sk_live_..." +``` + +### PHP +```php +// SQL injection +$db->query("SELECT * FROM users WHERE id = $id"); + +// XSS +echo $request->input('name'); + +// Command injection +shell_exec($userInput); +``` + +## Output Format + +```markdown +## Security Review + +### Critical +- **file:line** - SQL Injection: User input directly in query + +### High +- **file:line** - Hardcoded API key detected + +### Medium +- **file:line** - Missing CSRF protection + +### Low +- **file:line** - Debug endpoint exposed + +--- +**Summary**: X critical, Y high, Z medium, W low +``` diff --git a/claude/review/hooks.json b/claude/review/hooks.json new file mode 100644 index 0000000..6718624 --- /dev/null +++ b/claude/review/hooks.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://claude.ai/schemas/hooks.json", + "hooks": { + "PostToolUse": [ + { + "matcher": "tool == \"Bash\" && tool_input.command matches \"^gh pr create\"", + "hooks": [ + { + "type": "command", + "command": "${CLAUDE_PLUGIN_ROOT}/scripts/post-pr-create.sh" + } + ], + "description": "Suggest review after PR creation" + } + ] + } +} diff --git a/claude/review/scripts/post-pr-create.sh b/claude/review/scripts/post-pr-create.sh new file mode 100755 index 0000000..7914e09 --- /dev/null +++ b/claude/review/scripts/post-pr-create.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Suggest review after PR creation + +read -r input +OUTPUT=$(echo "$input" | jq -r '.tool_response.stdout // .tool_response.output // empty') + +# Extract PR URL from output +PR_URL=$(echo "$OUTPUT" | grep -oE 'https://github.com/[^/]+/[^/]+/pull/[0-9]+' | head -1) + +if [ -n "$PR_URL" ]; then + PR_NUM=$(echo "$PR_URL" | grep -oE '[0-9]+$') + cat << EOF +{ + "hookSpecificOutput": { + "hookEventName": "PostToolUse", + "additionalContext": "PR created: $PR_URL\n\nRun \`/review:pr $PR_NUM\` to review before requesting reviewers." + } +} +EOF +else + echo "$input" +fi diff --git a/claude/verify/commands/ready.md b/claude/verify/commands/ready.md new file mode 100644 index 0000000..51955f4 --- /dev/null +++ b/claude/verify/commands/ready.md @@ -0,0 +1,53 @@ +--- +name: ready +description: Quick check if work is ready to commit +--- + +# Ready Check + +Quick verification that work is ready to commit. + +## Checks + +1. **No uncommitted changes left behind** +2. **No debug statements** +3. **Code is formatted** + +## Process + +```bash +# Check for changes +git status --porcelain + +# Quick format check +core go fmt --check 2>/dev/null || core php fmt --test 2>/dev/null +``` + +## Output + +``` +## Ready Check + +✓ All changes staged +✓ No debug statements +✓ Code formatted + +**Ready to commit!** +``` + +Or: + +``` +## Ready Check + +✗ Unstaged changes: 2 files +✓ No debug statements +✗ Formatting needed: 1 file + +**Not ready** - run `/verify:verify` for details +``` + +## When to Use + +Use `/verify:ready` for a quick check before committing. +Use `/verify:verify` for full verification including tests. diff --git a/claude/verify/commands/tests.md b/claude/verify/commands/tests.md new file mode 100644 index 0000000..7361ee5 --- /dev/null +++ b/claude/verify/commands/tests.md @@ -0,0 +1,80 @@ +--- +name: tests +description: Verify tests pass for changed files +--- + +# Test Verification + +Run tests related to changed files. + +## Process + +1. **Identify changed files** + ```bash + git diff --name-only HEAD + ``` + +2. **Find related tests** + - Go: `*_test.go` files in same package + - PHP: `*Test.php` files in tests/ directory + +3. **Run targeted tests** + ```bash + # Go - run package tests + core go test ./pkg/changed/... + + # PHP - run filtered tests + core php test --filter=ChangedTest + ``` + +4. **Report results** + +## Smart Test Detection + +### Go +``` +Changed: pkg/api/handler.go +Related: pkg/api/handler_test.go +Run: core go test ./pkg/api/... +``` + +### PHP +``` +Changed: src/Http/UserController.php +Related: tests/Http/UserControllerTest.php +Run: core php test tests/Http/UserControllerTest.php +``` + +## Output + +``` +## Test Verification + +**Changed files**: 3 +**Related tests**: 2 packages + +### Results +✓ pkg/api: 12 tests passed +✓ pkg/auth: 8 tests passed + +**All tests passing!** +``` + +Or: + +``` +## Test Verification + +**Changed files**: 3 +**Related tests**: 2 packages + +### Results +✓ pkg/api: 12 tests passed +✗ pkg/auth: 1 failed + +### Failures +- TestValidateToken: expected true, got false + auth_test.go:45 + +**Fix failing tests before committing.** +``` diff --git a/claude/verify/hooks.json b/claude/verify/hooks.json new file mode 100644 index 0000000..fead228 --- /dev/null +++ b/claude/verify/hooks.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://claude.ai/schemas/hooks.json", + "hooks": { + "PreToolUse": [ + { + "matcher": "tool == \"Bash\" && tool_input.command matches \"^git push\"", + "hooks": [ + { + "type": "command", + "command": "${CLAUDE_PLUGIN_ROOT}/scripts/pre-push-check.sh" + } + ], + "description": "Warn about unpushed verification before git push" + } + ] + } +} diff --git a/claude/verify/scripts/pre-push-check.sh b/claude/verify/scripts/pre-push-check.sh new file mode 100755 index 0000000..42b2d13 --- /dev/null +++ b/claude/verify/scripts/pre-push-check.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Remind about verification before push + +read -r input + +# Check if tests were run recently (within last 5 minutes) +LAST_TEST=$(find . -name "*.test" -mmin -5 2>/dev/null | head -1) +LAST_COVERAGE=$(find . -name "coverage.*" -mmin -5 2>/dev/null | head -1) + +if [ -z "$LAST_TEST" ] && [ -z "$LAST_COVERAGE" ]; then + cat << 'EOF' +{ + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "additionalContext": "⚠️ No recent test run detected. Consider running `/verify:verify` before pushing." + } +} +EOF +else + echo "$input" +fi