Code intelligence engine that indexes repositories into an in-memory knowledge graph and exposes it via CLI, MCP Server, and web UI.
Built for 15 AI coding agents (Claude Code, Kiro, Cursor, Windsurf, VS Code / Copilot, Continue.dev, Cline, OpenCode, Antigravity, Codex CLI, Gemini CLI, Zed, Aider, Kilo Code, OpenClaw) — one smart_context call replaces 5-10 file reads, cutting token usage by ~94%.
See docs/agents.md for the adapter matrix, per-agent schema notes, and the gortex init --agents=<csv> CLI contract.
curl -fsSL https://get.gortex.dev | shDetects OS/arch, downloads the signed release tarball, verifies the SHA256 against
checksums.txt(and cosign if installed), drops the binary in$HOME/.local/bin, and adds it to your shell rc. Re-runs upgrade in place. No silent sudo. Linux + macOS, amd64 + arm64. Windows support is planned.
For Homebrew, package managers (.deb / .rpm / .apk), direct binary download, supply-chain verification (cosign + SLSA-3 + VirusTotal), and from-source builds — see docs/installation.md.
New to Gortex? After installing, see docs/onboarding.md for the 15-minute walkthrough: gortex install (once per machine) → gortex init (once per repo) → verify your AI assistant uses graph tools → what to do if it doesn't.
- Knowledge graph — every file, symbol, import, call chain, and type relationship in one queryable structure
- Multi-repo workspaces — index multiple repositories into a single graph with cross-repo symbol resolution, project grouping, reference tags, and per-repo scoping
- 92 languages — tree-sitter + regex extractors across core programming (Go, TypeScript, Python, Rust, Java, C#, Kotlin, Swift, C, C++, …), scripting (Bash, PowerShell, Perl, Lua, …), functional (Haskell, OCaml, Elixir, Clojure, …), template engines (Blade, EJS, Jinja, Twig, ERB, Liquid, Pug, Handlebars), blockchain (Solidity, Move, Cairo, Noir, Tact, Ballerina), scientific (Julia, R, MATLAB, Mathematica, SAS, Stata, Fortran, COBOL, Ada, Pascal, ABAP, Apex), emerging (Mojo, Odin, V, Hare, Carbon, ReScript, Gleam), build/data (Makefile, CMake, Dockerfile, SQL, Protobuf, JSON, YAML, TOML, HCL), and more. See docs/languages.md for the full table
- 50 MCP tools — symbol lookup, call chains, blast radius, community/process discovery, contract detection, unified
analyze(dead code, hotspots, cycles), scaffolding, inline editing, symbol renaming, read-free file writes (edit_file/write_file— no Read-before-Edit roundtrip for docs/configs/specs), multi-axis structured retrieval (winnow_symbols), multi-repo management, agent feedback loop, context export, graph-validated config hygiene (audit_agent_config), opening-move routing (plan_turn), narrative repo overview (get_repo_outline), test-coverage gaps (get_untested_symbols), and 18 agent-optimized tools - Semantic search — hybrid BM25 + vector search with RRF fusion. Hugot (pure-Go ONNX runtime with MiniLM-L6-v2) is bundled by default and auto-downloads the model on first use — zero-config, no native dependencies. GloVe word vectors remain as fallback. Optional build tags switch to ONNX or GoMLX for higher throughput
- LSP-enriched call-graph tiers — every edge carries an
origintier (lsp_resolved/lsp_dispatch/ast_resolved/ast_inferred/text_matched); passmin_tiertoget_callers,find_usages,find_implementations, etc. to restrict results to compiler-verified edges for high-stakes refactors - MCP progress notifications — long-running indexing and track_repository calls emit
notifications/progresswith stage messages (walking files → parsing → resolving → semantic enrichment → search index → contracts → done) so hosts show real progress bars on large repos - Type-aware resolution — infers receiver types from variable declarations, composite literals, and Go constructor conventions to disambiguate same-named methods across types
- On-disk persistence — snapshots the graph on shutdown, restores on startup with incremental re-indexing of only changed files (~200ms vs 3-5s full re-index)
- HTTP server (
gortex server) — versioned/v1/*JSON API exposing all MCP tools (/v1/health,/v1/tools,/v1/tools/{name},/v1/stats,/v1/graph,/v1/eventsSSE) for IDE plugins, CI, and the Next.js web UI. Localhost bind + bearer-token auth (--auth-token/$GORTEX_SERVER_TOKEN) by default; CORS configurable for separate frontend origins - Semantic enrichment — pluggable SCIP, go/types, and LSP providers upgrade edge confidence from ~70-85% (tree-sitter) to 95-100% (compiler-verified). Additive — graceful degradation when external tools unavailable
- Agent feedback loop — unified
feedbacktool (action: "record"/"query") lets agents report which symbols were useful/missing. Cross-session persistence improves futuresmart_contextquality via feedback-aware reranking - Context export —
export_contexttool +gortex contextCLI render graph context as portable markdown/JSON briefings for sharing outside MCP (Slack, PRs, docs, non-MCP AI tools) - ETag conditional fetch — content-hash based
if_none_matchon source-reading tools avoids re-transmitting unchanged symbols during iterative editing - Token savings tracking — per-call
tokens_savedfield on source-reading tools + session-level metrics ingraph_stats(calls counted, tokens returned, tokens saved, efficiency ratio) - GCX1 compact wire format — published, round-trippable text format for MCP tool responses. Opt-in per call via
format: "gcx"on 13 tools. Median −27.4% tiktoken savings vs JSON across a 20-case benchmark (best case −38.3%), 100% round-trip integrity. Spec:docs/wire-format.md. Standalone MIT-licensed reference implementations: Go (github.com/gortexhq/gcx-go) and TypeScript (github.com/gortexhq/gcx-ts, npm@gortex/wire). Reproducible harness:bench/wire-format/ - 7 MCP resources — lightweight graph context without tool calls
- 3 MCP prompts —
pre_commit,orientation,safe_to_changefor guided workflows - Two-tier config — global config (
~/.config/gortex/config.yaml) for projects and repo lists, per-repo.gortex.yamlfor guards, excludes, and local overrides - Guard rules — project-specific constraints (co-change, boundary) enforced via
check_guards - Watch mode — surgical graph updates on file change across all tracked repos, live sync with agents
- Web UI — standalone Next.js 15 app at
gortexhq/web(separate repo so it deploys independently) that talks togortex serverover/v1/*, with Sigma.js 2D graphs and five react-three-fiber 3D views (City, Strata, Galaxies, Constellation, Graph3D) - IMPLEMENTS inference — structural interface satisfaction for Go, TypeScript, Java, Rust, C#, Scala, Swift, Protobuf
- PreToolUse + PreCompact + Stop hooks — PreToolUse enriches Read/Grep/Glob/Bash (
codebase-search/rg/grepprobes routed through graph tools) with graph context and redirects to Gortex MCP tools; matchingTaskalso briefs spawned subagents with an inline tool-swap table + task-scopedsmart_contextso subagents don't fall back to grep/Read. PreCompact injects a condensed orientation snapshot (index stats, recently-modified symbols, top hotspots, feedback-ranked symbols) before Claude Code compacts the conversation. Stop runs post-task diagnostics (detect_changes→get_test_targets,check_guards,analyze dead_code,contracts checkon modified symbols) so the agent self-corrects before handoff. All hooks degrade silently when the server is unreachable - Long-living daemon (optional) —
gortex daemon startruns a single shared process that holds the graph for every tracked repo. Each Claude Code / Cursor / Kiro window connects as a thin stdio proxy over a Unix socket, getting per-client session isolation (recent activity, token stats) + cross-repo queries by default. Live fsnotify watching on every tracked repo so file edits flow into the graph without manual reload.gortex installsets up user-level config;gortex daemon install-serviceinstalls a LaunchAgent (macOS) or systemd--userunit (Linux) so the OS supervises lifecycle and auto-starts at login — no sudo required. Binaries fall back to embedded mode if the daemon isn't running; the feature is additive - Benchmarked — per-language parsing, query engine, indexer benchmarks
- Per-community skills —
gortex init --skills(default on) auto-generates SKILL.md per detected community with key files, entry points, cross-community connections, and MCP tool invocations for Claude Code auto-discovery; the same routing table lands in every detected agent's per-repo instructions file - Eval framework — SWE-bench harness for A/B benchmarking tool effectiveness with Docker-based environments and multi-model support
gortex evalCLI — first-class evaluation harness. Subcommands:recall(fixture-driven any-hit R@1/5/20 + MRR per ranker, per-tier breakdown, p50/p95 latency, tokens-returned, optional LLM judge for CQS-style dual-judge scoring),embedders(ONNX variant comparison — size + init + embed latency + end-to-end quality across MiniLM variants, BGE, Jina),swebench(passthrough),tokens(GCX1 wire-format bench). Seed fixture atbench/fixtures/retrieval.yaml; published BM25 baseline on Gortex: R@1 42.3% · R@5 56.4% · R@20 69.9% · exact R@5 95.2%- Zero dependencies — everything runs in-process, in memory, no external services
Setup is split into two commands — gortex install runs once per machine, gortex init runs once per repo:
gortex installwrites user-level artifacts:~/.claude.jsonMCP config,~/.claude/skills/gortex-*(tool-usage skills),~/.claude/commands/gortex-*.md(slash commands),~/.gemini/antigravity/Knowledge Items, and (optionally) user-level Claude Code hooks. Codebase-agnostic content lives here so it isn't duplicated into every repo.gortex initwrites per-repo artifacts:.mcp.json,.claude/settings.{json,local.json},CLAUDE.mdwith the codebase overview and community routing,.claude/skills/generated/per-community SKILL.md files, and a marker-guarded community routing block in every other detected agent's per-repo instructions file (AGENTS.md,.windsurfrules,GEMINI.md,.cursor/rules/gortex-communities.mdc, etc.).
gortex install # interactive-free: MCP + skills + slash commands at ~/.claude/
gortex install --start --track # also spawn the daemon and track the current directory
gortex install --no-hooks # skip user-level hook installation
# Daemon lifecycle (also spawned by `gortex install --start`):
gortex daemon start --detach # spawn in background
gortex daemon status # PID, uptime, memory, tracked repos, sessions, server roster
gortex daemon stop # graceful shutdown + final snapshot
gortex daemon restart # stop + start
gortex daemon reload # re-read config, pick up new/removed repos
gortex daemon logs -n 50 # tail the log file
# Multi-server roster — let the daemon route to additional Gortex servers (local sockets or remote HTTPS):
gortex daemon server list # show ~/.gortex/servers.toml
gortex daemon server add work --url https://gortex.work.example --auth-token-env WORK_TOK
gortex daemon server remove work
# Auto-start at login (launchd on macOS, systemd --user on Linux):
gortex daemon install-service
gortex daemon service-status
gortex daemon uninstall-service
# Track / untrack repos (daemon-first dispatch; falls back to config-only when no daemon):
gortex track ~/projects/backend
gortex untrack backend
# Per-repo status + daemon-wide status share the same command — it picks:
gortex statuscd ~/projects/myapp
gortex init # writes .mcp.json, .claude/settings.*, CLAUDE.md with community routing
gortex init --analyze # also index first for a richer CLAUDE.md overview
gortex init --no-skills # skip community-routing generation
gortex init --skills-min-size 5 --skills-max 10 # tune the generator
gortex init --hooks-only # (re)install repo-local hooks only, skip everything else
gortex init --no-hooks # full init but skip hook installation
# Run the MCP server standalone (auto-detects daemon via stdio; --no-daemon forces embedded):
gortex mcp --index /path/to/repo --watch
gortex mcp --no-daemon --watch # explicit embedded modegortex server --index . # HTTP/JSON API on :4747 (/v1/*). UI lives at github.com/gortexhq/web.
gortex savings # cumulative tokens saved + $ avoided across sessions
gortex versionGortex can index multiple repositories into a single shared graph, enabling cross-repo symbol resolution, impact analysis, and navigation.
Every node and contract is keyed on a workspace slug, which is the hard graph boundary for cross-repo work. Two repos that should pair their contracts (an HTTP server and the client that calls it, a Kafka producer and its consumer, etc.) must declare the same workspace: in their .gortex.yaml — otherwise contract matching stops at the boundary and they look like orphans.
Slug resolution precedence (first match wins):
RepoEntry.workspacein~/.config/gortex/config.yaml— overrides everything, ideal for OSS / read-only repos where you don't want to leave an artifact in the treeworkspace:in the repo's own.gortex.yaml— the default for first-party repos- The repo prefix — fallback when neither is set, so each unconfigured repo gets its own isolated workspace
The same chain applies to the optional project: slug (a sub-bucket inside a workspace). On gortex server, the --workspace and --scope-project flags filter both indexing and queries: gortex server --workspace api will only load repos that resolve to the api workspace, and a typo'd value errors out at startup rather than producing an empty graph.
Two-tier config hierarchy:
- Global config (
~/.config/gortex/config.yaml) — projects, repo lists, active project, reference tags - Workspace config (
.gortex.yamlper repo) — guards, excludes, local overrides
Excludes are layered — builtin → global → per-repo entry → workspace — with gitignore semantics. Use !pattern in a later layer to re-include something an earlier layer excluded.
# ~/.config/gortex/config.yaml
active_project: my-saas
exclude: # Applies to every tracked repo
- "**/*.generated.*"
- "node_modules/" # Already in the builtin baseline
repos:
- path: /home/user/projects/gortex
name: gortex
exclude: # Extra patterns just for this repo
- "results/**"
projects:
my-saas:
repos:
- path: /home/user/projects/frontend
name: frontend
ref: work
- path: /home/user/projects/backend
name: backend
ref: work
- path: /home/user/projects/shared-lib
name: shared-lib
ref: opensourceThe daemon's defaults handle typical workflows without configuration. These knobs exist for monorepos, branch-heavy workflows, or filesystems without fsnotify support.
# ~/.config/gortex/config.yaml (or per-repo .gortex.yaml)
watch:
debounce_ms: 150 # per-file patch debounce (default 150)
# Storm mode — when more than N events land within the window,
# switch from per-file debounced patching to a batched reconcile
# that defers cross-file resolver + search work until a quiet
# period has passed. Amortises the cost of bulk operations
# (rsync, npm install, branch checkout, bulk format-on-save,
# find-and-replace). Zero = disabled (default).
storm_threshold: 0 # 0 disables; try 50 on monorepos
storm_window_ms: 500
storm_quiet_period_ms: 500Environment variables:
GORTEX_RECONCILE_INTERVAL— janitor tick that walks every tracked repo and runsIncrementalReindexagainst disk. Insurance against fsnotify gaps on NFS/SMB mounts, inotify watch-limit exhaustion, or daemon downtime where edits happened offline. Default1h;"0"or"off"disables; otherwise any Go duration string (e.g.,15m).- The daemon also watches each tracked repo's
.git/HEAD, so branch switches and rebases reconcile incrementally (viagit diff --name-status) rather than by re-indexing every changed file individually — no configuration needed.
gortex track /path/to/repo # Add a repo to the workspace
gortex untrack /path/to/repo # Remove a repo from the workspace
gortex mcp --track /path/to/repo # Track additional repos on startup
gortex mcp --project my-saas # Set active project scope
gortex index repo-a/ repo-b/ # Index multiple repos
gortex status # Per-repo and per-project stats
# Stamp workspace / project slugs across tracked repos (migration helper)
gortex workspace list # Show what each tracked repo currently declares
gortex workspace set backend api # Write workspace=api to backend's .gortex.yaml
gortex workspace set upstream-lib api --global # OSS-friendly: pin to api in ~/.config/gortex/config.yaml
gortex workspace set-all api --root ~/projects/work --yes # Bulk: stamp every tracked repo under a prefix
# Manage the effective ignore list used by indexing + watching
gortex config exclude list # Show all layers (builtin, global, repo entry, workspace)
gortex config exclude add pkg/generated # Default target: workspace .gortex.yaml
gortex config exclude add '**/*.bak' --global # Write to ~/.config/gortex/config.yaml
gortex config exclude add testdata/ --repo backend # Write to a RepoEntry
gortex config exclude remove pkg/generated # Remove from the same targetAgents can manage repos at runtime without CLI access:
| Tool | Description |
|---|---|
track_repository |
Add a repo, index immediately, persist to config |
untrack_repository |
Remove a repo, evict nodes/edges, persist to config |
set_active_project |
Switch project scope for all subsequent queries |
get_active_project |
Return current project name and repo list |
All query tools (search_symbols, get_symbol, find_usages, get_file_summary, get_call_chain, smart_context) accept optional repo, project, and ref parameters for scoping. When an active project is set, it applies as the default scope.
- Qualified Node IDs — in multi-repo mode, IDs become
<repo_prefix>/<path>::<Symbol>(e.g.,frontend/src/app.ts::App). Single-repo mode keeps the existing<path>::<Symbol>format. - Cross-repo edges — the resolver links symbols across repo boundaries with same-repo preference. Cross-repo edges carry a
cross_repo: trueflag. - Impact analysis —
explain_change_impact,verify_change, andget_test_targetsfollow cross-repo edges automatically, grouping results by repository. - Shared repos — the same repo can appear in multiple projects with different reference tags. It's indexed once and shared across projects.
- Auto-detection — set
workspace.auto_detect: truein.gortex.yamlto auto-discover Git repos in a parent directory.
After gortex install (once per machine) and gortex init (once per repo), Claude Code automatically starts Gortex via .mcp.json. The agent gets:
- Slash commands:
/gortex-guide,/gortex-explore,/gortex-debug,/gortex-impact,/gortex-refactor— installed to~/.claude/commands/bygortex install - Tool-usage skills: installed to
~/.claude/skills/bygortex install— one copy per user, used across every repo - PreToolUse hook: automatic graph context + graph-tool suggestions on Read/Grep/Glob
- PreCompact hook: condensed orientation snapshot injected before context compaction so the agent resumes without re-exploring
- Stop hook: post-task diagnostics — tests to run, guard violations, dead code, and contract issues on the changed symbols — injected as context before the agent hands off
- CLAUDE.md: per-repo codebase overview (via
--analyze) plus a marker-guarded community routing block written bygortex init --skills
gortex install (user-level) and gortex init (repo-level) together auto-detect and configure 14 other AI coding assistants — Kiro, Cursor, VS Code / Copilot, Windsurf, Continue.dev, Cline, OpenCode, Antigravity, Codex CLI, Gemini CLI, Zed, Aider, Kilo Code, OpenClaw. Each adapter writes only when its host is present on the machine, and every re-run is idempotent.
Tool-usage guidance for agents that have a user-level surface (Claude Code, Antigravity) lives once per user; for the rest, MCP tool descriptions carry the teaching and gortex init adds only a per-repo community-routing block — no more duplicated instructions blocks in every repo.
- Adapter matrix + per-agent schema notes:
docs/agents.md - Audit what's currently configured:
gortex init doctor(zero-op;--jsonfor CI consumers) - Constrain setup:
gortex init --agents=claude-code,cursoror--agents-skip=antigravity(same flags accepted bygortex install) - CI / scripted install:
gortex install --yes --jsonthengortex init --yes --json --dry-run
gortex install One-time machine-wide setup (user-level MCP, skills, hooks, daemon wiring)
gortex init [path] Per-repo setup (.mcp.json, hooks, community routing, per-community SKILL.md)
gortex init doctor Zero-op drift report across all detected agents (human or --json)
gortex mcp [flags] Start the MCP stdio server (auto-detects daemon; --no-daemon / --proxy; --server adds HTTP API)
gortex server [flags] Start the HTTP/JSON API under /v1/* (--bind, --auth-token, --watch, --cors-origin)
gortex daemon <subcommand> start / stop / restart / reload / status / logs / install-service / service-status / uninstall-service / server (multi-server roster)
gortex eval <subcommand> Retrieval + token benchmarks — recall, embedders, swebench, tokens
gortex eval-server [flags] HTTP server used by the swebench harness
gortex context [flags] Generate portable context briefing for a task
gortex savings [flags] Show cumulative token savings + cost avoided across sessions
gortex index [path...] Index one or more repositories and print stats
gortex status [flags] Show index status (per-repo and per-project in multi-repo mode)
gortex track <path> Add a repository to the tracked workspace
gortex untrack <path> Remove a repository from the tracked workspace
gortex workspace <sub> list / set / set-all — manage workspace + project slugs across tracked repos
gortex config exclude ... add / list / remove entries in the effective ignore list
gortex query <subcommand> Query the knowledge graph from the CLI
gortex clean Remove Gortex files from a project
gortex version Print version
gortex query symbol <name> Find symbols matching name
gortex query deps <id> Show dependencies
gortex query dependents <id> Show blast radius
gortex query callers <func-id> Show who calls a function
gortex query calls <func-id> Show what a function calls
gortex query implementations <iface> Show interface implementations
gortex query usages <id> Show all usages
gortex query stats Show graph statistics
All query commands support --format text|json|dot (DOT output for Graphviz visualization).
| Tool | Description |
|---|---|
graph_stats |
Node/edge counts by kind, language, per-repo stats, and session token savings |
search_symbols |
Find symbols by name (replaces Grep). Accepts repo, project, ref params |
winnow_symbols |
Structured constraint-chain retrieval — kind, language, community, path_prefix, min_fan_in, min_fan_out, min_churn, text_match with per-axis score contributions |
get_symbol |
Symbol location and signature (replaces Read). Accepts repo, project, ref params |
get_file_summary |
All symbols and imports in a file. Accepts repo, project, ref params |
get_editing_context |
Primary pre-edit tool — symbols, signatures, callers, callees |
get_repo_outline |
Narrative single-call repo overview — top languages, communities, hotspots, most-imported files, entry points |
plan_turn |
Opening-move router — returns ranked next calls with pre-filled args for a task description (~200 tokens) |
| Tool | Description |
|---|---|
get_dependencies |
What a symbol depends on |
get_dependents |
What depends on a symbol (blast radius) |
get_call_chain |
Forward call graph |
get_callers |
Reverse call graph |
find_usages |
Every reference to a symbol |
find_implementations |
Types implementing an interface |
get_cluster |
Bidirectional neighborhood |
| Tool | Description |
|---|---|
get_symbol_source |
Source code of a single symbol (80% fewer tokens than Read). Returns tokens_saved per call |
batch_symbols |
Multiple symbols with source/callers/callees in one call |
find_import_path |
Correct import path for a symbol |
explain_change_impact |
Risk-tiered blast radius with affected processes |
get_recent_changes |
Files/symbols changed since timestamp |
edit_symbol |
Edit a symbol's source directly by ID — no Read needed |
edit_file |
Edit any file (markdown, config, spec, template, source) by exact string replacement — accepts absolute paths or repo-rooted paths. Kills the Read-before-Edit stall on files not in the graph |
write_file |
Create or overwrite any file with given content — atomic temp+rename, re-indexes on write |
rename_symbol |
Coordinated multi-file rename with all references |
| Tool | Description |
|---|---|
smart_context |
Task-aware minimal context — replaces 5-10 exploration calls |
get_edit_plan |
Dependency-ordered edit sequence for multi-file refactors |
get_test_targets |
Maps changed symbols to test files and run commands |
get_untested_symbols |
Inverse of get_test_targets — functions/methods not reached from any test file, ranked by fan-in |
suggest_pattern |
Extracts code pattern from an example — source, registration, tests |
export_context |
Portable markdown/JSON context briefing for sharing outside MCP |
feedback |
action: "record": report useful/missing symbols. action: "query": aggregated stats — most useful, most missed, accuracy metrics |
| Tool | Description |
|---|---|
get_communities |
Functional clusters (Louvain). Without id: list all. With id: members and cohesion for one community |
get_processes |
Discovered execution flows. Without id: list all. With id: step-by-step trace |
detect_changes |
Git diff mapped to affected symbols |
index_repository |
Index or re-index a repository path |
contracts |
API contracts. action: "list" (default): detected HTTP/gRPC/GraphQL/topics/WebSocket/env/OpenAPI. action: "check": orphan providers/consumers |
| Tool | Description |
|---|---|
verify_change |
Check proposed signature changes against all callers and interface implementors |
check_guards |
Evaluate project guard rules (.gortex.yaml) against changed symbols |
audit_agent_config |
Scan CLAUDE.md / AGENTS.md / .cursor/rules / .github/copilot-instructions.md / .windsurf/rules / .antigravity/rules for stale symbol references, dead file paths, and bloat — validated against the Gortex graph (no other competitor does this) |
| Tool | Description |
|---|---|
analyze |
Unified graph analysis. kind: "dead_code": symbols with zero incoming edges. kind: "hotspots": high fan-in/out symbols. kind: "cycles": Tarjan's SCC cycle detection. kind: "would_create_cycle": check if a new dependency would form a cycle |
index_health |
Health score, parse failures, stale files, language coverage |
get_symbol_history |
Symbols modified this session with counts; flags churning (3+ edits) |
| Tool | Description |
|---|---|
scaffold |
Generate code, registration wiring, and test stubs from an example symbol |
batch_edit |
Apply multiple edits in dependency order, re-index between steps |
diff_context |
Git diff enriched with callers, callees, community, processes, per-file risk |
prefetch_context |
Predict needed symbols from task description and recent activity |
| Tool | Description |
|---|---|
track_repository |
Add a repo at runtime — indexes immediately, persists to global config |
untrack_repository |
Remove a repo — evicts nodes/edges, persists to global config |
set_active_project |
Switch active project scope for all subsequent queries |
get_active_project |
Return current project name and its member repositories |
| Resource | Description |
|---|---|
gortex://session |
Current session state and activity |
gortex://stats |
Graph statistics (node/edge counts) |
gortex://schema |
Graph schema reference |
gortex://communities |
Community list with cohesion scores |
gortex://community/{id} |
Single community detail |
gortex://processes |
Execution flow list |
gortex://process/{id} |
Single process trace |
| Prompt | Description |
|---|---|
pre_commit |
Review uncommitted changes — shows changed symbols, blast radius, risk level, affected tests |
orientation |
Orient in an unfamiliar codebase — graph stats, communities, execution flows, key symbols |
safe_to_change |
Analyze whether it's safe to change specific symbols — blast radius, edit plan, affected tests |
The web UI lives in its own repo at gortexhq/web so it can be deployed independently of the backend (Vercel / a static host / your own Next.js deployment). It's a standalone Next.js 15 app that talks to gortex server over /v1/*:
# 1) Start the HTTP backend (localhost:4747 by default, bearer-auth in non-localhost binds)
gortex server --index /path/to/repo --watch
# 2) Clone and run the UI in another terminal
git clone https://github.com/gortexhq/web.git gortex-web && cd gortex-web
echo 'NEXT_PUBLIC_GORTEX_URL=http://localhost:4747' > .env.local
npm install && npm run dev
# Open http://localhost:3000| Page | Features |
|---|---|
| Dashboard | Health, stats, language pie chart, node kind bar chart |
| Graph Explorer | Sigma.js 2D + five react-three-fiber 3D modes (City / Strata / Galaxies / Constellation / Graph3D), node filters, selection, detail panel |
| Search | Semantic + BM25 search via /v1/*, results grouped by kind |
| Symbol Detail | Source code, signature, callers/callees/usages/deps tabs |
| Communities | Community cards with cohesion bars, expandable members |
| Processes | Collapsible call-tree steps, product vs test process split |
| Analysis | Dead code, hotspots, cycles, index health — 4 tabs |
| Contracts | API contracts (HTTP, gRPC, GraphQL, topics, WebSocket, env vars) with provider/consumer matching, request/response type tracing, yours / tests / deps / all scope filter |
| Services | Service-level graph visualization with per-repo stats |
| AI Chat | LLM-powered chat with code context (placeholder) |
The gortex server command exposes all MCP tools as an HTTP/JSON API under versioned /v1/* routes:
# Standalone HTTP backend (default bind 127.0.0.1:4747)
gortex server --index /path/to/repo --watch
# Non-localhost bind requires an auth token
gortex server --index . --bind 0.0.0.0 --auth-token "$(openssl rand -hex 32)"
# HTTP API alongside MCP stdio (same process)
gortex mcp --index /path/to/repo --server --port 8765Endpoints (all under /v1/):
| Endpoint | Method | Description |
|---|---|---|
/v1/health |
GET | Status, node/edge counts, uptime |
/v1/tools |
GET | List all available tools with descriptions |
/v1/tools/{name} |
POST | Invoke any MCP tool with JSON arguments. Accepts ?format=gcx or top-level "format" in the body |
/v1/stats |
GET | Graph statistics by kind and language, plus server_id + started_at |
/v1/graph |
GET | Full brief-graph dump (nodes + edges + stats); accepts ?project= and/or ?repo= for scoping |
/v1/events |
GET | SSE stream of graph-change events (requires --watch). Accepts ?token=<t> for EventSource auth |
Auth & binding. The server defaults to --bind 127.0.0.1 and runs unauthenticated on localhost only (logs server: unauthenticated mode; localhost only). Set --auth-token <token> or $GORTEX_SERVER_TOKEN to require Authorization: Bearer <token> on every /v1/* request (constant-time compare; CORS preflights bypass). Non-localhost binds without a token are rejected at startup. CORS origin is configurable via --cors-origin (default *). --bind also accepts unix:///path/to.sock for a Unix-domain socket.
Scoping the graph. Pass --workspace <slug> to restrict both indexing and queries to repos that resolve to that workspace, and --scope-project <slug> to narrow further. A scope that matches zero tracked repos errors out at startup rather than silently producing an empty graph.
Multi-server roster. When the daemon is running, it can route MCP traffic across multiple Gortex servers — a local Unix socket for the repos on this machine, plus one or more remote HTTPS servers for shared / cloud indexes. The roster lives at ~/.gortex/servers.toml; manage it with gortex daemon server list / add / remove. Auth tokens can be embedded directly (--auth-token) or pulled from an env var the daemon reads at request time (--auth-token-env, preferred). Restart the daemon to pick up roster changes.
Gortex detects API contracts across repos and matches providers to consumers:
# After indexing, contracts are auto-detected
gortex server --index .
# Via MCP tools
contracts # list all detected contracts (default action)
contracts {action: "check"} # find mismatches and orphans| Contract Type | Detection | Provider | Consumer |
|---|---|---|---|
| HTTP Routes | Framework annotations (gin, Express, FastAPI, Spring, etc.) | Route handler | HTTP client calls (fetch, http.Get) |
| gRPC | Proto service definitions | Service RPC | Client stub calls |
| GraphQL | Schema type/field definitions | Schema | Query/mutation strings |
| Message Topics | Pub/sub patterns (Kafka, NATS, RabbitMQ) | Publish calls | Subscribe calls |
| WebSocket | Event emit/listen patterns | emit() | on() |
| Env Vars | os.Getenv, process.env, .env files | Setenv / .env | Getenv / process.env |
| OpenAPI | Swagger/OpenAPI spec files | Spec paths | (linked to HTTP routes) |
Contracts are normalized to canonical IDs (e.g., http::GET::/api/users/{id}) and matched across repos to detect orphan providers/consumers and mismatches.
gortex init --skills (default on) analyzes your codebase, detects functional communities via Louvain clustering, and generates targeted SKILL.md files that Claude Code auto-discovers:
# Runs as part of `gortex init` by default — community generation is folded in
gortex init
# Tune or disable:
gortex init --skills-min-size 5 --skills-max 10
gortex init --no-skillsEach generated skill includes:
- Community metadata — size, file count, cohesion score
- Key files table — files and their symbols
- Entry points — main functions, handlers, controllers detected via process analysis
- Cross-community connections — which other areas this community interacts with
- MCP tool invocations — pre-written
get_communities,smart_context,find_usagescalls
For Claude Code, skills are written to .claude/skills/generated/<DirName>/SKILL.md, and a routing table is inserted into CLAUDE.md between <!-- gortex:communities:start/end --> markers. Every other detected agent gets the same routing table inside its per-repo instructions surface (AGENTS.md for Codex/OpenCode, .windsurfrules for Windsurf, GEMINI.md for Gemini CLI, .cursor/rules/gortex-communities.mdc for Cursor, etc.) — so the routing is consistent across tools on the same repo.
Hybrid BM25 + vector search with Reciprocal Rank Fusion (RRF). Multiple embedding tiers:
# Built-in word vectors (always available, zero setup)
gortex mcp --index . --embeddings
# Ollama (best quality, local)
ollama pull nomic-embed-text
gortex mcp --index . --embeddings-url http://localhost:11434
# OpenAI (best quality, cloud)
gortex mcp --index . --embeddings-url https://api.openai.com/v1 \
--embeddings-model text-embedding-3-small| Tier | Flag | Quality | Offline | Default build? |
|---|---|---|---|---|
| Hugot (pure Go) | --embeddings |
Good (MiniLM-L6-v2) | Yes (model auto-downloads on first use) | Yes |
| Built-in | --embeddings (when Hugot unavailable) |
Basic (GloVe word averaging) | Yes | Yes |
| API | --embeddings-url |
Best (transformer model) | No | Yes |
| ONNX | --embeddings + build tag |
Best | Yes (model + libonnxruntime required) | No |
| GoMLX | --embeddings + build tag |
Good | Yes (XLA plugin auto-downloads) | No |
The default build ships with Hugot using the pure-Go ONNX runtime — no native dependencies, no manual model placement. The MiniLM-L6-v2 model downloads to ~/.cache/gortex/models/ on first use (~90 MB).
Opt-in faster backends via build tags:
go build -tags embeddings_onnx ./cmd/gortex/ # needs: brew install onnxruntime
go build -tags embeddings_gomlx ./cmd/gortex/ # auto-downloads XLA pluginGortex tracks how many tokens it saves compared to naive file reads — per-call, per-session, and cumulative across restarts:
- Per-call:
get_symbol_sourceand other source-reading tools include atokens_savedfield in the response, showing the difference between reading the full file vs the targeted symbol. - Session-level:
graph_statsreturns atoken_savingsobject withcalls_counted,tokens_returned,tokens_saved,efficiency_ratio. - Cumulative (cross-session):
graph_statsalso returnscumulative_savingswhen persistence is wired — includesfirst_seen,last_updated, andcost_avoided_usdper model (Claude Opus/Sonnet/Haiku, GPT-4o, GPT-4o-mini). Backed by~/.cache/gortex/savings.json.
# Show totals + cost across all default models
gortex savings
# Highlight a single model (fuzzy match: "opus" → claude-opus-4)
gortex savings --model opus
# Machine-readable output
gortex savings --json
# Wipe cumulative totals
gortex savings --reset
# Override pricing (JSON array of {model, usd_per_m_input})
GORTEX_MODEL_PRICING_JSON='[{"model":"mycorp","usd_per_m_input":5}]' gortex savingsToken counts use tiktoken (cl100k_base) — the tokenizer Claude and GPT-4 actually use — via github.com/pkoukk/tiktoken-go with an embedded offline BPE loader, so no runtime downloads. The BPE is lazy-loaded on first call. If init fails for any reason, the package falls back to the legacy chars/4 heuristic so metrics stay usable.
Gortex snapshots the graph to disk on shutdown and restores it on startup, with incremental re-indexing of only changed files:
# Default cache directory: ~/.cache/gortex/
gortex mcp --index /path/to/repo
# Custom cache directory
gortex mcp --index /path/to/repo --cache-dir /tmp/gortex-cache
# Disable caching
gortex mcp --index /path/to/repo --no-cacheThe persistence layer uses a pluggable backend interface (persistence.Store). The default backend serializes as gob+gzip. Cache is keyed by repo path + git commit hash, with version validation to invalidate on binary upgrades.
Measured on an Apple Silicon laptop with the default CGO build:
| Repository | Files | Nodes | Edges | Index time | Throughput | Peak heap |
|---|---|---|---|---|---|---|
| torvalds/linux | 70,333 | 1,690,174 | 6,239,570 | ~3 min | 300 files/s | 5.07 GB |
| microsoft/vscode | 10,762 | 204,501 | 808,902 | ~1 min | 143 files/s | 580 MB |
| zzet/gortex (self) | 430 | 5,583 | 53,830 | 3.4s | 127 files/s | 52 MB |
Parsing dominates wall time (65–80%); reference resolution and search-index build scale sub-linearly. Everything runs in-process — no external services, no database, no network.
gortex binary
CLI (cobra) ──> MultiIndexer ──> In-Memory Graph (shared, per-repo indexed)
MCP (stdio) ──────────────────> Query Engine (repo/project/ref scoping)
HTTP /v1/* ──────────────────> same tools + /v1/graph + /v1/events (SSE)
Daemon (unix) ──────────────────> shared graph for every MCP client, session isolation
MCP Prompts ──────────────────> (pre_commit, orientation, safe_to_change)
MCP Resources ──────────────────> (session, stats, schema, communities, processes)
MultiWatcher <── filesystem events (fsnotify, per-repo)
CrossRepoResolver ──> cross-repo edge creation (type-aware)
Persistence ──> gob+gzip snapshot (pluggable backend)
Data flow:
- On startup, loads cached graph snapshot if available; otherwise performs full indexing
- MultiIndexer walks each repo directory concurrently, dispatches files to language-specific extractors (tree-sitter)
- Extractors produce nodes (files, functions, types, etc.) and edges (calls, imports, defines, etc.) with type environment metadata
- In multi-repo mode, nodes get
RepoPrefixand IDs become<repo_prefix>/<path>::<Symbol> - Resolver links cross-file references with type-aware method matching; CrossRepoResolver links cross-repo references with same-repo preference
- Query Engine answers traversal queries with optional repo/project/ref scoping
- MultiWatcher detects changes per-repo and surgically patches the graph (debounced per-file), then re-resolves cross-repo edges
- On shutdown, persists graph snapshot for fast restart
Node kinds: file, function, method, type, interface, variable, import, package
Edge kinds: calls, imports, defines, implements, extends, references, member_of, instantiates
Multi-repo fields: Nodes carry repo_prefix (empty in single-repo mode). Edges carry cross_repo (true when connecting nodes in different repos). Node IDs use <repo_prefix>/<path>::<Symbol> format in multi-repo mode.
Gortex indexes 92 languages — see docs/languages.md for the full table (extensions, engine, extracted symbols per language).
make build # Build with version from git tags
make test # go test -race ./...
make bench # Run all benchmarks
make lint # golangci-lint
make fmt # gofmt -s
make install # go install with version ldflagsRequires Go 1.21+ and CGO enabled (for tree-sitter C bindings).
Gortex is source-available under a custom license based on PolyForm Small Business. See LICENSE.md for full terms.
Free for: individuals, open-source projects, small businesses (<50 employees / <$500K revenue), nonprofits, education, government, socially critical orgs.
Commercial license required for: organizations with 50+ employees or $500K+ revenue, competing products, resale/bundling. Contact license@zzet.org.
Contributors: active contributors listed in CONTRIBUTORS.md receive a free non-competing commercial license for their employer.
See CONTRIBUTING.md for guidelines on adding features, language extractors, and submitting PRs. Active contributors receive a contributor commercial license.
