A modern shell history replacement with fuzzy search, statistics, and AI-powered queries.
Note: This application was built as an experiment in AI-assisted development - the entire codebase was created through collaborative coding with Claude & Copilot.
- Fast fuzzy search - Handles 40k+ commands instantly with interactive preview
- AI-powered search - Find commands using natural language queries
- Rich metadata - Captures timestamps, exit codes, duration, working directory, git branch
- Statistics - Analyze your command usage patterns
- Export/Import - Multiple formats (JSON, CSV, text) with optional AES-256 encryption
- Shell integration - Seamless bash/zsh integration with Ctrl-R binding
- Privacy-first - All data stored locally, no telemetry
- No daemon - Simple architecture, no background process required
Using Go:
go install github.com/spideyz0r/fh/cmd/fh@latestFrom source:
git clone https://github.com/spideyz0r/fh.git
cd fh
make build
make installInitialize fh and import your existing history:
fh --initRestart your shell:
# Bash
source ~/.bashrc
# Zsh
source ~/.zshrcThat's it! Press Ctrl-R to search your history.
# Launch fuzzy search (or press Ctrl-R)
fh
# Search with pre-filter
fh docker
# Search for kubectl commands
fh kubectl get pods# Set your OpenAI API key
export OPENAI_API_KEY='sk-...'
# Ask questions in natural language
fh --ask "what git commands did I run today?"
fh --ask "show me failed commands from last week"
fh --ask "how did I deploy the API to staging?"fh --stats# Export
fh --export --format json --output history.json
fh --export --format json --output backup.json.enc --encrypt
# Import
fh --import --input history.json
fh --import --input backup.json.enc --decryptEdit ~/.fh/config.yaml:
database:
path: ~/.fh/history.db
storage:
deduplicate:
enabled: true
strategy: keep_all # keep_first, keep_last, or keep_all
ignore:
patterns:
- ^ls$
- '^ls '
- ^cd$
- '^cd '
- ^pwd$
- ^exit$
- ^clear$
search:
limit: 0 # 0 = unlimited (recommended)
deduplicate: true # Show only unique commands in search results
keybinding: ctrl-r # Ctrl-R (use ctrl-g to keep native Ctrl-R)
ai:
enabled: true
provider: openai
model: gpt-4o-mini # gpt-4o, gpt-4, gpt-3.5-turbo
sql_timeout_secs: 60
max_sql_retries: 10
max_chunk_tokens: 10000fh supports two levels of deduplication to balance clean search results with rich AI context:
Storage Deduplication (storage.deduplicate)
- Controls how duplicate commands are stored in the database
keep_all(recommended): Stores every command execution with full metadata - best for AI queries that need temporal contextkeep_last: Updates timestamp of existing commands - saves database spacekeep_first: Keeps only first occurrence - minimal storage footprint
Display Deduplication (search.deduplicate)
- Controls what you see in fuzzy search (Ctrl-R)
true(default): Shows only unique commands (most recent occurrence)false: Shows all command executions
Recommended Setup:
storage:
deduplicate:
enabled: true
strategy: keep_all # Full history for AI context
search:
deduplicate: true # Clean search resultsThis gives you a clean search interface (e.g., 14K unique commands) while preserving full history for AI-powered queries like "show me all docker commands from last week".
For AI features, add your OpenAI API key to your shell RC file (~/.bashrc or ~/.zshrc):
export OPENAI_API_KEY='sk-...'By default, fh overrides Ctrl-R with its fuzzy finder interface. If you prefer to keep the native shell reverse search on Ctrl-R and use a different key for fh, configure the keybinding in ~/.fh/config.yaml:
search:
keybinding: ctrl-g # Use Ctrl-G for fh (keeps native Ctrl-R)Supported keybindings: ctrl-r, ctrl-g, ctrl-f, ctrl-s, ctrl-t, ctrl-h (or any ctrl-<letter>)
Common use case: Use ctrl-g for fh and keep ctrl-r for native shell reverse search. This gives you:
- Ctrl-R: Simple chronological search (predictable, finds recent commands first)
- Ctrl-G: Powerful fuzzy search with previews, filters, and deduplication
To change keybinding:
- Edit
~/.fh/config.yamland changekeybindingvalue - Run
fh --init- it will automatically detect and update your shell configuration - Restart your shell:
source ~/.bashrcorsource ~/.zshrc
When you run fh --init:
- Creates
~/.fh/directory and SQLite database - Imports your existing bash/zsh history
- Adds hooks to your shell RC file to capture new commands
- Binds Ctrl-R to launch fh
Every command is automatically saved with metadata (timestamp, exit code, duration, working directory, git branch).
No daemon required - command capture happens via shell hooks. All data stored locally in ~/.fh/history.db.
- Go: 1.21+ (only for building from source)
- Bash: 4.0+ or Zsh: any recent version
macOS ships with bash 3.2 which is not compatible. Either:
Option 1: Upgrade bash
brew install bash
echo /opt/homebrew/bin/bash | sudo tee -a /etc/shells
chsh -s /opt/homebrew/bin/bashOption 2: Use zsh
chsh -s /bin/zshCtrl-R doesn't work: Run fh --init and restart your shell (source ~/.bashrc or source ~/.zshrc)
AI search not working: Set export OPENAI_API_KEY='sk-...' in your shell RC file
No history entries: Check that shell hooks are in ~/.bashrc or ~/.zshrc
GNU General Public License v3.0
Contributions welcome! See CONTRIBUTING.md for development guidelines.
Built with go-fuzzyfinder, OpenAI Go SDK, and SQLite.