Skip to content

Team collaboration in Claude Code means committing the agent’s configuration to the repository: CLAUDE.md and .claude/rules/ for instructions, .claude/settings.json for permission rules and hooks, .mcp.json for MCP servers, and .claude/skills/ for shared workflows. A fresh clone then behaves the same for everyone, and code review guards every change to it.

This page is for the tech lead who owns a repository’s Claude Code setup, and for the developers who work in it. One engineer gets reliable results; the next copies a config snippet from chat, the MCP servers never connect, the agent asks for approval on every npm test, and they decide the tool does not work. The difference was never the model. Nothing about the working setup was shared, reviewed, or tested.

What a shared Claude Code setup gives your team

Section titled “What a shared Claude Code setup gives your team”
  • A clear split between what the repository commits and what each person keeps local.
  • A .claude/settings.json permission policy and a .mcp.json with no secrets in it, both ready to commit.
  • Team workflows as skills that every clone gets as the same /name command.
  • A CI job and a five-minute smoke test that prove the shared config works, without anyone rereading the files.
  • A recovery table for the ways shared config breaks.

Claude Code merges settings from five levels: managed, command line, .claude/settings.local.json, .claude/settings.json, and ~/.claude/settings.json, highest first. Array keys such as permissions.allow are concatenated across levels. That merge is what lets a team commit a shared floor while each person adds exceptions on top. The full precedence rules are on the Claude Code configuration page.

