Claude Code permissions define which tools the coding agent can use and which actions require approval. For .NET development, that boundary needs more thought than allowing anything that begins with dotnet. Reading a project file, editing an endpoint, running a test assembly, applying a database migration, and publishing an application are different operations with different effects.
The goal is not to eliminate every prompt. It is to make authority understandable. A developer should be able to explain why a command is permitted, which environment it reaches, and what remains outside the task.
Information checked October 9, 2026 against the current Claude Code permissions reference. Product modes and matching rules can change; consult that reference when changing configuration. All examples here are unexercised and use sanitized paths.
Instructions and permissions solve different problems
A repository instruction can say that production data is out of scope. That is useful context for the model. It does not revoke a tool, remove a credential, or prevent a permitted executable from connecting to a database.
The official reference makes this distinction explicit: permission rules are enforced by Claude Code, while prompts and CLAUDE.md shape what the model tries to do. Both matter. Instructions describe the intended workflow; permissions constrain tool access within the client.
There is a third boundary: the operating environment. A process can only use credentials, files, and network access available to it, subject to the platform's controls. Removing production credentials from a development runner can provide a stronger boundary than asking the model not to use them.
These layers should agree. If instructions prohibit publishing but the client permits a broad command family and the runner holds a deployment credential, the workflow contains a contradiction. A reviewer should resolve it before accepting unattended execution.
The permission model guide for another terminal agent explores similar questions about authority. Its flags and configuration are client-specific. Use it for the concepts, not as Claude Code syntax.
Classify .NET operations by their actual effects
Reading source files usually supports discovery without changing application state. Editing files changes the checkout. Running a build executes project-defined build logic and writes artifacts. Running tests executes arbitrary application and test code. Publishing writes output and may be wrapped by scripts that deploy it elsewhere.
The command name is not enough to establish safety. A build can contain custom targets. A test fixture can call a real API. A repository script with an innocent name can apply migrations or upload artifacts. Review the entry point and its dependencies before pre-approving it.
A practical classification begins with the resource affected. Is it only a disposable checkout? Does the command reach shared infrastructure? Does it require credentials? Is its output reversible? Is the environment isolated from production?
For a bounded endpoint task, permission to read relevant source and propose edits may be enough at first. Validation can happen through an approved remote workflow. There is no requirement that the same process that authors the change also holds every credential needed to validate or release it.
That separation has a cost: more handoff and potentially slower feedback. Its benefit is a smaller authority surface and clearer evidence about who executed which operation. The appropriate balance depends on the repository, not a universal allowlist. A bounded .NET terminal-agent workflow provides related context for keeping discovery, authoring, and verification explicit, without transferring another client's command syntax.
Understand the documented rule order
Claude Code permission rules use a tool name alone or a tool with a specifier, such as Read or Bash(dotnet --info). The current reference describes evaluation in the order deny, ask, then allow. A matching deny is not overridden by a narrower allow.
Likewise, a matching ask rule still prompts even if a more specific allow rule matches. This is important when reviewing inherited settings. A developer might add an exact allow and assume it takes effect, while an existing broader ask or deny intentionally keeps the operation gated.
Here is a deliberately small example for a Bash-tool session:
{
"permissions": {
"allow": [
"Bash(dotnet --info)"
],
"ask": [
"Bash(dotnet test *)",
"Bash(dotnet build *)",
"Bash(dotnet publish *)"
],
"deny": [
"Read(./.env)"
]
}
}
This is a syntax illustration, not a complete security policy. It auto-approves one exact informational command, keeps selected command families behind approval, and denies a specific file read. It does not authorize database writes, production deployment, or a broad tool family.
The .env denial is narrow. It does not claim to hide every credential file, block shell reads, or establish a sandbox. A real secret-protection policy needs to consider other paths and access mechanisms. Prefer withholding sensitive files from the execution environment where possible.
Tool names matter. These Bash(...) entries apply to the Bash tool; do not assume that they also describe the PowerShell tool. Inspect the actual tool calls in your installed client and consult the current reference before configuring another shell surface.
Keep wildcard scope visible
The documented * wildcard can match text including spaces. A command with no wildcard matches one exact command, while a pattern such as Bash(dotnet test *) covers a family of invocations beginning with that subcommand.
That can be convenient, but every varying argument deserves attention. A test command can select another project, use another configuration, or pass options affecting behavior. A broad dotnet family would include operations that do not belong in a source-editing task.
Exact commands are easier to reason about but less flexible. They may stop matching when someone changes a path, adds a filter, or uses a different argument order. Narrow families reduce maintenance but authorize a larger set. This is a tradeoff to make deliberately, not a reason to use the broadest pattern.
Command matching also has documented limits. Different invocation forms, wrappers, scripts, and shell behavior mean a textual rule should not be described as preventing every equivalent operation. The official permissions reference explains these limits and how compound shell commands are handled.
Do not attempt to repair an overbroad environment with an ever-growing collection of string patterns. If a runner must never publish or modify shared data, remove the corresponding credentials and capabilities as well. Client permissions and environment controls are complementary.
Choose a settings scope that matches ownership
Claude Code documents user, shared-project, project-local, command-line, and managed settings. The current settings precedence reference places managed settings above command-line settings, then project-local, shared-project, and user settings.
Shared project configuration belongs in .claude/settings.json. It communicates the repository's baseline to collaborators. Personal project adjustments belong in .claude/settings.local.json, while user settings apply across projects.
Do not put credentials in any of these examples. A configuration file that is appropriate to share is not necessarily an appropriate place for a token. Keep authority and secret delivery separate.
When behavior differs between two developers, compare the resolved configuration rather than only the tracked project file. User settings, local settings, command-line options, and managed policy can all matter. The /permissions interface lists rules and the settings file each comes from.
Managed policy is especially relevant in organizations. A project author should not promise that a committed setting can override an administrator's restriction. If an operation is blocked by policy, the correct result is an explicit limitation and an approved escalation path.
Understand modes without treating them as guarantees
The current permission reference describes several modes. default, labeled Manual, prompts according to the permission system. acceptEdits automatically accepts file edits and certain filesystem operations within the documented working-directory boundaries. It is not equivalent to automatically approving every shell command.
plan supports exploration without editing source files, but the documentation includes behavior involving classifier-approved commands when auto mode is available. Do not simplify that into a claim that Plan mode can never execute a command.
dontAsk denies calls that would otherwise prompt while allowing actions that need no approval and tools already approved under the documented rules. It is useful to understand this as a failure policy, not as proof that a scripted task has all the permissions it needs.
The reference also documents auto, where a classifier evaluates certain actions. That changes how permission decisions are made; it does not establish that application code is correct or that an external service authorizes an operation.
Choose the mode from the task's authority requirements. For educational examples, retaining visible approvals is often easier to audit than silently expanding what the agent can do. This article does not provide a permission-bypass recipe.
Be more careful with headless runs
Non-interactive execution changes the user interface, not the consequences of tool access. The current headless documentation describes -p runs and notes that ordinary project hooks and MCP configuration load without the interactive workspace trust and per-server approval dialogs.
That is a material distinction. Reviewing a repository interactively before approving a server is not the same process as pointing an unattended command at a new checkout. Treat repository configuration as executable input when designing automation.
For a narrow source-summary task, the documented bare mode skips automatic discovery of hooks, skills, plugins, MCP servers, memory, and CLAUDE.md. It also has distinct authentication requirements. Here is an illustrative command for an environment already provisioned with permitted API authentication:
claude --bare -p 'Summarize the public API in C:\work\Shipping\src\Shipping\Domain. Do not edit files or run commands.' --allowedTools 'Read'
The command has not been run. It shows the documented bare-mode and allowed-tool syntax, not a claim that a natural-language prohibition alone enforces read-only operation. Inspect the effective tool configuration and applicable policies for the actual session.
Bare mode also omits useful repository context. That is its tradeoff: less implicit startup behavior, but more context that the caller must supply explicitly. It is not a universal replacement for an interactive repository workflow.
The headless automation guide for Copilot CLI discusses related operational concerns. Keep its product syntax separate from the Claude command above.
Database and publishing authority should stay separate
A repository may contain migration tools, deployment scripts, or MCP tools that change shared state. Their presence does not make them appropriate for a coding task. Describe these as separate operations with separate authorization and execution identities.
For database work, distinguish generating or reviewing a migration from applying it. The first changes source artifacts. The second changes a database. An approval to edit an EF Core model should not be interpreted as consent to update production.
For publishing, distinguish creating build output from deploying it, and deploying a preview from releasing publicly. A release process should identify its target and revision explicitly. A model's summary that a task is complete does not establish that a human authorized a release.
MCP adds another authority surface. A server tool can have effects outside the shell and outside the checkout. Securing remote C# MCP servers explains why server-side authentication and authorization remain necessary even when a client has permission controls.
An MCP tool named get_report may still invoke application code with credentials. Verify its actual contract rather than inferring read-only behavior from its name. Client configuration should not be the sole control protecting shared systems.
Diagnose permission failures without widening everything
When a command is denied, begin with the exact attempted tool call. Was the rule written for Bash while the client called PowerShell? Did the command differ from an exact match? Did an ask or deny rule take precedence? Did managed policy limit the session?
Use the documented diagnostic interface rather than changing several settings at once:
claude doctor
This unexercised command is documented as a read-only installation diagnostic in the skills reference. Within an interactive session, /permissions provides the rule view. The diagnostic does not prove that your proposed command is safe.
If the agent needs an additional action, identify that action and why it belongs to the task. Approve or configure the narrow boundary deliberately. Do not respond to a blocked test by allowing every build, package, database, and publishing command.
A useful permission failure is information: the task attempted something outside the currently approved boundary. Sometimes the boundary should change. Sometimes the task should stop. Both outcomes are better than disguising the denial as a successful check.
Frequently asked questions
Does CLAUDE.md enforce Claude Code permissions?
No. It provides instructions and context. The official reference distinguishes model guidance from permissions enforced by the client. Environment controls and server-side authorization supply additional boundaries that instructions cannot replace.
Is allowing dotnet test always safe?
No. Tests execute code and can reach files, networks, databases, or custom fixtures. Inspect the selected project and environment. A narrow command approval still requires confidence in what that command runs.
Can an exact allow override a broader deny?
Not under the documented rule order. Deny is evaluated before ask and allow. A matching deny wins even when an allow is more specific, so inspect inherited settings when a seemingly valid rule does not take effect.
Does acceptEdits approve builds and database commands?
It should not be interpreted that way. The documented mode accepts edits and certain filesystem actions within its boundaries. Shell execution and externally consequential operations need their own applicable permission decisions and authorization.
Why can headless execution behave differently from an interactive session?
The current docs describe different trust-dialog behavior and automatic loading of project configuration in ordinary -p runs. Review the headless reference and effective settings before running untrusted repository content unattended.
What is the right response to a permission denial?
Identify the exact tool, command, source rule, and intended effect. Either authorize a narrow action through the approved process or report that it remains blocked. A denial is not justification for a broad allowlist.
Authority should remain explainable
Claude Code permissions for .NET development work best when the task, tool configuration, and execution environment describe the same boundary. Source editing, verification, database changes, and release operations are related, but they are not interchangeable permissions.
Understanding that separation makes an agent's work easier to review without pretending that every approved command is harmless or every completed run is correct.

