pxh 0.9.6

pxh is a fast, cross-shell history mining tool with interactive fuzzy search, secret scanning, and bidirectional sync across machines. It indexes bash and zsh history in SQLite with rich metadata for powerful recall.
Documentation

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

Prebuilt binaries (Linux x86_64/ARM64, macOS x86_64/ARM64):

curl -sSfL https://raw.githubusercontent.com/chipturner/pxhist/main/install.sh | sh

From source:

cargo install pxh        # requires Rust 1.88+

Shell setup

After installing, set up shell integration and import your existing history:

pxh install bash  # or: pxh install zsh

# Import your existing history
pxh import --shellname bash --histfile ~/.bash_history
# or for zsh:
pxh import --shellname zsh --histfile ~/.zsh_history

# Activate in current session without restarting
source <(pxh shell-config bash)  # or: source <(pxh shell-config zsh)

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.

pxh recall           # Open history browser
pxh recall --here    # Limit to current directory
pxh recall -q "git"  # Start with a pre-filled query

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:

pxh show ffmpeg           # Find commands containing "ffmpeg"
pxh s docker run          # Multiple patterns match in order (docker.*\s.*run)
pxh s -i CMAKE            # Case-insensitive search
pxh s --here              # Only commands from current directory
pxh s --session $PXH_SESSION_ID  # Only commands from current shell session
pxh s -v cargo build      # Verbose: show duration, session, directory
pxh s -l 100 git          # Show up to 100 results (default: 50, 0 = unlimited)
pxh s --loosen foo bar    # Match patterns in any order

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)
pxh sync --remote myserver

# One-way sync
pxh sync --remote myserver --send-only     # Push local → remote
pxh sync --remote myserver --receive-only  # Pull remote → local

# Custom SSH options (like rsync's -e flag)
pxh sync --remote myserver -e "ssh -p 2222"
pxh sync --remote myserver -e "ssh -i ~/.ssh/special_key"

# Sync only recent history
pxh sync --remote myserver --since 30  # Last 30 days only

# Custom remote paths
pxh sync --remote myserver --remote-db /custom/path/pxh.db
pxh sync --remote myserver --remote-pxh /usr/local/bin/pxh

Shared Directory Synchronization

Use Dropbox, OneDrive, NFS, or any shared filesystem:

# On each machine, run:
pxh sync ~/Dropbox/pxh/

# Export only (don't import from others)
pxh sync ~/Dropbox/pxh/ --export-only

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:

pxh scan                        # Scan with default sensitivity (critical)
pxh scan -c high                # Include high-confidence matches
pxh scan -c all                 # Show all potential matches
pxh scan -v                     # Verbose: show which pattern matched
pxh scan --json                 # Output as JSON for scripting
pxh scan --histfile ~/.bash_history  # Scan a histfile directly
pxh scan --dir ~/Dropbox/pxh/   # Scan all databases in a sync directory

Confidence levels: critical (default), high, low, all

Removing Secrets

Remove sensitive commands from your history:

pxh scrub                       # Interactive: prompts for the secret to remove
pxh scrub "my-api-key"          # Remove commands containing this string
pxh scrub --scan                # Remove all secrets found by scan
pxh scrub --scan -c high        # Remove critical and high-confidence secrets
pxh scrub -n                    # Dry-run: show what would be removed
pxh scrub -y                    # Skip confirmation prompt

# Scrub from multiple locations
pxh scrub --histfile ~/.bash_history "secret"  # Also scrub from histfile
pxh scrub --dir ~/Dropbox/pxh/ "secret"        # Scrub from sync directory
pxh scrub --remote myserver "secret"           # Scrub from remote machine

Other Commands

Import

Import history from existing shell history files:

pxh import --shellname zsh --histfile ~/.zsh_history
pxh import --shellname bash --histfile ~/.bash_history

# Import from another machine
pxh import --shellname zsh --histfile <(ssh server cat ~/.zsh_history) \
    --hostname server --username root

Export

Export your entire history as JSON:

pxh export > history.json
pxh export | jq '.[] | select(.exit_status != 0)'  # Filter failed commands

Maintenance

Optimize database performance and reclaim space:

pxh maintenance           # ANALYZE and VACUUM the database
pxh maintenance other.db  # Operate on a specific database file

Configuration

pxh reads configuration from ~/.pxh/config.toml. All settings are optional with sensible defaults.

Example configuration:

[recall]
# Keymap mode: "emacs" (default) or "vim"
keymap = "emacs"

# Show the preview pane with command details
show_preview = true

# Maximum results to load (default: 5000)
result_limit = 5000

[recall.preview]
# Which fields to show in the preview pane
show_directory = true
show_timestamp = true
show_exit_status = true
show_duration = true
show_hostname = false  # Useful if syncing across machines

[shell]
# Disable Ctrl-R binding (use pxh recall directly instead)
disable_ctrl_r = 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:

ln -s $(which pxh) ~/.local/bin/pxhs
pxhs ffmpeg  # Equivalent to: pxh show ffmpeg

Useful Patterns

# Commands that failed
pxh s -v . | grep -v "0s"  # Or query the database directly

# What did I do in this project last week?
pxh s --here -l 0

# How did I use that obscure tool?
pxh s -v ansible-playbook

# Commands from a specific session
pxh s --session $PXH_SESSION_ID  # Current session

Sync Strategies

  • Real-time sync: Run pxh sync --remote server periodically 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/

Privacy

  • Commands starting with a space are ignored (like bash's HISTCONTROL=ignorespace)
  • Use pxh scan regularly to detect accidentally committed secrets
  • Use --no-secret-filter with 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:
source <(pxh shell-config zsh --no-ctrl-r)

Option 2: Config file (~/.pxh/config.toml)

[shell]
disable_ctrl_r = 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)

sqlite3 ~/.pxh/pxh.db "SELECT * FROM command_history LIMIT 10"