Your Claude Code & Codex conversations, searchable forever.
The Problem
Claude Code (~/.claude/history.jsonl) and Codex (~/.codex/sessions/) store conversations — not searchable, not browsable, not persistent. Both agents compact and delete old sessions without warning.
pv turns that history into a searchable markdown library + SQLite database. It auto-detects Codex and merges both agents into one vault, tagging each conversation by source (cc = Claude Code, cx = Codex) with a ctrl-s filter to narrow by agent. Browse in Obsidian, search from the terminal with fzf. Zero dependencies. Pure stdlib.
Quick Start
# recommended — fast, isolated, always on PATH
uv tool install promptvault-py
# alternative — same idea, traditional tool
pipx install promptvault-py
pv-sync # sync your Claude Code history
pv # browse conversations
pv search "database migration" # full-text search
# upgrade to latest version
uv tool upgrade promptvault-py # or: pipx upgrade promptvault-py
Don't have uv?
curl -LsSf https://astral.sh/uv/install.sh | sh(docs)Don't have pipx?
brew install pipxorpip install --user pipx(docs)
Both tools install pv into an isolated virtualenv and symlink the executable to ~/.local/bin/, so it's available globally — no environment activation needed.
pvis the short alias.promptvault/promptvault-syncalso work.
Optional: install fzf for the interactive UI (brew install fzf / apt install fzf). Without it, pv falls back to plain text.
How It Works
pv-sync reads Claude Code's history.jsonl and (if ~/.codex/ exists) Codex's rollout sessions, groups prompts by conversation, and generates:
- Markdown vault — One
.mdper conversation,YYYY/MM/structure, YAML frontmatter (incl.source). Drop into Obsidian. - SQLite database — FTS5 full-text search with BM25 ranking. Millisecond queries. Each conversation keeps its
source.
The sync is idempotent — always rebuilds from source, impossible to reach a bad state. Resolves pasted-text placeholders, deduplicates prompts, filters slash commands, cleans whitespace.
Commands
All commands launch fzf by default (split pane: conversation list + live preview). Add --no-fzf for plain text.
| Command | Description |
|---|---|
pv |
Browse all conversations interactively |
pv search "query" |
Full-text search ranked by relevance |
pv recent [N] |
Last N conversations (default 20) |
pv list [--date DATE] [--project NAME] |
Filter by date or project |
pv stats |
Vault overview |
pv-sync |
Rebuild vault + database |
Controls:
| Key | Action |
|---|---|
Enter |
Open in $EDITOR (returns to fzf) |
Ctrl-O |
Open in $EDITOR (exits fzf) |
Ctrl-T |
Toggle conversation / prompt view |
Ctrl-P |
Cycle project filter |
Ctrl-D |
Cycle date range (all/today/week/month) |
Ctrl-B |
Toggle bookmark on selected conversation |
Ctrl-G |
Show only bookmarked conversations |
Ctrl-Y |
Copy to clipboard |
Ctrl-E |
Export to file (save dialog) |
Ctrl-X |
Exclude from results |
Ctrl-/ |
Toggle preview |
Tab |
Multi-select |
Esc |
Quit |
Full documentation: docs/usage.md
Shell Widget
Insert a previous prompt directly into your command line with Alt-P:
# Add to your shell config:
eval "$(pv shell-init zsh)" # or bash
Customise the key with PROMPTVAULT_WIDGET_KEY (default: \ep = Alt-P).
Real-Time Capture
A Claude Code hook captures prompts the moment you send them — no sync needed.
Add to ~/.claude/hooks.json:
{
"hooks": {
"UserPromptSubmit": [{
"hooks": [{
"type": "command",
"command": "python3 /path/to/promptvault/promptvault/hook.py",
"timeout": 5000
}]
}]
}
}
Fast (<50ms), silent (no stdout), safe (errors swallowed). Captures to ~/.claude/prompt-library/capture.jsonl.
Windows: use
pythoninstead ofpython3and backslash paths.
Markdown Vault
Each conversation becomes an Obsidian-compatible .md with YAML frontmatter:
~/.claude/prompt-library/vault/
├── _index.md
├── 2026/
│ └── 03/
│ ├── 2026-03-25__c792e74f__refactor-user-auth.md
│ └── ...
Open as an Obsidian vault. The Calendar plugin works well for browsing.
Environment Variables
| Variable | Default |
|---|---|
PROMPTVAULT_HISTORY |
~/.claude/history.jsonl |
PROMPTVAULT_OUTPUT |
~/.claude/prompt-library |
PROMPTVAULT_DB |
~/.claude/prompt-library/prompts.db |
PROMPTVAULT_VAULT |
~/.claude/prompt-library/vault |
PROMPTVAULT_PROJECTS |
~/.claude/projects |
PROMPTVAULT_CAPTURE_LOG |
~/.claude/prompt-library/capture.jsonl |
PROMPTVAULT_CODEX_SESSIONS |
~/.codex/sessions |
Contributing
Contributions welcome! See CONTRIBUTING.md. 340 tests, all synthetic data.
git clone https://github.com/reidemeister94/promptvault.git
cd promptvault
uv tool install --editable . # global "pv" that tracks your local source
make setup-dev-env
make test && make lint
License
MIT
Metadata
Release files for promptvault-py 0.0.11
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| promptvault_py-0.0.11.tar.gz | 60.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| promptvault_py-0.0.11-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 89.0 kB
Release files / promptvault_py-0.0.11.tar.gz
| Download URL | promptvault_py-0.0.11.tar.gz |
|---|---|
| Size | 60.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e9b0388ef3f3ca4aced9fbe4ad0dda9fcf9637f9d9177e5f212d79bc7bf85b49
|
|
BLAKE2b-256 checksum How to use checksums |
5d0610a0c38ce34677b6fbf9db5e4253217f908d114ad3ceee869d856dfe8cf1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.
Transparency logRelease files / promptvault_py-0.0.11-py3-none-any.whl
| Download URL | promptvault_py-0.0.11-py3-none-any.whl |
|---|---|
| Size | 28.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0a8e8949761dd9eb507a98f11961eb8ab0116ecb4af90095f6c9cd829e3e4c8a
|
|
BLAKE2b-256 checksum How to use checksums |
042b599a263a8d918a502b0726e3c58e616db1a742a089b34b3f4da4f9a286e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.
Transparency log