llm-wiki — action_menu knowledge bundle
Bundle OKF 1.0 · 7 conceitos · olispeedy/kitty-action-menu
Open source Repository Open in the app JSON README (API)
About
# llm-wiki — action_menu knowledge bundle
An [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
bundle of curated knowledge about the `action_menu` kitty kitten: how it's built,
the kitty-API gotchas learned the hard way, reusable playbooks, and the reasoning
behind past decisions. Written to be useful to both humans and coding agents.
For behavioral rules on _how to work in this repo_, see
[`/AGENTS.md`](/AGENTS.md). This bundle holds the _why_ and the _experience_.
## Kitten
- [action_menu architecture](/llm-wiki/kitten/architecture.md) - how the kitten is split across the overlay UI and the boss process.
## Gotchas
- [State is not available at menu-draw time](/llm-wiki/gotchas/state-at-draw-time.md) - why context-aware entry greying can't be done reliably.
- [Bundled Python has no pip packages](/llm-wiki/gotchas/bundled-python-no-pip.md) - use kitty's own APIs, not PyPI (the wcwidth lesson).
- [allow_remote_control adds a cr
Details
- Kind
- OKF bundles
- Topic
- AI, RAG & memory
- Publisher
- olispeedy
- Origin
- okf_github
- Category
- dados
- Version
- 1.0
- Stars
- 1
- Last push
- 2026-07-27T08:19:57Z
- Repository state
- ativo
- Language
- Python
- License
- GPL-3.0
- Added
- 2026-09-08 22:08:51
- Updated
- 2026-09-08 22:08:51
- Origin id
olispeedy/kitty-action-menu:llm-wiki/index.md
README
# kitty-action-menu
[](LICENSE)



[](https://github.com/olispeedy/kitty-action-menu/stargazers)
[](https://github.com/olispeedy/kitty-action-menu/issues)
[](https://github.com/olispeedy/kitty-action-menu/commits/main)
A pop-up action menu kitten for the [kitty terminal emulator](https://github.com/kovidgoyal/kitty).
It shows an overlay list of handy actions — copy selection, copy link/path,
paste, new tab, split, close — driven entirely by kitty's kitten API. It can be
opened by a right-click, but just as well by a keyboard shortcut or any other
kitty mapping.
<img src="assets/action_menu.png" alt="The action menu rendered in kitty" width="420">
## Motivation
Other graphical terminals — [Konsole](https://konsole.kde.org/),
[GNOME Terminal](https://help.gnome.org/users/gnome-terminal/stable/), and
[Windows Terminal](https://github.com/microsoft/terminal), etc. — pop up a
context menu on right-click. Coming to kitty, that familiar gesture was
missing. A _true_ context-sensitive menu (entries that change depending on what
is under the cursor) turns out to be tricky in kitty, but having a small set of
useful default actions one click (or keypress) away is already a nice
quality-of-life win.
So this kitten is deliberately **not** dynamic: it isn't a real context menu, it
just _looks_ a bit like one. The entries are a fixed list of the actions I found
useful for myself. It's easy to edit that list (see the `MENU` table in
`config/user/action_menu.py`) to fit your own workflow.
## Install
Copy the kitten into your kitty config directory:
```sh
cp config/user/action_menu.py ~/.config/kitty/action_menu.py
```
Then bind right-click in `~/.config/kitty/kitty.conf`:
```conf
mouse_map right press ungrabbed kitten action_menu.py
```
Reload the config (`ctrl+shift+f5` on Linux, `cmd+ctrl+,` on macOS) and
right-click in a window.
To troubleshoot, append the optional `--debug-action-menu` flag to the binding
(see [Testing & debugging](#testing--debugging)).
## Requirements
- [kitty](https://github.com/kovidgoyal/kitty) (uses its bundled Python and kitten API)
## Testing & debugging
The kitten accepts an optional `--debug-action-menu` flag that makes it emit
trace output. Add it to your binding while troubleshooting:
```conf
mouse_map right press ungrabbed kitten action_menu.py --debug-action-menu
```
To see that output you have to launch kitty **from another terminal**, so its
stdout/stderr is visible:
```sh
# from any other terminal (e.g. macOS Terminal.app, or another kitty window)
kitty
```
Then right-click in the new kitty window and pick menu entries. You'll see
lines like:
```
debug[actionmenu]: --- Kitten action_menu started ---
debug[actionmenu]: Args: ['action_menu.py', '--debug-action-menu']
debug[actionmenu]: on_mouse_event(): type=EventType.PRESS buttons=1 cell=(13,4) pixel=(109,77)
debug[actionmenu]: on_mouse_event(): type=EventType.RELEASE buttons=1 cell=(13,4) pixel=(109,77)
print[actionmenu]: handle_result: answer=3 target=1, dbg_enabled: False, forced: True
print[actionmenu]: menu entry: Paste from Clipboard (paste_clip), dbg_enabled: False, forced: True
print[actionmenu]: sel_before='' selection_nonempty=False, dbg_enabled: False, forced: True
print[actionmenu]: schedule_remote(): called ('action', '--match=id:1', 'paste_from_clipboard'), dbg_enabled: False, forced: True
```
Reading the output:
- `debug[actionmenu]:` — messages routed through kitty's `debug()` (UI/event
logic inside the overlay).
- `print[actionmenu]:` — messages forced to stdout (`force_print=True`), used in
`handle_result` and scheduled callbacks so they show up even when a launcher
swallows `debug()`.
- `on_mouse_event()` lines show the raw event `type`, `buttons` bitmask, and the
`cell`/`pixel` coordinates of the click — useful for diagnosing hit-testing.
- `handle_result: answer=N` is the 0-based index of the chosen `MENU` entry;
`answer=8` here is _Cancel_.
- `sel_before=` / `selection_nonempty=` shows the active selection captured
before the action ran (relevant for _Copy Selection_).
- `schedule_remote(): called (...)` / `combined action:` shows the actual kitty
remote-control call or `boss.combine(...)` invocation dispatched for the entry.
Tips:
- If nothing appears, confirm the binding actually passes `--debug-action-menu`
and that you launched kitty from a terminal (not via the app icon).
- A `WARNING: ... glCopyImageSubData` line from kitty is unrelated to this
kitten — it's a GPU/OpenGL notice and can be ignored.
- `tests/test_mouse.py` is a standalone kitten that just echoes raw mouse/key
events — handy for checking coordinates and event types in isolation. Bind it
to a key in `kitty.conf` to run it (it can't be launched from a `mouse_map`),
then press the key and click around; Esc quits:
```conf
map kitty_mod+t kitten tests/test_mouse.py
```
(`kitty_mod` defaults to `ctrl+shift` unless you've changed it.)
## Documentation
In-depth design notes, kitty-API gotchas, and how-tos live in the
[**`llm-wiki/`**](llm-wiki/index.md) knowledge bundle — an
[Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
corpus written to be useful to both humans and coding agents. It renders here on
GitHub (mermaid diagrams included).
## Repository layout
| Path | Purpose |
| ---------------------------- | ----------------------------------------------------- |
| `config/user/action_menu.py` | The kitten (mirrors the `~/.config/kitty/` layout) |
| `llm-wiki/` | OKF knowledge bundle: design, gotchas, how-tos |
| `tests/` | Standalone kittens for probing mouse/key events |
| `assets/` | Screenshots and other media |
| `.archive/` | Earlier AI-generated code/doc variants, for reference |
| `AGENTS.md` | Instructions for AI agents working on this repo |
## Ideas / roadmap
- **User-configurable menu entries.** Right now the `MENU` list is hard-coded in
`action_menu.py`. It would be nicer to define entries in a config file (or in
`kitty.conf`) so users don't have to edit the source. A more ambitious version
would let you _build_ the menu interactively — pick which actions to include
from a chooser, similar to kitty's built-in **command palette** kitten
(`kitten @ ...` / the `show_command_palette` action) — and persist the
selection.
- **Per-entry enable/disable based on state** (e.g. grey out _Copy Selection_
when there is no selection). This was attempted but **doesn't work reliably**:
the menu is drawn in a separate overlay process before an action is chosen, and
trustworthy selection / link / path state is only available later in
`handle_result()`. The renderer supports a `disabled` flag, but there's no
dependable way to compute it at draw time — see
[the llm-wiki gotcha](llm-wiki/gotchas/state-at-draw-time.md) for the details. It would likely need upstream kitty support to pass the
click-target window state into the kitten.
## A note on AI assistance
This kitten was developed with the help of AI coding assistants, but every
feature was **tested by hand** in a real kitty session before being committed.
The AI-generated variants that didn't make the cut are kept in
[`.archive/`](.archive/) for reference.
## License
GPL v3. See [LICENSE](LICENSE).