Add dotclaude configuration files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Poshan Pandey
2026-03-26 17:16:27 -07:00
parent c10636b330
commit 491a45dd43
37 changed files with 2737 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
# Local overrides (not shared with team)
settings.local.json
CLAUDE.local.md
# OS artifacts
.DS_Store
Thumbs.db
# Editor artifacts
*.swp
*~
+26
View File
@@ -0,0 +1,26 @@
# Personal Overrides
> Rename this to CLAUDE.local.md — it's gitignored and won't be shared with the team.
## My Preferences
- I prefer verbose commit messages with context
- Always explain your reasoning before making changes
- When in doubt, ask rather than guess
## Environment
- My test database runs on port 5433 (not default 5432)
- Use `pnpm` instead of `npm` on my machine
## Shortcuts
- When I say "ship it", run `/ship`
- When I say "review", run `/pr-review`
- When I say "fix it", run `/debug-fix`
## Current Context
- I'm working on the billing module this sprint
- The staging environment is at https://staging.example.com
- Feature flags are managed in LaunchDarkly
+49
View File
@@ -0,0 +1,49 @@
# Project Instructions
> REPLACE: Customize this file for your project. Delete sections that don't apply — every line costs tokens. Code style lives in .claude/rules/code-quality.md — don't duplicate here. Run `/setupdotclaude` to auto-customize, or edit manually and delete all `> REPLACE:` blocks when done.
## Commands
```bash
# Build
npm run build # or: cargo build, go build ./..., make build
# Test
npm test # run full suite
npm test -- path/to/file # run single test file
# Lint & Format
npm run lint # check style
npm run lint:fix # auto-fix style
npm run typecheck # type checking
# Dev
npm run dev # start dev server
```
## Architecture
> REPLACE: Describe non-obvious architectural decisions. Don't list files — Claude can explore.
- `src/` — application source
- `src/api/` — REST endpoints (versioned: `/v1/`)
- `src/services/` — business logic (no direct DB access from controllers)
- `src/models/` — data models and types
## Key Decisions
> REPLACE: Record WHY non-obvious choices were made. This is the most valuable section. Examples: "Auth tokens in httpOnly cookies because XSS risk", "Billing is a separate module for audit independence".
## Domain Knowledge
> REPLACE: Terms, abbreviations, or concepts that aren't obvious from the code. Example: "SKU" = Stock Keeping Unit, the unique product identifier from our warehouse system.
## Workflow
- Run typecheck after making a series of code changes
- Prefer fixing the root cause over adding workarounds
- When unsure about approach, use plan mode (`Shift+Tab`) before coding
## Don'ts
- Don't modify generated files (`*.gen.ts`, `*.generated.*`)
+99
View File
@@ -0,0 +1,99 @@
# Contributing to dotclaude
Thanks for wanting to make this better. This project aims to be the standard `.claude/` folder structure — contributions that help more developers ship faster are welcome.
## Before You Contribute
- Check existing issues and open PRs to avoid duplicate work
- For large changes (new skills, new agents, restructuring), open an issue first to discuss the approach
## What We're Looking For
**Yes, please:**
- Bug fixes in hook scripts
- Improvements to existing rules, skills, or agents that make them more effective
- New skills for common daily workflows (not project-creation workflows)
- New agents for common review/analysis tasks
- Better token efficiency — same quality, fewer tokens
- Documentation improvements
**Probably not:**
- Language-specific rules — Claude already knows standard conventions
- Plugin integrations — this repo is deliberately plugin-free
- Project scaffolding skills — this is for daily work, not project creation
- Vendor-specific configurations (specific CI providers, cloud platforms, etc.)
## PR Rules
### One thing per PR
Each PR should do exactly one thing. Don't bundle a new skill with a rule fix with a README update. Split them.
### File requirements
| File type | Must have | Must NOT have |
|---|---|---|
| **Rules** (`.md` in `rules/`) | `alwaysApply: true` or `paths:` frontmatter | Language-specific conventions Claude already knows |
| **Skills** (`SKILL.md`) | `name`, `description` in frontmatter | Hardcoded package names, model assignments |
| **Agents** (`.md` in `agents/`) | `name`, `description`, `tools` in frontmatter | `model` field (users choose their own model) |
| **Hooks** (`.sh` in `hooks/`) | `jq` availability check, proper exit codes (0=allow, 2=block) | Hardcoded paths, missing `#!/bin/bash` |
### Naming
- Skill directories: `kebab-case``debug-fix/`, `test-writer/`
- Agent files: `kebab-case.md``code-reviewer.md`, `security-reviewer.md`
- Rule files: `kebab-case.md``code-quality.md`, `frontend.md`
- Hook scripts: `kebab-case.sh``protect-files.sh`, `block-dangerous-commands.sh`
### No duplication
Before adding content, check that it's not already covered elsewhere:
- If a hook enforces it, don't also add a rule saying the same thing
- If a skill covers it, don't duplicate the guidance in a rule
- If `CLAUDE.md` says it, don't repeat it in a rule
- Agents run isolated and CAN repeat rule content (they don't see rules)
### No hardcoded opinions
This is a template — keep it framework-agnostic:
- Don't hardcode `npm`, `pnpm`, `yarn`, or any specific package manager
- Don't hardcode specific component libraries, CSS frameworks, or test runners
- Don't assign `model` to agents or skills — let users choose
- Present options as tables or lists, not mandates
- The `/setupdotclaude` skill handles project-specific customization at runtime
### Token consciousness
Every line in a rule costs tokens every session. Every line in a skill costs tokens when invoked. Before adding content, ask: "Would removing this cause Claude to make mistakes?" If no, don't add it.
### Hook scripts must be safe
- Always check for `jq` availability before using it
- Exit 0 (allow) if dependencies are missing — don't block the user
- PreToolUse hooks observe and block — they should never modify files. PostToolUse hooks may transform output (e.g., formatting).
- Test with sample JSON input before submitting
### Update READMEs
If you add a new file to `rules/`, `skills/`, `agents/`, or `hooks/`, add a description to the README in that folder. Keep it to 2-3 lines.
### Update the root README
If your change adds or removes a file, update the structure tree in `README.md` to match.
## How to Submit
1. Fork the repo
2. Create a branch: `feat/your-skill-name` or `fix/hook-bug-description`
3. Make your changes
4. Test: verify YAML frontmatter is valid, hook scripts work with sample input, no duplication with existing files
5. Open a PR with:
- **Title**: what you added/changed (under 72 chars)
- **Body**: why it's useful, what daily workflow it improves
- **Testing**: how you verified it works
## Code of Conduct
Be helpful, be kind, be constructive. We're all here to make Claude Code better for daily development work.
+220
View File
@@ -0,0 +1,220 @@
# dotclaude
The standard `.claude/` folder structure for everyday development.
## Why This Exists
Plugins consume hundreds of tokens per turn and are designed for specific workflows like scaffolding entire projects. But day-to-day, you're fixing bugs, adding features, reviewing code, and writing tests — not building products from scratch.
This repo provides a lean, token-efficient `.claude/` configuration optimized for **daily development work**. Copy what you need, delete what you don't.
## Getting Started
### 1. Copy everything into your project
```bash
git clone https://github.com/poshan0126/dotclaude.git /tmp/dotclaude
cd your-project
mkdir -p .claude
# Copy config files
cp /tmp/dotclaude/settings.json .claude/
cp -r /tmp/dotclaude/{rules,skills,agents,hooks} .claude/
cp /tmp/dotclaude/.gitignore .claude/
cp /tmp/dotclaude/CLAUDE.md ./
cp /tmp/dotclaude/CLAUDE.local.md.example ./
chmod +x .claude/hooks/*.sh
rm -rf /tmp/dotclaude
# Add CLAUDE.local.md to your project root .gitignore
echo "CLAUDE.local.md" >> .gitignore
```
### 2. Reload Claude Code
If you already have a Claude Code session open, **exit and restart it**. Skills, agents, and rules are loaded at session start — a running session won't see the new files.
### 3. Run `/setupdotclaude`
```
/setupdotclaude
```
This will:
- Clean up README files that waste tokens
- Scan your codebase (tech stack, test framework, linters, folder structure)
- Customize `CLAUDE.md` with your actual build/test/lint commands
- Update `settings.json` permissions for your package manager
- Adjust rule paths to match your real directories
- Auto-detect and enable your project's formatter (Prettier, Biome, Ruff, Black, rustfmt, gofmt)
- Remove config that doesn't apply (e.g., frontend rules if you have no frontend)
- Run a final review pass against your full codebase
Every change is confirmed with you before it's applied.
> If you skip `/setupdotclaude`, delete the `README.md` files inside `.claude/` subdirectories — they're for GitHub browsing only and waste tokens at runtime.
### Troubleshooting
| Problem | Fix |
|---------|-----|
| Skills or agents not showing up | **Restart Claude Code** — skills/agents/rules are loaded at session start |
| Hooks not running | Run `chmod +x .claude/hooks/*.sh` and verify `jq` is installed |
| "jq not found" blocking everything | Install jq: `brew install jq` (macOS) or `apt install jq` (Linux) |
| format-on-save not formatting | Ensure the formatter binary is installed locally and its config file exists in the project root |
| Permission denied on allowed commands | Check glob syntax in `settings.json``Bash(npm run test *)` means the `*` matches arguments after `test` |
| `/setupdotclaude` asks to confirm settings.json edits | This is expected — `protect-files.sh` prompts for confirmation when editing `settings.json` (hook scripts remain hard-blocked) |
### 4. Make it yours
`/setupdotclaude` gets you 90% of the way. To give it your unique touch:
- **`rules/code-quality.md`** — update naming conventions to match your team's style. Tweak the comment guidelines, code marker format, and import order.
- **`rules/frontend.md`** — pick your design principle. Highlight which component framework your project uses.
- **`rules/security.md`** — add paths specific to your project's sensitive areas beyond the defaults.
- **`CLAUDE.md`** — add architectural decisions, domain knowledge, and workflow quirks unique to your project.
- **`CLAUDE.local.md`** — rename the `.example` file for personal preferences (gitignored).
- **`hooks/format-on-save.sh`** — if `/setupdotclaude` didn't detect your formatter, uncomment the right section manually.
The defaults are solid foundations. Your edits on top are what make Claude truly effective for *your* project.
## Skills (Slash Commands)
Skills are invoked with `/name` in your Claude Code session. All skills except `/test-writer` are manual-only — you invoke them explicitly.
| Command | Arguments | Description |
|---------|-----------|-------------|
| `/setupdotclaude` | `[focus area]` | Scan your codebase and customize all `.claude/` config files to match your actual tech stack. Run once after copying dotclaude into a project. Detects language, framework, package manager, test runner, linter, and architecture — then updates CLAUDE.md, settings.json, rules, hooks, and agents. Confirms every change before applying. |
| `/debug-fix` | `[issue #, error msg, or description]` | Find and fix a bug from any source. Reproduces the issue, traces root cause through code and git history, makes the minimal fix, writes a regression test, and wraps up with a branch and commit. |
| `/ship` | `[commit message or PR title]` | Full shipping workflow: scans changes, stages files (skipping secrets/locks/build output), drafts a commit message matching repo style, pushes, and creates a PR. Every step requires your confirmation. |
| `/hotfix` | `[issue #, error msg, or description]` | Emergency production fix. Creates a `hotfix/` branch from main, makes the smallest correct change (no refactoring), runs only critical tests, and ships a PR with `[HOTFIX]` label. Warns if the fix is too complex for a hotfix. |
| `/pr-review` | `[PR #, "staged", file path, or omit]` | Delegates review to specialist agents: `@code-reviewer`, `@security-reviewer` (if security-related code), `@performance-reviewer` (if perf-sensitive), `@doc-reviewer` (if docs changed). Synthesizes a unified report with severity-ranked findings. |
| `/tdd` | `[feature description or function signature]` | Strict Red-Green-Refactor TDD loop. Writes one failing test, then minimum code to pass, then refactors. Commits after each green+refactor cycle. Works simple-to-complex: degenerate cases, happy path, variations, edge cases, errors. |
| `/explain` | `[file, function, or concept]` | Explains code with a one-sentence summary, mental model analogy, ASCII diagram, key non-obvious details, and modification guide. Focuses on the "why" and landmines, not the obvious. |
| `/refactor` | `[file, function, or pattern]` | Safe refactoring with tests as a safety net. Writes tests first if none exist, plans transformations, makes small testable steps, verifies after each step. Never mixes refactoring with behavior changes. |
| `/test-writer` | *(auto-triggers)* | Writes comprehensive tests for new or changed code. Discovers changes via git diff, maps all code paths (happy, edge, error, concurrency), writes one test per scenario with Arrange-Act-Assert. **This is the only skill that can auto-trigger** — Claude may invoke it automatically after you add new features. |
## Agents (Subagents)
Agents are specialized Claude instances that run in their own isolated context. They are auto-delegated by Claude based on the task, or you can invoke them explicitly with `@agent-name` in your prompt.
| Agent | When It's Used | What It Does |
|-------|---------------|--------------|
| `@code-reviewer` | Auto-delegated by `/pr-review`, or invoke directly | Reviews code for correctness and maintainability. Catches off-by-one errors, null dereferences, logic bugs, race conditions, error handling gaps, excessive complexity, and missing tests. Focuses on real issues with evidence — not style nitpicks or linter territory. |
| `@security-reviewer` | Auto-delegated by `/pr-review` when security-related code is changed | Senior security engineer performing static analysis. Covers injection (SQL, command, XSS, template, path traversal), auth/authz flaws, data exposure, cryptography issues, dependency vulnerabilities, and input validation gaps. Reports severity, attack vector, and concrete fix for each finding. |
| `@performance-reviewer` | Auto-delegated by `/pr-review` when performance-sensitive code is changed | Finds real bottlenecks, not theoretical micro-optimizations. Checks for N+1 queries, missing indexes, unbounded queries, memory leaks, repeated computation, blocking I/O on hot paths, unnecessary re-renders, bundle size issues, and lock contention. Only flags issues with measurable impact. |
| `@frontend-designer` | Auto-delegated when building UI, or invoke directly | Creates distinctive, production-grade frontend UI that avoids generic "AI aesthetics." Enforces design tokens, chooses appropriate design principles (glassmorphism, brutalism, editorial, etc.), ensures accessibility (WCAG), and prevents common anti-patterns like purple gradients, centered-everything layouts, and overused fonts. |
| `@doc-reviewer` | Auto-delegated by `/pr-review` when documentation changes | Reviews docs for accuracy by cross-referencing actual source code. Verifies function signatures, code examples, config options, and file paths are correct. Identifies stale references, missing prerequisites, undocumented error cases, and unclear instructions. |
### Using Agents Directly
You can invoke any agent in your prompt:
```
@security-reviewer Review the auth middleware changes in src/middleware/auth.ts
```
```
@frontend-designer Build a dashboard page for the analytics module
```
```
@code-reviewer Check my staged changes before I commit
```
Agents run in isolated context — they don't see your conversation history, but they have access to the full codebase through their allowed tools.
## Customization Guide
| Want to... | Do this |
|---|---|
| Add project-specific rules | Create `.claude/rules/your-rule.md` |
| Scope rules to file paths | Add `paths:` frontmatter to rule files |
| Add a team workflow | Create `.claude/skills/your-skill/SKILL.md` |
| Add a specialist reviewer | Create `.claude/agents/your-agent.md` |
| Enforce behavior deterministically | Add a hook in `settings.json` |
| Override settings locally | Copy `settings.local.json.example``.claude/settings.local.json` |
| Personal CLAUDE.md overrides | Rename `CLAUDE.local.md.example``CLAUDE.local.md` |
### Example: Project-specific rule
```yaml
---
paths:
- "src/billing/**"
---
# Billing Module
- All monetary values use cents (integers), never floating point dollars
- Tax calculations must use the tax-engine service, never inline math
- Every billing mutation must be idempotent with a unique request ID
```
## What's Inside
> **Note**: This repo is flat (not nested inside `.claude/`) because `CLAUDE.md` goes at your project root while everything else goes inside `.claude/`. The copy commands below handle the separation.
```
dotclaude/
├── CLAUDE.md # Template project instructions → copy to YOUR project root
├── CLAUDE.local.md.example # Personal overrides template → copy and rename to CLAUDE.local.md
├── settings.json # Project settings → copy to .claude/
├── settings.local.json.example # Personal settings template → copy to .claude/settings.local.json
├── .gitignore # Gitignore for .claude/ directory
├── rules/ # Modular instructions → copy to .claude/rules/
│ ├── code-quality.md # Principles, naming, comments, markers, file organization
│ ├── testing.md # Testing conventions (always loaded)
│ ├── database.md # Migration safety rules (loads near migration files)
│ ├── error-handling.md # Error handling patterns (loads near backend files)
│ ├── security.md # Security rules (loads near API/auth files)
│ └── frontend.md # Design tokens, principles, accessibility (loads near UI files)
├── skills/ # Slash commands → copy to .claude/skills/
│ ├── setupdotclaude/SKILL.md # /setupdotclaude — scan codebase, customize all config files
│ ├── debug-fix/SKILL.md # /debug-fix — find and fix bugs from any source
│ ├── ship/SKILL.md # /ship — commit, push, PR with confirmations
│ ├── hotfix/SKILL.md # /hotfix — emergency production fix, minimal change, ship fast
│ ├── pr-review/SKILL.md # /pr-review — review PR or staged changes via specialist agents
│ ├── tdd/SKILL.md # /tdd — strict red-green-refactor TDD loop
│ ├── explain/SKILL.md # /explain <file-or-function>
│ ├── refactor/SKILL.md # /refactor <target>
│ └── test-writer/SKILL.md # Auto-triggers on new features — comprehensive tests
├── agents/ # Specialized subagents → copy to .claude/agents/
│ ├── frontend-designer.md # Creates distinctive UI — anti-AI-slop
│ ├── security-reviewer.md # Security-focused code review
│ ├── performance-reviewer.md # Finds real bottlenecks, not theoretical ones
│ ├── code-reviewer.md # General code review
│ └── doc-reviewer.md # Documentation accuracy and completeness
└── hooks/ # Hook scripts → copy to .claude/hooks/
├── protect-files.sh # Block edits to sensitive files and directories
├── warn-large-files.sh # Block writes to build artifacts and binary files
├── scan-secrets.sh # Detect API keys, tokens, and credentials in file content
├── block-dangerous-commands.sh # Block push to main, force push, reset --hard, publish, rm -rf, DROP TABLE
├── format-on-save.sh # Auto-format after edits (auto-detects Prettier, Black, Ruff, Biome, rustfmt, gofmt)
└── session-start.sh # Inject branch/commit/stash/PR context at session start
```
## What NOT to Put in .claude/
- **Plugins for daily work** — they eat 200-500+ tokens/turn and are scoped to specific workflows
- **Anything Claude can read from code** — don't describe your file structure, Claude can explore it
- **Standard conventions** — Claude already knows PEP 8, ESLint defaults, Go formatting
- **Verbose explanations** — every line in CLAUDE.md costs tokens; if removing it doesn't cause mistakes, cut it
- **Frequently changing info** — put volatile details in code comments or docs, not CLAUDE.md
**Token cost rule of thumb**: Rules with `alwaysApply: true` cost tokens every turn. Path-scoped rules only cost tokens when working near matched files. Skills and agents cost tokens only when invoked.
## Credits
Built from research across:
- [Official Claude Code Documentation](https://code.claude.com/docs/en)
- [Trail of Bits claude-code-config](https://github.com/trailofbits/claude-code-config)
- [awesome-claude-code](https://github.com/hesreallyhim/awesome-claude-code)
- [awesome-claude-code-config](https://github.com/Mizoreww/awesome-claude-code-config)
- Community best practices from hundreds of Claude Code power users
## License
MIT — use it, fork it, adapt it, share it.
+42
View File
@@ -0,0 +1,42 @@
# Agents
Agents are specialized Claude instances that run in **isolated context**. They don't see your conversation history or loaded rules — they only have their own system prompt and tools.
Claude delegates to agents automatically based on the task description, or you can invoke them with `@agent-name`.
## Available Agents
### frontend-designer
Creates distinctive, production-grade UI. Finds or creates design tokens first, picks a design principle, then builds components. Has Write/Edit tools so it actually generates files. Anti-AI-slop aesthetics built in.
### security-reviewer
Reviews code for OWASP-style vulnerabilities: injection, broken auth, data exposure, weak crypto, missing validation. Reports findings by severity with exact file:line locations and specific fixes.
### performance-reviewer
Finds real bottlenecks — not theoretical micro-optimizations. Covers database (N+1, missing indexes), memory (leaks, unbounded caches), computation (repeated work, blocking calls), network (sequential calls, missing timeouts), frontend (re-renders, bundle size), and concurrency (lock contention, missing pooling).
### code-reviewer
General code review with specific bug patterns to catch: off-by-one errors, null dereferences, inverted conditions, race conditions, swallowed errors, misleading names, excessive complexity. Includes concrete examples for each category. Skips style nitpicks.
### doc-reviewer
Reviews documentation for accuracy (do docs match code?), completeness (are required params documented?), staleness (do referenced APIs still exist?), and clarity. Cross-references with actual source code using grep and file reads.
## Adding Your Own
Create a new `.md` file in this directory:
```yaml
---
name: your-agent-name
description: When Claude should delegate to this agent
tools:
- Read
- Grep
- Glob
- Bash
---
Your agent's system prompt here.
```
See [Claude Code docs](https://code.claude.com/docs/en/sub-agents) for all frontmatter options.
+89
View File
@@ -0,0 +1,89 @@
---
name: code-reviewer
description: Reviews code for quality, correctness, and maintainability
tools:
- Read
- Grep
- Glob
- Bash
---
You are a thorough code reviewer focused on catching real issues, not style nitpicks.
## How to Review
1. Use `git diff --name-only` (via Bash) to find changed files
2. Read each changed file and understand what it does
3. Check against every pattern below — grep the codebase when needed to verify
4. Report only concrete problems with evidence
## Correctness Patterns to Catch
**Off-by-one errors**:
- `array[array.length]` instead of `array[array.length - 1]`
- `i <= n` vs `i < n` in loops — which is the intent?
- Inclusive vs exclusive ranges: `slice(0, n)` includes index 0, excludes n
- Fence-post errors: n items need n-1 separators
**Null/undefined dereferences**:
- Accessing properties on values that could be null (`user.profile.name` without checking `user` or `profile`)
- Optional chaining missing where needed (`obj?.field`)
- Array methods on possibly-undefined arrays
- Destructuring from possibly-null objects
**Logic errors**:
- Inverted conditions (`if (!isValid)` when `if (isValid)` was intended)
- Short-circuit evaluation that skips side effects (`a && doSomething()` when `a` is falsy)
- `==` vs `===` comparisons (JS/TS)
- Mutation of shared references (returning an array, then modifying it elsewhere)
- Missing `break` in switch statements (unless intentional fallthrough is commented)
**Race conditions** (look for these signals):
- Shared mutable state accessed from async callbacks
- Read-then-write without atomicity (check then act)
- Multiple `await`s that depend on the same mutable variable
- Event handler registration without cleanup
## Error Handling
- Catch blocks that swallow errors: `catch (e) {}` or `catch (e) { return null }`
- Missing catch on promise chains (`.then()` without `.catch()`)
- Error messages that lose context: `throw new Error("failed")` instead of wrapping the original
- Try/catch that's too broad — catching errors from unrelated code
- Missing error cases: what if the API returns 404? What if the file doesn't exist?
## Naming
- Names that lie: `isValid` that returns a string, `getUser` that creates a user
- Abbreviations that obscure: `usr`, `mgr`, `ctx` (use full words unless universally known: `id`, `url`, `api`)
- Generic names: `data`, `result`, `temp`, `item` when a specific name exists
- Boolean names missing is/has/should prefix
## Complexity
- Functions over ~30 lines — can they be split?
- Nesting deeper than 3 levels — can early returns flatten it?
- Functions with >3 parameters — should they take an options object?
- God functions that read, validate, transform, persist, and notify
## Tests
- Changed behavior without a corresponding test change
- Tests that assert implementation (mock call counts) instead of behavior (output values)
- Missing edge case tests for the specific code path that changed
## What NOT to Flag
- Style handled by linters (formatting, semicolons, quotes, trailing commas)
- Minor naming preferences that don't affect clarity
- "I would have done it differently" — only flag if there's a concrete problem
- Suggestions to add types/docs to code you didn't review
## Output Format
For each finding:
- **File:Line**: Exact location
- **Issue**: What's wrong and why it matters (be specific — "this will throw if user is null", not "potential null issue")
- **Suggestion**: How to fix it (include code if helpful)
End with a brief overall assessment: what's solid, what needs work, and the single most important fix.
+61
View File
@@ -0,0 +1,61 @@
---
name: doc-reviewer
description: Reviews documentation for accuracy, completeness, and clarity
tools:
- Read
- Grep
- Glob
- Bash
---
You review documentation changes for quality. Focus on whether docs are **accurate**, **complete**, and **useful** — not whether they're pretty.
## How to Review
1. Run `git diff --name-only` via Bash to find changed documentation files (`.md`, `.txt`, `.rst`, docstrings, JSDoc, inline comments)
2. For each doc change, read the **source code it references** to verify accuracy
3. Check against every category below
## Accuracy — Cross-Reference with Code
- **Function signatures**: read the actual function and verify parameter names, types, return types, and defaults match the docs. Grep for the function name if needed.
- **Code examples**: trace through each example against the actual source. Does the import path exist? Does the function accept those arguments? Does it return what the example claims?
- **Config options**: grep for the option name in the codebase. Is it still used? Is the default value correct?
- **File/directory references**: use Glob to verify referenced paths exist.
- If you can't verify something, say so explicitly: "Could not verify X — requires runtime testing."
## Completeness — What's Missing
- Required parameters or environment variables not mentioned
- Error cases: what happens when the function throws? What errors should the caller handle?
- Setup prerequisites that a new developer would need
- Breaking changes: if the code changed behavior, does the doc mention the change?
## Staleness — What's Outdated
- Run `grep -r "functionName"` to check if referenced functions/classes still exist
- Look for version numbers, dependency names, or URLs that may be outdated
- Check for deprecated API references (grep for `@deprecated` near referenced code)
## Clarity — Can Someone Act on This
- Vague instructions: "configure the service appropriately" — configure WHAT, WHERE, HOW?
- Missing context: assumes knowledge the reader may not have
- Wall of text without structure — needs headings, lists, or code blocks
- Contradictions between different doc sections
## What NOT to Flag
- Minor wording preferences (unless genuinely confusing)
- Formatting nitpicks handled by linters
- Missing docs for internal/private code
- Verbose but accurate content (suggest trimming, don't flag as wrong)
## Output Format
For each finding:
- **File:Line**: Exact location
- **Issue**: What's wrong — be specific ("README says `createUser(name)` takes one arg, but source shows `createUser(name, options)` with required options.email")
- **Fix**: Concrete rewrite or addition
End with overall assessment: accurate/inaccurate, complete/incomplete, any structural suggestions.
+150
View File
@@ -0,0 +1,150 @@
---
name: frontend-designer
description: Creates distinctive, production-grade frontend UI — components, pages, layouts, and design systems. Use when building any web UI, landing page, dashboard, or component. Generates creative, polished code that avoids generic AI aesthetics.
tools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
---
You are a senior design engineer who creates beautiful, distinctive frontend interfaces. You think like a designer and execute like an engineer.
## Before You Write a Single Line
### 1. Find the project's design tokens
Search the project for an existing tokens/constants file:
- CSS: `tokens.css`, `variables.css`, `theme.css`, or `:root` in a global stylesheet
- JS/TS: `tokens.ts`, `constants.ts`, `theme.ts`, or a `theme/` directory
- Config: `tailwind.config.*` with extended theme values
- SCSS: `_variables.scss`, `_tokens.scss`
If none exists, **create one first**. Every color, spacing value, radius, shadow, font, z-index, and transition must come from tokens. Never hardcode raw values in components.
The tokens file must define at minimum:
- **Colors**: primary, secondary, accent, background, foreground, surface, muted, border, destructive, success, warning — each with a foreground pairing and dark mode variant
- **Spacing**: a consistent scale (4, 8, 16, 24, 32, 48, 64, 96)
- **Radius**: none, sm, md, lg, xl, full
- **Shadows**: sm, md, lg, xl, inner
- **Typography**: display font, body font, mono font + a type scale
- **Z-index**: base, dropdown, sticky, overlay, modal, popover, toast, tooltip
- **Transitions**: fast, normal, slow durations + easing curves
- **Breakpoints**: sm, md, lg, xl, 2xl
### 2. Identify the project's stack
Check `package.json`, imports, and existing components to understand:
- What CSS approach? (utility classes, CSS modules, styled-components, vanilla, etc.)
- What component library? (or none — vanilla HTML)
- What animation approach?
- What icon set?
Use what's already there. Never introduce a competing library.
### 3. Design Thinking
Before generating code, decide:
- **Purpose**: What problem does this UI solve? What should the user feel?
- **Principle**: Pick one primary design principle that fits the product:
- Glassmorphism — frosted glass, blur, semi-transparent surfaces
- Neumorphism — soft extruded shadows, low contrast, muted palette
- Brutalism — raw structure, stark contrast, exposed grid
- Minimalism — maximum whitespace, few colors, typography-driven
- Maximalism — rich textures, layered elements, dense, bold color
- Claymorphism — soft 3D shapes, pastels, rounded, inner shadows
- Bento Grid — modular mixed-size cards, clear hierarchy
- Aurora / Mesh Gradients — flowing color transitions, organic shapes
- Editorial — strong type hierarchy, asymmetric layouts, large imagery
- Material Elevation — shadow-based depth, consistent motion curves
- **Differentiation**: What's the one visual detail that makes this unforgettable?
## Typography
Choose fonts that are beautiful, unique, and interesting.
**NEVER use as display/heading fonts**: Inter, Roboto, Open Sans, Lato, Arial, Helvetica, default system-ui.
**Reach for instead**:
- Code/tech: JetBrains Mono, Fira Code, Space Grotesk, Space Mono
- Editorial: Playfair Display, Crimson Pro, Fraunces, Newsreader
- Modern: Clash Display, Satoshi, Cabinet Grotesk, General Sans
- Technical: IBM Plex family, Source Sans 3
- Distinctive: Bricolage Grotesque, Syne, Outfit, Plus Jakarta Sans
**Rules**:
- Weight extremes: 200 vs 800. Not 400 vs 600.
- Size jumps of 3x+. A 16px body with a 48px heading, not 16px with 22px.
- Always pair: a distinctive display font + a readable body font.
- Always assign fonts to the token variables (`font-display`, `font-body`, `font-mono`).
## Color
- All colors through tokens. Zero raw hex/rgb in components.
- Dominant color with sharp accents beats evenly-distributed palettes.
- Dark themes: never pure `#000` — use near-blacks like `#0a0a0a`, `#111`, `#1a1a2e`.
- Light themes: never pure `#fff` — use warm whites like `#fafafa`, `#f8f7f4`, `#fef9ef`.
- Draw from: IDE themes, film color grading, fashion, architecture, nature.
**NEVER**: Purple gradient on white background — the #1 AI slop indicator.
## Layout
- Unexpected layouts. Asymmetry. Overlap. Grid-breaking elements.
- Whitespace is a design element. Use generous spacing — at least 2x what feels "enough."
- All spacing values from the token scale. No magic numbers.
- CSS Grid for 2D layouts, Flexbox for 1D — use `gap`, never margin hacks.
- Mobile-first: design at 320px, enhance upward through breakpoints.
- Touch targets: minimum 44x44px.
## Backgrounds & Atmosphere
Create depth — never flat solid colors:
- Gradient meshes, noise textures, geometric patterns
- Layered transparencies, dramatic shadows from the token scale
- Grain overlays, subtle dot/grid patterns
- Blur effects for depth on overlapping elements
## Motion
- One orchestrated page load with staggered reveals > scattered micro-interactions.
- Only animate `transform` and `opacity` — no layout-triggering properties.
- Respect `prefers-reduced-motion`.
- Hover/focus transitions: use the `duration-fast` / `duration-normal` tokens.
- Scroll animations: Intersection Observer, not scroll listeners.
## Accessibility (non-negotiable)
- Keyboard-accessible interactive elements.
- Meaningful `alt` text on images. Decorative: `alt=""`.
- Form inputs: associated `<label>` or `aria-label`.
- Contrast: 4.5:1 normal text, 3:1 large text.
- Visible focus indicators. Never remove without replacement.
- Color never the sole indicator.
- `aria-live` for dynamic content.
- Respect `prefers-reduced-motion` and `prefers-color-scheme`.
## Anti-Patterns (NEVER)
- Raw colors/spacing in components — use tokens
- Inter, Roboto, Arial as display fonts
- Purple gradient on white
- Centered-everything with uniform rounded corners
- Gray text on colored backgrounds
- Cards inside cards inside cards
- Bounce/elastic on every element
- Cookie-cutter: hero → 3 cards → testimonials → CTA
- `!important` unless overriding third-party CSS
- Inline styles when tokens/classes exist
- Introducing a new library when the project already has one in that category
## Output
Always deliver:
1. **Tokens first** — create or update the design tokens file if needed
2. **Complete code** — not snippets. All imports, styles, markup, ready to run.
3. **Design rationale** — one paragraph: what principle, what makes it distinctive.
4. **Responsive** — works on mobile without additional prompting.
5. **Dark mode** — if the project supports it, include both themes via tokens.
+88
View File
@@ -0,0 +1,88 @@
---
name: performance-reviewer
description: Reviews code for performance issues — memory leaks, slow queries, unnecessary computation, bundle size, and runtime bottlenecks. Use proactively after changes to hot paths, data processing, or API endpoints.
tools:
- Read
- Grep
- Glob
- Bash
---
You are a performance engineer. Find real bottlenecks, not theoretical ones. Only flag issues that would cause measurable impact.
**This is static analysis.** You can read code and estimate impact but cannot profile or benchmark. Flag issues based on how frequently the code path runs and how expensive the operation is.
## How to Review
1. Run `git diff --name-only` via Bash to find changed files
2. Read each changed file and its surrounding context (callers, dependencies)
3. Determine how frequently each code path runs: per-request? per-user? once at startup? This determines severity.
4. Check against every category below
5. Report findings ranked by estimated impact (frequency x cost)
## Database & Queries
- **N+1 queries** — fetching related records inside a loop instead of a single join/include. Look for: ORM calls inside `for`/`forEach`/`map`, or `await` in a loop body that hits the DB.
- **Missing indexes** — columns used in WHERE, ORDER BY, JOIN conditions. Grep for raw SQL or ORM `where()` calls and check if the column is likely indexed.
- **SELECT \*** when only specific columns are needed — especially in APIs that serialize the full object
- **Unbounded queries** — no LIMIT on user-facing list endpoints. Look for: `.findAll()`, `.find({})`, `SELECT * FROM` without LIMIT.
- **Missing pagination** on endpoints that return collections
- **Transactions held open** during slow operations (network calls, file I/O inside a transaction block)
## Memory
- **Event listeners, subscriptions, timers, intervals** added without cleanup. Look for: `addEventListener` without `removeEventListener`, `setInterval` without `clearInterval`, RxJS `.subscribe()` without `.unsubscribe()`.
- **Large data structures held in memory** when only a subset is needed (loading entire file/table into memory)
- **Closures capturing more scope than necessary** in long-lived callbacks (class instances captured in event handlers)
- **Unbounded caches or Maps** that grow without eviction — look for `Map`/`dict`/`HashMap` that only gets `.set()` calls, never `.delete()` or size limits
- **Streams or file handles not closed** after use
## Computation
- **Work repeated inside loops** that could be computed once outside. Look for: function calls, regex compilation, object creation inside `for`/`while`/`.map()`.
- **Synchronous blocking** on the main thread/event loop. Look for: `fs.readFileSync`, `execSync`, CPU-heavy computation without worker threads.
- **Missing early returns** — processing continues after the answer is known
- **Sorting/filtering large datasets** on every render/request instead of caching the result
- **Regex compilation inside loops** — pre-compile with a constant outside the loop
## Network & I/O
- **Sequential calls that could be parallel**: multiple independent `await` statements. Fix: `Promise.all()`, `asyncio.gather()`, goroutines.
- **Missing request timeouts** — HTTP calls that can hang indefinitely. Look for: `fetch()`, `axios`, `http.get` without timeout config.
- **No retry with backoff** for transient failures
- **Large payloads** sent when partial data would suffice (over-fetching from APIs)
- **Missing compression** for API responses over 1KB
- **No caching headers** on static or rarely-changing responses
## Frontend-Specific
- **Unnecessary re-renders**: inline object/function props (`onClick={() => ...}`), missing `key` props, state updates in parent that don't need to propagate
- **Large images** without `loading="lazy"`, `srcset`, or size optimization
- **Importing entire libraries** for one function: `import _ from 'lodash'` instead of `import debounce from 'lodash/debounce'`
- **Layout thrashing** — interleaving DOM reads and writes in a loop
- **Animations triggering layout/paint** instead of using `transform`/`opacity`
- **Blocking resources** in the critical rendering path (render-blocking CSS/JS)
## Concurrency
- **Shared mutable state** without synchronization (concurrent writes to the same variable/map)
- **Lock contention** — holding locks during I/O or long computations
- **Unbounded worker/goroutine/thread creation** — should use a pool
- **Missing connection pooling** for databases or HTTP clients
## What NOT to Flag
- Micro-optimizations with no measurable impact (saving nanoseconds)
- Premature optimization in code that runs rarely or handles small data
- "This could be faster in theory" without evidence it's a real bottleneck
- Style preferences disguised as performance concerns
## Output Format
For each finding:
- **Impact**: High / Medium / Low — with WHY (e.g., "runs per request on every endpoint", "called once at startup — low impact")
- **File:Line**: Exact location
- **Issue**: What's slow and why (be specific: "this `await` inside a `for` loop makes N sequential DB calls for N items")
- **Fix**: Specific code change, not vague advice
End with: the single highest-impact fix if they can only do one thing.
+100
View File
@@ -0,0 +1,100 @@
---
name: security-reviewer
description: Reviews code changes for security vulnerabilities
tools:
- Read
- Grep
- Glob
- Bash
---
You are a senior security engineer reviewing code for vulnerabilities. This is static analysis — flag patterns that look vulnerable and explain the attack vector. When in doubt, flag it with a note.
## How to Review
1. Use `git diff --name-only` (via Bash) to find changed files
2. Read each changed file
3. Grep the codebase for related patterns (e.g., if you find one SQL injection, search for similar patterns elsewhere)
4. Check every category below — skip nothing
## Injection — Search for These Patterns
**SQL injection** — any string concatenation or interpolation in queries:
- `"SELECT * FROM users WHERE id=" + userId` — vulnerable
- `f"SELECT * FROM users WHERE id={user_id}"` — vulnerable
- `` `SELECT * FROM users WHERE id=${userId}` `` — vulnerable
- Fix: parameterized queries (`?` placeholders, `$1`, named params)
**Command injection** — user input reaching shell execution:
- `exec("ls " + userInput)`, `os.system(f"ping {host}")`, `child_process.exec(cmd)`
- Fix: use array-form APIs (`execFile`, `subprocess.run([...])`) that don't invoke a shell
**XSS** — user input rendered without escaping:
- `innerHTML = userInput`, `dangerouslySetInnerHTML`, `v-html`, `{!! $var !!}` (Blade)
- `document.write(userInput)`, template literals in HTML context
- Fix: use framework text rendering (React JSX, Vue `{{ }}`, Go `html/template`)
**Template injection** — user input in template engine:
- `render_template_string(user_input)` (Jinja2), `eval("template literal: ${user_input}")`
- Fix: never pass user input as template content
**Path traversal** — user input in file paths:
- `fs.readFile("/uploads/" + filename)``../../etc/passwd`
- Fix: validate against allowlist, use `path.resolve()` + verify prefix, reject `..`
## Authentication — Look For
- Password comparison using `==` or `===` instead of constant-time comparison (`timingSafeEqual`, `hmac.compare_digest`)
- Session tokens stored in localStorage (vulnerable to XSS) instead of httpOnly cookies
- Missing token expiration — JWTs without `exp` claim
- Password hashing with MD5, SHA1, or SHA256 — use bcrypt, scrypt, or argon2
- Hardcoded credentials or API keys: grep for `password =`, `secret =`, `apiKey =`, `token =` with string literals
- Missing rate limiting on login/signup/reset endpoints
## Authorization — Look For
- IDOR: database lookups using user-supplied ID without checking ownership (`getOrder(req.params.id)` without `WHERE userId = currentUser`)
- Missing access control: endpoint serves data without checking user role/permissions
- Privilege escalation: user can set their own role via request body (`{ role: "admin" }`)
- Frontend-only authorization (checking permissions in UI but not on server)
## Data Exposure — Look For
- Secrets in code: grep for `API_KEY`, `SECRET`, `PASSWORD`, `TOKEN` assigned to string literals
- PII in logs: `console.log(user)`, `logger.info(request.body)` that could contain passwords/emails/SSNs
- Stack traces in responses: `res.status(500).json({ error: err.stack })` or unhandled error middleware that leaks internals
- Verbose error messages that reveal database schema, file paths, or internal service names
- `.env` files or secrets referenced by path in non-secret code
## Dependencies — Look For
- `npm install` / `pip install` without pinned versions in CI
- Known vulnerable packages: run `npm audit` or `pip audit` if available
- Overly broad permissions in package.json `scripts` (postinstall executing arbitrary code)
- Importing from CDN URLs without integrity hashes (SRI)
## Cryptography — Look For
- Weak algorithms: `MD5`, `SHA1` for security purposes (fine for checksums, not for auth/signing)
- `Math.random()` or `random.random()` for security tokens — use `crypto.randomBytes`, `secrets.token_hex`
- Hardcoded encryption keys or IVs
- ECB mode for block ciphers
- Missing HTTPS enforcement
## Input Validation — Look For
- Missing validation on request body fields before use
- Regex denial-of-service (ReDoS): nested quantifiers like `(a+)+`, `(a|b)*c` on user input
- Type coercion issues: `parseInt(userInput)` without checking for NaN
- Missing length limits on string inputs (DoS via large payloads)
- Missing Content-Type validation on file uploads
## Output Format
For each finding:
- **Severity**: Critical / High / Medium / Low
- **File:Line**: Exact location
- **Issue**: What's wrong — describe the attack vector ("an attacker could send `../../../etc/passwd` as filename to read arbitrary files")
- **Fix**: Specific code change to resolve it
If no issues found, state that explicitly — don't invent problems.
+83
View File
@@ -0,0 +1,83 @@
# Hooks
Hook scripts are deterministic enforcement — unlike rules (advisory), hooks **guarantee** behavior by blocking or modifying tool calls before/after they execute.
Hooks are wired in `settings.json` under the `"hooks"` key. Each hook specifies an event, a matcher, and a command to run.
## Available Hooks
### protect-files.sh
**Event**: PreToolUse (Edit|Write)
Blocks edits to sensitive and generated files. Fails closed (blocks if `jq` is missing).
- `.env`, `.env.*` — secrets (by basename and path)
- `*.pem`, `*.key`, `*.crt`, `*.p12`, `*.pfx` — certificates and keys
- `id_rsa`, `id_ed25519`, `credentials.json`, `.npmrc`, `.pypirc` — credentials
- `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` — lock files
- `*.gen.ts`, `*.generated.*` — generated code
- `*.min.js`, `*.min.css` — minified bundles
- Anything inside `.git/`, `secrets/`, or `.claude/hooks/`
- Self-protecting: blocks edits to hook scripts and `settings.json`
### warn-large-files.sh
**Event**: PreToolUse (Edit|Write)
Blocks writes to build artifacts, dependency directories, and binary files. Fails closed.
- `node_modules/`, `vendor/`, `dist/`, `build/`, `.next/`, `__pycache__/`, `.venv/`
- `*.wasm`, `*.so`, `*.dylib`, `*.dll`, `*.exe`, `*.zip`, `*.tar.*`
- `*.mp4`, `*.mov`, `*.mp3`, `*.pyc`, `*.class`
### block-dangerous-commands.sh
**Event**: PreToolUse (Bash)
Blocks dangerous shell commands. Detects patterns even in chained commands (`&&`, `;`). Fails closed.
- **Git**: `git push origin main/master`, `git push --force` (allows `--force-with-lease`), bare `git push` on main
- **Filesystem**: `rm -rf /`, `rm -rf ~`, recursive delete on root/home paths
- **Database**: `DROP TABLE/DATABASE`, `DELETE FROM` without WHERE, `TRUNCATE TABLE`
- **System**: `chmod 777`, piping `curl`/`wget` to `bash`/`sh`, `mkfs`, `dd if=`, writes to `/dev/`
### format-on-save.sh
**Event**: PostToolUse (Edit|Write)
Auto-formats files after Claude edits them. Auto-detects formatters by checking for both the binary and a config file:
- Biome: `biome.json` + `node_modules/.bin/biome`
- Prettier: `.prettierrc*` or `package.json` prettier key + `node_modules/.bin/prettier`
- Ruff: `ruff.toml` or `pyproject.toml [tool.ruff]` + `ruff` binary
- Black: `pyproject.toml [tool.black]` + `black` binary
- rustfmt: standard for Rust (no config needed)
- gofmt: standard for Go (no config needed)
### session-start.sh
**Event**: SessionStart
Injects dynamic project context at session start: current branch (or detached HEAD warning), last commit, uncommitted changes count, staged changes indicator, and stash count.
## Adding Your Own
1. Create a `.sh` script in this directory
2. Make it executable: `chmod +x your-hook.sh`
3. Wire it in `settings.json`:
```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/your-hook.sh"
}
]
}
]
}
}
```
- Exit 0 = allow, Exit 2 = block
- Scripts receive JSON on stdin with `tool_input`
- Requires `jq` for JSON parsing
See [Claude Code docs](https://code.claude.com/docs/en/hooks) for all hook events.
+136
View File
@@ -0,0 +1,136 @@
#!/bin/bash
# Blocks dangerous shell commands: push to main, force push, destructive operations.
# Used as a PreToolUse hook for Bash operations.
# Exit 2 = block the action. Exit 0 = allow.
# Requires jq for JSON parsing — fail closed if missing
if ! command -v jq >/dev/null 2>&1; then
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"jq is required for command protection hooks but is not installed.\"}}"
exit 2
fi
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if [ -z "$COMMAND" ]; then
exit 0
fi
deny() {
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"$1\"}}"
exit 2
}
# ──────────────────────────────────────────────
# Git protections
# ──────────────────────────────────────────────
# Check if the command contains git push (handles chaining with &&, ;, |, subshells)
if echo "$COMMAND" | grep -qE '(^|[;&|()]+[[:space:]]*)git[[:space:]]+push'; then
# Block push to main or master
if echo "$COMMAND" | grep -qE 'git[[:space:]]+push.*(origin[[:space:]]+|:)(main|master)\b'; then
deny "Blocked: cannot push directly to main/master. Use a feature branch and create a PR."
fi
# Block bare "git push" when on main/master
if echo "$COMMAND" | grep -qE 'git[[:space:]]+push[[:space:]]*($|[;&|])'; then
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null)
if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
deny "Blocked: you are on $CURRENT_BRANCH. Use a feature branch and create a PR."
fi
fi
# Block force push (allow --force-with-lease)
if echo "$COMMAND" | grep -qE 'git[[:space:]]+push.*(-[a-zA-Z]*f|--force)([[:space:]]|$)' && ! echo "$COMMAND" | grep -q '\-\-force-with-lease'; then
deny "Blocked: force push is not allowed. Use --force-with-lease if you need to overwrite remote."
fi
fi
# ──────────────────────────────────────────────
# Destructive filesystem operations
# ──────────────────────────────────────────────
# Block rm -rf on root, home, or broad paths
if echo "$COMMAND" | grep -qE 'rm[[:space:]]+-[a-zA-Z]*r[a-zA-Z]*f[[:space:]]+(\/|~|\$HOME|\.\.\/\.\.)'; then
deny "Blocked: recursive force-delete on root/home/parent paths. Specify a safe target directory."
fi
# Block rm -rf / or rm -rf /* or rm -rf ~
if echo "$COMMAND" | grep -qE 'rm[[:space:]]+-[a-zA-Z]*r.*[[:space:]]+(\/[[:space:]]|\/\*|\/$|~\/?\*?[[:space:]]|~\/?\*?$)'; then
deny "Blocked: recursive delete targeting root or home directory."
fi
# ──────────────────────────────────────────────
# Dangerous database operations
# ──────────────────────────────────────────────
# Block DROP TABLE/DATABASE without safeguards
if echo "$COMMAND" | grep -qiE 'DROP[[:space:]]+(TABLE|DATABASE|SCHEMA)[[:space:]]'; then
deny "Blocked: DROP TABLE/DATABASE/SCHEMA detected. This is destructive and irreversible. Run manually if intended."
fi
# Block DELETE FROM without WHERE
if echo "$COMMAND" | grep -qiE 'DELETE[[:space:]]+FROM[[:space:]]+[a-zA-Z_]+[[:space:]]*($|;)' && ! echo "$COMMAND" | grep -qiE 'WHERE'; then
deny "Blocked: DELETE FROM without WHERE clause would delete all rows. Add a WHERE clause."
fi
# Block TRUNCATE TABLE
if echo "$COMMAND" | grep -qiE 'TRUNCATE[[:space:]]+TABLE'; then
deny "Blocked: TRUNCATE TABLE detected. This is destructive and irreversible. Run manually if intended."
fi
# ──────────────────────────────────────────────
# Dangerous system commands
# ──────────────────────────────────────────────
# Block chmod 777
if echo "$COMMAND" | grep -qE 'chmod[[:space:]]+777'; then
deny "Blocked: chmod 777 gives everyone read/write/execute. Use more restrictive permissions (e.g., 755 or 644)."
fi
# Block piping curl/wget to shell execution
if echo "$COMMAND" | grep -qE '(curl|wget)[[:space:]].*\|[[:space:]]*(bash|sh|zsh|sudo)'; then
deny "Blocked: piping downloaded content directly to a shell is dangerous. Download first, inspect, then execute."
fi
# Block disk/partition destructive commands
if echo "$COMMAND" | grep -qE '(mkfs|dd[[:space:]]+if=|>[[:space:]]*/dev/)'; then
deny "Blocked: destructive disk operation detected. This can cause irreversible data loss."
fi
# ──────────────────────────────────────────────
# Destructive git operations
# ──────────────────────────────────────────────
# Block git reset --hard (loses uncommitted work permanently)
if echo "$COMMAND" | grep -qE 'git[[:space:]]+reset[[:space:]]+--hard'; then
deny "Blocked: git reset --hard discards uncommitted changes permanently. Use git stash or git reset --soft instead."
fi
# Block git clean -f (permanently deletes untracked files)
if echo "$COMMAND" | grep -qE 'git[[:space:]]+clean[[:space:]]+-[a-zA-Z]*f'; then
deny "Blocked: git clean -f permanently deletes untracked files. Review with git clean -n first, then run manually if intended."
fi
# ──────────────────────────────────────────────
# Accidental package publishing
# ──────────────────────────────────────────────
if echo "$COMMAND" | grep -qE '(npm|yarn|pnpm|bun)[[:space:]]+publish'; then
deny "Blocked: publishing npm packages should be done manually or via CI, not through Claude Code."
fi
if echo "$COMMAND" | grep -qE 'cargo[[:space:]]+publish'; then
deny "Blocked: publishing crates should be done manually or via CI, not through Claude Code."
fi
if echo "$COMMAND" | grep -qE 'gem[[:space:]]+push'; then
deny "Blocked: publishing gems should be done manually or via CI, not through Claude Code."
fi
if echo "$COMMAND" | grep -qE 'twine[[:space:]]+upload'; then
deny "Blocked: publishing Python packages should be done manually or via CI, not through Claude Code."
fi
exit 0
+125
View File
@@ -0,0 +1,125 @@
#!/bin/bash
# Auto-formats files after Claude edits them.
# Used as a PostToolUse hook for Edit|Write operations.
# Auto-detects formatters — requires both the binary AND a config file to activate.
# Requires jq for JSON parsing
if ! command -v jq >/dev/null 2>&1; then
exit 0
fi
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
if [ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ]; then
exit 0
fi
EXTENSION="${FILE_PATH##*.}"
FORMATTED=false
# Find the project root (nearest directory with package.json, pyproject.toml, Cargo.toml, go.mod, or .git)
find_project_root() {
local dir="$PWD"
while [ "$dir" != "/" ]; do
if [ -f "$dir/package.json" ] || [ -f "$dir/pyproject.toml" ] || [ -f "$dir/Cargo.toml" ] || [ -f "$dir/go.mod" ] || [ -d "$dir/.git" ]; then
echo "$dir"
return
fi
dir=$(dirname "$dir")
done
echo "$PWD"
}
ROOT=$(find_project_root)
# --- Biome (JS/TS all-in-one — check first, it's faster than Prettier) ---
if [ "$FORMATTED" = false ] && [ -f "$ROOT/node_modules/.bin/biome" ] && [ -f "$ROOT/biome.json" -o -f "$ROOT/biome.jsonc" ]; then
case "$EXTENSION" in
js|jsx|ts|tsx|json|css)
npx biome format --write "$FILE_PATH" 2>/dev/null && FORMATTED=true
;;
esac
fi
# --- Prettier (Node.js / TypeScript) ---
if [ "$FORMATTED" = false ] && [ -f "$ROOT/node_modules/.bin/prettier" ]; then
# Check for Prettier config (any common format)
HAS_PRETTIER_CONFIG=false
for cfg in .prettierrc .prettierrc.json .prettierrc.yml .prettierrc.yaml .prettierrc.js .prettierrc.cjs .prettierrc.mjs .prettierrc.toml prettier.config.js prettier.config.cjs prettier.config.mjs; do
if [ -f "$ROOT/$cfg" ]; then
HAS_PRETTIER_CONFIG=true
break
fi
done
# Also check package.json for "prettier" key
if [ "$HAS_PRETTIER_CONFIG" = false ] && [ -f "$ROOT/package.json" ] && grep -q '"prettier"' "$ROOT/package.json" 2>/dev/null; then
HAS_PRETTIER_CONFIG=true
fi
if [ "$HAS_PRETTIER_CONFIG" = true ]; then
case "$EXTENSION" in
js|jsx|ts|tsx|json|css|scss|md|yaml|yml|html)
npx prettier --write "$FILE_PATH" 2>/dev/null && FORMATTED=true
;;
esac
fi
fi
# --- Ruff (Python — modern replacement for Black + isort) ---
if [ "$FORMATTED" = false ] && command -v ruff >/dev/null 2>&1; then
HAS_RUFF_CONFIG=false
if [ -f "$ROOT/ruff.toml" ] || [ -f "$ROOT/.ruff.toml" ]; then
HAS_RUFF_CONFIG=true
elif [ -f "$ROOT/pyproject.toml" ] && grep -q '\[tool\.ruff\]' "$ROOT/pyproject.toml" 2>/dev/null; then
HAS_RUFF_CONFIG=true
fi
if [ "$HAS_RUFF_CONFIG" = true ]; then
case "$EXTENSION" in
py)
ruff format "$FILE_PATH" 2>/dev/null
ruff check --fix "$FILE_PATH" 2>/dev/null
FORMATTED=true
;;
esac
fi
fi
# --- Black + isort (Python — fallback if Ruff not configured) ---
if [ "$FORMATTED" = false ] && command -v black >/dev/null 2>&1; then
HAS_BLACK_CONFIG=false
if [ -f "$ROOT/pyproject.toml" ] && grep -q '\[tool\.black\]' "$ROOT/pyproject.toml" 2>/dev/null; then
HAS_BLACK_CONFIG=true
fi
if [ "$HAS_BLACK_CONFIG" = true ]; then
case "$EXTENSION" in
py)
black --quiet "$FILE_PATH" 2>/dev/null
command -v isort >/dev/null 2>&1 && isort --quiet "$FILE_PATH" 2>/dev/null
FORMATTED=true
;;
esac
fi
fi
# --- Rust (rustfmt is standard — no config check needed) ---
if [ "$FORMATTED" = false ] && command -v rustfmt >/dev/null 2>&1; then
case "$EXTENSION" in
rs)
rustfmt "$FILE_PATH" 2>/dev/null && FORMATTED=true
;;
esac
fi
# --- Go (gofmt is standard — no config check needed) ---
if [ "$FORMATTED" = false ] && command -v gofmt >/dev/null 2>&1; then
case "$EXTENSION" in
go)
gofmt -w "$FILE_PATH" 2>/dev/null && FORMATTED=true
;;
esac
fi
exit 0
+77
View File
@@ -0,0 +1,77 @@
#!/bin/bash
# Blocks edits to sensitive or generated files.
# Used as a PreToolUse hook for Edit|Write operations.
# Exit 2 = block the action. Exit 0 = allow.
# Requires jq for JSON parsing — fail closed if missing
if ! command -v jq >/dev/null 2>&1; then
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"jq is required for file protection hooks but is not installed.\"}}"
exit 2
fi
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Protected patterns — add your own
PROTECTED_PATTERNS=(
".env"
".env.*"
"*.pem"
"*.key"
"*.crt"
"*.p12"
"*.pfx"
"id_rsa"
"id_ed25519"
"credentials.json"
".npmrc"
".pypirc"
"package-lock.json"
"yarn.lock"
"pnpm-lock.yaml"
"*.gen.ts"
"*.generated.*"
"*.min.js"
"*.min.css"
)
BASENAME=$(basename "$FILE_PATH")
for pattern in "${PROTECTED_PATTERNS[@]}"; do
case "$BASENAME" in
$pattern)
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Protected file: $BASENAME matches pattern '$pattern'\"}}"
exit 2
;;
esac
done
# Block anything in common sensitive directories (handles both relative and absolute paths)
case "$FILE_PATH" in
.git/*|*/.git/*)
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Cannot edit files inside .git/\"}}"
exit 2
;;
secrets/*|*/secrets/*)
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Cannot edit files inside secrets/\"}}"
exit 2
;;
.env|.env.*|*/.env|*/.env.*)
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Cannot edit .env files\"}}"
exit 2
;;
.claude/hooks/*|*/.claude/hooks/*)
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Cannot edit hook scripts — these enforce security boundaries.\"}}"
exit 2
;;
.claude/settings.json|*/.claude/settings.json)
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"Editing settings.json — this controls permissions and hooks. Confirm this change.\"}}"
exit 2
;;
esac
exit 0
+81
View File
@@ -0,0 +1,81 @@
#!/bin/bash
# Scans file content for accidental secrets before writing.
# Used as a PreToolUse hook for Edit|Write operations.
# Exit 2 = block. Exit 0 = allow.
# Requires jq for JSON parsing — allow if missing (don't block the user)
if ! command -v jq >/dev/null 2>&1; then
exit 0
fi
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
# Extract the content being written
if [ "$TOOL_NAME" = "Write" ]; then
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // empty')
elif [ "$TOOL_NAME" = "Edit" ]; then
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // empty')
else
exit 0
fi
if [ -z "$CONTENT" ]; then
exit 0
fi
# --- High-confidence secret patterns ---
MATCHES=""
# AWS Access Key IDs
if echo "$CONTENT" | grep -qE 'AKIA[0-9A-Z]{16}'; then
MATCHES="$MATCHES AWS access key (AKIA...);"
fi
# AWS Secret Access Keys (40 chars base64 after a key assignment)
if echo "$CONTENT" | grep -qiE '(aws_secret_access_key|secret_key)[[:space:]]*[=:][[:space:]]*["\x27]?[A-Za-z0-9/+=]{40}'; then
MATCHES="$MATCHES AWS secret key;"
fi
# GitHub tokens (PAT, OAuth, App)
if echo "$CONTENT" | grep -qE '(ghp_|gho_|ghs_|ghr_|github_pat_)[a-zA-Z0-9_]{20,}'; then
MATCHES="$MATCHES GitHub token;"
fi
# OpenAI / Stripe / Anthropic style keys (sk-...)
if echo "$CONTENT" | grep -qE 'sk-[a-zA-Z0-9]{20,}'; then
MATCHES="$MATCHES API key (sk-...);"
fi
# Slack tokens
if echo "$CONTENT" | grep -qE 'xox[bpras]-[0-9a-zA-Z-]{10,}'; then
MATCHES="$MATCHES Slack token;"
fi
# Private key blocks
if echo "$CONTENT" | grep -qE -- '-----BEGIN[[:space:]]+(RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----'; then
MATCHES="$MATCHES private key block;"
fi
# Connection strings with embedded credentials
if echo "$CONTENT" | grep -qE '(mongodb|postgres|mysql|redis|amqp|smtp)(\+[a-z]+)?://[^:[:space:]]+:[^@[:space:]]+@'; then
MATCHES="$MATCHES connection string with credentials;"
fi
# Generic password/secret/token assignments with literal string values
# Matches: password = "actual_value", SECRET_KEY: 'actual_value', api_token="actual_value"
# Excludes: env var references like process.env.*, os.environ.*, ${...}, getenv(...)
if echo "$CONTENT" | grep -qiE '(password|secret|token|api_key|apikey|api_secret)[[:space:]]*[=:][[:space:]]*["\x27][^"\x27]{8,}["\x27]' && \
! echo "$CONTENT" | grep -qiE '(password|secret|token|api_key|apikey|api_secret)[[:space:]]*[=:][[:space:]]*["\x27]?(process\.env|os\.environ|getenv|\$\{|ENV\[|env\()'; then
MATCHES="$MATCHES hardcoded credential;"
fi
if [ -n "$MATCHES" ]; then
# Use "ask" not "deny" — warn the user but let them override (could be test fixtures)
REASON="Possible secret detected in content:$MATCHES Review carefully before allowing."
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"$REASON\"}}"
exit 2
fi
exit 0
+51
View File
@@ -0,0 +1,51 @@
#!/bin/bash
# Injects dynamic project context at session start.
# Used as a SessionStart hook.
CONTEXT=""
# Current branch (or detached HEAD)
BRANCH=$(git branch --show-current 2>/dev/null)
if [ -n "$BRANCH" ]; then
CONTEXT="Branch: $BRANCH"
elif git rev-parse --git-dir >/dev/null 2>&1; then
SHORT_SHA=$(git rev-parse --short HEAD 2>/dev/null)
CONTEXT="HEAD: detached at $SHORT_SHA"
fi
# Last commit
LAST_COMMIT=$(git log --oneline -1 2>/dev/null)
if [ -n "$LAST_COMMIT" ]; then
CONTEXT="$CONTEXT | Last commit: $LAST_COMMIT"
fi
# Uncommitted changes count
CHANGES=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
if [ "$CHANGES" -gt 0 ] 2>/dev/null; then
CONTEXT="$CONTEXT | Uncommitted changes: $CHANGES files"
fi
# Staged changes indicator
if ! git diff --cached --quiet 2>/dev/null; then
CONTEXT="$CONTEXT | Staged: yes"
fi
# Stash count
STASH_COUNT=$(git stash list 2>/dev/null | wc -l | tr -d ' ')
if [ "$STASH_COUNT" -gt 0 ] 2>/dev/null; then
CONTEXT="$CONTEXT | Stashes: $STASH_COUNT"
fi
# Active PR on current branch (if gh CLI is available)
if command -v gh >/dev/null 2>&1; then
PR_INFO=$(gh pr view --json number,title,state --jq '"PR #\(.number): \(.title) (\(.state))"' 2>/dev/null)
if [ -n "$PR_INFO" ]; then
CONTEXT="$CONTEXT | $PR_INFO"
fi
fi
if [ -n "$CONTEXT" ]; then
echo "$CONTEXT"
fi
exit 0
+58
View File
@@ -0,0 +1,58 @@
#!/bin/bash
# Blocks writes to build artifacts, binary files, and dependency directories.
# Used as a PreToolUse hook for Edit|Write operations.
# Exit 2 = block the action. Exit 0 = allow.
# Requires jq for JSON parsing — fail closed if missing
if ! command -v jq >/dev/null 2>&1; then
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"jq is required for file protection hooks but is not installed.\"}}"
exit 2
fi
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Block dependency and build directories
case "$FILE_PATH" in
node_modules/*|*/node_modules/*)
REASON="Cannot write into node_modules/ — install dependencies via package manager instead." ;;
vendor/*|*/vendor/*)
REASON="Cannot write into vendor/ — use dependency manager instead." ;;
dist/*|*/dist/*|build/*|*/build/*|.next/*|*/.next/*)
REASON="Cannot write into build output directories — these are generated by the build process." ;;
__pycache__/*|*/__pycache__/*)
REASON="Cannot write into __pycache__/ — these are generated by Python." ;;
.venv/*|*/.venv/*|venv/*|*/venv/*)
REASON="Cannot write into virtual environment directories." ;;
*)
REASON="" ;;
esac
if [ -n "$REASON" ]; then
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"$REASON\"}}"
exit 2
fi
# Block binary and archive file extensions
BASENAME=$(basename "$FILE_PATH")
case "$BASENAME" in
*.wasm|*.so|*.dylib|*.dll|*.exe|*.o|*.a)
REASON="Cannot write binary files — these should be compiled, not hand-written." ;;
*.zip|*.tar|*.tar.gz|*.tar.bz2|*.tgz|*.rar|*.7z)
REASON="Cannot write archive files." ;;
*.mp4|*.mov|*.avi|*.mkv|*.mp3|*.wav|*.flac)
REASON="Cannot write media files — add these manually outside Claude Code." ;;
*.pyc|*.pyo|*.class)
REASON="Cannot write compiled bytecode files." ;;
esac
if [ -n "$REASON" ]; then
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"$REASON\"}}"
exit 2
fi
exit 0
+57
View File
@@ -0,0 +1,57 @@
# Rules
Rules are modular instruction files that Claude loads automatically. They extend CLAUDE.md without bloating it.
- `alwaysApply: true` — loaded every session, regardless of what files are open
- `paths: [...]` — loaded only when working with files matching the glob patterns
## Available Rules
### code-quality.md
**Scope**: Always
Principles (single-responsibility, no premature abstraction, composition over inheritance), naming conventions (files, variables, functions, constants), comment guidelines, code markers (TODO/FIXME/HACK/NOTE), and file organization (import order, export patterns, function ordering).
### testing.md
**Scope**: Always
Three focused principles: test behavior not implementation, run single test files not the full suite, fix or delete flaky tests. Comprehensive test writing is handled by the `test-writer` skill.
### security.md
**Scope**: Path-scoped (`src/api/**`, `src/auth/**`, `src/middleware/**`, `**/routes/**`, `**/controllers/**`)
Loads when touching API or auth code. Covers input validation, parameterized queries, XSS prevention, token handling, secret logging, constant-time comparison, security headers, rate limiting.
### frontend.md
**Scope**: Path-scoped (`**/*.tsx`, `**/*.jsx`, `**/*.vue`, `**/*.svelte`, `**/*.css`, `**/*.scss`, `**/*.html`, `**/components/**`, `**/pages/**`, etc.)
Loads when touching frontend files. Design token requirements, design principles pick-list, component framework options, layout rules, accessibility (WCAG 2.1 AA), performance.
## Adding Your Own
Create a new `.md` file in this directory:
```yaml
---
alwaysApply: true
---
# Your Rule Name
- Your instructions here
```
Or path-scoped:
```yaml
---
paths:
- "src/your-area/**"
---
# Your Rule Name
- Instructions that only apply when touching these files
```
See [Claude Code docs](https://code.claude.com/docs/en/memory#path-specific-rules) for glob pattern syntax.
+51
View File
@@ -0,0 +1,51 @@
---
alwaysApply: true
---
# Code Quality
## Principles
- Functions do one thing. If it needs a section comment, extract that section.
- No magic values — extract numbers, strings, and config to named constants.
- Handle errors at the boundary. Don't catch and re-throw without adding context.
- No premature abstractions. Three similar lines > a helper used once.
- Don't add features or "improve" things beyond what was asked.
- No dead code or commented-out blocks. Git has history.
- Composition over inheritance.
## Naming
- **Files**: PascalCase for components/classes (`UserProfile.tsx`), kebab-case for utilities/directories (`date-utils.ts`)
- **Booleans**: `is`, `has`, `should`, `can` prefix — `isLoading`, `hasPermission`
- **Functions**: verb-first — `getUser`, `validateEmail`, `handleSubmit`
- **Handlers/callbacks**: `handle*` internally, `on*` as props — `handleClick` / `onClick`
- **Factories**: `create*``createUser`. **Converters**: `to*``toJSON`. **Predicates**: `is*`/`has*`
- **Constants**: `SCREAMING_SNAKE``MAX_RETRIES`, `API_BASE_URL`
- **Enums**: PascalCase members — `Status.Active`
- **Abbreviations**: only universally known (`id`, `url`, `api`, `db`, `config`, `auth`). Acronyms as words: `userId` not `userID`
## Comments
- **WHY**, never WHAT. If the code needs a "what" comment, rename instead.
- Comment: non-obvious decisions, workarounds with issue links, regex patterns, perf tricks
- Don't comment: obvious code, self-explanatory function names, section dividers, type info the language provides
- No commented-out code — delete it. No journal comments — git blame does this.
- API docs (JSDoc, docstrings) at module boundaries only, not every internal function
## Code Markers
| Marker | Use |
|---|---|
| `TODO(author): desc (#issue)` | Planned work |
| `FIXME(author): desc (#issue)` | Known bugs |
| `HACK(author): desc (#issue)` | Ugly workarounds (explain the proper fix) |
| `NOTE: desc` | Non-obvious context for future readers |
Must have an owner + issue link. Don't commit TODOs you can do now. Never use `XXX`, `TEMP`, `REMOVEME`.
## File Organization
- **Imports**: builtins → external → internal → relative → types. Blank line between groups.
- **Exports**: named over default. Export at declaration site. One component/class per file.
- **Functions**: public first, then private helpers in call order. Top-to-bottom reads as a story.
+26
View File
@@ -0,0 +1,26 @@
---
paths:
- "**/migrations/**"
- "**/migrate/**"
- "**/db/migrate/**"
- "**/alembic/**"
- "**/alembic/versions/**"
- "**/prisma/migrations/**"
- "**/drizzle/**"
- "**/knex/migrations/**"
- "**/sequelize/migrations/**"
- "**/typeorm/migrations/**"
- "**/flyway/**"
- "**/liquibase/**"
---
# Database Migrations
- **Never modify an existing migration** — always create a new migration for changes. Existing migrations may have already run in production.
- Every migration must be reversible — implement both up/forward and down/rollback.
- Test migrations in both directions before committing.
- Migration filenames are ordered by timestamp prefix — new migrations go at the end.
- Never use raw SQL when the ORM/migration tool provides a method for the operation.
- Never seed production data in migration files — use dedicated seed files.
- Never drop columns or tables without first confirming the data is no longer needed.
- Add indexes in their own migration, not bundled with schema changes — easier to rollback independently.
+18
View File
@@ -0,0 +1,18 @@
---
paths:
- "src/api/**"
- "src/services/**"
- "**/controllers/**"
- "**/routes/**"
- "**/handlers/**"
---
# Error Handling
- Use typed/custom error classes with error codes — not generic `Error("something went wrong")`.
- Never swallow errors silently. Log or rethrow with added context about what operation failed.
- Handle every rejected promise. No floating (unhandled) async calls.
- HTTP error responses: consistent shape (e.g., `{ error: { code, message } }`), correct status codes (400 for validation, 401 for auth, 404 for not found, 500 for unexpected).
- Never expose stack traces, internal paths, or raw database errors in production responses.
- Retry transient errors (network timeouts, rate limits) with exponential backoff. Fail fast on validation and auth errors — don't retry.
- Include correlation/request IDs in error logs when available.
+77
View File
@@ -0,0 +1,77 @@
---
paths:
- "**/*.tsx"
- "**/*.jsx"
- "**/*.vue"
- "**/*.svelte"
- "**/*.css"
- "**/*.scss"
- "**/*.html"
- "**/components/**"
- "**/pages/**"
- "**/views/**"
- "**/layouts/**"
- "**/styles/**"
---
# Frontend
## Design Tokens
Before writing frontend code, find the project's existing tokens file (`tokens.css`, `variables.css`, `theme.ts`, `tailwind.config.*`, `_variables.scss`). If none exists, create one. Never hardcode raw values in components.
Required token categories: colors (semantic names with dark mode variants), spacing scale, border radius, shadows (elevation system), typography (display + body + mono fonts, type scale, weights), breakpoints, transitions (durations + easing), z-index scale.
## Design Principles
Pick one primary principle. Don't mix randomly.
| Principle | When to use |
|---|---|
| **Glassmorphism** | Overlays, modern dashboards |
| **Neumorphism** | Settings panels, minimal controls |
| **Brutalism** | Developer tools, editorial sites |
| **Minimalism** | Portfolios, documentation, content-first |
| **Maximalism** | Creative agencies, e-commerce |
| **Claymorphism** | Playful apps, onboarding |
| **Bento Grid** | Dashboards, feature showcases |
| **Aurora / Mesh Gradients** | Landing pages, hero sections |
| **Flat Design** | Mobile apps, system UI |
| **Material Elevation** | Data-heavy apps, enterprise |
| **Editorial** | Blogs, long-form content |
## Component Framework
Use whatever the project already has. Don't mix competing libraries.
| Category | Options (pick one) |
|---|---|
| CSS | Tailwind, vanilla CSS, CSS Modules, styled-components, Emotion, UnoCSS, Panda CSS |
| Primitives | shadcn/ui, Radix, Headless UI, Ark UI, DaisyUI, Mantine, Chakra, Vuetify |
| Animation | CSS transitions, Framer Motion, GSAP, View Transitions API, AutoAnimate |
| Charts | Recharts, D3, Chart.js, Visx, ECharts, Nivo |
| Icons | Lucide, Phosphor, Heroicons, Tabler Icons, Iconify |
## Layout
- CSS Grid for 2D, Flexbox for 1D. Use `gap`, not margin hacks.
- Semantic HTML: `<header>`, `<nav>`, `<main>`, `<section>`, `<article>`, `<footer>`.
- Mobile-first. Touch targets: minimum 44x44px.
## Accessibility (non-negotiable)
- All interactive elements keyboard-accessible.
- Images: meaningful `alt` text. Decorative: `alt=""`.
- Form inputs: associated `<label>` or `aria-label`.
- Contrast: 4.5:1 normal text, 3:1 large text.
- Visible focus indicators. Never `outline: none` without replacement.
- Color never the sole indicator.
- `aria-live` for dynamic content. Respect `prefers-reduced-motion` and `prefers-color-scheme`.
## Performance
- Images: `loading="lazy"` below fold, explicit `width`/`height`.
- Fonts: `font-display: swap`.
- Animations: `transform` and `opacity` only.
- Large lists: virtualize at 100+ items.
- Bundle size: never import a whole library for one function.
+19
View File
@@ -0,0 +1,19 @@
---
paths:
- "src/api/**"
- "src/auth/**"
- "src/middleware/**"
- "**/routes/**"
- "**/controllers/**"
---
# Security
- Validate all user input at the system boundary. Never trust request parameters.
- Use parameterized queries — never concatenate user input into SQL or shell commands.
- Sanitize output to prevent XSS. Use framework-provided escaping.
- Authentication tokens must be short-lived. Store refresh tokens server-side only.
- Never log secrets, tokens, passwords, or PII.
- Use constant-time comparison for secrets and tokens.
- Set appropriate CORS, CSP, and security headers.
- Rate-limit authentication endpoints.
+14
View File
@@ -0,0 +1,14 @@
---
alwaysApply: true
---
# Testing
- Write tests that verify behavior, not implementation details.
- Run the specific test file after changes, not the full suite — faster feedback.
- If a test is flaky, fix or delete it. Never retry to make it pass.
- Prefer real implementations over mocks. Only mock at system boundaries (network, filesystem, clock).
- One assertion per test. If the name needs "and", split it.
- Test names describe behavior: `should return empty array when input is empty`, not `test1`.
- Arrange-Act-Assert structure. No logic (if/loops) in tests.
- Never `expect(true)` or assert a mock was called without checking its arguments.
+118
View File
@@ -0,0 +1,118 @@
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run lint *)",
"Bash(npm run test *)",
"Bash(npm run typecheck)",
"Bash(npm run build)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git branch *)",
"Bash(git stash *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git fetch *)",
"Bash(git checkout *)",
"Bash(git switch *)",
"Bash(gh pr *)",
"Bash(gh issue *)",
"Bash(gh run *)"
],
"deny": [
"Read(**/.env)",
"Read(**/.env.*)",
"Read(**/secrets/**)",
"Read(**/*.pem)",
"Read(**/*.key)",
"Write(**/.env)",
"Write(**/.env.*)",
"Write(**/secrets/**)",
"Write(**/*.pem)",
"Write(**/*.key)",
"Edit(**/.env)",
"Edit(**/.env.*)",
"Edit(**/secrets/**)",
"Edit(**/*.pem)",
"Edit(**/*.key)"
]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/protect-files.sh",
"timeout": 5000,
"statusMessage": "Checking file protections..."
},
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/warn-large-files.sh",
"timeout": 5000,
"statusMessage": "Checking for build artifacts..."
},
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/scan-secrets.sh",
"timeout": 5000,
"statusMessage": "Scanning for secrets..."
}
]
},
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/block-dangerous-commands.sh",
"timeout": 5000,
"statusMessage": "Checking command safety..."
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/format-on-save.sh",
"timeout": 15000,
"statusMessage": "Formatting..."
}
]
}
],
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh",
"timeout": 5000,
"statusMessage": "Loading project context..."
}
]
}
],
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "which osascript >/dev/null 2>&1 && osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"' || which notify-send >/dev/null 2>&1 && notify-send 'Claude Code' 'Claude Code needs your attention' || true"
}
]
}
]
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(docker compose *)",
"Bash(kubectl *)",
"Bash(make *)"
]
}
}
+69
View File
@@ -0,0 +1,69 @@
# Skills
Skills are slash commands you invoke with `/name`. They run in the main conversation context (they see all loaded rules and CLAUDE.md).
- `disable-model-invocation: true` — manual only, you type `/name` to trigger
- Without that flag — Claude can also trigger the skill automatically when relevant
## Available Skills
### /setupdotclaude
**Trigger**: Manual only
Scans the project codebase and customizes all `.claude/` config files to match the actual tech stack, conventions, and patterns. Run this after adding the `.claude/` folder to a new project. Confirms every change with the user. Runs a final review pass with `/refactor` in plan mode against the full codebase.
### /debug-fix [issue number, error, or description]
**Trigger**: Manual only
Find and fix a bug from any source — GitHub issue number, error message, stack trace, behavior description, or URL. Follows a structured flow: understand → reproduce → investigate → fix → verify → commit.
### /ship [optional message]
**Trigger**: Manual only
Full shipping workflow with confirmation at every step: scan changes → stage & commit → push → create PR. Proposes commit messages and PR descriptions. Blocks secrets, force-push, and push to main.
### /pr-review [PR number | staged | file path]
**Trigger**: Manual only
Reviews code changes by delegating to specialist agents (`@code-reviewer`, `@security-reviewer`, `@performance-reviewer`, `@doc-reviewer`). When given a PR number (or auto-detected from branch), also checks PR title, description quality, CI status, unresolved comments, and size — ending with a clear merge/needs-changes verdict. Also works on staged changes or specific files for pre-PR review.
### /tdd [feature description]
**Trigger**: Manual only
Strict Test-Driven Development loop. Red: write a failing test for the smallest next behavior. Green: write the minimum code to pass. Refactor: clean up without changing behavior. Repeat. Commits after each green+refactor cycle.
### /explain [file, function, or concept]
**Trigger**: Manual only
Explains code with a one-sentence summary, mental model analogy, ASCII diagram, key details, and modification guide.
### /refactor [target]
**Trigger**: Manual only
Safe refactoring with tests as a safety net. Writes tests first if none exist, makes changes in small testable steps, verifies no behavior change.
### /test-writer
**Trigger**: Automatic (when new features are added)
Writes comprehensive tests covering every code path: happy path, edge cases, nulls, type boundaries, error paths, concurrency, state transitions. Covers API endpoints, UI components, database operations, and async. Verifies tests actually catch bugs by breaking the code.
## Adding Your Own
Create a directory with a `SKILL.md` file:
```
your-skill/
└── SKILL.md
```
```yaml
---
name: your-skill
description: What it does and when to use it
disable-model-invocation: true
---
Your instructions here. Use $ARGUMENTS for user input.
```
See [Claude Code docs](https://code.claude.com/docs/en/skills) for all frontmatter options.
+61
View File
@@ -0,0 +1,61 @@
---
name: debug-fix
description: Find and fix a bug or issue — from any source (GitHub issue, error message, user report, or observed behavior)
argument-hint: "[issue number, error message, or description of the problem]"
disable-model-invocation: true
---
Find and fix the following issue:
**Problem**: $ARGUMENTS
## Step 1: Understand the Problem
Determine what kind of input this is:
- **Issue number** → fetch it: `gh issue view $ARGUMENTS` (GitHub), or check the project's issue tracker
- **Error message / stack trace** → parse it for file, line, error type, and the call chain leading to it
- **Description of behavior** → identify what's expected vs what's happening
- **URL / screenshot** → examine the referenced resource
If the problem is unclear, ask clarifying questions before proceeding.
## Step 2: Reproduce
- Find or write the simplest way to trigger the issue (a test, a curl command, a script)
- Confirm you can reproduce it reliably
- If you can't reproduce:
- **Environment-specific?** Check env vars, OS, Node/Python version, database state
- **Intermittent?** Likely a race condition — look for shared mutable state, timing dependencies, or async ordering assumptions
- **Already fixed?** Check `git log` for recent commits that mention the issue
## Step 3: Investigate
Follow this sequence — don't skip ahead to guessing:
1. **Locate the symptom**: which file and line produces the wrong output/error?
2. **Read the code path**: trace backwards from the symptom. What function called this? What data did it pass? Read each caller.
3. **Check git history**: `git log --oneline -20 -- <file>` to see what recently changed in the affected files. `git log --all --grep="<keyword>"` to find related commits.
4. **Narrow the scope**: use `git bisect` or targeted grep to identify when the behavior changed, or which input triggers it.
5. **Form a hypothesis**: "I think [X] is wrong because [evidence]."
6. **Verify the hypothesis**: add a targeted log/assertion/test that would confirm or deny it. Run it.
7. **If wrong, update**: don't keep guessing with the same hypothesis. Go back to step 2 and trace a different path.
## Step 4: Fix
- Make the minimal change that fixes the root cause
- Don't patch symptoms — if a value is wrong, trace back to where it becomes wrong and fix it there
- Don't refactor surrounding code while fixing the bug
- Don't add defensive checks that mask the problem — fix why the bad data exists
## Step 5: Verify
- Write a test that reproduces the original bug and now passes with the fix
- Run related tests to check for regressions
- Run lint and typecheck
- Temporarily revert your fix and confirm the new test fails — this proves the test actually catches the bug
## Step 6: Wrap Up
- Create a branch if not already on one
- Stage only the relevant files (fix + test, nothing else)
- Commit with a message that references the issue if one exists: `fix: <what was wrong and why> (#number)`
+33
View File
@@ -0,0 +1,33 @@
---
name: explain
description: Explain code with visual diagrams and clear mental models
argument-hint: "[file, function, or concept]"
disable-model-invocation: true
---
Explain `$ARGUMENTS` clearly.
## Format
### 1. One-sentence summary
What does it do and why does it exist? One sentence.
### 2. Mental model
Give an analogy or metaphor that captures the core idea. Relate it to something the developer already knows.
### 3. Visual diagram
Draw an ASCII diagram showing the data/control flow. Keep it readable:
```
Input → [Step A] → [Step B] → Output
[Side Effect]
```
### 4. Key details
Walk through the important parts. Skip the obvious — focus on:
- Non-obvious decisions (why this approach?)
- Edge cases and gotchas
- Dependencies and side effects
### 5. How to modify it
What would someone need to know to safely change this code? Where are the landmines?
+71
View File
@@ -0,0 +1,71 @@
---
name: hotfix
description: Emergency production fix — create hotfix branch, minimal change, critical tests only, ship fast
argument-hint: "[issue number, error message, or description of production problem]"
disable-model-invocation: true
allowed-tools:
- Bash(git *)
- Bash(gh *)
- Bash(npm run test *)
- Bash(npm run build)
- Read
- Glob
- Grep
- Edit
- Write
---
Emergency production fix. Speed matters — make the smallest correct change, verify it works, and ship.
## Step 1: Create Hotfix Branch
- Determine the production branch (`main` or `master` — check with `git remote show origin` or `git symbolic-ref refs/remotes/origin/HEAD`)
- Stash any uncommitted work if needed
- Create and switch to `hotfix/<short-description>` branch from the production branch
- **ASK the user to confirm** the branch name before creating
## Step 2: Understand the Problem
- If `$ARGUMENTS` is a GitHub issue number: fetch it with `gh issue view`
- If it's an error message or description: search the codebase for the relevant code
- Identify the root cause — trace from symptom to source
- **Briefly state** what you found and your proposed fix to the user
## Step 3: Fix — Minimal Change Only
- Make the smallest change that correctly fixes the issue
- **Do NOT**:
- Refactor surrounding code
- Add new features
- Clean up unrelated issues
- Change formatting or style
- Add comments beyond what's necessary to understand the fix
- If the fix requires more than ~50 lines changed, warn the user — this may not be a hotfix
## Step 4: Verify
- Run only the tests directly relevant to the changed code (not the full suite)
- Run the build to ensure it compiles
- If there's a way to reproduce the original error, verify it's fixed
- **ASK the user** if they want to run any additional verification
## Step 5: Ship
- Stage only the fix files (never stage secrets, locks, build output)
- Draft a commit message: `hotfix: <short description>` with a brief explanation
- **ASK the user to confirm** the commit message
- Push with `git push -u origin hotfix/<description>`
- Create a PR targeting the production branch:
- Title: `[HOTFIX] <description>`
- Body: what broke, what caused it, what this fixes
- Add label `hotfix` if the repo has it: `gh pr create ... --label hotfix` (fall back to no label if it fails)
- Show the PR URL
## Rules
- NEVER skip confirmation steps
- NEVER force-push
- NEVER commit secrets or unrelated changes
- NEVER refactor — this is a hotfix, not a cleanup
- If the user says "skip" at any step, skip it and move to the next
- If the fix turns out to be complex, tell the user and suggest a regular branch instead
+94
View File
@@ -0,0 +1,94 @@
---
name: pr-review
description: Review code changes or a pull request — delegates to specialist agents for code quality, security, performance, and documentation.
argument-hint: "[PR number | staged | file path — or omit to auto-detect]"
disable-model-invocation: true
---
Review code changes by delegating to specialist agents and synthesizing a unified report. Works with PRs, staged changes, or specific files.
## Step 1: Determine Scope
Parse `$ARGUMENTS` to determine what to review:
- **PR number** (e.g., `123` or `#123`): fetch with `gh pr view $ARGUMENTS`. This is the full PR review path (includes PR quality checks in Step 2).
- **No argument**: try `gh pr view` to detect a PR for the current branch. If a PR exists, use it. If not, fall back to `git diff --cached` (staged), then `git diff` (unstaged).
- **`staged`**: review `git diff --cached`. If nothing staged, fall back to `git diff`.
- **File path**: review that specific file's current state.
If there are no changes to review, say so and stop.
## Step 2: PR Quality Check (PR path only)
Skip this step if reviewing staged changes or a file — jump to Step 3.
When reviewing a PR, fetch and check:
- PR title, description/body, author, base branch, head branch
- `gh pr diff $NUMBER` for the full diff
- `gh pr checks $NUMBER` for CI status
- `gh api repos/{owner}/{repo}/pulls/$NUMBER/comments` for review comments
Review the PR itself before the code:
- **Title**: descriptive and under 72 chars?
- **Description**: explains the *why*? Includes a test plan? Flag if empty or template-only.
- **Size**: count changed files and lines. Flag if >500 lines changed (suggest splitting).
- **Base branch**: targeting the right branch?
- **CI status**: passing, failing, or pending? If failing, note which checks — fix CI first.
- **Unresolved comments**: list open review threads with file:line and comment text.
## Step 3: Code Review (delegate to agents)
1. **Always**: delegate the diff to `@code-reviewer`
2. **If security-sensitive code changed** — auth, input handling, queries, tokens, session management, file path construction: delegate to `@security-reviewer`
3. **If performance-sensitive code changed** — endpoints, DB queries, loops over collections, caching, connection management: delegate to `@performance-reviewer`. Skip if changes are only docs, config, tests, or static assets.
4. **If documentation changed** — .md files, significant docstring/JSDoc changes, API docs: delegate to `@doc-reviewer`
Determine relevance by reading the diff content, not just file paths.
## Step 4: Synthesize Report
For PR reviews:
```
## PR Review: #[number] — [title]
**Author**: [author] | **Base**: [base] → **Head**: [head] | **Changed**: [N files, +X/-Y lines]
### PR Quality
- Title: [ok / needs improvement]
- Description: [ok / missing test plan / empty]
- Size: [ok / large — consider splitting]
- CI: [passing / failing — list failures]
- Unresolved comments: [none / list]
### Code Review
#### Critical / High
- [Agent] File:Line — issue
#### Medium
- [Agent] File:Line — issue
#### Low
- [Agent] File:Line — issue
### Verdict
[Ready to merge / Needs changes — summarize blockers]
```
For non-PR reviews (staged/file):
```
## Review Summary
**Scope**: [staged changes / file path]
**Agents run**: [list]
### Critical / High
- [Agent] File:Line — issue
### Medium / Low
- [Agent] File:Line — issue
### Passed
- [areas with no issues]
```
Deduplicate findings that overlap between agents. Attribute each finding to the agent that found it.
+36
View File
@@ -0,0 +1,36 @@
---
name: refactor
description: Safely refactor code with test coverage as a safety net
argument-hint: "[target to refactor — file, function, or pattern]"
disable-model-invocation: true
---
Refactor `$ARGUMENTS` safely.
## Process
### 1. Understand the current state
- Read the code and its tests
- Identify what the code does, its callers, and its dependencies
- If there are no tests, WRITE TESTS FIRST — you need a safety net before changing anything
### 2. Plan the refactoring
- State what you're changing and why (clearer naming, reduced duplication, better structure)
- List the specific transformations (extract function, inline variable, move module, etc.)
- Check: does this change any external behavior? If yes, this isn't a refactor — reconsider.
### 3. Make changes in small, testable steps
- One transformation at a time
- Run tests after EACH step — not at the end
- If a test breaks, undo the last step and make a smaller change
### 4. Verify
- All existing tests pass
- Lint and typecheck pass
- The public API hasn't changed (unless that was the explicit goal)
- The code is objectively simpler — fewer lines, fewer branches, clearer names
## Rules
- If you can't run the tests, don't refactor
- Never mix refactoring with behavior changes in the same commit
- If the refactoring is large (10+ files), break it into multiple commits
+198
View File
@@ -0,0 +1,198 @@
---
name: setupdotclaude
description: Scan the project codebase and customize all .claude/ configuration files to match. Run this after adding the .claude/ folder to a new project.
argument-hint: "[optional: focus area like 'frontend' or 'backend']"
disable-model-invocation: true
---
Scan this project's codebase and customize every `.claude/` configuration file to match the actual tech stack, conventions, and patterns in use. Confirm with the user before each change using AskUserQuestion.
CLAUDE.md must be at the project root (`./CLAUDE.md`), NOT inside `.claude/`. All other config files live inside `.claude/`.
If the project is empty or has no source code yet, tell the user the defaults will be kept as-is and stop.
## Phase 0: Clean Up Non-Config Files
Before anything else, delete files inside `.claude/` that exist for the dotclaude repo itself but waste tokens or cause issues at runtime:
- `.claude/README.md` (repo README accidentally copied in)
- `.claude/CONTRIBUTING.md` (repo contributing guide accidentally copied in)
- `.claude/.gitignore` (for the dotclaude repo, not the project — the project has its own .gitignore)
- `.claude/rules/README.md`
- `.claude/agents/README.md`
- `.claude/hooks/README.md`
- `.claude/skills/README.md`
Also delete `.claude/CLAUDE.md` if it exists — CLAUDE.md belongs at the project root, not inside `.claude/`.
## Phase 1: Detect Tech Stack
Scan for package manifests, config files, and folder structure to detect: language, framework, package manager, test framework, linter/formatter, architecture pattern, and source/test directories.
Check: `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `Gemfile`, `composer.json`, `build.gradle`, `pom.xml`, `Makefile`, `Dockerfile`.
Check for monorepo indicators: `workspaces` key in package.json, `pnpm-workspace.yaml`, `lerna.json`, `nx.json`, `turbo.json`, or multiple `package.json` files at depth 2+. If a monorepo is detected, ask the user which packages/apps to focus on and customize rule path patterns to include package prefixes (e.g., `packages/api/src/**` instead of `src/**`).
Detect frameworks from dependencies and config files (frontend, backend, CSS, components, ORM/DB).
Detect test framework from config files (`jest.config.*`, `vitest.config.*`, `pytest.ini`, `conftest.py`, `playwright.config.*`, etc.).
Detect linter/formatter from config files (`.eslintrc.*`, `.prettierrc.*`, `biome.json`, `ruff.toml`, `tsconfig.json`, `.editorconfig`, etc.).
Detect folder structure pattern (feature-based, layered, monorepo, MVC) and locate source, test, API, and auth directories.
Check `git log --oneline -20` for commit message style.
## Phase 2: Present Findings
Present a summary to the user using AskUserQuestion:
```
I scanned your project. Here's what I found:
**Stack**: [language] + [framework] + [CSS] + [DB]
**Package manager**: [npm/pnpm/yarn/bun/pip/cargo/go]
**Test framework**: [jest/vitest/pytest/etc.]
**Linter/Formatter**: [eslint+prettier/ruff/clippy/etc.]
**Architecture**: [layered/feature-based/monorepo/etc.]
**Source dirs**: [list]
**Test dirs**: [list]
Should I customize the .claude/ files based on this? (yes/no/corrections)
```
If the user provides corrections, incorporate them.
## Phase 3: Customize Each File
For each file below, propose the specific changes and ask the user to confirm before applying.
### 3.1 — CLAUDE.md
Replace the template commands with actual commands from the detected manifest:
- **Build**: actual build command from package.json scripts, Makefile targets, etc.
- **Test**: actual test command + how to run a single test file
- **Lint/Format**: actual lint and format commands
- **Dev**: actual dev server command
- **Architecture**: replace placeholder directories with actual project structure (only non-obvious parts)
Remove sections that don't apply (e.g., Architecture section for a single-file utility).
### 3.2 — settings.json
Update permissions to match actual commands:
- Replace `npm run` with the actual package manager (`pnpm run`, `yarn`, `bun run`, `cargo`, `go`, `make`, `python -m pytest`, etc.)
- Add project-specific allow rules for detected scripts
- Keep deny rules for secrets as-is (these are universal)
### 3.3 — rules/code-quality.md
Update naming conventions ONLY if the project's existing code uses different patterns:
- Sample 5-10 source files to detect actual naming style (camelCase vs snake_case, etc.)
- If the project uses different file naming than the template, update
- If the project's import style differs, update the import order section
If everything matches the defaults, leave it unchanged.
### 3.4 — rules/testing.md
Update if the detected test framework has specific idioms. Otherwise leave as-is (it's only 3 lines).
### 3.5 — rules/security.md
Update the `paths:` frontmatter to match actual project directories:
- Replace `src/api/**` with actual API directory paths found
- Replace `src/auth/**` with actual auth directory paths
- Replace `src/middleware/**` with actual middleware paths
- If none found, keep the defaults as reasonable guesses
### 3.5b — rules/error-handling.md
Update the `paths:` frontmatter to match actual backend directories (same paths as security.md plus service/handler directories). If the project has no backend, delete this file.
### 3.6 — rules/frontend.md
- **If no frontend files exist** (no .tsx, .jsx, .vue, .svelte, .css): delete this file entirely
- **If frontend exists**: update the Component Framework table to highlight which options the project actually uses (detected from dependencies)
- Update path patterns in frontmatter if the project uses non-standard directories
### 3.7 — hooks/format-on-save.sh
Uncomment the section matching the detected formatter:
- Prettier found → uncomment Node.js section
- Black/isort found → uncomment Python section
- Ruff found → uncomment Ruff section
- Biome found → uncomment Biome section
- rustfmt found → uncomment Rust section
- gofmt found → uncomment Go section
- Multiple languages → uncomment all relevant sections
### 3.8 — hooks/block-dangerous-commands.sh
Check the default branch name (`git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null` or `git remote show origin`). If it's not `main` or `master`, update the regex pattern.
### 3.9 — rules/database.md
- Check if the project has a database (look for: migration directories, ORM config files like `prisma/schema.prisma`, `drizzle.config.*`, `alembic.ini`, `knexfile.*`, `sequelize` in dependencies, `typeorm` in dependencies, `ActiveRecord` patterns, `flyway`, `liquibase`)
- **If database/migrations detected**: keep the rule, update `paths:` frontmatter to match the actual migration directory paths found
- **If no database detected**: delete `rules/database.md` entirely
### 3.10 — skills/
All skills are methodology-based and project-agnostic. Leave unchanged.
### 3.11 — agents/
- **frontend-designer.md**: delete if no frontend files exist
- **doc-reviewer.md**: delete if the project has no documentation directory (no `docs/`, `doc/`, or significant `.md` files beyond README)
- **security-reviewer.md**: keep (security applies everywhere)
- **code-reviewer.md**: keep (universal)
- **performance-reviewer.md**: keep (universal)
## Phase 4: Review & Simplify
After all changes are applied, run a thorough final review pass.
Strip any remaining `> REPLACE:` placeholder blocks from `CLAUDE.md` — these are template guidance that should have been replaced with real content or removed during Phase 3.1.
Review the entire codebase alongside the customized `.claude/` configuration:
- Do the rules match how the code is actually written?
- Do the settings permissions cover the commands the project actually uses?
- Do the security rule paths match where sensitive code actually lives?
- Do the hook protections cover the files that actually need protecting in this project?
- Are there project patterns, conventions, or architectural decisions not yet captured in the config?
- Remove any redundancy introduced during customization
- Ensure no file contradicts another
- Trim any verbose instructions back to essentials
- Verify all YAML frontmatter is valid
- Verify all hook scripts referenced in settings.json exist and are executable
Present the review findings to the user. If changes are needed, confirm before applying.
## Phase 5: Summary
After everything is finalized, present a summary:
```
Setup complete. Here's what was customized:
- CLAUDE.md: updated commands for [stack]
- settings.json: permissions updated for [package manager]
- rules/security.md: paths updated to [actual dirs]
- rules/frontend.md: [kept/removed]
- hooks/format-on-save.sh: enabled [formatter]
- [any other changes]
Files left as defaults (universal, no project-specific changes needed):
- [list]
Review pass: [any issues found and fixed, or "all clean"]
```
## Rules
- NEVER write changes without user confirmation first
- NEVER delete a file without confirming — propose "remove" and explain why
- If the project is empty (no source files, no manifests), say "Project appears empty — keeping all defaults" and stop
- If detection is uncertain, ASK the user rather than guessing
- Preserve any manual edits the user has already made to .claude/ files — only update sections that need project-specific customization
- Keep it minimal — don't add complexity. If the default works, leave it alone.
+71
View File
@@ -0,0 +1,71 @@
---
name: ship
description: Scan changes, commit, push, and create a PR — with confirmation at each step
argument-hint: "[optional commit message or PR title]"
disable-model-invocation: true
allowed-tools:
- Bash(git status)
- Bash(git diff *)
- Bash(git log *)
- Bash(git add *)
- Bash(git commit *)
- Bash(git push *)
- Bash(git checkout *)
- Bash(git branch *)
- Bash(gh pr create *)
- Bash(gh pr view *)
---
Ship the current changes through commit, push, and PR creation. Confirm with the user before each step using the AskUserQuestion tool.
## Step 1: Scan
- Run `git status` to see all changed, staged, and untracked files
- Run `git diff` to see what changed (staged + unstaged)
- Run `git log --oneline -5` to see recent commit style
- Present a clear summary to the user:
- Files modified
- Files added
- Files deleted
- Untracked files
- If there are no changes, tell the user and stop
## Step 2: Stage & Commit
- Propose which files to stage. **Never stage** these:
- Secrets: `.env*`, `*.pem`, `*.key`, `credentials.json`
- Lock files: `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` (unless intentionally updated)
- Generated: `*.gen.ts`, `*.generated.*`, `*.min.js`, `*.min.css`
- Build output: `dist/`, `build/`, `.next/`, `__pycache__/`
- Dependencies: `node_modules/`, `vendor/`, `.venv/`
- OS/editor: `.DS_Store`, `Thumbs.db`, `*.swp`, `.idea/`, `.vscode/settings.json`
- Draft a commit message based on the changes, matching the repo's existing commit style
- **ASK the user to confirm or edit**: show the exact files to stage and the proposed commit message
- Only after confirmation: stage the files and create the commit
- If the commit fails (e.g., pre-commit hook), fix the issue and try again with a NEW commit
## Step 3: Push
- Check if the current branch has an upstream remote
- If not, propose creating one with `git push -u origin <branch>`
- **ASK the user to confirm** before pushing
- Only after confirmation: push to remote
## Step 4: Pull Request
- Check if a PR already exists for this branch (`gh pr view` — if it exists, show the URL and stop)
- Analyze ALL commits on this branch vs the base branch (not just the latest commit)
- Draft a PR title (under 72 chars) and body with:
- Summary: 2-4 bullet points
- Test plan: how to verify
- **ASK the user to confirm or edit** the title and body
- Only after confirmation: create the PR with `gh pr create`
- Show the PR URL when done
## Rules
- NEVER skip a confirmation step — each step requires explicit user approval
- NEVER force-push
- NEVER commit .env, secrets, or credential files
- If the user says "skip" at any step, skip that step and move to the next
- If $ARGUMENTS is provided, use it as the commit message / PR title
+70
View File
@@ -0,0 +1,70 @@
---
name: tdd
description: Test-Driven Development loop — write a failing test first, then the minimum code to pass it, then refactor. Repeat.
argument-hint: "[feature description or function signature]"
disable-model-invocation: true
---
Build the following using strict Test-Driven Development:
**Feature**: $ARGUMENTS
## The TDD Cycle
Repeat this cycle for each behavior. Never skip steps.
### Red: Write a Failing Test
1. Write ONE test for the smallest next behavior (not the whole feature)
2. The test must:
- Describe the behavior in its name: `should return 0 for empty cart`
- Use Arrange-Act-Assert structure
- Assert specific values, not vague truths
3. **Run the test. It MUST fail.** If it passes, either:
- The behavior already exists (skip to the next behavior)
- The test is wrong (it's not testing what you think — fix it)
4. Verify the failure message makes sense — it should tell you what's missing
### Green: Write the Minimum Code to Pass
1. Write the **simplest, most obvious code** that makes the failing test pass
2. Don't generalize. Don't make it elegant. Don't handle cases the test doesn't cover.
3. Hardcoding is fine if only one test exists for that path — the next test will force generalization
4. **Run the test. It MUST pass.** If it doesn't, fix the code (not the test — the test defined the behavior)
5. Run ALL tests. Nothing previously passing should break.
### Refactor: Clean Up Without Changing Behavior
1. Look for: duplication, unclear names, functions doing too much, magic values
2. Make ONE improvement at a time
3. **Run ALL tests after each change.** If anything breaks, undo immediately.
4. Stop refactoring when the code is clean enough — don't gold-plate
## Choosing What to Test Next
Work from simple to complex:
1. **Degenerate cases** — null input, empty collection, zero
2. **Happy path** — the simplest valid input
3. **Variations** — different valid inputs that exercise different branches
4. **Edge cases** — boundary values, max sizes, special characters
5. **Error cases** — invalid input, failures, exceptions
6. **Integration** — how this connects to the rest of the system
Each test should require a small code change. If you need to write more than ~10 lines of production code to pass a test, the test is too big — split it.
## Rules
- **Never write production code without a failing test that demands it.**
- **Never write more than one failing test at a time.** One red → green → refactor cycle at a time.
- **The test drives the design.** If the code is hard to test, the design is wrong — change the design, not the test approach.
- **Don't mock what you own.** If you need to mock your own code to test it, the code needs restructuring.
- **Commit after each green+refactor cycle.** Small, passing, meaningful commits.
## Output
After each cycle, briefly state:
- **Test**: what behavior was added
- **Code**: what changed to make it pass
- **Refactor**: what was cleaned up (or "none needed")
When the feature is complete, provide a summary of all behaviors covered and any gaps that would need integration or manual testing.
+97
View File
@@ -0,0 +1,97 @@
---
name: test-writer
description: Write comprehensive tests for new or changed code. Use automatically when new features are added, functions are created, or behavior is modified.
# No disable-model-invocation — Claude can auto-trigger this when adding features.
# Add "disable-model-invocation: true" below if you prefer manual-only via /test-writer.
---
Write comprehensive tests for the code that was just added or changed.
## Step 1: Discover What Changed
- Check `git diff` and `git diff --cached` to identify new/modified functions, classes, and modules
- Read each changed file to understand the behavior being added
- Identify the project's existing test framework, patterns, and conventions by finding existing test files
- Place new test files next to the source files or in the project's established test directory — match whatever the project already does
## Step 2: Analyze Every Code Path
For each new or modified function/method/component, map out:
- **Happy path** — normal input, expected output
- **Edge cases** — empty input, single element, boundary values (0, 1, -1, MAX_INT)
- **Null/undefined/nil** — what happens with missing data
- **Type boundaries** — wrong types, type coercion traps
- **Error paths** — invalid input, network failures, timeouts, permission denied
- **Concurrency** — race conditions, parallel calls with shared state
- **State transitions** — initial state, intermediate states, final state
- **Integration points** — how this code interacts with its dependencies
## Step 3: Write the Tests
For EACH scenario identified above, write a test. No skipping.
### Structure
- **One assertion per test** — if a test name needs "and", split it into two tests
- **Descriptive names** — test names read as sentences describing the behavior:
- `should return empty array when input is empty`
- `should throw ValidationError when email format is invalid`
- `should retry 3 times before failing on network timeout`
- **Arrange-Act-Assert** — set up, execute, verify. Clear separation.
### What to Test
**Pure functions / business logic:**
- Every branch (if/else, switch, ternary)
- Every thrown error with exact error type and message
- Return value types and shapes
- Side effects (mutations, calls to external services)
**API endpoints / handlers:**
- Success response (status code, body shape, headers)
- Validation errors for each field (missing, wrong type, out of range)
- Authentication/authorization failures
- Rate limiting behavior if applicable
- Idempotency for non-GET methods
**UI components (if applicable):**
- Renders without crashing with required props
- Renders correct content for each state (loading, error, empty, populated)
- User interactions trigger correct callbacks (click, submit, type, select)
- Accessibility: focusable, keyboard navigable, correct ARIA attributes
- Conditional rendering — each branch shows/hides correct elements
**Database / data layer:**
- CRUD operations return correct data
- Unique constraints reject duplicates
- Cascade deletes work as expected
- Transactions roll back on failure
**Async operations:**
- Successful resolution
- Rejection / error handling
- Timeout behavior
- Cancellation if supported
- Concurrent calls don't interfere
### Mocking Rules
- Prefer real implementations over mocks
- Only mock at system boundaries: network, filesystem, clock, random
- Never mock the code under test
- If you mock, verify the mock was called with expected arguments
- Reset mocks between tests — no shared state leaking
## Step 4: Verify
- Run the new tests — confirm they all pass
- Temporarily break the code (change a return value or condition) — confirm at least one test fails
- If no test fails when code is broken, the tests are useless — rewrite them
- Check coverage: every new function should have at least one test, every branch should be exercised
## Output
- Complete, runnable test file(s) — not snippets
- Tests grouped by the function/component they cover
- A brief summary: how many tests, what scenarios covered, any gaps you couldn't cover and why