pxh
Fast, local-first shell history search and sync for bash and zsh.
Your shell history is one of the most useful things on your machine -- but it's fragile, unsearchable, and stuck on one box. pxh fixes that. It stores every command in a local SQLite database with rich metadata (directory, host, exit code, duration), gives you powerful regex search and an interactive TUI, and syncs across machines over SSH or a shared filesystem.
No cloud accounts. No servers. No networking code. No AI. Just your history, on your machines, searchable in milliseconds.
$ pxh s ffmpeg
2022-06-04 07:54:04 ffmpeg -encoders | grep '^ V'
2022-06-07 23:17:33 ffmpeg -y -r 30 -f concat -safe 0 -i <(sed...) -c:v libx264rgb output.mp4
2022-08-03 10:39:11 ffmpeg -i cropped.mp4 -vf "pad=width=430:..." cropped.gif
Install
Homebrew (macOS and Linux):
Prebuilt binaries (Linux x86_64/ARM64, macOS x86_64/ARM64):
|
From source:
Shell setup
After installing, set up shell integration and import your existing history:
# Import your existing history
# or for zsh:
# Activate in current session without restarting
From now on, pxh automatically records commands with directory, host, user, exit code, and duration.
Usage
Interactive Browser (pxh recall)
Press Ctrl-R in your shell to open the interactive history browser. Type to filter, arrows to navigate, Enter to execute, Tab to edit before executing. Alt-1 through Alt-9 quick-select visible entries.
Supports both emacs (default) and vim keybindings -- set keymap = "vim" in ~/.pxh/config.toml.
Searching History (pxh show)
The show command (alias: s) is the power-search interface:
Verbose output (-v):
$ pxh s -v cargo build
Start Duration Session Context Command
2023-02-06 22:10:20 1s 116ef63fc226 . cargo build --release
2023-02-07 06:32:04 37s ee6e1989f3da . cargo build --release
Synchronizing History (pxh sync)
Sync history across machines via SSH or a shared directory. pxh contains no networking code itself - sync works by invoking SSH or reading/writing files from a shared filesystem.
SSH Synchronization
# Bidirectional sync (default)
# One-way sync
# Custom SSH options (like rsync's -e flag)
# Sync only recent history
# Custom remote paths
Shared Directory Synchronization
Use Dropbox, OneDrive, NFS, or any shared filesystem:
# On each machine, run:
# Export only (don't import from others)
Each machine writes its own .db file and reads from all others.
Security: Scanning and Scrubbing
Scanning for Secrets
Detect potential secrets (API keys, passwords, tokens) in your history:
Confidence levels: critical (default), high, low, all
Removing Secrets
Remove sensitive commands from your history:
# Scrub from multiple locations
Other Commands
Import
Import history from existing shell history files:
# Import from another machine
# Import from Atuin
|
Export
Export your entire history as JSON:
|
Maintenance
Optimize database performance and reclaim space:
Configuration
pxh reads configuration from ~/.pxh/config.toml. All settings are optional with sensible defaults.
Example configuration:
[]
# Keymap mode: "emacs" (default) or "vim"
= "emacs"
# Show the preview pane with command details
= true
# Maximum results to load (default: 5000)
= 5000
[]
# Which fields to show in the preview pane
= true
= true
= true
= true
= false # Useful if syncing across machines
[]
# Override the detected hostname
= "my-laptop"
# Previous hostnames for this machine (history from these is treated as local)
= ["old-laptop", "work-mac"]
[]
# Disable Ctrl-R binding (use pxh recall directly instead)
= false
Design
pxh contains zero networking code. Sync works by invoking your SSH client or reading/writing files on a shared filesystem. No accounts, no cloud services, no ports, no attack surface. Your history stays on machines you control.
All data lives in a local SQLite database (~/.pxh/pxh.db). There's no central server. The binary is statically linked with no runtime dependencies beyond libc -- consistent behavior across bash and zsh, proper handling of edge cases (quoting, binary data, concurrent access), and fast enough that you never notice it.
Tips and Tricks
Quick Search Alias
Create a symlink named pxhs pointing to pxh, and it will automatically run pxh show:
Useful Patterns
# Commands that failed
|
# What did I do in this project last week?
# How did I use that obscure tool?
# Commands from a specific session
Sync Strategies
- Real-time sync: Run
pxh sync --remote serverperiodically via cron - Shared folder: Just run
pxh sync ~/Dropbox/pxh/occasionally on each machine - Backup: The database is a single SQLite file -
cp ~/.pxh/pxh.db backup/
zsh-autosuggestions
If you use zsh-autosuggestions, pxh automatically registers itself as a suggestion strategy. Suggestions come from your full cross-machine history database, not just the local zsh history file.
Privacy
- Commands starting with a space are ignored (like bash's
HISTCONTROL=ignorespace) - Use
pxh scanregularly to detect accidentally committed secrets - Use
--no-secret-filterwith sync if you want to disable automatic secret filtering during import
Disabling Ctrl-R
If you prefer to keep your shell's default Ctrl-R behavior:
Option 1: CLI flag
# When sourcing manually:
Option 2: Config file (~/.pxh/config.toml)
[]
= true
You can still use pxh recall directly or bind it to a different key.
Credits
Inspired by bash-history-sqlite, zsh-histdb, mcfly, and atuin. Embeds bash-preexec and secrets-patterns-db.
How it Works
pxh hooks into your shell via preexec/precmd functions to capture each command with its start/end time, working directory, exit status, session ID, hostname, and username. For bash, it embeds bash-preexec; for zsh, it uses native hooks.
Commands are stored as BLOBs (to handle non-UTF8 data) in SQLite with WAL mode and a 5-second busy timeout, so multiple shells can record simultaneously. A unique index prevents duplicates. Secret scanning uses patterns from secrets-patterns-db, categorized by confidence level.
Database location: ~/.pxh/pxh.db (override with --db or PXH_DB_PATH)