Claude Code Projects Tutorial: Set Up Project Memory, Config, and Team Workflows
Introduction
Claude Code becomes dramatically more useful once you stop treating it as a blank chat window and start treating each repository as a configured project. A Claude Code project is the bundle of files that tells Claude how your codebase works: project instructions in CLAUDE.md, shared permissions in .claude/settings.json, team MCP servers in .mcp.json, plus reusable commands, skills, and subagents under .claude/. This tutorial builds that bundle from scratch on a real demo repository. Every command below was run against a genuine Claude Code 2.1.296 installation on Linux, and the outputs are the actual transcripts.
Quick answer
Create a CLAUDE.md in your project root with build commands and conventions, put shared config in .claude/settings.json and .mcp.json, then add team commands, skills, and agents under .claude/. Verify with claude doctor and /context.
Evidence
The scale of Claude Code adoption makes project configuration a team discipline rather than a personal habit. In the week of 2026-10-05 to 2026-10-11, the @anthropic-ai/claude-code npm package recorded 12,502,712 downloads, according to the npm registry downloads API. The anthropics/claude-code GitHub repository carried 150,421 stars as of 2026-10-12, per the GitHub API, with commits landing the day before. Teams that large cannot coordinate on chat prompts alone, which is why the official configuration surface exists.
Anthropic’s own guidance on writing project instructions is blunt and worth quoting: “The more specific and concise your instructions, the more consistently Claude follows them.” That line comes from the official How Claude remembers your project page, which also sets a hard number for instruction hygiene: target under 200 lines per CLAUDE.md file, because longer files consume more context and reduce adherence. The same documentation describes project-scoped MCP servers in .mcp.json as committed to the repository but gated behind workspace trust and explicit approval, and the settings reference defines the precedence order for user, project, and local configuration scopes.
Prerequisites
- Node.js 18 or newer with npm available, to install Claude Code.
- An Anthropic API key or a Claude subscription, because you need
claude auth loginbefore interactive sessions work. The read-only diagnostics in this tutorial (claude doctor,claude --help) work without authentication. - A git repository for your project, so the team can share the configuration through version control.
- About 30 minutes.
Step-by-step guide
Step 1: Install Claude Code and open your project
Install the CLI globally and confirm the version:
npm install -g @anthropic-ai/claude-code
claude --version
On this lab machine the install completed in under a minute and reported 2.1.296 (Claude Code). Move into your repository and launch a session:
cd ~/my-project
claude
From this point on, every file you create under the project directory can become part of the project’s configuration. If you have never run Claude Code before, run claude auth login first and follow the browser sign-in flow.
Step 2: Generate the project CLAUDE.md with /init
CLAUDE.md is the file where the project’s persistent instructions live: build commands, coding conventions, architecture notes, and workflows Claude should know without being told. The fastest way to start is the bundled /init command. Inside a session, type /init and answer the questions it asks about your stack. Claude inspects the repository and writes a starter CLAUDE.md at the project root.
You do not have to keep everything /init writes. Edit the file down to facts Claude must hold in every session: the build command, the test command, the lint command, the directory layout, and two or three “always do X” rules. The official docs are explicit that project instructions can live at either ./CLAUDE.md or ./.claude/CLAUDE.md, and my recommendation for teams is the repo root: it is the first file new developers see, and it signals that the instructions are a team artifact, not hidden config.
To confirm the file actually loaded, run /context in the session and check the Memory files list. Your CLAUDE.md should appear there. If it does not, you launched Claude Code from a different directory, because discovery recurses upward from the working directory.
Step 3: Understand the instruction scope ladder
Before adding more files, it helps to see where project instructions sit in the full precedence ladder. Claude Code loads CLAUDE.md files from broadest to most specific scope, in this order:
| Scope | Location | Shared with |
|---|---|---|
| Managed policy | /etc/claude-code/CLAUDE.md (Linux) | Everyone in the organization, managed by IT |
| User instructions | ~/.claude/CLAUDE.md | Only you, across all projects |
| Project instructions | ./CLAUDE.md or ./.claude/CLAUDE.md | The team, through version control |
| Local instructions | ./CLAUDE.local.md | Only you, in this project |
Two properties of this ladder matter in practice. First, discovered files are concatenated into context rather than overriding each other, so a user-level rule and a project-level rule can coexist. Second, files in subdirectories of the working directory load on demand, only once Claude reads a file in that subdirectory, which keeps monorepo context lean.
Two companion mechanisms round out project memory. The .claude/rules/ directory holds topic files like testing.md that can be scoped to file paths with paths: frontmatter, so TypeScript testing rules only load when Claude touches TypeScript tests. And CLAUDE.md supports @path/to/file imports up to four hops deep, which lets you split a long instructions file without changing what loads. For purely personal project notes, create CLAUDE.local.md at the project root, load it alongside the team file, and add it to .gitignore so it is never committed.
Step 4: Add project-scoped settings with .claude/settings.json
Project settings live in .claude/settings.json and the most valuable section for teams is permissions. Instead of every developer answering the same “allow this bash command?” prompt fifty times a day, you pre-approve the commands your project actually uses and deny the dangerous ones. A real settings file for a Node.js project looks like this:
{
"permissions": {
"allow": ["Bash(npm test)", "Bash(npm run lint)", "Read(./src/**)"],
"deny": ["Bash(rm -rf *)"]
}
}
Write concrete tool patterns: Bash(npm test) approves exactly that command, while Bash(npm *) would approve any npm invocation. Keep the allow list tight enough that a compromised instruction file cannot silently run destructive commands. The full precedence and schema reference is documented in the settings documentation, which is the authoritative source when a setting behaves unexpectedly.
Step 5: Add project-scoped MCP servers with .mcp.json
Project MCP servers are declared in .mcp.json at the repository root and committed to git, so the whole team gets the same tool connections. Add one from the terminal with the project scope flag:
claude mcp add --scope project github -- npx -y @modelcontextprotocol/server-github
Everything after -- is the server’s launch command, passed through untouched. For secrets, never hard-code tokens in a committed file. Reference them as environment variables and let each developer export their own:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}" }
}
}
}
Project-scoped servers require workspace trust and explicit approval before Claude connects to them, because a malicious .mcp.json could otherwise exfiltrate data. You can see the pending state any time with claude mcp list, where unapproved servers show as paused and are health-checked only after approval. If you are new to MCP scopes, read our Claude Code MCP setup guide first, which walks through local, project, and user scopes with the exact CLI syntax, and the general MCP server tutorial for how the protocol itself works.
Step 6: Add team slash commands, skills, and subagents
The .claude/ directory is also where the team’s reusable behavior lives. Create a custom slash command as a single markdown file. The description frontmatter tells Claude when to suggest it:
---
description: Run the full pre-merge review checklist
---
Run the pre-merge checklist:
1. Run `npm test` and confirm all tests pass.
2. Run `npm run lint` and fix any errors.
3. Summarize what changed in plain language.
Save that as .claude/commands/review.md and the whole team gets a /review command. For richer reusable behavior, add a skill as a directory with a SKILL.md, for example .claude/skills/api-docs/SKILL.md with a description like “Generate API reference docs for any endpoint in src/api”. Skills load their body only when used, so they cost almost no context until they match the task. Our Claude Code mods tutorial covers the authoring format in more depth.
Subagents get their own directory too. A reviewer agent that only reads code can run in its own context window and return a summary, which keeps your main session’s context free for the actual work:
---
name: db-reviewer
description: Reviews database migration files for safety
tools: Read, Grep
model: haiku
---
You review database migrations. Flag destructive changes (DROP, ALTER COLUMN
type changes) and suggest rollback-safe alternatives.
Save that as .claude/agents/db-reviewer.md. The tools frontmatter restricts what the subagent can touch, and model: haiku keeps cheap review work off the expensive model. If you want to tune how much thinking each subagent does, see our guide to Claude Code subagent effort levels.
Step 7: Add path-scoped rules for noisy conventions
For conventions that only apply to part of the codebase, use .claude/rules/ with paths: frontmatter. A testing rule that should only load when Claude touches test files looks like this:
---
paths:
- "src/**/*.test.js"
---
Test files must use the project's test helpers from test/utils.js.
Do not mock database calls; use the test database instead.
Rules without a paths field load at launch with the same priority as .claude/CLAUDE.md, so prefer path scoping for anything file-specific. Glob patterns follow the usual rules: **/*.ts matches TypeScript files in any directory, src/**/* matches everything under src/. Before adding many rules, read the memory documentation’s section on organization, because every rule file adds to the launch-time context.
Step 8: Verify the whole project and commit it
Claude Code ships a doctor that validates the project configuration without starting a session or prompting for folder trust:
claude doctor
On the demo project I built for this tutorial, with the .mcp.json above and no token exported, the doctor reported exactly what you want a diagnostic to report:
Invalid settings
- /tmp/demo-project/.mcp.json › mcpServers.github: Missing environment variables: GITHUB_PERSONAL_ACCESS_TOKEN
Suggested fix: Set the following environment variables: GITHUB_PERSONAL_ACCESS_TOKEN
That is the tool reading your committed config, evaluating the ${VAR} references, and telling you the single action that fixes it. Export the token and re-run the doctor to confirm the warning clears. Then commit the whole bundle so the team shares it:
git add CLAUDE.md .claude .mcp.json
git commit -m "chore: add Claude Code project configuration"
Make sure CLAUDE.local.md stays out of the commit. A .gitignore entry for it is part of the project setup, not an afterthought.
Troubleshooting
1. claude doctor flags missing environment variables in .mcp.json
The real error looks like this:
mcpServers.github: Missing environment variables: GITHUB_PERSONAL_ACCESS_TOKEN
Suggested fix: Set the following environment variables: GITHUB_PERSONAL_ACCESS_TOKEN
Cause: your .mcp.json references ${GITHUB_PERSONAL_ACCESS_TOKEN} but the variable is not set in the shell where you launched the doctor or the session. Fix: export it in the same shell before launching Claude Code (export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_...), or add it to your shell profile. Do not “fix” this by pasting the real token into the committed .mcp.json; that leaks the secret to everyone with repository access.
2. Claude ignores the instructions in CLAUDE.md
This has three common causes, in order of likelihood. First, the file is too long: the official guidance targets under 200 lines per CLAUDE.md, and longer files measurably reduce adherence. Split procedures into skills or path-scoped rules. Second, the instructions are vague: “write clean code” is not verifiable, while “run npm test before committing” is. Third, two files contradict each other and Claude picks one arbitrarily. Diagnose with /context (confirm the file is in the Memory files list) and run /doctor prompt-audit in a session to get a report of outdated, conflicting, or broken instructions.
3. Project MCP servers sit in “Pending approval” forever
Project-scoped servers from .mcp.json do not connect until you approve them, and approval is gated by workspace trust: Claude Code will not even offer the prompt in a folder it does not trust. Cause: you opened an untrusted directory, or you approved the server in one worktree and expected it in another. Fix: open the project from its real path, answer the approval prompt when it appears, and check the state with claude mcp list. Servers you never approve stay paused and their tools never enter the context.
4. Settings edits do not take effect
Cause one: you edited .claude/settings.json while a session was running; settings load at session start, so restart the session. Cause two: the project source is excluded from --setting-sources, or you launched with --bare, which skips CLAUDE.md auto-discovery and hooks entirely. Cause three: a syntax error in the JSON, which claude doctor surfaces under Invalid settings. Fix the file, restart the session, and re-run the doctor until it reports no installation issues.
FAQ
The five questions in this article’s FAQ metadata cover the decisions teams revisit most: where CLAUDE.md should live, what to commit to git, how to inspect loaded memory with /context, how commands, skills, and subagents differ, and how configuration behaves in subdirectories.
Conclusion
A configured Claude Code project is a repository that onboards the AI the way a README onboards a developer: CLAUDE.md states the facts, .claude/settings.json sets the guardrails, .mcp.json wires up the tools, and commands, skills, and agents capture the workflows worth repeating. Build the bundle once, verify it with claude doctor, and commit it so every teammate and every future session starts from the same baseline. If your project needs custom tool integrations beyond off-the-shelf servers, the natural next step is our tutorial on building an MCP server in Python, and if your automation lives in n8n, see how to expose n8n workflows as MCP tools for Claude Code.
Frequently asked questions
Where should CLAUDE.md live, at the repo root or under .claude/?
Both locations work. Put it at ./CLAUDE.md when it should be the first thing the whole team sees, or at ./.claude/CLAUDE.md when it is an internal note for the AI that should not clutter the repo root. The two are never used at the same time in the same directory.
Should I commit .claude/ and .mcp.json to git?
Yes. CLAUDE.md, .claude/settings.json, .claude/commands, .claude/skills, .claude/agents, .claude/rules, and .mcp.json are all designed to be shared through version control. Keep secrets out of them: reference tokens as ${VAR_NAME} environment variables instead, and put personal notes in CLAUDE.local.md with a .gitignore entry.
How do I check which memory files Claude Code actually loaded?
Run /context inside a session and look at the Memory files list. It shows every CLAUDE.md, rules file, and auto-memory index that made it into the current session's context.
What is the difference between slash commands, skills, and subagents in a project?
Slash commands (.claude/commands/*.md) are single reusable prompts you invoke explicitly. Skills (.claude/skills/<name>/SKILL.md) are directories of instructions and resources that Claude uses automatically when the description matches the task. Subagents (.claude/agents/*.md) run in their own context window and return a summary, which keeps your main session clean.
Do project settings apply when I launch Claude Code from a subdirectory?
CLAUDE.md files are discovered by recursing up from your working directory, so repo-root instructions still load. The project's .claude/settings.json applies to the working directory it belongs to, so launch from the project root when you want the full project configuration.