Skip to content

dpopsuev/locus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Locus

Locus

Spatial context bus for AI agents. Point it at any repository and get architecture, dependency graph, churn, hot spots, and symbols -- via CLI or MCP server. No ceremony.

Quick Start

go install github.com/dpopsuev/locus/cmd/locus@latest

MCP Configuration (Cursor / Claude Desktop)

{
  "mcpServers": {
    "locus": {
      "command": "locus",
      "args": ["serve"]
    }
  }
}

Locus runs as a local stdio process with full filesystem access and native Go toolchain.

The Problem

LLM agents need to understand codebases to make good decisions. Without structural context, they grep blindly, read files one at a time, and miss the big picture -- coupling, churn, layering, trust boundaries.

This creates three failure modes:

  1. Blind navigation. The agent reads files sequentially without knowing which packages matter or how they connect.
  2. Missing risk signals. High-churn, high-coupling components are invisible unless the agent happens to stumble on them.
  3. No shared vocabulary. Without a component model, the agent can't discuss architecture with the developer in structural terms.

Locus solves this by scanning any repository and producing a structured context report -- components, dependencies, symbols, churn, hot spots, nesting depth, LOC -- that agents consume through MCP tools. The agent gets the whole architecture in one call.

Workflow

Locus is designed for natural language. You talk to your agent, and it calls the right MCP tools behind the scenes.

You: I just cloned this repo. What's the architecture?

Agent: (calls codograph with action scan_local) The project has 13 packages across 2 layers. internal/arch is the core with 54 symbols and the highest churn (21 commits). internal/protocol is the gateway — everything routes through it. Here's the dependency diagram...

You: Which parts are risky to change?

Agent: (calls analysis with action coupling, view hot_spots) Two components are in the danger zone: internal/arch (fan-in 7, churn 21) and internal/analysis (fan-in 4, churn 16). Both are deeply depended on and change frequently. I'd add tests before touching either.

You: If I refactor internal/cache, what breaks?

Agent: (calls analysis with action impact) Blast radius is 38%. Direct dependents: internal/protocol, internal/history, cmd/locus. Transitive: everything that depends on those — 5 packages total. Risk level: medium.

You: Show me the architecture as a layer diagram with health colors.

Agent: (calls render_diagram with type layers, theme natural) Here you go — 9 layers from cmd/locus at the top to internal/model at the bottom. Red means high fan-in + high churn. Yellow is borderline.

Architecture

Every diagram below was generated by running locus diagram . --theme natural on itself. Components are colored by health: green = healthy, yellow = sick (fan-in >= 3, churn >= 8), red = fatal (fan-in >= 5, churn >= 15). Re-run to update.

Dependency Graph

