Local-first semantic search for your shell history. Search by intent, not exact text. No cloud, no API keys.
Project description
whatwasit
Local-first semantic search for your shell history.
Search by what you were trying to do, not the exact command you typed — and nothing ever leaves your machine.
whatwasit "how did I fix that nginx issue"
Returns the session of commands you actually ran (cd, vim, systemctl reload nginx) weeks ago, even though you never typed "fix" or "issue".
Features
- Intent-based recall — embeds whole command sessions, not individual lines
- Session grouping — reconstructs working directory and groups commands by time
- Hybrid reranking — boosts exact tool-name / flag matches when the query contains them, without hurting natural-language queries
- Fully offline — ONNX embedding model runs on CPU; no cloud, no API keys
- Non-destructive — reads your existing history files; never modifies them
Install
From PyPI:
pip install whatwasit
From source:
git clone https://github.com/ThorOdinson246/whatwasit.git
cd whatwasit
pip install .
For development:
pip install -e ".[dev]"
Requirements: Python 3.9+, ~100 MB disk for the embedding model (downloaded once on first run).
Releasing to PyPI
One-time setup
- Create a PyPI API token: pypi.org/manage/account/token → Add API token
- Token scope:
whatwasit(project name; use “entire account” only if the project does not exist yet on first upload) - Copy the token (
pypi-AgE...) — it is shown only once
- Token scope:
- Add it to GitHub: repo Settings → Secrets and variables → Actions → New repository secret
- Name:
PYPI_API_TOKEN - Value: paste the token
- Name:
Each release
- Bump
versioninpyproject.tomlandwhatwasit/__init__.py(keep them identical). - Commit, push
main. git tag v0.1.0 && git push origin v0.1.0- GitHub → Releases → Draft new release → select the tag → Publish release.
The publish workflow builds the wheel and uploads to PyPI as whatwasit. Users install with:
pip install whatwasit
Usage
# Build or refresh the search index from your shell history
whatwasit index
# Force a full rebuild
whatwasit index --rebuild
# Adjust session grouping window (default: 300 seconds)
whatwasit index --window 600
# Interactive REPL (default when run with no arguments)
whatwasit
# One-shot search by intent (TUI with pre-fetched results)
whatwasit "that time I set up passwordless ssh"
# Plain / headless output (Rich panels on a TTY, line-oriented when piped)
whatwasit "docker volume that wouldn't persist" --plain
whatwasit "nginx config" --headless
# Return more results
whatwasit "docker volume that wouldn't persist" -k 20
TUI / REPL
Running whatwasit with no arguments opens a persistent REPL with a bottom input
bar. Type a natural-language query and press Enter to search; results update in
place with matched commands highlighted. Directory and timestamp appear as dim
secondary metadata under each result. Ranks (#1, #2, …) and qualitative
confidence badges (strong / medium / weak) replace raw similarity
scores. When the top result is below the low-confidence threshold (default
0.40), a soft warning banner appears without hiding results.
| Key / command | Action |
|---|---|
j / k or arrows |
Navigate results |
| Enter (on a result) | Copy matched command(s) to clipboard |
n or /more |
Show more results |
/help |
Show help |
/quit or q |
Quit |
One-shot whatwasit "query" still opens the TUI with the same result layout.
Use --plain or --headless for non-interactive output.
Configuration (~/.config/whatwasit/config.toml):
# Output mode: "tui" (default) or "plain"
output_mode = "tui"
# Number of results shown initially in the TUI; ``n`` or ``/more`` loads more
tui_page_size = 5
# Banner when top-1 score is below this value (does not suppress results)
low_confidence_threshold = 0.40
# Reserved for a future background daemon (not yet implemented)
use_daemon = false
CLI flags override config file values. For example, --plain forces plain
output even when output_mode = "tui" in the config file.
Data location: ~/.local/share/whatwasit/ (whatwasit.db + index.usearch).
Supported history sources: ~/.zsh_history, ~/.bash_history, Atuin DB
(if present). All are read non-destructively.
How it works
- Parse — reads your shell history files into timestamped commands
- Group — clusters commands into sessions by time gap and working directory
(replaying
cd/pushd/popdto reconstruct CWD) - Embed — encodes each session locally with
all-MiniLM-L6-v2(~22 MB ONNX, CPU-only viaonnxruntime) - Index — stores vectors in a local
usearchindex with SQLite metadata - Search — embeds your query, finds nearest sessions, highlights matching commands within each session
Performance
On an Intel i9-14900 (unthrottled), whatwasit meets its design targets:
| Scale | Index time | Query latency (avg) |
|---|---|---|
| 10k commands | 7.2 s | 165 ms |
| 100k commands | 92.9 s | 153 ms |
Pure ANN search over 100k session vectors: < 1 ms. Details in BENCHMARKS.md.
Search quality
Evaluated on a labeled dataset of 86 intent-paraphrase queries (P@1 = 0.535, MRR = 0.700) against a keyword baseline (P@1 = 0.291). See eval/README.md for methodology and full metrics.
Documentation
| Doc | Contents |
|---|---|
| ARCHITECTURE.md | Design decisions and module layout |
| BENCHMARKS.md | Performance measurements and reproduction |
| FUTURE_IDEAS.md | Explicitly out-of-scope ideas |
| eval/README.md | Search quality evaluation harness |
Privacy
- All processing is local — no network calls after the one-time model download
- Your shell history never leaves your machine
- Index data stays in
~/.local/share/whatwasit/
Development
pip install -e ".[dev]"
pytest
python benchmarks/run_bench.py --write-md # performance benchmarks
python eval/run_eval.py # search quality evaluation
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
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 whatwasit-0.1.0.tar.gz.
File metadata
- Download URL: whatwasit-0.1.0.tar.gz
- Upload date:
- Size: 348.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b81b3d4ccc1d5d5ae3175f4da55f9afd2740de44aa5842a3351e92404e2a343
|
|
| MD5 |
4315c92b6e4fc81c481d70ca91f903cc
|
|
| BLAKE2b-256 |
d7c5c959b332ec434354b68b433e191417dc16febcc07b69fe61d63062aa4490
|
File details
Details for the file whatwasit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: whatwasit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 44.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3a9fd4c38e4c41f44de717b01d566bc54b6526248811d3727f0bd48797605ca
|
|
| MD5 |
3e8853a3774d087edc6e3a23ad7596ce
|
|
| BLAKE2b-256 |
c896f77ea75a9fedcd7b0cd98b0e3a713d5b85823d5a372f4957b0fb8b4725b4
|