1. CLAUDE.md Files
CLAUDE.md is the primary mechanism for injecting persistent behavioral instructions into Claude Code agents. These files are loaded automatically at session start and their contents become part of the system prompt. They replace the need for repeating instructions in every conversation.
1.1 Instruction Hierarchy
CLAUDE.md files follow a hierarchical loading order with increasing specificity. More specific files override more general ones:
flowchart TD
A["~/.claude/CLAUDE.md
(User-global)"] --> B["Enterprise policy
(Org-level)"]
B --> C["Project root CLAUDE.md
(Repository-level)"]
C --> D[".claude/settings.json
(Project settings)"]
D --> E["Subdir CLAUDE.md
(Directory-specific)"]
E --> F["Effective system prompt
(All layers merged)"]
# File locations and their scope:
# 1. User-global (applies to ALL projects)
~/.claude/CLAUDE.md
# 2. Project root (applies to this repository)
/my-project/CLAUDE.md
# 3. Subdirectory-specific (applies only when working in this dir)
/my-project/backend/CLAUDE.md
# 4. Project settings (tool permissions, MCP config)
/my-project/.claude/settings.json
# Example: Project-root CLAUDE.md for a Python microservices project
# CLAUDE.md
## Project Context
This is a Python 3.12 FastAPI microservices application.
Monorepo with 4 services: auth, orders, payments, notifications.
## Coding Standards
- Use type hints on all function signatures
- Prefer `async def` for I/O-bound operations
- Use Pydantic v2 models for request/response validation
- Follow the existing patterns in each service (don't invent new ones)
## Testing
- Run tests with: `pytest tests/ -v --tb=short`
- All new code requires unit tests (minimum 80% coverage)
- Use `pytest-asyncio` for async test functions
## Architecture Rules
- Services communicate via HTTP (not direct imports)
- Each service owns its database schema
- Shared code goes in `/shared/` package only
## Do NOT
- Do not modify docker-compose.yml without asking
- Do not add new dependencies without explaining why
- Do not refactor code unrelated to the current task
1.2 Writing Effective Rules
Rules in CLAUDE.md work best when they are specific, actionable, and testable. Vague instructions get ignored; precise ones shape behavior reliably:
# ❌ BAD: Vague, unactionable rules
# - Write good code
# - Follow best practices
# - Be careful with changes
# ✅ GOOD: Specific, testable rules
## Code Style
- Maximum function length: 30 lines (split if longer)
- Imports: stdlib → third-party → local (separated by blank lines)
- Naming: snake_case for functions/variables, PascalCase for classes
## Workflow
- Always read the file BEFORE editing (never edit blind)
- Run `make lint` after every edit to catch issues early
- If tests fail after your change, fix them before moving on
## Safety
- NEVER run `git push --force` or `git reset --hard`
- NEVER delete files without listing them first and confirming
- NEVER modify .env files (they contain production secrets)
2. allowedTools Restrictions
2.1 Tool Scoping
allowed_tools and disallowed_tools control two different layers of how an agent interacts with tools. Understanding the distinction is critical:
| Option | Layer | Effect |
|---|---|---|
allowed_tools=["Read", "Grep"] | Permission | Read and Grep are auto-approved (no prompt). Tools NOT listed still exist and fall through to the permission mode — they’re not blocked. |
disallowed_tools=["Bash"] | Availability | Bare tool name: removes Bash entirely from Claude’s context. Claude cannot see or attempt it. |
disallowed_tools=["Bash(rm *)"] | Permission | Scoped rule: Bash stays visible, but calls matching rm * are denied in every mode, including bypassPermissions. |
tools=["Read", "Grep"] | Availability | Only listed built-ins appear in context. Unlisted built-ins are removed. MCP tools unaffected. |
allowed_tools does NOT constrain bypassPermissions. Setting allowed_tools=["Read"] alongside permission_mode="bypassPermissions" still approves every tool (including Bash, Write, Edit). allowed_tools only pre-approves; unlisted tools fall through to the permission mode, where bypassPermissions approves everything. If you need bypassPermissions but want specific tools blocked, use disallowed_tools.
Permission Evaluation Order (when Claude requests a tool):
- Hooks — Run first. A hook can deny the call outright. (A hook returning “allow” does NOT skip later steps.)
- Deny rules — Check
disallowed_tools+settings.json deny. If matched, blocked even inbypassPermissions. - Permission mode — Apply the active mode (
bypassPermissionsapproves all;acceptEditsapproves file ops;dontAskdenies unmatched). - Allow rules — Check
allowed_tools+settings.json allow. If matched, auto-approved. - canUseTool callback — If not resolved above, your runtime callback decides. (Skipped in
dontAskmode.)
# Agent SDK — allowed_tools and disallowed_tools
# Requires: pip install claude-agent-sdk
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
"""Demonstrate the two layers: availability vs. permission."""
options = ClaudeAgentOptions(
# PERMISSION layer: auto-approve these (no prompt shown)
allowed_tools=[
"Read", # Built-in: read files
"Glob", # Built-in: search file paths
"Grep", # Built-in: search file contents
"Bash(npm test *)", # Scoped: only npm test commands
"Bash(git diff *)", # Scoped: only git diff commands
"mcp__github__list_issues", # MCP: specific tool from github server
"mcp__github__get_issue", # MCP: another specific tool
],
# AVAILABILITY + PERMISSION layer: block these
disallowed_tools=[
"Bash(rm *)", # Scoped deny: blocks rm in ALL modes
"Bash(sudo *)", # Scoped deny: blocks sudo in ALL modes
"mcp__github__delete_repo", # Removes this tool entirely
],
# Permission mode for tools not covered by allow/deny rules
permission_mode="dontAsk", # Deny anything not pre-approved
)
async for message in query(
prompt="Check if tests pass and list any open bugs in the GitHub repo.",
options=options,
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())
2.2 Permission Patterns
Scoped rule syntax — accepted in allowed_tools, disallowed_tools, and settings.json:
| Rule Format | Applies To | Details |
|---|---|---|
Bash(npm run *) | Bash, Monitor | Command pattern matching |
Read(~/secrets/**) | Read, Grep, Glob, LSP | Path pattern matching |
Edit(/src/**) | Edit, Write, NotebookEdit | Path pattern matching (also grants read) |
WebFetch(domain:example.com) | WebFetch | Domain matching |
mcp__github__* | MCP tools | Wildcard: all tools from a server |
Agent(Explore) | Agent | Subagent type matching |
# Permission patterns for different agent roles
# Requires: pip install claude-agent-sdk
from claude_agent_sdk import ClaudeAgentOptions
# Read-only analyst: can search and read, cannot modify anything
analyst_options = ClaudeAgentOptions(
allowed_tools=[
"Read", "Glob", "Grep",
"Bash(cat *)", "Bash(ls *)", "Bash(wc *)", # Read-only bash
"mcp__db__query", # DB read only
"WebFetch(domain:docs.example.com)", # Only internal docs
],
disallowed_tools=[
"Write", "Edit", # Remove entirely from context
"Bash(rm *)", "Bash(sudo *)", # Scoped deny (extra safety)
"mcp__db__execute", # Block DB writes
],
permission_mode="dontAsk", # Deny anything not listed above
)
# CI/CD agent: can read, test, and commit — but never deploy or delete
ci_options = ClaudeAgentOptions(
allowed_tools=[
"Read", "Glob", "Grep",
"Bash(npm *)", "Bash(pytest *)", "Bash(git diff *)",
"Bash(git add *)", "Bash(git commit *)",
],
disallowed_tools=[
"Bash(git push --force *)", # Block force push in ALL modes
"Bash(rm -rf *)", # Block recursive delete
"mcp__deploy__*", # Block all deploy tools
],
permission_mode="dontAsk",
)
# Full developer agent: broad access with specific exclusions
dev_options = ClaudeAgentOptions(
allowed_tools=[
"Read", "Write", "Edit", "Glob", "Grep",
"Bash(npm *)", "Bash(git *)", "Bash(python *)",
"mcp__github__*", # All GitHub tools
],
disallowed_tools=[
"Bash(rm -rf /)", # Never nuke filesystem
"mcp__infra__delete_resource", # Never delete infra
],
permission_mode="acceptEdits", # Auto-approve file edits
)
# Locked-down agent: pair allowed_tools with dontAsk
# Result: ONLY listed tools work; everything else denied outright
locked_down = ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep"],
permission_mode="dontAsk",
)
Edit(...) implies read access: An Edit(/src/**) allow rule also grants read access to the same path. You do NOT need a separate Read(/src/**) rule. However, Read rules don’t grant write access.
Permission modes at a glance:
| Mode | Behavior | Use When |
|---|---|---|
default | Unmatched tools trigger canUseTool callback | Interactive agents where user approves dynamically |
dontAsk | Deny everything not pre-approved by allow rules | Headless/CI agents with fixed tool surface |
acceptEdits | Auto-approve file edits + filesystem Bash (mkdir, rm, mv) | Trust Claude’s edits; faster iteration on prototypes |
bypassPermissions | Approve ALL tools (deny rules + hooks still enforced) | Controlled environments where you trust all operations |
plan | Read-only: Claude explores but never edits source | Code review, planning, architecture analysis |
Multi-Tenant SaaS Agent Platform
A SaaS company deploys the same Claude agent for 50+ enterprise clients, each with different rules (tone, language, compliance requirements) and skills (industry-specific knowledge). Rules handle per-tenant customization without code changes; skills package domain expertise that can be shared across tenants. Onboarding a new client went from 2 weeks of custom development to 2 hours of configuration.
3. Skills & Agent Modes
Skills are reusable instruction packages that can be activated contextually. They allow different behavioral modes (e.g., “code review mode” vs. “debugging mode”) without changing the base CLAUDE.md:
# Skills are defined in .claude/skills/ directory
# Each skill is a markdown file with frontmatter + instructions
# .claude/skills/code-review.md
---
name: code-review
description: Structured code review with security focus
triggers:
- "review this"
- "check this code"
- "code review"
---
## Code Review Mode
When reviewing code:
1. Check for security vulnerabilities (OWASP Top 10)
2. Verify error handling (no swallowed exceptions)
3. Check for race conditions in async code
4. Verify input validation at boundaries
5. Flag hardcoded secrets or credentials
Output format:
- 🔴 Critical: Must fix before merge
- 🟡 Warning: Should fix, but not blocking
- 🟢 Suggestion: Nice to have improvement
Always end with a summary: "X critical, Y warnings, Z suggestions"
# .claude/skills/debugging.md
---
name: debugging
description: Systematic debugging workflow
triggers:
- "debug this"
- "why is this failing"
- "find the bug"
---
## Debugging Mode
When debugging:
1. REPRODUCE: Run the failing test/command to see the exact error
2. HYPOTHESIZE: Form 2-3 hypotheses about the root cause
3. INVESTIGATE: Use Read + Bash to gather evidence for each hypothesis
4. ISOLATE: Narrow to the specific line/function causing the issue
5. FIX: Make the minimal change that fixes the root cause
6. VERIFY: Run the test again to confirm the fix works
Rules:
- Never guess at fixes — always reproduce first
- If the fix is larger than 10 lines, explain your approach before editing
- Always run the failing test after your fix
3.2 Production SKILL.md (context:fork, agent types, tool restrictions)
The official Skill format uses a SKILL.md file inside .claude/skills/[name]/ directories with YAML frontmatter for execution control. Key features beyond basic descriptions:
# Production SKILL.md structure
# Location: .claude/skills/deploy-staging/SKILL.md
---
description: "Deploy the current branch to staging. Use when the user asks to deploy, ship, or push to staging."
context: fork
agent: default
allowed-tools:
- Bash
- Read
- Glob
---
## Deploy to Staging
1. Run `git status` to confirm clean working tree
2. Run `make build` to compile
3. Run `make test` to verify all tests pass
4. Run `./scripts/deploy-staging.sh` to deploy
5. Verify health check at https://staging.example.com/health
6. Report deployment status with commit hash and timestamp
If any step fails, stop immediately and report the error.
Do NOT proceed to deployment if tests fail.
SKILL.md Frontmatter Fields:
| Field | Purpose | Values |
|---|---|---|
description | Tells Claude when to use this skill (loaded every session) | Clear sentence describing usage trigger |
context: fork | Run skill in isolated subagent (fresh context) | fork or omit for in-context |
agent | Which agent type executes the forked skill | default, Explore, Plan |
allowed-tools | Tool restrictions (CLI only; SDK uses allowedTools option) | List of tool names |
disable-model-invocation | Hide from Claude until user explicitly invokes /skill-name | true / omit |
argument-hint | Shown in autocomplete when user types /skill-name | Short hint text |
# Example: Skill that Claude can NEVER auto-invoke (user must type /audit)
# .claude/skills/audit/SKILL.md
---
description: "Run comprehensive security audit on the codebase"
disable-model-invocation: true
context: fork
agent: Explore
allowed-tools:
- Read
- Grep
- Glob
argument-hint: "optional: path to audit (defaults to entire project)"
---
## Security Audit Workflow
# ... (read-only exploration, never modifies files)
- Use a Hook when the action must happen the same way every time (linting after edits, blocking dangerous commands, logging). Deterministic, zero context cost.
- Use a Skill when Claude should decide how to apply steps, or the content is knowledge rather than a script (deploy checklist, style guide, debugging playbook). Loads on-demand.
3.3 Agent Skills: Official Folder Format
Anthropic has published Agent Skills as an open standard that works across Claude.ai, Claude Code, and the API. A skill is a folder (not just a single file) containing:
| File/Folder | Required? | Purpose |
|---|---|---|
SKILL.md | Required | Instructions in Markdown with YAML frontmatter. Must be exactly SKILL.md (case-sensitive — skill.md and SKILL.MD are rejected) |
scripts/ | Optional | Executable code (Python, Bash, etc.) the skill can run |
references/ | Optional | Documentation loaded on-demand; keeps SKILL.md lean |
assets/ | Optional | Templates, fonts, icons used in output |
Folder naming rules: use kebab-case only. No spaces, no underscores, no capitals.
notion-project-setup✅Notion Project Setup❌ (spaces)notion_project_setup❌ (underscores)NotionProjectSetup❌ (capitals)
No README.md inside the skill folder — all documentation goes in SKILL.md or references/. A repo-level README.md for GitHub distribution is fine, but not inside the skill folder itself.
Progressive Disclosure — three-level system:
- YAML frontmatter: Always loaded in Claude’s system prompt. Provides just enough for Claude to know when to use the skill — minimal token cost.
- SKILL.md body: Loaded when Claude decides the skill is relevant to the current task.
- Linked files (
references/): Additional files Claude reads only when needed. Move detailed docs here to keep SKILL.md under 5,000 words.
Complete YAML frontmatter reference:
---
# REQUIRED
name: my-skill-name # kebab-case; must match folder name; no "claude" or "anthropic" prefix
description: | # What it does AND when to use it. Max 1024 chars. No XML angle brackets.
Analyzes Figma design files and generates developer handoff documentation.
Use when user uploads .fig files, asks for "design specs", "component documentation",
or "design-to-code handoff".
# OPTIONAL
license: MIT # e.g. MIT, Apache-2.0
allowed-tools: "Bash(python:*) Bash(npm:*) WebFetch" # Restrict tool access
compatibility: | # 1-500 chars. Environment requirements, intended product, etc.
Requires Python 3.9+. Designed for Claude.ai and Claude Code. Needs network access.
metadata: # Any custom key-value pairs (max 16 pairs)
author: Wasil Zafar
version: 1.0.0
mcp-server: figma
category: design
tags: [design, handoff, figma]
documentation: https://example.com/docs
support: support@example.com
---
< >) are forbidden because frontmatter is injected into Claude’s system prompt — angle brackets could inject instructions. Skills named with claude or anthropic prefixes are reserved and will be rejected.
3.4 Writing Effective Skill Descriptions
The description field is the most important part of a skill. It’s the only thing Claude reads before deciding whether to load the full skill. Structure: [What it does] + [When to use it] + [Key capabilities]
| Pattern | Example |
|---|---|
| Good — specific + trigger phrases | Manages Linear project workflows including sprint planning, task creation, and status tracking. Use when user mentions "sprint", "Linear tasks", "project planning", or asks to "create tickets". |
| Good — file-type trigger | Analyzes Figma design files and generates developer handoff docs. Use when user uploads .fig files or asks for "design specs" or "design-to-code handoff". |
| Bad — too vague | Helps with projects. — no trigger phrases, no scope |
| Bad — missing triggers | Creates sophisticated multi-page documentation systems. — no WHEN |
| Bad — no user language | Implements the Project entity model with hierarchical relationships. — too technical |
Debugging trigger issues: Ask Claude: “When would you use the [skill name] skill?” — Claude will quote the description back. Adjust based on what’s missing.
Adding negative triggers (to prevent overtriggering):
description: >
Advanced data analysis for CSV files. Use for statistical modeling,
regression analysis, and clustering. Do NOT use for simple data exploration
(use the data-viz skill instead) or for non-CSV formats.
3.5 Testing & Iteration
Three levels of testing rigor (choose based on your audience):
- Manual testing in Claude.ai — Run queries directly. Fastest iteration.
- Scripted testing in Claude Code — Automate test cases for repeatable validation.
- Programmatic testing via Skills API — Build evaluation suites for systematic testing.
Pro Tip: Iterate on a single challenging task until Claude succeeds, then extract the winning approach into a skill. Once you have a working foundation, expand to multiple test cases.
Three test areas to cover:
# 1. TRIGGERING TESTS — Does the skill load at the right times?
Should trigger:
- "Help me set up a new project workspace"
- "I need to create a project" (paraphrase)
- "Initialize a Q4 planning project" (paraphrase)
Should NOT trigger:
- "What's the weather in San Francisco?"
- "Help me write Python code"
# 2. FUNCTIONAL TESTS — Does the skill produce correct outputs?
Test: Create project with 5 tasks
Given: Project name "Q4 Planning", 5 task descriptions
When: Skill executes workflow
Then:
- Project created correctly
- 5 tasks with correct properties
- All tasks linked to project
- No API errors
# 3. PERFORMANCE COMPARISON — Does the skill improve results?
Without skill:
- User provides instructions each time
- 15 back-and-forth messages
- 3 failed API calls requiring retry
- 12,000 tokens consumed
With skill:
- Automatic workflow execution
- 2 clarifying questions only
- 0 failed API calls
- 6,000 tokens consumed
3.6 Distribution & API Usage
Skills are portable across Claude.ai, Claude Code, and the API — they’re an open standard.
Individual users (Claude.ai):
- Download/zip the skill folder
- Upload via Settings → Capabilities → Skills
- Or place in Claude Code’s skills directory
Organization-level: Admins can deploy skills workspace-wide with automatic updates and centralized management (shipped December 18, 2025).
API usage (for programmatic workflows and production agents):
# Skills in the Managed Agents API
# Requires: pip install anthropic
# Skills need the Code Execution Tool beta to run securely.
from anthropic import Anthropic
client = Anthropic()
# Create an agent with a custom skill
agent = client.beta.agents.create(
model="claude-sonnet-4-6",
name="design-handoff-agent",
system="You are a design handoff specialist.",
skills=[
{
"skill_id": "figma-handoff", # custom skill ID
"type": "custom",
"version": "1"
}
],
# Alternatively, use Anthropic-managed skills:
# skills=[{"skill_id": "xlsx", "type": "anthropic", "version": "1"}]
)
print(f"Agent created: {agent.id}")
# Add skills to a Messages API request via container.skills:
# (for one-off requests rather than registered agents)
response = client.beta.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
messages=[{"role": "user", "content": "Generate a design spec from this Figma file"}],
container={
"skills": ["figma-handoff"] # container.skills parameter
},
betas=["computer-use-2024-10-22"] # Code Execution Tool beta required
)
| Use Case | Best Surface |
|---|---|
| End users interacting with skills directly | Claude.ai / Claude Code |
| Manual testing and iteration during development | Claude.ai / Claude Code |
| Individual, ad-hoc workflows | Claude.ai / Claude Code |
| Applications using skills programmatically | API |
| Production deployments at scale | API |
| Automated pipelines and agent systems | API |
3.7 Troubleshooting Skills
Skill won’t upload
- “Could not find SKILL.md” → File must be exactly
SKILL.md(case-sensitive) - “Invalid frontmatter” → Missing
---delimiters, or unclosed quotes in YAML - “Invalid skill name” → Name has spaces or capitals; use
my-cool-skillnotMy Cool Skill
Skill doesn’t trigger automatically
- Description is too generic (“Helps with projects” won’t work)
- Missing trigger phrases users would actually say
- Fix: add more specific phrases and technical terms to description
Skill triggers too often
- Add negative triggers: “Do NOT use for X”
- Narrow the scope: “specifically for PayFlow payment workflows, not general financial queries”
Instructions not followed
- Instructions too verbose → use bullet points; move detail to
references/ - Critical instruction buried → put it at the top; use
## CRITICALheader - Ambiguous language → use explicit checklist format instead of prose
- Model “laziness” → add “Take your time. Quality over speed. Do not skip validation steps.” (more effective in user prompts than in SKILL.md)
Skill seems slow or degraded
- SKILL.md too large → move detailed docs to
references/, keep under 5,000 words - Too many skills enabled (20–50+ simultaneously degrades performance) → use selective enablement
4. CCA Exam Patterns
What the Exam Tests
- Task 3.1: Hierarchy — which CLAUDE.md takes precedence when rules conflict? (Answer: most specific wins)
- Task 3.1: Scope — does a subdirectory CLAUDE.md affect files outside that directory? (Answer: no)
- Task 3.2: allowedTools is deterministic enforcement, CLAUDE.md rules are probabilistic guidance
- Task 3.2: If a tool is blocked via allowedTools, no amount of prompting can override it
- Task 3.2: Subagent tool sets are defined per-AgentDefinition, not inherited from coordinator
5. Advanced Configuration (CCA 11.1–11.2)
Beyond basic CLAUDE.md files, the configuration system supports @-imports (shared rules across repos), path-specific rules (YAML frontmatter globs in .claude/rules/), auto memory (Claude’s persistent notepad), and skills (on-demand prompt templates that replace legacy slash commands). These features enable enterprise-scale agent governance while keeping individual repos clean and context-efficient.
5.1 @-Import Syntax & .claude/rules/
CLAUDE.md files support @path/to/file imports that pull external content directly into context at session start. Imported files expand inline — as if their content were written directly in the CLAUDE.md. Both relative and absolute paths are allowed; relative paths resolve relative to the importing file, not the working directory. Imports can nest recursively up to 4 hops deep.
`@README` stays literal, while @README outside backticks triggers the import. The first time Claude encounters external imports in a project, it shows an approval dialog — if you decline, imports stay disabled.
# CLAUDE.md — @-Import Syntax
See @README.md for project overview and @package.json for available npm commands.
# Additional Instructions
- Git workflow: @docs/git-instructions.md
- Personal overrides: @~/.claude/my-project-instructions.md
You can also import from your home directory for personal cross-project rules, or from URLs for company-wide standards shared across 50+ repos:
# CLAUDE.md — Import from multiple sources
# Team standards (checked into a shared repo):
@https://raw.githubusercontent.com/company/standards/main/python-rules.md
# Personal cross-project preferences (not committed):
@~/.claude/my-project-instructions.md
# Sibling file in the same directory:
@./shared/security-rules.md
For path-specific rules, create Markdown files under .claude/rules/. Each file uses YAML frontmatter with a paths: field to declare which files trigger the rule. Rules without a paths: field load unconditionally (like CLAUDE.md). Path-scoped rules trigger when Claude reads files matching the pattern — not on every tool use.
| Pattern | Matches |
|---|---|
**/*.ts | All TypeScript files in any directory |
src/**/* | All files under src/ directory |
src/components/*.tsx | React components in a specific directory |
src/**/*.{ts,tsx} | Brace expansion: multiple extensions |
**/tests/** | All files under any tests/ folder |
Here are three practical rule files demonstrating different scoping patterns:
# .claude/rules/python-style.md
---
paths:
- "**/*.py"
---
# Python Style Rules
- Use type hints on all function signatures
- Prefer async def for I/O-bound operations
- Maximum function length: 30 lines
- Use pathlib over os.path for file operations
# .claude/rules/test-conventions.md
---
paths:
- "**/tests/**"
- "**/*.test.ts"
- "**/*.spec.py"
---
# Test Conventions
- Use pytest fixtures (not setUp/tearDown)
- Name tests: test_[function]_[scenario]_[expected]
- One assertion per test function
- Mock external services, never call them
# .claude/rules/api-security.md
---
paths:
- "src/api/**/*.py"
- "src/routes/**/*.ts"
---
# API Security Rules
- All endpoints require authentication middleware
- Rate limit all public endpoints
- Input validation via Pydantic models (Python) or Zod (TypeScript)
- Never log request bodies (may contain PII)
- SQL queries must use parameterized statements
Rules without a paths: field load unconditionally and apply to all files — useful for universal project conventions that should always be active.
/compact, they reload the next time Claude reads a matching file. If a rule must persist across compaction, drop the paths: frontmatter or move it to the project-root CLAUDE.md. Unscoped rules and auto memory are re-injected from disk after compaction.
5.2 Auto Memory
Auto memory lets Claude accumulate knowledge across sessions without you writing anything. Claude saves notes for itself as it works: build commands, debugging insights, architecture notes, code style preferences, and workflow habits. It decides what’s worth remembering based on whether the information would be useful in a future conversation.
Auto memory is stored per git repository at ~/.claude/projects/<project>/memory/MEMORY.md. The first 200 lines or 25 KB of the MEMORY.md index is loaded at the start of every session. All worktrees of the same git repository share one auto memory directory. Auto memory is machine-local and not synced across machines.
How it works:
- Claude discovers something important during work (a build quirk, a team convention, an architecture decision)
- Claude writes it to auto memory automatically — no
/memory addcommand needed - In future sessions, this memory is loaded into context at start
What Claude typically remembers:
- Build commands: “npm run build fails unless NODE_ENV=production is set”
- Team conventions: “Alice reviews all auth PRs before merge”
- Project quirks: “The /legacy/ folder uses Python 2 — do not modernize”
- Debugging notes: “API timeouts usually mean Redis is down, check docker ps”
- Architecture: “Payment service uses event sourcing, not CRUD”
Memory structure on disk:
# ~/.claude/projects/<project>/memory/
# ├── MEMORY.md ← Concise index, loaded every session (first 200 lines)
# ├── debugging.md ← Detailed notes on debugging patterns
# ├── api-conventions.md ← API design decisions
# └── ... ← Claude creates topic files as needed
/compact (re-read from disk after compaction). Path-scoped rules do not survive compaction — they reload on the next matching file read.
| Command | Effect |
|---|---|
/memory | View which CLAUDE.md files, rules, and auto-memory entries loaded |
/context | Shows everything in the context window (system prompt, memory, skills, MCP tools, messages) |
/compact | Summarize context; auto memory and root CLAUDE.md are re-injected from disk |
/init | Generate a starter CLAUDE.md based on current project structure |
/doctor | Diagnose config errors, invalid keys, schema issues |
/debug | Enable debug logging for the session |
5.3 Skills (Replaces Legacy Slash Commands)
Skills are the recommended way to give Claude reusable prompts and workflows. They follow the Agent Skills open standard and replace the legacy .claude/commands/ format (which still works but is deprecated). A skill is a directory with a SKILL.md file containing YAML frontmatter and Markdown instructions.
Unlike CLAUDE.md (loaded every session), skills load on demand. Claude sees skill descriptions at startup and loads the full content only when relevant — so long reference material costs almost nothing until needed.
Two scopes:
- Project skills (
.claude/skills/<name>/SKILL.md) — shared with the team via git, specific to this project - User skills (
~/.claude/skills/<name>/SKILL.md) — personal skills, not committed to any repo
| Frontmatter | You Can Invoke | Claude Can Invoke | When Loaded |
|---|---|---|---|
| (default) | Yes | Yes | Description always in context; full skill on invocation |
disable-model-invocation: true | Yes | No | Hidden from Claude; loads only when you type /name |
user-invocable: false | No | Yes | Description always in context; Claude loads when relevant |
Example 1: A review skill that both you and Claude can invoke (default behavior). Invoked with /review-pr:
# .claude/skills/review-pr/SKILL.md
---
name: review-pr
description: Review current PR for bugs and style issues
---
Review the current git diff for:
1. Bugs or logic errors
2. Security vulnerabilities
3. Missing error handling
4. Style violations (per .claude/rules/)
Format your review as:
## Critical Issues (must fix)
## Suggestions (nice to have)
## Positive Notes
Example 2: A workflow skill with side effects that only you can trigger. The disable-model-invocation: true field prevents Claude from running it automatically — use this for deploy, send, or any destructive action:
# .claude/skills/fix-issue/SKILL.md
---
name: fix-issue
description: Fix a GitHub issue end-to-end
disable-model-invocation: true
---
Analyze and fix the GitHub issue: $ARGUMENTS
1. Use `gh issue view` to get the issue details
2. Understand the problem described in the issue
3. Search the codebase for relevant files
4. Implement the necessary changes
5. Write and run tests to verify the fix
6. Ensure code passes linting and type checking
7. Create a descriptive commit message
8. Push and create a PR
Invoked with /fix-issue 1234 — the $ARGUMENTS placeholder is replaced with whatever follows the command name.
Example 3: Background knowledge that only Claude can invoke. Setting user-invocable: false means Claude loads this when it detects the user is working on API files, but /api-conventions is not a meaningful command for the user to type:
# .claude/skills/api-conventions/SKILL.md
---
name: api-conventions
description: REST API design conventions for our services
user-invocable: false
---
# API Conventions
- Use kebab-case for URL paths
- Use camelCase for JSON properties
- Always include pagination for list endpoints
- Version APIs in the URL path (/v1/, /v2/)
- Return 201 for successful creation, 204 for deletion
- Include Link headers for pagination
.claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both create /deploy and work the same way. Existing command files continue to work — skills add optional features like invocation control and supporting files.
SDK Usage: Control which skills are available when using the Agent SDK programmatically:
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
# Skills in .claude/skills/ are discovered automatically
# when setting_sources includes "project"
async for message in query(
prompt="Review this PR using our code review checklist",
options=ClaudeAgentOptions(
setting_sources=["user", "project"],
skills="all", # Enable all discovered skills
# skills=["review-pr", "fix-issue"], # Enable only specific skills
# skills=[], # Disable all skills
allowed_tools=["Read", "Grep", "Glob"],
),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
@path imports pull content inline at session start (max 4 hops deep; backtick-wrapped paths are not imported). (2) .claude/rules/*.md files use YAML paths: globs (not applyTo:) to load per-path; they trigger on file reads, not every tool call. (3) Path-scoped rules are lost after /compact until a matching file is re-read; root CLAUDE.md and auto memory survive compaction. (4) Auto memory is stored at ~/.claude/projects/<project>/memory/MEMORY.md; first 200 lines load every session. (5) Skills (.claude/skills/<name>/SKILL.md) replace legacy commands; disable-model-invocation: true prevents Claude from auto-triggering. (6) $ARGUMENTS placeholder enables parameterized skills.
Next in the SDK Track
In Part 9: Plan Mode, Refinement & CI/CD, we cover plan mode for safe exploration before execution, iterative refinement with test-driven loops, and headless agent integration in CI/CD pipelines. Covers CCA Domain 3 Tasks 3.3 and 3.4.