locus diagram . --type dependency --theme natural

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#F7FAFC', 'primaryTextColor': '#2D3748', 'primaryBorderColor': '#4A90D9', 'lineColor': '#4A90D9', 'background': '#FFFFFF', 'fontSize': '14px'}}}%%
graph TD
    classDef boundary fill:#FFFFFF,stroke:#718096,color:#2D3748
    classDef component fill:#F7FAFC,stroke:#4A90D9,color:#2D3748
    classDef edge stroke:#4A90D9
    classDef entry fill:#4A90D9,stroke:#4A90D9,color:#FFFFFF
    classDef fatal fill:#E53E3E,stroke:#E53E3E,color:#FFFFFF
    classDef healthy fill:#38A169,stroke:#38A169,color:#FFFFFF
    classDef sick fill:#D69E2E,stroke:#D69E2E,color:#FFFFFF
    classDef violation_edge stroke:#E53E3E
    cmd_locus["cmd/locus [churn:15]"]:::entry
    internal_analysis["internal/analysis [churn:29]"]:::fatal
    internal_arch["internal/arch [churn:27]"]:::fatal
    internal_cache["internal/cache [churn:5]"]:::healthy
    internal_config["internal/config [churn:1]"]:::healthy
    internal_cursor["internal/cursor [churn:3]"]:::healthy
    internal_diagram["internal/diagram [churn:38]"]:::healthy
    internal_history["internal/history [churn:8]"]:::sick
    internal_mcp["internal/mcp [churn:19]"]:::healthy
    internal_model["internal/model [churn:3]"]:::healthy
    internal_protocol["internal/protocol [churn:22]"]:::healthy
    internal_remote["internal/remote [churn:4]"]:::healthy
    internal_store["internal/store [churn:11]"]:::sick
    internal_survey["internal/survey [churn:31]"]:::healthy
    internal_triage["internal/triage [churn:3]"]:::healthy
    cmd_locus -->|"2"| internal_analysis
    cmd_locus -->|"5"| internal_arch
    cmd_locus -->|"1"| internal_config
    cmd_locus -->|"15"| internal_diagram
    cmd_locus -->|"1"| internal_mcp
    cmd_locus -->|"29"| internal_protocol
    cmd_locus -->|"8"| internal_triage
    internal_analysis -->|"6"| internal_model
    internal_analysis -->|"5"| internal_survey
    internal_arch -->|"4"| internal_analysis
    internal_arch -->|"22"| internal_model
    internal_arch -->|"4"| internal_survey
    internal_cache -->|"1"| internal_arch
    internal_config -->|"2"| internal_cache
    internal_config -->|"1"| internal_history
    internal_config -->|"4"| internal_store
    internal_diagram -->|"45"| internal_analysis
    internal_diagram -->|"24"| internal_arch
    internal_diagram -->|"4"| internal_history
    internal_history -->|"13"| internal_arch
    internal_history -->|"3"| internal_cache
    internal_mcp -->|"2"| internal_analysis
    internal_mcp -->|"8"| internal_arch
    internal_mcp -->|"17"| internal_diagram
    internal_mcp -->|"53"| internal_protocol
    internal_mcp -->|"3"| internal_store
    internal_mcp -->|"11"| internal_triage
    internal_protocol -->|"12"| internal_analysis
    internal_protocol -->|"61"| internal_arch
    internal_protocol -->|"4"| internal_cursor
    internal_protocol -->|"12"| internal_history
    internal_protocol -->|"12"| internal_remote
    internal_protocol -->|"34"| internal_store
    internal_remote -->|"9"| internal_arch
    internal_store -->|"5"| internal_arch
    internal_store -->|"7"| internal_cache
    internal_store -->|"9"| internal_history
    internal_survey -->|"46"| internal_model
Loading

Layer Diagram

locus diagram . --type layers --theme natural

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#F7FAFC', 'primaryTextColor': '#2D3748', 'primaryBorderColor': '#4A90D9', 'lineColor': '#4A90D9', 'background': '#FFFFFF', 'fontSize': '14px'}}}%%
block-beta
    columns 1
    block:layer_0["Layer 0"]
        cmd_locus["cmd/locus"]
    end
    columns 1
    block:layer_1["Layer 1"]
        internal_mcp["internal/mcp"]
    end
    columns 3
    block:layer_2["Layer 2"]
        internal_diagram["internal/diagram"]
        internal_protocol["internal/protocol"]
        internal_triage["internal/triage"]
    end
    columns 3
    block:layer_3["Layer 3"]
        internal_cursor["internal/cursor"]
        internal_history["internal/history"]
        internal_remote["internal/remote"]
    end
    columns 1
    block:layer_4["Layer 4"]
        internal_cache["internal/cache"]
    end
    columns 1
    block:layer_5["Layer 5"]
        internal_arch["internal/arch"]
    end
    columns 1
    block:layer_6["Layer 6"]
        internal_analysis["internal/analysis"]
    end
    columns 1
    block:layer_7["Layer 7"]
        internal_survey["internal/survey"]
    end
    columns 1
    block:layer_8["Layer 8"]
        internal_model["internal/model"]
    end
Loading

C4 Component Diagram

locus diagram . --type c4 --theme natural

C4Component
    title github.com/dpopsuev/locus

    Container_Boundary(cmd_boundary, "cmd") {
        Component(cmd_locus, "cmd/locus", "package", "1 symbols, churn 9", $tags="healthy")
    }
    Container_Boundary(internal_boundary, "internal") {
        Component(internal_analysis, "internal/analysis", "package", "38 symbols, churn 16", $tags="fatal")
        Component(internal_arch, "internal/arch", "package", "54 symbols, churn 21", $tags="fatal")
        Component(internal_cache, "internal/cache", "package", "5 symbols, churn 4", $tags="healthy")
        Component(internal_cursor, "internal/cursor", "package", "4 symbols, churn 2", $tags="healthy")
        Component(internal_diagram, "internal/diagram", "package", "14 symbols, churn 32", $tags="healthy")
        Component(internal_history, "internal/history", "package", "12 symbols, churn 8", $tags="sick")
        Component(internal_mcp, "internal/mcp", "package", "1 symbols, churn 10", $tags="healthy")
        Component(internal_model, "internal/model", "package", "45 symbols, churn 3", $tags="healthy")
        Component(internal_protocol, "internal/protocol", "package", "27 symbols, churn 11", $tags="healthy")
        Component(internal_remote, "internal/remote", "package", "6 symbols, churn 3", $tags="healthy")
        Component(internal_survey, "internal/survey", "package", "12 symbols, churn 20", $tags="healthy")
        Component(internal_triage, "internal/triage", "package", "6 symbols, churn 3", $tags="healthy")
    }

    Rel(cmd_locus, internal_analysis, "uses")
    Rel(cmd_locus, internal_arch, "uses")
    Rel(cmd_locus, internal_cache, "uses")
    Rel(cmd_locus, internal_diagram, "uses")
    Rel(cmd_locus, internal_history, "uses")
    Rel(cmd_locus, internal_mcp, "uses")
    Rel(cmd_locus, internal_protocol, "uses")
    Rel(cmd_locus, internal_triage, "uses")

    UpdateElementStyle(*, $fontColor="#2D3748", $borderColor="#4A90D9")
    UpdateElementStyle(healthy, $bgColor="#38A169", $borderColor="#38A169")
    UpdateElementStyle(sick, $bgColor="#D69E2E", $borderColor="#D69E2E")
    UpdateElementStyle(fatal, $bgColor="#E53E3E", $borderColor="#E53E3E")
Loading

Tree / Mindmap

locus diagram . --type tree --theme natural — health markers: ✘ = fatal, ⚠ = sick

mindmap
    root(("locus"))
        cmd (1 sym)
            cmd/locus (1 sym)
        internal (224 sym)
            ✘ internal/analysis (38 sym)
            ✘ internal/arch (54 sym)
            internal/cache (5 sym)
            internal/cursor (4 sym)
            internal/diagram (14 sym)
            ⚠ internal/history (12 sym)
            internal/mcp (1 sym)
            internal/model (45 sym)
            internal/protocol (27 sym)
            internal/remote (6 sym)
            internal/survey (12 sym)
            internal/triage (6 sym)
Loading

Coupling Flow (Sankey)

locus diagram . --type coupling --theme natural

---
config:
  sankey:
    showValues: true
---
%% Health legend: Healthy=#38A169  Sick=#D69E2E  Fatal=#E53E3E
sankey-beta

internal/protocol,internal/arch,51
internal/survey,internal/model,46
internal/diagram,internal/analysis,45
internal/mcp,internal/protocol,44
cmd/locus,internal/protocol,28
internal/arch,internal/model,22
internal/diagram,internal/arch,21
internal/mcp,internal/diagram,15
cmd/locus,internal/diagram,15
internal/history,internal/arch,13
internal/mcp,internal/triage,11
internal/protocol,internal/remote,11
internal/protocol,internal/history,9
cmd/locus,internal/triage,8
internal/remote,internal/arch,7
internal/protocol,internal/cache,6
cmd/locus,internal/arch,5
internal/diagram,internal/history,4
internal/arch,internal/survey,4
internal/protocol,internal/cursor,4
internal/arch,internal/analysis,4
internal/history,internal/cache,3
internal/analysis,internal/survey,2
cmd/locus,internal/analysis,2
internal/protocol,internal/analysis,2
internal/mcp,internal/arch,2
internal/mcp,internal/analysis,2
cmd/locus,internal/cache,2
internal/cache,internal/arch,1
internal/mcp,internal/cache,1
internal/analysis,internal/model,1
cmd/locus,internal/mcp,1
cmd/locus,internal/history,1
Loading

Additional Diagram Types

These produce large output best viewed interactively. Run to generate for any repository:

locus diagram . --type zones --theme natural             # architecture zones with health
locus diagram . --type classes --theme natural           # class diagram with health colors
locus diagram . --type classes --exported-only            # exported symbols only
locus diagram . --type er --theme natural                 # entity-relationship
locus diagram . --type sequence --entry ScanAndBuild      # call trace from entry point
locus diagram . --type callgraph --entry ScanProject      # function call graph
locus diagram . --type dataflow --entry main              # DFD with trust boundaries
locus diagram . --type state                              # state machine detection
locus diagram . --type dependency --enrich loc,fan_in     # metrics on node labels

Packages

Package Symbols Churn Role
cmd/locus 1 9 CLI entry point (Cobra). Every MCP tool has a CLI equivalent.
internal/mcp 1 10 MCP server. Thin handlers that delegate to protocol.
internal/protocol 27 11 All business logic: scan, diff, coverage, cycles, evolution. Both CLI and MCP call through this layer.
internal/arch 54 21 Architecture model: scan, render, churn, hot spots, cycles, coverage, API surface.
internal/analysis 38 16 Type analysis (classes, interfaces, field refs, call chains, nesting) and deep analysis (call graph, data flow, state machines).
internal/diagram 14 32 Mermaid diagram renderers for all 12 diagram types with theming.
internal/survey 12 20 Language-specific scanners: Go, Rust, Python, TypeScript, C/C++, LSP, ctags.
internal/model 45 3 Data model: Project, Namespace, File, Symbol, DependencyGraph.
internal/store new Hexagonal storage port: Store interface + FilesystemStore adapter + LRU decorator.
internal/config new Backend selection and dependency wiring from env vars.
internal/cache 5 4 Filesystem scan cache keyed by git HEAD SHA (wrapped by Store).
internal/history 12 8 Codograph history: record, list, diff between snapshots (wrapped by Store).
internal/remote 6 3 Shallow-clone remote repos, scan, cache by URL+SHA.
internal/cursor 4 2 Read .cursor/rules and .cursor/skills from workspaces.
internal/triage 6 3 Intent-to-tool routing. Pure keyword matching, no LLM.

MCP Tools

Tool Description
codograph Scan and compare repository architectures. Actions: scan_local, scan_remote, history, diff, status, set_desired_state, get_desired_state. Use intent for scan depth (architecture/coupling/health/full). Returns cache_key for downstream tools.
analysis 16 analysis actions: deps, impact, coupling (view=hot_spots/edges), cycles, violations, scan_diff, callers, cross_repo, drift, suggest_architecture, search, component, preset (architecture_review/health_check/onboarding/pre_pr), query (natural language), coverage, api_surface, conventions, gaps. Pass cache_key from scan to avoid re-scanning. format=summary for <500 tokens.
render_diagram 13 diagram types: dependency, c4, coupling, churn, layers, tree, zones, classes, sequence, er, dataflow, callgraph, state. format=facts for plain-text assertions. enrich=loc,fan_in,churn for metrics on nodes. theme (light/dark/natural).
triage Map natural language intent to ranked tool list (no LLM).

