CLI

| Command | What it does |
|---|---|
lazycomd serve |
Run the daemon in the foreground |
lazycomd ls |
Name, state, pid, uptime, restarts |
lazycomd start <name> [-d] [--wait 30s] |
Start; -d starts dependencies first, --wait blocks until ready |
lazycomd stop <name> |
SIGTERM the process group, SIGKILL after 10s |
lazycomd restart <name> |
Stop then start |
lazycomd logs <name> [-n N] [-f] |
Show or follow output |
lazycomd reload |
Re-read the config and apply the diff |
lazycomd run <name> |
Start with dependencies, follow output, stop on Ctrl-C |
lazycomd port [N] |
Who is listening, and which command owns it |
lazycomd doctor |
Check the catalog for what will fail to start |
lazycomd files [add <dir>] |
Directories whose lazycomd.yaml is read |
lazycomd group start\|stop\|restart <name\|-> |
Act on every command carrying a group |
lazycomd mcp |
Serve the Model Context Protocol on stdio — see Agents |
lazycomd version |
Print the build version |
A name that is not exact matches on a unique prefix, so lazycomd logs tool
finds toolweb. An ambiguous one lists the candidates and exits 1. Flags may
come before or after the command name: logs api -f and logs -f api both
work.
lazycomd run on a command that is already running attaches to its output and
leaves it running on Ctrl-C — it only stops what it started.
Exit codes: 0 success, 1 daemon or client error, 2 usage error.
Start and wait for it
start returns as soon as the process spawns, which is too early to run
anything against it. --wait holds until the command is actually ready:
lazycomd start api --wait 30s && npm test
Ready means its health: URL answers 2xx; with no health URL, that its
port: accepts a connection; with neither, that it is running. A command that
exits while starting fails immediately rather than at the deadline, and the
daemon caps the wait at two minutes.
The daemon does the waiting, not the CLI — the health URL and the port are on the daemon’s machine, which is not always yours.
ls draws the same grouping the TUI does — a heading per group: label, the
commands carrying it underneath:
$ lazycomd ls
NAME STATE PID UPTIME RESTARTS
console
mdm-console:toolweb running 814 3m12s 0
databases
proxy:aviron-db-alpha-dev running 792 4m01s 0
A catalog where nothing sets a group stays flat. - is the commands with no
group.
Who owns this port
$ lazycomd port 3000
PORT ADDR PID PROCESS COMMAND
3000 127.0.0.1 41022 node app:web
The COMMAND column is the lazycomd command that owns the listener, by
process group, or - for anything else on the machine. With no port, it lists
every listener.
What is about to break
$ lazycomd doctor
error port 8080 is claimed by [api web]
error worker: cwd does not exist: /Users/me/old-checkout
warn the directory ~/coding/app is gone, so its commands are not loaded
It reports the mistakes that only ever show up as a process that will not
start: a program that is not on the daemon’s PATH, two commands claiming one
port, a depends_on naming nothing, a cwd that moved, a listed directory
that is gone. An error exits 1 so a script can gate on it; a warn does not.
The PATH it checks against is the daemon’s, not your shell’s — those differ under launchd and systemd, which is the whole reason a command can run in your terminal and fail here. See what a command inherits.
JSON
ls, start, stop, restart, logs, port, doctor, files and
group all take --json, so the CLI is usable from something other than a person:
$ lazycomd ls --json | jq -r '.[] | select(.state=="failed") | .name'
app:worker
$ lazycomd doctor --json | jq '[.[] | select(.level=="error")] | length'
2
Empty results are [], never null. logs --json returns
{"name":..., "lines":[...]}; following and JSON do not mix, so --json
wins and returns the buffer as it stands.