What you will be able to do
- Place an instruction at the right CLAUDE.md scope and predict when AGENTS.md and path-scoped rules load
- Order the settings.json scopes by precedence and pick what only managed settings can enforce
- Tell a pinned model ID from an alias and trace which model a Claude Code session starts on
- Pin, promote and roll back a prompt version per environment
- Declare plugin dependencies with version ranges and pin a dependency exactly
Key concept
Pin versus pointer — A pin names one fixed thing, such as a snapshot model ID, an exact plugin version or a numbered prompt version, and it behaves the same until you change the configuration yourself. A pointer, such as an alias, a version range or an unscoped default, resolves to whatever is current, so its behaviour can change without any edit on your side.
1.CLAUDE.md scopes, AGENTS.md and path-scoped rules
CLAUDE.md files carry the standing instructions Claude reads at the start of every session, and where a file lives decides who it applies to. There are four scopes. An organization-wide file sits at a managed policy path that IT deploys. Your personal file at ~/.claude/CLAUDE.md follows you into every project. The project file, ./CLAUDE.md or ./.claude/CLAUDE.md, is committed so the whole team shares it. ./CLAUDE.local.md holds your own notes for one project and belongs in .gitignore.
| Scope | Location | Shared with |
|---|---|---|
| Managed policy | /Library/Application Support/ClaudeCode/CLAUDE.md (macOS), /etc/claude-code/CLAUDE.md (Linux and WSL) | All users in organization |
| User instructions | ~/.claude/CLAUDE.md | Just you (all projects) |
| Project instructions | ./CLAUDE.md or ./.claude/CLAUDE.md | Team members via source control |
| Local instructions | ./CLAUDE.local.md | Just you (current project) |
These scopes do not override one another. They all load and add up. That is why contradictions matter: when two instructions disagree, Claude may follow either one, so review the root file, nested CLAUDE.md files in subdirectories and .claude/rules/ together. @path imports such as @docs/git-instructions.md help you split up a long file. They do not save context, because imported files also load at launch. If a monorepo pulls in another team's instructions, claudeMdExcludes lists glob patterns for files to skip.
Not everything loads at launch. Files in the working directory and the directories above it load when the session starts. A subdirectory's instruction files and its .claude/rules/ files load later, when Claude reads a file there. In a monorepo, a frontend/CLAUDE.md therefore stays out of context until Claude works under frontend/.
Path-scoped rules are how you cut a long CLAUDE.md down. A file in .claude/rules/ with a paths list in its frontmatter loads only when Claude works on files that match those globs. Aim for under 200 lines per CLAUDE.md. Move the narrow rules out, such as the API conventions for src/api/, and keep the general conventions in the always-loaded file. Personal rules can go in ~/.claude/rules/.
---
paths:
- "src/api/**/*.ts"
---
# API Development Rules
- All API endpoints must include input validation
- Use the standard error response format
- Include OpenAPI documentation commentsAGENTS.md is the cross-tool instruction file, and by default it is a fallback, not an addition. Claude reads every AGENTS.md in your working directory and the directories above it only when there is no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md in those directories. If one of those exists, AGENTS.md is skipped. Your user CLAUDE.md, the managed CLAUDE.md and .claude/rules/ files do not count toward that test, so they load either way. There are two ways to get both files. You can put an @AGENTS.md line in CLAUDE.md, and Claude never reads the file twice. Or you can set the built-in agents-md plugin to claude-md-and-agents-md. On Windows, use the import rather than a symlink: a clone without symlink support checks out a one-line CLAUDE.md.
{
"pluginConfigs": {
"agents-md@builtin": {
"options": { "instructionFiles": "claude-md-and-agents-md" }
}
}
}Checkpoint 1 of 8· Check yourself
A repository has an AGENTS.md at its root and a CLAUDE.md in .claude/. Nobody has changed the instruction-file setting. What does Claude load from the project when a session starts in the root?
The default value is claude-md-or-agents-md. A .claude/CLAUDE.md in the working directory counts, so Claude reads the CLAUDE.md files and skips AGENTS.md.
“Count, so Claude reads them instead of AGENTS.md: a CLAUDE.md, .claude/CLAUDE.md, or CLAUDE.local.md in your working directory or any directory above it”Source: code.claude.com
Checkpoint 2 of 8· Exam question
A large monorepo has a root `CLAUDE.md` with general repository conventions and a `frontend/CLAUDE.md` with React-specific rules. An engineer launches Claude Code from inside `frontend/` and asks it to edit a file in `frontend/components/`. In what order does the content from these two files enter context, and when is `frontend/CLAUDE.md` loaded?
Correct answer: A — Both files load at launch because they sit above or at the working directory; content is ordered from the filesystem root down, so the root file appears in context before the `frontend/CLAUDE.md` file
- A. Correct. Claude Code walks up the directory tree from the working directory, loading CLAUDE.md files found there and above at launch; content is concatenated in order from the filesystem root down to the working directory, so the root file is read before `frontend/CLAUDE.md`, which sits at the launch directory itself.
- B. Incorrect. `frontend/CLAUDE.md` sits at the working directory itself, not in a subdirectory below it, so it loads at launch along with the root file rather than being deferred to on-demand loading.
- C. Incorrect. Ancestor CLAUDE.md files above the working directory are loaded in full at launch, not ignored; the root file is included alongside the working-directory file.
- D. Incorrect. The documented order runs from the filesystem root down to the working directory, meaning instructions closer to the launch point are read last, not first, so the root file precedes `frontend/CLAUDE.md` in context.
Sources1
2.settings.json scopes, precedence and managed settings
CLAUDE.md files add together, but settings resolve key by key. When the same key is set in more than one place, the highest scope wins. Keys you leave out keep the value from a lower scope. There are four files, plus a flag for a single session.
| Scope | File | Use it for |
|---|---|---|
| Managed | managed-settings.json, an MDM policy, or server-managed settings | Security policy and compliance requirements |
| Project local | .claude/settings.local.json | Personal overrides for one project, and testing before you share |
| Shared project | .claude/settings.json | Team permissions, hooks, plugins, and the environment variables the project needs |
| User | ~/.claude/settings.json | Personal preferences: theme, editor mode, default model, your own permission rules |
From strongest to weakest, the order is: managed settings, command-line arguments (including JSON passed with --settings), .claude/settings.local.json, .claude/settings.json, and ~/.claude/settings.json. The local file is yours. The first time Claude Code writes it, it adds the file to your global git excludes. It also writes your "Yes, and don't ask again" approvals there as allow rules.
Some keys are merged rather than replaced. permissions.allow combines across every scope, and an allow rule in your local file does not outrank an ask rule from a project or managed file.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)"
]
}
}Your own settings cannot override managed settings, and that is what makes them enforceable. Use managed settings for technical controls: permissions.deny to block tools, commands or paths, sandbox.enabled to require isolation, env for provider routing, forceLoginMethod and forceLoginOrgUUID for sign-in, and allowManagedPermissionRulesOnly to ignore everyone else's allow rules. Guidance about behaviour belongs in the managed CLAUDE.md. A rule like "never push to main" therefore needs both: an instruction in the managed CLAUDE.md and a deny rule in managed settings.
A few security keys work the other way. Any scope can make them stricter, so a project's disableClaudeAiConnectors: true stays on even when a managed source sets false.
Values in a committed project file do not all apply as soon as someone clones the repository. permissions.allow rules, extraKnownMarketplaces and most env values wait until each teammate trusts the folder. deny and ask rules apply straight away. Some values never apply from project or local settings. For example, permissions.defaultMode set to bypassPermissions has to come from user or managed settings.
Checkpoint 3 of 8· Put it in order
Arrange these settings sources from highest precedence to lowest
- 1.Shared project settings (.claude/settings.json)
- 2.User settings (~/.claude/settings.json)
- 3.Managed settings
- 4.Project local settings (.claude/settings.local.json)
- 5.Command-line arguments such as --settings
Managed settings sit at the top. JSON passed with --settings applies above every file you own. Local overrides shared project, and user settings come last.
“Claude Code applies it above your user, project, and local files and below managed settings.”Source: code.claude.com
3.Model IDs, aliases and the model a session starts on
A model ID is a pin. The model behind it stays the same for as long as the ID exists. From the Claude 4.6 generation onward, IDs have no date, such as claude-opus-4-6 or claude-sonnet-5, and each one is the canonical name of a single snapshot. Older models carry a date, as in claude-sonnet-4-5-20250929, and on the Claude API they also have short aliases such as claude-sonnet-4-5. Those aliases point to the newest dated snapshot for that minor version. Each ID has its own deprecation and retirement schedule. A pin fixes the weights, but the serving infrastructure around them can still change. If a pinned ID starts behaving differently, an infrastructure update is the first thing to suspect.
The ID format depends on the provider, so a pin copied from one platform fails on another. Dateless IDs are claude-sonnet-4-6 on the Claude API and Google Cloud, and anthropic.claude-sonnet-4-6 on Amazon Bedrock. Dated models differ more: claude-sonnet-4-5-20250929 on the Claude API, anthropic.claude-sonnet-4-5-20250929-v1:0 on Bedrock, and claude-haiku-4-5@20251001 on Google Cloud, where the date follows an @.
Claude Code adds its own family aliases, and these drift by design. opus and sonnet resolve to the latest model in their family, and what that is depends on your provider. opus resolves to Opus 5.5 on the Anthropic API but to Opus 4.6 on Microsoft Foundry. default is not an alias. It clears any override. Use an alias on a developer machine where newer is better. Use a full ID wherever two environments must run the same model.
To keep an alias but freeze what it points to, set the ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL or ANTHROPIC_DEFAULT_FABLE_MODEL variable to a full ID. Under an organization's availableModels list, these variables cannot redirect an allowed alias to a model outside the list.
| Alias | Behavior |
|---|---|
| opus | Uses the latest Opus model for complex reasoning tasks |
| sonnet | Uses the latest Sonnet model for daily coding tasks |
| opusplan | Uses opus during plan mode, then switches to sonnet for execution |
| default | Clears any model override and reverts to the runtime default for your account |
The model a session starts on is chosen in a fixed order. The --model flag comes first, then the ANTHROPIC_MODEL environment variable, then a model value in any settings file (including the one /model saves), then an organization default. A model in project or managed settings applies again at every launch and outranks your saved /model choice. The startup header names the file it came from. A resumed session usually keeps the model it was using. If the requested model is outside the organization's availableModels, Claude Code swaps it at startup and prints a warning.
The default choice depends on what is recorded. When no organization default model is set, Default can resolve to the model recorded from your earlier choice. If model restrictions exclude that recorded model, or your account cannot use it, Default resolves as if nothing were recorded. A /model switch takes effect immediately in the running session, so changing models never needs a restart.
claude --settings '{"model": "claude-opus-5-5"}'Checkpoint 4 of 8· Match them up
Match each model reference to how it behaves over time
Tap a term, then the definition that fits it.
Dateless 4.6-and-later IDs and dated IDs are both pins. The older API aliases and the Claude Code family aliases move when a newer model ships.
“An alias such as claude-sonnet-4-5 is a convenience pointer that resolves to the most recent dated snapshot for that minor version.”Source: platform.claude.com
Checkpoint 5 of 8· Exam question
An engineer edits `.claude/settings.json` mid-session to add a new entry under `permissions.allow` for a Bash pattern the team just approved, then separately edits the `model` field in the same file to pin a different Claude version. Without restarting Claude Code, what should the engineer expect?
Correct answer: A — The new permission entry takes effect immediately through hot reloading, but the model change requires a restart before it applies
- A. Correct. Claude Code watches settings files and hot-reloads most keys, including `permissions`, `hooks`, and `env`, without a restart, but `model` and `outputStyle` are documented exceptions that require a restart before the new value is used.
- B. Incorrect. Not every key hot-reloads; `model` is explicitly excluded from live reloading and only takes effect after a restart, so this overstates what applies immediately.
- C. Incorrect. Claude Code does actively watch settings files during a session and hot-reloads most keys, so treating the file as read-once at startup is incorrect for keys like `permissions`.
- D. Incorrect. `model` is one of the keys that does not hot-reload, and no manual `/config` step is documented as a workaround for the permission entry, which reloads on its own.
Checkpoint 6 of 8· Exam question
An enterprise admin sets `availableModels: ["sonnet", "claude-opus-4-6"]` in managed settings to restrict which models developers can select, but does not set `enforceAvailableModels`. A developer who has never touched `/model` opens a fresh session. Which model does that session start on, and why?
Correct answer: A — The account-type default model, because `availableModels` on its own does not constrain the Default option, and enforcing the allowlist on Default requires the separate `enforceAvailableModels` setting
- A. Correct. The Default option in the model picker, and thus a session with no other model selection, is not affected by `availableModels` unless `enforceAvailableModels` is also set; on its own, `availableModels` leaves Default resolving to the account-type or organization default regardless of what the allowlist contains.
- B. Incorrect. Entries in `availableModels` restrict which models can be actively selected; they do not become the automatic starting model for a session that has not selected anything, since Default resolution is a separate mechanism gated by `enforceAvailableModels`.
- C. Incorrect. There is no rule that an unconfigured session automatically starts on the alias entry within an allowlist; Default resolution depends on the account-type default and the `enforceAvailableModels` setting, not on which allowlist entries exist.
- D. Incorrect. `availableModels` without `enforceAvailableModels` is a valid and documented configuration; it restricts named selections while leaving Default to resolve normally, and it does not cause a startup failure.
4.Prompt versions: pin, promote, roll back
A system prompt affects output as much as the model does, so manage it the same way: keep immutable versions, pin each environment to one version, and make every change an explicit move between versions. Anthropic follows this rule for models. A model ID never changes in place, and an update ships under a new ID. Your prompts need the same guarantee. Otherwise you cannot tell whether a regression came from a model change or a prompt change.
Managed Agents is an Anthropic API service that stores an agent, including its system prompt, on the server. agents.update is the call that changes the agent, and sessions.create is the call that starts a session against it. Each agents.update creates a new immutable version, and sessions.create can pin a session to a specific version. Promoting a prompt becomes a change to one version number in config, not a code diff that needs a rebuild.
What you pass to sessions.create decides whether you hold a pointer or a pin. A plain agent ID string gets whatever the latest version is. An object of the form {"type": "agent", "id": ..., "version": ...} pins one exact version. Production callers that pass the bare ID pick up a new prompt on their very next session.
Nothing gates agents.update. There is no built-in approval workflow, and any key in the workspace can call it. The review step therefore moves to the pin: production callers always pass an explicit version, and that version number in config goes through your normal review. Anyone can create version 2, 3 or 10, and those versions sit unused until a reviewed change promotes one.
The safe workflow follows a fixed sequence. Create version 1 and score it against a labelled test set. Ship version 2 and score it the same way. If it regresses, point callers back at version 1. Rolling back needs no deploy, because version 1 still exists unchanged.
Checkpoint 7 of 8· Put it in order
Put the prompt release cycle in order
- 1.Ship a version 2 prompt
- 2.Evaluate that version against a labelled test set
- 3.Roll back by pinning sessions to version 1
- 4.Create the agent at version 1
- 5.Detect a regression in the new version
Each version is scored before it is trusted. Rollback works because older versions are immutable and you can pin to them again.
“create v1, evaluate against a labelled test set, ship v2, detect a regression, roll back by pinning sessions to version 1”Source: platform.claude.com
5.Plugin dependency ranges and exact pins
A plugin is a package of Claude Code extensions that you install from a marketplace (see [Claude Code plugins](lesson:2.5)). A plugin can depend on other plugins, listed in the dependencies array of its plugin.json. Each entry is either a bare name or an object with a name, a semantic-version range in version, and an optional marketplace. Claude Code installs the highest git tag that satisfies the range, so the dependency's maintainer must tag releases. A plugin with its own repository is tagged by its author. A plugin referenced by a relative path is tagged by the marketplace maintainer. claude plugin tag --push creates the tag after it validates the plugin, and it refuses if the tag already exists.
With no satisfying tag, the outcome depends on where the dependency lives. A plugin with its own repository fails to install with a message that no git tag satisfies the range. A plugin referenced by a relative path installs the marketplace's current copy instead, and the range is checked when the plugin loads. If that copy falls outside the range, the dependent plugin stays disabled and claude plugin list shows the required range next to the installed version.
Checkpoint 8 of 8· Fill the gap
Which key declares the plugins deploy-kit depends on?
{
"name": "deploy-kit",
"version": "3.1.0",
" ? ": [
"audit-logger",
{ "name": "secrets-vault", "version": "~2.1.0" }
]
}The dependencies array takes bare names or objects with a name and a version range. Here ~2.1.0 allows 2.1.x patch releases only.
How wide you make a range decides how well it holds up when two plugins need the same dependency. Ranges that overlap resolve to a single install. Ranges that cannot overlap make the second install fail, and the first plugin keeps working. An exact pin is a version of =2.1.0 in the dependency object, for example { "name": "secrets-vault", "version": "=2.1.0" }. It also stops auto-update from moving the dependency for as long as the pinning plugin is installed. Use an exact pin when you have tested one specific build. Use a caret or tilde range when you want fixes to arrive on their own.
| Plugin A requires | Plugin B requires | Result |
|---|---|---|
| ^2.0 | >=2.1 | One install at the highest 2.x tag at or above 2.1.0; both load |
| ~2.1 | ~3.0 | Installing plugin B fails with a conflicting version requirements message |
| =2.1.0 | none | Stays at 2.1.0; auto-update skips newer versions while plugin A is installed |
Sources6
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.An AGENTS.md always loads alongside the project CLAUDE.md.Why is that wrong?
By default, AGENTS.md loads only when there is no CLAUDE.md or CLAUDE.local.md in the working directory or above it. To get both, use an @AGENTS.md import or the claude-md-and-agents-md setting.
Covered in CLAUDE.md scopes, AGENTS.md and path-scoped rules
2.Setting model in managed settings stops users from choosing another model.Why is that wrong?
A managed model only sets the starting model, and /model can still change it. The setting that enforces a restriction is availableModels.
Covered in settings.json scopes, precedence and managed settings
3.A dateless model ID like claude-sonnet-4-6 is an evergreen pointer that upgrades automatically.Why is that wrong?
From the 4.6 generation on, the dateless ID is the snapshot itself. Anthropic ships updates under new IDs.
Covered in Model IDs, aliases and the model a session starts on
4.Passing the agent ID to sessions.create keeps a session on the version you tested.Why is that wrong?
A plain agent ID string resolves to the latest version, so a new agents.update changes production on the next session. Only the object with an explicit version pins.
Covered in Prompt versions: pin, promote, roll back
5.A dependency version range resolves against the version string in the dependency's plugin.json.Why is that wrong?
Ranges resolve against git tags, so a release that is never tagged cannot be selected. For a plugin referenced by a relative path, the marketplace's current copy is installed and the range is checked at load.
Covered in Plugin dependency ranges and exact pins
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.https://code.claude.com/docs/en/memoryOfficial docs
“Move instructions that matter for only part of the codebase into path-scoped rules, which load only when Claude works with matching files.”
↩︎ CLAUDE.md scopes, AGENTS.md and path-scoped rules“if two instructions contradict each other, Claude may pick one arbitrarily.”
↩︎ CLAUDE.md scopes, AGENTS.md and path-scoped rules“Personal project-specific preferences; add to .gitignore”
↩︎ CLAUDE.md scopes, AGENTS.md and path-scoped rules“every AGENTS.md and .claude/AGENTS.md in your working directory and the directories above it”
↩︎ CLAUDE.md scopes, AGENTS.md and path-scoped rules“still load when Claude reads a file there”
↩︎ CLAUDE.md scopes, AGENTS.md and path-scoped rules“Block specific tools, commands, or file paths | Managed settings: permissions.deny”
↩︎ settings.json scopes, precedence and managed settings“Your CLAUDE.md files, or your AGENTS.md files when you have no CLAUDE.md or CLAUDE.local.md in your working directory or above it”
↩︎ Exam trap 1“Count, so Claude reads them instead of AGENTS.md: a CLAUDE.md, .claude/CLAUDE.md, or CLAUDE.local.md in your working directory or any directory above it”
↩︎ Checkpoint - 2.https://code.claude.com/docs/en/settingsOfficial docs
“Everyone your organization deploys it to; nothing you set overrides it, apart from a few security-sensitive exceptions”
↩︎ settings.json scopes, precedence and managed settings“.claude/settings.local.json”
↩︎ settings.json scopes, precedence and managed settings“Claude Code merges permissions.allow across scopes, unless your organization sets allowManagedPermissionRulesOnly.”
↩︎ settings.json scopes, precedence and managed settings“For a few keys Claude Code honors the restrictive value from any file, so a project true for disableClaudeAiConnectors stays on”
↩︎ settings.json scopes, precedence and managed settings“deny and ask rules apply right away.”
↩︎ settings.json scopes, precedence and managed settings“use /model to switch mid-session”
↩︎ Model IDs, aliases and the model a session starts on“A managed model sets the model each session starts with, and you can still switch with /model; the lock is availableModels”
↩︎ Exam trap 2“Claude Code applies it above your user, project, and local files and below managed settings.”
↩︎ Checkpoint - 3.
“When you use a model ID in an API request, the underlying model remains constant for the lifetime of that ID.”
↩︎ Model IDs, aliases and the model a session starts on“If you notice unexpected behavioral differences on a previously stable model ID, an infrastructure update is the most likely cause.”
↩︎ Model IDs, aliases and the model a session starts on“anthropic.claude-sonnet-4-5-20250929-v1:0”
↩︎ Model IDs, aliases and the model a session starts on“claude-haiku-4-5@20251001”
↩︎ Model IDs, aliases and the model a session starts on“When an updated version is available, it ships under a new model ID.”
↩︎ Prompt versions: pin, promote, roll back“It maps to a single, fixed model snapshot.”
↩︎ Key concept“Anthropic does not update the weights or configuration of an existing model ID.”
↩︎ Exam trap 3“A 4.6-generation ID such as claude-sonnet-4-6 is not an alias. It is the snapshot.”
↩︎ Prediction“An alias such as claude-sonnet-4-5 is a convenience pointer that resolves to the most recent dated snapshot for that minor version.”
↩︎ Checkpoint - 4.https://code.claude.com/docs/en/model-configOfficial docs
“When project or managed settings set the model, the startup header names the file.”
↩︎ Model IDs, aliases and the model a session starts on“A session you resume with claude --resume or --continue usually keeps the model it was using rather than your current default.”
↩︎ Model IDs, aliases and the model a session starts on“pin it with ANTHROPIC_DEFAULT_FABLE_MODEL”
↩︎ Model IDs, aliases and the model a session starts on“the Default option resolves as if nothing were recorded”
↩︎ Model IDs, aliases and the model a session starts on - 5.https://platform.claude.com/cookbook/managed-agents-cma-prompt-versioning-and-rollbackSecondary source
“Every agents.update produces a new immutable version, and sessions choose which version to use by ID.”
↩︎ Prompt versions: pin, promote, roll back“If something goes wrong, pointing callers back at the old version is all it takes to roll back.”
↩︎ Prompt versions: pin, promote, roll back“Passing a plain string (agent=AGENT_ID) gets you whatever the latest version is.”
↩︎ Prompt versions: pin, promote, roll back“There's no built-in approval workflow on agents.update.”
↩︎ Prompt versions: pin, promote, roll back“Passing a plain string (agent=AGENT_ID) gets you whatever the latest version is.”
↩︎ Exam trap 4“create v1, evaluate against a labelled test set, ship v2, detect a regression, roll back by pinning sessions to version 1”
↩︎ Checkpoint - 6.https://code.claude.com/docs/en/plugins/dependenciesOfficial docs
“Auto-update skips newer versions while plugin A is installed.”
↩︎ Plugin dependency ranges and exact pins“Refuses if the tag already exists”
↩︎ Plugin dependency ranges and exact pins“the constraint is checked when the plugin loads”
↩︎ Plugin dependency ranges and exact pins“The dependency installs at the highest git tag that satisfies this range”
↩︎ Exam trap 5