CLI reference
runwisp is one binary with a handful of subcommands. Run it with no
subcommand and it does the friendly thing — attaches to a running daemon,
or scaffolds a config and starts one. Everything else is a verb:
validate, reload, exec, import, and so on. This page is the full
list; each command also prints its own --help.
Global flags
Section titled “Global flags”These apply to every subcommand. They decide which config gets read, where state lives, where the HTTP server listens, and how the daemon logs.
| Flag | Default | What it does |
|---|---|---|
--config, -c | runwisp.toml | Path to the TOML config file, resolved against the working directory. |
--data | .runwisp | Directory for all persistent state — SQLite DB, per-task logs, PID file, Unix socket. |
--port, -p | 9477 | TCP port for the HTTP server (REST API, SSE log stream, Web UI). |
--host | 127.0.0.1 | Bind address. Use 0.0.0.0 to listen on every interface. |
--log-level | info | Verbosity: debug, info, warn, error. Env: RUNWISP_LOG_LEVEL. |
--log-format | auto | Log shape: auto, text, json. Env: RUNWISP_LOG_FORMAT. |
--data is the one to pick once and keep: the database (runwisp.db),
the socket (runwisp.sock), and every task’s logs all live under it, so
moving it later is a plain directory move, not a config change. The two
logging flags get the full treatment in
Logging.
Start the daemon and attach
Section titled “Start the daemon and attach”runwisp # attach a TUI to a running daemon, or scaffold + start onerunwisp daemon # start headless (no TUI) — for Docker, systemd, cronrunwisp tui # attach a TUI to a local daemon over its socketrunwisp tui --url <URL> # attach a TUI to a remote daemon over HTTPBare runwisp is the everyday entry point. If a daemon already owns this
data dir, it opens the TUI against it.
Otherwise — and if there’s no runwisp.toml yet — it offers to scaffold a
starter config, spawns the daemon in the background, and attaches.
If the port is already taken by another RunWisp daemon — one started from
a different data directory — runwisp tells you which datadir and config
that daemon is using and offers to connect to it, or to stop it and launch
here instead. (Pick a different port any time with --port.) When the port
belongs to something that isn’t RunWisp, you get the plain “port in use”
error with hints for finding the culprit.
runwisp daemon is the headless variant for boxes with no terminal: it
starts the scheduler, REST API, and Web UI without the TUI, and exits
non-zero if there’s no config rather than hanging on a prompt nobody can
answer. runwisp tui connects a fresh TUI to a daemon that’s already up,
over the local socket — no password needed. Add --url
(or set RUNWISP_URL) to attach to a daemon over HTTP — a remote host
or a container — logging in with its password; the
TUI tour covers
how that password is read and cached.
Look before you leap
Section titled “Look before you leap”runwisp validate # parse + validate runwisp.toml without starting anythingrunwisp list # show configured tasks and their schedulesrunwisp status # is the daemon alive right now?runwisp validate is the CI-and-pre-commit friend: it loads the config,
prints a short summary (task and service counts, the resolved timezone),
and surfaces the same advisory warnings the daemon would log at boot —
all without touching anything live. runwisp list renders the configured
tasks as a table. runwisp status pings the daemon over its local socket
and prints a short health summary; it also flags when runwisp.toml has
changed on disk since the daemon started.
Run a task now
Section titled “Run a task now”runwisp exec <task> # run a task, stream its output, exit with its coderunwisp exec <task> --daemon # require a running daemon (fail fast if none)runwisp exec <task> --standalone # require in-process (refuse if a daemon owns the dir)runwisp exec runs one task and streams its stdout/stderr straight to
your terminal, exiting with the run’s own exit code — so it slots cleanly
into a script. By default it auto-detects: if a daemon owns this data
dir, the run is dispatched through its REST API and followed live;
otherwise the task runs in this process from runwisp.toml. --daemon
and --standalone pin the choice and are mutually exclusive.
Apply config edits
Section titled “Apply config edits”runwisp reload # re-read runwisp.toml and reconcile the live task setrunwisp restart # stop and start fresh (restart-only settings, run_on_start, catch-up)runwisp stop # shut the daemon downFor the everyday edits — adding, changing, or removing tasks and
services, or tweaking [defaults] — runwisp reload (the same thing as
sending SIGHUP) re-reads the file and reconciles the running task set in
place. It’s validate-first: a config that won’t parse, fails validation,
or touches a restart-only setting is rejected and your running daemon
keeps going untouched. In-flight runs finish under the definition they
started with. The Reload page has the full rules.
runwisp restart is the heavier hammer: it stops the daemon and starts a
new one, which is what you need for the restart-only settings ([daemon],
the scheduler timezone, [storage], [notify], the bind host/port) and
when you want a fresh boot to re-fire run_on_start and missed-run
catch-up. runwisp stop takes the daemon down without starting a new one.
When the daemon is managed by systemd or launchd (via
runwisp service install), both restart and
stop delegate to the service manager so its view of the unit stays in
sync.
Migrate an existing setup
Section titled “Migrate an existing setup”runwisp import cron [FILE] # convert a crontab to runwisp.tomlrunwisp import supervisord [FILE...] # convert a supervisord config to runwisp.tomlBoth read from a file or from stdin, print the generated TOML to stdout
so you can review it, and write a # TODO comment for anything that
doesn’t map cleanly — nothing is silently dropped. Shared flags:
| Flag | What it does |
|---|---|
--output, -o | Write the TOML to this file instead of stdout. |
--write | Write to the --config path (default runwisp.toml). |
--force | Overwrite the target file without prompting. |
--quiet | Suppress the summary on stderr. |
--system | (cron only) Force system-crontab parsing (the user column). |
System crontabs (/etc/crontab, /etc/cron.d/*) carry a user column;
runwisp import cron detects that from the path or header and maps it to
a per-task user. The
Migrating from cron and
Migrating from supervisord recipes
walk through the whole flow.
Autostart
Section titled “Autostart”runwisp service install # wire up systemd (Linux/WSL) or launchd (macOS)runwisp service uninstall # remove the unit/plist (data dir is preserved)runwisp service status # is autostart wired up, and has anything drifted?These wire the daemon into the host init system so it survives a reboot —
OS plumbing only, never touching runwisp.toml. install takes --yes
(-y), --print (render the unit to stdout), --dry-run, --force
(overwrite a hand-edited unit), --system (a system-wide unit on Linux),
and --binary <path> (override the baked-in binary path). uninstall
takes --yes, --force, and --purge (also delete the data dir — which
makes you type the literal word delete to confirm). It’s all covered in
depth on the Autostart page.
Don’t confuse runwisp service status (“will the daemon come back after a
reboot?”) with runwisp status (“is it alive right now?”).
Auth and introspection
Section titled “Auth and introspection”runwisp password # print the daemon's ephemeral password (local socket only)runwisp openapi # print the OpenAPI 3.1 spec (JSON) to stdoutrunwisp password fetches the in-memory ephemeral password over the
local socket — handy when you want to log in from another device. It
prints in plaintext, so pipe it to a clipboard tool (runwisp password | wl-copy) to keep it out of your scrollback. If the daemon uses a fixed
RUNWISP_PASSWORD it refuses (that
value is never disclosed); if it runs with
RUNWISP_NO_AUTH there’s
no password at all and the command exits with a distinct code.
runwisp openapi dumps the OpenAPI 3.1 schema to stdout for feeding into
code generators — the same schema a running daemon serves at
/openapi.json.
Cloud and demo
Section titled “Cloud and demo”runwisp cloud # connect to the optional control plane instead of scheduling locallyrunwisp demo # boot a throwaway, fully-populated instance to explorerunwisp cloud starts the daemon connected to the optional control plane;
it needs RUNWISP_CLOUD_TOKEN (via env, .env, or --token) and takes
--url and --env-file (default .env), plus --no-tui for headless.
runwisp demo boots RunWisp against a temporary config and data dir
pre-seeded with hundreds of historical runs, so you can poke around the
TUI and Web UI without writing a config — everything lives in a temp
directory that’s deleted when the daemon stops. It takes --cloud (and
the same --token / --url / --env-file) to point at the control plane
instead of seeding local history. Pass --no-tui to leave the daemon
running in the background and print its Web UI password to stdout instead
of opening the TUI — handy over SSH or in a script where you just want to
open the Web UI in a browser; stop it later with runwisp stop --data <dir>
(the demo prints the exact data dir alongside the password).
Environment variables
Section titled “Environment variables”| Variable | What it does |
|---|---|
RUNWISP_PASSWORD | Sets the daemon password in memory. Unset, a fresh ephemeral one is minted every boot. See Auth. |
RUNWISP_NO_AUTH | 1 or true disables authentication entirely — local dev / trusted networks only. Mutually exclusive with RUNWISP_PASSWORD. See Auth. |
RUNWISP_TRUST_PROXY | Comma-separated CIDR list of reverse proxies whose X-Forwarded-* headers the daemon may honor. |
RUNWISP_CLOUD_TOKEN | Token for runwisp cloud. Ignored in standalone mode. |
RUNWISP_CLOUD_URL | Control-plane URL for runwisp cloud (overrides the built-in default). |
RUNWISP_LOG_LEVEL | Fallback for --log-level (debug/info/warn/error). The flag wins when both are set. |
RUNWISP_LOG_FORMAT | Fallback for --log-format (auto/text/json). The flag wins when both are set. |