Tutorials-as-Code: Execute and validate Markdown tutorials
Project description
GuideRails
Tutorials-as-Code: Execute and validate Markdown tutorials to prevent documentation drift.
GuideRails enables you to write interactive, executable tutorials in Markdown that can be:
- ✅ Validated automatically in CI/CD pipelines
- 🚀 Run interactively in guided mode for step-by-step execution
- 📝 Authored with minimal, unobtrusive markup
- 🌐 Executed from local files or web URLs
Features
- Markdown-first: Write tutorials in plain Markdown with minimal annotations
- Interactive mode: Step-by-step guided execution with user prompts
- CI mode: Automated validation for continuous integration
- Flexible validation: Support for exit codes, output matching, regex, and exact comparisons
- File generation: Create files directly from code blocks with
.gr-file - Output capture: Store command output and exit codes in variables
- Variable substitution: Use
${VAR}syntax for continuity across steps - Web support: Load tutorials from URLs with meta tag discovery
- Developer-friendly: Simple attribute syntax for marking executable steps
- Safe by default: Sandboxed file operations within working directory
Note: As of version 0.2.0, the CLI tool has been renamed from
guideruntoguiderailsfor consistency with the project name. Please update your scripts and workflows accordingly. See CHANGELOG.md for details.
Installation
pip install guiderails
Or install from source:
git clone https://github.com/srbouffard/guiderails.git
cd guiderails
pip install -e .
Quick Start
1. Write a Tutorial
Create a Markdown file with GuideRails annotations:
# My First Tutorial
## Step 1: Setup {.gr-step #step1}
Let's create a test directory:
\```bash {.gr-run data-mode=exit data-exp=0}
mkdir -p /tmp/test
\```
## Step 2: Verify {.gr-step #step2}
Check that it was created:
\```bash {.gr-run data-mode=contains data-exp="/tmp/test"}
ls -d /tmp/test
\```
2. Run Interactively
guiderails exec --guided tutorial.md
3. Validate in CI
guiderails exec --ci tutorial.md
Authoring Convention
Marking Steps
Mark tutorial steps by adding {.gr-step} to headings:
## Setup Environment {.gr-step #setup}
Optional: Add an ID with #step-id for reference.
Marking Executable Code
Mark code blocks for execution with {.gr-run}:
\```bash {.gr-run data-mode=exit data-exp=0}
echo "Hello, World!"
\```
Validation Modes
GuideRails supports four validation modes:
1. Exit Code (default)
\```bash {.gr-run data-mode=exit data-exp=0}
test -f myfile.txt
\```
2. Contains
\```bash {.gr-run data-mode=contains data-exp="success"}
./my-script.sh
\```
3. Regex
\```bash {.gr-run data-mode=regex data-exp="Error: [0-9]+"}
./check-status.sh
\```
4. Exact Match
\```bash {.gr-run data-mode=exact data-exp="Hello, World!"}
echo "Hello, World!"
\```
File-Generating Blocks
Create files directly from your tutorial using .gr-file blocks:
\```bash {.gr-file data-path="script.sh" data-mode=write data-exec=true}
#!/bin/bash
echo "Hello from GuideRails!"
\```
Attributes:
data-path: Target file path (relative to working directory)data-mode:write(default, overwrite) orappenddata-exec:trueto make file executable (chmod +x)data-template:none(default) orshell(enables ${VAR} substitution)data-once:trueto skip if file already exists
Example with variable substitution:
\```python {.gr-file data-path="config.py" data-template=shell}
VERSION = "${APP_VERSION}"
PORT = ${PORT}
\```
Output and Exit Code Capture
Capture command output and exit codes for use in later steps:
\```bash {.gr-run data-out-var=GREETING data-code-var=EXIT_STATUS}
echo "Hello, World!"
exit 0
\```
Capture Options:
data-out-var=VARNAME: Store combined stdout/stderr in a variabledata-out-file=path: Write stdout to a filedata-code-var=VARNAME: Store exit code in a variable
Variable Substitution
Use captured variables in subsequent blocks with ${VAR} syntax:
\```bash {.gr-run data-out-var=NAME}
echo -n "Alice"
\```
\```bash {.gr-run data-mode=contains data-exp="Hello, Alice"}
echo "Hello, ${NAME}"
\```
Variables are automatically substituted when:
- Running
.gr-runcode blocks (command is substituted before execution) - Writing
.gr-fileblocks withdata-template=shell
Safety: File paths are sandboxed to the working directory by default. Absolute paths and .. traversal are rejected unless explicitly allowed with CLI flags.
Additional Options
- Timeout:
data-timeout=60(seconds, default: 30) - Working Directory:
data-workdir=/tmp - Continue on Error:
data-continue-on-error=true
Example:
\```bash {.gr-run data-mode=exit data-exp=0 data-timeout=60 data-workdir=/tmp}
long-running-command
\```
CLI Usage
Commands
guiderails exec
Execute a tutorial:
guiderails exec [OPTIONS] TUTORIAL
Basic Options:
--guided: Run in interactive mode (shows each step, prompts for execution)--ci: Run in CI mode (non-interactive, fails fast, defaults to quiet output)--working-dir, -w PATH: Set base working directory for execution
Verbosity Options:
--verbosity LEVEL: Set verbosity level (quiet,normal,verbose,debug)--quiet, -q: Quiet mode (minimal output, alias for--verbosity=quiet)--verbose, -v: Increase verbosity (-vfor verbose,-vvor-vvvfor debug)--debug: Debug mode (maximum verbosity, alias for--verbosity=debug)
Output Toggle Options:
--show-commands / --no-show-commands: Show/hide commands being executed--show-substituted / --no-show-substituted: Show/hide variable substitution hints--show-expected / --no-show-expected: Show/hide expected validation values--show-captured / --no-show-captured: Show/hide captured variable information--timestamps / --no-timestamps: Show/hide execution timestamps--step-banners / --no-step-banners: Show/hide step banners and boxes--previews / --no-previews: Show/hide command previews and extra details
Output Format:
--output FORMAT: Output format (textorjsonl)
Verbosity Level Behaviors:
- quiet: Shows only step titles, commands (if
--show-commands), command output, and PASS/FAIL status. Minimal decoration. - normal (default): Adds step banners, content boxes, and basic execution results.
- verbose: Adds command previews, substitution details, timing information, and working directory.
- debug: Adds internal diagnostics, parser events, and variable table state.
Tutorial Sources:
- Local file:
./tutorial.md - Direct URL:
https://example.com/tutorial.md - HTML page with meta tag:
https://example.com/tutorial.html
Examples
Run locally with interaction:
guiderails exec --guided examples/getting-started.md
Validate in CI (defaults to quiet output):
guiderails exec --ci examples/getting-started.md
Run with verbose output:
guiderails exec --ci --verbose examples/getting-started.md
Run in quiet mode with no command display:
guiderails exec --ci --quiet --no-show-commands examples/getting-started.md
Run from URL:
guiderails exec --guided https://example.com/tutorial.md
From HTML with meta tag:
guiderails exec --guided https://example.com/tutorial.html
The HTML page should include:
<meta name="guiderails:source" content="https://example.com/raw/tutorial.md">
Configuration
GuideRails supports configuration through multiple sources with the following precedence:
1. Command-line flags (highest priority)
2. Environment variables
3. Configuration file (guiderails.yml)
4. Built-in defaults (lowest priority)
Environment Variables
# Verbosity level
export GUIDERAILS_VERBOSITY=quiet|normal|verbose|debug
# Output toggles
export GUIDERAILS_SHOW_COMMANDS=true|false
export GUIDERAILS_SHOW_SUBSTITUTED=true|false
export GUIDERAILS_SHOW_EXPECTED=true|false
export GUIDERAILS_SHOW_CAPTURED=true|false
export GUIDERAILS_TIMESTAMPS=true|false
export GUIDERAILS_STEP_BANNERS=true|false
export GUIDERAILS_PREVIEWS=true|false
Configuration File
Create a guiderails.yml file in your project root:
# Verbosity level (quiet, normal, verbose, debug)
verbosity: normal
# Output toggles
show_commands: true
show_substituted: false
show_expected: true
show_captured: true
show_timestamps: false
show_step_banners: true
show_previews: false
GuideRails will search for guiderails.yml in the current directory and parent directories.
CI Integration
GitHub Actions
Create .github/workflows/validate-tutorials.yml:
name: Validate Tutorials
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install GuideRails
run: pip install guiderails
- name: Validate tutorials
run: |
guiderails exec --ci docs/tutorial.md
Examples
See the examples directory for sample tutorials:
- getting-started.md - Basic GuideRails tutorial
- file-generation-and-capture.md - File generation, output capture, and variable substitution
- tutorial-page.html - HTML page with meta tag
Development
Setup
# Clone the repository
git clone https://github.com/srbouffard/guiderails.git
cd guiderails
# Install in development mode
pip install -e ".[dev]"
Running Tests
pytest tests/ -v
Code Formatting
black src/ tests/
ruff check src/
Roadmap
- Support for reStructuredText (reST) tutorials
- Environment variable support
- Parallel execution of independent steps
- Step dependencies and conditional execution
- Plugin system for custom validators
- Web UI for tutorial execution and monitoring
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE file for details.
Acknowledgments
Inspired by the need for validated, executable documentation that stays in sync with code.
Project details
Release history Release notifications | RSS feed
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 guiderails-0.1.0.tar.gz.
File metadata
- Download URL: guiderails-0.1.0.tar.gz
- Upload date:
- Size: 37.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d40637ffaf48d56e9e1bfaf8660c84bf8e5d1e57e6bae3fc3d7cee34c9bc6a04
|
|
| MD5 |
6ad6b7eff0d74b1f84e82aabcfc91e46
|
|
| BLAKE2b-256 |
ac9e3a9f3421924baab8c3d6202bfb0ebfba778d36d7d8affe4cb45fc171bb61
|
Provenance
The following attestation bundles were made for guiderails-0.1.0.tar.gz:
Publisher:
release.yml on srbouffard/guiderails
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guiderails-0.1.0.tar.gz -
Subject digest:
d40637ffaf48d56e9e1bfaf8660c84bf8e5d1e57e6bae3fc3d7cee34c9bc6a04 - Sigstore transparency entry: 661334925
- Sigstore integration time:
-
Permalink:
srbouffard/guiderails@5fae5df8aa7176e36180927c74973be908ab777d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/srbouffard
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5fae5df8aa7176e36180927c74973be908ab777d -
Trigger Event:
release
-
Statement type:
File details
Details for the file guiderails-0.1.0-py3-none-any.whl.
File metadata
- Download URL: guiderails-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62151ebba591c6266ff5d7ece985e878b05f2b00c627fde0ed42b9fdac509ba8
|
|
| MD5 |
58089c0f7f5a428b92e0f0bad9eeaf46
|
|
| BLAKE2b-256 |
e00390717722d3ba5401d9e846f87802cc9ff219277bf7ab241b24a280cbaa10
|
Provenance
The following attestation bundles were made for guiderails-0.1.0-py3-none-any.whl:
Publisher:
release.yml on srbouffard/guiderails
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guiderails-0.1.0-py3-none-any.whl -
Subject digest:
62151ebba591c6266ff5d7ece985e878b05f2b00c627fde0ed42b9fdac509ba8 - Sigstore transparency entry: 661334930
- Sigstore integration time:
-
Permalink:
srbouffard/guiderails@5fae5df8aa7176e36180927c74973be908ab777d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/srbouffard
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5fae5df8aa7176e36180927c74973be908ab777d -
Trigger Event:
release
-
Statement type: