Skip to main content
cargo install slurp-compiler gives you one binary, slurp, with four subcommands:
Nothing takes a positional argument. Every input is a named flag, so slurp build ./site is a usage error and slurp build --input ./site is what you meant.

Warnings and --verbose

Slurp is total and tolerant: a loop past its budget is truncated, a missing property renders empty, and neither aborts the build. Those are recorded as warnings, and slurp build prints warnings only under --verbose.
A build with no -v and no errors tells you almost nothing about whether the page is right.
The same is true of validate, where the flag is spelled --warnings:
The two differ in one detail. validate always prints the warning count in its summary line, even without -w:
build prints no such count. If you never pass -v, a warning leaves no trace at all.

slurp build

Compiles every .slurp file under the input tree and writes HTML for the ones that are pages.
path
default:"."
Directory to compile. The walk skips symlinks, dot-directories, node_modules, dist, target, and the output directory itself however it is spelled.
path
default:"dist"
Where HTML and static assets are written.
path
A JSON file whose top-level keys are seeded into the render context as globals. Named-but-unreadable, or valid JSON that is not an object, is a hard error rather than a silent empty context.
dir
Marks a directory as middleware, relative to --input. Repeatable. Without it, a correct middleware file fails the build. See Middleware below.
flag
Print warnings, plus a line per file showing what was emitted, checked or skipped.

What gets emitted

Not every template becomes a file, and the rule is a blocklist rather than an allowlist of pages/: Components and layouts are still compiled, so a syntax error or a security violation in a component that no page imports yet still fails the build. They are not emitted because a layout rendered on its own is a fragment carrying literal <slot> elements, and nothing can route to it. --verbose shows the split:
A build that emits nothing at all says so on stderr.

Static assets

Every non-.slurp file in the input tree is copied to the output, preserving its relative path. css/site.css becomes dist/css/site.css with no configuration.
The one exception is the file you passed to --globals. It is build input, not a site asset, and copying it would publish it at a guessable path. A globals file you do not pass on that run is copied like anything else.
Output is minified. The quickstart’s two products come out as one line:
dist/index.html

Middleware

Middleware obeys inverted scope rules. request.*, {redirect} and {next} are legal only there, and most other path roots are illegal there. The compiler cannot guess which files those are, because a host may put middleware anywhere, so you tell it:
Leave the flag off and a correct middleware file fails:
The flag is matched on resolved paths, so ./middleware, middleware/ and middleware all name the same directory, and a sibling called middleware-helpers/ is not caught by it. A directory that does not exist selects nothing, which leaves its files checked under the stricter page rules.

slurp validate

Parses and security-checks every .slurp file without writing anything. This is the fast pre-commit gate, and it enforces what a build enforces rather than only what parses.
path
default:"."
Directory to scan. Skips the same things the build walk does: symlinks, dot-directories, node_modules, dist and target.
dir
Identical to the build flag, and required for the same reason.
flag
Print the warnings, not just count them.
Diagnostics carry a code, a message and a file position:
Hold on to the code in brackets. It is what Errors is indexed by, and it is what to pass to the MCP server’s slurp_reference tool when you are working with an agent.
Two things validate does not do: it does not resolve imports across files, so a typo in a component path is not reported here (it renders as a placeholder), and the security walk stops at its first violation per file.

slurp dev

Starts the hot-reload development server on the current directory.
number
default:"3000"
TCP port for both the HTTP server and the reload WebSocket.
string
default:"127.0.0.1"
Accepted and then ignored. Any value other than 127.0.0.1 prints note: slurp-dev binds 127.0.0.1; --bind <value> is ignored. and the server still binds loopback.
path
A JSON file (or a directory holding fixtures.json) mapping a request path to a canned JSON response, so a theme previews with no backend running.
slurp dev is a launcher, not the server. It locates the slurp-dev binary next to itself, falls back to PATH, and passes on only --port and --fixtures. If it cannot find one it exits 127 and tells you how to build it:
The server has more options than these three, and reaching them means running slurp-dev directly. See Dev server.

slurp gitignore

Writes a .gitignore suited to a theme. The section at the bottom lists what must not be ignored, chiefly a compiled stylesheet: ignoring that produces a theme that publishes and renders as unstyled HTML while every static check stays green.
path
default:"."
Directory to write into. A path that is not a directory is an error.
flag
Add the rules to the end of an existing file, under a header saying where they came from. Cannot be combined with --force.
flag
Replace an existing file.
flag
Print the template and write nothing. Checked before everything else, so this works regardless of what is already on disk.
Refusing to clobber is the default. Run it where a .gitignore already exists and it exits 1 with the three ways forward:

Exit codes

slurp dev otherwise exits with whatever the server exited with.
A zero exit from build means no template raised an error. It does not mean the pages are right. See Common mistakes for the failures that produce a clean build and a broken page.

In CI

Run validate first. It fails on the same errors without writing an output tree, so a failing pipeline leaves nothing half-built behind.

Next

Dev server

Fixtures, reloads and security posture.

Working with agents

The MCP server, which answers the same questions without a shell.

Errors

Every diagnostic code, and what to do about it.

Limits

The budgets that truncate rather than fail.