selfdocumenting
Code-aware documentation site generator. Builds full static sites from Markdown templates and source code. Your code is the documentation -- directives in Markdown pull live content from your codebase at build time.
Supports Python, Go, and TypeScript/JavaScript. One runtime dependency (strictcli). Pure Python.
Install
pip install selfdocumenting
or via npm (delegates to Python under the hood):
npm install -g selfdocumenting
Requires 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 serve
Your selfdoc.json needs versions and locales -- even for a single-version, single-locale project:
{
"language": "python",
"source": ["src/"],
"base_url": "https://my-project.example.com",
"versions": [{"version": "1.0.0", "indexed": true}],
"locales": [{"code": "en", "label": "English", "default": true}]
}
Features
- Directive syntax -- embed live API references, schemas, tests, and CLI help directly from source code (
:-:,:<:,:>:) - Auto-generated pages -- API reference and CLI docs from source code structure (
selfdoc gen) - Multi-version docs -- build from git tags, cached builds, version picker UI
- Localization -- parallel locale directories, hreflang tags, locale picker, per-locale sitemaps
- Monorepo support -- unified site builder combines multiple projects into one docs site
- Faceted search -- key=value filter syntax, 7 dimensions, chip UI, auto-injected version default
- Sandboxed data generation -- run scripts in bubblewrap isolation (
selfdoc gen-data) - Theming -- dark mode, accent colors, custom CSS overrides
- Search engines -- builtin, Fuse.js, or MiniSearch
- SEO -- 15+ lint rules, WCAG contrast validation, JSON-LD structured data, sitemaps
- Coverage tracking -- per-symbol documentation coverage with configurable thresholds
- Syntax highlighting -- build-time Pygments, code tabs, sortable tables
- Performance -- CSS/JS/HTML minification, critical CSS inlining, gzip and Brotli pre-compression
- Feeds and AI -- Atom feed,
robots.txtwith AI crawler controls,llms.txt/llms-full.txt - Landing page -- hero section, tagline, and feature cards
- Live reload -- SSE-based dev server
- Auto-commit -- generated files committed automatically (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-endpoint |
REST API endpoint table from OpenAPI spec |
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/",
"base_url": "https://my-project.example.com",
"versions": [{"version": "1.0.0", "indexed": true}],
"locales": [{"code": "en", "label": "English", "default": true}],
"deploy": {
"provider": "cloudflare-pages",
"project": "my-docs"
},
"directives": {}
}
| Field | Required | Description |
|---|---|---|
source |
yes | List of source entries to extract documentation from. |
base_url |
yes | Base URL of the generated site, used for canonical links and SEO. |
version |
no | Project version. When present, used by deploy instead of reading from pyproject.toml/package.json. |
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. |
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', 'STALE001'). |
root_files |
no | List of underscore-prefixed template paths in docs/ for root file generation. |
redirects |
no | Page-level redirects expanded across all locale/version combos. |
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. |
schema_types |
no | Mapping from page type to schema.org @type (e.g. guide -> TechArticle). |
versions |
no | List of documentation versions to build. |
locales |
no | List of locales for multi-language documentation. |
unified |
no | Configuration for unified multi-project documentation. |
posts |
no | Blog post configuration. |
topology |
no | Deployment topology for multi-project unified sites. |
assembly |
no | Assembly configuration for unified site deployment. |
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 configuration and starter docs template |
build |
Build the documentation site from templates and source code |
serve |
Serve the documentation site locally with live reload |
deploy |
Deploy the built documentation site to the configured provider |
check |
Check documentation coverage, directive resolution, and lint rules |
gen |
Auto-generate documentation pages from project structure |
gen-data |
Generate data files by running sandboxed scripts via bwrap |
| post | Manage blog posts and chronological content for the documentation site |
post new |
Scaffold a new blog post markdown file with a date-prefixed filename and frontmatter template containing title, date, slug, tags, draft status, and project metadata. Creates the file in the configured posts directory and exits with an error if the file already exists. |
post list |
List all discovered blog posts with date, title, slug, and draft status. Scans the configured posts directory for markdown files with frontmatter, parses their metadata, and prints a formatted summary showing each post's publication date, title, slug identifier, and whether it is marked as a draft. |
post generate |
Generate a blog post markdown file from structured release metadata. Takes version, bump type, description, changelog, and registry URLs as inputs, produces a frontmatter-bearing post with title, date, tags, and body content, and updates the project manifest with the new post entry. |
post publish |
Publish non-draft blog posts to the documentation assembly. Builds posts locally, pushes built HTML and manifest to the assembly repo via the Git Data API, then dispatches a shared-only workflow to regenerate cross-project elements. |
| assembly | Manage the unified multi-project documentation assembly and deployment |
assembly init |
Create and initialize the assembly GitHub repository with workflow and configuration files. Creates a private GitHub repo, pushes initial files via the Contents API, creates a Cloudflare Pages project if credentials are available, and sets GitHub secrets for deployment authentication. |
assembly push |
Dispatch a GitHub Actions workflow to rebuild this project in the documentation assembly. Detects the source repository, resolves the latest git tag as the version reference, and sends a repository dispatch event to the assembly repo with the project slug, version, and commit SHA. |
assembly status |
Show the status of recent assembly build workflow runs on GitHub. Queries the assembly repository for recent workflow runs using the GitHub CLI and displays their status, conclusion, and timing information for monitoring deployment progress. |
assembly rebuild |
Dispatch rebuild workflows for every project registered in the assembly. Fetches the projects.json manifest from the assembly repository, then sends a separate GitHub Actions repository dispatch event for each registered project to trigger a full documentation rebuild. |
assembly redirects |
Generate a Cloudflare Pages _redirects file for this project that redirects standalone documentation URLs to the corresponding paths on the unified assembly site. Requires a project slug and assembly base URL as inputs, prints the redirect rules to stdout. |
assembly generate-shared |
Generate 6 shared cross-project elements for the assembled documentation site. Reads per-project manifest JSON files, merges post overlays, and produces a homepage, blog index, navigation JSON, RSS feed, XML sitemap, and security headers file in the site output directory. |
Deploy
Cloudflare Pages
Requires the Wrangler CLI installed and authenticated.
{
"deploy": {
"provider": "cloudflare-pages",
"project": "my-docs-project"
}
}
selfdoc build && selfdoc deploy
GitHub 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.
Documentation
Full documentation at selfdoc.smmh.dev.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file selfdoc-0.27.0.tar.gz.
File metadata
- Download URL: selfdoc-0.27.0.tar.gz
- Upload date:
- Size: 844.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0789b8aee2c6b6b86cd7b5efbe74ecfcc1a2567d3007a4b1ab71a0a4268070b
|
|
| MD5 |
4188e42e930673e6d7777c1b7139de75
|
|
| BLAKE2b-256 |
2432483bfdcbc1f325937981b284ba17bbaad661b5caf2903981cfd0d748dd7f
|
Provenance
The following attestation bundles were made for selfdoc-0.27.0.tar.gz:
Publisher:
publish.yml on smm-h/selfdoc
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
selfdoc-0.27.0.tar.gz -
Subject digest:
e0789b8aee2c6b6b86cd7b5efbe74ecfcc1a2567d3007a4b1ab71a0a4268070b - Sigstore transparency entry: 2084915735
- Sigstore integration time:
-
Permalink:
smm-h/selfdoc@537049493a9582d50cd1915d4c74d7ed31224517 -
Branch / Tag:
refs/tags/v0.27.0 - Owner: https://github.com/smm-h
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@537049493a9582d50cd1915d4c74d7ed31224517 -
Trigger Event:
release
-
Statement type:
File details
Details for the file selfdoc-0.27.0-py3-none-any.whl.
File metadata
- Download URL: selfdoc-0.27.0-py3-none-any.whl
- Upload date:
- Size: 361.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd2459cb1d0ed9f660491547b06c7eb39aad24f6bed57e71ca3b7f3d8cb63a85
|
|
| MD5 |
e6ab8304087e93a7f5dcefcdf1212758
|
|
| BLAKE2b-256 |
0fb47365e05f67b82328b5f396c8ec0f7207957bc6fb15439375ee98d96bf472
|
Provenance
The following attestation bundles were made for selfdoc-0.27.0-py3-none-any.whl:
Publisher:
publish.yml on smm-h/selfdoc
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
selfdoc-0.27.0-py3-none-any.whl -
Subject digest:
dd2459cb1d0ed9f660491547b06c7eb39aad24f6bed57e71ca3b7f3d8cb63a85 - Sigstore transparency entry: 2084915744
- Sigstore integration time:
-
Permalink:
smm-h/selfdoc@537049493a9582d50cd1915d4c74d7ed31224517 -
Branch / Tag:
refs/tags/v0.27.0 - Owner: https://github.com/smm-h
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@537049493a9582d50cd1915d4c74d7ed31224517 -
Trigger Event:
release
-
Statement type: