Skip to content

Getting started

waypost finds every task the tools in a repository already define — moon, just, package.json scripts, make, cargo and the rest — and puts them in one searchable list. It is built on

@sksizer/detect-runners

, which does the finding; waypost is the part you look at.

bun add -g @sksizer/waypost

This installs two binaries pointing at the same tool: way, the short one to type, and waypost, the full one for when something else on your PATH already answers to way.

Working on the tool itself? The installed binary follows the checkout you are standing in, and dev link points it at one from anywhere — see Running from a checkout.

waypost needs Bun 1.2 or later — the engines.bun field in its package.json says so, and it means it. The web view is built on Bun.serve, and the page’s own copy of the matcher is transpiled on demand by Bun.build. A Node entry point would give you a working terminal UI and a --serve that crashes, which is worse than asking for the runtime up front.

If you only need the data — no UI at all — the library’s own detect-runners CLI runs anywhere Node or Bun does.

With no arguments, way inspects the current directory and opens the terminal UI:

way

The directory is resolved upward to the project root, so running from a subdirectory still inspects the whole repository — the same thing moon and just already do for their own configuration.

way               # the terminal UI; Enter runs the selected task
way --serve       # the same catalog as a live page in the browser
way query dev    # the tasks matching a search, best match first
way --json        # the data, for anything else
  • The terminal UI (no flags) is the interactive browser — see The terminal UI.
  • --serve opens a live page over the same catalog — see The web view.
  • query is the terminal UI’s search without the UI: it ranks the catalog with the same matcher and prints one command line per match. Terms are ANDed and matched fuzzily, --exact makes every term match as a substring instead, --services keeps only the tasks that run until you stop them, and --json prints the matching tasks rather than their command lines. A search that matched nothing exits 1, so way query dev && … works from a script.
  • --json prints the whole catalog as JSON and exits, with no UI. --list prints one command per line instead, for piping. Both re-probe every run, so a script gets what the repository has right now; --cached answers them from the last stored probe instead — see The cache.
query <terms> the tasks matching a search, best match first
--exact with query: terms match as substrings, not subsequences
--services with query: only tasks that run until you stop them
--port N fixed port for --serve (default: an OS-assigned one)
--no-open print the URL rather than opening a browser
--cached answer --json/--list from the last stored probe
--no-exec skip runners that must run a subprocess (moon)
--exec allow them for this run only, without recording trust
--only a,b restrict to these runners
--exclude a,b skip these runners
--exclude-path P leave a path out of discovery (repeatable)
--discovery M git | walk | auto (default: auto)
-C, --dir PATH the directory to inspect (default: cwd)
-h, --help the short form: the ways in, and where the rest is
--help --all the block above, every default and every note
config read and write the layered settings file
trust allow this repository's runners to be read by running them

--help prints the short form — the ways in, the two flags most invocations pass, and the names of everything below it. --help --all prints the complete flag list, each subcommand answers for itself with its own --help, and way guide is the long form, by topic. A usage error prints the short form too: a tool that answers a mistyped flag with its whole surface makes the reader hunt for the error.

Reading some runners means running them — moon reads its build graph by running moon query, which evaluates that repository’s own toolchain configuration. way defaults to being willing to do that, since you are usually standing in your own repository, but willingness is not the whole gate. The repository must also be trusted, once, and

way trust is what records that. Until then those runners are withheld and the screen says so.

--exec is the one-run escape hatch: it allows them for this invocation and records nothing, which is what scripts and CI want. --no-exec forbids them however trusted the repository is, and a configuration file can turn them off by default too. See Trust & execution for the full gate and Configuration for the precedence order, and The terminal UI / The web view for what each interface adds on top of these flags.