Skip to main content

doclens

Structure-aware document retrieval — FTS5/BM25 keyword search over document trees, with an interactive TUI and a PWA Web UI.

PyPI version Python License

doclens parses documents into tree structures (headings, classes, functions…) and searches them with FTS5/BM25 keyword matching — no embeddings, no chunking, no vector DB required. Works entirely offline.


Features

Structure-aware search Returns results anchored to document headings, code classes, or function definitions — not orphaned line fragments
Multi-format Markdown, PDF, DOCX, PPTX, Excel, HTML, JSON, CSV, code (Python AST + tree-sitter)
Two UIs Textual TUI (terminal) and Lit + Shoelace PWA (browser)
LLM-augmented QA Send search results to Anthropic Claude for natural-language answers
Background watching Auto-reindexes changed files via watchdog
Web search Fetch + extract public web pages as markdown before searching

Installation

pip install doclens

Requires Python ≥ 3.10.

Quick setup:

# Index your documents
doclens index --force

# Search from CLI
doclens search "authentication"

# Or launch the Web UI (opens browser automatically)
doclens gui

CLI Reference

doclens <command> [--workdir DIR]
Command Description
doclens search <query…> Keyword search across indexed documents
doclens search_v2 '<json>' Structured search: AND / OR / NOT / PHRASE operators
doclens ai <message…> Send a message to the Claude agent
doclens index [--force] Build or update the document index
doclens status Show index statistics and system status
doclens gui [--port PORT] Launch the Web UI (PWA)
doclens read_document --path <path> Read a document with structure info
doclens web <query…> Search the live web
doclens webfetch <url> Extract a web page as markdown
doclens grep <pattern> Ripgrep-style regex search

Quick Start

1. Index your documents

# Index the current directory
doclens index --force

# Or specify a working directory
doclens index --workdir /path/to/project

doclens automatically discovers supported files (.md, .py, .pdf, .docx, .xlsx, …) and skips common ignore patterns (.git, node_modules, __pycache__, .venv).

2. Search

doclens search "authentication flow"
doclens search "量子 计算"          # Chinese supported via jieba

# Structured query
doclens search_v2 '{"type": "and", "terms": ["auth", "token"]}'

3. Interactive TUI

doclens

Opens the full terminal UI with live preview, command history, and keyboard navigation.

4. Web UI

doclens gui
# INFO: Uvicorn running on http://127.0.0.1:7860

Browser opens automatically. Port may vary if 7860 is in use — check the startup log.

5. Ask the AI

doclens ai "How does the authentication system work?"

doclens first retrieves relevant document sections, then sends them to Anthropic Claude as context for a grounded answer.


Claude Code Integration (MCP KB Q&A)

doclens auto-starts an MCP server (Streamable HTTP) inside both the TUI and the GUI, exposing the knowledge base as two MCP tools — search_kb and read_document. Any MCP-compatible client (Claude Code, Cursor, Cline, …) can connect and answer questions grounded in your indexed documents, with zero embedding / vector DB.

How it works

  • The MCP HTTP server runs in a background thread in-process, sharing the same IndexManager as the TUI/GUI — so live reindexing via the file watcher applies to MCP queries too.
  • It listens at http://<host>:<port>/mcp. The URL is printed in the startup log on every launch.
  • Loopback (127.0.0.1) by default, no auth. Binding to a non-loopback address requires a bearer token (CORTEX_MCP_TOKEN) — the server refuses to start otherwise.

Setup

1. Start doclens (this also starts the MCP server):

doclens gui          # Web UI mode
# or
doclens              # TUI mode

Read the MCP URL from the startup log:

MCP server: http://127.0.0.1:7880/mcp

2. Register it in Claude Code (once per project):

claude mcp add --transport http doclens http://127.0.0.1:7880/mcp --scope local
claude mcp list      # expect: doclens: ... ✔ Connected

Scopes: local (default — this project + you, not committed), user (global), project (.mcp.json, committed).

3. Restart your Claude Code session if it was already running — MCP servers load only at session start.

4. Ask. In Claude Code, ask anything about your indexed docs; it will call search_kb / read_document automatically. For a focused, KB-only answer, restrict the session to the two tools:

claude -p "量子密钥分发 QKD 的基本原理是什么?" \
  --allowedTools "mcp__doclens__search_kb" "mcp__doclens__read_document"

Bundled skill: kb-ask

doclens ships a Claude Code skill (source: doclens/claude_code_skills/kb-ask/skill.md) that codifies the full KB Q&A workflow: MCP-connected prerequisite check, FTS multi-query strategy, read_document deep-read, source-citation rules, and a no-fabrication constraint.

On TUI/GUI startup, doclens checks ~/.claude/skills/kb-ask/ and, if the skill is missing or out of date, prompts to install/overwrite it (skipped silently in non-interactive terminals). After the first install, restart your Claude Code session and invoke it anywhere:

/kb-ask 新能源汽车技术有哪些

Configuration

MCP behavior is controlled by these env vars (same .env as the rest of doclens):

Variable Default Description
CORTEX_MCP_ENABLED true Auto-start the MCP server in TUI/GUI. Set false to disable.
CORTEX_MCP_PORT 7880 MCP HTTP port (override via this env var).
CORTEX_MCP_HOST 127.0.0.1 Bind address. Non-loopback requires CORTEX_MCP_TOKEN.
CORTEX_MCP_TOKEN Bearer token enforced when host is non-loopback.

Troubleshooting

