> ## Documentation Index
> Fetch the complete documentation index at: https://better-duck.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Capabilities & Permissions

> Grant the webview access to plugin commands through Tauri capability files: the default and raw-sql sets, every autogenerated allow-/deny- identifier, scoped permission objects, and how the list is generated.

The first security gate is Tauri's capability system: a capability file grants a window the right to
invoke specific plugin commands. This page lists the exact permission identifiers and how to wire
them. For the model behind it, see [Security overview](/tauri/security-overview).

## Permission sets

The plugin ships two named sets:

| Identifier | Expands to | In default? |
| - | - | - |
| `better-duck-tauri:default` | `allow-load` + `allow-close` + `allow-select` | — (it *is* the default) |
| `better-duck-tauri:allow-raw-sql` | `allow-select` + `allow-execute` | No — opt in explicitly |

<Note>
  The **default set is read-only**: open/close a connection and run `select`. Writes (`execute`) and
  the raw-SQL umbrella are deliberately excluded, because the webview is untrusted and DuckDB SQL
  can reach the filesystem and network. Grant them explicitly only where needed.
</Note>

## Every command permission

Each command has an autogenerated `allow-<command>` and `deny-<command>` permission. Note the
identifiers are **hyphenated** — the underscore in a command name like `load_extension` becomes
`allow-load-extension`.

| Command | Allow | Deny |
| - | - | - |
| `load` | `better-duck-tauri:allow-load` | `better-duck-tauri:deny-load` |
| `close` | `better-duck-tauri:allow-close` | `better-duck-tauri:deny-close` |
| `select` | `better-duck-tauri:allow-select` | `better-duck-tauri:deny-select` |
| `execute` | `better-duck-tauri:allow-execute` | `better-duck-tauri:deny-execute` |
| `load_extension` | `better-duck-tauri:allow-load-extension` | `better-duck-tauri:deny-load-extension` |
| `import` | `better-duck-tauri:allow-import` | `better-duck-tauri:deny-import` |
| `export` | `better-duck-tauri:allow-export` | `better-duck-tauri:deny-export` |
| `append_rows` | `better-duck-tauri:allow-append-rows` | `better-duck-tauri:deny-append-rows` |
| `tables` | `better-duck-tauri:allow-tables` | `better-duck-tauri:deny-tables` |
| `columns` | `better-duck-tauri:allow-columns` | `better-duck-tauri:deny-columns` |
| `explain` | `better-duck-tauri:allow-explain` | `better-duck-tauri:deny-explain` |
| `stream` | `better-duck-tauri:allow-stream` | `better-duck-tauri:deny-stream` |
| `checkpoint` | `better-duck-tauri:allow-checkpoint` | `better-duck-tauri:deny-checkpoint` |
| `interrupt` | `better-duck-tauri:allow-interrupt` | `better-duck-tauri:deny-interrupt` |
| `revert` | `better-duck-tauri:allow-revert` | `better-duck-tauri:deny-revert` |
| `query_arrow` | `better-duck-tauri:allow-query-arrow` | `better-duck-tauri:deny-query-arrow` |

<Tip>
  `allow-query-arrow` corresponds to the `query_arrow` command, which only exists with the
  [`arrow` feature](/tauri/arrow). Granting it without the feature compiled in is harmless — the
  command returns a backend error.
</Tip>

## Writing a capability file

Capabilities live in `src-tauri/capabilities/*.json` and are compiled in by `tauri-build`. A
permission entry is either a bare identifier string or an object that also attaches a
[scope](/tauri/scope-and-policy):

```json theme={null}
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "Grants the main window the better-duck commands, with a connection and path scope.",
  "windows": ["main"],
  "permissions": [
    "core:default",
    { "identifier": "better-duck-tauri:allow-load", "allow": [{ "connection": "duckdb::memory:" }] },
    "better-duck-tauri:allow-close",
    "better-duck-tauri:allow-select",
    "better-duck-tauri:allow-execute",
    "better-duck-tauri:allow-append-rows",
    "better-duck-tauri:allow-tables",
    "better-duck-tauri:allow-columns",
    "better-duck-tauri:allow-explain",
    "better-duck-tauri:allow-checkpoint",
    { "identifier": "better-duck-tauri:allow-import", "allow": [{ "path": "data/" }] },
    { "identifier": "better-duck-tauri:allow-export", "allow": [{ "path": "data/" }] }
  ]
}
```

This is the [example app](/tauri/overview)'s capability. It grants the write and introspection
commands and scopes `load` to `duckdb::memory:` and import/export to the `data/` directory.

<Note>
  The scope object (`"allow"` / `"deny"` arrays of `{ connection, path }` entries) is the second
  gate. A bare identifier string grants the command with **no** scope narrowing, leaving the value
  constraints to the init-time [`Policy`](/tauri/scope-and-policy). See
  [Scope & Policy](/tauri/scope-and-policy) for the entry semantics.
</Note>

## How the list is generated

The command list is declared once in the crate's `build.rs` and handed to the Tauri plugin
permission tooling, which auto-generates the `allow-*` / `deny-*` permissions and the reference:

```rust theme={null}
// build.rs (crate side)
const COMMANDS: &[&str] = &[
    "load", "close", "select", "execute", "load_extension", "import", "export",
    "append_rows", "tables", "columns", "explain", "stream", "checkpoint",
    "interrupt", "revert", "query_arrow",
];

fn main() {
    tauri_plugin::Builder::new(COMMANDS)
        .global_scope_schema(schemars::schema_for!(scope::Entry))
        .build();
}
```

The same `build.rs` registers the [scope `Entry`](/tauri/scope-and-policy) schema, so capability
files get autocompletion and validation for the `connection` / `path` fields.

## See also

* [Scope & Policy](/tauri/scope-and-policy) — the value-level gate attached to these permissions.
* [Security overview](/tauri/security-overview) — why writes and raw SQL are opt-in.
* [Registration](/tauri/registration) — granting permissions is separate from registering the plugin.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.