CertSafari
    Anthropic Claude Certified Developer – Foundations (CCDV-F)· Lessons

    Domain 2 · Lesson 9/25

    Configuration management for Claude: CLAUDE.md, settings, model and prompt pinning

    Configuration Management

    19 min read
    5.52% of exam
    6 sources
    Published 12 Oct 2026
    Docs as of 30 Sep 2026

    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.

    The four CLAUDE.md scopes
    ScopeLocationShared 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.mdJust you (all projects)
    Project instructions./CLAUDE.md or ./.claude/CLAUDE.mdTeam members via source control
    Local instructions./CLAUDE.local.mdJust 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/.

    A rule that loads only when Claude works on TypeScript files under src/api/markdown
    ---
    paths:
      - "src/api/**/*.ts"
    ---
    
    # API Development Rules
    
    - All API endpoints must include input validation
    - Use the standard error response format
    - Include OpenAPI documentation comments

    AGENTS.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.

    Loading CLAUDE.md and AGENTS.md togetherjson
    {
      "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?

    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?

    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.

    Settings scopes, strongest first, and what each is for
    ScopeFileUse it for
    Managedmanaged-settings.json, an MDM policy, or server-managed settingsSecurity policy and compliance requirements
    Project local.claude/settings.local.jsonPersonal overrides for one project, and testing before you share
    Shared project.claude/settings.jsonTeam permissions, hooks, plugins, and the environment variables the project needs
    User~/.claude/settings.jsonPersonal 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.

    A shared project settings file with allow and deny rulesjson
    {
      "$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. 1.Shared project settings (.claude/settings.json)
    2. 2.User settings (~/.claude/settings.json)
    3. 3.Managed settings
    4. 4.Project local settings (.claude/settings.local.json)
    5. 5.Command-line arguments such as --settings

    Sources21

    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.

    Claude Code model aliases
    AliasBehavior
    opusUses the latest Opus model for complex reasoning tasks
    sonnetUses the latest Sonnet model for daily coding tasks
    opusplanUses opus during plan mode, then switches to sonnet for execution
    defaultClears 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.

    Pinning a full model ID for one runbash
    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.

    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?

    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?

    Sources342

    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. 1.Ship a version 2 prompt
    2. 2.Evaluate that version against a labelled test set
    3. 3.Roll back by pinning sessions to version 1
    4. 4.Create the agent at version 1
    5. 5.Detect a regression in the new version

    Sources35

    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" }
      ]
    }

    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.

    How two plugins' ranges for the same dependency resolve
    Plugin A requiresPlugin B requiresResult
    ^2.0>=2.1One install at the highest 2.x tag at or above 2.1.0; both load
    ~2.1~3.0Installing plugin B fails with a conflicting version requirements message
    =2.1.0noneStays 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. 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. 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. 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. 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. 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. 1.
      “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. 2.
      “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 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
      “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. 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
      “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. 4.
      “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. 5.
      “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. 6.
      “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

    Ready to test yourself?

    Practise the 20 questions on this subdomain.

    Spotted a mistake, or was something unclear? Tell us.