Claude Code Prompts: CLAUDE.md, Custom Commands, and Prompt Engineering
Claude Code v2.1.193 assembles over 500 distinct prompt fragments at session start, but developers control their experience through three layers: CLAUDE.md project files for persistent context, custom slash commands for reusable workflows, and Agent SDK options for programmatic configuration. Each layer has specific scoping, caching, and composition rules that determine how instructions reach the model.
How Claude Code Assembles Its Prompt Stack
The Piebald-AI analysis of Claude Code v2.1.193 cataloged 515 distinct prompt fragments that the tool conditionally assembles at session start. The base system prompt runs 2,300 to 3,600 tokens depending on your session mode, while tool definitions add another 14,000 to 17,000 tokens. Most developers never touch these internal prompts directly. Instead, they work with three controllable layers that sit on top.
The first layer is CLAUDE.md files. These are markdown documents placed in your project root, home directory, or specific subdirectories. Claude Code reads them at session start and injects their content into the conversation as project context. They persist across sessions and can be committed to version control.
The second layer is custom slash commands. These are markdown files stored in .claude/commands/ that define reusable prompt templates. Type /command-name during a session and Claude executes the prompt with any arguments you pass.
The third layer is the Agent SDK system prompt API. When you build tools on top of Claude Code programmatically, the SDK lets you choose between the full Claude Code preset, the preset with appended instructions, or a completely custom system prompt string.
Each layer serves a different purpose. CLAUDE.md handles persistent project context that every session needs. Custom commands handle repeatable workflows you run on demand. The SDK handles programmatic control when you are shipping a product built on Claude Code. Understanding when to use each one prevents the common mistake of cramming everything into a single CLAUDE.md file that grows past the recommended 200-line limit.
How to Write an Effective CLAUDE.md File
CLAUDE.md is the single most impactful prompt configuration in Claude Code. It loads automatically every session, so Claude starts with your project's conventions instead of guessing from code alone.
Three Scopes, Merged Automatically
Claude Code reads CLAUDE.md files from three locations and merges them from broad to specific:
- User-level (
~/.claude/CLAUDE.md): Personal preferences like your default package manager, testing habits, or formatting rules. These apply to every project on your machine. - Project-level (
<repo-root>/CLAUDE.mdor.claude/CLAUDE.md): Architecture overview, build commands, naming conventions, and hard constraints. This is the primary file most teams maintain. - Subdirectory-level (
<subdir>/CLAUDE.md): Module-specific rules loaded on demand when Claude accesses files in that directory. Useful for monorepos where different packages follow different conventions.
The SDK injects CLAUDE.md content into the conversation as a user message following the system prompt. This means CLAUDE.md works with any system prompt configuration, including fully custom ones.
Caching and Cost
Anthropic's prompt caching applies to CLAUDE.md content. The first request in a session pays the full token cost. Subsequent requests within roughly five minutes hit the cache at reduced rates. Any edit to the file invalidates the cache, triggering full-price billing on the next request.
In practice, a substantial CLAUDE.md costs full tokens once per session start, plus once after extended idle periods. It does not cost full tokens per message.
What to Include
High-signal content that saves Claude from guessing:
- Build, test, and lint commands:
npm run test:unit,make lint,cargo build --release. Accuracy matters because Claude will execute these. - Naming conventions: "Use camelCase for variables, PascalCase for components, snake_case for database columns."
- Architecture overview: Three sentences covering major components and how they connect. Not a full design doc.
- Hard constraints: "Never write production data in tests." "All API routes require authentication middleware."
- Known gotchas: "The Redis client silently reconnects, so connection errors surface as timeouts, not connection refused."
What to Skip
Content that wastes context without improving results:
- Full API documentation (Claude reads code directly)
- Changelogs or project history (git log exists)
- Obvious information from file structure
- Aspirational rules the team does not actually follow
Getting Started
Run /init in Claude Code to auto-generate a draft CLAUDE.md. It inspects your build commands, test setup, directory structure, and detected conventions. Review the output, trim anything redundant, and commit it. The whole process takes about five minutes.
To edit CLAUDE.md mid-session, use /memory or ask Claude directly to remember a rule. Claude appends the instruction to the appropriate scope file automatically.
Give your Claude Code agents a persistent shared workspace
Shared storage for agent outputs, versioned files, and team collaboration. Connect Claude Code to the Fast.io MCP server at /mcp for direct workspace access. Starts with a 14-day free trial.
Building Custom Slash Commands
Custom slash commands turn prompts you type repeatedly into one-word shortcuts. Each command is a markdown file that becomes available as /command-name during any Claude Code session.
File Location and Naming
Create markdown files in one of two directories:
- Project commands (
.claude/commands/): Shared with your team through version control. Available only in the current project. - Personal commands (
~/.claude/commands/): Available across all your projects. Good for personal workflow shortcuts.
The filename without the .md extension becomes the command name. A file at .claude/commands/review.md creates the /review command.
Basic Command Format
The simplest command is a markdown file containing the prompt text:
Review the current file for security vulnerabilities.
Check for SQL injection, XSS, exposed credentials,
and insecure configurations.
Save this as .claude/commands/security-check.md and type /security-check to run it.
Arguments and Placeholders
Commands accept dynamic arguments through placeholders:
$ARGUMENTScaptures everything after the command name$1,$2, etc. capture positional arguments
A file at .claude/commands/fix-issue.md might contain:
Fix issue #$1 with priority $2.
Check the issue description and implement the
necessary changes. Run tests after making changes.
Typing /fix-issue 42 high replaces $1 with "42" and $2 with "high".
Frontmatter for Advanced Configuration Optional YAML frontmatter controls tool access, model selection, and documentation:
---
allowed-tools: Read, Grep, Glob, Bash(git diff *)
description: Review recent code changes
model: claude-opus-4-7
argument-hint: [branch-name]
---
### Changed Files
!`git diff --name-only $1`
### Detailed Changes
!`git diff $1`
Review these changes for bugs, security issues,
and performance problems.
The allowed-tools field restricts which tools the command can use. The ! prefix before backtick commands executes them and embeds the output into the prompt. The @ prefix includes file contents inline: writing @package.json embeds your full package.json.
Organization with Subdirectories
Structure commands in subdirectories for larger projects:
.claude/commands/
├── frontend/
│ ├── component.md
│ └── style-check.md
├── backend/
│ ├── api-test.md
│ └── db-migrate.md
└── review.md
The subdirectory appears in the command description but does not change the command name.
The Skills Migration Anthropic now recommends .claude/skills/<name>/SKILL.md as the successor format to .claude/commands/. Skills support the same slash-command invocation plus autonomous invocation by Claude during a session. The commands format still works, and the CLI continues to support it. New projects should consider the skills format for forward compatibility.
Customizing System Prompts with the Agent SDK
When you build tools on top of Claude Code programmatically, the Agent SDK gives you four starting points for the system prompt. The right choice depends on how closely your product resembles the Claude Code CLI.
The claude_code Preset
Use this when building a CLI or IDE-like coding tool where a human watches and steers the work. You get the full Claude Code prompt with tool guidance, safety rules, code-style conventions, and environment awareness.
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Add input validation to the signup form",
options: {
systemPrompt: {
type: "preset",
preset: "claude_code"
}
}
})) {
// Full Claude Code behavior
}
Preset with Append
The lowest-risk customization. You keep everything from the preset and add your own instructions at the end. Nothing is removed.
const options = {
systemPrompt: {
type: "preset",
preset: "claude_code",
append: "Always write Python type hints. Follow Google docstring format."
}
};
This approach works well for adding coding standards, output formatting rules, or domain-specific constraints without reimplementing the tool guidance and safety rules that the preset already provides.
Custom String
Replace the system prompt entirely. You take responsibility for including any tool guidance and safety instructions your agent needs.
const options = {
systemPrompt: `You are a database migration specialist.
Only modify migration files and schema definitions.
Never touch application code directly.`
};
Use this when your agent has a different surface (not a terminal), a different identity (not Claude Code), or a different permission model (no human in the loop).
No System Prompt
When you omit systemPrompt, the SDK uses a minimal default that covers tool calling but skips Claude Code's coding guidelines, response style, and project context. This differs from claude -p, which uses the full preset by default.
Cross-Session Cache Optimization By default, two sessions using the same preset and append text cannot share a prompt cache entry if they run from different directories. The preset embeds per-session context (working directory, git status, platform, shell) in the system prompt.
Set excludeDynamicSections: true to move per-session context into the first user message, making the system prompt identical across sessions:
const options = {
systemPrompt: {
type: "preset",
preset: "claude_code",
append: "Follow internal triage workflow.",
excludeDynamicSections: true
}
};
The tradeoff: instructions in the user message carry slightly less weight than the same text in the system prompt. Enable this when cross-session cache reuse matters more than maximally authoritative environment context.
CLAUDE.md Still Works with Custom Prompts
CLAUDE.md content is injected into the conversation, not into the system prompt. This means it works regardless of which system prompt approach you choose. Even with a fully custom string, setting settingSources: ["project"] loads your project-level CLAUDE.md alongside whatever system prompt you configured.
What Prompt Patterns Actually Improve Results
The official Claude Code prompt library organizes effective prompts by development phase. These patterns work because they give Claude specific constraints rather than open-ended instructions.
Be Specific About Output Format
Instead of "review this code," specify the output structure:
Review src/auth/session.ts for security issues.
For each finding, provide:
1. The specific line or code block
2. The vulnerability type (OWASP category)
3. A concrete fix with code
Rate overall security 1-10.
Use File References for Context
When Claude needs to understand existing patterns before making changes, reference the files directly in your prompt or custom command:
Look at @src/components/Button.tsx for our component pattern.
Create a new Dropdown component following the same structure,
prop naming, and test conventions.
Combine Discovery and Action
The most effective prompts pair a discovery step with an action step:
Find all API endpoints that don't have rate limiting.
For each one, add rate limiting middleware using the
pattern in @src/middleware/rateLimit.ts.
This pattern works because Claude can verify its own discovery before acting. Single-step prompts that assume the codebase state often make incorrect changes.
Version and Share Prompts Across Teams
Prompt configurations drift across individual machines. One developer's CLAUDE.md tells Claude to use Prettier, while another's specifies ESLint formatting. Custom commands diverge as team members build their own variations.
Version control solves part of this problem: commit .claude/commands/ and the project-level CLAUDE.md to your repository. For teams running Claude Code agents in production, the outputs those agents generate need a persistent home too. Local filesystems work for solo developers, but teams need shared access with version history and permissions.
Cloud workspaces like Google Drive, Dropbox, or Fast.io let teams centralize agent outputs and reference documents. Fast.io adds an MCP server endpoint that Claude Code agents can connect to directly for reading and writing workspace files, with built-in versioning and Intelligence Mode for semantic search across stored documents. Every org starts with a 14-day free trial, with storage and monthly AI credits scaled to each plan, which covers most small team setups.
Whatever workspace you choose, the principle holds: prompt configurations belong in version control, and agent outputs belong in a shared workspace where both humans and agents can access them.
Frequently Asked Questions
What should I put in CLAUDE.md?
Focus on information Claude cannot infer from your code. Build, test, and lint commands belong at the top because accuracy matters when Claude executes them. Add naming conventions, a three-sentence architecture overview, hard constraints like 'all API routes require auth middleware,' and known gotchas. Skip full API docs, changelogs, and aspirational rules. Target under 200 lines for the best signal-to-noise ratio.
How do I create custom Claude Code commands?
Create a markdown file in `.claude/commands/` with the prompt text as the file body. The filename becomes the command name: `review.md` becomes `/review`. Add optional YAML frontmatter between `---` markers for `allowed-tools`, `description`, `model`, and `argument-hint`. Use `$ARGUMENTS` to capture all input after the command name, `$1` and `$2` for positional arguments, `!` before backtick commands to execute and embed their output, and `@filepath` to include file contents.
Where does Claude Code read its system prompt from?
Claude Code assembles its system prompt from multiple internal sources, with 110+ conditional sections selected based on your configuration. CLAUDE.md files are injected into the conversation as project context, not into the system prompt itself. Custom slash commands are expanded when invoked. If you use the Agent SDK, you can choose the `claude_code` preset, append to it, or replace it entirely with a custom string.
Can I customize Claude Code's behavior per project?
Yes, at multiple levels. A project-level CLAUDE.md at your repo root sets conventions for everyone on the team. Subdirectory CLAUDE.md files add module-specific rules loaded on demand. Project-scoped commands in `.claude/commands/` provide project-specific workflows. User-level files in `~/.claude/` add personal preferences that apply across all projects. Claude merges all of these from broad to specific at session start.
How does CLAUDE.md caching work?
Anthropic's prompt caching applies to CLAUDE.md content. The first request pays the full token cost. Subsequent requests within approximately five minutes hit the cache at reduced rates. Editing the file invalidates the cache, triggering full-price billing on the next request. A substantial CLAUDE.md file costs full tokens once per session start and once after extended idle periods, not per message.
What is the difference between .claude/commands/ and .claude/skills/?
The `.claude/commands/` format is the original way to create custom slash commands. Anthropic now recommends `.claude/skills/<name>/SKILL.md` as the successor format. Skills support both slash-command invocation and autonomous invocation by Claude during a session. The commands format still works and the CLI continues to support both, but new projects should consider skills for forward compatibility.
Related Resources
Give your Claude Code agents a persistent shared workspace
Shared storage for agent outputs, versioned files, and team collaboration. Connect Claude Code to the Fast.io MCP server at /mcp for direct workspace access. Starts with a 14-day free trial.