4 4
5# Modifying system prompts5# Modifying system prompts
6 6
7> Learn how to customize Claude's behavior by modifying system prompts using three approaches - output styles, systemPrompt with append, and custom system prompts.7> Choose between the `claude_code` preset and a custom system prompt, and customize behavior with CLAUDE.md, output styles, append, or a fully custom prompt.
8 8
9System prompts define Claude's behavior, capabilities, and response style. The Claude Agent SDK provides three ways to customize system prompts: using output styles (persistent, file-based configurations), appending to Claude Code's prompt, or using a fully custom prompt.9System prompts define Claude's behavior, capabilities, and response style. Start from the `claude_code` preset for CLI or IDE-like coding tools where a human watches and steers the work. Write your own prompt for agents with a different surface, identity, or permission model.
10 10
11## Understanding system prompts11This page covers:
12 12
13A system prompt is the initial instruction set that shapes how Claude behaves throughout a conversation.13* [How system prompts work](#how-system-prompts-work), with a decision table for choosing between the preset, the preset with `append`, and a custom prompt
14* [Customize agent behavior](#customize-agent-behavior) with CLAUDE.md files, output styles, `append`, or a custom string
15* [Compare the four approaches](#compare-the-four-approaches) by persistence, scope, and what they preserve
16* [Combine approaches](#combine-approaches) to layer customization methods together
14 17
15<Note>18## How system prompts work
16 **Default behavior:** The Agent SDK uses a **minimal system prompt** by default. It contains only essential tool instructions but omits Claude Code's coding guidelines, response style, and project context. To include the full Claude Code system prompt, specify `systemPrompt: { type: "preset", preset: "claude_code" }` in TypeScript or `system_prompt={"type": "preset", "preset": "claude_code"}` in Python.
17</Note>
18
19Claude Code's system prompt includes:
20
21* Tool usage instructions and available tools
22* Code style and formatting guidelines
23* Response tone and verbosity settings
24* Security and safety instructions
25* Context about the current working directory and environment
26
27## Methods of modification
28
29### Method 1: CLAUDE.md files (project-level instructions)
30 19
31CLAUDE.md files provide project-specific context and instructions that are automatically read by the Agent SDK when it runs in a directory. They serve as persistent "memory" for your project.20A system prompt is the initial instruction set that shapes how Claude behaves throughout a conversation. The Agent SDK has three starting points for it:
32 21
33#### How CLAUDE.md works with the SDK22* **Minimal default**: when you don't set `systemPrompt` in TypeScript or `system_prompt` in Python, the SDK uses a minimal prompt that covers tool calling but omits Claude Code's coding guidelines, response style, and project context. This differs from `claude -p`, which uses the full Claude Code prompt by default. If you're migrating from the CLI and want matching behavior, set the `claude_code` preset.
23* **`claude_code` preset**: the full system prompt that the Claude Code CLI uses, with tool usage instructions, code style and formatting guidelines, response tone and verbosity rules, security and safety instructions, and context about the working directory and environment. Set `systemPrompt: { type: "preset", preset: "claude_code" }` in TypeScript or `system_prompt={"type": "preset", "preset": "claude_code"}` in Python, optionally with `append` to add your own instructions on the end.
24* **Custom string**: a prompt you write yourself. The SDK sends only what you provide.
34 25
35**Location and discovery:**26### Decide on a starting point
36 27
37* **Project-level:** `CLAUDE.md` or `.claude/CLAUDE.md` in your working directory28The deciding factor is how closely your agent resembles Claude Code: a coding agent operating in a repository, with a human watching streaming output and steering the work. The further your product is from that, the more you'll want to write your own prompt.
38* **User-level:** `~/.claude/CLAUDE.md` for global instructions across all projects
39 29
40CLAUDE.md files are read when the corresponding setting source is enabled: `'project'` for project-level CLAUDE.md and `'user'` for `~/.claude/CLAUDE.md`. With default `query()` options both sources are enabled, so CLAUDE.md loads automatically. If you set `settingSources` (TypeScript) or `setting_sources` (Python) explicitly, include the sources you need. CLAUDE.md loading is controlled by setting sources, not by the `claude_code` preset.30| You're building | Use | What you get |
31| :----------------------------------------------------------------------------------------------------------- | :--------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- |
32| A CLI or IDE-like coding tool where a human watches and steers, and Claude Code's defaults are what you want | `claude_code` preset | The full Claude Code prompt: tool guidance, safety rules, terminal-friendly responses, repo-convention awareness |
33| The same kind of tool, plus product-specific rules like coding standards, output format, or domain context | `claude_code` preset with `append` | Everything above, with your instructions added after the preset. Nothing is removed, so this is the lowest-risk customization |
34| An agent with a different surface, identity, or permission model, or a non-coding agent | Custom prompt string | Only what you write. You take responsibility for replacing the tool guidance and safety instructions your agent still needs |
35| A thin tool-calling loop with no agent persona, where you supply all behavior in the user prompt | No `systemPrompt` option | The minimal default: tool-calling support and nothing else |
41 36
42**Content format:**37"Different from Claude Code" usually means one of the following:
43CLAUDE.md files use plain markdown and can contain:
44 38
45* Coding guidelines and standards39* **Different surface**: the output isn't read in a terminal by the person who triggered it. Chat UIs, structured-output consumers, and non-coding automation each need a prompt that matches how their output is rendered and reviewed. Unattended coding automation, like a CI job that fixes lint errors or reviews diffs, still fits the preset because the work itself is what the preset is written for.
46* Project-specific context40* **Different identity**: the agent shouldn't present itself as Claude Code. A support bot, a data-analysis assistant, or any domain-specific agent needs its own name, scope, and persona.
47* Common commands or workflows41* **Different permission model**: the agent runs autonomously without a human approving each step, or operates on a narrow set of resources. Claude Code's prompt assumes a human is in the loop with access to a full toolset.
48* API conventions42* **Non-coding tasks**: most of Claude Code's prompt is coding guidance. For research, content, or operations agents, that guidance competes with the instructions you actually need.
49* Testing requirements
50 43
51#### Example CLAUDE.md44The [comparison table](#compare-the-four-approaches) shows what each customization method preserves.
52 45
53```markdown theme={null}46## Customize agent behavior
54# Project Guidelines
55 47
56## Code Style48Output styles, `append`, and a custom prompt string each change the system prompt directly. CLAUDE.md takes a different path: the SDK reads it and injects its content into the conversation as project context, not into the system prompt, so it shapes behavior alongside whichever system prompt you choose. [Skills](/en/agent-sdk/skills), [hooks](/en/agent-sdk/hooks), and [permissions](/en/agent-sdk/permissions) also shape behavior outside the system prompt and are covered on their own pages.
57 49
58- Use TypeScript strict mode50### CLAUDE.md files for project-level instructions
59- Prefer functional components in React
60- Always include JSDoc comments for public APIs
61 51
62## Testing52CLAUDE.md files give Claude persistent project context and instructions. The SDK injects their content into the conversation, not into the system prompt, so they work with any system prompt configuration. For what to put in CLAUDE.md, where to place it, and how to write effective instructions, see [How Claude remembers your project](/en/memory). This section covers what's specific to the SDK: how CLAUDE.md loads.
63 53
64- Run `npm test` before committing54The SDK reads CLAUDE.md when the matching setting source is enabled: `'project'` loads `CLAUDE.md` or `.claude/CLAUDE.md` from the working directory, and `'user'` loads `~/.claude/CLAUDE.md`. Default `query()` options enable both sources, so CLAUDE.md loads automatically. If you set `settingSources` in TypeScript or `setting_sources` in Python explicitly, include the sources you need. CLAUDE.md loading is controlled by setting sources, not by the `claude_code` preset.
65- Maintain >80% code coverage
66- Use jest for unit tests, playwright for E2E
67 55
68## Commands56#### Load CLAUDE.md with the SDK
69 57
70- Build: `npm run build`58To load CLAUDE.md, set `settingSources` to include the level your CLAUDE.md lives at. The example below loads a project-level CLAUDE.md alongside the `claude_code` preset, so Claude has both the full coding-agent prompt and your project's conventions:
71- Dev server: `npm run dev`
72- Type check: `npm run typecheck`
73```
74
75#### Using CLAUDE.md with the SDK
76 59
77<CodeGroup>60<CodeGroup>
78 ```typescript TypeScript theme={null}61 ```typescript TypeScript theme={null}
117 ```100 ```
118</CodeGroup>101</CodeGroup>
119 102
120#### When to use CLAUDE.md103CLAUDE.md is persistent across all sessions in a project, shared with your team through git, and discovered automatically without code changes. It is not loaded if you pass an empty `settingSources` array.
121
122**Best for:**
123
124* **Team-shared context** - Guidelines everyone should follow
125* **Project conventions** - Coding standards, file structure, naming patterns
126* **Common commands** - Build, test, deploy commands specific to your project
127* **Long-term memory** - Context that should persist across all sessions
128* **Version-controlled instructions** - Commit to git so the team stays in sync
129
130**Key characteristics:**
131 104
132* ✅ Persistent across all sessions in a project105### Output styles for persistent configurations
133* ✅ Shared with team via git
134* ✅ Automatic discovery (no code changes needed)
135* ⚠️ Not loaded if you pass `settingSources: []`
136
137### Method 2: Output styles (persistent configurations)
138 106
139Output styles are saved configurations that modify Claude's system prompt. They're stored as markdown files and can be reused across sessions and projects.107Output styles are saved configurations that modify Claude's system prompt. They're stored as markdown files and can be reused across sessions and projects.
140 108
141#### Creating an output style109#### Create an output style
142
143<CodeGroup>
144 ```typescript TypeScript theme={null}
145 import { writeFile, mkdir } from "fs/promises";
146 import { join } from "path";
147 import { homedir } from "os";
148
149 async function createOutputStyle(name: string, description: string, prompt: string) {
150 // User-level: ~/.claude/output-styles
151 // Project-level: .claude/output-styles
152 const outputStylesDir = join(homedir(), ".claude", "output-styles");
153
154 await mkdir(outputStylesDir, { recursive: true });
155
156 const content = `---
157 name: ${name}
158 description: ${description}
159 ---
160
161 ${prompt}`;
162
163 const filePath = join(outputStylesDir, `${name.toLowerCase().replace(/\s+/g, "-")}.md`);
164 await writeFile(filePath, content, "utf-8");
165 }
166
167 // Example: Create a code review specialist
168 await createOutputStyle(
169 "Code Reviewer",
170 "Thorough code review assistant",
171 `You are an expert code reviewer.
172
173 For every code submission:
174 1. Check for bugs and security issues
175 2. Evaluate performance
176 3. Suggest improvements
177 4. Rate code quality (1-10)`
178 );
179 ```
180
181 ```python Python theme={null}
182 from pathlib import Path
183
184
185 async def create_output_style(name: str, description: str, prompt: str):
186 # User-level: ~/.claude/output-styles
187 # Project-level: .claude/output-styles
188 output_styles_dir = Path.home() / ".claude" / "output-styles"
189
190 output_styles_dir.mkdir(parents=True, exist_ok=True)
191 110
192 content = f"""---111An output style is a markdown file with a `name` and `description` in its frontmatter, followed by the prompt content. Save it to `~/.claude/output-styles/` for a user-level style available in every project, or `.claude/output-styles/` in your repository for a project-level style you can commit and share with your team.
193 name: {name}
194 description: {description}
195 ---
196 112
197 {prompt}"""113The example below defines a code-review persona. Save it as `~/.claude/output-styles/code-reviewer.md` to make it available across projects:
198 114
199 file_name = name.lower().replace(" ", "-") + ".md"115```markdown ~/.claude/output-styles/code-reviewer.md theme={null}
200 file_path = output_styles_dir / file_name116---
201 file_path.write_text(content, encoding="utf-8")117name: Code Reviewer
118description: Thorough code review assistant
119---
202 120
121You are an expert code reviewer.
203 122
204 # Example: Create a code review specialist123For every code submission:
205 await create_output_style(1241. Check for bugs and security issues
206 "Code Reviewer",1252. Evaluate performance
207 "Thorough code review assistant",1263. Suggest improvements
208 """You are an expert code reviewer.1274. Rate code quality (1-10)
209 128```
210 For every code submission:
211 1. Check for bugs and security issues
212 2. Evaluate performance
213 3. Suggest improvements
214 4. Rate code quality (1-10)""",
215 )
216 ```
217</CodeGroup>
218 129
219#### Using output styles130#### Activate an output style
220 131
221Once created, activate output styles via:132Once created, activate output styles via:
222 133
223* **CLI**: `/config`, then select Output style134* **CLI**: run `/config` and select an output style
224* **Settings**: set `outputStyle` in `.claude/settings.local.json`135* **Settings**: set `outputStyle` in `.claude/settings.local.json`
225* **Create new**: add a Markdown file at `~/.claude/output-styles/` or `.claude/output-styles/`; see [Create a custom output style](/en/output-styles#create-a-custom-output-style) for the format136* **TypeScript SDK**: set `options.outputStyle` to the style's name
137
138The Python SDK does not have an option to select an output style programmatically. For code-only deployments where you can't write to `.claude/settings.local.json`, use `append` or a custom prompt string instead.
226 139
227**Note for SDK users:** Output styles are loaded when you include `settingSources: ['user']` or `settingSources: ['project']` (TypeScript) / `setting_sources=["user"]` or `setting_sources=["project"]` (Python) in your options.140**Note for SDK users:** Output styles are loaded when you include `settingSources: ['user']` or `settingSources: ['project']` (TypeScript) / `setting_sources=["user"]` or `setting_sources=["project"]` (Python) in your options.
228 141
229### Method 3: Using `systemPrompt` with append142### Append to the `claude_code` preset
230 143
231You can use the Claude Code preset with an `append` property to add your custom instructions while preserving all built-in functionality.144You can use the Claude Code preset with an `append` property to add your custom instructions while preserving all built-in functionality.
232 145
254 ```167 ```
255 168
256 ```python Python theme={null}169 ```python Python theme={null}
257 from claude_agent_sdk import query, ClaudeAgentOptions170 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage
258 171
259 messages = []172 messages = []
260 173
269 ),182 ),
270 ):183 ):
271 messages.append(message)184 messages.append(message)
272 if message.type == "assistant":185 if isinstance(message, AssistantMessage):
273 print(message.message.content)186 print(message.content)
274 ```187 ```
275</CodeGroup>188</CodeGroup>
276 189
277#### Improve prompt caching across users and machines190#### Improve prompt caching across users and machines
278 191
279By default, two sessions that use the same `claude_code` preset and `append` text still cannot share a prompt cache entry if they run from different working directories. This is because the preset embeds per-session context in the system prompt ahead of your `append` text: the working directory, platform and OS version, current date, git status, and auto-memory paths. Any difference in that context produces a different system prompt and a cache miss.192By default, two sessions that use the same `claude_code` preset and `append` text still cannot share a prompt cache entry if they run from different working directories. This is because the preset embeds per-session context in the system prompt ahead of your `append` text: the working directory, whether it's a git repository, the platform, the active shell, the OS version, and auto-memory paths. Any difference in that context produces a different system prompt and a cache miss. CLAUDE.md content doesn't affect the system prompt cache because the SDK injects it into the conversation, not the system prompt.
280 193
281To make the system prompt identical across sessions, set `excludeDynamicSections: true` in TypeScript or `"exclude_dynamic_sections": True` in Python. The per-session context moves into the first user message, leaving only the static preset and your `append` text in the system prompt so identical configurations share a cache entry across users and machines.194To make the system prompt identical across sessions, set `excludeDynamicSections: true` in TypeScript or `"exclude_dynamic_sections": True` in Python. The per-session context moves into the first user message, leaving only the static preset and your `append` text in the system prompt so identical configurations share a cache entry across users and machines.
282 195
323 ```236 ```
324</CodeGroup>237</CodeGroup>
325 238
326**Tradeoffs:** the working directory, git status, and memory location still reach Claude, but as part of the first user message rather than the system prompt. Instructions in the user message carry marginally less weight than the same text in the system prompt, so Claude may rely on them less strongly when reasoning about the current directory or auto-memory paths. Enable this option when cross-session cache reuse matters more than maximally authoritative environment context.239**Tradeoffs:** the working directory, the git-repo flag, the platform, the active shell, the OS version, and auto-memory paths still reach Claude, but as part of the first user message rather than the system prompt. Instructions in the user message carry marginally less weight than the same text in the system prompt, so Claude may rely on them less strongly when reasoning about the current directory or auto-memory paths. Enable this option when cross-session cache reuse matters more than maximally authoritative environment context.
327 240
328For the equivalent flag in non-interactive CLI mode, see [`--exclude-dynamic-system-prompt-sections`](/en/cli-reference).241For the equivalent flag in non-interactive CLI mode, see [`--exclude-dynamic-system-prompt-sections`](/en/cli-reference).
329 242
330### Method 4: Custom system prompts243### Custom system prompts
331 244
332You can provide a custom string as `systemPrompt` to replace the default entirely with your own instructions.245You can provide a custom string as `systemPrompt` to replace the default entirely with your own instructions.
333 246
359 ```272 ```
360 273
361 ```python Python theme={null}274 ```python Python theme={null}
362 from claude_agent_sdk import query, ClaudeAgentOptions275 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage
363 276
364 custom_prompt = """You are a Python coding specialist.277 custom_prompt = """You are a Python coding specialist.
365 Follow these guidelines:278 Follow these guidelines:
376 options=ClaudeAgentOptions(system_prompt=custom_prompt),289 options=ClaudeAgentOptions(system_prompt=custom_prompt),
377 ):290 ):
378 messages.append(message)291 messages.append(message)
379 if message.type == "assistant":292 if isinstance(message, AssistantMessage):
380 print(message.message.content)293 print(message.content)
381 ```294 ```
382</CodeGroup>295</CodeGroup>
383 296
384## Comparison of all four approaches297## Compare the four approaches
298
299The four customization methods differ in where they live, how they're shared, and what they preserve from the `claude_code` preset.
385 300
386| Feature | CLAUDE.md | Output Styles | `systemPrompt` with append | Custom `systemPrompt` |301| Feature | CLAUDE.md | Output Styles | `systemPrompt` with append | Custom `systemPrompt` |
387| ----------------------- | ---------------- | --------------- | -------------------------- | ---------------------- |302| ----------------------- | ---------------- | --------------- | -------------------------- | ---------------------- |
395| **Version control** | With project | Yes | With code | With code |310| **Version control** | With project | Yes | With code | With code |
396| **Scope** | Project-specific | User or project | Code session | Code session |311| **Scope** | Project-specific | User or project | Code session | Code session |
397 312
398**Note:** "With append" means using `systemPrompt: { type: "preset", preset: "claude_code", append: "..." }` in TypeScript or `system_prompt={"type": "preset", "preset": "claude_code", "append": "..."}` in Python.313"With append" means using `systemPrompt: { type: "preset", preset: "claude_code", append: "..." }` in TypeScript or `system_prompt={"type": "preset", "preset": "claude_code", "append": "..."}` in Python. CLAUDE.md doesn't change the system prompt itself: the SDK injects its content into the conversation as project context.
399 314
400## Use cases and best practices315## Use cases and best practices
401 316
402### When to use CLAUDE.md317### When to use CLAUDE.md
403 318
404**Best for:**319Use CLAUDE.md for instructions that should apply to every session in a project, regardless of which system prompt the session uses: coding standards, common commands, architecture context, and team conventions. CLAUDE.md is committed to your repository, so it stays in sync with the code it describes. See [When to add to CLAUDE.md](/en/memory#when-to-add-to-claude-md) for full guidance.
405
406* Project-specific coding standards and conventions
407* Documenting project structure and architecture
408* Listing common commands (build, test, deploy)
409* Team-shared context that should be version controlled
410* Instructions that apply to all SDK usage in a project
411
412**Examples:**
413 320
414* "All API endpoints should use async/await patterns"321CLAUDE.md files load when the `project` setting source is enabled, which it is for default `query()` options. If you set `settingSources` in TypeScript or `setting_sources` in Python explicitly, include `'project'` to keep loading project-level CLAUDE.md.
415* "Run `npm run lint:fix` before committing"
416* "Database migrations are in the `migrations/` directory"
417
418CLAUDE.md files load when the `project` setting source is enabled, which it is for default `query()` options. If you set `settingSources` (TypeScript) or `setting_sources` (Python) explicitly, include `'project'` to keep loading project-level CLAUDE.md.
419 322
420### When to use output styles323### When to use output styles
421 324
325Output styles are for personas you want to reuse across the CLI and SDK without changing application code. Because they live as files in `.claude/output-styles`, the same persona is available from `/config` in the CLI and from any SDK session that loads the matching setting source.
326
422**Best for:**327**Best for:**
423 328
424* Persistent behavior changes across sessions329* Persistent behavior changes across sessions
425* Team-shared configurations330* Team-shared configurations
426* Specialized assistants (code reviewer, data scientist, DevOps)331* Specialized assistants like a code reviewer, data scientist, or DevOps assistant
427* Complex prompt modifications that need versioning332* Complex prompt modifications that need versioning
428 333
429**Examples:**334**Examples:**
434 339
435### When to use `systemPrompt` with append340### When to use `systemPrompt` with append
436 341
342Use `append` when the `claude_code` preset already fits your product and you only need to layer in extra instructions. You keep the preset's tool guidance, safety rules, and coding conventions without reimplementing them.
343
437**Best for:**344**Best for:**
438 345
439* Adding specific coding standards or preferences346* Adding specific coding standards or preferences
444 351
445### When to use custom `systemPrompt`352### When to use custom `systemPrompt`
446 353
354Use a custom prompt when your agent's surface, identity, or permission model differs from Claude Code's, as described in [Decide on a starting point](#decide-on-a-starting-point). You define the full instruction set, including any tool guidance and safety rules your agent needs.
355
447**Best for:**356**Best for:**
448 357
449* Complete control over Claude's behavior358* Complete control over Claude's behavior
452* Situations where default tools aren't needed361* Situations where default tools aren't needed
453* Building specialized agents with unique behavior362* Building specialized agents with unique behavior
454 363
455## Combining approaches364## Combine approaches
365
366These methods compose. A persistent output style or CLAUDE.md sets the long-lived behavior, and `append` layers session-specific instructions on top without touching the saved configuration.
456 367
457You can combine these methods for maximum flexibility:368### Combine an output style with session-specific additions
458 369
459### Example: Output style with session-specific additions370The example below assumes a Code Reviewer output style is already active. The `append` block layers session-specific focus areas on top of the persona, so a single review session can prioritize OAuth and token storage without changing the saved output style:
460 371
461<CodeGroup>372<CodeGroup>
462 ```typescript TypeScript theme={null}373 ```typescript TypeScript theme={null}
513 424
514## See also425## See also
515 426
516* [Output styles](/en/output-styles) - Complete output styles documentation427* [Output styles](/en/output-styles): create, manage, and share output styles for the CLI, including the file format and storage locations
517* [TypeScript SDK guide](/en/agent-sdk/typescript) - Complete SDK usage guide428* [How Claude remembers your project](/en/memory): what to put in CLAUDE.md, where to place it, and how to write effective project instructions
518* [Configuration guide](/en/settings) - General configuration options429* [TypeScript SDK reference](/en/agent-sdk/typescript): the full `Options` type, including `systemPrompt`, `settingSources`, and `outputStyle`
430* [Python SDK reference](/en/agent-sdk/python): the full `ClaudeAgentOptions` type, including `system_prompt` and `setting_sources`
431* [Settings](/en/settings): the `settings.json` reference, including where output styles and other configuration are stored