LLMScribe

License PyPI Version Downloads GitHub Contributors Visit llmscribe.vercel.app Official MCP Registry

Follow on X Follow on GitHub

--- # **LLMScribe** **Turn any code repository into clean, structured, deterministic data.** No AI. No embeddings. No hidden ranking. Apache-2.0, and it runs entirely on your machine — no network, no account. GitHub stars --- ## The problem Your agent does not have an intelligence problem. It has a **retrieval** problem. On a 1.4-million-line codebase, one benchmark agent burned 6,000 seconds and produced nothing — no analysis, no output, zero score. The same model, given structured code search instead of free-form file reading, finished the same task in **89 seconds** and scored 0.90. Across another benchmark, Codex CLI completed its entire turn sequence without ever reaching the file that would have solved the task in **27–29% of runs**. Handed the right context up front, its score nearly doubled. The bottleneck is not the model. It is what goes into the context window. What users keep reporting: - The agent explores 200 files to change one line, and admits it is "looking at unnecessary files" - Nine searches and fourteen files to find one constant, because the search itself is not ranked - The same files re-read in a loop, with no reasoning between the reads - Stale fixtures, mock data and outdated comments read as current truth - Search reporting "no matches found" when a plain `grep` finds the text immediately - Truncation that hides itself, and build output filling the window with noise ## What LLMScribe does about it | The failure | What LLMScribe does | | --- | --- | | Reads 200 files to change one line | `project_map` returns the whole tree with contents excluded, before a single file is read | | Re-reads the same files in a loop | Output is deterministic — same input, same bytes, every run | | Misses the file that actually mattered | `project_dependencies` resolves local, stdlib, external and unresolved imports, plus reverse dependencies | | Search returns nothing when the text exists | `search` returns path, line, matched text and match type, or a stable error code — never a silent empty | | Stale fixtures read as current truth | Nothing is inferred, embedded or ranked; you get the files as they are, plus a Git diff | | Build output and binaries fill the context | Real `.gitignore` semantics; binaries and oversized files are skipped | | Context silently truncated | Every cut is reported: `truncated`, `truncation_note`, `omitted_files` | > The file an agent needs next is usually the one *structurally* related to the file it is already looking at — a dependent, a sibling module, a test fixture. That is a graph question, not a similarity question, which is why LLMScribe ships dependency analysis and a real tree instead of embeddings. --- ## Feature Overview **Core Tools** | Feature | Description | |---------|-------------| | [**Map**](#map) | Generate a clean directory tree without dumping file contents | | [**Search**](#search) | Search file paths, file names, file contents, and individual lines | | [**Read**](#read) | Safely retrieve a specific file | **More** | Feature | Description | |---------|-------------| | [**Read Many**](#read-many) | Retrieve multiple files in a single operation | | [**Dependencies**](#dependencies) | See what a file depends on and what depends on it | | [**Diff**](#diff) | Inspect Git status and unified diffs | | [**Overview**](#overview) | Export the complete structure and supported file contents | --- ## Quick Start Install LLMScribe from PyPI: ```bash pip install llmscribe ``` Then point it at any project directory on your machine. No API key, no network access, no account. > The `project_map(...)`, `search(...)`, `read(...)` snippets below show **MCP tool calls**. The same operations are available from the CLI (local directories) and from Python through `llmscribe.core` (see [Python API](#python-api)). ### Map Generate a clean directory tree without file contents. This is the best first step when exploring an unfamiliar repository. ```python project_map() ```
CLI / MCP **CLI** ```bash llmscribe map llmscribe map --json ``` **MCP** ```text project_map ```
Output: ```text src/ ├── api/ │ ├── routes.py │ └── auth.py ├── models/ │ └── user.py └── main.py ``` ### Search Search across file paths, file names, file contents, and individual lines. Search is intentionally deterministic: LLMScribe does not try to guess what you meant. ```python search(query="authentication") ```
CLI / MCP **CLI** ```bash llmscribe search "authentication" llmscribe search "authentication" --json ``` **MCP** ```text search ```
Each match includes the file path, line number, the matching line, the matched text and the match type (`filename` or `content`). Results are ordered by path then line, and limited to 1,000 matches. Binary and oversized files are skipped. Output (`--json`, `data.matches`): ```json [ { "file_path": "src/auth/service.py", "line_number": 12, "line_content": "def authenticate(user, password):", "match_type": "content", "matched_text": "authenticate" } ] ``` ### Read Safely retrieve the contents of a specific file. LLMScribe validates paths and prevents path traversal outside the project. ```python read(file_path="src/auth/service.py") ```
CLI / MCP **CLI** ```bash llmscribe read src/auth/service.py ``` **MCP** ```text read ```
--- ## Power Your Agent Instead of throwing an entire repository into a context window, an agent can progressively retrieve exactly what it needs: ```text 1. project_map() ↓ 2. search("authentication") ↓ 3. read("src/auth/service.py") ↓ 4. project_dependencies("src/auth/service.py") ↓ 5. read_many([...]) ``` ### MCP LLMScribe is a standard Model Context Protocol server that runs locally over stdio. Any MCP-compatible client can use it against a project directory on your machine. **Config** — put this in your client (see the per-app setup below): ```json { "mcpServers": { "llmscribe": { "command": "llmscribe-mcp" } } } ```
Use the Python module instead of the command If `llmscribe-mcp` is not on your `PATH`, point the client at the module: ```json { "mcpServers": { "llmscribe": { "command": "python", "args": ["-m", "llmscribe.mcp"] } } } ```
#### Per-app setup Each client reads a different configuration file. The blocks below were checked against each tool's official documentation.
Claude Desktop Edit `claude_desktop_config.json` (in the app: **Settings → Developer → Edit Config**): - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` - Windows: `%APPDATA%\Claude\claude_desktop_config.json` ```json { "mcpServers": { "llmscribe": { "command": "llmscribe-mcp" } } } ``` Fully quit and reopen Claude Desktop after saving.
Claude Code ```bash claude mcp add llmscribe -- llmscribe-mcp ``` Confirm with `claude mcp list`. Add `--scope user` to make it available in every project, or `--scope project` to share it with your team via `.mcp.json`.
Cursor Create `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` for all projects): ```json { "mcpServers": { "llmscribe": { "command": "llmscribe-mcp" } } } ``` Restart Cursor, then check **Customize → MCPs**.
VS Code (GitHub Copilot) Create `.vscode/mcp.json` in your workspace. Note that VS Code uses `servers`, not `mcpServers`: ```json { "servers": { "llmscribe": { "type": "stdio", "command": "llmscribe-mcp" } } } ``` Then open Copilot Chat in **Agent** mode and click the tools icon to start the server.
Windsurf (Cascade) Edit `~/.codeium/mcp_config.json` (in the app: **Windsurf Settings → Cascade → MCP → View Raw Config**): ```json { "mcpServers": { "llmscribe": { "command": "llmscribe-mcp" } } } ``` Press the refresh button after saving.
Cline Open the Cline panel → **MCP Servers** → **Configure** → **Configure MCP Servers**, then add: ```json { "mcpServers": { "llmscribe": { "command": "llmscribe-mcp" } } } ```
Roo Code Edit the global `mcp_settings.json` (**Edit Global MCP**), or create `.roo/mcp.json` in your project (**Edit Project MCP**): ```json { "mcpServers": { "llmscribe": { "command": "llmscribe-mcp" } } } ```
LM Studio In the app: **Program** tab → **Install → Edit mcp.json**. The file is `~/.lmstudio/mcp.json` on macOS/Linux, `%USERPROFILE%\.lmstudio\mcp.json` on Windows: ```json { "mcpServers": { "llmscribe": { "command": "llmscribe-mcp" } } } ``` LM Studio follows Cursor's `mcp.json` notation.
Zed Add to your Zed settings (in the app: **Settings → AI → MCP Servers → Add Server**, or `zed: open settings file`): ```json { "context_servers": { "llmscribe": { "command": "llmscribe-mcp", "args": [], "env": {} } } } ```
Continue Add to `~/.continue/config.yaml` (or a standalone file under `.continue/mcpServers/`): ```yaml name: LLMScribe version: 1.0.0 schema: v1 mcpServers: - name: LLMScribe command: llmscribe-mcp ``` Continue also picks up Cursor/Claude/Cline JSON configs dropped into `.continue/mcpServers/`.
JetBrains IDEs (IntelliJ, WebStorm, …) **Settings → Tools → AI Assistant → Model Context Protocol (MCP) → Add → As JSON**: ```json { "mcpServers": { "llmscribe": { "command": "llmscribe-mcp" } } } ``` You can also click **Import from Claude** to reuse an existing Claude Desktop configuration.
Goose Add an extension to `~/.config/goose/config.yaml`: ```yaml extensions: llmscribe: name: llmscribe enabled: true type: stdio cmd: llmscribe-mcp args: [] timeout: 300 ```
OpenAI Codex CLI Add to `~/.codex/config.toml`: ```toml [mcp_servers.llmscribe] command = "llmscribe-mcp" ```
**Available tools** ```text project_map project_overview search read read_many project_dependencies project_diff ``` --- ## More Tools ### Read Many Retrieve multiple files in a single operation. Partial success is supported, so one problematic file does not invalidate the entire request. ```python read_many([ "src/auth/service.py", "src/auth/models.py", "src/api/login.py" ]) ``` ```bash llmscribe read-many src/auth/service.py src/api/login.py ``` ### Dependencies Inspect the dependency relationships around a file. LLMScribe identifies local dependencies, external dependencies, unresolved dependencies, and the files that depend on this file. ```python project_dependencies("src/auth/service.py") ``` ```bash llmscribe dependencies src/auth/service.py --json ``` Output: ```text src/auth/service.py │ ├── depends on │ ├── auth/models.py │ ├── auth/config.py │ └── auth/utils.py │ └── used by ├── api/login.py └── tests/test_auth.py ``` This is particularly useful when determining the potential impact of modifying a file. ### Diff Inspect repository changes using Git. Supports Git status, unstaged changes, staged changes, specific commits, and unified diffs. ```bash llmscribe diff ``` This lets applications and agents understand not only the current repository, but also **what changed**. ### Overview Generate a complete project snapshot containing the directory structure, supported text file contents, and structured project information. ```bash llmscribe overview ``` Best for small and medium-sized projects. For large repositories, use the recommended workflow instead: ```text map → search → read ``` --- ## CLI Every command can return machine-readable JSON with `--json`, which makes the CLI a building block for scripts, automation, and developer tools. ```bash llmscribe map llmscribe overview llmscribe search "authentication" llmscribe read src/auth/service.py llmscribe read-many src/auth/service.py src/api/login.py llmscribe dependencies src/auth/service.py llmscribe diff # machine-readable output llmscribe map --json llmscribe search "auth" --json llmscribe dependencies src/auth/service.py --json ``` --- ## Configuration LLMScribe runs entirely on your machine and needs no configuration. Two optional environment variables restrict which directories the MCP server may read: | Variable | Description | Default | |----------|-------------|---------| | `MCP_ALLOWED_ROOTS` | Directories (separated by `:` on POSIX, `;` on Windows) the tools may read | all paths | | `MCP_ALLOW_LOCAL_PATHS` | `0` disables local path access entirely | enabled | --- ## Python API ```python from pathlib import Path from llmscribe.core import project_map, search_project, read_file, read_files, analyze_dependencies, get_git_diff, LLMScribeError root = Path(".") print(project_map(root).tree) print(search_project("auth", root).to_dict()) print(read_files(["README.md", "missing.py"], root).to_dict()) # per-file errors, never raises try: analyze_dependencies("src/app.py", root) except LLMScribeError as err: # err.code is a stable machine-readable code print(err.code, err.message) ``` ## Behavior reference ### Ignore rules Defaults (`.git`, `node_modules`, `venv`, `dist`, `build`, `.env`, `*.log`, …), the root `.gitignore` and nested `.gitignore` files are applied with real Git semantics: wildcards, directories, `!` negation, and root-anchored patterns. Hidden files are included unless ignored. Symlinks are never followed or listed. ### Supported text files Known source, config and doc extensions, plus names such as `Dockerfile`, `Makefile`, `LICENSE` and `.gitignore`. Other files appear in the tree, but cannot be read or searched. ### Limits One source of truth: `llmscribe.core.limits`. - 400,000 content characters per `project_overview` / `read_many` - 50 files per `read_many` - 1,000 search matches - 20,000 map entries - 2 MiB per file - 200,000 diff characters - 100,000 scanned entries Anything cut is reported: `truncated`, `truncation_note`, `omitted_files`. ### Errors Every failure has a stable, machine-readable code: `invalid_argument` · `invalid_path` · `file_not_found` · `unsupported_file_type` · `binary_file` · `file_too_large` · `read_error` · `not_a_repository` · `git_unavailable` · `unsupported_operation` · `internal_error` JSON errors look like this: ```json {"ok": false, "tool": "...", "error": {"code": "...", "message": "..."}} ``` ### Dependencies Supported languages: Python, JavaScript/TypeScript, Java, Go, Rust, and C/C++. Each reference is classified as one of: - `local` — resolved to a file or directory inside the project - `stdlib` — part of the language's standard library - `external` — not in the project, assumed third-party - `unresolved` — a relative or local-looking reference that matches nothing `used_by` lists the reverse dependencies. ### Git diff Runs `git` with an argument list, a 30 s timeout, a minimal environment, and without external diff/textconv drivers. ### Migration notes - Legacy tool names (`project_get_file`, `project_get_files`, `project_search`, `project_list_files`) are gone; use `read`, `read_many`, `search`. - Error code `path_traversal` is now `invalid_path`; `not_text_file` is `unsupported_file_type`. - `project_dependencies` results: `all_local_files`/`all_external_deps`/`all_unresolved` were replaced by `used_by` and per-category lists (`stdlib_dependencies` added). - `llmscribe.core` functions raise `LLMScribeError` (not `FileNotFoundError`) for a bad root. - **1.3.0:** the online GitHub source was removed — LLMScribe is now local-only. The `repo` and `ref` arguments, the in-memory snapshot cache, the `llmscribe.github` package, and the hosted HTTP transport are gone. Point the tools at a local `path`. --- ## Architecture All interfaces share one core engine, so behavior stays consistent everywhere. ```text Repository │ ▼ Local Project │ ▼ LLMScribe Core │ ┌─────────────────────┼─────────────────────┐ │ │ │ ▼ ▼ ▼ CLI MCP GUI │ │ └──────────────┬──────┘ ▼ Structured Output / JSON ``` --- ## Philosophy LLMScribe intentionally stays simple. The goal is not to make the repository "smarter." The goal is to make the repository **accessible to software**. **We provide** - Repository extraction - Deterministic search - Structured project data - File retrieval - Dependency information - Git information - Multiple interfaces **We don't provide** - ❌ AI-generated answers - ❌ Embedding-based search - ❌ Semantic ranking - ❌ Autonomous coding - ❌ An AI coding agent - ❌ A generic Git client --- ## Use Cases - AI coding agents - MCP applications - Developer tools - Code search interfaces - Repository explorers - Documentation systems - Code analysis pipelines - Automation scripts - Local LLM applications - Exploring unfamiliar open-source projects --- ## Open Source LLMScribe is open source under the **Apache License 2.0**. Inspect the source, modify it, and build your own integrations. There is no hosted service and no telemetry. It reads your files, and nothing leaves your machine. --- ## Resources - **Website:** https://llmscribe.vercel.app - **GitHub:** https://github.com/AMRITO-KUNDU/llmscribe - **PyPI:** https://pypi.org/project/llmscribe/ - **Official MCP Registry:** https://registry.modelcontextprotocol.io/?q=llmscribe (`io.github.AMRITO-KUNDU/llmscribe`) - **Issues:** https://github.com/AMRITO-KUNDU/llmscribe/issues - **Contributing:** https://github.com/AMRITO-KUNDU/llmscribe/blob/main/CONTRIBUTING.md --- ## Contributing Contributions are welcome — whether that is repository extraction, search, dependency analysis, interfaces, integrations or documentation. Check the [contributing guide](https://github.com/AMRITO-KUNDU/llmscribe/blob/main/CONTRIBUTING.md) before opening a pull request. Contributors --- ## License LLMScribe is licensed under the **Apache License 2.0**. See the [LICENSE](https://github.com/AMRITO-KUNDU/llmscribe/blob/main/LICENSE) file for details.
*Repository data, structured.* ↑ Back to top