CodeSextant
A local code map service for AI agents. No cloud, no API keys. Every agent on your machine shares one import-resolved symbol graph, so they can understand a codebase without reading all of it.
Before an agent writes or changes any real code, it needs three answers: who calls this symbol, what breaks if I change it, and does something like this already exist. CodeSextant answers those from a resolved graph rather than a text search. It does not replace reading the code. It tells you which few places are worth reading.
The name is from the sextant: an instrument for fixing your position when there is no landmark in sight.
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
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_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
430 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.15.0.tar.gz.
File metadata
- Download URL: codesextant-0.15.0.tar.gz
- Upload date:
- Size: 232.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e44b7107b1ee7f02ed2f17823ef6007107eddc137a4e8bfa325e91ab1aff044c
|
|
| MD5 |
3d293e2884c54ba2e7f2775087fefd20
|
|
| BLAKE2b-256 |
123bf173530a80b024f92efb9aceedc6f71a684808264de25357c779edb514e6
|
File details
Details for the file codesextant-0.15.0-py3-none-any.whl.
File metadata
- Download URL: codesextant-0.15.0-py3-none-any.whl
- Upload date:
- Size: 178.2 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 |
9478b9a6779904dff40f85b739022888bbb82d5b3ef1f392c4f53ab06f49a9a9
|
|
| MD5 |
13c41b41a17de76c9550aae1bd2d149e
|
|
| BLAKE2b-256 |
71ba91767dd28a5f4e5a5bacc216f57c0cadaf55a4eb2087a5ec7f3245540c01
|