Skip to main content

A unified keybinding cheatsheet generated from your configs — which-key for your whole machine

Project description

rune

ci

One keybinding cheatsheet for your whole machine, generated from your configs.

which-key is great inside one program. rune is for the stack around it: tmux, Neovim, your shell, your terminal, your window manager, Git aliases, and the little binds you forget until you need them.

A hand-kept cheatsheet (a gist, a wiki page, a sticky note) drifts the moment you change a config. rune regenerates from the configs themselves, so it's never out of date. It also does two things a static sheet can't: doctor finds conflicts across tools — a window-manager chord silently eating a Neovim mapping — and the chord normalizer makes wildly different spellings comparable (cmd-alt-ctrl-shift-h, hyper+h, ^A, <C-w> are all the same kind of thing to rune).

rune show                 # interactive terminal cheatsheet
rune doctor               # find duplicate and shadowed chords
rune which cmd-h          # where is this bound?
rune export --html k.html # self-contained cheatsheet + keyboard page
rune build -o keys.json   # JSON for another renderer, such as sigil

rune demo: show, doctor, which

Install

pipx install rune-cheatsheet

From a clone:

pip install -e .

rune is pure Python 3.11+ and uses the standard library only.

Shell completions

rune completions {bash,zsh,fish} prints a completion script — subcommands, flags, and even extract's tool names — generated from rune's own parser, so it can't drift out of sync.

# bash — add to .bashrc
source <(rune completions bash)

# zsh — either eval it directly in .zshrc...
source <(rune completions zsh)
# ...or write it to a file on fpath (needs autoload -Uz compinit && compinit)
rune completions zsh > ~/.zfunc/_rune

# fish — add to config.fish
rune completions fish | source

Platforms

macOS and Linux are first-class — most extractors target tools native to one or the other (AeroSpace/Hammerspoon/skhd vs. Sway/Hyprland), and each fails soft when its tool isn't there. Run rune extractors --check to see what's live on your machine. On Windows, build, export, and doctor work; rune show falls back to plain text instead of the curses UI.

Quick Start

rune init
rune show

rune init writes a small rune.toml. rune show reads it, extracts bindings, and opens a terminal UI. Press k in the UI for the keyboard view.

No config yet? rune show still tries common tools so you can see whether it is useful before wiring anything up.

What It Reads

rune can read bindings in two ways. Mix them freely.

Native Extractors

These read real bindings with no annotation:

[[extract]]
tool = "tmux"

[[extract]]
tool = "git"

[[extract]]
tool = "nvim"
path = "~/.config/nvim/lua/keymaps.lua"

Current extractors include tmux, Git aliases, zsh, bash, fish, Neovim, WezTerm, Ghostty, Kitty, Alacritty, Helix, VS Code, AeroSpace, Hammerspoon, skhd, Vim, Sway, Hyprland, readline, and Emacs.

Check what works on your machine:

rune extractors --check

Inline Annotations

Use annotations when you want the description to be yours:

# @rune section Windows
# @rune family  system
# @rune row     caps + h :: focus left
# @rune row     caps + l :: focus right
# @rune end
cmd-alt-ctrl-shift-h = "focus left"
cmd-alt-ctrl-shift-l = "focus right"

@rune is the current marker. The old @cs marker still works.

If an extractor and an annotation produce the same section, the annotation wins. Extraction gives coverage; annotations give taste and authority.