FileCommit it?What it holds
CLAUDE.md (or AGENTS.md)YesBuild and test commands, conventions, and things Claude gets wrong without being told
.claude/rules/*.mdYesInstructions for one part of the tree, loaded only when Claude reads a matching path
CLAUDE.local.mdNo, add it to .gitignoreYour sandbox URL, test account, and local port; in a repository that keeps only AGENTS.md, start it with @AGENTS.md
.claude/settings.jsonYesPermission rules, hooks, and project plugin marketplaces
.claude/settings.local.jsonNoYour personal allow rules; Claude Code adds it to your global git excludes when it first writes the file
.mcp.jsonYesMCP servers, with ${VAR} references instead of credentials
.claude/skills/<name>/SKILL.mdYesTeam workflows invoked as /<name>
.claude/agents/*.mdYesSubagents with their own prompt, tools, and model
managed-settings.jsonNot in the app repositoryThe organisation’s policy that nobody can override; see enterprise integration

Two limits shape what a repository can do. First, a project file cannot choose the starting permission mode for the team: defaultMode set to auto or bypassPermissions is ignored in .claude/settings.json and must live in user or managed settings (Claude Code docs, checked against v2.1.283). The part the repository controls is the rules. Second, committed allow rules and the plugin marketplaces the file declares wait for each teammate to accept the workspace trust dialog, while deny and ask rules apply at once, because they only restrict. From v2.1.283 (both release channels on 2026-10-12), interactive sessions on supported models start in auto mode, in which a classifier reviews actions instead of prompting you, unless a settings file sets disableAutoMode. A matching ask rule still prompts in auto mode, so the committed rules keep their meaning in every mode.

Set up the shared harness in one pull request

Section titled “Set up the shared harness in one pull request”

Ship the whole harness as one reviewed pull request, so the team adopts a tested set rather than five files that arrive at different times.

  1. Write a short CLAUDE.md. Anthropic’s target is under 200 lines per file. Keep only what Claude would otherwise get wrong: the exact test and lint commands, directory boundaries, and banned patterns. Move rules for one area, such as migrations or React components, into .claude/rules/ with paths frontmatter. The memory system page shows a file that earns every line.

  2. Commit a permission policy. Allow the commands the project runs every day, ask before anything that leaves the machine, and deny secrets:

    .claude/settings.json
    {
    "$schema": "https://json.schemastore.org/claude-code-settings.json",
    "permissions": {
    "allow": [
    "Bash(npm run lint)",
    "Bash(npm run test *)",
    "Bash(npx tsc --noEmit)",
    "Bash(git status)",
    "Bash(git diff *)",
    "Bash(git log *)"
    ],
    "ask": [
    "Bash(git push *)",
    "Bash(npm install *)",
    "Bash(npm publish *)"
    ],
    "deny": [
    "Read(./.env)",
    "Read(./.env.*)",
    "Read(./secrets/**)",
    "Bash(npm run deploy *)"
    ]
    }
    }

    Rules are Tool or Tool(specifier). Claude Code checks deny, then ask, then allow, and a more specific allow rule cannot carve an exception out of a broader deny rule. A Bash deny rule matches the command text Claude writes, so sh -c 'npm run deploy' slips past it: treat it as a typo-catcher, and keep deploy credentials out of developer environments entirely.

  3. Commit .mcp.json with variables, not secrets. Claude Code expands ${VAR} and ${VAR:-default} in command, args, env, url, and headers:

    .mcp.json
    {
    "mcpServers": {
    "github": {
    "type": "http",
    "url": "https://api.githubcopilot.com/mcp/",
    "headers": { "Authorization": "Bearer ${GITHUB_PAT}" }
    },
    "sentry": { "type": "http", "url": "https://mcp.sentry.dev/mcp" },
    "linear": { "type": "http", "url": "https://mcp.linear.app/mcp" }
    }
    }

    Sentry and Linear authenticate with OAuth on first use, so they need no variable at all. List every variable a server needs in CLAUDE.md or the README. Server choice and scopes are covered in MCP setup for Claude Code.

  4. Add the team’s repeatable workflows as skills. A skill at .claude/skills/<name>/SKILL.md becomes /<name> for everyone who clones the repository. Existing .claude/commands/*.md files keep working, but new workflows belong in skills. The standup skill below is a complete example.

  5. Protect the files with CODEOWNERS. These files steer what an agent may run on every teammate’s machine, so a change to them needs the same review as CI config:

    .github/CODEOWNERS
    CLAUDE.md @acme/platform-leads
    /.claude/ @acme/platform-leads
    /.mcp.json @acme/platform-leads @acme/security
    /.github/ @acme/platform-leads

    Replace @acme/platform-leads and @acme/security with your own teams. The /.github/ line covers the CI gate below, and CODEOWNERS only blocks a merge once branch protection or a ruleset requires code owner review.

  6. Ignore the personal files. Add CLAUDE.local.md to .gitignore. Claude Code excludes .claude/settings.local.json for you only when it creates the file; if you created it by hand, ignore it too.

Skills turn the rituals a team repeats into one command with one behaviour. This one produces a standup update from git history instead of memory. disable-model-invocation: true means Claude runs it only when someone types /standup, and allowed-tools pre-approves the read-only git commands for that turn only.

.claude/skills/standup/SKILL.md
---
name: standup
description: Write my daily standup update from real git activity.
disable-model-invocation: true
allowed-tools: Bash(git log *) Bash(git branch *) Bash(git status)
---
Write my standup from real signals, not guesses.
Yesterday: run git log --author="$(git config user.name)" --since="1 day ago"
--oneline --all and summarise what changed in 3 to 5 bullets, grouped by feature.
Today: read the current branch name and git status, and list the 2 or 3 most
likely next tasks.
Blockers: name any failing check you saw in this session, or say "none".
Keep the whole update under 120 words. Do not invent work that is not in git.

Arguments, invocation control, and the context: fork option that hands heavy work to a subagent are covered on the custom commands and skills page. For review, start from the bundled /code-review skill and put your team’s rules in a skill of your own, as review automation shows, rather than writing a reviewer from scratch.

To share skills, hooks, and MCP servers across several repositories, package them as a plugin in a private marketplace. Register the marketplace in the repository with claude plugin marketplace add acme/acme-plugins --scope project, which writes it to .claude/settings.json, and commit that file. Each teammate sees the marketplace only after they trust the folder. The build-and-host steps are on running a team plugin marketplace.

In a script or a CI image, install without opening /plugin. claude plugin install PLUGIN --marketplace acme/acme-plugins installs the plugin from that marketplace and adds the marketplace to your user settings first when it is missing (v2.1.292, latest channel only on 2026-10-12). --config KEY=VALUE sets an option the plugin’s manifest declares and can repeat; the SERVER.KEY=VALUE form sets a setting that a bundled .mcpb MCP server declares and needs v2.1.285 or later (both channels on 2026-10-12). claude plugin configure PLUGIN shows a plugin’s options and which are still unset, and its --values-stdin flag saves values from a JSON object on standard input (v2.1.285). These come from claude plugin install --help and claude plugin configure --help in 2.1.296, checked 2026-10-12. Replace PLUGIN with the plugin’s name. Pipe a credential to --values-stdin from your secret store instead of typing it after --config, so it stays out of shell history and logs.

A shared config is only useful if it loads on every machine. Prove that with two checks that nobody has to read line by line.

A CI gate on every change to the harness. This job runs without secrets and without starting Claude Code, so it is safe on pull requests from any branch:

.github/workflows/claude-config.yml
name: claude-config
on:
pull_request:
paths: ['CLAUDE.md', 'AGENTS.md', '.claude/**', '.mcp.json']
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Settings and MCP config parse as JSON
run: for f in .claude/settings.json .mcp.json; do [ ! -f "$f" ] || jq empty "$f"; done
- name: No literal credentials in .mcp.json
run: |
if [ -f .mcp.json ] && grep -nE '(ghp_|github_pat_|sk-|xox[abp]-)[A-Za-z0-9_-]{10,}' .mcp.json; then
echo "::error::.mcp.json contains a literal token. Use \${VAR} instead."
exit 1
fi
- name: Secrets stay denied
run: |
[ ! -f .claude/settings.json ] || jq -e '.permissions.deny | index("Read(./.env)")' .claude/settings.json
- name: CLAUDE.md and AGENTS.md stay under 200 lines
run: |
for f in CLAUDE.md AGENTS.md; do
[ ! -f "$f" ] || test "$(wc -l < "$f")" -le 200
done

Each step fails on a real regression: a stray comma that breaks settings for everyone, a pasted token, a pull request that drops the .env deny rule, or a CLAUDE.md or AGENTS.md that grows until Claude ignores half of it. Each check skips a file the repository does not have, so an AGENTS.md-only repository or one without .mcp.json passes. On the pull_request trigger GitHub runs this workflow file from the pull request’s merge ref, so a pull request can edit or delete the check it is judged by. The gate holds only with /.github/ in CODEOWNERS and required code owner review, as in step 5.

A smoke test for each teammate’s machine. A new teammate, or anyone whose setup misbehaves, runs this once after cloning:

  1. In the terminal, run claude mcp list. Approved servers from .mcp.json are health-checked; a server shown as pending approval has not been approved in an interactive session yet and is not connected.
  2. Start claude in the repository and accept the workspace trust dialog.
  3. Run /permissions. Each rule is listed with the settings file it came from, so you can confirm the team rules loaded from .claude/settings.json.
  4. Run /context to see how much of the context window CLAUDE.md, skills, and MCP tools take before any work starts.
  5. Paste the prompt below and compare the answer with the files.

If the answer names the wrong test command, the fix belongs in CLAUDE.md, not in a follow-up message. The tech lead who owns CODEOWNERS signs off on harness changes. The CI gate and the smoke test are the evidence they sign against.

Keep CLAUDE.md current as the codebase moves

Section titled “Keep CLAUDE.md current as the codebase moves”

A CLAUDE.md that describes last quarter’s conventions is worse than none, because Claude trusts it. Run a short review after each sprint, and treat the output as a pull request like any other.

Onboard a new teammate onto the shared setup

Section titled “Onboard a new teammate onto the shared setup”

With the harness in the repository, onboarding is short and the same for everyone:

  1. Install Claude Code with the native installer or your team’s package manager, as described in installing Claude Code, and sign in with /login inside a session.
  2. Export the environment variables that .mcp.json references in the shell profile, never in a committed file.
  3. Clone the repository, start claude in it, accept the trust dialog, and approve the project MCP servers.
  4. Run the smoke test above.
  5. Keep the default model. The rule the team follows: start on Claude Code’s default, raise effort with /effort before changing model, and switch model only when your own evals say so. Current models and prices are on the models hub; /usage shows your own spend and limits.

Agree on one release channel for the team. Claude Code ships a latest channel and a stable channel that trails it by about a week (v2.1.296 and v2.1.287 on 2026-10-12), so features from v2.1.288 on can differ between them. Set autoUpdatesChannel once, ideally in managed settings, so two teammates never debug two different versions. For a fully identical toolchain, run Claude Code in the team dev container.

SymptomLikely causeRecovery
Project MCP servers never connect for a new teammateNobody approved them in an interactive session, or the teammate declinedStart claude in the repository and approve; claude mcp reset-project-choices clears earlier decisions so they are asked again
.mcp.json works on one machine and not anotherA ${VAR} is unset in the shell that started claude, or the server command (npx, Docker) is missingRun the server’s command in a plain terminal, export the variable, then restart; list the required variables in CLAUDE.md
Team allow rules seem ignored and every test run promptsThe teammate has not accepted the workspace trust dialog, so committed allow rules are not active yetRestart in the repository, accept the dialog, and check /permissions
Someone sets "defaultMode": "auto" in .claude/settings.json and nothing changesProject settings cannot set auto or bypassPermissions as the default modePut the mode in user settings, or enforce it for everyone in managed settings
CLAUDE.md conflicts on every pull request and keeps growingOne file holds everything, including personal notesMove area-specific rules into .claude/rules/ with paths, personal notes into CLAUDE.local.md, and resolve conflicts by section
Team AGENTS.md rules vanish for one teammateThey created CLAUDE.local.md, which switches Claude Code to CLAUDE.md filesImport the core with @AGENTS.md at the top of CLAUDE.local.md, or keep personal notes in ~/.claude/CLAUDE.md
A teammate runs with --dangerously-skip-permissions on a shared machineToo many prompts, so they bypassed the policyExtend the allow list instead; set disableBypassPermissionsMode: "disable" in managed settings, and use bypass only in a disposable, network-restricted container
You chose “Yes, and don’t ask again”, yet the same command still promptsThat choice saved an allow rule to your local file, and a local allow rule does not outrank an ask rule from the project or managed settingsLeave the prompt if the ask rule is deliberate; otherwise change the project rule in a reviewed pull request
A CI job running claude -p fails on commands the team allow list coversclaude -p never shows the trust dialog, so the committed permissions.allow rules are not used in a folder nobody trustedPass the commands with --allowedTools in the workflow, and keep the job’s credentials read-only; see Claude Code in CI/CD
An external repository’s .claude/ runs hooks, connects MCP servers or pre-approves tools you did not expectHooks and the env block run once you trust the folder; in claude -p they run without any trust step, and every .mcp.json server connects without asking; a skill’s allowed-tools is never gated by trust (Claude Code permissions docs, v2.1.283)Read .claude/settings.json, .claude/skills/ and .mcp.json before you trust or script a repository you did not write; see hooks automation

For errors outside shared config, such as authentication, network, or install problems, see Claude Code troubleshooting.

Where to go next with a shared Claude Code setup

Section titled “Where to go next with a shared Claude Code setup”