I Read the Claude Code Source Code. Here's Everything You Can Configure That the Docs Don't Tell You.
BuildingBetter
SubscribeSign in
I Read the Claude Code Source Code. Here's Everything You Can Configure That the Docs Don't Tell You.<br>Hook fields that rewrite commands mid-flight, persistent agent memory, auto-mode rules in plain English, self-improving dream loops, and every example is copy-paste ready.
André Figueira<br>Apr 01, 2026
Share
Claude Code’s auto-mode permission system is internally called the “YOLO Classifier.” That’s the actual variable name in yoloClassifier.ts. And you can configure it with plain English descriptions of your environment, things like “this is a staging server, destructive operations are acceptable,” that the classifier reads to decide what’s safe to auto-approve. This isn’t in any documentation.<br>It’s one of dozens of undocumented capabilities buried in the Claude Code source code, which is sitting right there in your node_modules as a publicly distributed npm package. The official docs cover the basics well enough. But the source code reveals fields, response formats, and settings that dramatically expand what you can build. Everything here works right now, and every example is designed to be dropped into your project as-is.<br>A note on versioning: These findings come from @anthropic-ai/claude-code@2.1.87. Undocumented features can change between releases, so treat this as a snapshot of what’s available today. Fields with “EXPERIMENTAL” in their names are explicitly flagged as unstable by Anthropic’s own engineers, and I’ll call those out individually.<br>Before you start
Quick reference for where everything lives:<br>Settings: ~/.claude/settings.json (personal) or .claude/settings.json (project, shared via git)
Skills: ~/.claude/skills//SKILL.md (personal) or .claude/skills//SKILL.md (project)
Agents: ~/.claude/agents/.md (personal) or .claude/agents/.md (project)
Hook scripts: ~/.claude/hooks/ is a good convention. Remember to chmod +x your scripts.
Project-level files in .claude/ can be committed to git and shared with your team. Personal files in ~/.claude/ are yours alone.<br>Your hooks can talk back, and nobody told you how
This is the biggest gap in the documentation. The docs tell you hooks receive JSON on stdin and that exit code 2 blocks an operation. What they don’t tell you is that hooks can return JSON on stdout with event-specific fields that modify Claude Code’s behavior in real time. The source code reveals exactly what each event type accepts.<br>PreToolUse hooks can return:<br>updatedInput - rewrite the tool’s input before it executes. You can modify commands mid-flight.
permissionDecision - force “allow” or “deny” without prompting the user.
permissionDecisionReason - explain the decision (shown in UI).
additionalContext - inject text into the conversation context.
SessionStart hooks can return:<br>watchPaths - set up automatic file watching that triggers FileChanged events.
initialUserMessage - prepend content to the first user message in the session.
additionalContext - inject context that persists for the whole session.
PostToolUse hooks can return:<br>updatedMCPToolOutput - modify what Claude sees from an MCP tool response.
additionalContext - inject context after a tool runs.
PermissionRequest hooks can return:<br>decision - programmatically allow or deny with updatedInput or updatedPermissions.
This is powerful stuff. Here’s a PreToolUse hook that automatically adds --dry-run to any git push command before Claude executes it.<br>In your settings.json:<br>"hooks": {<br>"PreToolUse": [{<br>"matcher": "Bash",<br>"hooks": [{<br>"type": "command",<br>"command": "~/.claude/hooks/dry-run-pushes.sh"<br>}]<br>}]<br>And the script at ~/.claude/hooks/dry-run-pushes.sh:<br>#!/bin/bash<br>INPUT=$(jq -r '.tool_input.command' Claude thinks it’s running git push origin main, but your hook quietly rewrites it to git push origin main --dry-run before execution. The updatedInput field isn’t in any docs.<br>Here’s a SessionStart hook that watches your config files and injects git context into every session.<br>settings.json:<br>"hooks": {<br>"SessionStart": [{<br>"hooks": [{<br>"type": "command",<br>"command": "~/.claude/hooks/session-context.sh",<br>"statusMessage": "Loading project context..."<br>}]<br>}]<br>~/.claude/hooks/session-context.sh:<br>#!/bin/bash<br>BRANCH=$(git branch --show-current 2>/dev/null)<br>CHANGES=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
jq -n \<br>--arg branch "$BRANCH" \<br>--arg changes "$CHANGES" \<br>'{<br>"watchPaths": ["package.json", ".env", "tsconfig.json"],<br>"additionalContext": "Current branch: \($branch). Uncommitted changes: \($changes) files."<br>}'<br>Now Claude Code automatically watches your package.json, .env, and tsconfig for changes, and it knows what branch you’re on and how many uncommitted files you have before you even type anything.<br>And here’s one that auto-approves read-only bash commands without prompting.<br>settings.json:<br>"hooks": {<br>"PreToolUse": [{<br>"matcher": "Bash",<br>"hooks": [{<br>"type":...