| name | services-user |
| description | Operate the `services` multi-backend supervision
frontend — create / start / stop / restart / status /
monitor services across daemontools, runit,
systemd-user, and launchd. Trigger when the user
wants to add a long-running daemon, manage user-mode
services, debug a flaky supervisor entry, or learn
the shared-run-script abstraction.
|
services-user skill
1. Design principles
- Educational. Reading
bin/services end-to-end
teaches the shared run-script convention and how
it maps onto each supervisor.
- Functional. Every verb is a thin shell over the
underlying supervisor's CLI.
- Decentralized. Per-user services; no central
service registry.
- Simple.
services calls only account at
runtime (for platform detection).
2. The model
A service is a directory with at least:
~/service/<name>/
run # the script the supervisor invokes
finish # (optional) cleanup hook
log/run # (optional) per-service logger
Backends:
| Platform | Supervisor | What services writes |
|---|
| Linux (alpine) | runit | the directory as-is |
| Linux (modern) | systemd-user | a wrapper .service unit |
| Linux (legacy) | daemontools | the directory as-is |
| macOS | launchd | a wrapper .plist |
The user writes one run script; services makes it
work on whichever supervisor is local.
Per FEAT-091, the multi-backend abstraction is the
core deliverable. Per FEAT-092, hook, healthcheck,
and depends verbs are filed; FEAT-094 vendors each
supervisor's reference docs.
3. Workflow recipes
-
Initialise the per-user service tree.
services init
-
Create a new service.
services create my-daemon
cat > ~/service/my-daemon/run <<'EOF'
#!/bin/sh
exec /usr/local/bin/my-daemon --foreground
EOF
chmod +x ~/service/my-daemon/run
-
Bring it up.
services start my-daemon
-
Inspect.
services list
services status my-daemon
services has my-daemon
-
Stop / restart.
services stop my-daemon
services restart my-daemon
-
Stream supervisor events.
services monitor
-
Run a hook (FEAT-092 — pending).
services hook my-daemon pre-up
services hook my-daemon post-up
4. Guardrails
run must be exec-final. Anything after
exec doesn't run; daemontools/runit relaunch on
exit, so background-forking daemonisers fight the
supervisor.
- Don't share names with system services. A
service named
nginx collides with the system
nginx unit on systemd; namespace yours
(my-nginx).
services start is non-blocking. It signals
the supervisor; verify with
services status <name> before assuming.
- Backend differences leak occasionally. A
run
script that uses bash here-docs may hit
/bin/sh on alpine. Test on the target backend.
- Health checks and depends aren't implemented
yet (FEAT-092 pending). Wait for that ticket if
you need ordered start.
5. Where to read more
man services
share/doc/services/standards/README.md — links to
daemontools, runit, systemd-user, launchd manuals
- This package's
CLAUDE.md