Claude Code Power-User Tips#
CLAUDE.md authoring#
CLAUDE.md is the highest-leverage investment in Claude Code. A good one turns Claude from a generic assistant into a teammate who already knows your project.
What to include#
# Project: <name>
## Stack (one line per component)
- Python 3.12, FastAPI, SQLAlchemy 2.0
- Postgres 16, Redis, Celery
- Deployed to AWS ECS via GitHub Actions
## Commands
- `make test` β run full test suite (pytest + mypy + ruff)
- `make dev` β start dev server with hot reload
- `make migration name=<name>` β create Alembic migration
## Key conventions
- Use `structlog` for all logging β no print()
- API responses always wrap in `{"data": ..., "meta": ...}`
- All public functions need docstrings and type hints
- Test files mirror source structure: `src/users/service.py` β `tests/users/test_service.py`
## Do not touch
- `alembic/versions/` β only `make migration` should create files here
- `config/production.yaml` β readonly; edit `config/development.yaml` instead
## Architecture notes
- `src/core/` β shared utilities, auth, logging config
- `src/api/` β FastAPI routers only; business logic goes in `src/services/`
- Tasks run in Celery workers in `src/workers/`
What not to include#
- Long prose explanations β Claude reads the code
- Boilerplate docs that repeat whatβs in README
- File lists β Claude reads the directory tree
- Implementation details that live in the code
[!TIP] Think of CLAUDE.md as βthings a new teammate would need to know in the first 30 minutes that they couldnβt figure out from the code alone.β
Team vs personal CLAUDE.md#
Commit CLAUDE.md to the repo for shared conventions. Use ~/.claude/CLAUDE.md for personal preferences (style, tone, shorthand). Subdir CLAUDE.md files are great for component-specific overrides:
project/
βββ CLAUDE.md # project-wide
βββ frontend/
β βββ CLAUDE.md # React conventions, component library notes
βββ ml/
βββ CLAUDE.md # Python conventions, GPU notes
Custom skills (slash commands)#
Skills let you encode repeatable workflows as named commands.
PR review skill#
# ~/.claude/commands/pr-review.md
Review the current git diff (staged + unstaged) as if it were a pull request.
Check for:
1. **Security** β hardcoded secrets, injection vulnerabilities, unvalidated input
2. **Correctness** β edge cases, null handling, off-by-one errors
3. **Performance** β N+1 queries, unnecessary loops, missing indexes
4. **Style** β consistency with surrounding code
Format:
- One section per category
- Flag only real issues, not style preferences
- For each issue: file:line, severity (Critical/Warning/Info), and a one-line fix suggestion
Deploy checklist skill#
# .claude/commands/predeploy.md
Run the pre-deploy checklist for this project:
1. Run `make test` β report pass/fail
2. Run `make lint` β report any violations
3. Check for any TODO/FIXME/HACK comments added in this branch vs main: `git diff main --unified=0 | grep -E '(TODO|FIXME|HACK)'`
4. Check that CHANGELOG.md has an entry for today's date
5. Report a final go/no-go with a one-line summary per check.
Quick refactor skill with arguments#
# ~/.claude/commands/extract.md
Extract the function or block described by "$ARGUMENTS" into its own well-named helper function.
Place the helper just above the call site. Add type hints. Do not change behavior.
Usage: /extract the date-parsing logic in process_invoice()
Multi-step workflow patterns#
Parallel research + write#
Claude Code supports multi-agent subagents. For large tasks, explicitly ask for parallel work:
> I need to add Redis caching to the user service. Research the existing
service patterns and our Redis config in parallel, then write the
implementation.
Iterative refinement#
> Step 1: write a first draft of the migration script
> Step 2: critique it for edge cases
> Step 3: fix the issues you found
Breaking work into explicit steps produces better results than one large prompt because Claude can revise with full context.
Verification loop#
> Write the feature, then run `make test` and fix any failures before
reporting done.
This pattern β write β test β fix loop β is more reliable than asking Claude to write perfect code in one shot.
Cost control#
Model selection#
| Task | Recommended model | Why |
|---|---|---|
| Complex refactors, architecture | claude-opus-4-7 | Best reasoning |
| Interactive coding, PR review | claude-sonnet-4-6 | Balanced quality/cost |
| Summarization, simple edits | claude-haiku-4-5 | Fastest and cheapest |
| Batch offline processing | claude-haiku-4-5 + batch API | 50% batch discount |
# Use Haiku for a quick summary task
claude --model claude-haiku-4-5-20251001 -p "Summarize the changes in the last 5 commits"
Scope your prompts#
# High cost β Claude reads entire codebase
> Refactor the project to use TypeScript
# Lower cost β explicit scope
> Refactor src/api/users.js to TypeScript. Keep the same exports.
Use /compact proactively#
Donβt wait for the context warning. Run /compact after completing a logical unit of work. This keeps the context window lean and reduces token usage on subsequent turns.
Check session cost#
> /cost
Output:
Session cost: $0.23
Input tokens: 48,320
Output tokens: 6,140
Cache hits: 31,200 (saves ~$0.09)
Prompt caching in headless mode#
When running Claude non-interactively with a large system prompt, add caching:
# First call writes cache; subsequent calls are ~90% cheaper
claude -p "Analyze this file for security vulnerabilities" < src/auth.py
Claude Code automatically uses prompt caching for repeated system prompts and tool definitions within a session.
Headless scripting patterns#
Pre-commit hook#
#!/bin/bash
# .git/hooks/pre-commit
STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(py|ts|js)$')
if [ -z "$STAGED" ]; then exit 0; fi
echo "$STAGED" | xargs cat | claude --allowedTools "" -p \
"Review this code for security issues and obvious bugs.
If any Critical issues found, exit 1 and describe them.
If clean, output 'OK' and exit 0." \
--output-format json | python3 -c "
import json, sys
r = json.load(sys.stdin)
text = r.get('result', '')
if 'Critical' in text:
print(text)
sys.exit(1)
print('Pre-commit check: OK')
"
CI code review#
# .github/workflows/ai-review.yml
- name: AI code review
run: |
git diff origin/main...HEAD | claude --allowedTools "" \
-p "Review this diff for security vulnerabilities only.
Output JSON: {\"issues\": [{\"file\": \"\", \"line\": 0, \"desc\": \"\"}]}" \
--output-format json > review.json
python3 -c "
import json
r = json.load(open('review.json'))
issues = r.get('issues', [])
if issues:
for i in issues: print(f'{i[\"file\"]}:{i[\"line\"]} {i[\"desc\"]}')
exit(1)
"
Automated documentation#
#!/bin/bash
# Generate API docs from source
for file in src/api/*.py; do
claude --allowedTools "Read" \
-p "Generate Markdown API documentation for this file.
Cover each public function: purpose, parameters, return value, example." \
--output-format text < "$file" > "docs/api/$(basename $file .py).md"
done
Keyboard shortcuts reference#
| Shortcut | Action |
|---|---|
Tab | Autocomplete slash commands |
Up / Down | Navigate input history |
Shift+Enter | Insert newline without submitting |
Ctrl+C | Cancel running operation |
Ctrl+D | Exit Claude Code |
Escape | Clear current input |
Cmd+Esc (Mac) | Open Claude Code from VS Code |
Ctrl+Esc (Win/Linux) | Open Claude Code from VS Code |
Troubleshooting#
Claude keeps asking for permission for the same tools#
Add them to the allow list in settings.json:
{"permissions": {"allow": ["Bash(npm test:npm run lint)"]}}
Context fills up fast on large repos#
- Add a
.claudeignorefile (same syntax as.gitignore) to exclude generated files, build outputs, and large assets. - Use explicit file paths in prompts instead of broad descriptions.
- Run
/compactmore aggressively.
Slow on first run per session#
Claude Code re-reads CLAUDE.md files and does directory scanning at session start. This is normal. Subsequent turns within the same session are faster because context is already loaded.
Hooks not firing#
- Check file is executable:
chmod +x /path/to/hook.sh - Use absolute paths in
settings.jsonβ~is not expanded in all contexts - Test manually:
CLAUDE_TOOL_NAME="Bash" CLAUDE_TOOL_INPUT='{"command":"ls"}' bash /path/to/hook.sh