CCLearn

Keeping current when the tool ships weekly

verified against Claude Code 2.1.261 · 2026-09-0914 min

By the end you can

  • Choose an update channel and version floor for a team and defend the choice
  • Distinguish a floor that constrains updates from a range that refuses to start
  • Check whether a documented behaviour is available on your version, plan and provider
  • Build a routine for reading release notes without disturbing the session

A teammate says your review hook fires on the wrong agent. You paste the same matcher into your own session and it behaves correctly. Neither of you has misread the config — you are running different builds of Claude Code, and one of them evaluates that matcher differently.

Everything you shipped in this level was written against a version. The tool moves; the file does not. This lesson is how a team stays on a known version, and how you check a documented sentence against the build in front of you.

How an update actually arrives

Claude Code checks for updates on startup and periodically while running. Updates download and install in the background, then take effect the next time you start Claude Code. — Set up Claude Code

So a session you have had open all afternoon is running the version it started with, whatever landed since — and a version number you read on Monday describes a machine, not a fleet.

Four ways to ask, each answering a different question:

AskWhat it tells you
claude --versionThe version number, and nothing else (CLI reference)
claude doctorRead-only install and settings diagnostics without starting a session — including the result of the most recent update attempt
/statusVersion, model, account and connectivity, on the Settings interface's Status tab
/doctorThe in-session checkup, which also checks for a newer version on your release channel — the bundled skill, on v2.1.205 or later

The two slash commands are documented in Commands. Lesson 1.2 used claude --version and claude doctor to prove one install healthy; here the question is whether everyone is on the same one.

That last row is itself a version claim, which makes it a fair demonstration of the lesson. What the table describes is the bundled skill, and the commands page dates what came before it: "Before v2.1.205, /doctor opened a read-only diagnostics screen and pressing f sent the report to Claude" (Commands). So when a teammate says /doctor "just opens a screen", that is not a broken install — it is an older build, and the row you are reading out to them describes a different command: a checkup that reports findings and offers to fix them, rather than a screen to read and a key that files a report. Nothing in the docs says which of the current checks that older screen ran, so do not carry the row's promises backwards across the gate; ask what version they are on. The fleet question in this lesson has a version-independent answer anyway, and it is claude --version compared against a number you wrote down.

Two channels, and what stable buys

autoUpdatesChannel controls which release channel background auto-updates and claude update follow.

ValueWhat you get
"latest" (the default when unset)New features as soon as they are released
"stable"A version that is typically about one week old, skipping releases with major regressions

That second row is the whole argument, quoted exactly (Set up Claude Code). Stable is not a long-term-support line and not a frozen version; it is a one-week delay that buys you the regressions somebody else already found — in practice the right default for a team, at the cost of a week of new features.

json
{
  "autoUpdatesChannel": "stable"
}

Any settings file may carry it; set it in managed settings to enforce one channel across an organization. Homebrew is the exception that will catch someone — Homebrew installs ignore this key, because the cask name chooses the channel: claude-code tracks stable, claude-code@latest tracks latest, and claude update defers to brew upgrade (Settings reference).

A floor that constrains updates, a range that refuses to start

These four keys look like variations on one idea. They are not.

KeyWhere it can be setWhat it doesWhat it does not do
autoUpdatesChannelAny settings fileChooses latest or stableNothing on a Homebrew install
minimumVersionAny settings fileRefuses to install anything below the valueDoes not block startup
requiredMinimumVersionManaged settings onlyClaude Code exits at startup below the floorDoes not end a session already running
requiredMaximumVersionManaged settings onlyClaude Code exits at startup above the ceilingDoes not stop claude update, claude install or claude doctor

The minimumVersion setting establishes a floor. Background auto-updates and claude update refuse to install any version below this value, so moving to the "stable" channel does not downgrade you if you are already on a newer "latest" build. — Set up Claude Code

That last clause is the everyday use: switching a machine from latest to stable would otherwise mean going backwards, and Claude Code writes the key for you when you choose to stay on your current version while switching channels in /config. In managed settings the same key enforces an organization-wide minimum that user and project settings cannot lower. Then the line that separates the two ideas:

The minimumVersion pin only constrains updates. To make Claude Code refuse to start outside a version range, use the managed settings requiredMinimumVersion and requiredMaximumVersion instead. — Set up Claude Code

minimumVersion shapes what an update may install; the required pair decides whether the program runs at all. If the intent is "nobody should drift too far behind", the floor is the setting. Reach for the startup range only when running an unapproved build is itself the thing you must prevent.

The trap: the ceiling, and where it bites

Three more edges on the same pair, from Settings reference and Managed settings:

  • Managed-scope only, and silent elsewhere. Claude Code gives no warning when it ignores the key in a user or project file. A required key in .claude/settings.json does nothing and tells nobody.
  • They fail open by design: an invalid value is dropped rather than enforced. A typo in a version string gives you no floor — safer than a locked fleet, and easy to mistake for a floor that is working.
  • requiredMinimumVersion is read only at session start. A session left open for weeks can still lag a rollout; the key blocks an outdated binary from starting and does not end a session already running.

