Metadata-Version: 2.4
Name: eulerian
Version: 0.1.1
Summary: Standalone real-time code index — live local directories and registered git repos
Keywords: code-navigation,mcp,tree-sitter,git-worktree,code-index,ai-agent
Author: Curtis Bangert
Author-email: Curtis Bangert <codecae@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Utilities
Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE)
Requires-Dist: fastmcp>=3.2.0
Requires-Dist: typer>=0.15.0
Requires-Dist: tree-sitter>=0.21
Requires-Dist: tree-sitter-python>=0.21
Requires-Dist: rapidfuzz>=3.0.0
Requires-Dist: watchfiles>=0.24.0
Requires-Dist: rich>=14.0.0
Requires-Python: >=3.13
Description-Content-Type: text/markdown

# 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.
- **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 parser.
Python only for now (multi-language grammars are straightforward to add —
see `parser.py`).

## Install

```bash
uv tool install eulerian
# or
pip install eulerian
```

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

## CLI

```bash
# 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)`, `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)`.

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.

## 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 |

## Architecture

```
parser.py        tree-sitter Python 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.
