Claude Code Configuration & Workflows
This domain covers how to configure Claude Code and design effective human-Claude workflows: structuring CLAUDE.md memory across the user/project/directory hierarchy, building custom slash commands and skills, scoping conventions to file paths, choosing plan mode vs direct execution, refining results iteratively, and running Claude Code non-interactively in CI/CD. The unifying theme is context management: Claude starts every session with a fresh context window that fills fast and degrades as it fills, so the right configuration loads the right instructions at the right time. Mastery means knowing which mechanism (always-loaded CLAUDE.md, on-demand skills, path-scoped rules, forked subagents, headless flags) fits each need, and avoiding the traps that bloat context or misplace shared instructions.
- 01Memorize the CLAUDE.md load order from broadest to most specific: managed policy -> user (~/.claude/CLAUDE.md) -> project (./CLAUDE.md or ./.claude/CLAUDE.md) -> local (CLAUDE.local.md). More specific loads later and effectively wins on conflicts.
- 02Diagnostic trap to recognize: instructions a teammate isn't getting are almost always in user-level (~/.claude) config, which is never shared via version control. The fix is moving them to project-level config that's committed to git.
- 03Know the three loading models cold: CLAUDE.md and .claude/rules/ load every session (or when matching paths open); skills load only when invoked or deemed relevant; context: fork runs a skill in an isolated subagent that returns only a summary.
- 04Plan mode = read-only research/proposal before edits, entered with Shift+Tab or /plan or --permission-mode plan. Use it for multi-file/architectural/unfamiliar work; skip it when 'you could describe the diff in one sentence.'
- 05For CI/CD remember the exact flags: -p / --print for non-interactive, --output-format json, and --json-schema to enforce a schema (result lands in the structured_output field). Built-in skills like /code-review are interactive-only and unavailable in -p mode.
- 06Independent review beats self-review: a fresh-context instance or subagent reviewing a diff is more effective than the same session that wrote it. This applies to CI review jobs and the Writer/Reviewer pattern.
- 07Path-scoped rules use YAML frontmatter `paths:` with glob patterns and beat subdirectory CLAUDE.md files when a convention spans many directories (e.g. **/*.test.tsx for all test files).
- 08Iterative refinement order matters: give concrete input/output examples for ambiguous transformations, batch interacting fixes in one message, fix independent issues sequentially, and use the interview (AskUserQuestion) pattern to surface considerations before building.
Configure CLAUDE.md files with appropriate hierarchy, scoping, and modular organization
Official objective — Knowledge & Skills
- The CLAUDE.md configuration hierarchy: user-level (~/.claude/CLAUDE.md), project-level (.claude/CLAUDE.md or root CLAUDE.md), and directory-level (subdirectory CLAUDE.md files)
- That user-level settings apply only to that user—instructions in ~/.claude/CLAUDE.md are not shared with teammates via version control
- The @import syntax for referencing external files to keep CLAUDE.md modular (e.g., importing specific standards files relevant to each package)
- .claude/rules/ directory for organizing topic-specific rule files as an alternative to a monolithic CLAUDE.md
- Diagnosing configuration hierarchy issues (e.g., a new team member not receiving instructions because they're in user-level rather than project-level configuration)
- Using @import to selectively include relevant standards files in each package's CLAUDE.md based on maintainer domain knowledge
- Splitting large CLAUDE.md files into focused topic-specific files in .claude/rules/ (e.g., testing.md, api-conventions.md, deployment.md)
- Using the /memory command to verify which memory files are loaded and diagnose inconsistent behavior across sessions
CLAUDE.md files are markdown instructions Claude reads at the start of every session. They exist in a hierarchy loaded from broadest to most specific scope, so more-specific files appear later in context and effectively override broader ones on conflict. The order is: managed policy (e.g. macOS /Library/Application Support/ClaudeCode/CLAUDE.md, org-wide, cannot be excluded), user (~/.claude/CLAUDE.md, personal, all your projects), project (./CLAUDE.md or ./.claude/CLAUDE.md, shared with the team via version control), and local (./CLAUDE.local.md, personal per-project, gitignored). Claude also walks up the directory tree concatenating ancestor files, and discovers subdirectory CLAUDE.md files on demand when it reads files there.
The critical scoping rule for diagnostics: user-level settings apply only to you and are never shared with teammates via git. If a new team member isn't receiving an instruction, it likely lives in ~/.claude/CLAUDE.md (or CLAUDE.local.md) rather than the committed project CLAUDE.md. The fix is to move it to ./CLAUDE.md.
Keep files modular. The @path/to/import syntax expands external files into context at launch; both relative (resolved relative to the importing file) and absolute/~/ paths work, and imports can recurse up to a maximum depth of four hops. This lets each package's CLAUDE.md selectively import only the standards files its maintainer knows are relevant. The first time Claude encounters imports in a project it shows an approval dialog.
For larger codebases, prefer the .claude/rules/ directory: drop topic-specific files like testing.md, api-conventions.md, deployment.md. All .md files there load automatically (no import needed) with the same priority as .claude/CLAUDE.md, are committed to source control, and are easier for teams to maintain than one monolithic file. Target under ~200 lines per CLAUDE.md; bloated files reduce adherence.
Use the /memory command to list every CLAUDE.md, CLAUDE.local.md, and rules file loaded in the current session. If a file isn't listed, Claude can't see it - the first step in diagnosing inconsistent behavior across sessions.
See @README.md for project overview and @package.json for npm commands.
# Standards
- API conventions: @docs/api-standards.md
- Git workflow: @docs/git-instructions.md
- Personal overrides: @~/.claude/my-project-instructions.mdyour-project/
.claude/
CLAUDE.md # Main project instructions
rules/
testing.md # Testing conventions
api-conventions.md
deployment.md| Trap | Why it fails | Correct pattern |
|---|---|---|
| Putting team-wide project instructions in ~/.claude/CLAUDE.md (user level). | User-level config is personal and never committed, so teammates never receive it - the classic symptom of a new hire not getting expected instructions. | Put shared instructions in the committed project ./CLAUDE.md (or ./.claude/CLAUDE.md); reserve ~/.claude/CLAUDE.md for personal preferences only. |
| Letting one monolithic CLAUDE.md grow to hundreds of lines. | Long files consume more context and reduce adherence - Claude starts ignoring rules buried in the noise. | Split into focused .claude/rules/*.md topic files (and path-scope where possible); target under ~200 lines per file. |
- Load order broadest-to-specific: managed policy -> user (~/.claude/CLAUDE.md) -> project (./CLAUDE.md or ./.claude/CLAUDE.md) -> local (CLAUDE.local.md); later/more-specific wins on conflict.
- User-level config (~/.claude/CLAUDE.md) is personal and NOT shared via git; project-level CLAUDE.md is shared with the team through version control.
- @import syntax pulls in external files (relative or absolute/~ paths) at launch; recursion is capped at a maximum depth of four hops.
- Imported files still load into the context window at launch - imports aid organization, not token savings.
- Use .claude/rules/ topic files (testing.md, api-conventions.md, deployment.md) as a modular alternative to a monolithic CLAUDE.md; they load automatically without imports.
- Run /memory to verify which memory/rules files are loaded and diagnose inconsistent cross-session behavior.
Create and configure custom slash commands and skills
Official objective — Knowledge & Skills
- Project-scoped commands in .claude/commands/ (shared via version control) vs user-scoped commands in ~/.claude/commands/ (personal)
- Skills in .claude/skills/ with SKILL.md files that support frontmatter configuration including context: fork, allowed-tools, and argument-hint
- The context: fork frontmatter option for running skills in an isolated sub-agent context, preventing skill outputs from polluting the main conversation
- Personal skill customization: creating personal variants in ~/.claude/skills/ with different names to avoid affecting teammates
- Creating project-scoped slash commands in .claude/commands/ for team-wide availability via version control
- Using context: fork to isolate skills that produce verbose output (e.g., codebase analysis) or exploratory context (e.g., brainstorming alternatives) from the main session
- Configuring allowed-tools in skill frontmatter to restrict tool access during skill execution (e.g., limiting to file write operations to prevent destructive actions)
- Using argument-hint frontmatter to prompt developers for required parameters when they invoke the skill without arguments
- Choosing between skills (on-demand invocation for task-specific workflows) and CLAUDE.md (always-loaded universal standards)
Skills extend Claude Code with reusable instructions packaged as a SKILL.md file inside a skill directory. Where the skill lives sets its scope: project skills in .claude/skills/<name>/SKILL.md are committed and shared with the team; personal skills in ~/.claude/skills/<name>/SKILL.md apply across all your projects and aren't shared. Custom commands have merged into skills - a file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy. The directory name becomes the command you type; the frontmatter name is only a display label.
Key frontmatter fields: description (how Claude decides when to load it - put the key use case first), argument-hint (autocomplete hint like [issue-number] shown when the developer invokes without args), allowed-tools (pre-approves listed tools so Claude uses them without prompting while the skill is active - it grants, it does not by itself restrict), context: fork (run in an isolated subagent), agent (which subagent type when forking: Explore, Plan, general-purpose), and disable-model-invocation: true (only you can trigger it - use for side-effecting workflows like deploy/commit).
context: fork is the isolation lever: the SKILL.md content becomes the subagent's prompt, it runs without your conversation history, and only a summary returns to the main session. Use it for skills that produce verbose output (codebase analysis) or exploratory context (brainstorming alternatives) you don't want polluting the main conversation. Forking only makes sense for skills with an actual task, not pure reference guidelines.
For personal customization without affecting teammates, create a personal variant in ~/.claude/skills/ under a different name rather than editing the shared project skill.
Choosing skills vs CLAUDE.md: CLAUDE.md is always-loaded universal standards (facts that apply in every session); skills load on demand only when invoked or deemed relevant, so long task-specific procedures cost almost nothing until needed. Move a CLAUDE.md section to a skill once it becomes a multi-step procedure rather than a standing fact.
---
name: deep-research
description: Research a topic thoroughly across the codebase
context: fork
agent: Explore
argument-hint: [topic]
---
Research $ARGUMENTS thoroughly:
1. Find relevant files with Glob and Grep
2. Read and analyze the code
3. Summarize findings with specific file references---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
allowed-tools: Bash(git push *) Bash(npm run build)
---
Deploy $ARGUMENTS to production:
1. Run the test suite
2. Build
3. Push to the deployment target| Trap | Why it fails | Correct pattern |
|---|---|---|
| Putting an always-relevant convention (e.g. universal code style) into a skill instead of CLAUDE.md. | Skills load only on demand, so a convention you want applied every session may never load when needed. | Use CLAUDE.md (or .claude/rules/) for always-loaded standards; reserve skills for task-specific, on-demand procedures. |
| Leaving a side-effecting workflow (deploy, commit, send-message) auto-invocable by Claude. | Claude may decide to run it on its own when code 'looks ready,' triggering unintended deploys. | Set disable-model-invocation: true so only you can trigger it with /name, and scope allowed-tools narrowly. |
| Adding context: fork to a skill that is pure reference guidelines with no task. | The forked subagent receives guidelines but no actionable prompt and returns without meaningful output. | Only fork skills that contain an explicit task; keep reference-only content inline (no fork). |
- Project skills (.claude/skills/) are shared via git; personal skills (~/.claude/skills/) are yours across all projects.
- Custom commands merged into skills: .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both create /deploy.
- context: fork runs the skill in an isolated subagent so verbose/exploratory output returns as a summary instead of polluting the main conversation.
- allowed-tools pre-approves tools for the active skill (read-only research, restricted writes); disable-model-invocation: true makes a skill manual-only for side-effecting workflows.
- argument-hint provides an autocomplete hint for expected parameters; $ARGUMENTS / $0,$1 inject the passed args.
- Skills = on-demand task-specific workflows; CLAUDE.md = always-loaded universal standards. Make a personal variant under a new name to avoid affecting teammates.
Apply path-specific rules for conditional convention loading
Official objective — Knowledge & Skills
- .claude/rules/ files with YAML frontmatter paths fields containing glob patterns for conditional rule activation
- How path-scoped rules load only when editing matching files, reducing irrelevant context and token usage
- The advantage of glob-pattern rules over directory-level CLAUDE.md files for conventions that span multiple directories (e.g., test files spread throughout a codebase)
- Creating .claude/rules/ files with YAML frontmatter path scoping (e.g., paths: ["terraform/**/*"]) so rules load only when editing matching files
- Using glob patterns in path-specific rules to apply conventions to files by type regardless of directory location (e.g., **/*.test.tsx for all test files)
- Choosing path-specific rules over subdirectory CLAUDE.md files when conventions must apply to files spread across the codebase
Path-specific rules let conventions load conditionally, only when Claude works with files matching a glob pattern, instead of consuming context in every session. They live as markdown files in .claude/rules/ with YAML frontmatter containing a paths field of glob patterns. A rule WITHOUT a paths field loads unconditionally (same priority as .claude/CLAUDE.md); a rule WITH paths triggers only when Claude reads files matching the pattern, not on every tool use.
Glob patterns match by extension, directory, or any combination - for example **/*.ts (all TypeScript anywhere), src/**/* (everything under src/), *.md (markdown in the project root), src/components/*.tsx (a specific directory). You can list multiple patterns and use brace expansion to cover several extensions in one entry, e.g. src/**/*.{ts,tsx}.
The central skill is choosing path-specific rules over subdirectory (directory-level) CLAUDE.md files when a convention applies to files by TYPE regardless of where they live. Test files, for instance, are scattered throughout a codebase; a single .claude/rules/testing.md scoped to paths: ["**/*.test.tsx"] applies your testing conventions everywhere those files appear and loads only when one is opened. Achieving the same coverage with directory-level CLAUDE.md files would require duplicating the convention into every directory that contains tests, and those files would still load whenever Claude works anywhere in that directory tree. Path scoping reduces irrelevant context and token usage by loading the convention precisely when it's relevant.
The paths glob format is the same one used by skill frontmatter paths, so the mental model transfers between rules and skills. Rules in .claude/rules/ are committed to source control, so the whole team inherits the conditional conventions, and they support symlinks for sharing across projects.
---
paths:
- "**/*.test.tsx"
- "tests/**/*.test.ts"
---
# Test conventions
- Name tests with describe/it blocks matching the component name
- Avoid mocks; prefer real fixtures from tests/fixtures/---
paths:
- "terraform/**/*"
---
# Terraform conventions
- Pin provider versions
- All resources must include the standard tags block| Trap | Why it fails | Correct pattern |
|---|---|---|
| Duplicating a cross-cutting convention into a subdirectory CLAUDE.md in every folder that contains the relevant file type. | Conventions for files spread across the codebase (e.g. tests) require copies in many directories, drift out of sync, and load even when irrelevant. | Write one .claude/rules/ file with a glob `paths:` (e.g. **/*.test.tsx) so the convention applies by file type and loads only when a matching file is opened. |
- .claude/rules/ files use YAML frontmatter `paths:` with glob patterns; the rule loads only when Claude reads a matching file.
- A rule with no `paths` field loads unconditionally with the same priority as .claude/CLAUDE.md.
- Glob patterns match by type/location regardless of directory, e.g. `**/*.test.tsx` for all test files or `src/**/*.{ts,tsx}` via brace expansion.
- Prefer path-specific rules over subdirectory CLAUDE.md when a convention spans many directories - it avoids duplication and irrelevant context.
- Path scoping reduces token usage by loading conventions precisely when matching files are in play.
Determine when to use plan mode vs direct execution
Official objective — Knowledge & Skills
- Plan mode is designed for complex tasks involving large-scale changes, multiple valid approaches, architectural decisions, and multi-file modifications
- Direct execution is appropriate for simple, well-scoped changes (e.g., adding a single validation check to one function)
- Plan mode enables safe codebase exploration and design before committing to changes, preventing costly rework
- The Explore subagent for isolating verbose discovery output and returning summaries to preserve main conversation context
- Selecting plan mode for tasks with architectural implications (e.g., microservice restructuring, library migrations affecting 45+ files, choosing between integration approaches with different infrastructure requirements)
- Selecting direct execution for well-understood changes with clear scope (e.g., a single-file bug fix with a clear stack trace, adding a date validation conditional)
- Using the Explore subagent for verbose discovery phases to prevent context window exhaustion during multi-phase tasks
- Combining plan mode for investigation with direct execution for implementation (e.g., planning a library migration, then executing the planned approach)
Plan mode tells Claude to research and propose changes without making them: it reads files and runs read-only exploration but does not edit your source until you approve a plan. Enter it by pressing Shift+Tab to cycle (default -> acceptEdits -> plan), prefixing a single prompt with /plan, or starting with claude --permission-mode plan; set permissions.defaultMode: "plan" in .claude/settings.json to make it the project default. Press Ctrl+G to open the proposed plan in your editor before Claude proceeds; approving exits plan mode into an execution mode (auto, accept edits, or manual review).
Plan mode is designed for complex work: large-scale changes, multiple valid approaches, architectural decisions, and multi-file modifications - for example microservice restructuring, a library migration affecting 45+ files, or choosing between integration approaches with different infrastructure requirements. It enables safe exploration and design before committing, preventing costly rework from solving the wrong problem.
Direct execution is appropriate for simple, well-scoped changes where you already know what needs to happen: a single-file bug fix with a clear stack trace, adding one date-validation conditional, a typo, a log line, or a rename. The official heuristic: 'If you could describe the diff in one sentence, skip the plan.' Plan mode adds overhead, so don't apply it to trivial changes.
The two combine well: plan mode for investigation, then direct execution for the planned implementation (plan a library migration, then execute the approved approach). For the verbose discovery phase, use the Explore subagent - a read-only agent optimized for codebase exploration that runs investigation in an isolated context and returns only a summary, so raw file contents never enter and exhaust your main conversation. This is the recommended pattern for multi-phase tasks: explore (in a subagent), plan, then implement.
claude --permission-mode planUse subagents to investigate how our auth system handles token refresh
and whether existing OAuth utilities exist to reuse. Report back a summary.| Trap | Why it fails | Correct pattern |
|---|---|---|
| Using plan mode for a trivial, well-scoped change like a typo fix or a single-line conditional. | Plan mode adds research/approval overhead with no benefit when the diff is obvious and one-sentence describable. | Ask Claude to make small, clear changes directly; reserve plan mode for multi-file, architectural, or unfamiliar work. |
| Letting Claude read hundreds of files in the main conversation during open-ended 'investigate this' exploration. | Raw file contents flood the context window and degrade performance for the actual implementation. | Scope the investigation narrowly or run it in the Explore subagent so only a summary returns to the main context. |
- Plan mode is read-only: Claude researches and proposes a plan but makes no edits until you approve.
- Enter via Shift+Tab cycle, /plan prefix, --permission-mode plan, or defaultMode plan; Ctrl+G edits the plan before proceeding.
- Use plan mode for complex/architectural/multi-file/unfamiliar work; use direct execution for simple, clearly-scoped changes.
- Heuristic: if you could describe the diff in one sentence, skip the plan - planning adds overhead.
- Combine plan mode (investigation) with direct execution (implementation) for a single migration-style task.
- The Explore subagent isolates verbose discovery in a separate read-only context and returns a summary, preserving main-conversation context.
Apply iterative refinement techniques for progressive improvement
Official objective — Knowledge & Skills
- Concrete input/output examples as the most effective way to communicate expected transformations when prose descriptions are interpreted inconsistently
- Test-driven iteration: writing test suites first, then iterating by sharing test failures to guide progressive improvement
- The interview pattern: having Claude ask questions to surface considerations the developer may not have anticipated before implementing
- When to provide all issues in a single message (interacting problems) versus fixing them sequentially (independent problems)
- Providing 2-3 concrete input/output examples to clarify transformation requirements when natural language descriptions produce inconsistent results
- Writing test suites covering expected behavior, edge cases, and performance requirements before implementation, then iterating by sharing test failures
- Using the interview pattern to surface design considerations (e.g., cache invalidation strategies, failure modes) before implementing solutions in unfamiliar domains
- Providing specific test cases with example input and expected output to fix edge case handling (e.g., null values in migration scripts)
- Addressing multiple interacting issues in a single detailed message when fixes interact, versus sequential iteration for independent issues
Iterative refinement is the practice of converging on correct output through tight feedback loops rather than expecting a perfect first pass. The most reliable lever when prose is interpreted inconsistently is concrete input/output examples: provide 2-3 example pairs that pin down the exact transformation you expect. Natural-language descriptions of a transformation are ambiguous; examples are not.
Test-driven iteration is the strongest verification loop. Write a test suite first that covers expected behavior, edge cases, and performance requirements, then iterate by sharing the failing test output back to Claude so each pass is guided by a concrete pass/fail signal. Giving Claude a check it can run itself (tests, a build, a screenshot diff) is what lets it close the loop without you as the verification bottleneck. For a specific edge case (e.g. null values in a migration script), hand over a precise test case with example input and expected output.
The interview pattern surfaces design considerations you may not have anticipated before any code is written. Start with a minimal prompt and ask Claude to interview you using the AskUserQuestion tool - it probes technical implementation, UI/UX, edge cases, failure modes, and tradeoffs (such as cache invalidation strategies), then can write a self-contained spec. This is especially valuable in unfamiliar domains. Run the implementation in a fresh session against the written spec.
Knowing how to batch feedback matters: when problems interact (a fix for one affects another), provide all of them in a single detailed message so Claude can reason about them together; when problems are independent, fix them sequentially. Correcting the same issue more than twice usually means context is polluted with failed approaches - clear it and restart with a sharper prompt incorporating what you learned, rather than piling on more corrections.
Write a validateEmail function. Examples:
user@example.com -> true
invalid -> false
user@.com -> false
Run the tests after implementing and fix until they pass.I want to build a write-through cache layer. Interview me in detail using
the AskUserQuestion tool. Ask about invalidation strategy, failure modes,
edge cases, and tradeoffs. Then write a complete spec to SPEC.md.| Trap | Why it fails | Correct pattern |
|---|---|---|
| Describing a transformation only in prose and re-correcting when output drifts. | Prose descriptions are interpreted inconsistently, so each attempt can diverge in a different direction. | Supply 2-3 concrete input/output example pairs (and a test to run) so the expected transformation is unambiguous. |
| Fixing several interacting bugs one message at a time. | A fix for one interacting issue can break another, causing oscillation across turns. | When fixes interact, present all the issues in a single detailed message; reserve sequential fixes for independent problems. |
- Provide 2-3 concrete input/output example pairs when prose produces inconsistent results - examples disambiguate transformations.
- Test-driven iteration: write tests covering behavior, edge cases, and performance first, then iterate by sharing test failures.
- Give Claude a runnable check (tests/build/screenshot diff) so it can close the loop itself instead of relying on you to spot every mistake.
- Use the interview pattern (AskUserQuestion) to surface edge cases, failure modes, and tradeoffs before implementing, especially in unfamiliar domains.
- Batch interacting fixes into one detailed message; fix independent issues sequentially.
- After ~2 failed corrections, /clear and restart with a sharper prompt rather than accumulating failed-approach context.
Integrate Claude Code into CI/CD pipelines
Official objective — Knowledge & Skills
- The -p (or --print) flag for running Claude Code in non-interactive mode in automated pipelines
- --output-format json and --json-schema CLI flags for enforcing structured output in CI contexts
- CLAUDE.md as the mechanism for providing project context (testing standards, fixture conventions, review criteria) to CI-invoked Claude Code
- Session context isolation: why the same Claude session that generated code is less effective at reviewing its own changes compared to an independent review instance
- Running Claude Code in CI with the -p flag to prevent interactive input hangs
- Using --output-format json with --json-schema to produce machine-parseable structured findings for automated posting as inline PR comments
- Including prior review findings in context when re-running reviews after new commits, instructing Claude to report only new or still-unaddressed issues to avoid duplicate comments
- Providing existing test files in context so test generation avoids suggesting duplicate scenarios already covered by the test suite
- Documenting testing standards, valuable test criteria, and available fixtures in CLAUDE.md to improve test generation quality and reduce low-value test output
Claude Code runs non-interactively for CI/CD with the -p (or --print) flag, which sends a single prompt and prints the result without starting an interactive session - essential so a pipeline never hangs waiting for input. Pair it with --allowedTools (or a locked-down permission mode like dontAsk) so tool calls don't block on approval prompts, and --append-system-prompt to inject a role such as a security reviewer.
For machine-parseable findings, use --output-format json to wrap the response with metadata (result, session_id, cost, usage). To enforce a specific shape, add --json-schema with a JSON Schema definition; the structured result is returned in the structured_output field (the plain text answer is in result). This produces deterministic objects you can pipe into jq and post as inline PR comments. (Note: text, json, and stream-json are the three output formats; stream-json is for real-time streaming.)
CLAUDE.md is the mechanism for giving CI-invoked Claude project context it can't infer: testing standards, valuable-test criteria, available fixtures, and review criteria. Documenting these improves test-generation quality and cuts low-value output. Provide existing test files in context so generated tests don't duplicate scenarios already covered, and include prior review findings when re-running after new commits, instructing Claude to report only new or still-unaddressed issues to avoid duplicate comments.
Session context isolation is the key quality principle: the same session that generated code is biased toward it and is a weaker reviewer than an independent instance. A fresh-context review (a new claude -p invocation, a subagent, or the bundled /code-review in interactive use) sees only the diff and criteria, so it evaluates on its own terms. Remember that user-invoked skills and built-in commands like /code-review are interactive-only and not available in -p mode; in headless runs, describe the task directly instead.
claude -p "Review this diff and list issues" \
--output-format json \
--json-schema '{"type":"object","properties":{"findings":{"type":"array","items":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"integer"},"issue":{"type":"string"}}}}},"required":["findings"]}' \
| jq '.structured_output'gh pr diff "$1" | claude -p \
--append-system-prompt "You are a security engineer. Review for vulnerabilities." \
--output-format json| Trap | Why it fails | Correct pattern |
|---|---|---|
| Invoking Claude Code interactively (no -p) or without pre-approved tools in a CI job. | The run blocks on permission prompts or waits for interactive input and the pipeline hangs. | Use claude -p with --allowedTools (or --permission-mode dontAsk) so the run is fully non-interactive. |
| Re-running a review on each new commit without supplying prior findings. | Claude re-reports already-flagged issues, spamming the PR with duplicate comments. | Pass prior findings in context and instruct Claude to report only new or still-unaddressed issues. |
| Reusing the same session that wrote the code to also review it. | The authoring session is biased toward its own implementation and misses its own edge cases. | Run review in an independent instance/subagent (fresh context) that sees only the diff and criteria. |
- Use -p / --print for non-interactive CI runs so the pipeline never hangs on input.
- --output-format json returns structured metadata; --json-schema enforces a schema with the result in the structured_output field (parse with jq).
- Pre-approve tools with --allowedTools (or dontAsk permission mode) so headless runs don't block on permission prompts.
- CLAUDE.md supplies CI context: testing standards, valuable-test criteria, available fixtures, review criteria.
- Include existing tests so generated tests avoid duplicates; include prior findings and report only new/unaddressed issues to avoid duplicate PR comments.
- An independent review instance reviews changes better than the session that wrote them - context isolation reduces self-review bias.
- Built-in skills like /code-review are interactive-only and unavailable in -p mode; describe the task directly in headless runs.
Drill Claude Code Configuration & Workflows
19 scenario-based questions, timed, with full explanations.
Start the Claude drill →