Local-first search for coding-agent sessions across Codex, Claude Code, Cursor, and more.
Project description
Threadlens
Find the coding-agent session you half-remember. Keep the history on your machine.
Threadlens searches local sessions from Codex, Claude Code, Cursor, Pi, OMP,
Amp, Droid, OpenCode, and custom JSONL agents through one CLI. It turns rough
memories such as plunk otp, monorepo split, or a typo into grouped session
results with useful snippets and optional resume actions.
uv tool install threadlens
threadlens start
threadlens search "plunk otp"
Threadlens does not upload sessions. It reads the original local stores into a private, disposable SQLite FTS index that you can refresh or rebuild at any time.
Why Threadlens
- Search across agents. One query covers supported local session stores.
- Search the way you remember. Exact, prefix, partial, and bounded typo-tolerant matching help when the wording is fuzzy.
- Return sessions, not message spam. Matches are grouped with titles, working directories, timestamps, and the best snippets.
- Stay local. No hosted sync, account, embeddings API, or background daemon.
- Use it anywhere. Search from the terminal, Raycast, scripts, or a bundled
agent
SKILL.md.
Supported sources
| Source | Local store | Notes |
|---|---|---|
| Codex | JSONL sessions | Search and verified resume command |
| Claude Code | JSONL sessions and history | Search and verified resume command |
| Cursor | Local SQLite state | Best-effort because the private format can change |
| Pi | JSONL sessions | Search and verified resume command |
| OMP | JSONL sessions | Search and verified resume command |
| Amp | Local prompt history | Prompts only; the observed store has no assistant history or resumable IDs |
| Droid | JSONL sessions | Search and verified resume command |
| OpenCode | Local SQLite database | Available when the database contains sessions |
| Custom agents | Configured JSONL files | Add a profile without changing Threadlens code |
Raw stores remain the source of truth. Threadlens never writes to them.
Install
Threadlens is a Python CLI distributed through PyPI. It does not ship native executables or platform-specific binary downloads.
[!NOTE] The old npm and standalone builds stop at 1.2.2 and will not receive updates. Install Threadlens 1.3.0 or newer with
uvorpipx. Ifcommand -v threadlensstill points to an npm shim, remove that old global package to avoid aPATHconflict.
uv (recommended)
uv can install Threadlens and manage a compatible
Python automatically:
uv tool install threadlens
Run it once without installing:
uvx threadlens search "plunk otp"
pipx or pip
pipx install threadlens
# or
pip install threadlens
Threadlens requires Python 3.10 or newer.
From source
git clone https://github.com/moinulmoin/threadlens.git
cd threadlens
uv tool install .
make verify
After changing the checkout, reinstall with uv tool install --reinstall ..
Core workflow
1. Build the local index
threadlens start
start discovers supported stores, creates the local index, and prints useful
next commands. Running search against an empty index performs the same initial
setup unless --no-bootstrap is passed.
2. Search what you remember
threadlens search "plunk otp"
threadlens search "monorepo api split" --source codex
threadlens search "rider modal" --cwd /path/to/project --limit 20
Use JSON Lines for integrations:
threadlens search "plunk otp" --json --no-bootstrap
Each JSON result includes a stable result ID, source, session ID, title, working directory, timestamp, score, matched terms, snippets, source location, freshness metadata, and supported actions.
3. Refresh when sessions change
threadlens refresh
threadlens refresh --days 14
threadlens search "plunk otp" --fresh
Refresh tracks file modification time and size, so unchanged files are skipped.
Use --force to reprocess matching files or --reset for a clean rebuild:
threadlens refresh --force
threadlens refresh --reset
4. Inspect and continue a result
threadlens brief codex:019...
threadlens resume codex:019...
resume prints a command; it never executes it. Resume actions are emitted only
for agents whose local command syntax has been verified.
Useful commands
threadlens sources # show detected stores
threadlens doctor # check adapters and index readiness
threadlens stats # show indexed message/session counts
threadlens search "query" --source claude # filter by source
threadlens search "query" --cwd "$PWD" # filter by project tree
Global options must appear before the subcommand:
threadlens --db /tmp/threadlens/index.sqlite refresh
threadlens --db /tmp/threadlens/index.sqlite search "cursor composer"
threadlens --config /tmp/threadlens/sources.json sources
By default, the index lives in the platform's user data directory and custom source profiles live in its user configuration directory.
Raycast
The raycast/ directory contains a thin Raycast extension over
threadlens search --json. It renders results and actions but does not index,
parse, or rank sessions itself.
Install the CLI first:
uv tool install threadlens
The extension finds common CLI locations such as ~/.local/bin,
/opt/homebrew/bin, and /usr/local/bin. If needed, set Threadlens Command
to the full output of command -v threadlens.
For local extension development:
cd raycast
npm install
npm run dev
Then run Search Agent Sessions in Raycast. You can also use Raycast's
Import Extension command and select the repository's raycast/ directory.
Bundled agent skill
The Python package includes a SKILL.md that teaches compatible coding agents
when and how to retrieve prior local sessions with Threadlens.
Print its durable installed path:
threadlens skill
threadlens skill --json
Copy or symlink the reported threadlens directory into the host agent's skills
directory. The skill uses the installed CLI; it does not download or execute a
standalone binary. The Raycast extension remains independent of the skill.
Custom JSONL agents
Add a named source profile when another agent stores sessions as JSONL:
threadlens sources add aider \
--path "~/.aider/**/*.jsonl" \
--session-key session.id \
--message-key message.id \
--role-key message.role \
--text-key message.content \
--timestamp-key createdAt \
--cwd-key cwd \
--title-key title \
--resume-template "cd {cwd} && aider --resume {session_id}"
threadlens refresh --source aider
threadlens search "custom agent bug" --source aider
Built-in names are reserved. Custom names become result prefixes such as
aider:session-id. Resume templates support {cwd}, {session_id}, and
{source}; Threadlens shell-quotes the substituted values.
For an unnamed one-off JSONL root:
threadlens refresh --include ~/.local/share/my-agent/sessions
Privacy and safety
- Session data and the search index stay on the local machine.
- Source stores are read-only inputs; the SQLite index is disposable.
- User and assistant messages are indexed where the source format identifies roles. System/developer instructions, thinking blocks, and tool output are skipped by supported adapters where those fields are distinguishable.
- Generic and Cursor extraction skip obvious credential fields.
- Display-time redaction masks common token and credential shapes.
- Session content is treated as untrusted data. Threadlens does not execute it or follow instructions found inside it.
- Index and profile files use private filesystem permissions where supported. Threadlens creates its own storage directories privately and never changes the permissions of a parent directory that already exists.
See SECURITY.md for the full data boundary and reporting guidance.
Platform support
Threadlens runs wherever Python 3.10+ runs. Source discovery depends on where each agent stores its local data:
- macOS: fully supported and tested.
- Linux: supported, including XDG locations for Cursor, Amp, and OpenCode.
- Windows: implemented as best-effort but not yet validated on a physical
Windows machine. Cursor, Amp, and OpenCode discovery checks
%APPDATA%and%LOCALAPPDATA%. Please report confirmed paths in issue #1.
Updating
Use the same tool you installed with:
uv tool upgrade threadlens
pipx upgrade threadlens
pip install --upgrade threadlens
The index survives normal upgrades. Run threadlens refresh --reset only when
you want to rebuild it from scratch.
Evaluation and benchmarks
Threadlens includes deterministic retrieval evaluation and latency gates:
threadlens --db .threadlens/index.sqlite \
eval .threadlens/eval-local-10.json --timings
threadlens --db .threadlens/index.sqlite \
bench .threadlens/eval-local-10.json --max-p95-ms 250
Private eval files should map remembered queries to known local sessions. The project acceptance target is Recall@5 >= 90%, no unrelated target sessions in the top five, and p95 search latency below 250 ms on the current local corpus.
Public custom-source fixtures live under eval/. Run the complete
project verification suite with:
make verify
Project boundaries
Search is the product. Indexing is local plumbing, and resume/open commands are optional result actions. Threadlens intentionally has no hosted sync, account system, team sharing, semantic embeddings, or background daemon.
Documentation
- Architecture — adapters, index, ranking, and UI boundary
- Contributing — development workflow and adapter rules
- Security — privacy model and untrusted-session handling
- Evaluation — eval formats and acceptance testing
Built by moinulmoin · @moinulmoin · MIT licensed
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 threadlens-1.3.0.tar.gz.
File metadata
- Download URL: threadlens-1.3.0.tar.gz
- Upload date:
- Size: 64.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8132ab54d735a0486fb17d6553072481ab4e48295bf3a1bb2ecc6af44c152fca
|
|
| MD5 |
3a81b8d3071cd573a19d9d9772e5586a
|
|
| BLAKE2b-256 |
0c8420d7fc7b37679608cd9380b5d923ef5b95be7b3da82c2dfc35f7aaa25e34
|
Provenance
The following attestation bundles were made for threadlens-1.3.0.tar.gz:
Publisher:
release.yml on moinulmoin/threadlens
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
threadlens-1.3.0.tar.gz -
Subject digest:
8132ab54d735a0486fb17d6553072481ab4e48295bf3a1bb2ecc6af44c152fca - Sigstore transparency entry: 2228575948
- Sigstore integration time:
-
Permalink:
moinulmoin/threadlens@880492953853547fe318817123b1ea9d43486b58 -
Branch / Tag:
refs/tags/v1.3.0 - Owner: https://github.com/moinulmoin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@880492953853547fe318817123b1ea9d43486b58 -
Trigger Event:
push
-
Statement type:
File details
Details for the file threadlens-1.3.0-py3-none-any.whl.
File metadata
- Download URL: threadlens-1.3.0-py3-none-any.whl
- Upload date:
- Size: 37.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5bcd5dc8f5806f90db53de195a2ceb7ce7bd5d8724d061b4e473fe689bd85849
|
|
| MD5 |
ef45ace25cf23a2c7f85dd5c21347ed4
|
|
| BLAKE2b-256 |
495924c21ea29ac4b1d496b41f450ea3998f94c8eb419cfeb125d3ebef3bcb20
|
Provenance
The following attestation bundles were made for threadlens-1.3.0-py3-none-any.whl:
Publisher:
release.yml on moinulmoin/threadlens
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
threadlens-1.3.0-py3-none-any.whl -
Subject digest:
5bcd5dc8f5806f90db53de195a2ceb7ce7bd5d8724d061b4e473fe689bd85849 - Sigstore transparency entry: 2228576299
- Sigstore integration time:
-
Permalink:
moinulmoin/threadlens@880492953853547fe318817123b1ea9d43486b58 -
Branch / Tag:
refs/tags/v1.3.0 - Owner: https://github.com/moinulmoin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@880492953853547fe318817123b1ea9d43486b58 -
Trigger Event:
push
-
Statement type: