Permission mode
ProThe agent's permission mode, with what each mode lets it do written out, and a way to change it. Modes that hand decisions away from the person (allow everything, a classifier) ask "Switch to …?" first. A mode your policy fixes is locked and says why. The mode shown is the one the agent last reported, never the one just picked: while the change is on its way the switcher says so, and a mode that wasn't reported reads "Not reported".
Preview
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/permission-mode
Brings in: button, locale, locked, popover, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import * as React from "react"
import { PermissionMode } from "@/components/permission-mode"
export default function Example() {
// The mode shown is the one the agent reports; here the "agent" reports the change after a moment.
const [mode, setMode] = React.useState("default")
const [pending, setPending] = React.useState(false)
const change = (next: string) => {
setPending(true)
setTimeout(() => (setMode(next), setPending(false)), 600)
}
return (
<div className="flex max-w-md flex-col gap-6">
<PermissionMode mode={mode} pending={pending} onChange={change} modes={[{ id: "default" }, { id: "acceptEdits" }, { id: "plan" }, { id: "auto" }, { id: "bypassPermissions", locked: "Your workspace’s policy turns this off." }]} />
<PermissionMode variant="compact" mode={mode} pending={pending} onChange={change} />
</div>
)
}<PermissionMode>
| Prop | Type | Default | Description |
|---|---|---|---|
| mode | string | undefined | — | The mode the agent last reported. Undefined while it hasn't said. |
| modes | PermissionModeOption[] | undefined | builtIn.map((id) => ({ id })) | The modes to offer, in order. Defaults to the six SDK modes. |
| onChange | ((mode: string) => void) | undefined | — | Asks for a change. Show the new mode once the agent reports it (`mode`). |
| pending | boolean | undefined | false | A change is on its way. |
| error | string | undefined | — | Why the last change failed, if it did. Pass "" for no reason. |
| locked | string | undefined | — | Why the mode can't be changed at all here: a policy, a role. |
| variant | "list" | "compact" | undefined | "list" | "list" shows every mode with its consequences; "compact" is a button that opens the list, for a toolbar. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under permissionMode in <LocaleProvider strings={{ … }}>; the table is exported as permissionModeStrings.
| Key | English |
|---|---|
| label | Permission mode |
| current | Permission mode: {mode} |
| default | Ask before acting |
| defaultDetail | The agent asks before anything a rule doesn’t already allow. |
| acceptEdits | Accept file edits |
| acceptEditsDetail | File edits in the project and simple file commands run without asking. Anything else still asks. |
| plan | Plan only |
| planDetail | The agent reads and plans. It changes nothing until you approve the plan. |
| auto | Automatic |
| autoDetail | A classifier allows or blocks each action instead of you. It can be wrong, and you’re not asked. |
| dontAsk | Don’t ask |
| dontAskDetail | Nothing asks you: what a rule doesn’t already allow is denied. |
| bypassPermissions | Allow everything |
| bypassPermissionsDetail | Nothing is checked. The agent can run any command and change or delete any file it can reach. |
| confirmTitle | Switch to “{mode}”? |
| confirm | Switch |
| cancel | Keep “{mode}” |
| changing | Changing… |
| failed | The mode didn’t change: {reason} |
| failedNoReason | The mode didn’t change. |
| unknown | Not reported |
Types
- PermissionModeOption
- A mode the switcher offers. The six SDK modes have built-in words; your own need `label` and `detail`.
{ /** The mode's name as the agent knows it: "default", "acceptEdits", "plan", "auto", "dontAsk", "bypassPermissions". */ id: string label?: string | undefined /** What the agent may do in this mode, in a sentence. */ detail?: string | undefined /** Why this mode can't be chosen here, e.g. "Your organisation's policy turns this off." */ locked?: string | undefined /** Ask "Switch to …?" before cha