Claude Code ships with a ~900-line system prompt and ~30 tools that actively fight a bash-first workflow. Three CLI flags fix most of it:
#!/bin/bash
claude \
--dangerously-skip-permissions \
--tools "Bash,Read,Edit,Write,Skill" \
--system-prompt "$(sed "s|{{DATE}}|$(date +%Y-%m-%d)|;s|{{CWD}}|$(pwd)|" ~/.claude/SYSTEM.md)" \
"$@"--system-promptreplaces the 900-line default with a ~30-line pi-equivalent prompt (6.1K → 275 tokens)--toolsrestricts to 5 core tools, dropping ~25 tool descriptions (8.5K → ~5K tokens)--dangerously-skip-permissionsstops asking for permission on every file operation
Result: 14.6K → 5.2K baseline tokens (64% reduction). CLAUDE.md files, skills, and project context still load normally.
Setup: §9 — The claude-lean Approach has the complete SYSTEM.md, wrapper script, and measured results.
⚠️ Caveat: This is experimental. The token reduction is measured, but the behavioral impact hasn't been thoroughly tested across diverse workflows yet. If you try this, I'd welcome comments on what worked, what broke, and what you'd adjust.
The rest of this document is the analysis that got us here.
Make Claude Code behave more like pi through configuration only — no codebase changes.
Pi's system prompt is ~60 lines. It tells the model:
- You're an expert coding assistant inside pi
- Here are your tools (read, bash, edit, write)
- Use bash for ls, rg, find
- Be concise
- Here's the docs path if asked about pi itself
That's it. Pi delegates almost everything to the model's judgment. The system prompt is a frame, not a rulebook.
Claude Code's system prompt is ~900+ lines of generated TypeScript producing a multi-section document with:
- Detailed tool preference hierarchy (never use cat, use FileRead instead)
- Commit/PR workflow scripts with step-by-step numbered instructions
- Sandbox configuration
- Output efficiency rules
- Tone/style rules
- Explicit action reversibility framework
- Task management instructions
- Git safety protocols with forbidden command lists
Claude Code treats the model as a junior dev who needs guardrails. Pi treats it as a senior dev who needs context.
| Feature | Claude Code | Pi |
|---|---|---|
| Global user instructions | ~/.claude/CLAUDE.md |
~/.pi/agent/CLAUDE.md (or AGENTS.md) |
| Project instructions | ./CLAUDE.md, ./.claude/CLAUDE.md |
./CLAUDE.md, ./AGENTS.md |
| Private local | ./CLAUDE.local.md |
(not supported) |
| Rules directory | ./.claude/rules/*.md (with glob-based conditional loading) |
(not supported) |
| Managed/policy | /etc/claude-code/CLAUDE.md |
(not supported) |
| Include directive | @path in memory files |
(not supported) |
| Ancestor walk | Walks CWD → root loading CLAUDE.md at each level | Walks CWD → root loading CLAUDE.md/AGENTS.md at each level |
| Priority | Later-loaded = higher priority | Same — CWD wins over ancestors |
| Instruction emphasis | "IMPORTANT: These instructions OVERRIDE any default behavior" |
Appended as # Project Context section |
Key difference: Claude Code wraps all memory files with a strong instruction: "Codebase and user instructions are shown below. Be sure to adhere to these instructions. IMPORTANT: These instructions OVERRIDE any default behavior and you MUST follow them exactly as written." Pi just appends them as project context.
| Feature | Claude Code | Pi |
|---|---|---|
| Custom system prompt | --system-prompt flag (replaces default) |
.pi/SYSTEM.md or --system-prompt flag |
| Append to system prompt | --append-system-prompt setting |
.pi/APPEND_SYSTEM.md or --append-system-prompt flag |
| Agent definition override | --agent flag or agent setting |
(agents are subagent-only in pi) |
| Feature | Claude Code | Pi |
|---|---|---|
| Location (global) | ~/.claude/skills/*.md |
~/.pi/agent/skills/*/SKILL.md |
| Location (project) | ./.claude/skills/*.md |
./.pi/skills/*/SKILL.md |
| Invocation | /skill-name slash command via SkillTool |
/skill:name or read tool loads SKILL.md |
| Frontmatter | Supports description, allowed-tools, model, effort, shell |
Supports description, user-invocable |
| Loading | Skills are listed in system prompt; content loaded on invocation | Same pattern — listed in system prompt, read on invocation |
| Tool | Purpose |
|---|---|
read |
Read file contents (text + images) |
bash |
Execute shell commands |
edit |
Exact text replacement in files |
write |
Create/overwrite files |
Pi also has optional grep, find, ls tools, but the default config is just the four above. When only bash is available (no grep/find/ls), pi's prompt says "Use bash for file operations like ls, rg, find" — explicitly routing file exploration through bash.
Core file tools: FileRead, FileEdit, FileWrite, Bash, Glob, Grep
Plus: Agent, AskUserQuestion, TodoWrite, TaskCreate/Get/List/Update/Stop, TeamCreate/Delete, WebFetch, WebSearch, Skill, ToolSearch, EnterPlanMode, ExitPlanMode, EnterWorktree, ExitWorktree, Config, SendMessage, Sleep, NotebookEdit, MCP, LSP, etc.
Claude Code's system prompt contains extensive steering away from bash:
IMPORTANT: Avoid using this tool to run find, grep, cat, head, tail, sed, awk,
or echo commands... Instead, use the appropriate dedicated tool...
Do NOT use the Bash to run commands when a relevant dedicated tool is provided.
This is CRITICAL to assisting the user.
This means Claude Code will:
- Use
Globinstead offindorls - Use
Grepinstead ofgreporrg - Use
FileReadinstead ofcat - Use
FileEditinstead ofsed - Use
FileWriteinstead ofecho >or heredocs
Pi does the opposite — it routes through bash for exploration and reserves dedicated tools for targeted operations.
Claude Code has a rich settings.json system. Key settings relevant to pi-like behavior:
- Global (user):
~/.claude/settings.json - Project (shared, checked in):
.claude/settings.json - Local (gitignored):
.claude/settings.local.json - Managed (enterprise): managed-settings.json in platform-specific path
- Flag:
--settingsCLI flag
When --system-prompt is set (via CLI flag or SDK), it replaces the entire default system prompt — all ~900 lines of behavioral specification. Here's exactly what gets replaced and what survives:
Replaced (the defaultSystemPrompt array — all of §1's verbose content):
- Identity/intro section
- "Doing tasks" behavioral rules
- "Executing actions with care" reversibility framework
- "Using your tools" section (don't use bash for X)
- Tone and style rules
- Output efficiency rules
- Environment info (CWD, OS, model, git status)
- MCP instructions
- Session-specific guidance
- Language/output style overrides
Still loaded (survives custom system prompt):
userContext— CLAUDE.md files are still loaded. Your~/.claude/CLAUDE.md, projectCLAUDE.md,.claude/rules/*.mdall still inject.appendSystemPrompt— if set via--append-system-prompt, appended after your custom prompt- Tool descriptions — each tool's prompt (Bash ~200 lines, FileEdit, FileRead, etc.) is attached to the tool schema, NOT in the system prompt. These are not replaceable.
Skipped (not loaded when custom prompt is set):
systemContext— git status snapshot, cache breaker. Explicitly skipped as optimization.- The default
getSystemPrompt()call itself — never runs.
Net effect: --system-prompt lets you replace ~3,000-5,000 tokens of system prompt with whatever you want. But ~4,000-6,000 tokens of tool descriptions are baked into the tool schemas and always present. You still get your CLAUDE.md context on top.
This is a viable path to a pi-like experience. You could write a lean system prompt (~60 lines, like pi's) and pass it via --system-prompt. Combined with your CLAUDE.md, you'd get:
- Your custom framing (instead of Claude Code's 900-line rulebook)
- Your CLAUDE.md directives (with the "OVERRIDE" emphasis)
- Tool descriptions (unavoidable but largely benign)
- No git status snapshot, no environment section, no output style rules
Example: claude --system-prompt "$(cat ~/.claude/SYSTEM.md)"
Or create an alias:
alias claude-lean='claude --system-prompt "$(cat ~/.claude/SYSTEM.md)"'There's an environment variable CLAUDE_CODE_SIMPLE that, when truthy, replaces the entire system prompt with:
You are Claude Code, Anthropic's official CLI for Claude.
CWD: /path/to/cwd
Date: 2026-04-09
This is even more extreme — it strips the system prompt AND skips tool guidance sections. CLAUDE.md files still load (they're in userContext). Could be combined with your own SYSTEM.md via --append-system-prompt but you lose environment info entirely.
This is your most powerful lever. It replaces the entire ~900-line default system prompt with your own. Create ~/.claude/SYSTEM.md and launch with claude --system-prompt "$(cat ~/.claude/SYSTEM.md)".
A pi-equivalent system prompt:
You are Claude Code, Anthropic's official CLI for Claude. You help users by reading files, executing commands, editing code, and writing new files.
Guidelines:
- Use bash for file operations like ls, rg, find
- Use Read tool to examine specific files (not cat or sed)
- Use Edit tool for precise changes with exact text replacement
- Use Write tool only for new files or complete rewrites
- Be concise in your responses
- Show file paths clearly when working with files
- Read files before modifying them
- Don't add features, refactor, or "improve" beyond what was asked
- Don't create files unless necessary — prefer editing existing filesThis eliminates:
- The "don't use bash" steering (~saves 2K+ tokens)
- The action reversibility framework
- The output efficiency / tone rules
- The commit/PR workflow scripts
- The task management instructions
- Environment info section (CWD, OS, model info)
Your CLAUDE.md files still load on top of this. Tool descriptions are still present (unavoidable). But you go from ~12K baseline to ~3-4K.
Second most powerful lever, and works with or without --system-prompt. Claude Code's memory loading wraps this with "IMPORTANT: These instructions OVERRIDE any default behavior", so directives here genuinely override the verbose built-in prompt.
Recommended additions to align with pi's philosophy:
# Tool Usage Philosophy
Prefer bash for file exploration (ls, find, rg, grep, cat, head).
Use dedicated file tools (Read, Edit, Write) only for targeted operations on known files.
Do not avoid bash in favor of Glob or Grep — bash is the primary exploration tool.
When you need to understand a codebase:
- Use bash with ls, find, rg, tree, wc — not Glob or Grep tools
- Use Read tool to examine specific files you've identified
- Use Edit tool for precise changes to files you've already read
# Communication Style
- Be concise and direct
- No filler, no preamble, no restating what I said
- Skip "Let me..." and "I'll..." — just do it
- Show file paths clearly when working with files
- Don't narrate each tool call
# Work Approach
- Read files before modifying them
- Use the simplest approach first
- Don't add features, refactor, or "improve" beyond what was asked
- Don't create files unless necessary — prefer editing existing files
- If an approach fails, diagnose why before switching tactics{
"includeGitInstructions": false,
"permissions": {
"allow": [
"Bash(*):",
"FileRead",
"FileEdit",
"FileWrite",
"Glob",
"Grep"
]
},
"promptSuggestionEnabled": false
}Why includeGitInstructions: false: This removes ~200 lines of step-by-step commit and PR workflow scripts from the system prompt. Your CLAUDE.md can contain your own git conventions (like your worktree workflow) without fighting the built-in scripts.
Why allow all core tools: Reduces permission friction. Pi never asks permission for file operations.
Why disable prompt suggestions: Pi doesn't suggest what to do next — it waits for your input.
Port your pi skills to Claude Code format. The format is nearly identical — markdown files with frontmatter.
Pi skill format (~/.pi/agent/skills/cleanup/SKILL.md):
---
description: End-of-session checklist
---
# Cleanup Skill
...instructions...Claude Code skill format (~/.claude/skills/cleanup.md):
---
description: End-of-session checklist
---
# Cleanup Skill
...instructions...Main differences:
- Pi uses
SKILL.mdinside a named directory; Claude Code usesskillname.mddirectly - Pi skills reference files relative to
skill.baseDir; Claude Code skills reference relative to CWD - Both support
/skillnameinvocation
Claude Code supports .claude/rules/*.md files that are automatically loaded into context. These can have frontmatter paths: for conditional loading (only applied when working on matching files). This is more powerful than pi's approach and worth using for project-specific conventions.
These are hardcoded in Claude Code and not overridable via configuration:
-
Tool descriptions — The verbose bash tool prompt (~200 lines including sandbox, git safety, commit workflow) is generated code. Your CLAUDE.md can counter it but can't remove it.
-
"Don't use bash for X" steering — Deeply embedded in both the system prompt and individual tool descriptions. Your CLAUDE.md override helps, but Claude Code may still prefer Glob over
finddue to tool-level instructions. -
Output efficiency section — The "be concise" vs "flowing prose" instructions are built in. Your CLAUDE.md can reinforce conciseness but the base instruction exists.
-
Action reversibility framework — The "check with user before destructive actions" section is always present.
-
Task/Todo tools — These exist in the tool pool even if you never use them. The model may suggest using them.
-
Agent tool — The subagent spawning system is always available. Pi's subagent system works differently (uses the
subagentcustom tool with isolated context).
| Item | Claude Code (est. tokens) | Pi (est. tokens) |
|---|---|---|
| Base system prompt | ~3,000-5,000 | ~400-600 |
| Tool descriptions (all) | ~4,000-6,000 | ~800-1,200 |
| Bash tool prompt alone | ~2,000+ | ~50 |
| Git/commit instructions | ~1,500 | 0 (unless in CLAUDE.md) |
| Memory files | varies | varies |
| Skills listing | ~same | ~same |
| Baseline overhead | ~10,000-14,000 | ~1,200-1,800 |
This means Claude Code burns roughly 8-12K more tokens on system prompt before your first message. This matters for context window management and prompt cache efficiency.
Write a lean system prompt (see §5A) and launch with:
claude --system-prompt "$(cat ~/.claude/SYSTEM.md)"Or set up a shell alias:
alias claude-lean='claude --system-prompt "$(cat ~/.claude/SYSTEM.md)"'This single step eliminates most of the behavioral gap. Everything below stacks on top.
{
"includeGitInstructions": false,
"permissions": {
"allow": [
"Bash(*):",
"FileRead",
"FileEdit",
"FileWrite",
"Glob",
"Grep",
"WebFetch",
"WebSearch"
]
},
"promptSuggestionEnabled": false
}Transfer your pi global context (~/.pi/agent/CLAUDE.md) and add the tool usage philosophy section from §5A above.
Copy your pi skills from ~/.pi/agent/skills/*/SKILL.md to ~/.claude/skills/skillname.md.
Adjust any path references — pi skills use relative paths from the skill directory; Claude Code skills work from CWD.
Your existing project CLAUDE.md / AGENTS.md files work in both tools — Claude Code recognizes both filenames.
Even with optimal configuration, these differences persist:
| Behavior | Pi | Claude Code |
|---|---|---|
| File exploration | bash (ls, rg, find) |
Still prefers Glob/Grep tools despite override |
| Subagents | subagent tool with isolated context |
Agent tool — different isolation model |
| Permission prompts | Never prompts for file ops | Prompts unless allow rules cover the case |
| System prompt weight | Light — model drives decisions | Heavy — model follows detailed scripts |
| Context overhead | ~1.5K tokens baseline | ~12K tokens baseline |
| Tool count | 4-7 tools | 30+ tools |
| Commit workflow | User-defined via CLAUDE.md | Built-in 4-step process (even with includeGitInstructions: false, some git safety remains in bash tool prompt) |
| Edit tool | Exact text replacement (oldText → newText) | Exact text replacement (old_string → new_string) — functionally identical |
With --system-prompt, the gap narrows significantly — you can replace the ~5K-token system prompt with ~500 tokens, bringing baseline overhead to ~4-5K (vs pi's ~1.5K). The remaining gap is tool descriptions baked into tool schemas.
Without --system-prompt, CLAUDE.md can redirect behavior but competes with thousands of tokens of built-in instruction.
Based on the analysis above, the highest-impact configuration is a wrapper script that swaps in a pi-equivalent system prompt via --system-prompt.
Fresh session /context comparison:
| Metric | claude (default) |
claude-lean |
Reduction |
|---|---|---|---|
| System prompt | 6.1K tokens | 275 tokens | 95% |
| System tools | 8.5K tokens | 4.9K tokens | 42% |
| Baseline | 14.6K tokens | 5.2K tokens | 64% |
* Baseline = system prompt + system tools only. Skills, MCP tools, and CLAUDE.md content vary by config and aren't affected by claude-lean.
A pi-equivalent system prompt. Guidelines are copied directly from pi's promptGuidelines for its default 4-tool config. {{DATE}} and {{CWD}} are replaced at launch by the wrapper script.
You are Claude Code, Anthropic's official CLI for Claude. You help users by reading files, executing commands, editing code, and writing new files.
Available tools:
- read: Read file contents
- bash: Execute bash commands (ls, grep, find, etc.)
- edit: Make precise file edits with exact text replacement
- write: Create or overwrite files
In addition to the tools above, you may have access to other custom tools depending on the project.
Guidelines:
- Use bash for file operations like ls, rg, find
- When exploring files and directories, use generous limits (e.g. `head -200`, `find | head -200`) to get complete pictures rather than artificially small samples
- Use read to examine files instead of cat or sed.
- Use edit for precise changes (old_string must match exactly and be unique in the file)
- Keep old_string as small as possible while still being unique. Do not pad with large unchanged regions.
- Use write only for new files or complete rewrites.
- Be concise in your responses
- Show file paths clearly when working with files
CWD: {{CWD}}
Date: {{DATE}}#!/bin/bash
claude \
--dangerously-skip-permissions \
--tools "Bash,Read,Edit,Write,Skill" \
--system-prompt "$(sed "s|{{DATE}}|$(date +%Y-%m-%d)|;s|{{CWD}}|$(pwd)|" ~/.claude/SYSTEM.md)" \
"$@"| Flag | What it does |
|---|---|
--dangerously-skip-permissions |
No permission prompts — matches pi's "just do it" behavior |
--tools "Bash,Read,Edit,Write,Skill" |
Pi's 4 core tools + Skill for /skill-name invocation — drops ~25 tool descriptions (~3.5K tokens) |
--system-prompt |
Replaces 900-line default with pi-equivalent prompt |
"$@" |
Passes through any additional flags (e.g. --continue, --resume) |
Make executable and add to PATH:
chmod +x ~/.claude/bin/claude-lean
echo 'export PATH="$HOME/.claude/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc- CLAUDE.md files — global, project, local, and
.claude/rules/*.mdall still load - Skills — still listed and invocable via
/skill-name --continue/--resume— session management works normally via$@passthrough
| Removed | Tokens saved |
|---|---|
| "Don't use bash for X" steering | ~2K |
| Action reversibility framework | ~500 |
| Output efficiency / tone rules | ~500 |
| Commit/PR workflow scripts | ~1.5K |
| Task management instructions | ~300 |
| Environment info section | ~300 (replaced by 2 lines) |
| Git status snapshot | ~200 |
| 26 tool descriptions (Glob, Grep, Agent, Task*, etc.) | ~3.6K |
The remaining ~4.9K tokens are the tool descriptions for Bash, Read, Edit, and Write — baked into the tool schemas sent with every API call. Claude Code's Bash tool description alone is ~2K tokens (vs pi's ~50 tokens for the same tool). These descriptions contain behavioral steering (e.g., cautious output limits, git safety) that can conflict with your system prompt. The SYSTEM.md guidelines serve as a counter-signal.
{ // Replace the default model "model": "claude-sonnet-4-6-20250514", // Git-related behavioral instructions in system prompt "includeGitInstructions": true, // default: true — set false to remove commit/PR scripts // Permissions — most relevant for "just let it work" flow "permissions": { "defaultMode": "allowEdits", // or "bypassPermissions" for full auto "allow": [ "Bash(*):", // allow all bash "FileRead", // allow all reads "FileEdit", // allow all edits "FileWrite" // allow all writes ] }, // Output style — can override the chatty default "outputStyle": "concise", // Language preference "language": "english", // Thinking/effort level "effortLevel": "high", // Disable prompt suggestions (the "what would you like to do?" suggestions) "promptSuggestionEnabled": false, // Agent mode — replaces the entire system prompt with an agent definition "agent": "my-custom-agent" }