Metadata-Version: 2.4
Name: loom-tool
Version: 0.3.5
Summary: A code intelligence platform that turns repositories, docs, and tickets into one searchable graph.
Project-URL: Homepage, https://github.com/devashishjadav/loom
Project-URL: Issues, https://github.com/devashishjadav/loom/issues
Author-email: Devashish <jadhavom24@gmail.com>
License: MIT
License-File: LICENSE
Keywords: agent,code-intelligence,mcp,symbol-index,tree-sitter
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: fastmcp>=3.0.2
Requires-Dist: gitpython>=3.1.46
Requires-Dist: networkx>=3.3
Requires-Dist: pathspec>=1.0.4
Requires-Dist: pydantic>=2.12.5
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: rich>=14.3.3
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
Requires-Dist: tree-sitter-java>=0.23.5
Requires-Dist: tree-sitter-javascript>=0.25.0
Requires-Dist: tree-sitter-python>=0.25.0
Requires-Dist: tree-sitter-typescript>=0.23.2
Requires-Dist: tree-sitter>=0.25.2
Requires-Dist: typer>=0.24.1
Description-Content-Type: text/markdown

# Loom

> A persistent symbol index for AI coding agents. Agents find functions instantly. Agents write summaries as they work. The cache gets richer every session — zero LLM cost from Loom's side.

## What Loom is

Loom indexes your codebase into a local SQLite database using tree-sitter. It extracts functions, classes, methods, and call relationships across all languages. Agents query it to skip file exploration and read only what they need. When an agent understands a function, it writes a summary back — the next agent gets it for free.

**Core loop:**

```
loom analyze .              # tree-sitter indexes all symbols → ~/.loom/projects/myrepo.db
search_code("login")        # instant: {name, path, line, summary, signature}
get_context(node_id)        # full picture: summary + callers + callees, one call
store_understanding(id, s)  # cache what you learned → returned on future searches
```

No Docker. No embeddings. No LLM calls from Loom. Pure tree-sitter + SQLite.

## Why it matters

Every Claude Code / Cursor / Codex session starts by re-exploring the codebase: reading CLAUDE.md, grepping for functions, re-discovering structure. Loom eliminates that.

| Repo | Files | Without Loom | With Loom | Reduction |
|------|-------|-------------|-----------|-----------|
| replay-agent | 35 Python | ~22,112 tokens | ~433 tokens | **51× fewer** |
| finpower | 678 TS/TSX/Python/Go | ~794,462 tokens | ~527 tokens | **1,507× fewer** |

- **Session 1:** agent reads files, stores summaries → Loom gets smarter
- **Session 2+:** summaries returned instantly → file reads skipped entirely
- **Compounding:** every session makes Loom richer for every future agent

## Installation

```bash
pip install loom-tool
# or with uv:
uv add loom-tool
```

Requirements: Python 3.10+. Tested on 3.10, 3.11, 3.12, 3.13, 3.14. No Docker. No external services.

**If you see `ModuleNotFoundError: No module named 'tree_sitter_language_pack'`** — pip sometimes silently skips binary deps on newer Python versions. Fix:

```bash
pip install loom-tool tree-sitter-language-pack
```

Or use `uvx` which manages an isolated environment automatically:

```bash
uvx --from loom-tool loom --help
```

### Claude Code plugin

Anyone can install directly from GitHub:

```
/plugin marketplace add ddevilz/loom
/plugin install loom@loom-tool
```

Installs the MCP server (`uvx --from loom-tool loom-mcp`) and the `/loom` skill automatically.

## Quick start

```bash
cd my-repo
loom analyze .      # index the repo (~10s for 500 files)
loom install        # configure Claude Code, Cursor, Windsurf, Codex + git hook
loom serve          # start MCP stdio server
```

After `loom install`, MCP clients connect automatically. Claude Code sessions get the `loom://primer` resource loaded at startup.

## Project-isolated databases

Loom auto-detects the git root and creates a per-project database. No flags needed.

```
~/.loom/projects/
  my-api.db          ← cd ~/projects/my-api && loom analyze .
  frontend.db        ← cd ~/projects/frontend && loom analyze .
  loom.db            ← cd ~/projects/loom && loom analyze .

~/.loom/loom.db      ← fallback when not inside a git repo
```

Override with `LOOM_DB_PATH` env var or `--db` flag.

## CLI reference

| Command | Purpose |
|---------|---------|
| `loom analyze <path>` | Index or refresh the graph for a repo |
| `loom sync [--old-sha] [--new-sha]` | Incremental sync of changed files via SHA-256 |
| `loom context [-m module]` | Print ~200-token session primer (modules, hot functions, coverage) |
| `loom serve` | Start MCP stdio server |
| `loom install [--platform] [--list-plugins]` | Configure MCP for all detected AI tools + git hook |
| `loom query <text>` | FTS5 / name search across nodes |
| `loom blast-radius <target>` | Show transitive callers of a function |
| `loom callers <target>` | Direct callers (one-hop incoming CALLS) |
| `loom callees <target>` | Functions this target calls (one-hop outgoing CALLS) |
| `loom communities` | Run Louvain community detection |
| `loom dead-code` | Mark functions with no incoming CALLS |
| `loom summaries [-n N]` | Show agent-written summaries, most recent first |
| `loom savings [-n N]` | Token savings dashboard — totals + recent cache hits |
| `loom stats` | Node/edge counts by kind |
| `loom export` | Self-contained interactive HTML graph |

## MCP tools

| Tool | Purpose |
|------|---------|
| `search_code(query, limit)` | FTS5 search — returns summary + signature when cached |
| `get_node(node_id)` | Single node by id |
| `get_context(node_id)` | Full context packet: summary, signature, callers, callees, staleness |
| `get_callers(node_id)` | One-hop incoming CALLS |
| `get_callees(node_id)` | One-hop outgoing CALLS |
| `get_blast_radius(node_id, depth)` | Transitive callers via recursive CTE |
| `get_neighbors(node_id, depth)` | All edges, both directions |
| `get_community(community_id)` | All members of a community cluster |
| `shortest_path(from_id, to_id)` | Shortest directed path on CALLS subgraph |
| `graph_stats()` | Node/edge counts by kind |
| `god_nodes(limit)` | Most-called functions (highest in-degree) |
| `store_understanding(node_id, summary, force?)` | Cache agent-generated summary permanently. Returns `skipped: true` if summary already fresh — no re-write needed. |
| `store_understanding_batch(updates)` | Batch version, max 50 per call |
| `get_savings()` | Token savings report — all-time totals + 10 recent hits |
| `start_session(agent_id)` | Register session start, returns session_id |
| `get_delta(previous_session_id)` | What changed since last session (changed + deleted nodes) |

**MCP resources:**

| Resource | Purpose |
|----------|---------|
| `loom://primer` | ~200-token codebase overview — load at session start |
| `loom://savings` | Token savings report — totals + recent cache hits |

## Node ID format

`{kind}:{relative-path}:{symbol}`

```
function:src/auth.py:validate_token
method:src/models/user.py:User.save
class:src/models/user.py:User
file:src/auth.py
```

## Agent workflow

```
# Session start
resource = read("loom://primer")         # orient: modules, hot functions, coverage
start_session(agent_id="claude-code")    # store returned session_id

# Or if returning:
get_delta(previous_session_id="<id>")   # only what changed since last time

# Finding code
results = search_code("validate token") # summary + signature included
# If results[0].summary → read summary, skip file

# Before reading any file
ctx = get_context("function:src/auth.py:validate_token")
# Returns callers, callees, summary, staleness — often enough to reason without reading

# After understanding a function
store_understanding(
    node_id="function:src/auth.py:validate_token",
    summary="Validates JWT tokens, returns False if expired or signature invalid."
)
# Returns {"ok": true, "skipped": false} — written
# Returns {"ok": true, "skipped": true}  — already fresh, no re-write needed
```

## How summaries work

**Auto-summaries:** `loom analyze` fills summaries from static metadata (params, return type, decorators) via tree-sitter. Coverage goes from 0% → ~80% on first analyze. No LLM.

**Agent summaries:** `store_understanding` stores a summary permanently with a `summary_hash` (snapshot of `content_hash` at write time).

- If source changes → `summary_stale: true` in `get_context` → agent re-reads and updates
- If source unchanged → `store_understanding` returns `skipped: true` → no duplicate writes
- Pass `force: true` to overwrite regardless

**Priority:** Agent summaries are never overwritten by auto-summaries. Re-analyzing preserves agent work.

## Plugin system

`loom install` uses a plugin registry. Built-in plugins: `claude-code`, `cursor`, `windsurf`, `codex`.

Add a custom platform without editing any source:

```python
# ~/.loom/plugins/zed.py
from loom.cli.plugins import Plugin, register
from pathlib import Path

register(Plugin(
    name="zed",
    config_path=Path.home() / ".config" / "zed" / "mcp.json",
    config_key="mcpServers",
))
```

```bash
loom install --list-plugins   # see all registered plugins
loom install --platform zed   # install only for Zed
```

## Session delta — how it works

```
Session 1:                     Session 2:
  start_session()                get_delta(previous_session_id)
  [work on auth.py]              → {changed: [2 fns], deleted: [], unchanged: 310}
  session_id stored              Only read the 2 changed functions. Skip the rest.
```

Delta uses `updated_at` on nodes — only bumped when `content_hash` changes. Safe against false positives from re-analyzing identical files.

## Token savings tracking

Every `search_code` hit with a cached summary records how many tokens were saved (source line count × 15 — no extra deps, no index overhead).

```bash
loom savings          # CLI dashboard
```

```
Total tokens saved: 127,400
Cache hits: 847  (agent: 23  auto: 824)
agent = store_understanding summaries (provably skipped file reads)
auto  = metadata summaries from loom analyze
```

Inside Claude Code, call `get_savings()` MCP tool or load `loom://savings` resource for the same report.

`search_code` results include `tokens_saved` and `summary_type` per hit when a summary is cached.

## Auto-indexing

When installed via the Claude Code plugin, Loom auto-indexes the current project on first session start — no manual `loom analyze` needed. If the DB is empty when the MCP server starts, indexing runs in the background while the session continues.

## Supported languages

Code extraction (functions, methods, classes, calls): **Python, TypeScript, TSX, JavaScript, JSX, Java**

Indexed as file nodes: HTML, CSS, JSON, YAML, TOML, XML, INI, .env, .properties

## Schema

Full DDL in [`src/loom/core/schema.sql`](src/loom/core/schema.sql). Two core tables:

```sql
nodes    -- id, kind, name, path, language, summary, summary_hash,
            token_count, content_hash, start_line, end_line, metadata, deleted_at, updated_at
edges    -- from_id, to_id, kind, confidence
savings  -- ts, node_id, query, tokens_saved, summary_type
sessions -- id, agent_id, started_at
meta     -- key/value counters (savings totals)
```

FTS5 virtual table `nodes_fts` indexes name + summary + path for full-text search.
Sessions table tracks agent session timestamps for delta context.

## Architecture

```
src/loom/
├── core/          # Node/Edge models, DB context, schema.sql
├── ingest/        # index_repo, sync_paths, tree-sitter parsers per language
├── analysis/      # communities (Louvain), coupling (git co-change), dead code
├── query/         # search, blast_radius, context packets, primer, delta
├── store/         # nodes CRUD, sessions, savings, FTS5 sync
├── mcp/           # FastMCP server (server.py), standalone entry point (run.py)
├── cli/           # typer commands
│   └── plugins/   # platform plugin registry (claude-code, cursor, windsurf, codex)
├── templates/     # graph.html — interactive export UI
└── data/          # loom-skill.md — Claude Code skill installed by loom install
```

## Development

```bash
git clone https://github.com/ddevilz/loom
cd loom
uv sync
uv run pytest
uv run ruff check .
uv run mypy src/
```

## License

MIT - Free for personal and commercial use
