Prerequisites#
-
Node.js >= 20.19 -- Anatoly uses modern Node.js APIs (ES modules, native fetch). Check your version with
node --version. -
Windows users: install and run Anatoly only inside WSL (Ubuntu / Debian). Anatoly depends on native modules (ONNX Runtime, tree-sitter, LanceDB) and on POSIX shell semantics for its bash tool, which the Windows-native Node runtime does not provide. Do not install Node.js on the Windows side: a Windows install ends up on the WSL
$PATH(typically vianvm-for-windowsor the Node MSI) and silently shadows your WSL Node, leading to confusing crashes. Usenvminside WSL to manage Node, and ensurewhich noderesolves to a Linux path (/home/<you>/.nvm/...), never to/mnt/c/.... -
An LLM auth path -- Anatoly is multi-provider and supports four modes. Pick one:
Mode Setup Cost When to pick Subscription (default) Claude Code CLI installed + logged in Your Claude.ai (Pro / Max) subscription Most users — no API key needed Subscription (Google) Google OAuth via Gemini CLI Your Code Assist subscription, $0/token Cost-optimize lightweight axes BYOK API Set ANTHROPIC_API_KEY(orOPENAI_API_KEY,GOOGLE_GENERATIVE_AI_API_KEY, etc.)Per-token billing No subscription, or pay-as-you-go preferred Local Run Ollama / LM Studio / vLLM Free Code that cannot leave your network
By default Anatoly assumes subscription mode for anthropic and google providers — the configured .anatoly.yml lists these as mode: subscription. If you prefer API mode, set the relevant env var and switch the provider's mode to api:
# Only needed for BYOK API mode
export ANTHROPIC_API_KEY="sk-ant-..."See Configuration → providers for the full provider config and Recommended LLM Setup for tuning per axis.
Install#
Run without installing#
The fastest way to try Anatoly:
npx @r-via/anatoly runInstall globally (npm)#
npm install -g @r-via/anatoly
anatoly runInstall globally (pnpm)#
pnpm add -g @r-via/anatoly
anatoly runInstall as a dev dependency#
npm install -D @r-via/anatoly
npx anatoly runThe first time anatoly run indexes a project, the default embedding model (Jina Embeddings V2 Base Code, ONNX, ~150 MB) is downloaded from HuggingFace and cached under ~/.cache/huggingface/. Progress is reported in the run log. Subsequent runs reuse the cached model.
To pre-download the model out of band (e.g. CI image build), run the bundled script:
node ./node_modules/@r-via/anatoly/scripts/download-model.jsInstall from source (debug unpublished commits)#
To test changes from a branch or unpublished commit, do not use npm install -g github:r-via/anatoly — it hits two reproducible npm/WSL bugs (NPM_CONFIG_GLOBAL inheritance breaks devDeps install in pacote, and ext4 races on tarball extract during the outer global install). Use the bundled Makefile instead:
# prerequisite: GNU make (usually preinstalled; on minimal distros: sudo apt install -y make)
git clone https://github.com/r-via/anatoly # or -b <branch>
cd anatoly
make install # deps + build + global symlink
make doctor # verify environment
anatoly --version # confirmmake help lists every target. To remove later: make uninstall.
WSL2 users#
If anatoly run exits with an error like:
/mnt/c/nvm4w/nodejs/anatoly: 15: exec: node: Permission denied…your Node.js is installed on the Windows side (typically nvm-windows / nvm4w) and is being picked up from the WSL PATH. Linux can't execute the Windows node.exe from a WSL shim. Install Node.js inside the distribution and re-install Anatoly:
# 1. Install nvm into the WSL distribution
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# 2. Load nvm into the *current* shell (DO NOT use `exec $SHELL` here —
# it replaces the process and discards any commands queued after it)
. "$HOME/.nvm/nvm.sh"
# 3. Install Node and re-install anatoly
nvm install 20.19
nvm use 20.19
which node # must NOT be under /mnt/c/...
npm install -g @r-via/anatolyAnatoly also fails fast at startup if it detects it is running under a Windows-installed Node from inside WSL (via binfmt_misc), so you should never end up with cross-OS path semantics silently degrading the run.
Optional: GPU-accelerated embeddings#
If you have an NVIDIA GPU with >= 12 GB VRAM and Docker installed, you can use GGUF-quantized models in Docker llama.cpp containers for higher-quality embeddings:
npx anatoly local-embeddings upgrade # Pulls Docker images, downloads GGUF models (SHA256-verified)
npx anatoly local-embeddings status # Inspect current install without making changesContainers start automatically with anatoly run when setup is detected. No Python dependency -- Docker is the only runtime requirement for GPU mode.
First run walkthrough#
From your project root (the directory containing package.json and your src/ folder):
npx anatoly runThis single command executes the full pipeline:
scan --> estimate --> triage --> usage graph --> index --> review --> deliberate --> reportWhat happens step by step#
-
Config -- Anatoly looks for
.anatoly.ymlin the project root. If none exists, it uses sensible defaults (scanssrc/**/*.tsandsrc/**/*.tsx). -
Scan -- The AST scanner (web-tree-sitter) parses every matched file and extracts symbols: functions, classes, types, enums, hooks, constants. It records line ranges, export status, and computes SHA-256 hashes for caching.
-
Estimate -- A local token estimation pass (no API calls) counts symbols and predicts cost and duration.
-
Triage -- Files are classified into
skiporevaluatetiers. Barrel exports (index.tsthat only re-exports), type-only files, and trivial files skip review at zero API cost. -
Usage graph -- A one-pass import resolution builds a project-wide usage graph, so the agent knows which symbols are imported where without making redundant tool calls.
-
RAG index -- Local code embeddings (768-dim vectors) are computed with Jina Embeddings V2 Base Code and stored in LanceDB. This enables semantic duplication detection across files. Zero API cost.
-
Review -- Each file in the
evaluatetier is reviewed by Claude agents running all seven axes in parallel (correction, overengineering, utility, duplication, tests, best practices, documentation). The agent can grep the project, read other files, and query the RAG index. Findings must include evidence. -
Report -- Reviews are aggregated into a Markdown report with a per-file summary, severity-sorted findings, and a global verdict.
What gets created#
After the first run, your project will contain:
.anatoly/
cache/
progress.json # Per-file review status (PENDING/DONE/CACHED/ERROR)
tasks/
<filename>.task.json # Per-file review task files
rag/ # LanceDB vector index + embeddings cache
runs/
2026-03-15_143022/
report.md # The audit report
reviews/ # Per-file review JSON
logs/ # Per-file agent transcripts
anatoly.ndjson # Structured run log
run-metrics.json # Timing, cost, and statsThe .anatoly/ directory is fully local and safe to .gitignore. On subsequent runs, unchanged files (same SHA-256 hash) are skipped automatically.
Subsequent runs#
anatoly run is always incremental — only files whose content has changed since the previous run get re-reviewed. Use --no-cache to force a full re-review of the entire codebase.
anatoly run # Always incremental — only changed files
anatoly run --no-cache # Force a full re-review of every file
anatoly run --file "src/core/**" # Review only matching files
anatoly run --run-id v1.2 # Custom run ID instead of timestampVerify it works#
After the run completes, you will see output like:
review complete -- 42 files | 7 findings | 35 clean (12 skipped . 30 evaluated) | 4m 23s
run 2026-03-15_143022
report .anatoly/runs/2026-03-15_143022/report.md
reviews .anatoly/runs/2026-03-15_143022/reviews/
transcripts .anatoly/runs/2026-03-15_143022/logs/
log .anatoly/runs/2026-03-15_143022/anatoly.ndjsonOpen the report to see findings:
anatoly run --open # Opens report in default app after generation
# or
cat .anatoly/runs/<run-id>/report.mdExit codes:
0-- All files are CLEAN1-- One or more findings reported2-- Fatal error (invalid configuration or runtime error)