Team collaboration with shared Claude Code config
PLTeam 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.jsonpermission policy and a.mcp.jsonwith no secrets in it, both ready to commit. - Team workflows as skills that every clone gets as the same
/namecommand. - 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.
What to commit and what to keep personal
Section titled “What to commit and what to keep personal”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.
| File | Commit it? | What it holds |
|---|---|---|
CLAUDE.md (or AGENTS.md) | Yes | Build and test commands, conventions, and things Claude gets wrong without being told |
.claude/rules/*.md | Yes | Instructions for one part of the tree, loaded only when Claude reads a matching path |
CLAUDE.local.md | No, add it to .gitignore | Your sandbox URL, test account, and local port; in a repository that keeps only AGENTS.md, start it with @AGENTS.md |
.claude/settings.json | Yes | Permission rules, hooks, and project plugin marketplaces |
.claude/settings.local.json | No | Your personal allow rules; Claude Code adds it to your global git excludes when it first writes the file |
.mcp.json | Yes | MCP servers, with ${VAR} references instead of credentials |
.claude/skills/<name>/SKILL.md | Yes | Team workflows invoked as /<name> |
.claude/agents/*.md | Yes | Subagents with their own prompt, tools, and model |
managed-settings.json | Not in the app repository | The 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.
-
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/withpathsfrontmatter. The memory system page shows a file that earns every line. -
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
ToolorTool(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, sosh -c 'npm run deploy'slips past it: treat it as a typo-catcher, and keep deploy credentials out of developer environments entirely. -
Commit
.mcp.jsonwith variables, not secrets. Claude Code expands${VAR}and${VAR:-default}incommand,args,env,url, andheaders:.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.mdor the README. Server choice and scopes are covered in MCP setup for Claude Code. -
Add the team’s repeatable workflows as skills. A skill at
.claude/skills/<name>/SKILL.mdbecomes/<name>for everyone who clones the repository. Existing.claude/commands/*.mdfiles keep working, but new workflows belong in skills. The standup skill below is a complete example. -
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-leadsReplace
@acme/platform-leadsand@acme/securitywith your own teams. The/.github/line covers the CI gate below, andCODEOWNERSonly blocks a merge once branch protection or a ruleset requires code owner review. -
Ignore the personal files. Add
CLAUDE.local.mdto.gitignore. Claude Code excludes.claude/settings.local.jsonfor you only when it creates the file; if you created it by hand, ignore it too.
Share a team workflow as a skill
Section titled “Share a team workflow as a skill”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.
---name: standupdescription: Write my daily standup update from real git activity.disable-model-invocation: trueallowed-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 mostlikely 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.
How do you know the shared config works?
Section titled “How do you know the shared config works?”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:
name: claude-configon: pull_request: paths: ['CLAUDE.md', 'AGENTS.md', '.claude/**', '.mcp.json']permissions: contents: readjobs: 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 doneEach 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:
- In the terminal, run
claude mcp list. Approved servers from.mcp.jsonare health-checked; a server shown as pending approval has not been approved in an interactive session yet and is not connected. - Start
claudein the repository and accept the workspace trust dialog. - 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. - Run
/contextto see how much of the context windowCLAUDE.md, skills, and MCP tools take before any work starts. - 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:
- Install Claude Code with the native installer or your team’s package manager, as described in installing Claude Code, and sign in with
/logininside a session. - Export the environment variables that
.mcp.jsonreferences in the shell profile, never in a committed file. - Clone the repository, start
claudein it, accept the trust dialog, and approve the project MCP servers. - Run the smoke test above.
- Keep the default model. The rule the team follows: start on Claude Code’s default, raise effort with
/effortbefore changing model, and switch model only when your own evals say so. Current models and prices are on the models hub;/usageshows 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.
When shared Claude Code config breaks
Section titled “When shared Claude Code config breaks”| Symptom | Likely cause | Recovery |
|---|---|---|
| Project MCP servers never connect for a new teammate | Nobody approved them in an interactive session, or the teammate declined | Start 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 another | A ${VAR} is unset in the shell that started claude, or the server command (npx, Docker) is missing | Run 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 prompts | The teammate has not accepted the workspace trust dialog, so committed allow rules are not active yet | Restart in the repository, accept the dialog, and check /permissions |
Someone sets "defaultMode": "auto" in .claude/settings.json and nothing changes | Project settings cannot set auto or bypassPermissions as the default mode | Put the mode in user settings, or enforce it for everyone in managed settings |
CLAUDE.md conflicts on every pull request and keeps growing | One file holds everything, including personal notes | Move 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 teammate | They created CLAUDE.local.md, which switches Claude Code to CLAUDE.md files | Import 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 machine | Too many prompts, so they bypassed the policy | Extend 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 prompts | That 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 settings | Leave 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 covers | claude -p never shows the trust dialog, so the committed permissions.allow rules are not used in a folder nobody trusted | Pass 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 expect | Hooks 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”- Enterprise integration: enforce a floor across every repository with managed settings.
- Hooks automation: turn “always run the tests” from a
CLAUDE.mdrequest into a hook that runs every time, and shared hooks governance for reviewing them across teams. - Custom commands and skills: build and test the team’s command library.
- Team collaboration across Cursor, Claude Code and Codex: the cross-tool view of shared rules for a mixed team.
- Claude Tag: let the team delegate work from Slack once these gates are in place.