uncoded
AI coding agents navigate codebases poorly. They grep for guessed keywords, skim the first few lines of files, and fill gaps from pretraining rather than reading the actual code. The result is plausible-looking output built on a hallucinated understanding of the code.
uncoded builds a static navigation index for the codebase. Agents load it at the start of a task and navigate directly to what they need, without guessing or grepping.
It also ships uncoded body to read symbol bodies and uncoded refs to find
every reference to a symbol. References cover callers, dead-symbol checks, and
the full set of sites to update before a rename.
What it generates
Running uncoded sync produces:
.uncoded/namespace.yaml: a hierarchical YAML file listing every symbol:
directories, files, classes (with attributes and methods), functions. Covers all
configured source roots. An agent can load this at the start of a task and
immediately know the full vocabulary of the codebase.
.uncoded/stubs/: one .pyi stub per source file, with imports, full
signatures (parameter names, types, return types), module constants, and class
attributes.
.uncoded/docs.yaml: a heading outline of configured Markdown files. Each
file nests its #-prefixed headings as keys. Leaf headings map to null. Agents
load this to orient to the documentation. They then navigate to a heading with
Read or grep. uncoded generates it only when doc-roots is configured. It
is an outline only. uncoded body, uncoded refs, and stubs do not apply to
Markdown.
.uncoded/.gitignore: a local ignore rule for the whole .uncoded/
directory, including the rule itself. Generated indexes therefore stay out of
Git by default.
Skills, written to both .claude/skills/ and .agents/skills/:
uncoded-code-navigation: the code dispatch rule: loadnamespace.yamlfirst, read.pyistubs before source, useuncoded bodyanduncoded refsfor symbol operations. Generated whensource-rootsis configured.uncoded-doc-navigation: the docs navigation rule: loaddocs.yamlat session start, then useReadorgrepto reach a heading. Generated whendoc-rootsis configured.uncoded-consistency-review: a semantic consistency review that reports concrete disagreements between claims about the same concept (see Semantic consistency review). Generated whensource-rootsis configured.
Add these lines to your AGENTS.md or CLAUDE.md to load the navigation skills
every session. Skills are on-demand by default. Tying the load to an action
agents are about to take prompts them to act on it:
## Before you start
- Load the `uncoded-code-navigation` skill once per session, before searching, reading or editing any code.
- Load the `uncoded-doc-navigation` skill once per session, before searching, reading or editing any docs.
Install uv
uncoded runs via uv. Install uv if you don't
already have it. No separate uncoded install is needed. uvx runs it from PyPI
on demand.
Configure
Add a [tool.uncoded] section to your pyproject.toml:
[tool.uncoded]
source-roots = ["src", "tests"]
doc-roots = ["docs", "README.md"] # dirs walked for *.md, or individual .md files
source-roots and doc-roots are each optional. At least one must be set.
source-roots drives the code index (namespace.yaml + stubs). doc-roots
drives the doc index (docs.yaml). Entries in doc-roots can be directories (all
*.md files walked recursively) or individual .md files.
Non-Python repos can use .uncoded.toml in the project root instead, with
the same keys at the top level. No [tool.uncoded] wrapper is needed:
doc-roots = ["docs"]
pyproject.toml takes precedence over a sibling .uncoded.toml only when it
carries a [tool.uncoded] section. If both files configure uncoded in the same
directory, uncoded reports a configuration error. Configure in one file only.
Across directories, the nearer file wins. uncoded never reads either file from
inside the .uncoded/ directory.
Use
uvx uncoded sync
Run uvx uncoded sync from the repo root. It reads pyproject.toml (or
.uncoded.toml) to find your configured roots and builds the index and skill
files. Commit the generated skill files so that agents can load them in a fresh
checkout. The generated .uncoded/.gitignore keeps the index itself local.
If an existing repository already tracks .uncoded/, remove the directory from
Git's index once. The files stay on disk, and the generated ignore rule keeps
them out of later commits:
git rm -r --cached .uncoded
uvx uncoded sync
Keep it current with pre-commit
Add uncoded sync as a pre-commit hook so the index stays in sync
automatically:
- repo: local
hooks:
- id: uncoded
name: uncoded
entry: uvx uncoded sync
language: system
pass_filenames: false
The hook regenerates the ignored local index before every commit. If a skill template changed, the hook also updates its tracked generated skill files; stage those files and commit again.
You can also run pre-commit run --all-files in CI to verify that index
generation succeeds and the tracked skill files are current.
Verify the index is fresh
Use the check subcommand for scripted checks that must not modify the working
tree:
uvx uncoded check
It runs the same pipeline but writes nothing. It exits 0 if every generated file
is byte-identical to what a rebuild would produce. It exits 1 otherwise,
printing which files would change. Run sync first in a fresh checkout, because
the ignored local index does not come from Git.
Retrieve a symbol body
Use the body subcommand when you need a symbol's implementation, not just its
signature from the stub:
uvx uncoded body <name_path> --in <relative_path>
name_path is a slash-separated path: one segment (fn) for a top-level
symbol, two for a class member (Class/method). --in is the source file's
path (relative to cwd). The command prints the source text of the symbol to
stdout, byte-identical to what's on disk. No reformatting, no ast.unparse
normalisation.
For example, to retrieve the body of resolve_body from src/uncoded/body.py:
uvx uncoded body resolve_body --in src/uncoded/body.py
Find references to a symbol
Use the refs subcommand for impact analysis. Run it before a rename, signature
change, or delete. Run it also to confirm a symbol is dead before removing it:
uvx uncoded refs <name_path> --in <relative_path>
name_path follows the same convention as body: one segment for a top-level
symbol, two for a class member (Class/method).
Output is one reference per line as <path>:<line>:<col>. Line and column are
1-indexed. Each path is relative to the current working directory when possible
and otherwise absolute. Results are sorted by path, then line, then column. It
exits 0 on success. Empty output means no references.
For example, to find all callers of resolve_body:
uvx uncoded refs resolve_body --in src/uncoded/body.py
How agents use it
Agents load the navigation skills and follow this protocol once uncoded is set
up:
- Load the orientation artefacts. Read
.uncoded/namespace.yamlto see every symbol at a glance. Whendoc-rootsis configured, also read.uncoded/docs.yaml, the heading outline of all docs. Headings are literal text. UseReadorgrepto navigate to a section. - Read the relevant
.pyistubs to understand imports, signatures, constants, and class members. - Run
uvx uncoded body <name_path> --in <relative_path>when they need implementation detail for a specific symbol. - Run
uvx uncoded refs <name_path> --in <relative_path>to find every reference to a symbol: callers, dead-symbol checks. See Find references to a symbol for detail. - Edit a symbol using
Editwithuncoded body's output asold_string. - Rename across the codebase using
uncoded refsto enumerate every site, thenEditat each. - Safely delete by running
uncoded refsfirst. The output must be empty. ThenEditto remove. - Run
uvx uncoded syncafter every source or indexed documentation change, before using the index again.
Each tool owns one job. uncoded provides the stable map and signature index,
code through namespace.yaml and docs through docs.yaml. uncoded body
resolves a symbol's source body. uncoded refs maps every reference. Agents do
not grep, guess line numbers, or do offset arithmetic.
Semantic consistency review
A codebase can make conflicting claims about one concept through competing names, stale docstrings, mismatched signatures, or behaviour that no longer matches a symbol's name.
uncoded sync installs an /uncoded-consistency-review skill that checks for
semantic and naming inconsistencies supported by concrete evidence.
Invoke the skill by name:
- Claude Code:
/uncoded-consistency-review - Codex:
$uncoded-consistency-review
The review first checks vocabulary across the namespace, then checks symbol contracts across names, signatures, docstrings, and behaviour. Every finding quotes two claims about the same concept, explains how they differ, and explains why they should agree. The review retrieves symbol bodies only when it needs a docstring or implementation to confirm a candidate.
The skill returns its Markdown report directly. It does not modify the repository or report general design and hygiene concerns that do not establish a semantic inconsistency.
Upgrading from v1
Version 2.0.0 replaces injection with skills. In v1, uncoded sync always
injected navigation guidance into AGENTS.md/CLAUDE.md. In v2 it ships as
on-demand skills. Agents load them when relevant. Four manual steps after
upgrading:
-
Remove old marker blocks from your
AGENTS.mdandCLAUDE.md. Look for and delete these blocks:<!-- uncoded:start ... --> ... <!-- uncoded:end -->
and
<!-- uncoded:docs:start ... --> ... <!-- uncoded:docs:end -->
uncoded no longer manages these sections. Leaving them in place is harmless but they are now dead markup.
-
Update any skill pointer that references
coherence-review,uncoded-review, oruncoded-coherence-reviewtouncoded-consistency-review. The skill now names its semantic consistency focus directly. -
Remove the
instruction-filesconfig key if yourpyproject.tomlor.uncoded.tomlhas it. uncoded no longer reads this key. Leaving it in place causes no error. -
Restore always-on navigation if you want v1 behaviour back. Add the "Before you start" lines from What it generates to your
AGENTS.mdandCLAUDE.md.
Contributing
See AGENTS.md.
Metadata
Release files for uncoded 3.0.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 | |
|---|---|---|---|
| uncoded-3.0.0.tar.gz | 96.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| uncoded-3.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 133.6 kB
Release files / uncoded-3.0.0.tar.gz
| Download URL | uncoded-3.0.0.tar.gz |
|---|---|
| Size | 96.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1988f2e1ccd3d0f1ee84406c4085d859e0221d1099e76a28adfdd8420a3cb8fb
|
|
BLAKE2b-256 checksum How to use checksums |
efb0ef0a584881f9be09297ac1b4c0a21098dc590670d455792ddae737817f59
|
| 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 Sep 19, 2026.
Transparency logRelease files / uncoded-3.0.0-py3-none-any.whl
| Download URL | uncoded-3.0.0-py3-none-any.whl |
|---|---|
| Size | 37.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e1c5d2b3d3ecded0db913c1bb670dfd58da28c30a1e4e46a7b197194e592bd4e
|
|
BLAKE2b-256 checksum How to use checksums |
ccf4a691a87688d6771f7193cabd7bb750f1fa15cb0892a625223cf19c4d3f3f
|
| 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 Sep 19, 2026.
Transparency log