Structural Elixir code intelligence and search powered by ExAST, Reach, Ecto, and Postgres/ParadeDB
  • Elixir 97.7%
  • TypeScript 1.9%
  • CSS 0.3%
  • HTML 0.1%
Find a file
2026-06-11 12:19:24 +03:00
.github/workflows Skip DuckDB contract tests in CI 2026-06-07 01:59:31 +03:00
assets Fix arrow keys: remove broken stopPropagation handler that killed Monaco key events 2026-05-18 01:10:40 +03:00
config Add text search mode, hexdocs source links, fix Volt 0.11 CSS paths 2026-05-16 18:01:34 +03:00
examples Populate fragment.module and add example script 2026-05-12 21:18:33 +03:00
guides Polish backend documentation wording 2026-06-08 19:34:59 +03:00
lib Prepare 0.8.0 release 2026-06-08 19:47:28 +03:00
priv/iconify Progress monitoring: CLI progress bar + LiveView dashboard 2026-05-17 16:29:46 +03:00
test Polish backend documentation wording 2026-06-08 19:34:59 +03:00
.credo.exs Add CI code quality checks 2026-05-06 13:09:28 +03:00
.formatter.exs Initial Exograph implementation 2026-05-06 10:18:51 +03:00
.gitignore Prepare 0.8.0 release 2026-06-08 19:47:28 +03:00
.reach.exs Run Reach smell checks in CI 2026-05-06 13:33:12 +03:00
.tool-versions Support Elixir 1.20 type checks 2026-06-06 16:59:40 +03:00
CHANGELOG.md Prepare 0.8.0 release 2026-06-08 19:47:28 +03:00
LICENSE Add MIT license 2026-05-07 18:06:45 +03:00
mix.exs Prepare 0.8.0 release 2026-06-08 19:47:28 +03:00
mix.lock Use published QuackDB release 2026-06-08 11:20:02 +03:00
README.md README: ecosystem footer linking org and Building Blocks standard 2026-06-11 12:19:24 +03:00

Exograph

Local CodeQL-style code search for Elixir, backed by DuckDB/QuackDB or Postgres and ExAST.

Exograph indexes Elixir source code into normalized Ecto-backed tables: files, AST fragments, comments, definitions, references, package versions, and optional Reach call graph facts. You can then query that index with structural AST patterns, text/regex search, symbol/reference filters, and Ecto-shaped joins.

What is Exograph?

Exograph is:

  • a library for indexing Elixir source code into DuckDB or Postgres
  • a set of Ecto schemas and migrations for normalized code facts
  • a structural search engine using ExAST for exact AST verification
  • an optional Reach-backed call graph index
  • a foundation for CodeQL-like Elixir queries over one project or many package versions

Exograph is not:

  • a hosted search service
  • a language server
  • a general multi-language analyzer
  • a replacement for ExAST or Reach

Why?

Use Exograph when text search is not enough:

  • find functions matching an AST shape
  • search definitions and references across packages
  • ask "which private functions call Repo.transaction/1?"
  • index multiple Hex package versions into one database
  • combine relational filters with exact ExAST verification
  • persist Reach call graph facts for caller/callee queries

Installation

def deps do
  [
    {:exograph, "~> 0.7"}
  ]
end

DuckDB through QuackDB is the default local backend. Postgres remains supported; ParadeDB's pg_search extension is optional and enables BM25-backed text/code-fact retrieval.

Quickstart

Point Exograph at Elixir source. Mix tasks start a managed QuackDB server automatically unless you pass an existing QuackDB-backed Ecto repo:

{:ok, index} =
  Exograph.index("lib",
    repo: MyApp.QuackDBRepo,
    migrate?: true
  )

{:ok, hits} = Exograph.search(index, "Repo.get!(_, _)")

The configured backend retrieves candidates by term index; ExAST verifies the structural match.

Index Hex.pm

Download and index packages directly from Hex.pm:

mix exograph.index.hex --mode latest --duckdb-shards 4 --duckdb-threads 1 --prefix hex

Modes: latest (one version per package), top --limit 5000, all (every version). Resumes automatically — already-indexed packages are skipped.

For large corpora, DuckDB sharding keeps independent shard files and queries them through %Exograph.ShardedIndex{} without a merge step. Use --manifest-path to persist the shard manifest.

Web UI

Exograph includes an embedded web interface for exploring indexes:

mix exograph.web --prefix myindex --port 4200

Add --web to mix exograph.index.hex for a live progress dashboard while indexing runs.

Features:

  • Monaco editor with Elixir syntax highlighting and autocompletion
  • Structural, text, and regex search modes
  • IDE-style error diagnostics
  • Collapsible results grouped by package with code previews
  • Hex.pm links on package names
  • Live progress dashboard at /progress during Hex.pm indexing

JSON API

The web server exposes a JSON API:

POST /api/search   — structural, text, or regex search
POST /api/query    — DSL query execution
GET  /api/packages — list indexed packages
GET  /api/stats    — index statistics

Cursor pagination via cursor/next_cursor. Rate limited (60 req/min).

Query with code facts

Use Exograph.DSL to combine structural AST patterns with indexed code facts:

import Exograph.DSL

query =
  from(f in Fragment,
    join: r in assoc(f, :references),
    where: r.qualified_name == "Repo.transaction/1",
    where: matches(f, "def _ do ... end")
  )

{:ok, hits} = Exograph.all(index, query)

Reach call graph facts can also be queried directly:

Exograph.search_callers(index, "Repo.transaction/1")
Exograph.search_callees(index, "MyApp.Accounts.update_user/2")

How it compares

Tool Scope Storage Query style Elixir AST-aware? Best for
ripgrep local text search none regex/text no fast ad-hoc text search
ExAST structural AST matching none/advisory terms AST patterns/selectors yes exact search and patching
Reach dependence analysis in-memory graph/reports APIs / Mix tasks yes call/data/control-flow analysis
CodeQL semantic code analysis CodeQL database QL language not first-class Elixir security analysis at scale
Sourcegraph cross-repo search external index text/structural depending setup not Elixir-specific organization-wide search
Exograph Elixir code fact index DuckDB/QuackDB or Postgres/ParadeDB ExAST + Ecto-shaped DSL yes local/self-hosted Elixir code intelligence, large Hex package indexing

Features

  • ExAST-backed structural search with exact verification
  • normalized Ecto-backed storage for files, fragments, comments, definitions, references, packages, versions, and call edges
  • mix exograph.index.hex — streaming pipeline to index all of Hex.pm
  • package/version-scoped indexes for Hex or other source archives
  • text and regex search via DuckDB FTS/BM25 or Postgres/ParadeDB
  • optional Reach call graph extraction
  • ExDNA-powered structural similarity
  • web UI with Monaco editor, live progress dashboard, and JSON API

Documentation

Guide Content
Getting Started Installation, backend setup, first index/search
Querying Structural, text, and regex search; planning/explain
DSL Exograph.DSL, joins, selects, predicates
Code Facts Definitions, references, comments, typed hits
Call Graph Reach extraction, callers/callees, call edge DSL
DuckDB and QuackDB Recommended backend, sharding, manifests, tuning
Postgres and ParadeDB Postgres backend, migrations, BM25, performance tuning
Backend benchmarks Current DuckDB/Postgres benchmark methodology and results
Postgres COPY staging Design notes for a future fair Postgres bulk-ingest path
Package Indexing Indexing Hex.pm and manual package archives
Mix Tasks CLI indexing, searching, web UI
Web UI Monaco editor, search modes, progress dashboard
API JSON API endpoints, pagination, rate limiting
Comparisons Exograph vs ExAST, Reach, CodeQL, Sourcegraph
Architecture Storage model, verifier contract, extraction pipeline

Part of Elixir Vibe

Exograph indexes Elixir code — up to the entire public package ecosystem — for structural, AST-verified search.

It is one building block of a larger stack — tools that make AI-generated software checkable: structural search, dependence analysis, duplication and slop detection, session replay, and ecosystem-wide code search. See the Elixir Vibe organization for the rest, and Building Blocks for the Future Web for the thesis, architecture, and roadmap that tie them together.

License

MIT.