And the one that undoes the plan if you miss it: both required keys themselves require Claude Code v2.1.163 or later. The mechanism for keeping people off ancient builds is absent on a sufficiently ancient build.

When updates do not arrive at all

Native installations auto-update. Several common install methods do not, and whether your channel setting means anything depends on which one your team used (Set up Claude Code).

SituationWhat happens
Homebrew, WinGet, apt, dnf, apkNone of them auto-update by default. You upgrade with brew upgrade claude-code (or claude-code@latest), winget upgrade Anthropic.ClaudeCode, or your Linux package manager's upgrade command
Homebrew or WinGet, opted inSetting CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE to 1 has Claude Code run the upgrade in the background and show a restart prompt on success
apt, dnf, apkNo opt-in exists: those commands need elevated privileges, so the upgrade stays manual and arrives through your normal system upgrade workflow
npm global directory not writableA one-time notice at startup; claude doctor lists the available fixes
DISABLE_AUTOUPDATER set to 1Only the background check stops; claude update and claude install still work
DISABLE_UPDATES set to 1Blocks all update paths, including manual updates

The last two rows are the pair people confuse. If you distribute Claude Code through your own channels and need users to stay on the version you provide, DISABLE_UPDATES is the one; the other leaves a one-command escape hatch open.

For a team on apt or dnf, autoUpdatesChannel and minimumVersion have nothing to act on, because Claude Code is not the thing installing the update. Two levers survive. The required pair still applies, because it checks the version that is running rather than how it got there. And the repositories carry channels of their own: the apt, dnf and apk repositories each offer a stable channel, serving a version typically about one week old and skipping releases with major regressions, and a latest channel serving every release as it ships (Set up Claude Code). An honest rollout plan names which lever a given machine answers to, rather than shipping an autoUpdatesChannel key that half the fleet ignores.

Reading release notes without spending the window

Lesson 3.2 made the case for /btw: a question whose answer never joins the conversation. /release-notes is that discipline applied to the changelog.

View the changelog in an interactive version picker. Select a specific version to see its release notes, or choose to show all versions. The notes appear in your transcript without entering the conversation Claude sees — Commands

You can read a month of releases mid-task without paying for them in context or changing the model's view of what you are working on. Pair it with claude --version for the two halves of the question: what changed, and whether you have it yet.

The docs are version-gated, and so is your reading of them

The official docs put version qualifiers inline, in the same sentence as the behaviour they gate. That is the honest place for them and the easiest place to skim past while copying a line into a team runbook.

Hyphens in the exact-match set require Claude Code v2.1.195 or later. On earlier versions a hyphenated name like code-reviewer is evaluated as an unanchored regular expression, so it also fires for senior-code-reviewer; anchor it as ^code-reviewer$ on those versions to match only that name. — Hooks

That is the opening scenario, explained: identical config, two evaluations, no bug. Plugin distribution carries a floor of its own. A plugin has two names — its name in the marketplace entry, and the name in its own plugin.json — and they can differ. As of v2.1.195, Enable and Disable in the /plugin interface work for plugins whose two names differ, and /plugin enable and /plugin disable accept either name; on an earlier version, disabling such a plugin reports already disabled and leaves it enabled (Discover plugins). To a teammate that reads as "the uninstall instructions are wrong". Two more from the commands page alone: /config key=value requires v2.1.181, and the /doctor CLAUDE.md trim check requires v2.1.206 or later.

The rule to carry: a doc sentence with a version qualifier keeps its qualifier when you copy it. Dropping it turns a conditional into a promise you cannot keep for everyone reading the file. Lesson 1.3 is the worked instance you have already met: the permission mode labelled Manual from v2.1.200, whose config value default did not change with the label.

Plan and provider: the other two gates

Version is one gate. Two more decide whether a documented feature exists for a given teammate, and neither is fixed by updating.

The Claude Code CLI and everything that runs locally work on every provider. — Feature availability

Read it precisely, because it is reassuring for a conventions pack and narrower than the sentence sounds. Subagents, hooks, commands, skills, CLAUDE.md memory, plugins, MCP servers, checkpoints, sandboxing, OpenTelemetry metrics and the managed settings file are listed as working on every provider — so the telemetry half of Lesson 12.4 travels. Three of those carry provider-specific differences the page then spells out: MCP servers, subagents and commands, where /design-sync and /import are unavailable on Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry and Claude Platform on AWS, and /voice requires a claude.ai account.

Lesson 12.5's other delivery mechanism does not travel with the file. Server-managed settings are marked unavailable on Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform and Microsoft Foundry, and on a Claude subscription they are a Team and Enterprise feature. "Managed settings work everywhere" is true of the file on disk and false of the admin console.

Plan gates run alongside provider gates, and the measurement plan is where that bites. The Enterprise Analytics API returns per-user engagement, usage and cost reports across Claude surfaces, Claude Code included — on one plan:

A Primary Owner creates a key with the read:analytics scope at claude.ai/analytics/api-keys. The API is not available on the Teams plan. — Analytics

