0%
#claude-code#configuration#tutorial#setup#team-workflow#settings#hooks

The Complete .claude/ Folder Guide — Configure Claude Code for Team Workflows (2026)

Published 2026-05-0514 min read

[01]What Lives in the .claude/ Folder

Open any well-configured Claude Code project and you will find a .claude/ folder at the repo root. This is where a generic AI assistant becomes your project's specialist — it knows your codebase conventions, has access to the right tools, and follows your team's workflow rules. Configuring the Claude Code .claude folder properly is the highest-leverage one-time investment a team can make, and yet the official docs scatter the information across half a dozen pages. This guide consolidates everything in one place.

Here is the complete inventory:

.claude/
├── settings.json              # team-shared, committed to Git
├── settings.local.json        # personal, gitignored
├── commands/                  # custom slash commands
│   ├── deploy.md
│   └── review.md
├── agents/                    # custom subagents
│   ├── pr-reviewer.md
│   └── test-writer.md
├── hooks/                     # shell scripts triggered by events
│   └── post-edit.sh
└── CLAUDE.md                  # also valid here, though usually at repo root

And at the repo root, working alongside .claude/:

CLAUDE.md                     # project memory and standing instructions
.gitignore                    # must include .claude/settings.local.json

Each file plays a different role. The next sections walk through them in the order you will most often touch them: CLAUDE.md first (every project), then settings.json (permissions and hooks), then the commands/, agents/, and hooks/ directories for power users. We finish with team-sharing patterns and common pitfalls.

[02]CLAUDE.md — Project Memory and Standing Instructions

CLAUDE.md is the single most important file in your Claude Code setup. It loads into every session as standing instructions — the AI reads it before responding to your first message and treats its contents as binding context.

The file lives at the repo root by default (Claude Code looks there first), though you can also place it inside .claude/. Most teams use the repo root because it is more discoverable to humans browsing the project.

What to Put in CLAUDE.md

Three categories of content earn their keep:

  1. Common commands — the half-dozen shell commands developers actually run (npm run dev, pytest, cargo check). Include the flags. Claude will use these instead of inventing similar-but-wrong invocations.
  2. Architecture overview — entry points, routing layer, state management approach, key directories. Three to five bullet points; not a full architecture document.
  3. Conventions — naming, import paths, where new files go. The patterns Claude cannot derive from reading three files.

What to Leave Out

Everything Claude can derive by reading the actual code. Type definitions, function signatures, dependency lists — Claude can read package.json and tsconfig.json. Stuffing CLAUDE.md with derivable information just bloats every session and pushes the useful instructions further down.

Real Example

# MyApp

## Common Commands

```bash
npm run dev        # Vite dev server, port 3000
npm run build      # tsc + vite build → dist/
npm run check      # tsc --noEmit
npm run test       # vitest run
```

## Architecture

