Skip to main content

Feature Flags: Why Your Claude Code Isn't Mine

Advanced

Two developers install the same Claude Code version, on the same OS, in the same repo. One of them has a feature the other doesn't, and neither of them gets an error message. This isn't folklore — it's the documented design. Claude Code switches some features on using feature flags it fetches from Anthropic at startup, and several ordinary, well-intentioned configurations turn that fetch off completely.

The consequence that surprises people: a purely local operation can depend on a network call. In September 2026 that became a 437-point Hacker News thread, because reading a Markdown file off your own disk turned out to need one.

What you'll learn
  • How Claude Code's remote feature flags are fetched, cached, and evaluated
  • The four configurations that silently switch flag fetching off
  • Why DISABLE_TELEMETRY=0 still opts you out — and why DO_NOT_TRACK=0 doesn't
  • The fifteen features you lose with fetching off
  • How to detect gating in two minutes and pin behavior so it can't bite you

The mechanism​

Claude Code ships with a code default for every flag and then tries to fetch the real values. The provider is GrowthBook — there's a dedicated DISABLE_GROWTHBOOK environment variable, and the changelog has entries like a crash fix for "when a GrowthBook feature evaluates to null" (v2.1.214).

Four properties of that system explain almost every weird case you'll hit:

Guided walkthrough1 of 4
  1. The binary knows the flag names and a fallback value for each. The values that decide what your session can do come from Anthropic over the network. No fetch means every flag falls back to its code default — which for a feature mid-rollout is usually off.

The four ways the fetch goes dark​

The docs are explicit about this. Claude Code skips the flag fetch in these sessions:

  • You set one of four environment variables: DISABLE_GROWTHBOOK, DISABLE_TELEMETRY, DO_NOT_TRACK, or CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC.
  • You're on a third-party provider: Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, or Microsoft Foundry — unless a host platform that embeds Claude Code sets CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST.
  • You're in a Claude apps gateway session.
  • It's your first session after a fresh install or an upgrade — the flags haven't arrived yet. More on this below.

Notice what those first two have in common: they're the configurations a security-conscious enterprise picks. The exact population most likely to disable telemetry and route through Bedrock is the population that silently gets the smallest feature set.

Watch out
  • Disabling telemetry is not only a privacy choice — it is also a feature switch. The docs say DISABLE_TELEMETRY 'also disables feature-flag fetching with the same effect as DISABLE_GROWTHBOOK'.
  • If you want privacy without losing features, there is no combination that gives you both: every documented way to stop the telemetry also stops the flag fetch.
  • CI runners with an ephemeral HOME are a fresh install on every run, so they land in the no-flags case every single time.

The value trap: three variables, three parsing rules​

This is the part that costs people an afternoon. These variables live in the same family, read as if they do the same thing, and parse their values under three different rules.

VariableHow it reads the valueSo =0 means
DISABLE_TELEMETRYAny non-empty value turns it onStill opts you out. Unset it to re-enable
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICAny non-empty value turns it onStill disables the traffic. Unset it to re-enable
DISABLE_ERROR_REPORTINGAny non-empty value turns it onStill opts you out. Unset it to re-enable
DISABLE_GROWTHBOOKStandard boolean — set to 1 or trueLeaves fetching on
DO_NOT_TRACKStandard boolean — set to 1Leaves telemetry on

Read that table twice. DISABLE_TELEMETRY=0 disables telemetry. DO_NOT_TRACK=0 does not. Both are documented, deliberate, and opposite.

What you'll learn
  • The docs state the rule directly: some variables 'read only whether you set them at all, so any non-empty value including 0 turns the behavior on'.
  • To undo one of those, you must unset the variable or set it to an empty value — assigning 0 or false is not an off switch.
  • This bites hardest in a Dockerfile or CI config where someone 'turned it off' by flipping 1 to 0.

What you actually lose​

With flag fetching off, fifteen documented capabilities go away. Grouped by what they cost you:

Permissions and startup

  • Sessions can't start in auto mode by default on Pro, Max, and Team plans
  • The VS Code extension can't read settings files for the starting permission mode
  • /auto-mode-setup can't draft autoMode.environment entries

Anything that reaches beyond the local session

  • Remote Control
  • Messaging sessions on other machines (same-machine messaging still works)
  • Syncing the skills and plugins enabled for your claude.ai account into terminal sessions
  • Reading or replying to comments on an artifact
  • The advisor tool

Commands and diagnostics

  • claude import and the /import command
  • /skill-doctor and its report in the /plugin Stats tab

Silent behavior changes — the dangerous group

  • MCP: Claude Code stops excluding MCP tools whose input schema the API would reject. It sends the schema anyway, and the request fails with a 400 naming the tool by position
  • MCP: no probing of claude.ai connector servers for protocol revision 2026-07-28, unless you set MCP_PROTOCOL_NEGOTIATION=auto
  • Large pastes are no longer treated as pasted rather than typed text — the content behind a [Pasted text #N] placeholder reaches Claude unmarked
  • On Windows with Git Bash installed, claude.ai and Console accounts don't get the PowerShell tool by default; set CLAUDE_CODE_USE_POWERSHELL_TOOL=1
  • Claude-drafted feedback is off

The last group is the one to internalize. A missing slash command announces itself. A 400 error that names a tool by its position in the array does not look like a telemetry setting, and you will debug your MCP server for an hour before you think to check an env var.

The blast radius has precedent​

Flag and telemetry settings have leaked into places nobody would predict. Two fixed-but-instructive examples from the changelog:

  • v2.1.108 fixed subscribers who set DISABLE_TELEMETRY falling back to a 5-minute prompt cache TTL instead of 1 hour. A privacy variable was quietly costing money on every long session — a 12× shorter cache window.
  • v2.1.105 fixed CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC set in one project's settings permanently disabling usage metrics for all projects on the machine.

Both are fixed. Both show the shape of the risk: these switches cut across subsystems that look unrelated.

The first session after an install or upgrade​

This one is worth its own heading because it produces the classic irreproducible bug report.

On your first session after installing Claude Code — or after upgrading to a version that adds a feature — a flag-gated feature can simply be missing, and the session can start in Manual mode on a plan that otherwise starts in auto mode. Claude Code fetches the flags during that session, so both are present next time.

Two corollaries:

  • It fixes itself, which is exactly why it's hard to report. By the time anyone looks, the second session has the flags.
  • It never fixes itself in ephemeral environments. A CI runner, a fresh container, or any setup with a throwaway home directory is on its first session every time.

The docs do note one mitigation: after a fresh install, a non-interactive session such as claude -p, the Agent SDK, or the VS Code extension can still pick the flags up before it chooses the starting permission mode.

Case study: AGENTS.md, a local file behind a remote switch​

The clearest example of the whole pattern, and the one that made the front page.

Guided walkthrough1 of 5
  1. The changelog entry: in a project with no CLAUDE.md, Claude Code reads AGENTS.md instead; change it under 'Project instructions' in /config. The entry itself flags that it isn't on Bedrock, Vertex or Foundry yet.

The lesson generalizes past this one bug. Ask of any new Claude Code feature: is this gated? If it is, then your telemetry posture, your provider, and how recently you installed all become inputs to whether it works.

Diagnose it in two minutes​

You don't need to guess. Three checks, cheapest first.

1. Ask whether the setting even exists. When AGENTS.md support is unavailable, the Project instructions row doesn't appear in the /config panel at all. A missing setting is itself the diagnosis — the feature isn't off, it's absent.

2. Look at what an interactive session tells you. When it works, Claude Code prints a line in the conversation like no CLAUDE.md found; AGENTS.md loaded: /home/you/repo/AGENTS.md. No line, no load.

3. Run a canary. The technique that cracked the original report: put a word in the file that appears nowhere else, then ask for it in a clean, non-interactive session. If the word comes back, the file reached the model. This works for any instruction file, on any version.

Canary test — did the instruction file actually load?

mkdir -p /tmp/canary && cd /tmp/canary
echo 'The project codeword is PERIWINKLE.' > AGENTS.md
claude -p 'What is the project codeword? Answer with one word.'

Run it once with your normal environment, then once with the privacy variables cleared, and compare. Note the empty-string assignment — remember that DISABLE_TELEMETRY=0 would not clear it.

Same test with flag fetching allowed — note the empty values, not zeros

cd /tmp/canary
env DISABLE_TELEMETRY= CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC= DISABLE_GROWTHBOOK=false \
claude -p 'What is the project codeword? Answer with one word.'

4. If you need the detail, turn on debug logging. Launch with --debug or /debug, and logs land in ~/.claude/debug/<session-id>.txt. One catch: the DEBUG environment variable only accepts the truthy values 1, true, yes, and on — a namespace pattern like DEBUG=express:* left over from another tool will not enable it.

Pin behavior instead of relying on a flag​

The durable fix is to stop depending on the gate. Two patterns.

Pin the setting explicitly. For instruction files, the Project instructions value can go in a settings file under the built-in plugin's ID rather than being left to the default. One important limit: Claude Code ignores this key in project and local settings files — it only reads it from ~/.claude/settings.json, a --settings file, or managed settings. Putting it in your repo's .claude/settings.json will do nothing.

Load CLAUDE.md and AGENTS.md together — user or managed settings only

{
"pluginConfigs": {
  "agents-md@builtin": {
    "options": { "instructionFiles": "claude-md-and-agents-md" }
  }
}
}

Use a path that was never gated. A CLAUDE.md that imports AGENTS.md has worked on every version, every provider, and with telemetry off — because it's ordinary @path import expansion, not a flagged code path. This is the recommendation the docs themselves give for Bedrock, Vertex and Foundry sessions.

The one-line CLAUDE.md that has never needed a flag

@AGENTS.md

One subtlety if you take this route: an AGENTS.md read through the setting behaves slightly differently from one pulled in by import. InstructionsLoaded hooks don't fire for the setting-based path, but they fire as usual for an AGENTS.md that a CLAUDE.md imports or symlinks to. If you have hooks on instruction loading, the import is the safer path.

Flag gating at a glance
Press Enter or Space to flip the card. Use the left and right arrow keys to move between cards.Term shown.
1 / 8

Check yourself​

Check yourself

0/4
  1. Your Dockerfile has ENV DISABLE_TELEMETRY=0 because a colleague 'turned telemetry back on'. What's actually happening?
  2. A CI job reports that Claude Code never picks up the repo's AGENTS.md, but it works fine on every developer laptop. What's the most likely cause?
  3. With flag fetching disabled, which failure is hardest to trace back to the flag setting?
  4. You want AGENTS.md to load reliably on Amazon Bedrock, on any version. What's the robust move?
Key takeaways
  • Claude Code fetches feature flags from Anthropic (GrowthBook), caches them to disk, and evaluates them against your version and subscription tier — so two identical installs can legitimately behave differently.
  • Four env vars, three third-party providers, apps gateway sessions, and the first session after an install all skip that fetch, costing you fifteen documented features.
  • DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC and DISABLE_ERROR_REPORTING treat any non-empty value as on — including 0. DO_NOT_TRACK and DISABLE_GROWTHBOOK are real booleans. Unset, don't zero.
  • The worst losses are silent: unfiltered MCP schemas causing positional 400s, and unmarked pasted text.
  • AGENTS.md was the case study — native from v2.1.277, gated, fixed in v2.1.281. A CLAUDE.md containing @AGENTS.md never needed the flag.

Next​

Sources & further reading​