Executable documentation that never lies.
RunDoc is a CLI tool that turns your Markdown documentation into executable specifications. It finds code blocks, runs them, and validates the output — ensuring your documentation is always truthful and up to date.
Documentation gets stale the moment you write it. Commands stop working, code examples have typos, and new team members waste hours figuring out which parts of the docs are actually correct.
RunDoc transforms your Markdown files into living documents that verify themselves. Add a simple annotation to any code block, and RunDoc will execute it, compare the output against your expectations, and tell you exactly what's broken.
- Multi-language support — Bash, Go, Python, and more with extensible runners
- Output validation — exact match, regular expressions, and exit code checking
- Windows and Unix support — works on any platform
- Verbose mode — detailed execution logs for debugging
- Update mode — automatically refresh expected outputs in your docs
- CI/CD ready — fails the build when documentation is out of date
git clone https://github.com/maypress/RunDoc.git
cd RunDoc
go build -o rundoc cmd/rundoc/main.gogo install github.com/maypress/RunDoc/cmd/rundoc@latestCreate a file named example.md:
# My Documentation
## Check the version
```bash run
echo "Hello, World!"
# expect: Hello, World!
Now run it:
```bash run
rundoc example.md
Output:
📄 example.md
✓ echo "Hello, World!" (bash) — 2.3ms
📊 Result: 1 of 1 blocks passed
Check a documentation file:
rundoc README.mdRun with verbose output to see execution details:
rundoc --verbose README.mdUpdate expected outputs in your documentation:
rundoc --update README.mdCombine flags:
rundoc --update --verbose README.mdRunDoc looks for code blocks with the run annotation. Add it right after the language name:
```bash run
your-command-here
```Use comments inside your code block to tell RunDoc what to expect:
```bash run
echo "Hello"
# expect: Hello
``````python run
import datetime
print(datetime.datetime.now().year)
# expect-regex: \d{4}
``````bash run
cat non-existent-file.txt
# expect-exit: 1
```| Language | Annotation |
|---|---|
| Bash | bash run or sh run |
| Go | go run |
| Python | python run or py run |
RunDoc uses a runner interface. To add a new language:
- Create a new file in
internal/runner/extensions/ - Implement the
Runmethod - Add your language to the switch in
runner.go
Create docs/api.md:
# API Setup
## Start the server
```bash run
curl -s http://localhost:3000/health
# expect: OK
```rundoc docs/api.md📄 docs/api.md
✗ Start the server (bash) — 1.2s
💡 output mismatch:
Expected:
OK
Got:
Connection refused
📊 Result: 0 of 1 blocks passed
💡 Update documentation: rundoc docs/api.md --update
Either fix the actual API server, or update the documentation with the correct expected output:
rundoc docs/api.md --updateRunDoc returns exit code 1 when any block fails, making it perfect for CI pipelines.
name: Validate Documentation
on:
push:
paths:
- '**.md'
- '**.go'
jobs:
validate-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install RunDoc
run: go install github.com/maypress/RunDoc/cmd/rundoc@latest
- name: Run Documentation Tests
run: rundoc --verbose ./docs/*.mdvalidate-docs:
stage: test
script:
- go install github.com/maypress/RunDoc/cmd/rundoc@latest
- rundoc --verbose docs/*.md
only:
changes:
- "**/*.md"| Flag | Description |
|---|---|
--update |
Update expected outputs in the Markdown file |
--verbose |
Show detailed execution information |
RunDoc/
├── cmd/
│ └── rundoc/
│ └── main.go # CLI entry point
├── internal/
│ ├── parser/ # Markdown parser
│ │ └── parser.go
│ ├── runner/ # Code execution
│ │ ├── runner.go # Runner interface
│ │ └── extensions/ # Language implementations
│ │ ├── bash.go
│ │ ├── go.go
│ │ └── python.go
│ ├── validator/ # Output validation
│ │ └── validator.go
│ └── reporter/ # Console output
│ └── reporter.go
├── testdata/ # Test files
│ └── sample.md
└── go.mod
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a feature branch
- Add your changes
- Run tests:
go test ./... - Submit a pull request
- Go 1.21 or higher
- Git
This project is licensed under the MIT License - see the LICENSE file for details.
RunDoc was inspired by tools like cram, mdtest, and Python's doctest — bringing the concept of executable documentation to modern multi-language projects.