Click the GIF above to view the full video with audio (MP4)
Transform static markdown into interactive, executable workflows. Build complex scripts with named blocks, interactive forms, cross-document navigation, and template systems.
- Named Blocks: Create reusable code blocks with dependencies
- Block Requirements: Automatically include required blocks in execution order
- Interactive Selection: Choose blocks from intuitive menus
- Script Approval: Review generated scripts before execution
- Variable Input: Create interactive forms for user input
- Validation: Built-in regex validation with custom transforms
- Dynamic Menus: Selection from allowed values or command output
- Auto-initialization: Set values from environment, commands, or defaults
- Dependencies: Chain UX blocks with complex relationships
- Link Blocks: Navigate between markdown files seamlessly
- Variable Passing: Share data between documents
- Inherited Context: Maintain state across document boundaries
- HyperCard-style Navigation: Create interactive document stacks
- Import Directives: Include content from other files with
@import - Parameter Substitution: Replace variables in imported content
- Shell Expansions: Use
${variable}and$(command)syntax throughout documents - Dynamic Content: Generate content based on user selections
- Shell Blocks: Execute bash shells
- UX Blocks: Interactive forms with validation, transforms, and dynamic behavior
- Vars Blocks: Define variables in YAML format
- Opts Blocks: Configure document behavior and appearance
- Link Blocks: Cross-document navigation and variable passing
- Script Persistence: Save and replay executed scripts
- Output Logging: Capture and review execution results
- State Inheritance: Manage context across sessions
- Configuration: Flexible options via environment, files, or CLI
gem install markdown_execmde # Process README.md in current folder
mde my-document.md # Process specific markdown file
mde . # Select from markdown files in current foldermde my-document.md my-block # Execute specific block directly
mde --list-blocks # List all available blocks
mde --list-docs # List all markdown documentsCreate interactive forms that prompt users for input:
```ux
name: USER_NAME
prompt: Enter your name
init: Guest
```
```ux
name: ENVIRONMENT
allow:
- development
- staging
- production
prompt: Select environment
```
```ux
name: EMAIL
prompt: Enter email address
validate: '(?[^@]+)@(?[^@]+)'
transform: '%{local}@%{domain}'
```
Navigate between documents while maintaining context:
```link
file: next-document.md
vars:
current_user: ${USER_NAME}
environment: ${ENVIRONMENT}
```
Use imports with parameter substitution:
@import template.md USER_NAME=John ENVIRONMENT=production
Create complex workflows with automatic dependency resolution:
```bash :deploy +setup +test +deploy
echo "Deploying to ${ENVIRONMENT}"
```
```bash :setup
echo "Setting up environment"
```
```bash :test
echo "Running tests"
```
# Environment variables
export MDE_SAVE_EXECUTED_SCRIPT=1
export MDE_USER_MUST_APPROVE=1
# Configuration file (.mde.yml)
save_executed_script: true
user_must_approve: true
# Command line
mde --save-executed-script 1 --user-must-approve 1
mde --save-executed-script 1 # Save executed scripts
mde --list-recent-scripts # List saved scripts
mde --select-recent-script # Execute saved script
mde --save-execution-output 1 # Save execution output```bash
echo "Hello World"
```
```ux
name: USER_NAME
prompt: Enter your name
init: Guest
```
```ux
name: ENVIRONMENT
allow:
- development
- staging
- production
act: :allow
```
```ux
name: CURRENT_DIR
exec: basename $(pwd)
transform: :chomp
```
```ux
name: EMAIL
prompt: Enter email address
validate: '(?[^@]+)@(?[^@]+)'
transform: '%{local}@%{domain}'
```
```vars
DATABASE_URL: postgresql://localhost:5432/myapp
DEBUG: true
```
```link
file: next-page.md
vars:
current_user: ${USER_NAME}
```
```yaml
users:
- name: John
role: admin
- name: Jane
role: user
```
@import template.md USER_NAME=John ENVIRONMENT=production
```opts :(document_opts)
user_must_approve: true
save_executed_script: true
menu_ux_row_format: 'DEFAULT %{name} = ${%{name}}'
```
```bash
export MDE_SAVE_EXECUTED_SCRIPT=1
export MDE_USER_MUST_APPROVE=1
```
```yaml
# .mde.yml
save_executed_script: true
user_must_approve: true
menu_with_inherited_lines: true
```
mde --save-executed-script 1 --user-must-approve 1 --config my-config.ymlSee Tab Completion Documentation for installation and usage instructions.
This example demonstrates a complete interactive workflow with UX blocks, dependencies, and cross-document navigation:
```ux :user-setup
name: USER_NAME
prompt: Enter your name
init: Guest
```
```ux :environment
name: ENVIRONMENT
allow:
- development
- staging
- production
prompt: Select environment
```
Prompts the user for both values and generates output.
```bash :setup +user-setup +environment
echo "Setting up for user: ${USER_NAME}"
echo "Environment: ${ENVIRONMENT}"
```
```bash :deploy +setup
if [ "${ENVIRONMENT}" = "production" ]; then
echo "Deploying to production with extra safety checks"
else
echo "Deploying to ${ENVIRONMENT}"
fi
```
```link
file: next-workflow.md
vars:
user: ${USER_NAME}
env: ${ENVIRONMENT}
```
For a complete testing environment with all dependencies, use the Docker testing container:
# Build the test environment
docker build -f Dockerfile.test -t markdown-exec-test .
# Run all tests (RSpec, Minitest, and BATS)
docker run -it markdown-exec-test bash -c 'bundle exec rake test'
# Run individual test suites
docker run -it markdown-exec-test bash -c 'bundle exec rspec' # RSpec only
docker run -it markdown-exec-test bash -c 'bundle exec rake minitest' # Minitest only
docker run -it markdown-exec-test bash -c 'bundle exec rake bats' # BATS tests only
# Enter the container interactively
docker run --rm -it markdown-exec-test bashExecute tests for individual libraries locally:
bundle exec rake minitest
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the MarkdownExec project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
