selfdocumenting
v0.8.1
Published
Code-aware static site generator with directive-based content extraction
Maintainers
Readme
selfdocumenting
Code-aware documentation site generator. Builds full static sites from Markdown templates and source code, with directive-based content extraction, auto-generated API/CLI reference pages, theming, search, SEO, and deploy to Cloudflare Pages or GitHub Pages.
Supports Python, Go, and TypeScript/JavaScript. One runtime dependency (strictcli). Pure Python.
Install
pip install selfdocumentingor via npm (delegates to Python under the hood):
npm install -g selfdocumentingRequires Python 3.11+.
The npm package is named selfdocumenting (npm blocks selfdoc due to name similarity). The CLI command remains selfdoc.
Quick start
# Initialize in an existing project (auto-detects language)
selfdoc init
# Auto-generate API and CLI reference pages
selfdoc gen
# Edit docs/ pages -- add directives referencing your code
# Build HTML output
selfdoc build
# Validate directives, coverage, and SEO lint
selfdoc check
# Serve locally with live reload
selfdoc serveFeatures
- Attribute-based directive syntax (
:-:,:<:,:>:) for embedding code-extracted content - Auto-generated API reference and CLI docs from source code structure (
selfdoc gen) - Sandboxed data generation scripts (
selfdoc gen-data) - Theming with dark mode, accent colors, and custom CSS overrides
- Pluggable search (builtin, Fuse.js, or MiniSearch)
- 15+ SEO lint rules, WCAG contrast validation, JSON-LD structured data
- Per-symbol documentation coverage tracking with configurable thresholds
- Build-time Pygments syntax highlighting, code tabs, sortable tables
- CSS/JS/HTML minification, critical CSS inlining, gzip and Brotli pre-compression
- Atom feed,
robots.txtwith AI crawler controls,llms.txt/llms-full.txt - Landing page with hero section, tagline, and feature cards
- SSE-based live reload dev server
- Auto-commit of generated files (prefers safegit)
Directive syntax
Directives are inline blocks in your Markdown templates. They get replaced with content extracted from your source code at build time.
:-: directive-name path="arg"Self-closing directives use :-:. Block directives that wrap a body use :<: to open, :>: to close, with :=: and ::: to delimit sections inside. Directives inside fenced code blocks are ignored.
Built-in directives
| Directive | Description |
| --- | --- |
| callout-danger | Styled danger callout block |
| callout-important | Styled important callout block |
| callout-note | Styled note callout block |
| callout-tip | Styled tip callout block |
| callout-warning | Styled warning callout block |
| code-help | Extract CLI help/usage text and flag definitions |
| code-test | Embed test source code (whole file or specific function) |
| list-features | Module summaries from docstring first lines |
| list-glossary | Definition list from Term: Definition lines |
| list-modules | List source modules with file paths and docstring summaries |
| list-tree | File/directory tree listing |
| prose-desc | Extract module/package docstring as prose text |
| ref | Extract module docstring, exported functions, and classes |
| table-commands | CLI command summary table from strictcli structure |
| table-config | Render a config file (JSON/TOML) as a key-value table |
| table-config-schema | Configuration field reference table from schema |
| table-dep | Dependencies table from pyproject.toml |
| table-directives | Table of all core built-in directives |
| table-schema | Extract dataclass/struct fields as a markdown table |
| var | Interpolate project metadata value |
Example -- embed the API docs for a Python module:
## API Reference
:-: ref path="selfdoc.config"Example -- show a JSON schema as a table:
:-: table-schema path="selfdoc.json"Custom directives
Register custom directives in selfdoc.json under the directives key. Each entry maps a directive name to a Python script (relative to project root) that exports a resolve(attrs, config, body) function returning a Markdown string.
{
"directives": {
"changelog": "scripts/changelog_directive.py"
}
}Script interface:
def resolve(attrs: dict, config: dict, body: list) -> str:
"""Return Markdown string to replace the directive block.
attrs -- directive attributes as str->str dict (e.g. {"path": "v1.0.0"})
config -- the full selfdoc.json config dict
body -- body lines from the directive block (empty list for one-liners)
"""
version = attrs.get("path")
...Use in templates:
:-: changelog path="v1.0.0"Custom directives take priority over built-in names.
Configuration
selfdoc.json at the project root:
{
"language": "python",
"source": ["selfdoc/"],
"docs": "docs/",
"output": "docs/_build/",
"deploy": {
"provider": "cloudflare-pages",
"project": "my-docs"
},
"directives": {}
}| Field | Required | Description |
| --- | --- | --- |
| language | yes | Programming language of the documented project. |
| source | yes | List of source directories or files to extract documentation from. |
| base_url | yes | Base URL of the generated site, used for canonical links and SEO. |
| docs | no | Directory containing Markdown documentation templates. |
| output | no | Output directory for generated HTML files. |
| theme | no | Visual theme for the generated site. |
| repo | no | GitHub repository URL shown in the site header. |
| lang | no | BCP 47 language tag for the site content (e.g. 'en', 'pt-BR'). |
| description | no | Short description of the project, used in meta tags and SEO. |
| branch | no | Git branch used for source links in the generated site. |
| search | no | Search UI mode: icon button, full bar, or hidden. |
| search_engine | no | Client-side search engine implementation to use. |
| code_icons | no | Style of language icons shown on code blocks. |
| line_numbers | no | Show line numbers in code blocks. |
| run_button | no | Show a run button on code blocks for supported languages. |
| page_nav | no | Show previous/next navigation links between pages. |
| page_progress | no | Show a reading progress bar at the top of each page. |
| glossary | no | Auto-generate a glossary page from dfn terms. |
| min_coverage | no | Minimum documentation coverage percentage required by the check command. |
| feed_max_entries | no | Maximum number of entries in the Atom feed, sorted by most recent. |
| lint_ignore | no | List of lint rule IDs to suppress (e.g. 'SEO007'). |
| root_files | no | List of underscore-prefixed template paths in docs/ for root file generation. |
| deploy | no | Deployment configuration for publishing the generated site. |
| directives | no | Custom directive mappings from directive name to source file path. |
| author | no | Author information for meta tags and structured data. |
| feedback | no | Feedback collection configuration (at least one of webhook or ga required). |
| branding | no | Landing page branding and call-to-action configuration. |
| auto_detect | no | Automatic content detection settings for step guides and API entries. |
| gen | no | Configuration for the gen command. |
| gen_data | no | Configuration for the gen-data command. |
selfdoc init auto-detects language and source paths from project files (pyproject.toml, go.mod, tsconfig.json, package.json).
Commands
| Command | Description |
| --- | --- |
| init | Initialize selfdoc in the current project |
| build | Build the documentation site |
| serve | Serve the documentation site locally |
| deploy | Deploy the documentation site |
| check | Check documentation coverage and consistency |
| gen | Auto-generate documentation pages from project structure |
| gen-data | Generate data files by running sandboxed scripts |
Deploy
Cloudflare Pages
Requires the Wrangler CLI installed and authenticated.
{
"deploy": {
"provider": "cloudflare-pages",
"project": "my-docs-project"
}
}selfdoc build && selfdoc deployGitHub Pages
Pushes the output directory to the gh-pages branch via force-push.
{
"deploy": {
"provider": "github-pages"
}
}Enable GitHub Pages in your repo settings (source: gh-pages branch).
Integration with rlsbl
When rlsbl detects a selfdoc.json in the project, it can trigger selfdoc build and selfdoc deploy as part of the release lifecycle via the .rlsbl/hooks/post-release.sh hook.
License
MIT
