A tool that links documentation to code so it stays up to date. When function signatures, APIs, or arguments change, the system marks related documentation paragraphs as "possibly outdated" and suggests what to fix.
- Code β doc linking: explicit mapping between code entities (functions, classes, APIs) and documentation fragments
- Freshness checking: after code changes β mark outdated sections and suggest updates
- Contextual view (planned): show the relevant doc fragment in the IDE when hovering over a function or method call
- Docs next to code: store documentation in the repository and view it as a site with navigation and search
Recommended order:
- Code β documentation mapping format β without it, you can't unambiguously link a doc paragraph to a code entity. Define this first.
- Repository structure and stack β Python, TypeScript/JavaScript, and Go for MVP, shared architecture for future languages and IDE support.
- Prototype on one example β one module, one doc page, code parser, and a check that "the document is outdated after a code change."
In short: first the format and structure, then a minimal prototype.
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββββββ
β Code parser ββββββΆβ Link graph βββββββ Doc parser β
β (AST / API) β β (code_id β doc) β β (markdown + anchors)β
ββββββββββ¬βββββββββ ββββββββββ¬βββββββββββ βββββββββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββ ββββββββββββββββββββ
β Change β β Report / site β
β detector ββββββΆβ "outdated" + β
β (diff / hash) β β suggestions β
βββββββββββββββββββ ββββββββββββββββββββ
- Code parser: extracts signatures (name, arguments, types) and unique identifiers. Supports Python, TypeScript/JavaScript, and Go.
- Doc parser: parses Markdown with explicit anchors (see
spec/code-doc-mapping.md), associating paragraphs/blocks withcode_id. - Link graph: stores (code_id, doc_fragment_id) pairs. When code changes (new signature/hash), related fragments are marked as "possibly outdated."
- Change detector: compares current code state (signatures/hashes) with the last saved state.
Extensibility: code and doc parsers are per-language plugins; the graph and report are shared.
- Primary format: Markdown in the repository (e.g., a
docs/folder or next to modules). - Linking to code: anchors in Markdown (see
spec/code-doc-mapping.md), optionally plus annotations in code (docstring tags) that reference a fragment id. - Site: generate a static site (MkDocs, Docusaurus, or custom) from the same Markdown files; navigation and search on top of the generated site.
- Python: functions, class methods (
module.path:nameormodule.path:Class.method) - TypeScript/JavaScript: functions, arrow functions, classes, methods, interfaces, type aliases (
.ts,.tsx,.js,.jsx). Supports destructuring params. Excludes*.d.ts,*.test.*,*.spec.*,node_modules,dist,build. - Go: functions and methods (
.go). Format:package:FunctionNameorpackage:(*Type).Method. Excludesvendor,*_test.go.
- Features:
- Parse modules (functions, methods, signatures, and language-specific constructs) for Python, TypeScript/JavaScript, and Go
- Documentation (e.g. Markdown) with
livedocanchors linking to code entities - Detect outdated doc sections when linked code signatures change; anchor validation (each
code_idmust exist in parsed code); code locations in reports (path:lineto the definition)
- Extensibility: abstractions for the code parser and anchor format to support more languages and IDE integration later.
LiveDoc/
βββ README.md # this file
βββ spec/
β βββ code-doc-mapping.md # anchor format and codeβdoc mapping
βββ src/
β βββ livedoc/
β βββ __init__.py
β βββ core/ # link graph, change detector
β βββ parsers/ # Python code parser, doc parser
β βββ report/ # "outdated" report, future site generation
βββ tests/
βββ examples/ # sample project (Python + TypeScript + Go)
β βββ sample_module/ # Python
β βββ ts_sample/ # TypeScript
β βββ go_sample/ # Go
β βββ docs/
βββ pyproject.toml
-
Install:
pip install living-doc(orpip install -e .from this repo) -
Create docs in
docs/with anchors linking to code:<!-- livedoc: code_id = "mymodule.calc:add" --> ## add Adds two numbers.
For TypeScript:
<!-- livedoc: code_id = "src.utils:add" -->(path.to.file:name or path.to.file:Class.method) -
First run (saves code signatures):
python -m livedoc --docs docs
-
CI: See GitHub Actions in your project for a full workflow you can copy.
-
Optional: Add
.livedoc.jsonin project root for defaults:{ "docs": "docs", "ignore": ["build"], "ignore_code_ids": ["generated.client:*"], "format": "text" }Use
ignore_code_idsto exclude specific symbols or glob patterns from checks. -
Optional: Add
.livedocignore(one pattern per line) to exclude paths:build scripts -
Optional: Pre-commit hook β add to
.pre-commit-config.yaml:- repo: local hooks: - id: livedoc name: livedoc entry: python -m livedoc language: system pass_filenames: false
Then:
pip install pre-commit && pre-commit install
# Install (optional, for livedoc command)
pip install -e .
# Check links and freshness for the example (from repo root)
python -m livedoc examples
# First run saves code signatures to examples/.livedoc/code_signatures.json.
# After changing a function/method signature, the next run will show
# related doc fragments as "possibly outdated" with a diff of old vs new signature.
# To update signatures after editing docs: --update
# Pre-commit (this repo): pre-commit install && pre-commit run livedoc
# Options (CLI overrides .livedoc.json):
# --ignore PATTERN Exclude paths (can be repeated)
# --format json Machine-readable output for CI/scripts
# --quiet Reduce non-essential output (good for CI logs)
# .livedoc.json Config: docs, ignore, ignore_code_ids, format
# .livedocignore File with ignore patterns (one per line)Use the published package from PyPI so CI matches what developers install locally.
- Add
livedocanchors to your Markdown under the folder you pass as--docs(oftendocs/). - Run once locally from the repository root:
pip install living-doc && python -m livedoc . --docs docs
(adjust--docsif your folder differs, or set"docs": "docs"in.livedoc.jsonand runpython -m livedoc .). - Commit
.livedoc/code_signatures.json(created on first run). CI compares future commits to this baseline; without it, the first CI run only saves signatures and passes.
Save as .github/workflows/livedoc.yml in your repository:
name: Living documentation
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
livedoc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install living-doc
run: pip install living-doc
- name: Check doc freshness and anchors
run: python -m livedoc . --docs docs- Replace
docswith your docs directory if needed, or rely on.livedoc.json("docs": "...") and usepython -m livedoc .. - To pin the version:
pip install "living-doc==0.1.6". - For machine-readable logs: add
--format jsonor set"format": "json"in.livedoc.json(e.g. to parse in a follow-up step). - To exclude specific symbols from checks, set
"ignore_code_ids": ["pkg:GeneratedClient", "internal.*:*"]in.livedoc.json.
- Outdated docs: update the Markdown or run
python -m livedoc . --docs docs --updateafter intentional API changes, then commit the updated.livedoc/code_signatures.json. - Unknown anchors: fix or remove invalid
code_idvalues in Markdown (see Anchor validation).
Every code_id in a livedoc anchor must match a symbol parsed from your project (Python, TypeScript/JavaScript, Go). If an anchor points to a missing or mistyped id, the check fails with Unknown code_id references (exit code 1). The JSON report includes an unknown_anchors array.
When documentation is outdated because a linked symbol changed, the text report includes a Code: line with the file path (relative to the project root) and line number of the current definition, e.g. sample_module/calc.py:6. JSON entries under code_changes include code_file and code_line. Each change also includes a reason such as args changed, return type changed, or symbol removed. If the symbol was removed from the codebase, the text report says (symbol removed from codebase) instead.
Example JSON fragment:
{
"code_id": "web.service:render",
"old_sig": "render(name) -> string",
"new_sig": "render(name, locale) -> string",
"reason": "args changed",
"diff": "render(name) -> string -> render(name, locale) -> string",
"code_file": "web/service.ts",
"code_line": 1
}The workflow .github/workflows/livedoc.yml installs this repo in editable mode (pip install -e .) and runs python -m livedoc examples --docs docs so CI always uses the current source. The committed examples/.livedoc/code_signatures.json is the baseline; if example code changes without updating docs or signatures, the job fails.
pip install build twine
python -m build
python -m twine upload dist/*Requires a PyPI account and token. Use __token__ as username and your API token as password.
On github.com/baksvell/Livedoc, click βοΈ next to About and set:
| Field | Suggested value |
|---|---|
| Description | Link docs to code; flag outdated Markdown when signatures change. |
| Website | https://pypi.org/project/living-doc/ |
| Topics | documentation, living-docs, python, typescript, go, golang, code-docs, markdown, developer-tools |
(Topics are added one by one in the About editor.)
- Add parsers for other languages in
parsers/ - IDE integration: LSP or extension (show docs on hover)
- Generate and serve a documentation site with "outdated" highlights
See CONTRIBUTING.md for development setup, tests, and PR checklist.