v0.2.31 85a3c3b

README.md RawHistoryFolder

approve — example zot extension

Demonstrates the spontaneous open_panel pattern: an extension-registered tool opens a panel from inside its handler goroutine, blocks until the user responds, then returns the result to the model.

What it does

Registers one LLM-callable tool:

approve_action(action, reason?)

When the model calls it, a panel appears in the TUI:

╭─ Approval required ─────────────────────╮
│  Action:  delete /tmp/build              │
│  Reason:  cleaning up after the build    │
│                                          │
│    y  approve      n / esc  deny         │
╰──────────────────────────────────────────╯
  y approve  n deny  esc cancel

The model's tool call is held open until the user presses a key. The model receives "approved" or "denied: user rejected the action" as the tool result and replies accordingly.

Build

cd examples/extensions/approve
go build -o approve .

Install

zot ext install .

Try it

In zot, ask:

Request approval to delete the temp directory.

The model calls approve_action; the panel opens. Press y to approve, n or esc to deny.

Ask me to approve before running any destructive command.

The model will start calling approve_action before suggesting risky steps; each call pauses until you respond.

Key points

  • The tool handler calls e.OpenPanel(...) directly — no slash command needed.
  • A chan bool bridges the panel key handler back to the blocked tool goroutine; nothing in the wire protocol changes.
  • Panel IDs are unique per call so multiple concurrent approvals don't collide (rare in practice, but handled correctly).
  • The onClose callback on OnPanelKey handles the case where the user dismisses the panel from the TUI border rather than pressing a key, treating it as a denial.

See also

  • examples/extensions/secret — same pattern with masked text input (credential collection)
  • examples/extensions/guard — blocks dangerous tool calls via interception (no panel)
  • docs/extensions.md — full protocol reference
source
1# approve — example zot extension
2
3Demonstrates the **spontaneous `open_panel`** pattern: an
4extension-registered tool opens a panel from inside its handler
5goroutine, blocks until the user responds, then returns the result to
6the model.
7
8## What it does
9
10Registers one LLM-callable tool:
11
12```
13approve_action(action, reason?)
14```
15
16When the model calls it, a panel appears in the TUI:
17
18```
19╭─ Approval required ─────────────────────╮
20│  Action:  delete /tmp/build              │
21│  Reason:  cleaning up after the build    │
22│                                          │
23│    y  approve      n / esc  deny         │
24╰──────────────────────────────────────────╯
25  y approve  n deny  esc cancel
26```
27
28The model's tool call is held open until the user presses a key. The
29model receives `"approved"` or `"denied: user rejected the action"` as
30the tool result and replies accordingly.
31
32## Build
33
34```bash
35cd examples/extensions/approve
36go build -o approve .
37```
38
39## Install
40
41```bash
42zot ext install .
43```
44
45## Try it
46
47In zot, ask:
48
49> Request approval to delete the temp directory.
50
51The model calls `approve_action`; the panel opens. Press **y** to
52approve, **n** or **esc** to deny.
53
54> Ask me to approve before running any destructive command.
55
56The model will start calling `approve_action` before suggesting risky
57steps; each call pauses until you respond.
58
59## Key points
60
61- The tool handler calls `e.OpenPanel(...)` directly — no slash command
62  needed.
63- A `chan bool` bridges the panel key handler back to the blocked tool
64  goroutine; nothing in the wire protocol changes.
65- Panel IDs are unique per call so multiple concurrent approvals don't
66  collide (rare in practice, but handled correctly).
67- The `onClose` callback on `OnPanelKey` handles the case where the
68  user dismisses the panel from the TUI border rather than pressing a
69  key, treating it as a denial.
70
71## See also
72
73- `examples/extensions/secret` — same pattern with masked text input
74  (credential collection)
75- `examples/extensions/guard` — blocks dangerous tool calls via
76  interception (no panel)
77- `docs/extensions.md` — full protocol reference

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close