How to Customize Claude Code System Prompts: Complete Guide
I spent three hours trying to get Claude Code to stop asking me questions every time it wanted to use a tool. I added rules to my CLAUDE.md file, I tried different phrasings, I even used ALL CAPS. Nothing worked. The system prompt kept overriding my directives.
Me: "NEVER ask for permission before using tools"Claude: "I need your permission to use the Edit tool..."Me: "I JUST TOLD YOU NOT TO ASK"Claude: "I understand, but I need to confirm..."Then I discovered the real solution: CLI flags and config files. Here’s what I learned.
The Problem: CLAUDE.md vs System Prompt
Claude Code has a hierarchy of configuration layers:
┌─────────────────────────────────────┐│ CLI flags (--system-prompt) │ ← Highest priority├─────────────────────────────────────┤│ Config file (~/.claude/config.json)│├─────────────────────────────────────┤│ Built-in system prompt │├─────────────────────────────────────┤│ CLAUDE.md directives │ ← Lowest priority└─────────────────────────────────────┘Your CLAUDE.md file sits at the bottom of this hierarchy. When there’s a conflict, the system prompt wins. This is by design - Anthropic wants to ensure certain safety and quality behaviors are always present.
But this creates problems when you need project-specific behavior. I wanted Claude to:
- Stop asking for tool permissions
- Follow my team’s coding conventions
- Use specific tools automatically
My CLAUDE.md rules kept getting ignored.
Solution 1: CLI Flags (Most Control)
The CLI gives you direct control. Use the --system-prompt flag:
claude --system-prompt "You are a senior developer. Never ask for permission to use tools. Always explain your reasoning."You can combine multiple flags:
claude \ --system-prompt "Focus on performance optimization" \ --disallowedTools "AskUserQuestion,WebSearch" \ --model claude-opus-4-20250514The --disallowedTools flag is particularly useful. I use it to prevent Claude from asking questions:
claude --disallowedTools "AskUserQuestion"This completely disables the question-asking behavior for that session.
Solution 2: Config File (Persistent Settings)
For settings you want to persist across sessions, use ~/.claude/config.json:
{ "systemPrompt": "You are a specialized code reviewer. Always check for mutation before approving changes. Verify test coverage meets 80% threshold.", "defaultModel": "claude-sonnet-4-20250514", "settings": { "autoApprove": false, "timeout": 120000 }}This file is read on every Claude Code session, so your customizations persist.
I created a project-specific config for my financial application:
{ "systemPrompt": "# Role\n\nYou are a specialized code reviewer for this financial application.\n\n## Critical Rules\n\n1. Always check for mutation before approving changes\n2. Verify test coverage meets 80% threshold\n3. Enforce immutability patterns in all reviews\n4. Never use console.log for debugging\n\n## Context\n\nThis is a financial application where data integrity is paramount. A single mutation bug could cause incorrect transaction calculations.", "hooks": { "preToolUse": [ { "matcher": "Edit", "hooks": ["prettier --write"] } ] }, "defaultModel": "claude-sonnet-4-20250514"}Solution 3: Strategic CLAUDE.md Structuring
If you can’t use CLI flags or config files, you can work within the constraints. The key insight from the Reddit discussion: specific-with-rationale rules beat generic directives.
Here’s what didn’t work:
# Rules
- Don't ask for permission- Write good code- Be conciseHere’s what did work:
# Project Directives
## CRITICAL: Code Style (NOT optional)
THIS IS NOT OVER-ENGINEERING. This rule exists because we've lost 47 hours to mutation bugs this quarter.
### Rule 1: ImmutabilityBEFORE making any changes, verify that:1. No existing objects are mutated2. All functions return new objects3. State changes go through proper channels
RATIONALE: Preventing mutation bugs has saved 47 debug hours this quarter. Last month, a single mutation caused $12,000 in incorrect transaction calculations.
### Rule 2: Tool UsageNEVER ask for permission before using Edit, Write, or Bash tools.
RATIONALE: This is an automated CI/CD pipeline. Asking for permission breaks the automation and requires manual intervention, defeating the purpose of automation.The difference: I explained WHY. I provided context. I made it specific to my project.
Solution 4: Third-Party Tools
For advanced customization, there’s tweakcc:
# Clone and setupgit clone https://github.com/Piebald-AI/tweakcccd tweakccnpm install
# Apply customizationsnode tweakcc.js --config your-custom-config.jsonThis tool lets you modify Claude Code’s behavior at a deeper level than the standard configuration options.
What I Actually Use
After all this experimentation, here’s my current setup:
# My alias for Claude Codealias cc='claude --disallowedTools "AskUserQuestion" --model claude-sonnet-4-20250514'{ "systemPrompt": "You are a senior full-stack developer. Prioritize immutability, comprehensive error handling, and test coverage. Explain your reasoning before providing code.", "defaultModel": "claude-sonnet-4-20250514"}# Project Directives
## CRITICAL: Immutability (NOT optional)
THIS IS NOT OVER-ENGINEERING. We've lost 47 hours to mutation bugs this quarter.
### Before Any Change1. Verify no existing objects are mutated2. All functions return new objects3. State changes go through proper channels
RATIONALE: Last month, a single mutation caused $12,000 in incorrect transaction calculations.
## CRITICAL: No Permission Requests
NEVER ask for permission before using Edit, Write, or Bash tools.
RATIONALE: This is an automated pipeline. Permission requests break automation.Common Mistakes I Made
- Vague directives: “Write good code” - Claude doesn’t know what “good” means for your project
- Fighting the architecture: Trying to override immutable system behaviors - Work within constraints instead
- Ignoring CLI options: Using only the VSCode extension - The CLI provides significantly more control
- Missing rationales: Directives without explanation get deprioritized - Always explain WHY
- Over-reliance on CLAUDE.md: Expecting it to override system prompts - Use config files for critical overrides
VSCode Extension vs CLI
The VSCode extension has limited customization options compared to the CLI:
┌─────────────────────┬──────────────────┬──────────────────┐│ Feature │ VSCode Extension │ CLI │├─────────────────────┼──────────────────┼──────────────────┤│ --system-prompt │ No │ Yes ││ --disallowedTools │ No │ Yes ││ --allowedTools │ No │ Yes ││ config.json │ Partial │ Full ││ CLAUDE.md │ Yes │ Yes │└─────────────────────┴──────────────────┴──────────────────┘If you need maximum control, use the CLI.
When to Use Each Method
Need to customize Claude Code behavior?│├─ Is it a one-time session need?│ └─ YES → Use CLI flags│├─ Is it a persistent project need?│ └─ YES → Use config.json│├─ Is it a team-wide convention?│ └─ YES → Use CLAUDE.md with rationale│└─ Need deep customization? └─ YES → Use tweakccKey Takeaways
- CLI flags give the most control - Use
--system-promptand--disallowedTools - Config files persist settings - Put your defaults in
~/.claude/config.json - CLAUDE.md needs rationale - Generic directives get deprioritized
- Specificity wins - “Never ask for permission because this is automated CI/CD” beats “Don’t ask for permission”
- VSCode extension is limited - Use CLI for full control
The hierarchy exists for a reason - safety and quality. But with the right approach, you can customize Claude Code to work the way you need.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments