SEAM · ARCHITECTURE · v0.3.0

The structure of a
codebase, computed once.

Seam parses a repository with tree-sitter, stores it as a typed graph in local SQLite, and exposes it over twelve read-only MCP tools — so an AI agent queries structure instead of reconstructing it with grep every session.

12 LANGUAGES · 12 TOOLS · 9 EDGE KINDS · SQLITE + FTS5 · ZERO NETWORK AT QUERY TIME

01 · THE THESIS

Structural knowledge is computable.

An agent that greps to answer "what breaks if I change this?" rebuilds a call graph by hand, every session, from scratch. That graph already exists in the parser. Seam computes it once and answers the question directly.

▽ without seam

grep init_db → 14 files → open each → trace imports → reconstruct the graph by hand. ~30k tokens, often wrong.

△ with seam

seam_impact init_db → blast radius bucketed by risk tier, graph-accurate, with provenance. ~4.5k tokens.

02 · SYSTEM PIPELINE

One write path. Three read transports.

Source is parsed into a SQLite graph; two post-passes enrich it (clusters, synthesis); a watcher keeps it fresh. Reads fan out to the MCP server, the CLI, and the web explorer — all over the same engine.

WRITE PATH source files 12 languages tree-sitter parse · never raises indexer pipeline symbols + 15-kind edges .seam/seam.db SQLite + FTS5 · schema v16 clustering post-pass synthesis post-pass init / sync only — not the watcher watchdog debounced re-index READ PATH resolve · BFS traverse · shape caps · lean · byte ceiling · staleness banner MCP server · 19 tools CLI read commands Seam Explorer (web) AI agent Claude Code · Cursor · Codex
CHARTREUSE = write path · MAGENTA = read path · DASHED = background / async
03 · LAYERED ARCHITECTURE

Dependencies flow one way — down.

A lower layer never imports an upper one. The analysis layer is built from pure leaf modules — stdlib only, no DB, no IO, never raise — so each algorithm is testable in isolation and the read path's failure surface is tiny.

cli · server · watcher · web entry points & transports analysis impact · trace · changes · clusters · pure leaves query engine · pack · semantic · structure indexer · db parse → extract → upsert · SQLite
IMPORT HIERARCHY — read top-to-bottom

Pure leaf modules

No database, no IO, never raise — degrade to an empty/neutral result on error.

clustering · rwr · relevance · byte_budget · steer · staleness · builtins · imports

The facade split

server/tools.py re-exports every handler so all imports stay byte-identical, while the implementation lives in focused sub-1000-line files: impact_handler, trace_handler, handler_common.

04 · THE GRAPH

Symbols are nodes. Ten relationships are edges.

Edges are keyed by symbol name, not row id — which is exactly what lets the watcher re-index one file without rewriting the rest of the graph. Traversal is kind-agnostic, so every tool sees every edge kind for free.

Server Client Handler AuthImpl Config.url load() holds call implements synthesized call reads / writes instantiates
BLUE = structural · CHARTREUSE = synthesized (heuristic) · MAGENTA = data-flow
EdgeCaptures
callone symbol invokes another
importa module / symbol import
extendssubclass → base class
implementsclass → interface
instantiatesnew Foo() / struct literal
holdsclass stores a typed field (composition)
usesfunction references a type as a parameter
readsa field is read (data-flow)
writesa field is written / deleted
http_callsliteral local client calls → route symbols · no dynamic URL guessing · direct provenance
reads_configcode reads a literal config/env key
configuresa config key describes a runtime resource
05 · DATA FLOW

Write once. Resolve at read.

Confidence is recomputed at read time against the live name-count map — so a single-file watcher edit keeps the whole graph correct with no backfill.

Write path · seam init

1 walk tree → collect files by extension 2 per file: parse → extract → upsert symbols · 15-kind edges · comments · imports · routes · config/resources 3 clustering post-pass (whole graph) 4 synthesis post-pass (after clusters) 5 [--semantic] embedding post-pass 6 commit · watcher starts

Read path · a tool call

1 validate + clamp inputs 2 resolve_edge → confidence + import promote 3 BFS traverse (kind-agnostic) 4 shape: tiers · cap · lean · byte ceiling 5 attach index_status if stale 6 finalize MCP envelope

Resolution order — resolve_edge()

1 · importsame-file import binds target to one declarer → EXTRACTED (the homonym fix)
2 · name-countcount==1 → EXTRACTED · count>1 → AMBIGUOUS + proximity best_candidate
3 · builtinfires only at count==0 — a user-declared name can never be misread as builtin
4 · fallbackcount==0, not builtin → INFERRED / unresolved
06 · THE INTERFACE

Sixteen read-only tools, grouped by question.

The server never writes the index. Each tool answers one question an agent actually asks.

find code

seam_search
Where is text X mentioned? FTS5 + fuzzy fallback + optional semantic.
seam_query
Find all code related to concept X — match + 1-hop expansion.

understand a symbol

seam_context
Everything about X: callers, callees, signature, cluster.
seam_context_pack
A paste-ready bundle, neighbors ranked by relevance.
seam_why
The WHY / HACK / NOTE / TODO comments on X.

assess change risk

seam_impact
What breaks if I change X? Blast radius by risk tier.
seam_changes
Is my current git diff risky?
seam_affected
Which tests should I run for these files?

navigate & map

seam_trace
How does X reach Y? Shortest path, hop by hop.
seam_flows
Where does execution start, and where does it go?
seam_clusters
What are the functional areas? (Louvain communities)
seam_structure
How is the repo physically laid out?
07 · GRADED CERTAINTY

Seam never hides uncertainty — it grades it.

Confidence tiers

EXTRACTEDtarget is unambiguous — high certainty
AMBIGUOUSname collides — verify by reading
INFERREDheuristic / cross-module / synthesized

A multi-hop path is only as strong as its weakest hop.

Risk tiers — impact & changes

WILL_BREAKd=1 · direct dependents — must update
LIKELY_AFFECTEDd=2 · indirect — should test
MAY_NEED_TESTINGd≥3 · transitive — test if critical

seam_changes rolls these up to low → medium → high → critical.

08 · STORAGE

One SQLite file per project. Schema v14.

Loaded packaged-first from the wheel and auto-migrated additively on open. Gitignored — never leaves the machine.

TableHolds
filesindexed files · hash · mtime · indexed_at
symbolsnodes · kind (incl. field, route, config, resource) · qualified_name · signature · visibility · cluster_id · entry_score
edgessource · target · kind (15) · confidence · receiver · synthesized_by · provenance
routesHTTP route metadata · method · path · framework · handler · provenance
config_keysconfig/env key metadata · source · role · redacted value shape · provenance
resourcesruntime resource metadata · category · source · provenance
commentsWHY / HACK / NOTE / TODO / FIXME markers
clustersLouvain communities · label · size · cohesion
import_mappingsper-file import bindings (read-time promotion)
embeddingsoptional semantic vectors (--semantic only)
symbols_ftsFTS5 over name + docstring + signature + search_text
09 · NON-NEGOTIABLES

The guarantees, not just the rules.

  1. Zero external services at runtime. The MCP read path makes no network calls. The only optional outbound call — LLM cluster naming — runs at index time, is off by default, and falls back to deterministic labels on any error.
  2. SQLite only. No graph DB, no vector DB to babysit, no ORM. One gitignored file per project.
  3. Parsers never raise. A malformed file is skipped, not fatal. Analysis leaves return empty rather than throw.
  4. Edges are keyed by name. This is what makes independent per-file re-indexing correct — the watcher rewrites one file without touching the rest of the graph.
  5. Additive by default. New features ship behind a defaulted-on switch with an off that is byte-identical to before. Schema changes are additive migrations that auto-run on open.