This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
numd is a Nushell module for creating reproducible Markdown documents. It executes Nushell code blocks within markdown files and writes results back to the document.
# Run numd on a markdown file (updates file with execution results)
use numd; numd run README.md
# Preview mode (output to stdout, don't save)
use numd; numd run README.md --echo
# Run tests (executes all example files and reports changes)
nu toolkit.nu test --json
# Clear outputs from a markdown file
use numd; numd clear-outputs path/to/file.md
# Strip markdown to get pure Nushell script
use numd; numd clear-outputs path/to/file.md --strip-markdown --echo- mod.nu: Entry point exporting user-friendly commands (
run,clear-outputs, etc.) - plumbing.nu: Low-level pipeline commands for advanced usage/scripting
- commands.nu: Core implementation containing all command logic
- capture.nu:
capture start/stopcommands for interactive session recording - parse-help.nu:
parse-helpcommand for formatting --help output - parse.nu: Frontmatter parsing utilities (
parse-frontmatter,to md-with-frontmatter) - nu-utils/: Helper utilities (
cprint.nu,str repeat.nu)
Low-level composable commands (import via use numd/plumbing.nu):
use numd/plumbing.nu
# Parse markdown file into blocks table
plumbing parse-file file.md
# Strip output lines (# =>) from blocks
plumbing parse-file file.md | plumbing strip-outputs
# Execute code blocks and update with results
plumbing parse-file file.md | plumbing execute-blocks --save-intermed-script temp.nu
# Render blocks table back to markdown
plumbing parse-file file.md | plumbing strip-outputs | plumbing to-markdown
# Extract pure Nushell script (no markdown)
plumbing parse-file file.md | plumbing strip-outputs | plumbing to-numd-scriptThe high-level commands use these internally:
run=parse-file | execute-blocks | to-markdownclear-outputs=parse-file | strip-outputs | to-markdown
-
parse-markdown-to-blocks: Parses markdown into a table classifying each block by type (text,```nushell,```output-numd) and action (execute,print-as-it-is,delete) -
decorate-original-code-blocks+generate-intermediate-script: Transforms executable code blocks into a temporary.nuscript with markers for output capture -
execute-intermediate-script: Runs the generated script in a new Nushell instance, capturing stdout -
extract-block-index+merge-markdown: Parses execution results using#code-block-marker-open-Nmarkers and merges them back into the original markdown structure
Blocks support fence options (e.g., ```nushell try, no-output):
no-run/N: Skip executionno-output/O: Execute but hide outputtry/t: Wrap in try-catchnew-instance/n: Execute in separate Nushell instanceseparate-block/s: Output results in separate code block instead of inline# =>run-once: Execute code block once, then set tono-run
- Code blocks are split by blank lines (double newlines) into command groups
- Each command group is executed separately via
split-by-blank-lines - Lines starting with
# =>contain output from previous command group - Plain
#comments are preserved;# =>output lines are regenerated on each run - Use
separate-blockfence option to output results in a separate code block instead of inline# =>
# Run all tests (unit + integration)
nu toolkit.nu test
# Run only unit tests (nutest-based, tests internal functions)
nu toolkit.nu test-unit
# Run only integration tests (executes example markdown files)
nu toolkit.nu test-integration
# All commands support --json for CI
nu toolkit.nu test --jsonUnit tests use nutest framework. Tests import internal functions via use ../numd/commands.nu * to test parsing and transformation logic directly.
The test-integration command:
- Runs all example files in
z_examples/through numd - Generates stripped
.nuversions inz_examples/99_strip_markdown/ - Runs
numd run README.mdto update README with latest outputs - Reports Levenshtein distance and diff stats to detect changes
Example files serve as integration tests - use both the Levenshtein stats and git diff to verify changes.
Some files legitimately differ on each run due to:
- Dynamic content:
git tagoutput in README.md (version changes over time) - Nushell version changes: Error message formatting, table rendering differences
A zero levenshtein_dist for most files + expected diffs in dynamic content files = passing tests.
By default, numd runs intermediate scripts with nu -n (no config files) for reproducible output across different systems. Use --use-host-config to load host's env, config, and plugin files when needed.
Use --eval to prepend Nushell code to the intermediate script:
# Inline code
numd run README.md --eval '$env.numd.table-width = 80'
# From config file
numd run README.md --eval (open -r z_examples/numd_config_example1.nu)Example config file (z_examples/numd_config_example1.nu):
$env.config.table.mode = 'rounded'
$env.numd.table-width = 100 # optional: set custom table width- Do not squash commits when merging PRs - preserve individual commit history