Agent Workflow

codograph status            → check what's cached
codograph scan_local        → returns cache_key + 50-token summary
  intent=architecture       → fast structure-only scan
  intent=health             → default, includes churn + nesting
analysis coupling cache_key → risk areas without re-scanning
render_diagram type=zones   → architecture overview
analysis drift              → check against desired state

Triage

Locus includes a built-in intent router that maps natural language queries to the right tool chain without an LLM:

$ locus triage "where are the hot spots?"
{
  "category": "architecture",
  "confidence": 0.037,
  "tools": [
    {
      "name": "analysis",
      "params": { "action": "coupling", "view": "hot_spots", "top_n": 10 },
      "reason": "Structural hot spots reveal design pressure points"
    }
  ]
}

All tools grouped by category:

Category Tools
architecture codograph scan_local, analysis coupling, codograph scan_remote, analysis, render_diagram
onboarding codograph scan_local, codograph scan_remote
performance analysis coupling (view=hot_spots), analysis
refactoring analysis coupling (view=hot_spots), analysis deps, analysis impact
dependencies analysis deps, analysis coupling (view=edges), analysis
comparison codograph history (diff=true), codograph diff
review codograph diff
churn codograph history
testing analysis (analysis=coverage)
quality analysis (analysis=gaps)
security analysis (analysis=api_surface)
visualization render_diagram
meta triage

Supported Languages

Language Scanner Symbols Dependencies
Go go/ast native functions, types, methods, interfaces import graph + call graph (GoAST analyzer)
Rust Cargo.toml + regex functions, structs, traits, impls crate dependency graph
Python tree-sitter-python functions, classes, async functions import graph + call graph (PythonDeep analyzer)
TypeScript tree-sitter-typescript functions, classes, arrow functions import graph + call graph (TypeScriptDeep analyzer)
C/C++ #include + ctags functions, structs, typedefs include graph
Any LSP (gopls, etc.) workspace/symbol references
Any ctags (universal) all ctags kinds import heuristics

Diagram Theming

Locus supports three visual themes for Mermaid diagrams: light, dark, and natural (default). Themes control colors, shapes, and health-based semantic coloring.

Health Classification

Components are automatically classified by risk level based on fan-in and churn:

Level Condition Color
Healthy Default Green
Sick fan-in >= 3 AND churn >= 8 Yellow
Fatal fan-in >= 5 AND churn >= 15 Red

Health coloring is applied to dependency flowcharts, C4 component diagrams, churn bar charts, and tree mindmaps. Layer diagrams highlight violations in red.

Theme Selection

locus diagram . --type dependency --theme dark
LOCUS_THEME=dark locus diagram . --type c4

Via MCP: pass "theme": "dark" in the render_diagram arguments.

Custom Theme File

Place a theme.yaml in ~/.locus/ or set LOCUS_THEME_FILE to override default tokens:

colors:
  green:
    dark: "#68D391"
    light: "#276749"
    natural: "#38A169"
shapes:
  component:
    fill: surface
    stroke: blue
    color: text

Configuration

Variable Default Description
LOCUS_STORE filesystem Storage backend: filesystem
LOCUS_CACHE_DIR ~/.locus/cache Scan cache directory
LOCUS_HISTORY_DIR ~/.locus/history Codograph history directory
LOCUS_TRANSPORT stdio Transport: stdio, http
LOCUS_ADDR :8081 Listen address (HTTP only)
LOCUS_THEME natural Default diagram theme: light, dark, natural
LOCUS_THEME_FILE ~/.locus/theme.yaml Custom theme override file
LOCUS_LOG_LEVEL info Log level: debug, info, warn, error. JSON to stderr.

License

MIT

About

Spatial context scanner — architecture graphs, dependency analysis via CLI and MCP server

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages