CodeSextant
AI coding agents can generate code faster than they can understand a repository. They search for names, reread files, miss call sites, and break B while fixing A. The bottleneck is not model intelligence alone. It is the missing index.
CodeSextant is a local, shared code index for coding agents. It builds an import-aware symbol graph and answers the questions an agent needs before editing: who calls this symbol, what depends on it, and which few files are actually worth reading?
Python and TypeScript/JavaScript get resolved references. Other supported languages are clearly labelled when results come from low-confidence name matching. Index once, then every agent on the machine reuses the same map. No cloud, no API keys, and no source code leaves your machine.
The name is from the sextant: an instrument for fixing your position when there is no landmark in sight.
Visual map prototype
This working prototype renders 598 real symbols from CodeSextant itself. Its shape is not decorative: reference edges determine structural communities, cohesive communities form tighter and more separated clusters, and tangled coupling produces overlap and visual noise. The interaction supports rotation, semantic zoom, and flying from an overview into a symbol.
The visual renderer is not wired into the published Python package yet. Layout normalization,
cross-machine reproducibility, and module-level aggregation for very large repositories remain
open work. The current map command returns a ranked text map, not this renderer.
The problem
The hidden cost of agentic coding is token budget. An agent that starts editing without a global picture rewrites things that already exist, misses call sites, and creates conflicts.
The usual fallback is grep. But name matching treats every identically-named symbol as the same thing, so in a codebase with common names like handle, run, or Config, the results are mostly noise. We have measured cases where every returned "reference" was wrong.
CodeSextant resolves imports instead of matching text, and it keeps the resulting graph in a single resident service that every agent on the machine queries.
What makes it different
| Import resolution, not name matching | Python goes through jedi (which understands import chains and scope); TS/JS through ts-morph (findReferences, so same-name symbols in unrelated modules do not collide). Results are labelled high or low confidence, and an agent is expected to auto-trust only the high-confidence ones. |
| One daemon, shared by every agent | A single process per machine (cross-process file lock plus an exclusive listen socket, with idempotent startup). Claude Code, Cursor, or any HTTP client talk to the same instance. Projects are isolated by sha1(absolute repo path) into separate SQLite databases. |
| Python and TypeScript/JavaScript | These are the languages CodeSextant actually resolves imports for, and the ones it is tested against. tree-sitter can extract symbols from a dozen more (Go, Rust, C#, Java, C, C++, Kotlin, Swift, PHP, Ruby, Bash, Lua) but those get name-matched references, not resolved ones. Treat them as experimental. Broader real support is a goal, not a claim. |
| Local only | No cloud calls, no API key, nothing leaves the machine. This is stricter than "local LSP tooling": there is no key to configure at all. |
| Budgeted output | map uses weighted PageRank to return the most important N symbols that fit a token budget, rather than dumping the whole graph. |
Quick start
Requires Python 3.10 or newer.
pip install codesextant
watchdog is installed with CodeSextant. The first index scans the repository once. After that,
the daemon listens for native OS file events and sends only created, edited, moved, or deleted
paths to the indexer after a short debounce. A normal save does not walk the repository. A full
reconciliation is reserved for initial indexing, daemon restart recovery, lost watcher state, or
an explicit forced rebuild.
Give CodeSextant to your agent
Download the single CodeSextant SKILL.md after installation and place it in your agent's skill directory. For example:
.agents/skills/codesextant/SKILL.md # Codex and compatible agents
.claude/skills/codesextant/SKILL.md # Claude Code
Keep the entry filename as SKILL.md. The containing codesextant directory is the skill
name under the Agent Skills specification.
If an agent does not support skill directories, attach that one Markdown file and ask the agent to follow it before editing. The skill starts the shared daemon, binds the current repository, uses the map to narrow what should be read, checks references and impact before changes, and preserves confidence labels instead of treating name matches as confirmed callers.
High-confidence TS/JS resolution needs two more things: Node on your PATH, and a one-time npm install inside ts_bridge/. That directory ships in the git repository, not in the pip package. So a pip install gives you resolved references for Python and name-matched ones for TS/JS; clone the repository instead if you need TS/JS resolved. Either way the result carries its confidence label, and a missing bridge degrades the answer rather than breaking the tool.
python -m codesextant index <repo> # build or incrementally update the index
python -m codesextant map <repo> [--budget N] # most important symbols, within a token budget
python -m codesextant references <repo> <symbol> [--src-root R] [--def-path D]
python -m codesextant symbols <repo> [--file F]
python -m codesextant status <repo>
# any command takes --json for machine-readable output
Running it as a resident service:
python -m codesextant.daemon ensure # idempotent: starts one only if none is running
python -m codesextant.daemon ping # strict liveness check (verifies /health brand, not just the port)
python -m codesextant.daemon stop
# then open http://127.0.0.1:8790/ for a self-contained dashboard (inline CSS/JS, no CDN, works offline)
HTTP endpoints, all taking project=<absolute repo path>:
GET /health /get_symbols /get_map /status (?fresh=1 to compare against git HEAD) /projects;
POST /find_references /reindex.
On Windows, tools/register_windows_startup.ps1 registers the daemon to start on login (run it as administrator to get boot-time start as well). It is idempotent, so re-running it is safe. A supervisor task probes liveness every 5 seconds and restarts the daemon if it exits.
Architecture
┌── CodeSextant daemon (Python, port 8790, single instance, shared by all agents) ──┐
│ tree-sitter symbol extraction + jedi / ts-morph import resolution │
│ incremental SQLite (content hash + git HEAD freshness) + weighted PageRank │
│ per-project isolation: sha1(repo path) -> ~/.codesextant/<key>.db │
│ HTTP API, plus a self-contained dashboard on GET / │
└───────────────────────────────────────────────────────────────────────────────────┘
▲ one daemon, many front-ends: standalone shell, IDE webview, agent HTTP clients
Single-instance startup is what makes "every agent shares one map" work at all. Without it, each agent would build and hold its own copy of the graph.
Large cold map queries are served from a SQLite covering index plus a revision-checked JSON snapshot, with a small in-process LRU on top. Every snapshot is a cache keyed on index revision and query parameters; SQLite remains the only source of truth, and any change invalidates them.
Configuration
All settings are environment variables. Boolean flags accept 1/true/yes/on case-insensitively.
| Variable | Default | Effect |
|---|---|---|
CODESEXTANT_HOME |
~/.codesextant |
SQLite database directory |
CODESEXTANT_PORT |
8790 |
daemon port |
CODESEXTANT_SUPERVISOR_INTERVAL_SEC |
5 |
liveness probe interval, minimum 1 |
CODESEXTANT_MAP_TIMEOUT_SEC |
60 |
client deadline for cold map queries only |
CODESEXTANT_MAP_CACHE_SIZE |
4 |
trimmed map results cached per DB revision |
CODESEXTANT_NAMEGRAPH_MAX_FILES |
adaptive | override the file-scan cap; adapts 12 to 5000 by symbol count when unset |
CODESEXTANT_NAMEGRAPH_MAX_UNIQUE_EDGES |
250000 |
hard cap so generated code cannot exhaust memory |
CODESEXTANT_WATCH_ENABLED |
on | filesystem watcher for proactive incremental indexing |
CODESEXTANT_WATCH_DEBOUNCE_MS |
2000 |
delay that combines a burst of file events into one dirty-path update |
CODESEXTANT_TS_MORPH_DISABLED |
off | force TS/JS to name matching |
CODESEXTANT_TS_MORPH_TIMEOUT |
30 |
ts-morph subprocess timeout, seconds |
CODESEXTANT_GIT_FRESHNESS_DISABLED |
off | stop comparing the index against git HEAD |
CODESEXTANT_CSRF_GUARD |
on | Origin check on POST endpoints (allows localhost, Tauri and IDE webviews; blocks cross-site) |
A few lower-level language-inference knobs (CODESEXTANT_INFER_LANG_*) are documented in the source.
Testing
python -m pytest tests/ -q
443 tests, about a minute on a developer laptop. They cover the daemon lifecycle, incremental indexing, map scalability, snapshot invalidation, and reference resolution across the supported languages.
Known limitations
We would rather state these than have you discover them.
- Reference lookup needs the right
--src-rootwhen the import root lives in a subdirectory (.../src). Get it wrong and high-confidence references are silently missed. - When several symbols share a name, omitting
--def-pathmeans the first candidate definition wins, and high-confidence results may legitimately come back as zero. All candidates are listed so you can disambiguate. - PageRank quality depends on how dense the reference edges are, and those accumulate as
find_referencesis called. A freshly indexed repo produces a rougher map than one that has been queried for a while. - High-confidence TS/JS resolution requires
npm installints_bridge/, which only the git repository carries. A pip install therefore gets name-matched TS/JS references, and the confidence label says so rather than hiding it. - Go and Rust get tree-sitter symbols but name-matched references. This is a real accuracy ceiling, not a temporary gap.
- Index freshness is content-hash incremental plus a git HEAD comparison;
status?fresh=1tells you whether the index has fallen behind.
Repository layout
| Path | What it is |
|---|---|
codesextant/ |
The Python implementation. This is what pip install codesextant gives you and what the docs above describe. |
ts_bridge/ |
A small Node helper the Python side shells out to for ts-morph reference resolution. Git only; the pip package does not carry it. |
tests/ |
Test suite for the Python implementation. |
ts/ |
An in-progress TypeScript rewrite, not yet wired to anything. Nothing in codesextant/ imports it and it is not published. It is in the repository because the work is real and ongoing, but do not mistake it for the shipping implementation. |
Licence
MIT. See LICENSE.
The core is free and open source. A commercial edition is planned around what open source deliberately does not cover: a shared central map for teams and multi-agent fleets, access control with audit logs, private deployment, and supported integrations.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file codesextant-0.16.0.tar.gz.
File metadata
- Download URL: codesextant-0.16.0.tar.gz
- Upload date:
- Size: 236.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4512eb493286de533a028d328bef1d18eaa5df777abcb4c0af82fd8484a35f10
|
|
| MD5 |
4fb574bf9bc6d52f7f2a0aaf9b2c6998
|
|
| BLAKE2b-256 |
408ab8c0633445369a8ac434ea8d7578d4533598cd5dbe40b7e51ac65c66837a
|
File details
Details for the file codesextant-0.16.0-py3-none-any.whl.
File metadata
- Download URL: codesextant-0.16.0-py3-none-any.whl
- Upload date:
- Size: 181.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ee22c1ec21642ccfa162e321ec6ca2be28df4dde6a33bfe7c1ac27f2131880f
|
|
| MD5 |
1284c424b477bc44e60a47b407707160
|
|
| BLAKE2b-256 |
7ea0aea0b64091f661070a6d53ea1d4bf4c9f9f2191719104a674b794993bd26
|