> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Permissions

> Manage interactive tool-approval rules from the CLI with praisonai permissions

Manage interactive tool-approval rules from the CLI — `praisonai permissions` lists, adds, removes, and shares your project's approval rules.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    A[Agent] --> B[Tool Call]
    B --> C{Permission Check}
    C -->|Rule match| D[Allow / Deny]
    C -->|No rule| E[Prompt User]
    E --> F[Allow / Deny / Persist]

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef tool fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef check fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff

    class A agent
    class B tool
    class C,E check
    class D,F result
```

## Quick Start

<Steps>
  <Step title="Run with interactive approval">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai --approval console run "Check git status"
    ```

    When a sensitive tool runs, you see the approval prompt.
  </Step>

  <Step title="Persist with always">
    Press `a` at the prompt to write a persistent allow-rule to `approvals.json`.
  </Step>

  <Step title="Re-run without prompting">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai --approval console run "Check git status again"
    ```

    Matching rules are applied automatically.
  </Step>
</Steps>

## Approval prompt

```
🔒 Tool Approval Required
Function: execute_command
Risk Level: MEDIUM
Agent: researcher
Arguments:
  command: git status

Allow execute_command?  [o] once   [s] this session   [a] always (bash:git status *)   [n] no   [d] deny & redirect
Choice [o/s/a/n/d] (n):
```

The five keys choose how long the approval lasts:

* `[o]` **once** — consumed after this exact call; a second matching call re-prompts
* `[s]` **session** — kept in memory for this process
* `[a]` **always** — persisted to `~/.praisonai/permissions/` and reused across runs
* `[n]` **no** — deny once
* `[d]` **deny & redirect** — deny, then type what the agent should do instead at the `What should the agent do instead?` follow-up; the guidance steers the next turn

See [Interactive Tool Approval](/docs/docs/features/interactive-approval#scope-choice) for the full scope semantics.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant U as User
    participant CLI as CLI
    participant PM as PermissionManager
    participant D as Disk

    CLI->>PM: check(target, agent)
    alt Rule matches
        PM-->>CLI: ALLOW / DENY
    else No rule
        CLI->>U: Show prompt
        U-->>CLI: o / s / a / n
        opt a (always)
            CLI->>PM: approve(target, reusable_scope=True)
            PM->>D: approvals.json
        end
    end
```

## CLI approval modes

| Flag                      | Mode           | Behaviour                                                                                                                                                                   |
| ------------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--approval console`      | `DEFAULT`      | Prompt for sensitive tools                                                                                                                                                  |
| `--approval plan`         | `PLAN`         | Block write, edit, delete, bash, shell                                                                                                                                      |
| `--plan` (shortcut)       | `PLAN`         | Alias for `--approval plan`. Read-only — write, edit, delete, bash, shell are denied. Cannot be combined with `--approval`, `--allow`, `--deny`, or `--permission-default`. |
| `--approval accept-edits` | `ACCEPT_EDITS` | Auto-approve edit/write tools                                                                                                                                               |
| `--approval bypass`       | `BYPASS`       | Skip all checks (dangerous)                                                                                                                                                 |

<Tip>
  The CLI flag `bypass` maps to `PermissionMode.BYPASS`, whose value is `bypass_permissions`.
</Tip>

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai --approval plan run "Explore the codebase"
praisonai --approval accept-edits run "Refactor utils.py"
```

### Read-only mode shortcut

`--plan` on `praisonai run` and `praisonai code` is a discoverable shortcut for `--approval plan`.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai run  --plan "Explore the codebase"
praisonai code --plan "Draft a migration plan"
```

Both wrap `--approval plan` (`PermissionMode.PLAN`) — the underlying enforcement is unchanged. `--plan` cannot be combined with `--approval`, `--allow`, `--deny`, or `--permission-default` (and on `code`, not with `--no-safe` / `--dangerously-skip-approval`); contradictory combinations exit 1. See [Permission Modes](/docs/features/permission-modes).

## Non-interactive mode

| Option                        | Type | Default | Description                             |
| ----------------------------- | ---- | ------- | --------------------------------------- |
| `--yes` / `-y`                | flag | off     | Skip prompts; approval defaults to deny |
| `PRAISONAI_NON_INTERACTIVE=1` | env  | unset   | Same as `--yes` for CI and scripts      |

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai --yes --approval console run "Deploy check"
PRAISONAI_NON_INTERACTIVE=1 praisonai --approval console run "Deploy check"
```

## Subcommands

### `list`

List all permission rules in the current project.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai permissions list
```

### `allow`

Add an ALLOW rule.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai permissions allow "bash:git *" --description "Allow git"
```

| Option          | Type   | Default    | Description                     |
| --------------- | ------ | ---------- | ------------------------------- |
| `--agent`       | string | all agents | Scope rule to one agent         |
| `--description` | string | auto       | Human-readable label            |
| `--priority`    | int    | `100`      | Higher values are checked first |

### `deny`

Add a DENY rule.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai permissions deny "bash:rm *" --priority 200
```

| Option          | Type   | Default    | Description                     |
| --------------- | ------ | ---------- | ------------------------------- |
| `--agent`       | string | all agents | Scope rule to one agent         |
| `--description` | string | auto       | Human-readable label            |
| `--priority`    | int    | `100`      | Higher values are checked first |

### `ask`

Add an ASK rule (always prompt).

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai permissions ask "bash:*" --agent researcher
```

| Option          | Type   | Default    | Description                     |
| --------------- | ------ | ---------- | ------------------------------- |
| `--agent`       | string | all agents | Scope rule to one agent         |
| `--description` | string | auto       | Human-readable label            |
| `--priority`    | int    | `50`       | Higher values are checked first |

