Claude Code
Patterns
Ten common tasks, each as a complete worked example. The page to bookmark. When you need to do something with Claude Code and are not sure how to start, come here.
Each pattern follows the same shape: a one-line description of when to use it, the prompt that kicks it off, a terminal reconstruction of the interaction, and a "watch out for" note on where it can go wrong. The prompts are written to be copied and adapted. The terminal cards show what the real session looks like.
1. Debug a bug
When: you have a bug report, a stack trace, or a symptom, and you want Claude to find and fix the root cause.
> Users are reporting that the CSV export sometimes produces duplicate rows. Here is a sample export showing the duplication. The export handler is in src/exports/csv.ts. Find the bug, fix it, and add a test that catches duplicates.
Read src/exports/csv.ts (94 lines)
Read src/exports/__tests__/csv.test.ts (56 lines)
Read src/db/queries/export.ts (38 lines)
Found it. The SQL query joins on the events table without a DISTINCT, and when an event has multiple tags, each tag creates a separate row. The export then outputs one CSV row per database row instead of per event.
Fix: add DISTINCT to the query and group by event ID. Test: create a fixture with a multi-tagged event and assert the CSV has exactly one row for it.
Edit src/db/queries/export.ts (1 line changed)
Edit src/exports/__tests__/csv.test.ts (18 lines added)
Run npm test
All 24 tests passed.
Watch out for
Claude may fix the symptom without finding the root cause. If the fix feels like a workaround, ask "is this the root cause or a band-aid?" Genuine root-cause fixes change the query or the logic. Band-aids add deduplication after the fact.
2. Build a new feature
When: you need to add something that does not exist yet. This is the pattern that benefits most from the plan step.
> I want to add a webhook system that notifies external URLs when a new report is published. Plan first: which files need to change, what is the approach, what should I watch out for?
Plan:
1. New model: WebhookSubscription (url, event type, active flag, secret for signing)
2. New service: src/webhooks/dispatcher.ts (queue, retry logic, HMAC signing)
3. Hook into the report publish flow: src/reports/publish.ts line 47
4. New API routes: CRUD for subscriptions + a test endpoint
5. Tests: dispatcher unit tests + integration test for the full publish flow
Watch out: retry logic needs exponential backoff. Signing needs a shared secret per subscription.
> Looks good. Start with step 1 and 2, test them, then move to step 3.
Watch out for
Without the plan step, Claude will jump straight to writing code and may choose an approach that does not fit your architecture. Always plan first for features that touch more than two files.
3. Refactor safely
When: you need to restructure code without changing behaviour. The key is existing tests as a safety net.
> The UserService class at src/services/user.ts is 400 lines and does too much. Split it into UserAuthService and UserProfileService. Run tests after every file change. Do not change any public API.
Read src/services/user.ts (412 lines)
Run npm test -- --testPathPattern=user
18 tests passed (baseline).
Splitting auth methods into UserAuthService and profile methods into UserProfileService. The original UserService will become a thin facade that delegates. Public API stays identical.
Create src/services/user-auth.ts
Create src/services/user-profile.ts
Edit src/services/user.ts (refactored to facade)
Run npm test -- --testPathPattern=user
18 tests passed (all green, no behaviour change).
Watch out for
No tests? No safe refactor. If the code you want to refactor does not have tests, write the tests first (pattern 4), confirm they pass, then refactor. The tests are the proof that behaviour did not change.
4. Write tests first
When: you want to add test coverage to existing code, or you want to use test-driven development on a new feature.
> Read src/billing/invoice.ts and write a complete test suite for it. Cover happy path, edge cases (zero amount, negative amount, missing customer), and error handling. Do not change the source file. Run the tests after writing them.
Read src/billing/invoice.ts (67 lines)
Create src/billing/__tests__/invoice.test.ts (94 lines)
Run npm test -- --testPathPattern=invoice
11 tests passed. 3 edge case tests, 5 happy path, 3 error handling.
Full coverage. One thing I noticed while reading: the function doesn't handle the case where amount is NaN. Do you want me to add a test for that and then fix the function?
Watch out for
Claude may write tests that test what the code does, not what it should do. If the code has a bug, the test will pass (testing the bug). Always read the test descriptions and ask "is this what I want, or is this what happens?"
5. Review a PR
When: you want a first-pass review of a pull request before spending your own time on it.
> Review PR #52 on this repo. Focus on correctness, edge cases, and security. Rank comments by severity. Do not nitpick style.
Run gh pr view 52 --json body,files
Run gh pr diff 52
Read src/api/handlers/upload.ts (context for the changed lines)
Three comments, ranked:
1. CRITICAL: the file size check on line 24 uses req.body.length, but multipart uploads are streamed and body.length is undefined until fully buffered. This means the size limit is never enforced. Use the Content-Length header or a stream counter.
2. IMPORTANT: the error message on line 38 includes the full file path from the server, which is an information disclosure risk in production.
3. MINOR: the success response on line 45 returns the internal file ID. Consider whether clients need this or whether a public-facing ID would be safer.
Watch out for
Claude reviews the diff, not the deployed behaviour. If the PR depends on context outside the diff (a config change, a feature flag, a database migration), tell Claude about it or it will miss the dependency.
6. Scaffold a project
When: you want to create a new tool, service, or project from scratch.
> Build me a small CLI tool in Python that watches a folder for new CSV files, validates each row against a schema I define, and prints a report of invalid rows. Use argparse for the CLI, no external dependencies except watchdog. Show me the plan first.
Plan: 4 files.
1. main.py: argparse CLI, launches the watcher
2. schema.py: dataclass-based schema definition
3. validator.py: reads CSV, validates against schema, returns a report
4. requirements.txt: watchdog only
> Go. Start with main.py so I can see the skeleton.
Create main.py (42 lines)
Create schema.py (28 lines)
Create validator.py (51 lines)
Create requirements.txt
Run pip install -r requirements.txt
Run python main.py --help
usage: main.py [-h] --schema SCHEMA --watch WATCH
Watch out for
Claude loves over-engineering. If you asked for "a small tool", push back on class hierarchies, abstract base classes, and dependency injection that a 50-line script does not need. "Keep it simple" is a valid instruction.
7. Explore unfamiliar code
When: you have inherited a codebase, joined a new team, or need to understand code someone else wrote.
$ claude --plan
> I just joined this project. Read the src/api/ directory and give me a map: which endpoints exist, what each one does, and how auth works across them.
Read src/api/routes.ts
Read src/api/handlers/auth.ts
Read src/api/handlers/reports.ts
Read src/api/handlers/export.ts
Read src/api/middleware/auth.ts
Here is the API map:
POST /auth/login: email+password, returns JWT
POST /auth/refresh: rotates JWT using httpOnly cookie
GET /reports: list reports (auth required, paginated)
POST /reports: create report (auth required, admin only)
GET /export/:id: download CSV (auth required)
Auth: JWT in Authorization header, verified by middleware on all routes except /auth/*. Admin check is a role field in the JWT payload.
Watch out for
Use plan mode for exploration. If you use normal mode, Claude might suggest changes you did not ask for. Plan mode is read-only: it can map and explain but cannot modify.
8. Automate a chore
When: you need to make the same change across many files. Renames, import updates, pattern migrations.
> Rename every import of "OldLogger" to "Logger" across the entire codebase. Update the import paths from "@/utils/old-logger" to "@/utils/logger". Run the linter and tests after.
Grep: found 34 files referencing OldLogger
Edit 34 files (import rename + path update)
Run npm run lint
No lint errors.
Run npm test
All 87 tests passed.
Done. 34 files updated, all imports renamed, lint and tests clean. Also renamed the file from old-logger.ts to logger.ts and updated the barrel export in utils/index.ts.
Watch out for
On very large codebases (hundreds of files), consider using the fan-out pattern: generate the file list first, then process in batches. Claude's context is large but not unlimited, and a 500-file rename in one pass may lose accuracy on the later files.
9. Generate documentation
When: you need docs that match what the code actually does, not what someone wrote six months ago.
> Read every endpoint in src/api/handlers/ and generate API documentation in Markdown. For each endpoint: method, path, description, request body (with types), response body (with types), auth requirements, and one curl example. Save as docs/api-reference.md.
Read src/api/handlers/auth.ts
Read src/api/handlers/reports.ts
Read src/api/handlers/export.ts
Read src/api/handlers/webhooks.ts
Create docs/api-reference.md (186 lines)
API reference generated from the source code. 8 endpoints documented with types, auth requirements, and curl examples. Two things I could not determine from the code alone: the rate limits (if any) and the error response format for 500s. I've left "TBD" markers for both.
Watch out for
Claude documents what the code does, not what it should do. If the code has a bug, the docs will faithfully document the buggy behaviour. Always review generated docs against intent, not just against code.
10. Fix a failing CI build
When: CI is red and you need it green. Paste the log, point Claude at the failing test or build step.
> CI is failing on the lint step. Here is the log:
> [pasted: 12 lines of ESLint errors]
Two issues. First: three files have unused imports that the CI linter catches but the local linter does not (different ESLint config). Second: one file uses a named export that should be a default export per your .eslintrc rule.
Edit src/utils/format.ts (removed unused import)
Edit src/utils/date.ts (removed unused import)
Edit src/api/middleware/cors.ts (removed unused import)
Edit src/api/handlers/webhooks.ts (changed to default export)
Run npm run lint
No lint errors.
Run npm test
All tests passed.
Fixed. Also: your local .eslintrc is missing the "no-unused-imports" rule that CI has. Want me to add it so this does not happen again?
Watch out for
If Claude fixes the lint errors but the underlying code change that introduced them was wrong, you have green CI on bad code. Always check whether the fix addresses the symptom or the cause. "Remove the unused import" is fine. "Remove the import and also the function that was supposed to use it" is a sign something went wrong upstream.
Pattern summary
| Pattern | Start with | Key prompt line |
| Debug | Symptom + trace | "Find the bug, fix it, and add a test that catches it" |
| Feature | Plan first | "Plan first: which files, what approach, what to watch out for" |
| Refactor | Tests as baseline | "Run tests after every file change. Do not change any public API" |
| Tests | Read the code | "Cover happy path, edge cases, and error handling. Run after writing" |
| PR review | The PR number | "Focus on correctness and security. Rank by severity. Do not nitpick style" |
| Scaffold | Plan first | "Show me the plan first" then "Start with X so I can see the skeleton" |
| Explore | Plan mode | "Read X and give me a map" |
| Automate | The change | "Run the linter and tests after" |
| Docs | The source | "Leave TBD markers for anything you cannot determine from the code" |
| Fix CI | The log | "Here is the log" then let Claude diagnose |
Every pattern has the same underlying discipline: give Claude specific context, ask for a specific output, include a verification step (tests, lint, a check), and review the result before moving on.
Next: Configuration covers CLAUDE.md, hooks, permissions, and cost management. Or go back to the Claude Code overview.