The availability table is blunter: that API is ✗ on Pro, Max and Team, ✓ on Enterprise. But do not shorten this to "programmatic per-user numbers are Enterprise-only", because a Console organization reaches the same daily per-user metrics through a different API and a different credential — the Claude Code Analytics API, with an Admin API key. Same question, different door, depending on how the team authenticates. Before promising a team any capability, check three things and not one: their version, their plan, their provider.

A maintenance routine for the conventions pack

Small, and on a calendar rather than in someone's head:

  1. Record the version the pack was verified against, and the version any baseline was taken on — Lesson 12.4 showed a metric definition stepping at an upgrade, and a recorded number is what lets you tell that from a real change.
  2. Read /release-notes for the range since then, in the version picker rather than a web search, so it stays out of the conversation.
  3. Re-run the pack's own check. Lesson 12.3 gave the rollout an observable outcome; that check is now also your regression test for an update.
  4. Move the floor deliberately. Raise minimumVersion when a behaviour you depend on has a floor; leave requiredMaximumVersion unset unless running an unapproved build is genuinely the risk you are managing.
  5. Re-read the version qualifiers the runbook quotes — the floor you just raised may have made a workaround unnecessary.

A team's Claude Code setup is a dependency like any other. The only thing that makes it feel different is that it updates itself in the background and takes effect on a restart nobody announced.

Checkpoint

  1. Your organization wants "nobody more than a month behind". Which of minimumVersion, requiredMinimumVersion and requiredMaximumVersion do you deploy, in which file, and what do the other two do that you did not ask for?

    Show answer

    minimumVersion, in managed settings. Any settings file may carry the key, but managed settings is what makes it an organization-wide minimum that user and project settings cannot lower. It establishes a floor on installs: background auto-updates and claude update refuse to install anything below the value, and nothing about startup changes. The intent you described — nobody should drift too far behind — is what the floor is for; "a month" is a number you raise deliberately on a schedule, not something the key tracks for you.

    The other two are managed-settings-only and do something stronger than you asked: they make Claude Code exit at startup outside a version range. requiredMinimumVersion refuses to start below the floor, and is read only at session start, so a session left open for weeks still lags a rollout. requiredMaximumVersion refuses to start above a ceiling — it does not push a machine out of a range it is already in, it bites machines arriving from outside it, such as a new hire running the install script or a Homebrew install that ignored your channel setting. Both fail open, so a typo in a version string leaves you with no floor at all and looks exactly like one that works, and both need v2.1.163 or later — the mechanism for keeping people off ancient builds is absent on a sufficiently ancient build.

  2. A teammate reports that /plugin disable says already disabled and the plugin keeps loading. Before touching the plugin, what do you ask them, and which command gives the answer?

    Show answer

    Ask what version of Claude Code they are running, and have them run claude --version. A plugin has two names — its name in the marketplace entry and the name in its own plugin.json — and they can differ. As of v2.1.195, Enable and Disable in the /plugin interface work for plugins whose two names differ, and /plugin enable and /plugin disable accept either name; on an earlier build, disabling such a plugin reports already disabled and leaves it enabled.

    So this is a version gate wearing the costume of a broken plugin, and to the teammate it reads as "the uninstall instructions are wrong". Compare their number against v2.1.195 before you change anything in the plugin itself.

  3. Half your team installed with the native installer and half with apt. You set autoUpdatesChannel to "stable" in managed settings. Which half is affected, and what is the actual mechanism for the other half?

    Show answer

    Only the native half. autoUpdatesChannel chooses the channel that background auto-updates and claude update follow, and apt installs do not auto-update at all — Claude Code is not the thing installing the update there, so the key has nothing to act on. (Homebrew ignores it for a different reason: the cask name picks the channel.)

    For the apt half the mechanism is the repository's own channel. The apt, dnf and apk repositories each offer a stable channel — a version typically about a week old, skipping releases with major regressions — and a latest channel serving every release, and the upgrade arrives through your normal system upgrade workflow. There is no opt-in equivalent to CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE, which covers Homebrew and WinGet, because those commands need elevated privileges. One lever does reach both halves: the managed required pair checks the version that is running rather than how it got there. Name in the plan which lever each machine answers to, rather than shipping one key half the fleet ignores.

  4. You are about to write "the analytics API gives us per-user cost reports" into the rollout plan. Name the three gates you check before that sentence ships, and explain how the same sentence can be false for a claude.ai Team organization and true for one on the Console.

    Show answer

    Version, plan, and provider — three gates, not one. Any of them can make a documented capability absent for a given teammate, and only the first is fixed by updating.

    The plan gate is what makes the sentence false on Team. The Enterprise Analytics API, which returns per-user engagement, usage and cost across Claude surfaces with Claude Code included, is not available on the Teams plan — the availability table marks it ✗ on Pro, Max and Team and ✓ on Enterprise, and a Primary Owner creates the key with the read:analytics scope. The same sentence is true for a Console organization through a different door: the Claude Code Analytics API, reached with an Admin API key, returns daily per-user metrics. Same question, different API and different credential, depending on how the team authenticates — which is why "programmatic per-user numbers are Enterprise-only" is the shortening to avoid.

Sources