uncoded 3.0.0__tar.gz → 3.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. {uncoded-3.0.0 → uncoded-3.0.1}/.agents/skills/uncoded-code-navigation/SKILL.md +11 -11
  2. {uncoded-3.0.0 → uncoded-3.0.1}/.claude/skills/uncoded-code-navigation/SKILL.md +11 -11
  3. {uncoded-3.0.0 → uncoded-3.0.1}/.github/workflows/ci.yml +2 -2
  4. uncoded-3.0.1/.github/workflows/docs.yml +43 -0
  5. {uncoded-3.0.0 → uncoded-3.0.1}/.pre-commit-config.yaml +6 -0
  6. {uncoded-3.0.0 → uncoded-3.0.1}/AGENTS.md +1 -6
  7. uncoded-3.0.1/PKG-INFO +35 -0
  8. uncoded-3.0.1/README.md +19 -0
  9. uncoded-3.0.1/docs/agent-workflow.md +73 -0
  10. uncoded-3.0.1/docs/architecture.md +43 -0
  11. uncoded-3.0.1/docs/commands.md +85 -0
  12. uncoded-3.0.1/docs/configuration.md +57 -0
  13. uncoded-3.0.1/docs/contributing.md +73 -0
  14. uncoded-3.0.1/docs/getting-started.md +83 -0
  15. uncoded-3.0.1/docs/index.md +79 -0
  16. uncoded-3.0.1/docs/keeping-current.md +48 -0
  17. uncoded-3.0.1/docs/stylesheets/extra.css +214 -0
  18. uncoded-3.0.1/docs/upgrading.md +64 -0
  19. uncoded-3.0.1/dreamcatcher.toml +39 -0
  20. uncoded-3.0.1/mkdocs.yml +71 -0
  21. {uncoded-3.0.0 → uncoded-3.0.1}/pyproject.toml +4 -2
  22. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/code_navigation.md +11 -11
  23. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/refs.py +6 -3
  24. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_refs.py +21 -0
  25. uncoded-3.0.1/uv.lock +1101 -0
  26. uncoded-3.0.0/PKG-INFO +0 -318
  27. uncoded-3.0.0/README.md +0 -294
  28. uncoded-3.0.0/dreamcatcher.toml +0 -25
  29. uncoded-3.0.0/uv.lock +0 -580
  30. {uncoded-3.0.0 → uncoded-3.0.1}/.agents/skills/uncoded-consistency-review/SKILL.md +0 -0
  31. {uncoded-3.0.0 → uncoded-3.0.1}/.agents/skills/uncoded-doc-navigation/SKILL.md +0 -0
  32. {uncoded-3.0.0 → uncoded-3.0.1}/.claude/skills/uncoded-consistency-review/SKILL.md +0 -0
  33. {uncoded-3.0.0 → uncoded-3.0.1}/.claude/skills/uncoded-doc-navigation/SKILL.md +0 -0
  34. {uncoded-3.0.0 → uncoded-3.0.1}/.github/workflows/publish.yml +0 -0
  35. {uncoded-3.0.0 → uncoded-3.0.1}/.gitignore +0 -0
  36. {uncoded-3.0.0 → uncoded-3.0.1}/.markdownlint-cli2.yaml +0 -0
  37. {uncoded-3.0.0 → uncoded-3.0.1}/.prettierrc +0 -0
  38. {uncoded-3.0.0 → uncoded-3.0.1}/CLAUDE.md +0 -0
  39. {uncoded-3.0.0 → uncoded-3.0.1}/LICENSE +0 -0
  40. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/__init__.py +0 -0
  41. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/ast_helpers.py +0 -0
  42. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/body.py +0 -0
  43. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/cli.py +0 -0
  44. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/config.py +0 -0
  45. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/consistency_review.md +0 -0
  46. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/doc_navigation.md +0 -0
  47. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/docs_map.py +0 -0
  48. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/extract.py +0 -0
  49. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/markers.py +0 -0
  50. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/namespace_map.py +0 -0
  51. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/read_helpers.py +0 -0
  52. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/resolver.py +0 -0
  53. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/skill.py +0 -0
  54. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/stubs.py +0 -0
  55. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/sync.py +0 -0
  56. {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/yaml_tree.py +0 -0
  57. {uncoded-3.0.0 → uncoded-3.0.1}/tests/__init__.py +0 -0
  58. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_body.py +0 -0
  59. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_cli.py +0 -0
  60. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_config.py +0 -0
  61. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_docs_map.py +0 -0
  62. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_encoding_gate.py +0 -0
  63. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_extract.py +0 -0
  64. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_markers.py +0 -0
  65. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_namespace_map.py +0 -0
  66. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_skill.py +0 -0
  67. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_stubs.py +0 -0
  68. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_sync.py +0 -0
  69. {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_uncoded.py +0 -0
@@ -31,8 +31,8 @@ tools don't.
31
31
 
32
32
  ## How to execute the rule
33
33
 
34
- The index has two parts: a namespace map and per-file stubs. Follow this
35
- sequence.
34
+ The index has two parts: a namespace map and per-file stubs. Start with the map
35
+ and add detail only when the task needs it.
36
36
 
37
37
  **Step 1: Orient. Read the namespace map first.** If the map is missing, run the
38
38
  repository's configured `uncoded sync` command. Then, before answering the user,
@@ -55,18 +55,18 @@ src/foo/bar.py → .uncoded/stubs/src/foo/bar.pyi
55
55
  tests/test_foo.py → .uncoded/stubs/tests/test_foo.pyi
56
56
  ```
57
57
 
58
- Read the stub for every file you intend to touch or reference, including tests.
59
- The stub contains imports, every signature with types, module-level assignments,
60
- and class attributes. That is enough for most navigation. Skipping straight to
61
- source means reading many lines to learn what the stub would have told you in
62
- one. If no stub exists at the expected path, the file has no symbols indexed. In
63
- that narrow case, read source directly.
58
+ The stub contains imports, parameter names and annotations, return types,
59
+ module-level assignments, and class attributes. It omits parameter defaults,
60
+ decorators, docstrings, and function bodies. Read source when the task depends
61
+ on an omitted detail or needs exact code. If no stub exists at the expected
62
+ path, the file has no symbols indexed. In that narrow case, read source
63
+ directly.
64
64
 
65
65
  **Step 3: Act.** Use `uncoded body` to read a symbol's body. Use `uncoded refs`
66
66
  to find every reference to a symbol. Use `Edit` (with `uncoded body`'s output as
67
- `old_string`) to change a symbol. With the map and stub loaded, you have the
68
- exact `relative_path` and `name_path` each tool needs. Use `ClassName/method`
69
- for a method and `function_name` for a top-level function. Per task:
67
+ `old_string`) to change a symbol. Use the exact `relative_path` and `name_path`
68
+ from the map. Use `ClassName/method` for a method and `function_name` for a
69
+ top-level function. Per task:
70
70
 
71
71
  - **Read a symbol's body.** `uvx uncoded body <name_path> --in <relative_path>`
72
72
  prints the symbol's source text to stdout, byte-identical to disk. Returns
@@ -31,8 +31,8 @@ tools don't.
31
31
 
32
32
  ## How to execute the rule
33
33
 
34
- The index has two parts: a namespace map and per-file stubs. Follow this
35
- sequence.
34
+ The index has two parts: a namespace map and per-file stubs. Start with the map
35
+ and add detail only when the task needs it.
36
36
 
37
37
  **Step 1: Orient. Read the namespace map first.** If the map is missing, run the
38
38
  repository's configured `uncoded sync` command. Then, before answering the user,
@@ -55,18 +55,18 @@ src/foo/bar.py → .uncoded/stubs/src/foo/bar.pyi
55
55
  tests/test_foo.py → .uncoded/stubs/tests/test_foo.pyi
56
56
  ```
57
57
 
58
- Read the stub for every file you intend to touch or reference, including tests.
59
- The stub contains imports, every signature with types, module-level assignments,
60
- and class attributes. That is enough for most navigation. Skipping straight to
61
- source means reading many lines to learn what the stub would have told you in
62
- one. If no stub exists at the expected path, the file has no symbols indexed. In
63
- that narrow case, read source directly.
58
+ The stub contains imports, parameter names and annotations, return types,
59
+ module-level assignments, and class attributes. It omits parameter defaults,
60
+ decorators, docstrings, and function bodies. Read source when the task depends
61
+ on an omitted detail or needs exact code. If no stub exists at the expected
62
+ path, the file has no symbols indexed. In that narrow case, read source
63
+ directly.
64
64
 
65
65
  **Step 3: Act.** Use `uncoded body` to read a symbol's body. Use `uncoded refs`
66
66
  to find every reference to a symbol. Use `Edit` (with `uncoded body`'s output as
67
- `old_string`) to change a symbol. With the map and stub loaded, you have the
68
- exact `relative_path` and `name_path` each tool needs. Use `ClassName/method`
69
- for a method and `function_name` for a top-level function. Per task:
67
+ `old_string`) to change a symbol. Use the exact `relative_path` and `name_path`
68
+ from the map. Use `ClassName/method` for a method and `function_name` for a
69
+ top-level function. Per task:
70
70
 
71
71
  - **Read a symbol's body.** `uvx uncoded body <name_path> --in <relative_path>`
72
72
  prints the symbol's source text to stdout, byte-identical to disk. Returns
@@ -15,7 +15,7 @@ jobs:
15
15
  fetch-depth: 0
16
16
  - uses: astral-sh/setup-uv@v6
17
17
  - run: uv python install 3.12
18
- - run: uv sync --extra dev
18
+ - run: uv sync
19
19
  - run: uv run pre-commit run --all-files
20
20
 
21
21
  test:
@@ -29,7 +29,7 @@ jobs:
29
29
  fetch-depth: 0
30
30
  - uses: astral-sh/setup-uv@v6
31
31
  - run: uv python install ${{ matrix.python-version }}
32
- - run: uv sync --extra dev
32
+ - run: uv sync
33
33
  - run: uv run pytest -v -m "integration or not integration"
34
34
  env:
35
35
  PYTHONWARNDEFAULTENCODING: "1"
@@ -0,0 +1,43 @@
1
+ name: Docs
2
+
3
+ # The site is already built in strict mode by the pull request checks. This
4
+ # workflow repeats that build from main and publishes its output.
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ concurrency:
14
+ group: pages
15
+ cancel-in-progress: false
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
+ with:
23
+ fetch-depth: 0
24
+ - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
25
+ - run: uv sync --locked
26
+ - run: uv run mkdocs build
27
+ - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
28
+ with:
29
+ path: site
30
+
31
+ deploy:
32
+ needs: build
33
+ runs-on: ubuntu-latest
34
+ permissions:
35
+ actions: read
36
+ pages: write
37
+ id-token: write
38
+ environment:
39
+ name: github-pages
40
+ url: ${{ steps.deployment.outputs.page_url }}
41
+ steps:
42
+ - id: deployment
43
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
@@ -48,6 +48,12 @@ repos:
48
48
  args: ["--write"]
49
49
  files: \.md$
50
50
  exclude: ^(CLAUDE\.md|(\.claude|\.agents)/skills/.*)$
51
+ - id: mkdocs
52
+ name: build documentation
53
+ entry: uv run mkdocs build
54
+ language: system
55
+ always_run: true
56
+ pass_filenames: false
51
57
  - id: uncoded
52
58
  name: uncoded
53
59
  entry: uv run uncoded sync
@@ -73,16 +73,11 @@ Clone and install dev dependencies:
73
73
  ```sh
74
74
  git clone https://github.com/alimanfoo/uncoded
75
75
  cd uncoded
76
- uv sync --extra dev
76
+ uv sync
77
77
  uv run uncoded sync
78
78
  uv run pre-commit install
79
79
  ```
80
80
 
81
- Run `uv sync --extra dev` before the first pre-commit run in a clean checkout.
82
- The ty hook type-checks `src` and `tests`. The test modules import dev-only
83
- packages such as pytest and hypothesis. Without the dev extras in the venv, ty
84
- cannot resolve those imports and reports spurious errors.
85
-
86
81
  This repo uses uncoded on itself. The pre-commit hook runs `uv run uncoded sync`
87
82
  on each commit. The local `.uncoded/` index is ignored. If the hook modifies a
88
83
  tracked generated skill file, the commit fails. Re-stage the skill file and
uncoded-3.0.1/PKG-INFO ADDED
@@ -0,0 +1,35 @@
1
+ Metadata-Version: 2.5
2
+ Name: uncoded
3
+ Version: 3.0.1
4
+ Summary: Symbol index with associated code reading tools for AI coding agent navigation
5
+ Project-URL: Homepage, https://github.com/alimanfoo/uncoded
6
+ Project-URL: Repository, https://github.com/alimanfoo/uncoded
7
+ Author-email: Alistair Miles <alimanfoo@googlemail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Requires-Python: >=3.12
14
+ Requires-Dist: pyyaml>=6.0
15
+ Description-Content-Type: text/markdown
16
+
17
+ # uncoded
18
+
19
+ AI coding agents navigate codebases poorly. They grep for guessed keywords, skim
20
+ the first few lines of files, and fill gaps from pretraining rather than reading
21
+ the actual code. The result is plausible-looking output built on a hallucinated
22
+ understanding of the code.
23
+
24
+ **uncoded** builds a static navigation index that gives coding agents
25
+ progressively deeper views of a codebase. Agents start with the namespace map,
26
+ read compact stubs when they need parameters and types, and retrieve only the
27
+ symbol bodies that they need. Each view adds detail without making the agent
28
+ read whole source files.
29
+
30
+ The `uncoded body` command retrieves symbol bodies, and `uncoded refs` finds
31
+ every reference to a symbol. References cover callers, dead-symbol checks, and
32
+ the full set of sites to update before a rename.
33
+
34
+ Read the [documentation](https://alimanfoo.github.io/uncoded/) for installation,
35
+ configuration, command reference, upgrades, and contributor guidance.
@@ -0,0 +1,19 @@
1
+ # uncoded
2
+
3
+ AI coding agents navigate codebases poorly. They grep for guessed keywords, skim
4
+ the first few lines of files, and fill gaps from pretraining rather than reading
5
+ the actual code. The result is plausible-looking output built on a hallucinated
6
+ understanding of the code.
7
+
8
+ **uncoded** builds a static navigation index that gives coding agents
9
+ progressively deeper views of a codebase. Agents start with the namespace map,
10
+ read compact stubs when they need parameters and types, and retrieve only the
11
+ symbol bodies that they need. Each view adds detail without making the agent
12
+ read whole source files.
13
+
14
+ The `uncoded body` command retrieves symbol bodies, and `uncoded refs` finds
15
+ every reference to a symbol. References cover callers, dead-symbol checks, and
16
+ the full set of sites to update before a rename.
17
+
18
+ Read the [documentation](https://alimanfoo.github.io/uncoded/) for installation,
19
+ configuration, command reference, upgrades, and contributor guidance.
@@ -0,0 +1,73 @@
1
+ # Agent workflow
2
+
3
+ The generated skills tell your agent when to load the index, read source, and
4
+ check references. Once you have [set up the repository](getting-started.md), the
5
+ agent follows this workflow during a coding task.
6
+
7
+ ## Start a task
8
+
9
+ The agent loads `.uncoded/namespace.yaml` in full to learn the Python symbols
10
+ that exist. For a documentation task, it loads `.uncoded/docs.yaml` to find the
11
+ relevant file and heading.
12
+
13
+ Navigation skills load once per session. Their instructions apply throughout the
14
+ session.
15
+
16
+ ## Read code
17
+
18
+ The agent adds detail only when the task needs it. This progressive disclosure
19
+ keeps broad work on compact views and limits source reads to the implementations
20
+ that matter.
21
+
22
+ 1. The namespace map shows every indexed symbol and its file. It is often enough
23
+ for questions about structure or where a feature lives.
24
+ 2. The file's stub under `.uncoded/stubs/` adds imports, parameter names and
25
+ annotations, return types, constants, and attributes. It omits parameter
26
+ defaults, decorators, docstrings, and function bodies. It is often enough for
27
+ questions about names and types.
28
+ 3. `uncoded body` returns one symbol's exact source when the task needs it:
29
+
30
+ ```sh
31
+ uvx uncoded body greet --in src/greetings.py
32
+ ```
33
+
34
+ This example assumes `greet` is defined in `src/greetings.py`. For a method, use
35
+ `ClassName/method_name`. See [the command reference](commands.md#body) for
36
+ supported symbols and paths.
37
+
38
+ A file with no indexed symbols has no stub, so the agent reads the file
39
+ directly. Free text and patterns still belong in a text search.
40
+
41
+ ## Change a symbol
42
+
43
+ Before renaming, changing a signature, or deleting a symbol, the agent checks
44
+ its references:
45
+
46
+ ```sh
47
+ uvx uncoded refs greet --in src/greetings.py
48
+ ```
49
+
50
+ The results identify the sites to inspect and update. After changing indexed
51
+ Python or Markdown files, the agent runs `uncoded sync` before navigating again.
52
+
53
+ ## Review consistency
54
+
55
+ With `source-roots` configured, uncoded also generates a consistency review
56
+ skill. It looks for concrete disagreements between names, signatures,
57
+ docstrings, and behavior. Every finding must quote both conflicting claims and
58
+ show that they describe the same concept.
59
+
60
+ Invoke it with `$uncoded-consistency-review` in Codex or
61
+ `/uncoded-consistency-review` in Claude Code.
62
+
63
+ ## Know the limits
64
+
65
+ The code index describes static Python structure. It does not run imports or
66
+ resolve runtime registration. Files that cannot be parsed or decoded are skipped
67
+ with a warning.
68
+
69
+ The documentation index records headings that begin with `#`. It excludes
70
+ underlined headings and headings inside fenced code blocks. Read documentation
71
+ sections directly; `body` and `refs` operate on Python symbols.
72
+
73
+ Keep using tests and type checks to verify changes.
@@ -0,0 +1,43 @@
1
+ # Architecture
2
+
3
+ uncoded builds static code and documentation indexes. The CLI reads the
4
+ configuration, validates roots, and coordinates extraction and file writes.
5
+
6
+ ## Sync pipeline
7
+
8
+ | Module | Responsibility |
9
+ | ------------------ | ----------------------------------------------------------------------------------------- |
10
+ | `config.py` | Finds the nearest configuration and resolves the project root. |
11
+ | `cli.py` | Validates roots and dispatches the configured work. |
12
+ | `extract.py` | Extracts symbols from parseable Python files. |
13
+ | `namespace_map.py` | Renders the Python hierarchy as YAML. |
14
+ | `stubs.py` | Extracts imports, signatures, and assignments into a mirrored `.pyi` tree. |
15
+ | `docs_map.py` | Extracts Markdown headings and renders their hierarchy as YAML. |
16
+ | `skill.py` | Writes navigation and consistency review skills to both agent directories. |
17
+ | `sync.py` | Writes and removes files only when needed; reports changes without writing in check mode. |
18
+
19
+ Code and documentation indexes are independent. Removing a root type removes its
20
+ generated index and skills on the next sync.
21
+
22
+ The skill instructions ship as Markdown package resources. `skill.py` renders
23
+ them into repository skill files. `markers.py` defines the provenance marker
24
+ shared by every generated output.
25
+
26
+ ## Symbol tools
27
+
28
+ `resolver.py` locates a named Python symbol in the abstract syntax tree and
29
+ records its source position. `body.py` uses that location to return the original
30
+ source text.
31
+
32
+ `refs.py` sends the position to a one-shot `ty` language server, then sorts and
33
+ formats the returned references. `ty` resolves the references; uncoded provides
34
+ the command and output format.
35
+
36
+ ## Path boundary
37
+
38
+ `sync` and `check` anchor all generated files at the configuration file's parent
39
+ directory. Every configured root must remain inside that directory after
40
+ resolving symbolic links.
41
+
42
+ `body` and `refs` resolve their `--in` paths from the current working directory.
43
+ They can operate without a project configuration.
@@ -0,0 +1,85 @@
1
+ # Commands
2
+
3
+ Run uncoded with `uvx uncoded`. Contributors use `uv run uncoded` to run the
4
+ code in their checkout.
5
+
6
+ | To… | Use |
7
+ | ------------------------------------- | --------------------------------------- |
8
+ | Build or refresh the index and skills | `uvx uncoded sync` |
9
+ | Check generated files without writing | `uvx uncoded check` |
10
+ | Read a Python symbol's source | `uvx uncoded body <symbol> --in <file>` |
11
+ | Find references to a Python symbol | `uvx uncoded refs <symbol> --in <file>` |
12
+
13
+ ## `sync`
14
+
15
+ ```sh
16
+ uvx uncoded sync
17
+ ```
18
+
19
+ Builds or refreshes every configured index and navigation skill. Output lists
20
+ files created, updated, or removed. Running it from a subdirectory produces
21
+ output at the same project root.
22
+
23
+ Files that cannot be parsed or decoded are skipped with a warning. Invalid
24
+ configuration or roots cause exit status `1`.
25
+
26
+ ## `check`
27
+
28
+ ```sh
29
+ uvx uncoded check
30
+ ```
31
+
32
+ Runs the same pipeline as `sync` without changing files.
33
+
34
+ | Status | Meaning |
35
+ | ------ | ------------------------------------------------------------------------------ |
36
+ | `0` | All generated files match a fresh build. |
37
+ | `1` | A file would be created, updated, or removed, or the configuration is invalid. |
38
+
39
+ Run `sync` first in a fresh checkout. The local index is not committed.
40
+
41
+ ## `body`
42
+
43
+ ```sh
44
+ uvx uncoded body greet --in src/greetings.py
45
+ uvx uncoded body Greeter/greet --in src/greetings.py
46
+ ```
47
+
48
+ Prints the named symbol's source to standard output, exactly as written in the
49
+ file. These examples assume a `greet` function or a `Greeter.greet` method in
50
+ `src/greetings.py`.
51
+
52
+ Use one name for a top-level function, class, module assignment, or Python 3.12
53
+ `type` alias. Use `Class/member` for a method or class attribute. Deeper paths
54
+ and empty segments are unsupported.
55
+
56
+ The `--in` path is relative to your current directory, not the configuration
57
+ file. No project configuration is required.
58
+
59
+ ## `refs`
60
+
61
+ ```sh
62
+ uvx uncoded refs greet --in src/greetings.py
63
+ uvx uncoded refs Greeter/greet --in src/greetings.py
64
+ ```
65
+
66
+ Finds references to the symbol. Names and `--in` paths follow the same rules as
67
+ `body`. Each result is printed as:
68
+
69
+ ```text
70
+ path:line:column
71
+ ```
72
+
73
+ Positions are one-based. Results are sorted by path and position. Paths within
74
+ the current directory are relative; other paths are absolute. Empty output with
75
+ exit status `0` means no references were found.
76
+
77
+ Reference resolution uses the pinned `ty` language server through `uvx`. The
78
+ first call may download it. `uvx` must be on `PATH`.
79
+
80
+ ## Lookup errors
81
+
82
+ `body` and `refs` exit with status `1` if the source cannot be read or parsed,
83
+ the symbol is missing, or its name path is unsupported. A reference lookup also
84
+ fails if the language server fails. Missing required arguments exit with status
85
+ `2`.
@@ -0,0 +1,57 @@
1
+ # Configuration
2
+
3
+ Use one configuration file in your repository root. Choose the directories
4
+ containing Python code and the files or directories containing Markdown docs.
5
+
6
+ ## Choose a configuration file
7
+
8
+ For a standalone configuration, use `.uncoded.toml`:
9
+
10
+ ```toml title=".uncoded.toml"
11
+ source-roots = ["src", "tests"]
12
+ doc-roots = ["README.md", "docs"]
13
+ ```
14
+
15
+ To keep the settings in `pyproject.toml`, add a section there instead:
16
+
17
+ ```toml title="pyproject.toml"
18
+ [tool.uncoded]
19
+ source-roots = ["src", "tests"]
20
+ doc-roots = ["README.md", "docs"]
21
+ ```
22
+
23
+ Both formats work in Python and non-Python repositories. At least one root list
24
+ must be non-empty. You can configure either type on its own.
25
+
26
+ ## Settings
27
+
28
+ | Setting | Accepted paths | Indexed content |
29
+ | -------------- | ------------------------------------- | ------------------------------ |
30
+ | `source-roots` | Directories | Python symbols and signatures. |
31
+ | `doc-roots` | Directories or individual `.md` files | Markdown headings. |
32
+
33
+ Every path is relative to the configuration file's directory and must exist.
34
+ Paths that resolve outside that directory are rejected, including through
35
+ symbolic links.
36
+
37
+ uncoded searches upwards from the current directory and uses the nearest
38
+ configuration. In one directory, `.uncoded.toml` takes precedence over a
39
+ `pyproject.toml` without `[tool.uncoded]`. If both files configure uncoded, the
40
+ command fails. Keep the settings in one file.
41
+
42
+ ## Generated files
43
+
44
+ | Output | When generated | Commit it? |
45
+ | --------------------------------------------- | ---------------------- | ---------- |
46
+ | `.uncoded/namespace.yaml` | `source-roots` is set. | No. |
47
+ | `.uncoded/stubs/` | `source-roots` is set. | No. |
48
+ | `.uncoded/docs.yaml` | `doc-roots` is set. | No. |
49
+ | Code navigation and consistency review skills | `source-roots` is set. | Yes. |
50
+ | Documentation navigation skill | `doc-roots` is set. | Yes. |
51
+
52
+ The index's generated `.gitignore` keeps `.uncoded/` out of Git. Skills are
53
+ written to both `.agents/skills/` and `.claude/skills/`.
54
+
55
+ When you remove a root type and run `sync`, uncoded removes that type's index
56
+ and skills. Every generated file has a provenance marker. Change generated files
57
+ by running `sync`, rather than editing them by hand.
@@ -0,0 +1,73 @@
1
+ # Contributing
2
+
3
+ Use Python 3.12 or later and [uv](https://docs.astral.sh/uv/).
4
+
5
+ ## Set up a checkout
6
+
7
+ ```sh
8
+ git clone https://github.com/alimanfoo/uncoded
9
+ cd uncoded
10
+ uv sync
11
+ uv run uncoded sync
12
+ uv run pre-commit install
13
+ ```
14
+
15
+ The development dependency group includes tests, linting, type checking,
16
+ documentation, and pre-commit tools. The local index is ignored by Git, so build
17
+ it before navigating the checkout.
18
+
19
+ On Windows, enable symbolic links before cloning:
20
+
21
+ ```sh
22
+ git config --global core.symlinks true
23
+ ```
24
+
25
+ This lets Git check out `CLAUDE.md` as the symbolic link to `AGENTS.md`.
26
+
27
+ ## Run the tests
28
+
29
+ ```sh
30
+ uv run python -X warn_default_encoding -m pytest -q --tb=short
31
+ ```
32
+
33
+ The suite requires complete branch coverage. The Python option enables
34
+ `EncodingWarning`, which the test configuration turns into an error.
35
+
36
+ For a focused run without the repository-wide coverage gate:
37
+
38
+ ```sh
39
+ uv run python -X warn_default_encoding -m pytest -q --tb=short tests/test_stubs.py --no-cov
40
+ ```
41
+
42
+ ## Run the checks
43
+
44
+ ```sh
45
+ uv run pre-commit run --all-files
46
+ ```
47
+
48
+ The suite runs formatters, linters, type and complexity checks, the strict
49
+ documentation build, and `uncoded sync`. If a hook changes files, stage the
50
+ changes and run the suite again. Never commit with `--no-verify`.
51
+
52
+ ## Edit the docs
53
+
54
+ ```sh
55
+ uv run mkdocs serve
56
+ ```
57
+
58
+ Preview the site at `http://127.0.0.1:8000/`. Run `uv run mkdocs build` to check
59
+ links, anchors, and navigation. The strict build treats warnings as errors.
60
+
61
+ ## Change indexed content
62
+
63
+ After editing Python code or indexed Markdown, run `uv run uncoded sync` before
64
+ navigating again. Commit any changed generated skill files with the sources that
65
+ produced them. Read
66
+ [AGENTS.md](https://github.com/alimanfoo/uncoded/blob/main/AGENTS.md) for the
67
+ code and testing conventions.
68
+
69
+ ## Release
70
+
71
+ Publish a GitHub release from its version tag. `.github/workflows/publish.yml`
72
+ builds the source distribution and wheel and uploads them with PyPI Trusted
73
+ Publishing. The repository does not store a PyPI token.
@@ -0,0 +1,83 @@
1
+ # Get started
2
+
3
+ Set up uncoded in your repository, then ask your agent to use the index. You
4
+ need [uv](https://docs.astral.sh/uv/getting-started/installation/). `uvx` runs
5
+ uncoded on demand; there is no separate install step.
6
+
7
+ <span id="install-uv"></span> <span id="choose-a-configuration-file"></span>
8
+
9
+ ## 1. Choose what to index
10
+
11
+ Create `.uncoded.toml` in your repository root:
12
+
13
+ ```toml title=".uncoded.toml"
14
+ source-roots = ["src", "tests"]
15
+ doc-roots = ["README.md", "docs"]
16
+ ```
17
+
18
+ Replace these paths with directories and files that exist in your repository.
19
+ `source-roots` indexes Python files. `doc-roots` indexes Markdown headings.
20
+ Remove either line if you only need the other index.
21
+
22
+ <span id="build-the-index"></span>
23
+
24
+ ## 2. Build the index
25
+
26
+ Run from your repository root:
27
+
28
+ ```sh
29
+ uvx uncoded sync
30
+ ```
31
+
32
+ The command prints the files it creates. With both root types configured, you
33
+ will find:
34
+
35
+ | Output | Purpose |
36
+ | --------------------------------------- | ------------------------------------------------------- |
37
+ | `.uncoded/namespace.yaml` | Lists Python symbols and their locations. |
38
+ | `.uncoded/stubs/` | Records imports, signatures, constants, and attributes. |
39
+ | `.uncoded/docs.yaml` | Lists Markdown files and headings. |
40
+ | `.agents/skills/` and `.claude/skills/` | Give agents the navigation instructions. |
41
+
42
+ Commit the generated skill files. The `.uncoded/` index stays local and is
43
+ ignored by Git.
44
+
45
+ <span id="tell-agents-to-use-the-skills"></span>
46
+
47
+ ## 3. Tell your agent to use it
48
+
49
+ Add these instructions to your repository's `AGENTS.md` or `CLAUDE.md`:
50
+
51
+ ```text title="Agent instructions"
52
+ ## Before you start
53
+
54
+ - Load the `uncoded-code-navigation` skill once per session, before searching, reading or editing any code.
55
+ - Load the `uncoded-doc-navigation` skill once per session, before searching, reading or editing any docs.
56
+ ```
57
+
58
+ Keep only the lines for the root types you configured.
59
+
60
+ ## 4. Try a task
61
+
62
+ Start a new agent session in the repository and ask:
63
+
64
+ ```text title="Example prompt"
65
+ Explain this repository using the uncoded navigation skills.
66
+ Read the index first, then show me one function or documentation section
67
+ that explains how the project works.
68
+ ```
69
+
70
+ For Python code, the agent should move from `.uncoded/namespace.yaml` to a
71
+ matching stub and then to `uncoded body` as it needs more detail. The agent can
72
+ stop after the map or stub when that view answers the question. For
73
+ documentation, it should load `.uncoded/docs.yaml` and read the relevant
74
+ section.
75
+
76
+ <span id="keep-the-index-current"></span>
77
+
78
+ When you change indexed code or docs, run `uvx uncoded sync` again before
79
+ navigating. [Keep the index current](keeping-current.md) explains how to
80
+ automate this with pre-commit.
81
+
82
+ See [Configuration](configuration.md) to use `pyproject.toml` or change the
83
+ indexed paths.