Reference: Claude Code in Action
CLAUDE.md (3 types)Claude Code can read instructions from CLAUDE.md at different scopes:
@filename / @pathUse @ to explicitly reference a file or path in prompts.
Example:
@src/db/schema.py@docs/architecture.md@package.jsonThis is useful to:
You can write a note inside your instructions that Claude should remember and reuse.
Example:
# The database schema is defined in the @path/to/file.py file. Reference it anytime.
This pattern is great for:
Claude Code supports copy-pasting images directly into the conversation.
Useful for:
You can trigger deeper reasoning by adding explicit thinking tags/phrases like:
Thinkthink morethink a lotthink longerultrathinkExample prompt:
This is a tough task — ultrathink about the best approach and tradeoffs.
Notes:
Esc and add a correction into memory/instructions.Esc twice to rewind./compact
This compresses the current conversation so you can keep working with a cleaner context window.
.claude/commands/)You can create reusable “commands” inside:
.claude/commands/<command_name>.md
audit.mdYou goal is to update any vulnerable dependencies.
- Check lockfiles
- Upgrade safely
- Ensure builds/tests still pass
- Summarize changes + risks
write_tests.mdWrite comprehensive tests for: $ARGUMENT
- Follow project test conventions
- Prefer integration tests where useful
- Cover edge cases
- Include setup/teardown notes
Use cases:
MCP servers let Claude use external tools safely (browser, filesystem, automation, etc).
Playwright MCP allows Claude to:
Add it via CLI:
claude mcp add playwright npx ...
You can also allow/configure MCP in:
settings.local.jsonEnable Claude GitHub integration:
/install-github-app
A) Mention Claude
@claudeB) Pull Request actions Claude can:
.github/workflows/claude.yml)You can define project setup steps, like:
- name: Project Setup
run: |
npm run setup
npm run dev:daemon
Add custom instructions (environment assumptions):
custom_instructions: |
The project is already set up with all dependencies installed.
The server is already running at localhost:3000.
Logs are being written to logs.txt.
If needed, you can query the db with the 'sqlite3' CLI.
If needed, use the mcp__playwright toolset to interact with the app.
Example MCP config block:
mcp_config: |
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": [
"@playwright/mcp@latest",
"--allowed-origins",
"localhost:3000;cdn.tailwindcss.com;esm.sh"
]
}
}
}
Example allow-list of tools:
allowed_tools: "Bash(npm:*),Bash(sqlite3:*),mcp__playwright__browser_snapshot,mcp__playwright__browser_click,..."
Hooks let you run scripts before or after Claude uses tools.
You can set hooks:
Manage via:
/hooks
(or manually editing config files)
PreToolUseRuns before a tool executes.
0 → OK / allow2 → Error (PreToolUse: block)Tool names you can hook into:
readeditmultiEditwritebashWebFetchGrepglob"$VAR"...env.git/{
"hooks": {
"PostToolUse": [
{
"matcher": "(Edit|Write).*\\.sql",
"hooks": [
{
"type": "command",
"command": "uv run sqlmesh format",
"timeout": 30,
"description": "Auto-format SQLMesh models and tests after editing"
}
]
}
]
}
}
You can automate code formatting and linting with Ruff after every code edit by configuring a post-edit hook in Claude.
.claude/settings.json{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/run-ruff.sh"
}
]
}
]
}
}
run-ruff.sh ScriptNote: Claude does not display logs, echo, or errors from hooks. For debugging, write output to a file (e.g., using
echoortee).
#!/bin/bash
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path' 2>/dev/null)
# Only proceed if the file exists and is a Python file
if [[ -z "$file_path" || ! -f "$file_path" || "$file_path" != *.py ]]; then
exit 0
fi
uv run ruff check --fix --unsafe-fixes "$file_path"
uv run ruff format "$file_path"
exit 0
Tips:
jq, uv, and ruff are installed and available in your environment.chmod +x .claude/hooks/run-ruff.shecho "$file_path" >> /tmp/ruff_hook.log.This setup ensures your Python files are automatically linted and formatted after each edit, keeping your codebase clean and consistent.
Besides PreToolUse and PostToolUse, you can hook into:
Claude Code SDK supports automation from:
Python
Example (async):
from claude_code_sdk import query
async for message in query("look for duplicate queries"):
print(message)
Example (sync):
import asyncio
from claude_code_sdk import query
async def main():
async for message in query("look for duplicate queries"):
print(message)
asyncio.run(main())