docs · pre-release
Menu
Start here / Getting started

Getting started

shep is one binary. Running it starts a daemon called the shepherd, which keeps a flock of your long-running processes alive. This page takes you from an install to a running flock.

careful

shep is pre-1.0, so anything here can still change. macOS, Linux and Windows all work; the Windows tier is newer, and two limits are worth knowing before you rely on it — shep stop has no graceful signal to send unless your app reads the shepherd channel, andshep startup is not built there.

1. Install it

$ cargo install shep
$ shep --help

Prefer to build it yourself, or want to hack on it?

$ git clone https://github.com/shep-pm/shep.git
$ cd shep
$ cargo build --release
$ ./target/release/shep --help

Rust 1.88 or newer, edition 2024, if you build from source. Puttarget/release/shep on your PATH, or keep typing the full path. Everything below works either way.

Two more things that belong to this step.shep completions <shell> prints a completion script for bash, elvish, fish, powershell or zsh, to redirect wherever your shell reads them from. It completes verbs and flags and stops there: sheep names, fold names and anything else the shepherd knows are never completed, because the script never talks to one. Andshep welcome reprints the greeting a fresh$SHEP_HOME shows once on its own: the sheep, the home it set up, and the five commands worth knowing.

Upgrading later

cargo install shep replaces the binary on disk. It does not touch anything already running: the shepherd keeps the code it booted with until you reload it, and each dog keeps its own until you reinstall it separately.

$ cargo install shep
$ cargo install shep-log-rotate # and every other dog
$ shep daemon reload

A flock that can be carried keeps running through the reload. The shepherd replaces its own image in place, so every sheep keeps the pid it already had and its log carries on where it was. The dogs cross with it rather than being stopped and started alongside the flock; the dogs page says what each one does on the far side. One that cannot be carried is stopped and started instead, which moves every pid and starts every log again; the note below says which flocks those are.

If a dog cannot talk to the new shepherd, the reload names it. It waits for the dogs to reconnect first, so the answer is about the shepherd now running, not the one it replaced.

One thing still sends a reload down the older path: a sheep whose log pump has stopped answering. The shepherd cannot say which files that sheep is writing to, so it stops and starts the flock instead and names the sheep that held it back. Coming from 0.1.17 or earlier, the first reload always takes that path too: the shepherd being replaced predates the handover and has nothing to hand over with.

careful

Skip shep daemon reload and the new binary answersshep --version while the running shepherd is still the old one. shep refuses most verbs against a version-skewed shepherd and names this exact command as the fix.

2. Write a Flockfile

Two fields is a complete one. Flockfile.toml,.yaml, .json and .json5 all work. shep start below takes the path explicitly;shep runtime and shep dev can find one on their own instead, by searching ten filenames in a fixed order: seeYour first Flockfile.

Flockfile.toml
[[app]]
name   = "web"
script = "./server"
note

Unknown fields are a parse error, not a shrug. A typo tells you at load instead of at 3am. Durations and sizes are strict on purpose:512M and 30s parse; 512MB,1.5G and 30S do not.

Scripts that need an interpreter

script is run directly, so a compiled binary or a file with a shebang and the executable bit needs nothing further. A plainserver.js has neither, and shep will not guess: guessing is how a process manager ends up with opinions you did not ask for.

Instead you tell it once. On first run shep writes a starter mapping into ~/.shep/shep.toml, commented so you can see exactly what it will do:

~/.shep/shep.toml
[interpreters]
js = "node"
py = "python3"
sh = "sh"

From then on shep start server.js works. Edit the table, add an extension, or delete the whole thing to turn it off. An individual app can override it with its owninterpreter field, and a single run can override both with --interpreter; the last one named wins.

3. Start the flock

You never launch the daemon yourself. shep start notices nothing is listening and re-execs itself in the background.

$ shep start Flockfile.toml
$ shep ls
ID NAME STATUS PID RESTARTS EXIT CPU MEM UPTIME FOLD
1   web    online  1001  1         12.5%  48.1M  1m      backend
2   worker online  1002  2         12.5%  48.1M  2m      backend
3   cron    online  1003  3        -      48.1M  30s    backend

Shown plain here. At a real terminal that table is box-drawn, each status is coloured and carries a sheep's face, and columns drop as the window narrows; piped anywhere else it prints exactly what you see above. Terminal output covers all of it, including how to turn it down.

The CPU column prints - rather than 0.0% when a reading is unavailable, because a confident zero is worse than an obvious blank. EXIT uses the same convention, and shows why a stopped sheep stopped.

4. Watch what it prints

shep bleats follows the logs; --no-followprints the tail and exits. If you prefer the boring word,shep logs is the same command and always will be.

shep bleats
same as shep logs
shep flock
same as shep list / ls
shep muster
same as resurrect
shep thatlldo
same as graceful stop

5. Pipe it somewhere

Every command renders as --format json too, under a versioned envelope, so nothing has to scrape columns.

"schema_version": 1, "command": "flock", "data": [ { "id": 1, "name": "web", "status": "online", "pid": 1001, "restarts": 1, "uptime_ms": 60000, "fold": "backend", "cpu_percent": 12.5, "memory_bytes": 50462720, "dog": null } ] }

Where to go next