start
Bring the-loop up: one command that reads the CLI config and starts, detached, every service it enables (issue-228, decision-084).
the-loop start| Service | Enabled by | Default |
|---|---|---|
| Control-plane service (REST + dashboard) | service.enabled | on |
MCP endpoint (/mcp, mounted on the service) | service.mcp.enabled | on |
| GitHub webhook receiver | webhooks.ghWebhook.enabled | off |
| Poller | polling.enabled | off |
The ingresses are explicit opt-ins: a config that merely describes a receiver or a polling source must not open a port or start a loop. start prints one line per service — started, hosted (see below), already-running (start is idempotent), disabled (naming the key that enables it), misconfigured (an enabled poller with no polling.sources), or failed (pointing at the service's logfile) — and exits 0 only when every enabled service came up. One service failing never hides the others' outcomes.
One process by default
With the service enabled and service.hostIngresses at its default (true, issue-231), start boots one process: the service, which runs the enabled ingresses as background threads inside its own lifespan. Each hosted ingress still holds its own pidfile lock — under the service's pid — so status, stop and the daemons API answer unchanged, and an ingress already running standalone is skipped with a warning, never fought over.
$ the-loop start
service started [enabled] started at http://127.0.0.1:4114; /mcp exposed
gh-webhook hosted [enabled] in the service process (pid 24846)
poller hosted [enabled] in the service process (pid 24846)Set hostIngresses: false to keep every enabled service in its own process (fault isolation). Then each daemon is spawned detached (its own session, output to its logfile under state.root):
$ the-loop start
service started [enabled] started at http://127.0.0.1:4114; /mcp exposed
gh-webhook disabled [disabled] webhooks.ghWebhook.enabled is false
poller started [enabled] spawned pid 24913; logging to .the-loop/logs/poller.outIn either mode start waits for the proof that a service is genuinely up — the service's /health, an ingress's pidfile lock — before reporting success.
Foreground and cron forms
start composes daemons; it does not host one in your shell. For a supervisor (systemd Type=simple) or a cron job, run the daemon entry point directly:
python -m the_loop.daemon_entry poller # foreground run loop
python -m the_loop.daemon_entry poller --once # one poll cycle and exit (cron)
python -m the_loop.daemon_entry gh-webhook # foreground receiverThese replace the removed the-loop poll start [--once]; the run loop itself is unchanged (lock, dependency checks, heartbeat, config hot-reload).
See also
stop·status·restart- The control-plane service and the webhook receiver — what each service is and how to talk to it (
/mcp, verification, guards). The granularservice/gh-webhook/pollcommands are gone (owner review on PR #229): this one surface is the lifecycle.