### `remove`

Remove a rule by ID prefix (from `list` output).

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai permissions remove a1b2c3d4
```

### `reset`

Delete all rules and approvals (requires confirmation).

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai permissions reset
```

### `export`

Print rules as JSON to stdout.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai permissions export > rules.json
```

### `import`

Import rules from a JSON file.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai permissions import rules.json
```

## Rule patterns

Patterns use `tool_name:argument_pattern` glob syntax:

| Pattern                | Matches                                                                                                                                               |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bash:git *`           | All git bash commands                                                                                                                                 |
| `bash:ls *`            | ls commands                                                                                                                                           |
| `read:*`               | All read tool calls — does not authorise `.env`/private keys — see [Secret-File Read Gate](/docs/docs/features/permissions#built-in-secret-file-read-gate) |
| `read:*.env`           | `.env` reads — required to opt in past the [Secret-File Read Gate](/docs/docs/features/permissions#built-in-secret-file-read-gate)                         |
| `read:*.pem`           | Reads of PEM private keys — gated by default                                                                                                          |
| `read:id_rsa`          | Reads of SSH private keys — gated by default                                                                                                          |
| `write:*.env`          | Writes to `.env` files                                                                                                                                |
| `write:/etc/*`         | Truncating redirections to `/etc/` (e.g. `cat foo > /etc/hosts`)                                                                                      |
| `external_dir:/data/*` | Access to `/data/` when `workspace_root` is set                                                                                                       |
| `external_dir:*`       | All out-of-workspace access (use with deny to hard-block)                                                                                             |

### external\_dir: patterns

When `workspace_root` is set on `PermissionManager`, any path that resolves outside the root emits an `external_dir:<parent>/*` sub-target defaulting to **ask**. Use the CLI to pre-authorise or hard-block these:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Allow a specific external data directory
praisonai permissions allow "external_dir:/data/*" --description "Shared data volume"

# Hard-block all out-of-workspace access (no prompt, immediate deny)
praisonai permissions deny "external_dir:*" --description "Lock down external filesystem"
```

See [Workspace Boundary](/docs/features/workspace-boundary) for full details on what triggers the gate and how to configure it.

### Opt in to reading `.env`

Reading `.env`/private keys defaults to **ask** even with a broad `read:*` allow. Teams who genuinely need credential-file reads opt in with a secret-specific rule:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Allow reading .env files (secret-specific — a broad read:* won't do)
praisonai permissions allow "read:*.env" --description "CI reads .env"
```

<Warning>
  Allowing `read:*.env` lets an agent forward the contents of `.env` to the model provider. Only opt in for trusted CI/workflows, and prefer a persistent approval or per-agent scope over a project-wide rule. See [Secret-File Read Gate](/docs/docs/features/permissions#built-in-secret-file-read-gate).
</Warning>

<Note>
  Compound shell commands (`&&`, `;`, `|`, subshells, `$(...)`) are decomposed and each operation is checked against your rules. A `deny` on `bash:rm *` blocks `cd /tmp && rm -rf x` and `echo $(rm -rf x)`. See [Command-Aware Permissions](/docs/features/command-aware-permissions).
</Note>

When you choose `[a] always`, the CLI auto-generates a scoped pattern — for example `bash:git status *` for a git subcommand, or `tool:<tool_name>` as the default.

## Project storage

Rules and session approvals are stored under the current working directory:

| File                                    | Purpose                         | Commit to git?         |
| --------------------------------------- | ------------------------------- | ---------------------- |
| `.praisonai/permissions/rules.json`     | Persistent allow/deny rules     | Yes — share team rules |
| `.praisonai/permissions/approvals.json` | Per-developer session approvals | No — local only        |

<Note>
  Rules can also be declared directly in `.praisonai/config.yaml` under the `permissions:` key — no CLI commands needed. Both approaches are fully supported and can be used together. See [Single-Source Config](/docs/features/single-source-config) and [Declarative Permissions](/docs/features/declarative-permissions) for details.
</Note>

## Best practices

<AccordionGroup>
  <Accordion title="Commit rules.json for team alignment">
    Share `.praisonai/permissions/rules.json` so everyone gets the same allow/deny defaults.
  </Accordion>

  <Accordion title="Never use bypass in production">
    `--approval bypass` skips every check. Reserve it for fully trusted local sandboxes.
  </Accordion>

  <Accordion title="Use plan for exploration">
    `--approval plan` blocks writes and shell commands while you inspect a codebase.
  </Accordion>

  <Accordion title="Broaden patterns with wildcards">
    Use `bash:git *` instead of one-off rules so related commands stay covered.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Single-Source Config" icon="gear" href="/docs/features/single-source-config">
    Declare permissions in .praisonai/config.yaml
  </Card>

  <Card title="Command-Aware Permissions" icon="shield-halved" href="/docs/features/command-aware-permissions">
    Compound command decomposition and evasion blocking
  </Card>

  <Card title="Declarative Permissions" icon="shield-halved" href="/docs/features/declarative-permissions">
    All permission surfaces — YAML, CLI, Python
  </Card>

  <Card title="Interactive Tool Approval" icon="shield-check" href="/docs/features/interactive-approval">
    User-facing approval experience
  </Card>

  <Card title="Permission Modes" icon="shield" href="/docs/features/permission-modes">
    Mode reference for agents and CLI
  </Card>

  <Card title="Workspace Boundary" icon="shield-halved" href="/docs/features/workspace-boundary">
    Gate shell and file access outside your project root
  </Card>
</CardGroup>