Symptom Fix
claude mcp list shows doclens missing / ✘ doclens not running, or wrong port. Start doclens, read the URL from its log, re-add.
Tools mcp__doclens__* not available in session MCP loads at session start — restart the Claude Code session after adding.
search_kb returns nothing Keywords may not match FTS tokens. Try synonyms, EN↔CN, or rebuild the index: doclens index --force.
Non-loopback start refused Set CORTEX_MCP_TOKEN, or bind back to 127.0.0.1.

Configuration

doclens reads .env in the project root. Copy and customize:

cp doclens/.env.example .env

Key variables:

Variable Default Description
CORTEX_SEARCH_PATH . Root directory to index and search
CORTEX_DB_PATH .cortex/sessions.db SQLite database path
ANTHROPIC_API_KEY Required for ai and web commands
ANTHROPIC_BASE_URL Custom API endpoint (optional)

Troubleshooting

PST indexing fails on Windows (WinError 225)

When indexing Outlook .pst archives, Microsoft Defender may block the parser sidecar with:

[WinError 225] 无法成功完成操作,因为文件包含病毒或潜在的垃圾软件

Cause: the sidecar (pst-extract.exe) extracts email attachments to a temp dir; once any attachment is flagged as malware, Defender cascades and blocks pst-extract.exe itself, so every subsequent PST fails instantly — while the index still reports "complete".

Fix — run in an admin PowerShell 7:

# Exclude the sidecar by process name to stop the cascade (works regardless of install location)
Add-MpPreference -ExclusionProcess "pst-extract.exe"
# Optional: stop extracted attachments from being scanned/quarantined
Add-MpPreference -ExclusionPath "<your-pst-directory>"

Then rebuild: doclens index --force --workdir <your-pst-directory>

⚠️ Real mail archives can contain malicious attachments. With the exclusion in place, those files land in <workdir>/.cortex/pst_attachments/ unscanned — use them for search only, never open or execute them.

PST indexing is serialized (max_pst_concurrency=1): each PST launches a heavy sidecar, so they run one at a time to avoid the memory/IO contention that previously crashed the sidecar. A 10+ GB archive takes a few minutes; progress is logged every 30 s.


Architecture

┌─────────────────────────────────────────────┐
│                  TUI (Textual)              │
│  ┌───────────────────────────────────────┐  │
│  │  HeaderBar │ ContentArea │ InputBox   │  │
│  └───────────────────────────────────────┘  │
└────────────────────┬────────────────────────┘
                     │
┌────────────────────▼────────────────────────┐
│           Web UI (Lit + Shoelace PWA)      │
│         FastAPI + SSE streaming             │
└────────────────────┬────────────────────────┘
                     │
┌────────────────────▼────────────────────────┐
│         IndexManager + Scoring              │
│    TreeSearch (FTS5 + BM25)                │
└────────────────────┬────────────────────────┘
                     │
┌────────────────────▼────────────────────────┐
│    treesearch/  —  parsers, indexer, FTS5  │
│    planify/     —  AI agent runner          │
└─────────────────────────────────────────────┘
  • treesearch: Powers the indexing and retrieval engine (FTS5/BM25 over document trees)
  • planify: Drives the AI agent, session management, and tool execution
  • doclens: Ties them together — CLI, TUI, Web UI, event bus, and file watcher

License

Apache License 2.0 — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

doclens-1.1.25.tar.gz (6.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

doclens-1.1.25-py3-none-any.whl (6.7 MB view details)

Uploaded Python 3

File details

Details for the file doclens-1.1.25.tar.gz.

File metadata

  • Download URL: doclens-1.1.25.tar.gz
  • Upload date:
  • Size: 6.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.0

File hashes

Hashes for doclens-1.1.25.tar.gz
Algorithm Hash digest
SHA256 56c15ea5d72ea73402346413027dcbda5aa03e1e4d50696b263d58c31d6d4423
MD5 85757e5a796c42da6ed734c5524bdd54
BLAKE2b-256 778f13afd113dc524d9a60ccf2f6def408cf8c6388910bbd78f007da7d74dad6

See more details on using hashes here.

File details

Details for the file doclens-1.1.25-py3-none-any.whl.

File metadata

  • Download URL: doclens-1.1.25-py3-none-any.whl
  • Upload date:
  • Size: 6.7 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.0

File hashes

Hashes for doclens-1.1.25-py3-none-any.whl
Algorithm Hash digest
SHA256 320c303b269cca0c804e8be09873a3b087cc2671924a138ab1ac231c5c445abb
MD5 5d38ab905b37f0504a6613dcdf8e2fd4
BLAKE2b-256 ad3cde2cbbe8bb8c100ba72662e2c053c8bab0faa74a8650065994e6f91cf6aa

See more details on using hashes here.

Release history Release notifications | RSS feed

1.1.44

1 file

1.1.43

1 file

1.1.42

2 files

1.1.41

2 files

1.1.40

2 files

1.1.39

2 files

1.1.38

2 files

1.1.37

2 files

1.1.35

2 files

1.1.34

2 files

1.1.33

2 files

1.1.32

2 files

1.1.31

2 files

1.1.30

2 files

1.1.29

2 files

1.1.28

2 files

1.1.27

2 files

1.1.26

2 files

This release

1.1.25 This release

2 files

1.1.24

2 files

1.1.23

2 files

1.1.22

2 files

1.1.21

2 files

1.1.20

2 files

1.1.19

2 files

1.1.18

2 files

1.1.17

2 files

1.1.16

2 files

1.1.15

2 files

1.1.14

2 files

1.1.13

2 files

1.1.12

2 files

1.1.11

2 files

1.1.10

2 files

1.1.9

2 files

1.1.8

2 files

1.1.7

2 files

1.1.6

2 files

1.1.5

2 files

1.1.3

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page