# Permission prompt
> Agent permission prompt: a scan runs over the command, a risk meter fills, and Allow once, Always allow or Deny settles it.
- Element: `<hf-approve>`
- React: `import { HfApprove } from "@/components/lumesec/hf-approve"`
- Collection: Pixel HD (https://elements.lumesec.ai/components/pixel-hd)
- Registry item: https://elements.lumesec.ai/r/hf-approve.json
- Page: https://elements.lumesec.ai/components/pixel-hd/approve



Live preview: https://elements.lumesec.ai/view/hf-approve

```html
<hf-approve></hf-approve>
```

## Installation

```bash
npx shadcn@latest add @lumesec/hf-approve
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/hf-approve.json
```

## Usage

React:

```tsx
import { HfApprove } from "@/components/lumesec/hf-approve";

export function Example() {
  return (
    <HfApprove />
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/hf-approve.js"></script>

<hf-approve></hf-approve>
```

## Behaviour

A scan runs across the command, then a risk meter fills. High-risk commands can’t be always-allowed. Deciding sweeps the card green or fills it with red static. Keys 1–3 answer.

## API reference

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event      | React prop   | Detail                                                                      | Description                                                                                                        |
| ---------- | ------------ | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `decision` | `onDecision` | `{ decision: 'once' \| 'always' \| 'deny', tool: string, command: string }` | Fires when a choice is made by click or by keys 1 to 3. `command` is the full command text of the current request. |

### Methods

Call them on the element, for example through a React ref.

| Method                                                                                               | Description                                                                                                                                                                            |
| ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request(o: { tool: string; title: string; cmd: string; why: string; risk: 1 \| 2 \| 3 \| 4 \| 5 })` | Shows a new request (`HApproveRequest`; `risk` is `HApproveRisk`). Risk 1–2 is Low, 3 Medium, 4 High, 5 Critical. At 4 and above, Always allow is disabled from the start of the scan. |
| `next()`                                                                                             | Shows the next of the four built-in demo requests and focuses Allow once.                                                                                                              |

## Keyboard

| Keys | Action                                               |
| ---- | ---------------------------------------------------- |
| 1    | Allow once.                                          |
| 2    | Always allow. Ignored while that button is disabled. |
| 3    | Deny.                                                |

## Accessibility

* The card has `role="alertdialog"` and is labelled by its title.
* Actions are native buttons that show their shortcut in a `<kbd>`; they are disabled once a decision is made.
* The shortcuts listen on the document and act while the pointer is over the card or focus is inside it. They are ignored in text fields and with Ctrl or Meta held.
* After a decision, the buttons are replaced by a result row with a Next request button; focus is not moved there.
* The risk level and the result are not live regions. The scan and meter are drawn on an `aria-hidden` canvas.
* Reduced motion: the scan sweep is skipped and the risk shows at once, the meter fills without easing or pulsing, and the result row appears without the green sweep or red static.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--border`, `--card`, `--foreground`, `--lumesec`, `--lumesec-foreground`, `--muted` and `--muted-foreground`.

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-border`, `--ui-fg`, `--ui-mono`, `--ui-muted`, `--ui-on-accent`, `--ui-raised`, `--ui-surface` and `--ui-track`.

## Notes

* Starts with the first of four built-in demo requests; call `request()` to show your own.
* The risk level appears 1.1 s after a request is shown. For risk 4 and 5, Always allow is disabled as soon as the request is shown, so it cannot be chosen during the scan.
* The component does not run or block anything; act on `decision`.


