symbol
AST-native code intelligence, in Rust.
A fast, single-binary code-intelligence engine for humans and coding agents. Point it at a codebase and ask where a symbol is defined, who calls it, or edit it precisely — without re-reading whole files.
symbol answers the questions a human or an agent actually has about an
unfamiliar codebase:
- Where is
UserServicedefined, who callsdb.commit, what is the body ofprocess_payment— by qualified path, in tokens, not line ranges. - Edit a symbol safely: rename it and its references, replace its
definition, insert next to it, or patch an exact byte range — every write
transactional and reversible with
undo. - Measure a tree: lines of code across 500+ languages via a GitHub-Linguist port.
Static analysis only — symbol never imports or executes the target code.
Status. The Rust binary (
rust/) implements the symbol index, the read and write surface,loc, the MCP server and the Claude Code hook; it is differentially verified byte-for-byte against the Python implementation it replaced across real corpora (flask, gin, this repo). The Python package keeps the Python-specific analysis commands:audit,analyze,dump,init,map(the Python import graph) andupdate-linguist. The binary's ownmapworks over the index for every indexed language.
How it works
The engine is language-neutral. It never parses source in-process. Instead,
language analysis runs out-of-process in native-AST daemons that speak
newline-delimited JSON-RPC 2.0 over stdio (schemas/symbol.rpc.schema.json):
| Language | Daemon | Backed by |
|---|---|---|
| Python | pyscan |
Python's own ast |
| Go | go-scan |
go/types |
The Rust core owns everything neutral — the on-disk index, staleness and incremental refresh, search/read/write orchestration, transactions, the read cache, and LOC. A new language is a new daemon, not new branches in the engine.
pyscan is compiled into the binary. Its modules are stdlib-only and are
unpacked once into the user cache dir (~/Library/Caches/symbol on macOS,
$XDG_CACHE_HOME/symbol or ~/.cache/symbol elsewhere). They then run on the
first Python >= 3.11 found as python3 or python on PATH; set
SYMBOL_PYTHON to choose the interpreter. Parity with the Python CLI is
verified with both on the same Python minor version. An older interpreter
can't parse newer syntax, and files that fail to parse are skipped.
Daemon discovery: SYMBOL_PYSCAN / SYMBOL_GOSCAN override the full command.
Without an override, go-scan (or go-scan-<os>-<arch>) is taken from the
directory holding the symbol executable, then from a source checkout
(SYMBOL_REPO, else the one the binary was built from). If the project has
files in a language whose daemon can't start, index, refresh, symbol-level
writes, and reads that need a refresh exit non-zero
(daemon_unavailable, or python_unavailable naming the required version)
and leave the index and files untouched.
Install
PyPI
uv tool install wyolet-symbol # or: pipx install wyolet-symbol
Wheels for macOS 13+ (arm64, x86_64), Linux (x86_64, arm64; glibc or musl),
and Windows (x86_64) bundle the Rust symbol binary and go-scan. The
package's symbol runs audit, analyze, dump, init, map, and
update-linguist in Python and every other command on the binary, with
pyscan on the interpreter the package is installed into. Other platforms
get a pure wheel without binaries.
The binary is the first of: SYMBOL_BIN, the one bundled in the wheel,
rust/target/release/symbol or rust/target/debug/symbol when running from
a source checkout, and a symbol on PATH that is not a Python entry point
(such as the standalone binary below). Without one, those commands exit 1
and name these options.
Standalone binary
Each GitHub release has
symbol-<version>-<target>.tar.gz (.zip for Windows) for darwin-arm64,
darwin-amd64, linux-amd64, linux-arm64, and windows-amd64, plus
SHA256SUMS. The archive holds symbol and go-scan; keep them in the same
directory.
version=0.2.5 target=linux-amd64
base=https://github.com/wyolet/symbol/releases/download/v$version
curl -fsSLO "$base/symbol-$version-$target.tar.gz" -O "$base/SHA256SUMS"
grep " symbol-$version-$target.tar.gz" SHA256SUMS | sha256sum -c # macOS: shasum -a 256 -c
tar -xzf "symbol-$version-$target.tar.gz" -C ~/.local/bin
Linux binaries are statically linked. On macOS, archives downloaded through a
browser are quarantined: xattr -d com.apple.quarantine symbol go-scan.
From source
git clone https://github.com/wyolet/symbol
cd symbol/rust
cargo build --release # → target/release/symbol
Put target/release on your PATH, or alias it while building from source:
alias symbol="$PWD/target/release/symbol"
make dist builds the host platform's wheel and archive into dist/ and
build/archives/.
The Go daemon (go-scan) is cross-compiled per platform in CI; a Go toolchain
lets you build it locally via make build-go-scan. For Go projects without
Python, place a go-scan binary next to symbol. Go renames, refs, and
implementers also need the Go toolchain (go) on PATH, since go-scan loads
packages through packages.Load for them; indexing and other reads don't. Python analysis needs only a
Python >= 3.11 interpreter: no pip install and no repo checkout.
Usage
All commands take a global --root PATH (default .) and --json for machine
output.
Index
symbol index # build .symbol/symbol_index.msgpack.zst
symbol refresh # reindex only changed files
symbol stats # index statistics
The index builds lazily — read and write commands build or refresh it as needed.
Read
symbol search UserService # narrow candidates by name (signatures only)
symbol search user service --fixed # every pattern must appear as a substring
symbol search '^get_' --regex # regex match
symbol search save --kind method --limit 20
symbol code services.user.UserService # body by qualified path
symbol code services.user.UserService.save
symbol code src/services/user.py:120-145 # body by explicit line range
symbol outline src/services/user.py # parent-child symbol tree of a file
symbol callers UserService # tier-1 textual reference scan
symbol refs store.Store.Save # type-resolved references (Go)
symbol implementers net/http.Handler # implementers of an interface, or interfaces a type implements (Go)
Write
Every write is transactional and reversible. Pass --dry-run to preview the
diff without touching disk.
# Byte-range edit — replace, or delete with empty content
symbol patch src/foo.py 10-20 'new body'
symbol patch src/foo.py 10-20 ''
# Multiple non-overlapping edits to one file, applied atomically
symbol multi-patch src/foo.py '[{"range":"10-12","content":"..."},{"old":"x=1","content":"x=2"}]'
# Symbol-level ops by qualified path
symbol rename-symbol services.user.UserService AccountService # renames refs too
symbol replace-symbol services.user.UserService.save 'def save(self): ...'
symbol insert-symbol services.user.UserService after 'def new_method(self): ...'
symbol delete-symbol services.user.old_helper # refuses if callers exist; --force overrides
symbol undo # revert the most recent transaction
insert-symbol positions are before / after / start / end (relative to
the anchor symbol). Range edits run a read-cache preflight so an agent can't
patch a stale view of a file; --force skips it.
Import graph
The binary's map works over the index. The PyPI package's symbol map PATH
is the Python import graph instead (symbol map --help).
symbol map # cycles, hotspots, fan-out, deep chains
symbol map -v # plus every import site and coverage detail
symbol map --exclude '*_test.go' # leave files out of the graph
symbol map --dependents pkg/gateway/client # everything that imports it, by depth
symbol map --deps cmd/server --depth 2 # what it imports, two hops out
Nodes are modules — a Go package, a Python module — derived from the qualified paths in the index; edges are imports whose source names a module in the project, including across Go modules in one tree. A module can be named in full, by an indexed file path, or by a unique trailing part of its name. Cycle edges list their import sites, so cycles that exist only through test files are visible as such.
The index records each file's module only through its symbols and keeps
Python import sources as written. A file with no symbols (such as a
re-export-only __init__.py) has no node, and relative imports are not
resolved; map reports both as notes rather than counting them as edges.
Lines of code
symbol loc # colored breakdown by language
symbol loc path/ --files # per-file detail
symbol loc --classify src/app.py # show how each file was classified
MCP server
symbol --root path/to/project mcp # stdio MCP server for coding agents
| Tool | Does |
|---|---|
SearchSymbol, SymbolOutline, SymbolBody |
locate declarations, outline a file, fetch a body or line range |
SymbolCallers |
textual references by name (any language) |
SymbolRefs, SymbolImplementers |
type-resolved references and implements relation (Go) |
Patch, MultiPatch |
byte-range edits, read-cache gated |
ReplaceSymbol, InsertSymbol, DeleteSymbol, RenameSymbol |
symbol-level writes |
Undo, Refresh |
revert the last transaction, reindex |
Tool descriptions live in
src/wyolet/symbol/data/mcp_tools.toml.
Configuration
symbol.toml at the project root, or the same tables under [tool.symbol] in
pyproject.toml. The Rust index honors global and project [checker] excludes:
[checker]
exclude = ["alembic/*", "scripts/*"]
loc takes --exclude, --no-vendor-skip, and --config-dir for one-off
overrides.
Repository layout
rust/
├── symbol/ symbol-core → the `symbol` binary (index, reads, writes, loc)
├── linguist/ symbol-linguist → GitHub-Linguist port + LOC counting
├── dataset/ differential-test dataset mining and verification
└── harness/ black-box feature harness
src/wyolet/symbol/ is the Python package: the symbol console entry, the
audit engine (checkers, spec system, import graph), the package specs, and
the pyscan daemon the binary embeds.
License
MIT — see LICENSE.
Metadata
Release files for wyolet-symbol 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wyolet_symbol-0.3.0.tar.gz | 589.8 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| wyolet_symbol-0.3.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| wyolet_symbol-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl | Python 3 | none | Linux musl 1.1+ x86-64, Linux glibc 2.17+ x86-64 | Details |
| wyolet_symbol-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl | Python 3 | none | Linux glibc 2.17+ ARM64, Linux musl 1.1+ ARM64 | Details |
| wyolet_symbol-0.3.0-py3-none-macosx_13_0_x86_64.whl | Python 3 | none | macOS 13.0+ x86-64 | Details |
| wyolet_symbol-0.3.0-py3-none-macosx_13_0_arm64.whl | Python 3 | none | macOS 13.0+ ARM64 | Details |
| wyolet_symbol-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.9 MB
Release files / wyolet_symbol-0.3.0.tar.gz
| Download URL | wyolet_symbol-0.3.0.tar.gz |
|---|---|
| Size | 589.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c65eaed24c9df9c6d082d6bcb0bde26534cc6962ee9036f1acf4690a11b7b7dc
|
|
BLAKE2b-256 checksum How to use checksums |
3846fe99486d951b6aede11bcf68af7a852b6411cb8e5917b52f0e0393233d33
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / wyolet_symbol-0.3.0-py3-none-win_amd64.whl
| Download URL | wyolet_symbol-0.3.0-py3-none-win_amd64.whl |
|---|---|
| Size | 5.5 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
759fdafd69720212f0af17c2a18c924a1d22005e1fd5f0234d7b541ff3942a58
|
|
BLAKE2b-256 checksum How to use checksums |
a360d36e28e7570d742cf7b87ca27b3e8e399dcbb460d77af1a3702c53fb015e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / wyolet_symbol-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl
| Download URL | wyolet_symbol-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl |
|---|---|
| Size | 5.8 MB |
| Tags | Linux glibc 2.17+ x86-64 Linux musl 1.1+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
995de56ba0f3af47780dee3e41b64b9c41da355d9e93f4a8afb094fa141da2fa
|
|
BLAKE2b-256 checksum How to use checksums |
8ba4c02c5e38ea2fb1e2e78f93442ec50d4107763359764d2fbc45196338c819
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / wyolet_symbol-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl
| Download URL | wyolet_symbol-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl |
|---|---|
| Size | 5.2 MB |
| Tags | Linux glibc 2.17+ ARM64 Linux musl 1.1+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
64158b090372ac0a0b7558f5f759f6ffb9e31ae604c403d0339f753874728081
|
|
BLAKE2b-256 checksum How to use checksums |
c51ce107763a318b65c8263afdd5f029fc97200bd2a3ad40b8b090be3684a6b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / wyolet_symbol-0.3.0-py3-none-macosx_13_0_x86_64.whl
| Download URL | wyolet_symbol-0.3.0-py3-none-macosx_13_0_x86_64.whl |
|---|---|
| Size | 5.5 MB |
| Tags | Python 3 macOS 13.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
e5dd1ac62baedc91f4c3719ad456f89ce33c27b425f711f7f596a503ef4ba48b
|
|
BLAKE2b-256 checksum How to use checksums |
d787244d25aa4bbfac8193681c4a43980bd160e2ad327f5bd80da96f563dca13
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / wyolet_symbol-0.3.0-py3-none-macosx_13_0_arm64.whl
| Download URL | wyolet_symbol-0.3.0-py3-none-macosx_13_0_arm64.whl |
|---|---|
| Size | 5.0 MB |
| Tags | Python 3 macOS 13.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
6490e1ecc0abe1631e302e600397139dfbb7f0dfa92ce9dcdc710e04e0a2705a
|
|
BLAKE2b-256 checksum How to use checksums |
7d71772304f528f4473e542eb1b88cb5aa7168c828b417f33e254b9c21121325
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / wyolet_symbol-0.3.0-py3-none-any.whl
| Download URL | wyolet_symbol-0.3.0-py3-none-any.whl |
|---|---|
| Size | 287.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
de5dd880d9a4560d19febb452a6bf544265216750a608287c1374fbcb606da1b
|
|
BLAKE2b-256 checksum How to use checksums |
95dd4fb603c9c04d4364fdc8a67a1dbc15313aa4caf166feb3793e4de8321f9c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency log