last-updated: '2026-06-10T11:37:48.418276' mdship-log: | 2026-06-10 11:37:48 - update: processed all placeholders checksum: b326a942cc09f96603903254dec3898f18523158e38d42f285111bc9cfc87394 checksum_algorithm: sha256
mdship
mdship keeps AI-written and generated parts of your Markdown in sync with the sources they come from, and tells you exactly which part is stale and why.
- 1. Why mdship
- 2. Quickstart
- 3. Enforce It in CI
- 4. Generated Content Without AI
- 5. Markdown and Editing Tools
- 6. MCP Server
- 7. Installation
- 8. Documentation
- 9. Dependencies and Licensing
- 10. Development
1. Why mdship
Documentation generated by an LLM goes stale silently. The code changes, the paragraph that describes it does not, and nothing tells you which paragraph is now wrong. Regenerating everything is expensive, and it rewrites text that was still correct.
mdship treats a generated paragraph the way a build system treats a build artifact. An AI placeholder declares its inputs: the prompt, the source files (or slices of them) it depends on, and an optional shared writing brief. mdship records a checksum of every input and of the generated text itself. From then on it can answer, for every placeholder:
- Is it up to date? Nothing it depends on has changed, so there is nothing to regenerate.
- Why is it stale? This dependency changed, or the prompt changed, or the brief changed.
- Was it edited by hand? The generated text no longer matches what was generated.
An agent works through two MCP tools. ai_context is the gate: it says whether anything relevant changed and, only if something did, returns exactly the inputs needed to regenerate: the source slices, the previous text, and the brief. ai_update writes the new text and records all checksums at once. The agent never reads the whole repository or the whole document, which keeps both the token cost and the room for unrelated edits small.
All control information lives in HTML comments, so GitHub and every other Markdown renderer show plain, readable Markdown.
2. Quickstart
This makes one section of docs/api.md an AI-maintained summary of src/api.py, using Claude Code.
1. Install and set up the project.
pip install mdship
cd your-project
mdship init
mdship init registers the mdship MCP server for Claude Code and installs the /ai-placeholder skill (see init).
2. Add a placeholder where the generated text should go:
# API
<!--AI
name: "api-summary"
prompt: |
Summarize the public functions in one short paragraph.
deps:
- path: ../src/api.py
-->
<!--/AI-->
Dependency paths are relative to the Markdown file. A dependency can be a whole file or a slice of it, selected by line range, regex markers, or heading.
3. Generate the text. In Claude Code, run:
/ai-placeholder docs/api.md
The skill calls ai_context, writes the paragraph, and installs it with ai_update, which also records the checksums in the placeholder's opening comment.
4. Check the status.
$ mdship ai-list docs/api.md
[{"name": "api-summary", "line": 3, "status": "up_to_date"}]
5. Change the source and check again. After editing src/api.py:
$ mdship ai-check docs/api.md
Error: docs/api.md: AI placeholder 'api-summary': dep ../src/api.py has changed since last generation
$ mdship ai-list docs/api.md
[{"name": "api-summary", "line": 3, "status": "needs_update"}]
Run /ai-placeholder docs/api.md again, and only the stale placeholder is regenerated.
No agent at hand? Write the text between the markers yourself and run mdship ai-fix docs/api.md to record the checksums. The full workflow, including the brief: file and every dependency selector, is in documentation/AI.md.
3. Enforce It in CI
mdship detects problems; it does not prevent them. The checksums are recorded only when text is generated through ai_update or accepted with ai-fix, and they are compared only when someone runs a check. mdship update does not process AI placeholders at all. Without a check in CI, nothing stops a hand edit or a stale paragraph from being merged.
What mdship ai-check catches, and what it does not:
| Situation | ai-check |
|---|---|
| A dependency changed since the text was generated | fails |
| The prompt or the brief changed | fails |
| The generated text was edited by hand | fails |
| The placeholder has never been generated | passes: nothing recorded |
To catch placeholders that were never generated, look for never_generated in mdship ai-list.
With the mdship GitHub Action:
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check AI-maintained documentation
uses: verhas/mdship@v1
with:
command: ai-check
files: README.md docs/**/*.md
The same action runs validate (broken links, anchors, missing files and images) and verify (whole-document checksum). In any other CI system, run mdship ai-check <files>: it exits with status 1 when a check fails. More recipes are in documentation/GITHUB_ACTIONS.md.
4. Generated Content Without AI
The same checksum model covers deterministic generated content, refreshed with mdship update:
<!--INCLUDE
from: "../src/api.py"
prefix: "```python"
postfix: "```"
start:
pattern: "def greet"
include: true
-->
<!--/INCLUDE-->
After mdship update docs/api.md, the block holds src/api.py from the def greet line to the end of the file. mdship records a checksum of the block; if someone edits the included text by hand, the next update stops with an error instead of silently overwriting the edit.
| Placeholder | What it does | Documentation |
|---|---|---|
INCLUDE |
Embed a file, or a slice of it by line range, regex markers, or heading | INCLUDE |
TOC |
Generate a table of contents | TOC |
SET, IMPORT, SLURP, SIP, SUP |
Define variables inline, load JSON/YAML/TOML/XML, or extract them with regexes | SET, IMPORT, SLURP, SIP, SUP |
JINJA2 |
Render a Jinja2 template with the document's variables | JINJA2 |
MERMAID |
Render a Mermaid diagram to SVG or PNG (needs mdship[mermaid]) |
MERMAID |
PYTHON |
Generate content or define variables with a project-local script | PYTHON |
TEMPLATE |
Deprecated: use JINJA2 |
TEMPLATE |
Variables are inserted into the text with references such as <!--$version-->1.2.0. How placeholders are processed and in what order, and how integrity checks work, is in the reference.
5. Markdown and Editing Tools
mdship also has a set of ordinary Markdown commands. They are useful on their own, and they give agents a way to read and change exactly the part of a document they need instead of rewriting the whole file:
- Structure:
fix-headings,shift-headings,number/unnumber - Formatting:
reflow,semantic-line-breaks,format-tables - Reading and editing:
list-headings,get-section/replace-section,get-lines/insert-lines/delete-lines,get-paragraphs,find-replace,extract-table/update-table,frontmatter-get/frontmatter-set - Checking:
validate(links, anchors, files, images),sum/verify(whole-document checksum)
mdship get-section docs/guide.md --heading "Setup > Prerequisites"
mdship fix-headings docs/guide.md
mdship validate README.md
Every command has a page in documentation/commands/. Modifying commands write a .md.bak backup unless git already holds the file's current content; --bak and --no-bak override that.
6. MCP Server
mdship init configures the server for Claude Code. For other MCP clients, run mdship mcp over stdio:
{
"mcpServers": {
"mdship": {
"command": "mdship",
"args": ["mcp"]
}
}
}
The server exposes most of the commands above as tools, such as get_section, replace_section, and fix_headings, plus the AI workflow tools list_ai_placeholders, ai_context, ai_update, ai_fix, and ai_check. See the MCP section of the reference.
7. Installation
mdship needs Python 3.11 or newer.
pip install mdship
Rendering MERMAID diagrams needs the optional mermaid extra:
pip install 'mdship[mermaid]'
8. Documentation
| Document | Contents |
|---|---|
| Reference | Every command option and placeholder setting, with examples |
| AI placeholders | Dependencies, briefs, and the agent workflow |
| Commands | One page per CLI command, and its MCP tool where there is one |
| Managed content integrity | How generated regions are protected against hand edits |
| Python scripting | Project-local scripts and the trust model |
| GitHub Actions | CI recipes |
9. Dependencies and Licensing
mdship is dual-licensed under MIT or Apache-2.0, at your option. Its dependencies:
| Package | Version | License | Purpose |
|---|---|---|---|
| typer | >=0.12 | MIT | Command-line interface |
| rich | >=13 | MIT | Terminal output |
| mcp | >=2,<3 | MIT | MCP server |
| markdown-it-py | >=3 | MIT | Markdown parsing |
| pyyaml | >=6 | MIT | YAML in placeholders and front-matter |
| jinja2 | >=3 | BSD-3-Clause | JINJA2 placeholders |
| merm | >=0.1 | WTFPL | MERMAID rendering; optional, only with mdship[mermaid] |
Details are in LICENSES.txt.
10. Development
uv sync --extra dev
uv run pytest
uv run ruff check
Metadata
Release files for mdship 1.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mdship-1.3.1.tar.gz | 2.1 MB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mdship-1.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.2 MB
Release files / mdship-1.3.1.tar.gz
| Download URL | mdship-1.3.1.tar.gz |
|---|---|
| Size | 2.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
31ead52f71f0ad207121fb047bb2cf8de30b2b82f4d5597b7c869748a0d45e21
|
|
BLAKE2b-256 checksum How to use checksums |
87fe612670d106fa6b957cacbb130f65f6207e769ea29cd965768bd7c76bbd24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.13
|
Release files / mdship-1.3.1-py3-none-any.whl
| Download URL | mdship-1.3.1-py3-none-any.whl |
|---|---|
| Size | 126.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
beb668a8564973c10c60ef3caaaccce0190d8f4b20c5414395ec8c03e7ddbb0d
|
|
BLAKE2b-256 checksum How to use checksums |
edd96fc0150d16423001485250a54f7860091ee345c1ca007d217b0527c774bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.13
|
Security for mdship 1.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.