| id | 80 |
|---|---|
| title | Terminal recording in README |
| status | ✅ |
| summary | Auto-generate a terminal demo GIF via GitHub Actions and embed it in README.md |
The README describes mdsmith's features in text, but a short terminal recording showing the tool in action is more compelling. The recording must stay current — if commands or output change, the GIF should update automatically.
Embed an auto-generated terminal demo GIF in the root
README, placed right after the intro paragraph. A
GitHub Actions workflow regenerates the recording on
every push to main, and PR CI verifies the recording
pipeline works without pushing artifacts.
Use VHS from
Charm. VHS reads a declarative .tape file, drives a
headless terminal, and renders to GIF. It runs in CI
without a display server. Add VHS as a Go tool
dependency in go.mod so it is invoked via
go tool vhs — no separate install step needed.
A VHS tape file at the repo root that cycles through key mdsmith features:
./mdsmith initin a temporary directory — shows config generation without conflicting with the repo's existing.mdsmith.yml./mdsmith checkon a sample file with lint errors — shows diagnostic output with source context./mdsmith fixon the same file — shows auto-fix./mdsmith checkagain — clean pass, exit 0./mdsmith help rule line-length— shows built-in rule docs./mdsmith help rule catalog— shows catalog rule./mdsmith help rule directory-structure— shows directory-structure rule./mdsmith help rule required-structure— shows required-structure rule./mdsmith query 'status: "✅"' plan/— shows front-matter filtering./mdsmith metrics rank --by bytes --top 5 .— shows metrics
Each step has a short pause so viewers can read the output. The tape targets an 80x24 terminal at a comfortable typing speed.
A small Markdown file demo/sample.md with intentional
lint issues (long line, trailing spaces, missing code
fence language). Kept out of normal lint runs via an
ignore entry in .mdsmith.yml so ./mdsmith check .
in CI does not flag it.
The GIF is embedded immediately after the first paragraph (the one-liner description), before the "Why mdsmith" section:
# 🔨 mdsmith
A fast, auto-fixing Markdown linter ...

## ✨ Why mdsmithThe assets/ directory holds the generated GIF. It is
committed to the repo so the image renders on GitHub
without external hosting.
Generate workflow (.github/workflows/demo.yml):
runs on push to main. Steps:
- Checkout repo
- Build mdsmith (
go build -o mdsmith ./cmd/mdsmith) - Run
go tool vhs demo.tape(VHS added as a tool dependency ingo.mod) - Configure git
user.name/user.emailfor the CI bot. Ifassets/demo.gifchanged, commit with a[skip ci]marker and push it back tomain. Add a loop guard (e.g. skip whengithub.actorisgithub-actions[bot]) to avoid retriggering the workflow. Requestpermissions: contents: writeso theGITHUB_TOKENcan push.
This keeps the GIF in sync with the latest CLI output.
PR verification (add a job to .github/workflows/ci.yml):
runs on pull requests. Steps:
- Checkout repo
- Build mdsmith
- Run
go tool vhs demo.tape - Assert
assets/demo.gifwas produced and is a valid GIF (check file header bytesGIF89aorGIF87a) - Assert file size is within a reasonable range (> 10 KB, < 5 MB) to catch broken recordings
- Analyze the GIF content: extract frames, verify
expected command output appears (e.g. grep rendered
text for key strings like
MDS001,./mdsmith check,0 issues found). Use a frame-to-text tool or compare against a set of reference screenshots to catch regressions where the GIF renders but shows wrong or empty output
The PR job does not commit — it only verifies the pipeline succeeds and the output is sane.
- Create
demo/sample.mdwith intentional lint issues for the demo - Write
demo.tapeVHS script that cycles through init, check, fix, help-rule, query, and metrics commands - Create
assets/directory with a.gitkeep - Add the demo GIF embed to
README.mdafter the intro paragraph - Create
.github/workflows/demo.ymlthat builds mdsmith, runs VHS, and commits the updated GIF on pushes tomain - Add a
demojob to.github/workflows/ci.ymlthat runs VHS and validates the output GIF on PRs - Add
demo/to the ignore list in.mdsmith.yml(requires explicit user consent per CLAUDE.md) so the intentionally broken sample file does not fail./mdsmith check . - Test the full pipeline locally: run
go tool vhs demo.tape, verify the GIF renders correctly
-
demo.tapeexists and defines a multi-step demo covering init, check, fix, help-rule (line-length, catalog, directory-structure, required-structure), query, and metrics commands -
demo/sample.mdcontains intentional lint errors that produce visible diagnostics -
README.mdembedsassets/demo.gifbetween the intro paragraph and the "Why mdsmith" section -
.github/workflows/demo.ymlregenerates the GIF on push tomainand commits it if changed - CI job in
.github/workflows/ci.ymlruns VHS on PRs and asserts the GIF is valid (file exists, has a correct GIF header, and falls within a reasonable file size range) -
demo/is excluded from mdsmith linting so the sample file does not cause CI failures - All tests pass:
go test ./... -
go tool golangci-lint runreports no issues