Skip to main content

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

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)

Source distribution for mdship 1.3.1
File Size Uploaded Provenance
mdship-1.3.1.tar.gz 2.1 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mdship 1.3.1
File Interpreter ABI Platform
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page