MeshWorld India Logo MeshWorld.
Claude Code AI Agents Developer Tools Configuration Productivity Tutorial Developer Experience 42 min read

Master Your Workflow: Anatomy of the .claude Folder

Darsh Jariwala
By Darsh Jariwala
| Updated: Apr 28, 2026
Master Your Workflow: Anatomy of the .claude Folder

The Hidden Control Center

You open your project directory one morning and there it is—a folder you didn’t create. .claude. It appeared silently while you were working, like a digital artifact that materialized from nowhere.

Your first instinct? Add it to .gitignore and forget about it.

But here’s what nobody tells you: that folder is the most powerful tool in your development arsenal. It’s the difference between an AI assistant that gives you generic, tutorial-level code and one that operates as a senior architect who intimately understands your project, your conventions, and your team’s standards.

The .claude folder is Claude Code’s control center. It holds your instructions, your custom workflows, your permission guardrails, and even Claude’s memory across sessions. When configured properly, it transforms Claude from a helpful chatbot into a specialized member of your engineering team.

In this comprehensive guide, we’ll explore every file, every folder, and every configuration option inside .claude/. No shortcuts. No skipped details. Just a complete map of how to build a professional-grade AI workflow that 10x’s your engineering velocity.

What You'll Master

By the end of this guide, you’ll understand:

  • The 5 Subsystems: Instructions, Actions, Guardrails, Memory, and Workflows
  • Project vs. Global: When to share configurations and when to keep them personal
  • CLAUDE.md: The highest-leverage file and all its variants
  • Rules: Modular, path-scoped instructions for lean context
  • Skills: Reusable automation workflows with slash commands
  • Agents: Specialized personas that run in isolated contexts
  • Security: Permission models that protect your secrets
  • Progression: A 4-stage roadmap from beginner to power user

The Two Homes: Project vs. Global

Before we examine individual files, you need to understand that there are two .claude directories—not one. This distinction is fundamental to how you’ll organize your configurations.

Project-Level (./.claude/)

This lives in your repository root. Commit it to git. Your entire team benefits from the same rules, skills, and permission policies.

What’s stored here:

  • Team coding standards and conventions
  • Project-specific build and test commands
  • Shared automation workflows (skills)
  • Security policies that protect team secrets

Example scenario: Your team decides to use 2-space indentation and requires every API endpoint to have OpenAPI documentation. These rules live in the project-level .claude/ so every developer gets the same experience.

Global (~/.claude/)

This lives in your home directory (~/.claude/ on macOS/Linux, %USERPROFILE%\.claude on Windows). Never commit this. It contains your personal preferences that apply across every project.

What’s stored here:

  • Your personal coding style preferences
  • Machine-specific paths and configurations
  • Auto-memory: Claude’s notes about your work patterns
  • Skills and agents you want available everywhere

Example scenario: You prefer verbose test output, or you always want Claude to explain TypeScript generics because you’re still learning. These personal preferences stay in your global ~/.claude/ and follow you into every project.

The Precedence Stack

When settings conflict, which one wins? Here’s the complete priority order, from highest to lowest:

PrioritySourceLocationOverride Power
1 (Highest)Managed PolicySystem-level (IT-enforced)Organization-wide rules you cannot override
2CLI ArgumentsCommand line flagsPer-session overrides
3Local Overrides.claude/settings.local.jsonYour personal project preferences
4Project Settings.claude/settings.jsonTeam-shared defaults
5 (Lowest)User Settings~/.claude/settings.jsonYour global personal defaults

Key insight: Your team can set project defaults in settings.json, but you can override them locally in settings.local.json without affecting anyone else. This is perfect for machine-specific paths or personal workflow tweaks.

A Practical Example

Imagine your team has this in .claude/settings.json:

json
{
  "permissions": {
    "allow": ["Bash(npm run *)", "Bash(git status)"]
  }
}

But on your machine, you also use Docker for local development. You add this to .claude/settings.local.json (which is automatically gitignored):

json
{
  "permissions": {
    "allow": ["Bash(docker *)"]
  }
}

Result: You get all the team permissions plus your personal Docker permissions. The settings merge intelligently—arrays combine, scalar values use the local override.


CLAUDE.md: The Highest-Leverage File

If you only configure one thing, make it this file. CLAUDE.md is the single most important configuration file in the entire Claude Code ecosystem.

Why It’s So Powerful

When you start a Claude Code session, the first thing Claude reads is CLAUDE.md. It loads the contents directly into the system prompt, and those instructions persist for the entire conversation.

Think of it as onboarding documentation for a new senior engineer—except the engineer is Claude, and it reads this file in milliseconds.

What this means in practice:

  • Tell Claude to always write tests before implementation? It will.
  • Specify that all error handling must use structured logging? Done.
  • Require that every API endpoint returns typed results? Enforced.

Where CLAUDE.md Can Live

Claude Code walks up the directory tree from your current working directory, loading every CLAUDE.md it finds. This means you can have layered instructions:

LocationScopeShared?When It Loads
./CLAUDE.md (project root)Team instructionsVia gitEvery session
./.claude/CLAUDE.mdAlternative locationVia gitEvery session
./CLAUDE.local.mdPersonal project preferencesJust you (gitignored)Every session
~/.claude/CLAUDE.mdPersonal, all projectsJust youEvery session
src/Api/Handlers/CLAUDE.mdSubdirectory specificVia gitOn-demand when editing files there
Managed policy pathOrganization-wideAll usersEvery session

The subdirectory trick: If you’re working in src/Api/Handlers/ and there’s a CLAUDE.md in that subdirectory, Claude loads it on-demand when reading files there. Parent directory CLAUDE.md files load at startup. This is incredibly powerful for monorepos—you can have folder-specific API conventions without cluttering the root file.

What a Good CLAUDE.md Looks Like

Here’s a practical example for a modern web API project:

markdown
# Project Alpha API

Modern REST API built with Clean Architecture principles.

## Commands

npm run build              # Build the project
npm run test               # Run all tests (Jest)
npm run test:watch         # Run tests in watch mode
npm run lint               # ESLint with auto-fix
npm run db:migrate         # Apply database migrations
npm run db:seed            # Seed development data

## Architecture

- **Clean Architecture**: API → Application → Domain → Infrastructure
- **API Layer**: Express controllers in `src/api/controllers/`
- **Application Layer**: Use cases in `src/application/useCases/`
- **Domain Layer**: Entities and business logic in `src/domain/`
- **Infrastructure Layer**: Database, external APIs in `src/infrastructure/`
- **Database**: PostgreSQL with TypeORM
- **Testing**: Jest with supertest for integration tests

## Key Paths

| Component | Location |
|-----------|----------|
| API Controllers | `src/api/controllers/` |
| Use Cases | `src/application/useCases/` |
| Domain Entities | `src/domain/entities/` |
| Database Migrations | `src/infrastructure/database/migrations/` |
| Integration Tests | `tests/integration/` |
| Unit Tests | `src/**/*.test.ts` (next to source files) |

## Conventions

- **API Responses**: Always return `{ success: boolean, data?: T, error?: string }`
- **Error Handling**: Use `AppError` class with error codes; never throw raw errors
- **Logging**: Use `pino` logger; include correlation IDs in all logs
- **Validation**: Use Zod for input validation; validate at controller entry
- **Database**: Use repositories pattern; no raw SQL in controllers
- **Async**: Always use `async/await`; include error handling
- **Types**: Strict TypeScript; no `any` types except in test mocks

## Watch Out For

- Integration tests use a real PostgreSQL database via Docker Compose
- The `src/shared/` folder is referenced by both API and background workers
- Changes to domain entities require migration updates
- Rate limiting is enforced at the CDN level, not application level

That’s about 50 lines. It gives Claude everything needed to work productively without constant clarification.

Notice the structure:

  1. Commands: How to build, test, and run the project
  2. Architecture: High-level patterns and technology choices
  3. Key Paths: Where to find different types of files
  4. Conventions: Coding standards and patterns
  5. Watch Out For: Non-obvious gotchas and edge cases

This covers 95% of what Claude needs to know. The remaining 5% goes into specialized rule files (which we’ll cover next).

What NOT to Put in CLAUDE.md

Avoid these common mistakes:

  1. Linter rules: If ESLint/Prettier already enforces it, don’t duplicate it here
  2. Full documentation: Link to docs instead of pasting them
  3. Long theory paragraphs: Claude needs actionable instructions, not essays
  4. Code snippets: These belong in skills or the docs/ folder
  5. Implementation details: “How to configure Webpack” should be in docs, not CLAUDE.md

The 200-Line Rule

Target under 200 lines. Files longer than that consume excessive context and Claude’s instruction adherence actually drops. If yours is getting crowded, that’s your signal to split instructions into .claude/rules/ files.

CLAUDE.md Survives Compaction

Here’s a crucial detail: when you run /compact or Claude auto-compacts to manage context, CLAUDE.md is re-read fresh from disk. Instructions you give only in conversation will be lost after compaction, but CLAUDE.md instructions persist.

This makes CLAUDE.md the most reliable way to give Claude permanent, high-impact instructions.

Personal Overrides with @import

Sometimes you need preferences that are specific to you, not the whole team. The recommended approach is using @import syntax to pull in a personal file:

markdown
# In your project CLAUDE.md
@~/.claude/my-personal-preferences.md

# Team instructions below...

Or use ~/.claude/CLAUDE.md for preferences that apply across all your projects:

markdown
# Personal Preferences (in ~/.claude/CLAUDE.md)

- I prefer concise explanations—skip the obvious
- Always show full file paths in code references
- When suggesting refactors, explain the trade-off, not just the benefit
- I work on Windows with WSL—use Unix commands in Bash
- When explaining code, include the "why" alongside the "what"

The @import syntax supports relative and absolute paths with a maximum depth of 5 hops of recursive imports. First encounter of external imports triggers an approval dialog for security.


The rules/ Folder: Modular, Path-Scoped Instructions

CLAUDE.md works great for small projects. But once your instructions grow beyond 200 lines, or when multiple team members need to maintain different sections, you need modularity. That’s what .claude/rules/ provides.

The Problem: The “Junk Drawer” CLAUDE.md

Imagine a CLAUDE.md with 500 lines covering:

  • Frontend React conventions
  • Backend API design
  • Database migration standards
  • Testing requirements
  • Deployment procedures
  • Security guidelines

It’s a mess. When the backend lead wants to update API conventions, they scroll through 300 lines of React rules to find the right section. When the security team updates guidelines, they might accidentally break frontend formatting instructions.

The Solution: Modular Rules

Every markdown file inside .claude/rules/ gets loaded alongside your CLAUDE.md. Instead of one giant file, you split instructions by concern:

plaintext
.claude/rules/
├── code-style.md           # General formatting conventions
├── testing.md              # Test requirements and patterns
├── api-conventions.md      # REST API design standards
├── database.md             # Database and migration rules
├── security.md             # Auth patterns, secret handling
└── frontend/
    ├── react.md            # React component patterns
    └── styling.md          # CSS/styling conventions

Each file stays focused and easy to update. The API lead edits api-conventions.md. The QA engineer owns testing.md. Nobody steps on each other.

Rules Without Path Scoping: Always Loaded

Rules without frontmatter load at startup, every session. These are for instructions Claude needs regardless of what file it’s editing:

markdown
# .claude/rules/code-style.md

## General Conventions

- Use 2-space indentation everywhere
- Maximum line length: 100 characters
- Use single quotes for strings unless escaping is needed
- Prefer `const` over `let`; never use `var`
- Arrow functions for callbacks: `(x) => x * 2`

## Naming Conventions

- Variables: camelCase (`userName`, `isActive`)
- Constants: UPPER_SNAKE_CASE (`MAX_RETRY_COUNT`)
- Classes: PascalCase (`UserService`)
- Files: kebab-case (`user-service.ts`)
- Boolean variables: prefix with `is`, `has`, `should` (`isValid`, `hasPermission`)

## Error Handling

- Use custom error classes extending `AppError`
- Always include error codes for programmatic handling
- Log errors with full stack traces in development
- Never expose internal error details to API consumers

This loads every session because these conventions apply to every file in the project.

