# Configuring allowed-tools in Skill Frontmatter to Control Claude Code Tool Permissions

> Control Claude Code tool permissions without prompts. Configure allowed-tools in skill frontmatter with argument patterns for precise control.

- Repository: [Shayan Rais/claude-code-best-practice](https://github.com/shanraisshan/claude-code-best-practice)
- Tags: best-practices
- Published: 2026-03-12

---

**You can eliminate permission prompts in Claude Code by declaring `allowed-tools` as a comma-separated list in a skill's YAML frontmatter, optionally using argument patterns like `Bash(gh *)` to restrict usage to specific command prefixes.**

The Claude Code framework from `shanraisshan/claude-code-best-practice` enables fine-grained tool permissions through skill-level declarations. By configuring the `allowed-tools` field in your skill's frontmatter, you create a whitelist that allows specific tools to run silently while maintaining security-by-default for all other operations.

## How `allowed-tools` Works in Skill Frontmatter

According to [`best-practice/claude-skills.md`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/best-practice/claude-skills.md), the `allowed-tools` field accepts a simple comma-separated string listing tools that may execute without triggering a user confirmation dialog. When omitted, every tool call generates a permission request, ensuring no accidental privilege escalation occurs.

### Syntax and Pattern Matching

The field supports plain tool names or tool names followed by an argument pattern in parentheses. As shown in [`.claude/skills/agent-browser/SKILL.md`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/.claude/skills/agent-browser/SKILL.md), you can restrict Bash commands to specific namespaces:

```yaml
allowed-tools: Bash(agent-browser:*)

```

This permits any Bash invocation starting with `agent-browser:` while blocking arbitrary shell access.

### Permission Hierarchy

Skill-level permissions follow a strict override order: **Skill > Agent > Command > Global defaults**. A skill's `allowed-tools` declaration beats any broader setting, giving you surgical control over what each individual skill can access without affecting the global configuration described in [`CLAUDE.md`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/CLAUDE.md).

## Balancing Access with `disallowedTools`

The framework implements a security-by-default posture where explicit denials override allowances. If a tool appears in both `allowed-tools` and `disallowedTools`, the denial wins. This allows you to grant broad access patterns while carving out specific dangerous operations, such as allowing `Bash(sed *)` but explicitly denying `Bash(rm *)` via `disallowedTools`.

## Real-World Configuration Examples

The repository [`reports/claude-agent-command-skill.md`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/reports/claude-agent-command-skill.md) demonstrates common `allowed-tools` patterns including `Read`, `Grep`, `Glob`, and scoped Bash commands.

### Read-Only File Access

```yaml
name: simple-reader
description: Reads a file and returns its contents.
allowed-tools: Read

```

This skill can call the `Read` tool without prompting; `Edit` and `Bash` still require explicit permission.

### Restricted CLI Commands

```yaml
name: github-agent
description: Executes GitHub CLI commands on behalf of the user.
allowed-tools: Bash(gh *)

```

Allows any `Bash` invocation starting with `gh ` (e.g., `gh issue list`), while unrelated Bash calls remain gated.

### Combining Allow and Deny Lists

```yaml
name: file-updater
description: Reads a config, updates a key, and writes it back.
allowed-tools: Read, Edit, Write, Bash(sed *)
disallowedTools: Bash(rm *)

```

The skill may use file operations and `sed`-based Bash commands, but any `rm` attempt is explicitly blocked despite the general `Bash` allowance.

### Inheriting and Extending Parent Permissions

When skills preload other skills via the `skills:` field, each child inherits the parent's `allowed-tools` but can augment its own list. For example, a parent skill defined in [`.claude/skills/agent-browser/SKILL.md`](https://github.com/shanraisshan/claude-code-best-practice/blob/main/.claude/skills/agent-browser/SKILL.md) might declare:

```yaml
name: agent-browser
allowed-tools: Bash(agent-browser:*)

```

A child skill can add `Read` capabilities:

```yaml
name: browser-scraper
skills:
  - agent-browser
allowed-tools: Read

```

The resulting child can execute both the parent's browser-specific Bash commands and read files without prompts.

## Summary

- Declare `allowed-tools` in skill frontmatter as a comma-separated string to enable silent tool execution without permission prompts.
- Use argument patterns like `Bash(gh *)` to restrict tools to specific command prefixes, balancing usability with security.
- Remember that explicit `disallowedTools` entries always override `allowed-tools` entries, allowing you to block specific dangerous operations within broader allowances.
- Skill-level permissions travel with the skill file, eliminating configuration drift and ensuring consistent behavior across environments.

## Frequently Asked Questions

### What happens if I don't specify `allowed-tools` in my skill?

If you omit the `allowed-tools` field, Claude Code defaults to a security-first posture where every tool call triggers a permission prompt. No tools execute silently unless explicitly whitelisted in the skill's frontmatter.

### Can I use wildcards in `allowed-tools` patterns?

Yes. The syntax supports patterns in parentheses after the tool name, such as `Bash(gh *)` to allow any GitHub CLI command or `Bash(agent-browser:*)` to restrict Bash to specific command namespaces, as implemented in the `agent-browser` skill example.

### How do skill permissions interact with global Claude Code settings?

Skill-level `allowed-tools` declarations override broader permissions following the hierarchy: **Skill > Agent > Command > Global defaults**. This means a skill's specific whitelist takes precedence over any agent or global configuration, ensuring fine-grained control per workflow.

### What is the difference between `allowed-tools` and `disallowedTools`?

`allowed-tools` functions as a whitelist granting silent execution permission, while `disallowedTools` acts as a blacklist that explicitly blocks specific tools or patterns. If a tool matches both lists, `disallowedTools` wins, allowing you to grant broad access while carving out specific dangerous exceptions.