Config-driven parser for keybindings with fzf interface
Project description
confhelp
Find and edit your keybindings instantly.
The Problem
Over time you accumulate tmux bindings, zsh aliases, vim mappings, custom functions - scattered across dozens of files. You know you set something up, but where?
Two pain points:
- Finding bindings - "What key did I bind for git status?" "Do I have an alias for docker compose?"
- Editing bindings - You remember it exists, now you need to change it. Which file? What line? grep → open → scroll → find → edit. Every. Single. Time.
The Solution
confhelp -b ~/dotfiles --edit
Fuzzy search all your bindings → select one → opens $EDITOR at exact file:line.
Install
pip install confhelp
Usage
# Output all bindings (uses base_dirs from config)
confhelp
# Interactive fzf selection
confhelp --select
# Select and open in $EDITOR at line
confhelp --edit
# JSON output
confhelp -f json
# Override base directory
confhelp -b ~/other-dotfiles
# Show keys defined more than once
confhelp --conflicts
# Report lines that look like bindings but failed to parse
confhelp --check
Example output:
[tmux] prefix+g display-popup -w 80%... .tmux.conf:42
[alias] gs git status .zsh_aliases:15
[bind] ^[e edit-command-line .zshrc:89
The --edit flag drops you directly into the file at the exact line. Change the binding, save, done.
Binding Sources
confhelp supports two ways to extract bindings:
1. Regex Parsing (data-driven)
Define patterns in TOML to extract bindings from config files. Works for any text-based config format - tmux, zsh, aliases, etc. You specify paths, regex, and capture groups.
2. Query Engines (code-driven)
Some tools (like nvim) store bindings in ways that can't be reliably parsed with regex - runtime keymaps, plugin-generated bindings, multi-line table formats. Query engines run the tool itself to extract bindings.
Currently available: nvim (runs nvim headlessly to query keymaps)
Architecture note: Query engines are currently hardcoded. Future versions may support registering custom extractors - any code that returns (type, key, desc, file, line) tuples could become a binding source. This would allow community-contributed engines for tools like vim, emacs, i3, sway, etc.
Config Format
Define parsers in TOML. Each section describes how to extract bindings from a set of files:
# Default directories to search (no -b needed)
base_dirs = ["~/dotfiles", "~/work-dotfiles"]
# Query engines - run external tools to get bindings
# Available: "nvim" (queries nvim headlessly for keymaps)
query_engines = ["nvim"]
# tmux: bind [-n] <key> <command>
# Example: bind r source-file ~/.tmux.conf
# bind-key -n M-l popup -E lazygit
# Captures: (1) key=r or M-l, (2) command
[tmux]
paths = [".tmux.conf"]
match_line = "^bind"
regex = 'bind(?:-key)?\s+(?:-n\s+)?(\S+)(.*)'
key_group = 1
desc_group = 2
type = "tmux"
truncate = 100
# zsh alias: alias [-gs] <name>=<command>
# Example: alias gs='git status'
# alias -g C='| xsel --clipboard'
# Captures: (1) name=gs or C, (2) command
[alias]
paths = [".zsh_aliases", ".zsh_claude"]
regex = "alias\\s+(?:-[gs]\\s+)?([^=]+)=(.*)"
key_group = 1
desc_group = 2
type = "alias"
strip_quotes = true
# zsh-abbr: "abbrev" 'expansion'
# Example: "ga" 'git add'
# Captures: (1) abbrev=ga, (2) expansion=git add
[abbrev]
paths = [".zsh_abbreviations"]
match_line = '".*"'
regex = '''"([^"]+)"\s+'([^']+)''''
key_group = 1
desc_group = 2
type = "abbrev"
# nvim query engine options (enabled via query_engines above)
[nvim]
truncate = 60
# nvim regex fallback (if nvim binary unavailable, use this instead of query_engines)
[nvim-regex]
paths = [".config/nvim/lua/**/*.lua"]
match_line = "vim.keymap.set"
regex = 'vim\.keymap\.set\([^,]+,\s*"([^"]+)".*desc\s*=\s*"([^"]+)"'
key_group = 1
desc_group = 2
type = "nvim"
Config Options
Top-level options:
| Option | Description |
|---|---|
base_dirs |
Default directories to search |
query_engines |
List of query engines to enable (e.g., ["nvim"]) |
Section options:
| Option | Description |
|---|---|
paths |
List of files or glob patterns (e.g., **/*.lua) |
regex |
Pattern with capture groups for key/desc (Python re syntax) |
key_group |
Capture group number for the key |
desc_group |
Capture group number for description |
match_line |
Only process lines matching this pattern |
skip_comment |
Skip lines starting with # |
truncate |
Max length for description |
strip_quotes |
Remove surrounding quotes from desc |
desc_literal |
Use fixed string as description |
desc_from_comment |
Extract desc from trailing # comment |
Regex Tips
Patterns use Python's re module. Test patterns at regex101.com (select Python flavor).
Quick CLI test:
echo "bind r reload" | python -c "import re,sys; m=re.search(r'bind\s+(\S+)\s+(.*)', sys.stdin.read()); print(m.groups() if m else 'no match')"
Output Formats
pipe(default): pipe-delimited[type]|key|desc|file:linetsv: Tab-separatedjson: JSON array
The pipe format works well with column -t -s'|' for aligned display.
Integration Examples
confhelp outputs text. How you display it is up to you.
Alacritty Popup
Spawn a centered popup window showing bindings. Enter jumps to the file:
selection=$(confhelp -b ~/dotfiles | column -t -s'|' | fzf)
# parse selection, open in editor
See examples/alacritty-popup.sh for a complete implementation.
tmux Popup
tmux display-popup -w 80% -h 80% -E 'confhelp -b ~/dotfiles --select'
See examples/tmux-popup.sh for a complete implementation.
Rofi/dmenu
confhelp -b ~/dotfiles | rofi -dmenu
Acknowledgments
Inspired by Extracto.
License
MIT
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file confhelp-0.6.0.tar.gz.
File metadata
- Download URL: confhelp-0.6.0.tar.gz
- Upload date:
- Size: 270.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81c98bbba179fa54ba1b120759c6480a6c09a4191ed9c2d01159498a9f71d1c1
|
|
| MD5 |
09a8a016c6d8386bbf700f26e5dc95af
|
|
| BLAKE2b-256 |
b85e35624bfcb4b12602d0f648498658b056fd250bbbaacab2b6af47b6f662bd
|
Provenance
The following attestation bundles were made for confhelp-0.6.0.tar.gz:
Publisher:
publish.yml on Piotr1215/confhelp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
confhelp-0.6.0.tar.gz -
Subject digest:
81c98bbba179fa54ba1b120759c6480a6c09a4191ed9c2d01159498a9f71d1c1 - Sigstore transparency entry: 788865878
- Sigstore integration time:
-
Permalink:
Piotr1215/confhelp@417c38d62f32cb2f201259183328cb8297dd58e3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Piotr1215
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@417c38d62f32cb2f201259183328cb8297dd58e3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file confhelp-0.6.0-py3-none-any.whl.
File metadata
- Download URL: confhelp-0.6.0-py3-none-any.whl
- Upload date:
- Size: 11.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e767a14fd62f2e69cf2ca6f8c38d6aa4292f6d386363582d413f568c75fab276
|
|
| MD5 |
d14885a0d5b99fbf9ca119b704ee75bc
|
|
| BLAKE2b-256 |
c3378421f901770730e008233946e7b9fa3ca90c22b6d350237a47748ea84300
|
Provenance
The following attestation bundles were made for confhelp-0.6.0-py3-none-any.whl:
Publisher:
publish.yml on Piotr1215/confhelp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
confhelp-0.6.0-py3-none-any.whl -
Subject digest:
e767a14fd62f2e69cf2ca6f8c38d6aa4292f6d386363582d413f568c75fab276 - Sigstore transparency entry: 788865882
- Sigstore integration time:
-
Permalink:
Piotr1215/confhelp@417c38d62f32cb2f201259183328cb8297dd58e3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Piotr1215
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@417c38d62f32cb2f201259183328cb8297dd58e3 -
Trigger Event:
push
-
Statement type: