Sign in

Notes

Customizing Claude Code

Updated 2026-06-19
On this page

Claude Code is useful out of the box, but it gets genuinely good once you teach it your project and wire in your tools. Customization is mostly a few files Claude reads at startup, plus automations.

CLAUDE.md — persistent project knowledge

CLAUDE.md (at the repo root or in .claude/) is a markdown file you commit so Claude knows your project: build and test commands, conventions, architecture, gotchas. It's read at the start of every session.

Run /init to have Claude draft one from your codebase, then trim it — a focused file Claude follows beats a long one it skims. Layered files load together, most-specific last:

  • ~/.claude/CLAUDE.md — your personal defaults, across all projects.

  • .claude/CLAUDE.md — project instructions (committed).

  • .claude/CLAUDE.local.md — personal, project-specific (gitignored).

Claude Code also keeps an automatic memory it writes itself — build commands it discovers, decisions, things you tell it — under ~/.claude/projects/\<project>/memory/, indexed by a MEMORY.md that loads at session start. Run /memory to see and edit it.

settings.json — config and permissions

settings.json lives in ~/.claude/ (you) or .claude/settings.json (project, shareable); .claude/settings.local.json stays on your machine. The part I touch most is permissions — pre-approve the safe things so Claude stops asking, and hard-block the dangerous ones:

{
  "permissions": {
    "allow": ["Bash(npm run test:*)", "Bash(git status)", "Read(./src/**)"],
    "deny": ["Bash(rm -rf *)", "Read(./.env)"],
    "defaultMode": "acceptEdits"
  },
  "env": { "NODE_ENV": "development" }
}

defaultMode sets the permission mode each session starts in (default, acceptEdits, or plan; bypassPermissions exists for sandboxes). env vars propagate to the commands Claude runs.

Hooks — automate on events

Hooks run a command at points in Claude's lifecycle — formatting after an edit, linting before a commit, blocking a risky command. They're configured by event, then matcher, then handlers:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          { "type": "command", "command": ".claude/hooks/format.sh" }
        ]
      }
    ]
  }
}

Common events include PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, and Stop (there are more). On tool events you can add an if filter like "if": "Bash(git \*)" to scope a hook to matching calls. Your script receives JSON on stdin; exit non-zero to block the action.

Skills — reusable commands

When you keep pasting the same checklist or procedure, make it a skill: a SKILL.md with YAML frontmatter at .claude/skills/\<name>/SKILL.md (personal: ~/.claude/skills/...). The folder name becomes the command — /deploy, say. Claude can also invoke a skill on its own when its description matches the work; add disable-model-invocation: true to keep it manual-only.

---
name: deploy
description: Deploy the current branch to staging
disable-model-invocation: true
---
1. Run tests and type-check.
2. Build and push the image.
3. Smoke-test the deployment.

A skill's body only loads when it's used, so long reference material costs nothing until you need it. (Older .claude/commands/\<name>.md files still work the same way.)

MCP — connect external tools

The Model Context Protocol lets Claude Code read and act on outside systems — GitHub, Jira, Slack, a database, your own service — instead of you pasting data into chat. Add a server with claude mcp add:

# Remote HTTP server
claude mcp add --transport http notion https://mcp.notion.com/mcp

# Remote SSE server
claude mcp add --transport sse asana https://mcp.asana.com/sse

# Local stdio server (everything after -- runs the server)
claude mcp add --env API_KEY=value --transport stdio airtable -- npx -y airtable-mcp-server

--scope controls where it's stored: local (default — just you, in ~/.claude.json), project (shared via a committed .mcp.json), or user (all your projects). Then you just ask in plain language and Claude routes the call.

Subagents — specialized workers

A subagent is a separate assistant with its own context window, system prompt, and tool access. Define one as a markdown file with frontmatter in .claude/agents/ (or ~/.claude/agents/), or run /agents to create it interactively:

---
name: code-reviewer
description: Reviews changes for quality, bugs, and security
tools: Read, Grep, Glob, Bash
model: sonnet
---
You are a senior reviewer. Focus on correctness, security, and clear naming.
Report findings grouped by severity.

Claude delegates to it when the description fits, or you can say "use the code-reviewer subagent." Subagents keep noisy work out of your main thread, let you restrict which tools are available, and can run on a faster, cheaper model like haiku.

See also

Getting started with Claude Code

How I work with Claude Code

Details

Section:
Notes
Updated:
2026-06-19
Customizing Claude Code — Chris Case — Dev Notes