Path-Scoped Rules: The Secret Sauce

This is where rules become powerful. Add a YAML frontmatter block with paths, and the rule only activates when Claude is working with matching files:

markdown
---
paths:
  - "src/infrastructure/database/**/*.ts"
  - "**/*Repository*.ts"
  - "**/migrations/**"
---

# Database Rules

## Migrations

- Always use meaningful names: `add-user-email-index` not `migration-001`
- Include both `up()` and `down()` methods
- Test migrations against a copy of production data before deploying
- Run `npm run db:migrate:check` to verify SQL before applying

## Query Patterns

- Use parameterized queries; never concatenate SQL strings
- Add indexes for all foreign key columns
- Use transactions for multi-table operations
- Prefer explicit column lists over `SELECT *`

## TypeORM Conventions

- Always specify column types explicitly
- Use `CreateDateColumn` and `UpdateDateColumn` for timestamps
- Define relationships with `eager: false` by default

Why this matters: When you’re fixing a CSS bug in the frontend at 4:30 PM on a Friday, Claude’s context stays lean. It doesn’t waste tokens on database migration rules. When you open a migration file, those rules activate automatically.

Glob Pattern Reference

The paths array supports standard glob patterns:

PatternMatches
**/*.tsAll TypeScript files anywhere in the project
src/api/**/*.tsTypeScript files under src/api/ only
*.mdMarkdown files in project root only
src/**/*.{ts,tsx}Brace expansion for multiple extensions
**/*Repository*.tsAny file containing “Repository” in the name
tests/**All files in the tests directory
!**/*.test.tsNegation: exclude test files

Another Path-Scoped Example: API Design

markdown
---
paths:
  - "src/api/controllers/**/*.ts"
  - "src/api/routes/**/*.ts"
  - "**/endpoints/**/*.ts"
---

# API Design Rules

## Response Format

All endpoints must return this structure:
```typescript
{
  success: boolean;
  data?: T;
  error?: {
    code: string;
    message: string;
    details?: Record<string, string[]>;
  };
  meta?: {
    page?: number;
    limit?: number;
    total?: number;
  };
}

HTTP Status Codes

  • 200: Success with data
  • 201: Resource created
  • 204: Success with no content
  • 400: Validation error (bad request)
  • 401: Authentication required
  • 403: Permission denied
  • 404: Resource not found
  • 409: Conflict (duplicate, etc.)
  • 422: Unprocessable entity (business logic violation)
  • 500: Internal server error

Validation

  • Use Zod schemas for all input validation
  • Validate at controller entry, not in services
  • Return all validation errors at once, not first-only

Security

  • All endpoints except /health require authentication
  • Check resource ownership after authentication
  • Rate limiting headers must be present in responses
plaintext

### When to Split Out of CLAUDE.md

Use this rule of thumb:

- If a section in your CLAUDE.md is longer than 15-20 lines
- And it applies to a specific concern (testing, API design, database)
- **Move it to a rule file**

If it only applies to certain file types, add path scoping.

### Practical Split for a Typical Project

.claude/rules/ ├── code-style.md # No paths - always loaded ├── testing.md # paths: [”/*.test.ts”, “tests//”] ├── api-conventions.md # paths: [“src/api/**/.ts”] ├── database.md # paths: [“src/infrastructure/database//*”, “/migrations/”] ├── frontend-react.md # paths: [“src/frontend//.tsx”, “src/components/**/.tsx”] └── deployment.md # paths: [”**/Dockerfile*”, “docker-compose*.yml”, “*.tf”]

plaintext

### User-Level Rules

Personal rules in `~/.claude/rules/` apply to every project. They load before project rules, giving project rules higher priority when there's a conflict.

This is a good place for personal coding preferences that you want everywhere:

```markdown
# ~/.claude/rules/personal-style.md

## My Preferences

- I prefer verbose explanations—don't skip the "why"
- Always include import paths in code examples
- When suggesting libraries, mention 2-3 alternatives with trade-offs
- Use emojis in comments to mark TODOs (🔴 urgent, 🟡 pending, 🟢 done)

Skills: The Automation Engine

If CLAUDE.md is the instruction manual, skills are the automation engine. Each skill is a reusable workflow that Claude can invoke with a slash command or trigger automatically based on your conversation.

Skills vs Rules: The Critical Distinction

This trips up almost everyone at first:

AspectRulesSkills
When loadedAt startup (or on file access for path-scoped)On demand when invoked
How invokedAutomatic—Claude reads them silently/skill-name or auto-invoked by Claude
PurposePassive instructions (“always do X”)Active workflows (“do this sequence of steps”)
SizeShort (10-50 lines)Long (50-300 lines)
Context costAlways consuming contextOnly when active

The simple version: Rules tell Claude how to behave. Skills tell Claude what to do.

SKILL.md Format

Every skill lives in its own subdirectory with a SKILL.md file as the entry point:

plaintext
.claude/skills/
├── code-review/
│   └── SKILL.md
├── fix-issue/
│   └── SKILL.md
└── deploy/
    ├── SKILL.md
    └── templates/
        └── release-notes.md

Skills can bundle supporting files alongside SKILL.md. Reference them with @ syntax inside the skill:

markdown
### Step 3: Generate Release Notes
Read the template: @templates/release-notes.md

Use this template to format the release notes...

SKILL.md Frontmatter

The YAML frontmatter configures skill behavior:

markdown
---
name: code-review
description: Review the current branch for bugs, security issues, and code quality.
  Use when the user asks to review code, check a PR, or audit changes.
allowed-tools: Read Grep Glob Bash
argument-hint: [branch-name]
---

Frontmatter fields explained:

FieldPurposeExample
nameSlash command name (max 64 chars)code-review/code-review
descriptionWhen Claude should auto-invoke”Use when reviewing code for quality”
allowed-toolsTools that run without permission promptsRead Grep Glob
modelOverride the model for this skillsonnet (cheaper for simple tasks)
argument-hintAutocomplete hint in slash menu[branch-name]
contextRun in isolated subagent contextfork
agentSubagent type when context: forkExplore, Plan, or custom
effortEffort level overridehigh, low
disable-model-invocationPrevent auto-invoketrue (for destructive ops)
user-invocableHide from / menufalse (background knowledge)

