tw
One command for a Markdoc corpus: lint it, format it, serve it to an editor, preview the site and build the PDFs, with the same tools at the same versions on every writer's machine and in CI.
tw links the rules — markdoc-lint
for structure, markdoc-prose for
prose — and launches the rest at the versions the corpus pins:
markdoc-ls, markdoc-pdf and the
corpus's site generator.
Install
Download the binary for your platform from the
latest release, each with a
.sha256 beside it, and put it on your PATH:
| Platform | Asset |
|---|---|
| Linux (x86-64) | tw-linux-x86_64 |
| Windows (x86-64) | tw-windows-x86_64.exe |
| macOS (Apple Silicon) | tw-macos-aarch64 |
| macOS (Intel) | tw-macos-x86_64 |
After that, tw update replaces it with the newest release. To build it from
source instead:
cargo install --git https://github.com/markdoc-rs/tw
Getting started
In a corpus, a directory with .tooling/ at its root:
tw setup # install the git hooks and fetch the pinned tools
tw check # lint the whole corpus, structure and prose
Commands
| Command | What it does |
|---|---|
tw check [PATH]... |
Lint the structure and the prose, and report both together. The whole corpus when no path is given. --no-prose for structure only, --staged for what git has staged, --json for CI and editors, --list-rules for what the corpus has turned on. Exits 1 when it finds something. |
tw setup |
Install the git hooks and fetch the pinned tools. Safe to re-run; --no-tools downloads nothing. |
tw update |
Replace this binary with the newest release, then re-pin the tools. |
tw fmt [ARGS]... |
Format the tags, with the pinned markdoc-ls. |
tw lsp |
Run the language server, the pinned markdoc-ls. |
tw preview |
Build and serve the site locally, with the generator tw.toml names under [preview]. |
tw build |
Render the manuals, with the pinned markdoc-pdf. |
tw completions <SHELL> |
Print a completion script for bash, zsh, fish, elvish or PowerShell. |
tw <name> |
Run tw-<name>, from PATH or the corpus's pinned tools, as git runs git-<name>. |
tw help lists them, and tw <command> --help says more about each.
The hooks tw setup installs, in .githooks/ through core.hooksPath, run
tw check --no-prose --staged before a commit and tw check --no-prose
before a push. The prose pass is left to CI: it is too slow for a hook.
The corpus
tw works from the corpus root: the nearest directory at or above where it
runs that holds .tooling/, or else tw.toml or markdoc-lint.toml. There
it reads:
.tooling/tooling-versions.json: the version pinned for each tooltwlaunches, and the forges they are released on. Downloads go to.tooling/bin/and are checked against their.sha256.tw.toml: what the corpus adds.[preview]names its site generator,[tools.<name>]other pinned programs, and[[check.external]]checks thattw checkruns and reports with its own.markdoc-lint.tomlandmarkdoc-prose.toml: the rules' configuration..env: a writer's own credentials, such as a token for a private forge. It is used only when git ignores it.
A tool tw launches is looked for in this order: the path in its environment
variable (MARKDOC_LS, MARKDOC_PDF, or <NAME>_BIN for one from
tw.toml), .tooling/tools/, a sibling checkout's target/release (such as
../markdoc-ls), the pinned release, and last PATH.
Building
cargo build --release
bash .github/scripts/check.sh # the gate CI runs: fmt, clippy, tests, a release build
Licence
MIT