A path containing *, ?, or [ is treated as a glob and expands to one annotation source per match (path = "~/.config/nvim/lua/keymaps/*.lua").

Example Config

[[extract]]
tool = "tmux"

[[extract]]
tool = "git"

[[annotate]]
path = "~/.config/aerospace/aerospace.toml"

[[view]]
id = "term"
label = "Terminal"
key = "1"
columns = [["tmux-prefix"], ["git-aliases"], []]

There is a fuller example at examples/dotfiles.rune.toml.

Output

  • rune show opens a terminal cheatsheet with search and a keyboard view.
  • rune export --html keys.html writes one portable HTML page.
  • rune export --md keys.md writes Markdown for docs or a wiki.
  • rune build -o keys.json writes the stable JSON contract.
  • rune list writes a flat TSV, one row per chord: key, action, section, source.

rune list is the fzf/grep/awk surface — no nested JSON to unwrap:

rune list | fzf

Filtering (the TUI's / search and every --filter flag) is substring or subsequence — "wndwfcs" finds "window focus" even with the spaces dropped and half the letters skipped.

The HTML and TUI keyboard views show physical keys by modifier layer. That makes used chords and free chords visible at a glance. The layout assumes an ANSI US-QWERTY physical keyboard for now.

Conflicts

rune doctor

doctor looks for:

  • duplicates: the same chord bound twice in the same context
  • shadows: an outer layer catches a chord before an inner layer can see it

For example, a window-manager binding can shadow a terminal, tmux, shell, or editor binding. Modal bindings such as tmux prefix maps and Vim leader maps are handled separately so intentional layers do not look like bugs.

Sample output, from a skhd config with a repeated binding and a chord that also lives in zsh:

analyzed 4 chord(s) across 2 context(s): skhd, zsh

duplicate (one silently wins):
  ⚠ cmd+h bound 2× in skhd — one silently wins
      skhd               yabai -m window --focus west   ← extractor:skhd
      skhd               yabai -m window --focus west   ← extractor:skhd

shadow (outer layer eats the key):
  ⚠ ctrl+h: skhd grabs it before zsh ever sees it
      skhd               yabai -m window --focus west   ← extractor:skhd
      zsh                backward delete char   ← extractor:zsh

2 conflict(s).

doctor's exit code is the conflict count, so it wires straight into CI or a pre-commit hook.

Before binding a new chord, check whether it's already taken:

rune which cmd-h

which looks up a chord across every tool rune knows about and prints every binding it finds, using the same normalizer as doctor — so cmd-h and ⌘h find the same match. It exits 0 if the chord is bound and 1 if it's free, so it also works as a script check.

sigil

rune owns the data and its own renderers (TUI, HTML, Markdown); rune build emits a stable JSON contract that other tools can consume too. sigil is one such consumer — a native macOS HUD that reads that JSON and renders it as an overlay. Nothing about the contract is macOS- or sigil-specific; any renderer of the JSON works the same way.

(rune's keyboard-cheatsheet feature started life inside sigil and was later pulled out to stand on its own.)

Status

v0.1. The JSON shape is intended to be stable. Extractors are best effort. Annotate anything you want to be exact, polished, or personal.

For internals and maintenance notes, read docs/GUIDE.md.

Authorship

This project and its docs were written with AI assistance. Care was taken to keep the code and explanations readable by both humans and AI agents: short sections, direct examples, stable names, and comments where they earn their place.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rune_cheatsheet-0.1.0.tar.gz (55.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rune_cheatsheet-0.1.0-py3-none-any.whl (53.4 kB view details)

Uploaded Python 3

File details

Details for the file rune_cheatsheet-0.1.0.tar.gz.

File metadata

  • Download URL: rune_cheatsheet-0.1.0.tar.gz
  • Upload date:
  • Size: 55.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rune_cheatsheet-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2ad337016e3b14dd0d6565179ef1f5105a2f5a20e394ecb154398d7eb4adcd90
MD5 e060fade665c9dfcae0d6904e54b829f
BLAKE2b-256 d33e0cad0b87c5906cb9bfe42e827fcaa8abe3110c117ac0955f2ba3071745fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for rune_cheatsheet-0.1.0.tar.gz:

Publisher: release.yml on adames/rune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rune_cheatsheet-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for rune_cheatsheet-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7501bf3300479cdc3c43f978330753b21376f8a39261e3a7ae4a69e1c95fc7e7
MD5 f908ea404457a998e556b4c25e8fb64f
BLAKE2b-256 68b73190676ab194852bbbc2964cf8023214874268db32c6a9aed6562fab9ee0

See more details on using hashes here.

Provenance

The following attestation bundles were made for rune_cheatsheet-0.1.0-py3-none-any.whl:

Publisher: release.yml on adames/rune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page