doctracker 0.1.0__py3-none-any.whl

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 (38) hide show
  1. doctracker/__init__.py +5 -0
  2. doctracker/__main__.py +4 -0
  3. doctracker/cli.py +55 -0
  4. doctracker/config.py +65 -0
  5. doctracker/extraction/__init__.py +5 -0
  6. doctracker/extraction/griffe_loader.py +148 -0
  7. doctracker/server/__init__.py +1 -0
  8. doctracker/server/app.py +78 -0
  9. doctracker/server/guide.md +62 -0
  10. doctracker/server/guide.py +68 -0
  11. doctracker/server/state.py +32 -0
  12. doctracker/server/tools.py +76 -0
  13. doctracker/server/watcher.py +63 -0
  14. doctracker/server/web.py +120 -0
  15. doctracker/wiki/__init__.py +1 -0
  16. doctracker/wiki/pages.py +356 -0
  17. doctracker/wiki/static/htmx-LICENSE.txt +13 -0
  18. doctracker/wiki/static/htmx.min.js +1 -0
  19. doctracker/wiki/static/live.js +178 -0
  20. doctracker/wiki/static/style.css +424 -0
  21. doctracker/wiki/templates/base.html +33 -0
  22. doctracker/wiki/templates/entity.html +97 -0
  23. doctracker/wiki/templates/fragment.html +3 -0
  24. doctracker/wiki/templates/fragment_content.html +5 -0
  25. doctracker/wiki/templates/header.html +20 -0
  26. doctracker/wiki/templates/loading.html +2 -0
  27. doctracker/wiki/templates/members.html +18 -0
  28. doctracker/wiki/templates/module.html +19 -0
  29. doctracker/wiki/templates/not_found.html +6 -0
  30. doctracker/wiki/templates/search.html +21 -0
  31. doctracker/wiki/templates/source.html +1 -0
  32. doctracker/wiki/templates/tree.html +31 -0
  33. doctracker-0.1.0.dist-info/METADATA +234 -0
  34. doctracker-0.1.0.dist-info/RECORD +38 -0
  35. doctracker-0.1.0.dist-info/WHEEL +4 -0
  36. doctracker-0.1.0.dist-info/entry_points.txt +3 -0
  37. doctracker-0.1.0.dist-info/licenses/LICENSE +21 -0
  38. doctracker-0.1.0.dist-info/licenses/src/doctracker/wiki/static/htmx-LICENSE.txt +13 -0
@@ -0,0 +1,97 @@
1
+ {% include "header.html" %}
2
+ {% set role = page_role(state, entity) | replace(' ', '-') %}
3
+
4
+ <details class="block divider block-description" data-section="description" open>
5
+ <summary class="badge badge-description">Description</summary>
6
+ {% set texts = other_sections(entity) | selectattr("kind", "equalto", "text") | list %}
7
+ {% if texts %}
8
+ <div class="docstring">{% for section in texts %}{{ section.text | markdown | safe }}{% endfor %}</div>
9
+ {% else %}
10
+ <p class="empty">No docstring.</p>
11
+ {% endif %}
12
+ </details>
13
+
14
+ <details class="block divider block-{{ role }}" data-section="signature" open>
15
+ <summary class="badge badge-{{ role }}">Signature</summary>
16
+ {% if entity.decorators %}
17
+ <p class="chips decorators">{% for decorator in entity.decorators %}<code class="chip">@{{ decorator }}</code>{% endfor %}</p>
18
+ {% endif %}
19
+ <pre class="signature code-block"><code>{{ signature(entity) | highlight }}</code></pre>
20
+ {% if entity.kind == "class" and entity.bases %}
21
+ <p class="bases">Bases: {% for base in entity.bases %}<code class="chip">{{ base }}</code>{% endfor %}</p>
22
+ {% endif %}
23
+ </details>
24
+
25
+ {% set rows = parameter_rows(entity) %}
26
+ {% if rows %}
27
+ <details class="block divider block-{{ role }}" data-section="parameters" open>
28
+ <summary class="badge badge-{{ role }}">Parameters <span class="count">{{ rows | length }}</span></summary>
29
+ <table>
30
+ <thead><tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
31
+ <tbody>
32
+ {% for row in rows %}
33
+ <tr>
34
+ <td><code class="param-name">{{ row.name }}</code></td>
35
+ <td>{% if row.annotation %}<code>{{ row.annotation }}</code>{% else %}<span class="empty">-</span>{% endif %}</td>
36
+ <td>{% if row.default %}<code>{{ row.default }}</code>{% else %}<span class="empty">-</span>{% endif %}</td>
37
+ <td>{% if row.description %}{{ row.description | markdown | safe }}{% else %}<span class="empty">-</span>{% endif %}</td>
38
+ </tr>
39
+ {% endfor %}
40
+ </tbody>
41
+ </table>
42
+ </details>
43
+ {% endif %}
44
+
45
+ {% set documented = other_sections(entity) | rejectattr("kind", "equalto", "text") | list %}
46
+ {% if entity.kind == "function" and entity.returns and not documented | selectattr("kind", "equalto", "returns") | list %}
47
+ <details class="block divider block-returns" data-section="returns" open>
48
+ <summary class="badge badge-returns">Returns</summary>
49
+ <p><code>{{ entity.returns }}</code></p>
50
+ </details>
51
+ {% endif %}
52
+
53
+ {% for section in documented %}
54
+ {% set kind = section.kind | replace(' ', '-') %}
55
+ <details class="block divider block-{{ kind }}" data-section="{{ kind }}" open>
56
+ <summary class="badge badge-{{ kind }}">{{ section.title or section.kind }}{% if section["items"] | length > 1 %} <span class="count">{{ section["items"] | length }}</span>{% endif %}</summary>
57
+ {% if section.text %}{{ section.text | markdown | safe }}{% endif %}
58
+ {% if section["items"] %}
59
+ <ul class="items">
60
+ {% for item in section["items"] %}
61
+ <li>
62
+ {% if item.is_code %}
63
+ <pre class="code-block"><code>{{ item.description | highlight }}</code></pre>
64
+ {% else %}
65
+ {% if item.name or item.annotation %}
66
+ <code class="item-head">
67
+ {%- if item.name %}<span class="param-name">{{ item.name }}</span>{% endif %}
68
+ {%- if item.name and item.annotation %}<span class="type">: {{ item.annotation }}</span>
69
+ {%- elif item.annotation %}<span class="param-name">{{ item.annotation }}</span>{% endif %}
70
+ </code>
71
+ {% endif %}
72
+ {{ item.description | markdown | safe }}
73
+ {% endif %}
74
+ </li>
75
+ {% endfor %}
76
+ </ul>
77
+ {% endif %}
78
+ </details>
79
+ {% endfor %}
80
+
81
+ {% if entity.kind == "class" %}
82
+ {% with divider = true %}{% include "members.html" %}{% endwith %}
83
+ {% endif %}
84
+
85
+ {# Open by default; the code is fetched right after the page is shown, so the page itself stays light. #}
86
+ <details class="block divider block-source" data-section="source" open
87
+ hx-get="/source/{{ entity.path }}" hx-trigger="load" hx-target="find .code">
88
+ <summary class="badge badge-source">Source</summary>
89
+ {# Changing the theme saves it to doc/config/config.json. #}
90
+ <label class="theme-picker">Code theme
91
+ <select class="code-theme-select" name="code_theme"
92
+ hx-post="/settings/code-theme" hx-trigger="change" hx-swap="none">
93
+ {% for name in code_themes %}<option value="{{ name }}"{% if name == code_theme %} selected{% endif %}>{{ name }}</option>{% endfor %}
94
+ </select>
95
+ </label>
96
+ <div class="code"><p class="empty">Loading…</p></div>
97
+ </details>
@@ -0,0 +1,3 @@
1
+ {# htmx response: new content panel plus the tree, swapped out of band. #}
2
+ {% include "fragment_content.html" %}
3
+ {% with oob = true %}{% include "tree.html" %}{% endwith %}
@@ -0,0 +1,5 @@
1
+ {# Reloads itself when the server reports a change in the code.
2
+ hx-disinherit keeps links inside the page from inheriting this element's hx-swap. #}
3
+ <article hx-get="/wiki/{{ path }}" hx-trigger="docs-changed from:body" hx-swap="outerHTML" hx-disinherit="*">
4
+ {% include content %}
5
+ </article>
@@ -0,0 +1,20 @@
1
+ {% set role = page_role(state, entity) %}
2
+ <header class="page-header">
3
+ <p class="crumbs">
4
+ {% for crumb in breadcrumbs %}
5
+ <a href="/wiki/{{ crumb.path }}" hx-get="/wiki/{{ crumb.path }}" hx-target="#content" hx-push-url="true">{{ crumb.name }}</a>
6
+ <span class="sep">›</span>
7
+ {% endfor %}
8
+ </p>
9
+ <h1>
10
+ <span class="icon icon-{{ role | replace(' ', '-') }}">{{ symbols.get(role, "") }}</span>
11
+ <span class="name role-{{ role | replace(' ', '-') }}">{{ entity.name }}</span>
12
+ <span class="kind">{{ role }}</span>
13
+ </h1>
14
+ <p class="meta">
15
+ <code class="path">{{ entity.path }}</code>
16
+ {% if entity.filepath %}
17
+ <span class="location">{{ entity.filepath }}{% if entity.lineno and entity.kind != "module" %}:{{ entity.lineno }}–{{ entity.endlineno }}{% endif %}</span>
18
+ {% endif %}
19
+ </p>
20
+ </header>
@@ -0,0 +1,2 @@
1
+ <h1>Building the documentation…</h1>
2
+ <p>This page updates by itself when the first reading of the code finishes.</p>
@@ -0,0 +1,18 @@
1
+ {% for group in members_by_group(state, entity) %}
2
+ <details class="block{% if divider %} divider{% endif %} block-{{ group.role | replace(' ', '-') }}" data-section="{{ group.label | lower }}" open>
3
+ <summary class="badge badge-{{ group.role | replace(' ', '-') }}">{{ group.label }} <span class="count">{{ group["items"] | length }}</span></summary>
4
+ <ul class="members">
5
+ {% for item in group["items"] %}
6
+ <li>
7
+ <a class="member" href="/wiki/{{ item.path }}" hx-get="/wiki/{{ item.path }}" hx-target="#content" hx-push-url="true">
8
+ <span class="icon icon-{{ item.role | replace(' ', '-') }}">{{ item.symbol }}</span>
9
+ <span class="member-body">
10
+ <code class="member-signature"><span class="name role-{{ item.role | replace(' ', '-') }}">{{ item.name }}</span><span class="details">{{ item.details }}</span></code>
11
+ {% if item.summary %}<span class="summary">{{ item.summary }}</span>{% endif %}
12
+ </span>
13
+ </a>
14
+ </li>
15
+ {% endfor %}
16
+ </ul>
17
+ </details>
18
+ {% endfor %}
@@ -0,0 +1,19 @@
1
+ {% include "header.html" %}
2
+
3
+ <details class="block block-description" data-section="description" open>
4
+ <summary class="badge badge-description">Description</summary>
5
+ {% if entity.docstring %}
6
+ <div class="docstring">{{ entity.docstring | markdown | safe }}</div>
7
+ {% else %}
8
+ <p class="empty">No docstring.</p>
9
+ {% endif %}
10
+ </details>
11
+
12
+ {% if entity.exports %}
13
+ <details class="block block-exports" data-section="exports" open>
14
+ <summary class="badge badge-exports">Public API <code>__all__</code></summary>
15
+ <p class="chips">{% for name in entity.exports %}<code class="chip">{{ name }}</code>{% endfor %}</p>
16
+ </details>
17
+ {% endif %}
18
+
19
+ {% include "members.html" %}
@@ -0,0 +1,6 @@
1
+ <h1>Not found</h1>
2
+ <p>No documented entity is called <code>{{ path }}</code>.</p>
3
+ {% if state.errors %}
4
+ <h2>Loading errors</h2>
5
+ <ul>{% for error in state.errors %}<li><code>{{ error }}</code></li>{% endfor %}</ul>
6
+ {% endif %}
@@ -0,0 +1,21 @@
1
+ {% if query.strip() %}
2
+ <ul class="search-options" role="listbox">
3
+ {% for item in results %}
4
+ <li role="option" aria-selected="false">
5
+ <a class="search-link" href="/wiki/{{ item.path }}" hx-get="/wiki/{{ item.path }}" hx-target="#content" hx-push-url="true">
6
+ <span class="icon icon-{{ item.role | replace(' ', '-') }}">{{ item.symbol }}</span>
7
+ <span class="search-text">
8
+ <span class="search-name">{{ item.before }}<mark>{{ item.match }}</mark>{{ item.after }}</span>
9
+ <span class="search-path">{{ item.path }}</span>
10
+ {% if item.snippet %}
11
+ <span class="search-snippet">{{ item.snippet.before }}<mark>{{ item.snippet.match }}</mark>{{ item.snippet.after }}</span>
12
+ {% endif %}
13
+ </span>
14
+ <span class="search-kind">{{ item.role }}</span>
15
+ </a>
16
+ </li>
17
+ {% else %}
18
+ <li class="search-empty">No results</li>
19
+ {% endfor %}
20
+ </ul>
21
+ {% endif %}
@@ -0,0 +1 @@
1
+ <pre class="code-block"><code>{{ code | highlight }}</code></pre>
@@ -0,0 +1,31 @@
1
+ {# The icon comes before the link: on branches it opens/closes the branch, the name navigates.
2
+ Packages show a folder, modules (files) a file, other entities their kind symbol. #}
3
+ {% macro icon(item) %}
4
+ <span class="icon icon-{{ item.role }}">{{ item.symbol }}</span>
5
+ {% endmacro %}
6
+ {% macro link(item) %}
7
+ <a href="/wiki/{{ item.path }}" hx-get="/wiki/{{ item.path }}" hx-target="#content" hx-push-url="true"
8
+ class="role-{{ item.role }}{% if item.current %} current{% endif %}" {% if item.current %}aria-current="page"{% endif %}>
9
+ {{- item.name -}}
10
+ </a>
11
+ {% endmacro %}
12
+ {% macro node(item) %}
13
+ <li>
14
+ {% if item.children %}
15
+ {# Packages and modules start open; classes open only on the path to the current page. #}
16
+ <details data-path="{{ item.path }}" {% if item.open or item.role != "class" %}open{% endif %}>
17
+ <summary>{{ icon(item) }}{{ link(item) }}</summary>
18
+ <ul>
19
+ {% for child in item.children %}{{ node(child) }}{% endfor %}
20
+ </ul>
21
+ </details>
22
+ {% else %}
23
+ <div class="leaf">{{ icon(item) }}{{ link(item) }}</div>
24
+ {% endif %}
25
+ </li>
26
+ {% endmacro %}
27
+ <nav id="tree" {% if oob %}hx-swap-oob="true"{% endif %}>
28
+ <ul>
29
+ {% for item in tree %}{{ node(item) }}{% endfor %}
30
+ </ul>
31
+ </nav>
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: doctracker
3
+ Version: 0.1.0
4
+ Summary: MCP server that centralizes the documentation of Python projects developed with LLM agents.
5
+ Author: Carlos Filipe de Castro Lemos
6
+ Author-email: Carlos Filipe de Castro Lemos <carlos.lemos.dev@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ License-File: src/doctracker/wiki/static/htmx-LICENSE.txt
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Topic :: Software Development :: Documentation
19
+ Requires-Dist: click>=8.5.0
20
+ Requires-Dist: griffe>=2.4.1
21
+ Requires-Dist: jinja2>=3.1.6
22
+ Requires-Dist: markdown-it-py>=4.2.0
23
+ Requires-Dist: mcp>=2.3.0,<3
24
+ Requires-Dist: pygments>=2.21.0
25
+ Requires-Dist: starlette>=1.10.0
26
+ Requires-Dist: uvicorn>=0.54.0
27
+ Requires-Python: >=3.11
28
+ Project-URL: Homepage, https://github.com/cfclemos/doctracker
29
+ Project-URL: Repository, https://github.com/cfclemos/doctracker
30
+ Project-URL: Issues, https://github.com/cfclemos/doctracker/issues
31
+ Description-Content-Type: text/markdown
32
+
33
+ # DOCUMENTATION TRACKER (DOCTRACKER)
34
+
35
+ **One place for the documentation of a Python project developed with LLM agents.**
36
+
37
+ When agents work on a codebase, documentation ends up scattered: notes in many
38
+ Markdown files, memories, code comments and commit messages, all drifting out of
39
+ sync. Documentation Tracker (doctracker) centralizes it. It runs an [MCP](https://modelcontextprotocol.io)
40
+ server that any agent (Claude Code, OpenCode, …) can connect to, and serves a live
41
+ wiki of the project in your browser.
42
+
43
+ > **Status: alpha (0.1).** This first version builds the technical reference of the
44
+ > code. Notes, commit history and LLM summaries come in the next versions (see
45
+ > [Roadmap](#roadmap)).
46
+
47
+ ## Features
48
+
49
+ - **Technical reference built from the code** — modules, classes, functions,
50
+ methods and attributes, with signatures, type hints, decorators and parsed
51
+ docstrings (Google, NumPy or Sphinx style).
52
+ - **Static analysis only** — the code is read with [griffe](https://mkdocstrings.github.io/griffe/),
53
+ never imported or executed.
54
+ - **Live wiki** — edit a file and the open page updates by itself.
55
+ - **MCP server** — agents can list and read the documentation, and get a guide on
56
+ how to document the code so the wiki stays complete.
57
+ - **Search** — by name, path and description, with keyboard navigation.
58
+ - **Everything in one folder** — doctracker keeps its files in `doc/` inside your
59
+ project and never touches anything else.
60
+ - **Cross-platform** — Windows and Linux, Python 3.11+.
61
+
62
+ ## Installation
63
+
64
+ Install it as a development dependency of the project you want to document:
65
+
66
+ ```bash
67
+ uv add --dev doctracker
68
+ ```
69
+
70
+ or with pip:
71
+
72
+ ```bash
73
+ pip install doctracker
74
+ ```
75
+
76
+ ## Quick start
77
+
78
+ From the root of your project:
79
+
80
+ ```bash
81
+ doctracker init # creates doc/config/config.json (packages are detected automatically)
82
+ doctracker start # starts the server
83
+ ```
84
+
85
+ With uv, prefix the commands with `uv run` (e.g. `uv run doctracker start`).
86
+ `start` runs `init` on its own if the project has no configuration yet.
87
+
88
+ The server prints its two addresses:
89
+
90
+ ```text
91
+ Wiki: http://127.0.0.1:8765/
92
+ MCP: http://127.0.0.1:8765/mcp
93
+ ```
94
+
95
+ Open the wiki in your browser. Keep the server running while you work on the code;
96
+ stop it with `Ctrl+C`.
97
+
98
+ ## Connecting an agent
99
+
100
+ The MCP server uses the Streamable HTTP transport at `http://127.0.0.1:8765/mcp`.
101
+ The server must be running before the agent connects.
102
+
103
+ **Claude Code** — add a `.mcp.json` file at the root of your project:
104
+
105
+ ```json
106
+ {
107
+ "mcpServers": {
108
+ "doctracker": { "type": "http", "url": "http://127.0.0.1:8765/mcp" }
109
+ }
110
+ }
111
+ ```
112
+
113
+ or register it from the terminal:
114
+
115
+ ```bash
116
+ claude mcp add --transport http doctracker http://127.0.0.1:8765/mcp
117
+ ```
118
+
119
+ **OpenCode** — in `opencode.json`:
120
+
121
+ ```json
122
+ {
123
+ "mcp": {
124
+ "doctracker": { "type": "remote", "url": "http://127.0.0.1:8765/mcp" }
125
+ }
126
+ }
127
+ ```
128
+
129
+ **Other agents** — any MCP client that supports Streamable HTTP can connect to the
130
+ same URL.
131
+
132
+ ### What the agent gets
133
+
134
+ | Name | Kind | What it does |
135
+ | --- | --- | --- |
136
+ | `list_entities` | tool | Lists documented entities, filtered by path prefix and kind. |
137
+ | `get_entity` | tool | Full technical reference of one entity. |
138
+ | `status` | tool | Whether the documentation is built, and loading errors. |
139
+ | `documentation_guide` | tool | How to document this project's code (adapted to its settings). |
140
+ | `doctracker://guide` | resource | The same guide, as a Markdown resource. |
141
+
142
+ The server's instructions tell the agent to read the guide before writing or
143
+ changing docstrings.
144
+
145
+ ## The wiki
146
+
147
+ - **Tree** — packages (📦/📁), modules (📄), classes (**C**), functions (**f**) and
148
+ methods (**m**). Branches collapse; the tree can be resized or hidden (☰).
149
+ - **Module pages** — description, public API (`__all__`) and members grouped by kind.
150
+ - **Entity pages** — description, signature, parameters table, returns, raises,
151
+ examples, notes, members (for classes) and the source code with syntax
152
+ highlighting. Every section can be collapsed from its badge.
153
+ - **Code theme** — choose among the Pygments themes in the Source section; the
154
+ choice is saved in `config.json`.
155
+ - **Search** — press `/` anywhere, type, use ↑/↓ and Enter.
156
+
157
+ ## Configuration
158
+
159
+ `doc/config/config.json` (created by `doctracker init`):
160
+
161
+ | Key | Default | Description |
162
+ | --- | --- | --- |
163
+ | `packages` | detected | Top-level packages to document. |
164
+ | `search_paths` | `["src", "."]` | Folders where the packages are found, relative to the project root. |
165
+ | `host` | `"127.0.0.1"` | Address the server listens on. |
166
+ | `port` | `8765` | Port of the server (also `doctracker start --port`). |
167
+ | `docstring_style` | `"google"` | `google`, `numpy` or `sphinx`. |
168
+ | `show_private` | `true` | Show `_private` members. |
169
+ | `code_theme` | `"default"` | Pygments theme of the source code. |
170
+ | `ssl_certfile` / `ssl_keyfile` | `null` | Certificate and key files; when both are set, the server uses HTTPS. |
171
+ | `watch_interval` | `1.0` | Seconds between checks for changed files. |
172
+
173
+ ### The `doc/` folder
174
+
175
+ ```text
176
+ doc/
177
+ ├── .gitignore # keeps local data out of git
178
+ └── config/
179
+ └── config.json # commit this file
180
+ ```
181
+
182
+ Other folders (local data, models) are created only when a feature needs them, and
183
+ are ignored by `doc/.gitignore`.
184
+
185
+ ## Documenting your code
186
+
187
+ doctracker shows what the code says, so the wiki is as good as the docstrings. In
188
+ short:
189
+
190
+ - a docstring for every module, public class, function and method;
191
+ - the first line is a one-sentence summary (it is used in lists and search);
192
+ - type hints on every parameter and return value;
193
+ - `Args`, `Returns`, `Raises`, `Attributes` and `Examples` sections as needed;
194
+ - constants documented with a string on the line after the assignment.
195
+
196
+ ```python
197
+ def get_weather(city: str, units: str = "metric") -> Forecast:
198
+ """Fetch the forecast for a city.
199
+
200
+ Args:
201
+ city: City name, e.g. `Lisbon`.
202
+ units: `metric` or `imperial`.
203
+
204
+ Returns:
205
+ Forecast data for the city.
206
+
207
+ Raises:
208
+ CityNotFound: When the city is unknown.
209
+ """
210
+ ```
211
+
212
+ Agents get the complete guide from the `documentation_guide` tool.
213
+
214
+ ## Security
215
+
216
+ - By default the server listens only on `127.0.0.1`, and the MCP endpoint
217
+ validates the `Host` and `Origin` headers (protection against DNS rebinding).
218
+ - The wiki only accepts changes (such as the code theme) from its own pages.
219
+ - Exposing the server on a network is not supported yet: there is no
220
+ authentication in this version.
221
+
222
+ ## Roadmap
223
+
224
+ - Notes recorded by the agent through the MCP server, turned into atomic commits.
225
+ - Commit history linked to each function and class, with LLM summaries
226
+ (llama.cpp or vLLM).
227
+ - Knowledge graph of the code: callers, callees, dead code.
228
+ - Semantic search.
229
+ - Editing the documentation from the wiki.
230
+
231
+ ## License
232
+
233
+ [MIT](LICENSE). The bundled [htmx](https://htmx.org) is distributed under the
234
+ Zero-Clause BSD license (`src/doctracker/wiki/static/htmx-LICENSE.txt`).
@@ -0,0 +1,38 @@
1
+ doctracker/__init__.py,sha256=OPHbolX0pWdelvIIY955T7zRPyOfB0BUYsx-B0Pt-p0,168
2
+ doctracker/__main__.py,sha256=X2wMUJYRd25PjHhdVo7VesexL5SdCQu8K0p2qPsRWnc,71
3
+ doctracker/cli.py,sha256=yatqx4J73OOdWcCqScJtmF8h7hLgbbAUDWQ4LSjcoy8,2115
4
+ doctracker/config.py,sha256=aUCAocPHfaQK8JWwDmP8B5e435bNjzwpXL_nqwzVe5s,2459
5
+ doctracker/extraction/__init__.py,sha256=ZJr6nwoYDrR3tlM_1Qb2_H-0k6ado2AUINVt2ysdg3Y,156
6
+ doctracker/extraction/griffe_loader.py,sha256=_Ev-n-V44AP2yCthVKCdeKBRQB4KQOWlhFRLZg3lkSk,5876
7
+ doctracker/server/__init__.py,sha256=XhKWcquD0benxpMuuBt4rwK2XG1lVKz8jysxI65mdeo,67
8
+ doctracker/server/app.py,sha256=HpedKlRwFxXNVWwBL6DZdCgI4Rz7Dh_T4gZdHanByOI,2778
9
+ doctracker/server/guide.md,sha256=YzoDKvs145a18MXY-untYNzSIzoYu_2Yn3aAyyxEiM0,2622
10
+ doctracker/server/guide.py,sha256=UvKj9Z-eex2aa6ltT5urhS7cK-qV9fxRFQAd-mYCBhc,1810
11
+ doctracker/server/state.py,sha256=dpC8Yem-B5MHAvkOWyXfQzJ99IwoFi_RA6-h6P3wV1Y,1088
12
+ doctracker/server/tools.py,sha256=LbZDcTvKvDVX0_6wvj8XL0_XcisqXLsfzIoMOTgB8HA,2854
13
+ doctracker/server/watcher.py,sha256=Yw4Nd-mqwmw_4nO7SYIv0hcgWlwSZaOt-tg9QdvwUyg,2292
14
+ doctracker/server/web.py,sha256=2SApeHwbpN-zdf0ZCuNxLE_A2qRmd6Pg4hNp5mUN6Sg,5289
15
+ doctracker/wiki/__init__.py,sha256=0buyZNaGj4oACwT_SWXCnsalTE8OCPjHlwQPKXus6So,48
16
+ doctracker/wiki/pages.py,sha256=rIwOgsV1x4cOb0epa9ZSs41aZsC2ihNKNmi5wAk1BKI,13592
17
+ doctracker/wiki/static/htmx-LICENSE.txt,sha256=09JFb3ZBTyRWEEZg69Za_xwEzXlmuUK9q9Y_PNsxajg,642
18
+ doctracker/wiki/static/htmx.min.js,sha256=1v3HXyBOa976mbab8ebUrGm4o2T3eSn0XBNHa0AA9xc,52182
19
+ doctracker/wiki/static/live.js,sha256=bdqNCfyBRoqnUZgTk6f-DeRT4s3TvqNUWAFmi_Qc28M,6141
20
+ doctracker/wiki/static/style.css,sha256=TBz9o36vMqrVl1Kp_6pXEgODVTslh-svaY9jMEftOMk,16029
21
+ doctracker/wiki/templates/base.html,sha256=ixIRxNIcEUUu3VediP5u9ocM9X6smDQFe6UUGRzwrvI,1463
22
+ doctracker/wiki/templates/entity.html,sha256=gVTBXMY1jr82LwanZU5tsMdDC9glzbp1DDDYo94sc1E,4528
23
+ doctracker/wiki/templates/fragment.html,sha256=cWMUrPQdRHvpgYe_DQLecu3JqvJ47sjueFMqGzKNujk,173
24
+ doctracker/wiki/templates/fragment_content.html,sha256=rerxgekXdfq36g4D7ZFme0Qk9p-bw4kknwZgd9UljWE,297
25
+ doctracker/wiki/templates/header.html,sha256=8a1ER8hdWx8ODw_EbsTGiuPiwxlJLXCnAjWTZzslpCw,839
26
+ doctracker/wiki/templates/loading.html,sha256=nBiMvmX392O8tclG3wi6-SmufhGFd4QWmBEQkAo3taU,119
27
+ doctracker/wiki/templates/members.html,sha256=kppY02QYP2ozCnWyyeCGSPtpM1UBK3v3Ko-GyfgpzpE,1028
28
+ doctracker/wiki/templates/module.html,sha256=JVmREILC4bfz3MDhYvKQbStwNWhzqHDxMNLEcdPeZR4,672
29
+ doctracker/wiki/templates/not_found.html,sha256=6GTjW1Eyj87SKJ4RFfylDKw6Jxz4vfWmV30tCH3hjWs,226
30
+ doctracker/wiki/templates/search.html,sha256=OIEvlbzvONPHphrQeOgMREaWXfi6EDZtusmrfJ2wURM,906
31
+ doctracker/wiki/templates/source.html,sha256=-fFyb5gbUzk4bqGlVFdpEqVk9-KJnjtwuZMCrfbYj2w,66
32
+ doctracker/wiki/templates/tree.html,sha256=LDmst4sprNRojUiQBOwKqUX6HQHwa0TkDNhxcmrdOnA,1218
33
+ doctracker-0.1.0.dist-info/licenses/LICENSE,sha256=EPwZHQ2im2N4aU6nrT6NuQ_I4X4JnkFYu80yqiAILhI,1086
34
+ doctracker-0.1.0.dist-info/licenses/src/doctracker/wiki/static/htmx-LICENSE.txt,sha256=09JFb3ZBTyRWEEZg69Za_xwEzXlmuUK9q9Y_PNsxajg,642
35
+ doctracker-0.1.0.dist-info/WHEEL,sha256=9IUYslYuG_asT4WlWvfk_K76nveuLvSTKDoLeL0cV-Q,80
36
+ doctracker-0.1.0.dist-info/entry_points.txt,sha256=zg9ymdE9eqS9HdygNKpTg-uXu03AvfUUMs5atlp3lx4,52
37
+ doctracker-0.1.0.dist-info/METADATA,sha256=lhXtfz8ElyCUgCjSLFzUfx-j1_P6cTdXONEQjRJatlQ,8319
38
+ doctracker-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.13.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ doctracker = doctracker.cli:main
3
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Carlos Filipe de Castro Lemos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ Zero-Clause BSD
2
+ =============
3
+
4
+ Permission to use, copy, modify, and/or distribute this software for
5
+ any purpose with or without fee is hereby granted.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL
8
+ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
9
+ OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
10
+ FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
11
+ DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
12
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13
+ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.