Critical: The description field determines when Claude auto-invokes the skill. Claude reads all skill descriptions at session start. If your description is vague (“helps with code”), Claude invokes it at the wrong time. If it’s specific (“review current branch for bugs when user mentions ‘check this PR’”), Claude nails it.

Complete Skill Example: Code Review

markdown
---
name: code-review
description: Review the current branch for bugs, security issues, and code quality.
  Use when the user asks to review code, check a PR, or audit changes.
allowed-tools: Read Grep Glob Bash
argument-hint: [branch-name]
---

# Code Review

Review all changes on the current branch against main.

## Step 1: Get the Diff

\!`git diff main...HEAD --stat`

List all files changed with their change counts.

## Step 2: Read Changed Files

Read every modified file in full. Don't just look at the diff—understand the surrounding context.

For each file:
- Understand what the code does before the change
- Understand what the code does after the change
- Identify the intent behind the modification

## Step 3: Check Against Standards

Read `.claude/rules/code-style.md` and `.claude/rules/testing.md` for the team's quality bar.

Check for:
- **Bugs**: Logic errors, null reference risks, race conditions
- **Security**: Injection risks, auth gaps, exposed secrets, unsafe inputs
- **Quality**: Naming, complexity, missing error handling
- **Tests**: Is the change covered? What test cases are missing?
- **Performance**: N+1 queries, unnecessary iterations, memory leaks

## Step 4: Report

For each file, provide:
1. **Summary**: What changed and why
2. **Issues**: Specific problems with line references
3. **Suggestions**: Concrete improvements with code examples

Rate overall: **APPROVE**, **REQUEST CHANGES**, or **NEEDS DISCUSSION**.

Shell Injection with !backticks

The !backticks“ syntax runs shell commands before the skill content reaches Claude and injects the output. This is preprocessing—Claude sees the actual results, not the commands:

markdown
## Current PR Context

- Changed files: \!`git diff main...HEAD --name-only`
- Branch: \!`git branch --show-current`
- Last commit: \!`git log -1 --oneline`

When you invoke the skill, Claude sees something like:

plaintext
## Current PR Context

- Changed files: src/api/users.ts
              src/domain/user.ts
              tests/users.test.ts
- Branch: feature/user-auth
- Last commit: abc1234 Add user authentication

This makes skills dynamic and context-aware. The commands run fresh every time the skill is invoked.

String Substitutions

Skills support variable substitution:

VariableDescription
$ARGUMENTSAll arguments passed when invoking
$ARGUMENTS[0] or $0First argument (0-based index)
${CLAUDE_SESSION_ID}Current session ID
${CLAUDE_SKILL_DIR}Directory containing the SKILL.md file

Example usage:

A skill invoked with /fix-issue 234 would have $ARGUMENTS substituted with 234.

markdown
---
name: fix-issue
description: Investigate and fix a GitHub issue. Use when the user mentions
  an issue number or asks to fix a bug from GitHub.
argument-hint: [issue-number]
allowed-tools: Read Edit Write Grep Glob Bash
---

# Fix Issue

## Step 1: Understand the Issue

\!`gh issue view $ARGUMENTS --json title,body,labels,comments`

Analyze the issue description to understand:
- What is the expected behavior?
- What is the actual behavior?
- What are the reproduction steps?

## Step 2: Reproduce

Based on the issue description, identify the failing behavior.
Run the relevant test suite to see if there's already a failing test:

```bash
npm test -- --grep "relevant test pattern"

Step 3: Find the Root Cause

Trace the issue through the codebase:

  1. Identify the entry point mentioned in the issue
  2. Follow the code path to understand the flow
  3. Find where the behavior deviates from expected
  4. Don’t just fix the symptom—understand why it’s happening

Step 4: Fix and Test

  1. Implement the fix with minimal, focused changes
  2. Write a test that would have caught this issue
  3. Run the full test suite to check for regressions
  4. Verify the fix against the original issue description

Step 5: Summary

Report:

  • Root cause: What was causing the issue
  • Fix applied: What you changed and why
  • Test added: How this issue will be caught in the future
plaintext

### Auto-Invocation vs Manual Invocation

Skills can be invoked two ways:

| Method | How | Example |
|--------|-----|---------|
| **Manual** | You type `/fix-issue 234` | Explicit command |
| **Auto-invoked** | Claude matches your intent to a skill description | "Can you look at issue 234?" → Claude invokes `/fix-issue` |

**Control this behavior with frontmatter:**

| Frontmatter | User Invokes | Claude Invokes | When to Use |
|-------------|--------------|----------------|-------------|
| (default) | Yes | Yes | Most skills |
| `disable-model-invocation: true` | Yes | No | Destructive or expensive operations |
| `user-invocable: false` | No | Yes | Background knowledge skills |

**Best practice:** Use `disable-model-invocation: true` for deploy skills and anything that modifies production. You want to be deliberate about invoking those.

### Skill Context Budget

Skill descriptions consume about 1% of the context window (with an 8,000 character fallback). Each individual description is capped at 250 characters in the listing.

**What this means:**
- If you have many skills with long descriptions, they get shortened to fit
- This can strip the keywords Claude needs to match your request
- Run `/context` to check your current usage

**Mitigation strategies:**
1. Front-load the key use case in the first 250 characters
2. Set `disable-model-invocation: true` on rarely-used skills to remove them from context
3. Raise the limit with `SLASH_COMMAND_TOOL_CHAR_BUDGET` environment variable

### Where Skills Live

| Location | Shows As | Availability |
|----------|----------|--------------|
| `.claude/skills/<name>/SKILL.md` | `/<name>` | This project only |
| `~/.claude/skills/<name>/SKILL.md` | `/<name>` | All your projects |

Personal skills in `~/.claude/skills/` are available across all projects. Good candidates:
- Commit message generator following your convention
- Daily standup helper
- Quick security scan
- Personal code review checklist

---

## Commands: The Predecessor to Skills

Before skills existed, the `commands/` folder was how you created custom slash commands. Every markdown file in `.claude/commands/` becomes a command.

### How Commands Work

A file at `.claude/commands/review.md` creates `/project:review`.
A file at `.claude/commands/fix-issue.md` creates `/project:fix-issue`.

The filename (without extension) becomes the command name.

### Simple Command Example

```markdown
---
description: Quick health check of the project
---

## Build Status
\!`npm run build 2>&1 | tail -5`

## Test Results
\!`npm test 2>&1 | tail -10`

## Lint Status
\!`npm run lint 2>&1 | tail -5`

## Outdated Dependencies
\!`npm outdated`

Summarize the project health based on the above results.

Commands vs Skills: Current State

Important: Commands have been merged into the skills system. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create a /deploy command and work the same way.

  • Existing command files keep working
  • If a skill and command share the same name, the skill takes precedence

When to Use What

Use a Command When…Use a Skill When…
It’s a single-file promptIt needs supporting files alongside it
You always invoke it manuallyClaude should auto-invoke based on context
It’s simple (< 50 lines)It’s a multi-step workflow (50-300 lines)
No special tool restrictions neededYou want to limit which tools are available

Recommendation: If you’re starting fresh, just use skills. They’re strictly more capable. Commands are simpler to create (single file, no directory), but that’s about the only advantage.


Agents: Specialized Subagent Personas

When a task is complex enough to benefit from a dedicated specialist, you define a subagent persona in .claude/agents/. Each agent is a markdown file with its own system prompt, tool access, and model preference.

What Are Agents?

Think of agents like delegating to a specialist colleague:

  • You say: “Review this PR for security issues”
  • The security auditor agent spawns in its own context
  • It reads 50 files, runs security analysis
  • Returns a 1-paragraph summary to your main session

Your main conversation stays clean. You don’t see every file the agent opened or every grep it ran.

Agent File Structure

plaintext
.claude/agents/
├── code-reviewer.md
├── security-auditor.md
└── documentation-writer.md

Each file defines a specialized persona.

Complete Agent Example: Security Auditor

markdown
---
name: security-auditor
description: Security specialist. Use PROACTIVELY when reviewing code for
  vulnerabilities, before deployments, or when touching auth/payment logic.
tools: Read, Glob, Grep
model: sonnet
maxTurns: 50
---

You are a senior application security engineer with 10+ years of experience.

When auditing code:

## Authentication & Authorization
- Verify auth middleware is applied to all protected endpoints
- Check for proper session/token validation
- Ensure role-based access control (RBAC) is enforced
- Look for missing authorization checks on resource access

## Input Validation
- Check for SQL injection risks (even with ORMs—watch for raw queries)
- Verify all user inputs are validated before processing
- Look for XSS vulnerabilities in rendered output
- Check for command injection in shell executions

## Data Protection
- Verify sensitive data is encrypted at rest
- Check that secrets aren't logged or exposed in errors
- Ensure proper handling of PII (Personally Identifiable Information)
- Verify secure transmission (TLS) for sensitive operations

## Common Vulnerabilities
- Check for insecure deserialization
- Look for race conditions in concurrent operations
- Verify file upload restrictions (type, size, path traversal)
- Check for mass assignment vulnerabilities

## Reporting
Rate each finding: **CRITICAL** (exploitable now), **HIGH** (serious risk), **MEDIUM** (should fix), **LOW** (best practice)

Provide specific fixes with code examples for CRITICAL and HIGH findings.

How Agents Work

  1. Delegation: Claude spawns an isolated context for the agent
  2. Execution: The agent does its work—reading files, running searches, analyzing code
  3. Compression: Findings are compressed into a summary
  4. Return: Summary sent back to main session

The technical details: Agents run in separate context windows. This isolation means:

  • Your main session doesn’t get cluttered
  • The agent can use different tools than your main session
  • The agent can run a cheaper/faster model if appropriate

All Agent Frontmatter Fields

FieldPurposeExample
nameIdentifier (required)security-auditor
descriptionWhen to delegate (required)“Use when reviewing for security”
toolsWhat the agent can doRead, Glob, Grep
disallowedToolsTools to explicitly denyBash, Write
modelModel selectionsonnet, haiku, opus
maxTurnsMaximum iterations50
permissionModePermission leveldefault, acceptEdits, plan
isolationGit worktree isolationworktree
memoryPersistent memory scopeuser, project, local
backgroundAlways run as backgroundtrue
skillsPreload skills into context["api-conventions"]
mcpServersMCP servers available(inline or reference)

Tool Restrictions Are Intentional

A security auditor only needs Read, Grep, and Glob. It has no business writing files or executing commands. A documentation writer needs Read, Write, and Edit but doesn’t need Bash.

Being explicit about tool access is a safety feature, not just configuration.

Model Selection Saves Money

Use cheaper, faster models for focused tasks:

  • Haiku: Read-only exploration, simple searches
  • Sonnet: Most tasks—good balance of speed and capability
  • Opus: Complex reasoning, architectural decisions, debugging

Example: A code reviewer that only reads and analyzes can run on Haiku. Save Opus for tasks that actually need deep reasoning.

Agents vs Skills: The Comparison

AspectSkillsAgents
ContextShared in main chat (unless context: fork)Always isolated
IdentityClaude with specific task instructionsSeparate persona with own system prompt
ToolsRestricted via allowed-toolsRestricted via tools/disallowedTools
PersistenceNo persistent stateCan have memory across sessions
NestingCan spawn agentsCannot spawn other agents
Best forRepeatable workflowsSpecialist expertise needing isolation

Rule of thumb:

  • Need Claude to do a specific task (deploy, review, fix)? → Use a skill
  • Need Claude to become a specialist (security auditor, performance optimizer)? → Use an agent

The docs/ Folder: Shared Knowledge Base

This pattern has become essential for any non-trivial .claude setup. The .claude/docs/ directory holds reference documents that skills read on demand.

Why docs/?

The problem with putting everything in rules: Rules load automatically. If you put a 200-line architecture document in a rule file, it consumes context in every session—even when you’re fixing a CSS bug and the architecture doc is completely irrelevant.

The solution: Docs stay dormant until a skill explicitly reads them. Each skill only loads the docs it needs.

Typical docs/ Structure

plaintext
.claude/docs/
├── architecture.md           # System architecture, module boundaries
├── coding-standards.md       # Style guide, naming conventions
├── deployment.md            # Deploy process, environments, rollback
├── testing-strategy.md       # What to test, how to test, coverage targets
├── api-guidelines.md        # REST conventions, versioning, pagination
└── onboarding.md            # New engineer guide

How Skills Use docs/

A /code-review skill might read:

markdown
### Step 3: Check Against Standards
Read `.claude/docs/coding-standards.md` for the team's quality bar.
Read `.claude/docs/testing-strategy.md` for test coverage requirements.

A /deploy skill might read:

markdown
### Step 1: Review Deployment Checklist
Read `.claude/docs/deployment.md` and follow the production release procedure.

The DRY Principle for Prompt Engineering

Without a docs folder, every skill needing coding standards would have its own copy:

markdown
# In skill 1:
- Use 2-space indentation
- Maximum line length: 100
- Prefer const over let

# In skill 2:
- Use 2-space indentation
- Maximum line length: 100
- Prefer const over let

When you update a convention, you’d have to update it in every skill.

With docs/: The coding standard lives in one place. Skills reference it:

markdown
### Step 3: Check Against Standards
Read `.claude/docs/coding-standards.md` for the team's quality bar.

One source of truth, referenced by many skills. The same principle that makes good code also makes good Claude configuration.

What Belongs Where?

Put it in…When…Example Size
CLAUDE.mdClaude needs it every session, it’s short< 20 lines per section
rules/Claude needs it every session (or path-scoped), focused on one concern10-50 lines
docs/Only specific skills need it, detailed reference material50-300 lines
skills/It’s a reusable workflow with specific steps50-300 lines

settings.json: Permissions and Guardrails

The settings.json file inside .claude/ controls what Claude is and isn’t allowed to do. It’s where you define tool permissions, hook configurations, and project-level settings.

The Permission Model

Claude Code has three permission levels:

LevelEffectConfigured In
AllowRuns without askingpermissions.allow
AskPrompts for approvalDefault for unlisted tools
DenyBlocked entirelypermissions.deny

If a command isn’t in either allow or deny, Claude asks before proceeding. This middle ground is intentional—you don’t need to anticipate every possible command upfront.

Complete settings.json Example

json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(npm test *)",
      "Bash(npm run build *)",
      "Bash(npm run lint *)",
      "Bash(git status)",
      "Bash(git diff *)",
      "Bash(git log *)",
      "Bash(git branch *)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(docker ps)",
      "Bash(docker compose *)",
      "Read",
      "Write",
      "Edit",
      "Glob",
      "Grep",
      "WebFetch"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(curl *)",
      "Bash(wget *)",
      "Bash(git push *)",
      "Bash(git reset --hard *)",
      "Bash(git clean -fd *)",
      "Bash(sudo *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(**/*secret*)",
      "Read(**/secrets.*)",
      "Read(**/credentials.*)",
      "Read(**/private-key*)",
      "Read(**/id_rsa*)",
      "Read(**/id_ed25519*)"
    ]
  },
  "env": {
    "NODE_ENV": "development",
    "LOG_LEVEL": "debug"
  },
  "autoMemoryEnabled": true,
  "includeGitInstructions": true
}

Permission Rule Syntax

The pattern matching is flexible:

RuleMatches
BashAll Bash commands
Bash(npm run *)Commands starting with npm run
Bash(npm test *)Commands starting with npm test
Read(./.env)Reading the specific file
Read(**/.env)Reading any .env file anywhere
WebFetch(domain:github.com)Fetch requests to github.com
Agent(Explore)Spawning the Explore subagent
Skill(deploy *)Invoking skills starting with “deploy”

Rule Evaluation Order

Rules evaluate in this order:

  1. Deny first—if it matches a deny rule, it’s blocked
  2. Ask—if not in allow or deny, prompt for approval
  3. Allow—if it matches an allow rule, run without asking

Critical: A deny rule always wins, even if there’s a matching allow rule.

The $schema Line

Always include this:

json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  ...
}

It enables autocomplete and inline validation in VS Code, Cursor, and other editors.

PRO TIP: Start Minimal

Don’t try to create the perfect settings.json upfront. Instead:

  1. Start with a minimal configuration
  2. Let Claude prompt you when it needs permissions
  3. When you find yourself clicking “allow” for the same command repeatedly, add it to the allow list

This is safer than guessing what to allow upfront.

settings.local.json: Personal Overrides

Create .claude/settings.local.json for permission changes you don’t want committed to git. Claude Code automatically configures git to ignore this file.

Example use cases:

  • API keys in environment variables
  • Domain-specific WebFetch permissions
  • Machine-specific paths (your database might be on port 5433 instead of 5432)
  • Personal tool preferences

The team’s settings.json stays clean with just the essentials. Your personal overrides live in settings.local.json.

Beyond Permissions

settings.json handles more than permissions:

json
{
  "env": {
    "NODE_ENV": "development",
    "API_BASE_URL": "http://localhost:3000"
  },
  "model": "claude-sonnet-4",
  "effortLevel": "high",
  "autoMemoryEnabled": true,
  "includeGitInstructions": true,
  "claudeMdExcludes": [
    "**/node_modules/**/CLAUDE.md",
    "**/dist/**/CLAUDE.md"
  ],
  "statusLine": {
    "enabled": true,
    "format": "{model} | {tokens} tokens"
  }
}

Field explanations:

FieldPurpose
envEnvironment variables for every session
modelOverride the default model
effortLevelPersist effort level (low, medium, high)
autoMemoryEnabledToggle auto-memory (default: true)
includeGitInstructionsInclude git context in prompts
claudeMdExcludesSkip irrelevant CLAUDE.md files in monorepos
statusLineCustom status line configuration

Monorepo tip: Use claudeMdExcludes to skip CLAUDE.md files from other teams’ directories that aren’t relevant to your work.


The Global ~/.claude/ Folder: Memory and Personal Config

You don’t interact with this folder often, but understanding it helps you grasp how Claude “remembers” things across sessions.

What’s Inside ~/.claude/

PathPurpose
~/.claude/CLAUDE.mdPersonal instructions for all projects
~/.claude/settings.jsonGlobal permission settings
~/.claude/rules/Personal rules loaded in every project
~/.claude/skills/Personal skills available everywhere
~/.claude/agents/Personal agents available everywhere
~/.claude/projects/<project>/memory/Per-project auto-memory
~/.claude/plugins/Installed plugins and marketplaces

The Auto-Memory System

This is one of the least understood but most powerful features. Claude Code automatically saves notes as it works:

  • Commands it discovers
  • Patterns it observes
  • Architectural insights
  • Your preferences and corrections

Where it’s stored:

plaintext
~/.claude/projects/<project>/memory/
├── MEMORY.md                    # Index file
├── commands_discovered.md       # Commands Claude learned
├── patterns_observed.md         # Code patterns in your codebase
├── user_preferences.md          # Your stated preferences
└── architecture_insights.md     # High-level architectural notes

How it works:

  • The <project> directory is derived from your git repo
  • All worktrees and subdirectories share one auto-memory directory
  • MEMORY.md is loaded at every session start (first 200 lines or 25KB)
  • Topic-specific files are loaded on demand

You can manage memory with the /memory command.

Example memory entries:

markdown
# User Preferences

- User prefers verbose test output with full stack traces
- User likes TypeScript generics explained in comments
- User runs tests with --watch flag by default

# Commands Discovered

- `npm run db:reset` - Full database reset for testing
- `npm run test:e2e` - End-to-end test suite
- Custom script: `scripts/verify-migrations.sh`

# Architecture Insights

- The auth flow goes: Controller → AuthService → JWT middleware → Route handler
- Database migrations must be verified against staging before prod
- The `shared/` folder is referenced by both API and workers

Key things to know:

  • Auto-memory is machine-local—it doesn’t sync across machines
  • It’s not shared with your team—it’s Claude’s personal notebook
  • Toggle it: autoMemoryEnabled setting or CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 env var
  • You can tell Claude to remember things explicitly: “Remember that I prefer integration tests over mocks”

Global CLAUDE.md

Your ~/.claude/CLAUDE.md loads into every Claude Code session. This is the place for preferences that apply regardless of project:

markdown
# Personal Preferences

## Communication Style
- I prefer concise explanations—skip the obvious
- Always show full file paths in code references
- When suggesting refactors, explain the trade-off, not just the benefit

## Technical Preferences
- Prefer functional programming patterns over OOP when possible
- Always use strict type checking—no `any` types
- Include error handling in every async function
- Write tests before implementation when possible

## Environment
- I work on macOS with Homebrew
- Use zsh commands in Bash tool
- My editor is VS Code with Vim keybindings

## Learning Style
- When introducing new concepts, connect them to something familiar
- Use analogies to explain complex technical ideas
- I learn best by seeing examples, then trying myself

User-level rules in ~/.claude/rules/ load before project rules, giving project rules higher priority when there’s a conflict.


The worktrees/ Folder: Isolated Agent Work

This folder exists for Claude Code’s git worktree integration. It enables agents to work on isolated branches without affecting your main working directory.

How Worktrees Work

When you or an agent runs with isolation: worktree, Claude:

  1. Creates a temporary copy of your repository
  2. Places it in a separate git worktree
  3. The agent works on an isolated branch
  4. Your main working directory stays untouched

Lifecycle of a Worktree

Creation:

  • Agent starts with isolation: worktree
  • Claude creates worktree in .claude/worktrees/<unique-id>/
  • Checks out a new branch for the agent’s work

During work:

  • Agent reads, writes, tests in the worktree
  • Your main repo is unaffected
  • You can keep working normally

Cleanup:

  • If no changes: Worktree is deleted automatically
  • If changes were made: Worktree persists with its branch for review

Use Case: Code Review Without Disruption

A code reviewer agent running in a worktree can:

  1. Checkout the PR branch
  2. Run tests
  3. Analyze changes
  4. Leave comments

All while you continue working on your current feature branch in the main directory.

Configuration

Enable worktrees in agent frontmatter:

markdown
---
name: code-reviewer
description: Review code in isolated worktree
isolation: worktree
tools: Read, Grep, Glob, Bash
---

Or in settings.json:

json
{
  "worktree": {
    "enabled": true,
    "symlinks": false,
    "sparsePaths": ["src/", "tests/"]
  }
}

The Progression Path: From Beginner to Power User

Don’t try to build everything at once. Here’s the recommended progression:

Stage 1: The Basics (Day 1)

Goal: Get immediate value with minimal setup

Create:

plaintext
your-project/
├── CLAUDE.md              # 30-50 lines with essentials
└── .claude/
    └── settings.json      # Basic allow/deny rules

CLAUDE.md should include:

  • Build, test, and lint commands
  • Architecture overview (3-5 bullet points)
  • Top 3-5 coding conventions
  • One “watch out for” gotcha

settings.json should include:

  • Allow: project build/test commands
  • Allow: git status, diff, log
  • Deny: reading .env files, secrets
  • Deny: destructive operations (rm -rf, git reset —hard)

Result: Claude now understands your project basics. You’ll immediately notice better suggestions.

Stage 2: Modular Rules (Week 2-3)

Goal: Split CLAUDE.md as it grows; add path-scoped rules

Create:

plaintext
your-project/
├── CLAUDE.md              # Trimmed to 50-80 lines
└── .claude/
    ├── settings.json
    └── rules/
        ├── code-style.md           # Always loaded
        ├── testing.md              # paths: ["**/*.test.ts"]
        ├── api-conventions.md      # paths: ["src/api/**/*"]
        └── database.md             # paths: ["src/db/**/*", "**/migrations/**"]

When to move something to rules:

  • It’s longer than 20 lines in CLAUDE.md
  • It applies to a specific concern (testing, API design)
  • It only applies to certain file types (add path scoping)

Result: Your context stays lean. Claude only loads relevant rules. Team members can own different rule files.

Stage 3: First Skills (Month 2)

Goal: Automate repeated workflows

When you catch yourself copy-pasting the same prompt more than twice, turn it into a skill.

Create:

plaintext
your-project/
├── CLAUDE.md
└── .claude/
    ├── settings.json
    ├── rules/
    └── skills/
        ├── code-review/
        │   └── SKILL.md
        ├── fix-issue/
        │   └── SKILL.md
        └── deploy/
            ├── SKILL.md
            └── templates/
                └── release-notes.md

Good first skills:

  • /code-review - Review current branch
  • /fix-issue - Investigate and fix GitHub issues
  • /refactor - Apply specific refactoring patterns
  • /test - Generate tests for modified code
  • /docs - Update documentation for changes

Result: You stop writing repetitive prompts. Claude executes consistent workflows with a single command.

Stage 4: The Full System (Month 3+)

Goal: Add specialists and shared knowledge

Create:

plaintext
your-project/
├── CLAUDE.md
└── .claude/
    ├── settings.json
    ├── settings.local.json    # Personal overrides
    ├── rules/                 # 3-5 rule files
    ├── skills/                # 5-15 skills
    ├── agents/                # 2-3 specialized agents
    │   ├── code-reviewer.md
    │   └── security-auditor.md
    └── docs/                  # Reference docs
        ├── architecture.md
        ├── coding-standards.md
        └── deployment.md

Add agents when:

  • A task is complex enough to benefit from isolation
  • You need a specialist perspective (security, performance)
  • You want to keep main history clean

Add docs when:

  • Multiple skills reference the same information
  • You have detailed reference material (> 50 lines)
  • You want one source of truth for standards

Result: You have a professional-grade AI workflow. Claude operates as a senior architect who knows your codebase intimately.

Decision Matrix: Which File to Create?

Your SituationCreate This
Just started with Claude CodeCLAUDE.md + settings.json
CLAUDE.md over 200 linesSplit into .claude/rules/ files
Different rules for different file typesAdd paths: frontmatter to rules
Copy-pasting the same prompt repeatedlyCreate a skill
Need a specialist (security audit, code review)Create an agent
Multiple skills reference the same infoMove it to .claude/docs/
Clicking “allow” on the same command repeatedlyAdd to settings.json
Personal preferences you don’t want to commitsettings.local.json or ~/.claude/

Troubleshooting: When Things Don’t Work

Claude Ignores My Rules File

Check:

  1. File is in .claude/rules/ (not .claude/rule/)
  2. File has .md extension
  3. If it has paths: frontmatter, verify the glob pattern matches files you’re editing
  4. Rules with path scoping only load when Claude accesses matching files
  5. Run /context to see what rules are loaded

Skill Doesn’t Show Up in Slash Menu

Check:

  1. Skill needs SKILL.md file (case matters on Linux/macOS)
  2. Inside a named subdirectory of .claude/skills/
  3. Directory name uses only lowercase, numbers, hyphens (max 64 chars)
  4. Run /context to check if skill was excluded due to context budget
  5. Check SLASH_COMMAND_TOOL_CHAR_BUDGET if you have many skills

Claude Auto-Invokes the Wrong Skill

Problem: Skill descriptions are too similar or vague.

Fix: Make each description specific about when to invoke:

Instead of:

yaml
description: Helps with testing

Write:

yaml
description: Run the full test suite and report failures with stack traces.
  Use when the user asks to run tests, check for regressions, or verify code works.

Permission Prompts Keep Appearing

Fix: Add the exact command pattern to permissions.allow:

json
{
  "permissions": {
    "allow": [
      "Bash(npm run test *)",
      "Bash(npm run build *)",
      "Bash(git diff *)"
    ]
  }
}

Use wildcards: Bash(npm test *) covers npm test, npm test --watch, etc.

Remember: settings.local.json overrides are gitignored, so use that for machine-specific permissions.

CLAUDE.md Changes Don’t Take Effect

How it works:

  • Claude reads CLAUDE.md at session start
  • Claude re-reads it after /compact
  • Mid-session changes aren’t picked up until new session or compaction

Fix: Start a fresh session to test changes, or run /compact to force re-read.

Context Budget Exceeded—Skills Disappearing

Problem: Skill descriptions consume about 1% of context window (8,000 character fallback). Each description capped at 250 characters in listing.

Symptoms:

  • Skills disappear from /context output
  • Claude doesn’t invoke skills it should
  • Skill descriptions truncated in listings

Fixes:

  1. Front-load key use case in first 250 characters of description
  2. Set disable-model-invocation: true on rarely-used skills
  3. Raise limit: SLASH_COMMAND_TOOL_CHAR_BUDGET environment variable
  4. Reduce number of skills, consolidate related ones

”I added a rule but it doesn’t apply”

Check:

  1. Rule is in .claude/rules/ subdirectory (not root)
  2. YAML frontmatter is valid (check for syntax errors)
  3. If using paths:, verify files you’re editing match the glob
  4. Rules without paths: should apply to all files

”My agent isn’t being invoked”

Check:

  1. Agent file is in .claude/agents/ (not .claude/agent/)
  2. Has required frontmatter: name, description
  3. Description matches your request language
  4. Agent has appropriate tools for the task

Key Takeaways

  1. The .claude folder is a protocol for telling Claude who you are, what your project does, and what rules it should follow. The more clearly you define this, the less time you spend correcting Claude.

  2. CLAUDE.md is your highest-leverage file. Get this right first. Everything else is optimization. Keep it under 200 lines, focus on commands, architecture, and conventions.

  3. Rules provide modularity. Split CLAUDE.md into .claude/rules/ when it grows. Use path-scoping to keep context lean—Claude only loads relevant rules.

  4. Skills are automation engines. Turn repeated prompts into reusable workflows. Use frontmatter to control auto-invocation, tool access, and behavior.

  5. Agents provide specialist expertise. When a task needs isolation or a dedicated persona, spawn an agent. Your main session stays clean.

  6. Security starts with settings.json. Use the permission model (allow/ask/deny) to protect secrets and prevent destructive operations.

  7. Start small, grow organically. Don’t build everything at once. Stage 1: CLAUDE.md + settings.json. Stage 2: Modular rules. Stage 3: Skills. Stage 4: Agents and docs.

  8. Treat it like infrastructure. Your .claude configuration is part of your project. Version it, refine it, and share it with your team. It pays dividends every day.


Ready to dive deeper? Here are related guides to continue your mastery: