Claude Code saves a "Yes, and don't ask again" approval as an allow rule in .claude/settings.local.json at the root of your git repository. That file is meant to stay on your machine: Claude Code adds it to your global git excludes the first time it writes the file, but if you created the file yourself, or anything in it reaches a commit, the rules and any keys typed into them can be published with your code. This guide explains what the file holds, when it is and is not kept out of git, how a secret gets into it, and what to do if one already has. It was checked on November 9, 2026 against Anthropic's, GitHub's and Git's own documentation.

What settings.local.json is for

Anthropic's settings documentation describes .claude/settings.local.json as the project-local scope: personal overrides for one project, and a place to test settings before you share them in .claude/settings.json. The shared file is meant to be committed so a team gets the same rules. The local file is not.

Three things usually end up in the local file:

Where "don't ask again" rules are saved

According to the permissions documentation, a permanently saved approval goes to .claude/settings.local.json at the root of the git repository, even if you started Claude Code in a subdirectory. The rule then applies to future sessions anywhere in that repository, including subdirectories and worktrees. The table in that documentation lists Bash rules as permanent per repository and command, and WebFetch rules as permanent per repository and domain.

Two details matter for review:

There are exceptions, for example outside a git repository and on Windows, where the rule is stored elsewhere. The settings page lists them; check it if your setup is one of those cases.

Is it kept out of git?

Usually, but not always. The settings documentation says that the first time Claude Code writes the file in a git repository that does not already ignore it, it adds **/.claude/settings.local.json to your global git excludes file. If you create the file by hand, the documentation says to add it to .gitignore yourself.

The global excludes file belongs to your user account, not to the repository. Git's documentation describes it as the file named by core.excludesFile, by default $XDG_CONFIG_HOME/git/ignore or ~/.config/git/ignore, and contrasts it with .gitignore, which is the file that travels with the repository when it is cloned. In practice that means (ours):

Adding .claude/settings.local.json to the repository's own .gitignore closes all three gaps for everyone who clones the project. It costs one line.

The documentation also notes a trust difference: allow rules in the local file apply without the workspace-trust step, while a tracked file goes through that step. So a local file that becomes tracked is not only a leak risk, it also changes how its rules are treated.

How a secret ends up in the file

The saved rule is built from the command you approved (ours, from how the documentation describes saving approvals). If that command contained a credential, for example a token in a curl header, a password in a database connection string or an inline API_KEY=... before a script, the credential can end up in the rule text. Nothing about the prompt makes that obvious at the moment you click.

The other common route is the env block. It is convenient for giving Claude Code an environment variable, and it stores the value in plain JSON.

On November 8, 2026 a security vendor's report on agent permission files found in public GitHub repositories drew a large discussion on Hacker News. We could not read the report itself, so this post does not repeat its numbers; the advice below rests on the vendor documentation only.

A short checklist

If a key was already committed

Treat it as exposed. GitHub's secret scanning documentation says scanning runs automatically on public repositories, that some partner secrets are reported directly to the issuing provider, and that you should rotate an affected credential immediately. Removing the line in a new commit does not remove it from history or from clones, forks and caches (ours). The order that works:

  1. Revoke or rotate the credential with its provider.
  2. Check the provider's logs for use you do not recognise.
  3. Remove the file from tracking (git rm --cached .claude/settings.local.json), add it to .gitignore, and commit.
  4. Decide whether to rewrite history. It helps for private repositories, but it does not undo a leak from a public one, which is why rotation comes first.

What this does not solve

Keeping the file out of git stops one kind of leak. It does not limit what an approved command can do on your machine, and it does not stop an agent from reading a secret that is on disk and sending it somewhere it is allowed to reach. For those, see how to sandbox an AI agent, prompt injection and the AI agent security checklist. If the agent talks to MCP servers, the MCP security checklist covers token handling on that side. For company-wide rules that developers cannot override, see Claude Code managed settings.

How we approach this

This is our approach, not a rule. On client projects we commit a reviewed .claude/settings.json with the team's allow and deny rules, ignore the local file in the repository's own .gitignore, keep credentials in environment variables that come from a secrets manager, and run a secret scanner in CI as well as relying on GitHub's. "Don't ask again" is fine for commands that never carry a credential; for anything that does, we would rather answer the prompt each time.

Sources: Claude Code, settings, Claude Code, permissions, GitHub, about push protection, GitHub, about secret scanning, Git, gitignore. All read November 9, 2026. Tool behavior changes often, so check the current pages before configuring.