Skip to main content

eulerian

Real-time code navigation for AI agents and editors. eulerian keeps a live symbol index — files, classes, functions, methods, constants, with line ranges — so an agent can jump straight to a definition instead of grepping or reading whole files.

Two ways to point it at code:

  • Local mode — watch a real working directory. A filesystem watcher re-parses files the moment they're saved; the index never goes stale and there's no explicit re-index step. Every query also runs a synchronous, cheap mtime-diff catch-up first (LocalWatcher.sync()), so a query issued immediately after a save — with no delay — never races ahead of the watcher's debounce window and returns pre-edit state.
  • Repo mode — register a git remote, check out a (user, repo, ref) worktree, and browse it without touching your actual working tree. Freshness is checked against the remote on each call instead of pushed live, since nothing is editing the worktree directly.

Both modes share one in-memory symbol index and the same tree-sitter parsing core. Python, Java and Go today; additional grammars are straightforward to add — see parser.py.

Install

uv tool install eulerian
# or
pip install eulerian

No other runtime dependencies beyond tree-sitter, tree-sitter-python, tree-sitter-java, tree-sitter-go, rapidfuzz, watchfiles, fastmcp, and typer — all pulled in automatically.

CLI

# Local mode: one-shot queries against a directory, no persistent watcher
eulerian status [PATH]
eulerian outline QUERY [PATH] [-k N]
eulerian find SYMBOL [PATH]

# Local mode: live watch + MCP server (stdio by default, for an MCP client)
eulerian watch [PATH] [--http --host HOST --port PORT]

# Repo mode: register, checkout, browse
eulerian repo add URL
eulerian repo list
eulerian repo fetch REPO
eulerian repo checkout REPO REF [--user NAME]
eulerian repo outline REPO REF QUERY [--user NAME] [-k N]

MCP server

eulerian watch [PATH] starts a FastMCP server (stdio or --http) exposing:

Local mode — watch(path), unwatch(path), outline(query, paths, root, k, format), find(symbol, root), references(symbol, root, regex, max_results), callers(symbol, root, depth), callees(symbol, root, depth), call_path(source, target, root, max_depth), imports(file, root), read(path, start, end, root, segments), status(root).

Repo mode — repo_add(url), repo_fetch(repo), repo_list(), repo_pubkey(), checkout(repo, ref, user), checkout_close(repo, ref, user), git_log(repo, ref, user, n), repo_outline(repo, ref, query, paths, user, k, format, reset_head), repo_read(repo, ref, path, user, start, end, segments, reset_head), repo_references(repo, ref, symbol, user, regex, max_results, reset_head), repo_callers(repo, ref, symbol, user, depth, reset_head), repo_callees(repo, ref, symbol, user, depth, reset_head), repo_call_path(repo, ref, source, target, user, max_depth, reset_head), repo_imports(repo, ref, file, user, reset_head).

Point any MCP-capable client (Claude Code, etc.) at eulerian watch <path> to get instant, line-precise code navigation without burning tool calls on grep/read round-trips.

references/repo_references complement outline/find, which only match definitions in the symbol index: they grep the watched directory's or worktree's file contents directly for call sites, imports, type hints, decorators, and any other textual mention of a symbol, defaulting to whole-word matching (pass regex=True for a raw pattern instead).

callers/callees/call_path/imports (and their repo_* counterparts) walk a structural call/import graph instead, built from the CallEdge/ ImportEdge records the parser resolves during parsing — same-file calls and calls through a tracked import alias. They're precise where they resolve at all, but resolve less than references() finds textually: instance-method calls on untracked objects, decorators, and other dynamic call forms aren't in the graph. depth/max_depth walk multiple hops (depth=1 is direct callers/callees only); call_path finds the shortest path between two symbols, one per matching start node.

Indexing scope and .gitignore

Every file walk — the initial full scan, the local watcher's live filter, and repo_references's grep — honors .gitignore recursively (nested .gitignore files and global excludes included) whenever the root is a git working tree, via git ls-files/git check-ignore. Registered-repo worktrees always qualify; a locally watched directory only gets this treatment if it's itself a git repo. On top of that, a fixed set of noise directories (.venv, node_modules, __pycache__, build, dist, etc. — see parser.SKIP_DIRS) is always excluded, gitignored or not.

Repo-mode configuration

Bare clones and worktrees live under ~/.eulerian/ by default:

Env var Default Purpose
EULERIAN_GIT_REPOS_PATH ~/.eulerian/repos/ Bare clone + worktree storage
EULERIAN_GIT_SSH_KEY ~/.eulerian/ssh/id_ed25519 Deploy key for private remotes
EULERIAN_GIT_WORKTREE_MAX_IDLE_SEC 3600 Idle worktree eviction threshold

repo_add clones with --filter=blob:none (blobless partial clone) — the full commit/tree graph is fetched up front so any ref still resolves and checks out, but file content is fetched lazily per worktree instead of for the entire history. This cuts clone time and disk use substantially on repos with a lot of history/blob volume. Falls back to a full clone automatically if the remote doesn't support partial clone.

Architecture

parser.py        tree-sitter Python + Java + Go parser -> Symbol / CallEdge / ImportEdge
index.py         in-memory Index, keyed by an opaque handle, rapidfuzz search
sources/local.py watchfiles watcher  -> handle = resolved root Path
sources/repo.py  bare clone + worktree lifecycle -> handle = (user, repo, ref)
mcp/             FastMCP server exposing both modes as tools
cli.py           typer CLI

Index doesn't care what a handle is — local mode and repo mode just pick different shapes for it. Both feed the same outline/find query surface.

Metadata

Release files for eulerian 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for eulerian 0.4.0
File Size Uploaded Provenance
eulerian-0.4.0.tar.gz 38.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for eulerian 0.4.0
File Interpreter ABI Platform
eulerian-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 82.1 kB

Release files / eulerian-0.4.0.tar.gz

Download URL eulerian-0.4.0.tar.gz
Size 38.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f43fe6be3adbadaccc56cadfbfdb011dca9e5f7c6ac232b9b263bf637844cdf6
BLAKE2b-256 checksum
How to use checksums
732eea579def2d842a5d0ff751929ae8fab6be6652d8878aee75242b57c0e016
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / eulerian-0.4.0-py3-none-any.whl

Download URL eulerian-0.4.0-py3-none-any.whl
Size 43.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
df23f56c38ec6b80a1186d1cce256cfc230fc41b7b491f4d41bf6d3a3cd90171
BLAKE2b-256 checksum
How to use checksums
d7e51139fa192d2fb744b8a8a036165cd376df0a4b1992fa1172c5a49565b506
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for eulerian 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page