- React 19 SPA with Wouter (not React Router) for routing
- Tailwind v4 via Vite plugin (no PostCSS, no tailwind.config.js)
- All state in Zustand stores under client/src/stores/
- Path alias: @/* → client/src/*

## Conventions

- New components → client/src/components/
- shadcn/ui components are in client/src/components/ui/, do not edit
- All user-facing strings must use the t() hook from I18nContext

This is the kind of CLAUDE.md that pays for itself in one session. Compare to a 200-line monster that no human reads and no agent benefits from.

[03]settings.json — Permissions, Hooks, Environment

If CLAUDE.md is the brain, .claude/settings.json is the operating manual. It controls what tools Claude is allowed to use, what hooks fire on tool events, what environment variables get loaded, and a handful of quality-of-life options.

The schema is documented at https://json.schemastore.org/claude-code-settings.json — point your editor at it for autocomplete.

Permissions

The most consequential field is permissions.allow — a list of patterns that Claude can run without asking. Without explicit allows, Claude prompts on every shell command, which gets tedious fast.

{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "Bash(pytest:*)",
      "Read(./src/**)",
      "Edit(./src/**)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push:*)",
      "Bash(git reset --hard:*)"
    ]
  }
}

The pattern syntax is glob-style for paths and prefix-style for shell commands. Bash(npm run *) matches any npm run invocation; Bash(git diff:*) matches any git diff with arguments.

Allow generously for read operations, conservatively for writes. The tedium of confirming every git diff is real, and the risk of an unwanted git diff is zero. The same is not true for git push.

Environment Variables

{
  "env": {
    "NODE_ENV": "development",
    "DEBUG": "myapp:*"
  }
}

These get exported into Claude's tool-call environment. Useful for non-secret configuration that should be consistent across the team. Never put real secrets heresettings.json is checked into Git.

Quality-of-Life Settings

{
  "model": "claude-opus-4-5",
  "outputStyle": "concise",
  "statusLine": {
    "type": "command",
    "command": "echo $(git branch --show-current) | tr -d '\n'"
  }
}

The statusLine field is underused — it lets you display anything (current branch, uptime, deploy environment) at the bottom of the Claude Code UI. Cheap context that prevents a class of mistakes.

[04]Custom Slash Commands in .claude/commands/

Custom slash commands live in .claude/commands/ as Markdown files. The filename becomes the command name: .claude/commands/deploy.md defines /deploy.

Inside each file you write the prompt that Claude executes when the command runs. Standard frontmatter optionally restricts which tools the command can use:

---
description: Run a full pre-deploy check
allowed-tools: Bash, Read
---

Run these checks in order. Stop if any fail:

1. `npm run check` — TypeScript must pass with zero errors
2. `npm run test` — All tests must pass
3. `npm run build` — Production build must succeed
4. Check that no .env files have uncommitted changes
5. Confirm we are on the main branch

If everything passes, output `READY TO DEPLOY`. Otherwise output the exact command that failed.

Now anyone on the team can type /deploy in Claude Code and run the same five-step pre-flight check. The benefit is not just convenience — it is that the deploy procedure is now versioned in Git. New team members get it for free.

Arguments

Use $ARGUMENTS to pass arguments through:

---
description: Generate a migration for the named table
---

Create a database migration for the table: $ARGUMENTS

Use the migration template at scripts/migration-template.sql. Place the new
file in db/migrations/ with the naming convention `{timestamp}_{table}.sql`.

Then /migrate users generates a migration for the users table.

What to Make a Slash Command

Anything you do more than three times. Pre-deploy checks, generating boilerplate (new component, new test file, new API route), kicking off a complex review (security review, performance audit). One-off tasks should stay in regular conversation.

[05]Custom Subagents in .claude/agents/

Subagents are specialized Claude personas that can be delegated to from a main session. They live in .claude/agents/ as Markdown files with frontmatter:

---
name: pr-reviewer
description: Reviews pull request changes for security, performance, and style
tools: Read, Grep, Bash
model: claude-opus-4-5
---

You are an experienced engineer reviewing a pull request.

Focus on:
1. Security vulnerabilities (auth bypasses, injection, secrets in code)
2. Performance regressions (N+1 queries, blocking I/O on hot paths)
3. Test coverage for the changed lines
4. Adherence to the project's CLAUDE.md conventions

Be direct. If the PR is fine, say so in one sentence. If not, list issues
in priority order with file:line references.

The main session invokes them via the Agent tool. The subagent runs with its own context window, returns a focused result, and does not pollute the main conversation with intermediate exploration.

When to Use a Subagent vs a Slash Command

Use a slash command when…Use a subagent when…
The work is procedural (run X, then Y, then Z)The work needs judgment and exploration
You want the conversation to stay in main sessionYou want isolated context (e.g. for parallel investigations)
The output is short (status, summary)The output is a detailed report you'll read once

A common pattern: a slash command that orchestrates several subagent calls. /audit might invoke a security reviewer, a performance reviewer, and a docs reviewer in parallel, then synthesize results.

[06]Hooks in .claude/hooks/ — Automate Around Tool Calls

Hooks are shell commands that fire on Claude Code lifecycle events. They live in settings.json (or .claude/settings.local.json for personal hooks) under the hooks key:

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

This runs .claude/hooks/format.sh after every Edit, Write, or MultiEdit tool call — typical use case: run Prettier on the changed file so the AI's output always lands formatted.

Available Events

  • PreToolUse — fires before a tool runs. Can block the call by exiting non-zero. Useful for guardrails.
  • PostToolUse — fires after a tool runs. Useful for cleanup or formatting.
  • UserPromptSubmit — fires when the user submits a prompt. Useful for adding context.
  • Stop — fires when Claude finishes a response. Useful for notifications.
  • SessionStart / SessionEnd — useful for warming caches or saving telemetry.

Real Example: Auto-format Edited Files

#!/usr/bin/env bash
# .claude/hooks/format.sh
# Read the JSON event from stdin, extract the edited file path, run Prettier.

INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

if [[ -n "$FILE" && -f "$FILE" ]]; then
  case "$FILE" in
    *.ts|*.tsx|*.js|*.jsx|*.json|*.md)
      npx prettier --write "$FILE" 2>/dev/null
      ;;
  esac
fi

Make it executable (chmod +x), commit it, and now every team member's edits get formatted automatically. No more "Claude wrote it without trailing commas" PR comments.

[07]Sharing the .claude/ Folder Across a Team

The team-sharing model has one rule: commit settings.json, gitignore settings.local.json. Everything else flows from there.

What Goes Where

File / DirectoryCommitted to Git?Why
CLAUDE.mdYesProject knowledge belongs to the team
.claude/settings.jsonYesPermissions, hooks, env — team baseline
.claude/settings.local.jsonNo (gitignore)Personal preferences, machine-specific paths
.claude/commands/YesSlash commands are workflow assets
.claude/agents/YesSubagent definitions are team assets
.claude/hooks/*.shYesHooks must be reproducible across machines

Required .gitignore Entry

# In .gitignore at repo root:
.claude/settings.local.json

This is non-negotiable. settings.local.json is where developers put personal touches that should not affect teammates: a more permissive allow-list, a different model preference, machine-specific tool paths. Committing it leaks personal config and creates merge conflicts on every change.

The settings.local.json Override Pattern

Claude Code merges settings.json and settings.local.json at session start, with the local file winning on conflicts. The intent: team baseline + personal overrides. A common usage:

// .claude/settings.json (committed)
{
  "permissions": {
    "allow": ["Bash(npm run *)", "Read(./src/**)", "Edit(./src/**)"],
    "deny": ["Bash(rm -rf *)"]
  }
}

// .claude/settings.local.json (gitignored)
{
  "permissions": {
    "allow": ["Bash(docker *)", "Bash(kubectl *)"]
  }
}

Now everyone on the team gets the safe baseline, and a developer who actually uses Docker can opt-in to those permissions on their machine without imposing them on others.

[08]Eight Common Mistakes and How to Fix Them

Patterns we see in audits of Claude Code setups across teams. Each one trades a little setup pain now for a lot of tool-call pain later.

1. CLAUDE.md is a 500-line wall of derivable information

Fix: delete everything Claude can read from package.json, tsconfig, README. Keep only what you wish a new hire would memorize on day one.

2. settings.json with no permissions block

Fix: add at least the permissions.allow list for your top-five most-run commands. Your wrist will thank you.

3. settings.local.json committed to Git

Fix: git rm --cached .claude/settings.local.json, add to .gitignore, and tell your team to re-create personal versions.

4. Slash commands that duplicate shell commands

If /test just runs npm test, you don't need a slash command. Save them for procedures that involve multiple steps or judgment.

5. Subagents that have access to all tools

Defeats the purpose. A pr-reviewer subagent should not have Edit or Write in its tools list — review is read-only.

6. Hooks that mutate Claude's input or output silently

Hooks should observe and gate, not rewrite. Silent rewriting hides what Claude actually did from the user, which is bad for trust and bad for debugging.

7. Environment variables in settings.json with real secrets

Fix: never. Use a secrets manager or the user's shell environment. settings.json is committed.

8. No CLAUDE.md update process

The most insidious one. CLAUDE.md goes stale within weeks if no one owns it. Add a quarterly calendar reminder, or better: include "review CLAUDE.md" in your release checklist.

[09]A Real Team Workflow Example

Here is a complete .claude/ setup for a hypothetical mid-size React + Node team. Six files, all committed (except settings.local.json), about 250 lines total.

repo/
├── CLAUDE.md                              # 60 lines — commands, arch, conventions
├── .gitignore                             # contains: .claude/settings.local.json
└── .claude/
    ├── settings.json                       # 40 lines — permissions, hooks, env
    ├── commands/
    │   ├── deploy.md                       # /deploy — pre-flight + production push
    │   ├── new-component.md                # /new-component <name>
    │   └── audit.md                        # /audit — invokes 3 subagents
    ├── agents/
    │   ├── security-reviewer.md            # focuses on auth, injection, secrets
    │   ├── performance-reviewer.md         # focuses on queries, rendering
    │   └── docs-reviewer.md                # focuses on README and inline docs
    └── hooks/
        ├── format.sh                       # PostToolUse: Prettier on edited files
        └── pre-push-check.sh               # PreToolUse: blocks git push if checks fail

Time investment: roughly half a day for one engineer to write the initial set, then 30-minute increments as patterns emerge. Payoff: every developer on the team gets the same disciplined Claude setup automatically. New hires are productive on day one. The same /deploy works on every machine.

For more on individual pieces: see our Codex /pet command cheat sheet for a different CLI's command system, and the Buddy Checker for what was lost when Claude Code v2.1.97 retired the buddy feature.

[10]Frequently Asked Questions

Where does Claude Code look for the .claude folder?

It walks up from your current working directory looking for .claude/ or CLAUDE.md. The first match wins, which means a project's local config beats anything global. There is also a global config at ~/.claude/ for cross-project defaults.

Can I have a global CLAUDE.md that applies to all projects?

Yes — put it at ~/.claude/CLAUDE.md. It loads for every Claude Code session. Use this for personal preferences (preferred response style, common abbreviations) rather than project-specific instructions.

Should I check .claude/ into Git?

Yes for settings.json, slash commands, agents, hooks, and CLAUDE.md. No for settings.local.json — that goes in .gitignore. The committed files become a team asset; the local file stays personal.

How do I share permissions across multiple projects without copy-pasting?

Put common permissions in ~/.claude/settings.json (your global config). Project-level .claude/settings.json adds project-specific permissions on top. Both merge at session start with project-level winning on conflicts.

What's the difference between a slash command and a subagent?

Slash commands run in your main session and consume your context window. Subagents run in their own session with isolated context. Use slash commands for procedural work where you want the dialog visible; use subagents for exploratory work where you only want the conclusion. See section 5 for a comparison table.

Can I disable hooks for a single command?

Not easily — hooks fire on every matching event. The workaround is to make the hook itself smart enough to no-op based on the event payload (e.g. skip Prettier if the file is in a vendor directory). Read the JSON from stdin in the hook script and decide whether to run.

Why isn't my custom slash command showing up?

Three things to check: (1) the file is in .claude/commands/ with a .md extension, (2) the filename has no spaces or special characters, (3) you've restarted Claude Code after adding it (some versions cache the command list at session start).

Related reading: Codex /pet and /hatch command cheat sheet · Claude Buddy retired — migration guide · Claude Buddy Checker

// COMMENTS

github_discussions.sh

Sign in with GitHub to leave a comment.

Ready to find your buddy?

CHECK YOUR BUDDY

Built by the community. Not affiliated with Anthropic.

All computation is local. No data is collected or transmitted.

> EOF