---
title: Units
---
# Units
A unit is the shortest path from an ad-hoc command to systemg supervision. Use
one when you want systemg to manage a database tunnel, development server,
watcher, script, or other command without writing a project manifest first.
```bash
$ sysg start --daemonize --name db-tunnel -- sh db-tunnel.sh
```
When `--name` is omitted, systemg generates a unit name from the command.
<Info>
**Staging is translation.** systemg writes your command as a generated
version 2 manifest—the format its central supervisor understands for every
service and project. The generated unit is project-less, so the supervisor
manages it in the `__loose__` bundle. Its command runs from the directory
where it was staged, even though the generated manifest lives elsewhere.
</Info>
## From command to running unit
`sysg start -- <command...>` always stages the command first. What happens next
depends on whether a supervisor already exists:
- **No supervisor is running:** the staged manifest starts a new supervisor and
the unit runs immediately.
- **A supervisor is already running:** systemg writes the manifest but leaves
the live supervisor unchanged. The unit has been staged, but it is not yet
registered and no process has started for it.
<Info>
The explicit apply step protects the supervisor's live topology. An ad-hoc
command cannot silently add work while the supervisor is managing other
services and projects. Applying the staged manifest gives systemg a clear
point to validate it and reconcile it into the live state.
</Info>
For a resident supervisor, systemg prints the exact command required to apply
the unit:
```text
Unit staged at ~/.local/share/systemg/units/db-tunnel-<hash>.yaml.
Run `sysg start --daemonize --config ~/.local/share/systemg/units/db-tunnel-<hash>.yaml` to apply it.
```
Run that printed command, then inspect the unit normally:
```bash
$ sysg start --daemonize --config ~/.local/share/systemg/units/db-tunnel-<hash>.yaml
$ sysg status
$ sysg logs --service db-tunnel
$ sysg stop --service db-tunnel
```
## Common examples
Run a shell script under supervision.
```bash
$ sysg start --daemonize -- sh foo.sh
```
Keep a lightweight HTTP server alive.
```bash
$ sysg start --daemonize -- python3 -m http.server 8080
```
Tail application logs under supervision.
```bash
$ sysg start --daemonize -- tail -F ./logs/app.log
```
Run a frontend development server.
```bash
$ sysg start --daemonize -- npm run dev
```
Run a backend API in reload mode.
```bash
$ sysg start --daemonize -- uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
```
Run a worker with explicit queue and concurrency settings.
```bash
$ sysg start --daemonize -- sh -lc 'QUEUE=critical CONCURRENCY=4 ./bin/worker'
```
Run a live TypeScript watcher and build loop.
```bash
$ sysg start --daemonize -- sh -lc 'pnpm install && pnpm run dev:watch'
```
Run a periodic heartbeat loop.
```bash
$ sysg start --daemonize -- sh -lc 'while true; do date; sleep 30; done'
```
Run a composed multi-step local pipeline.
```bash
$ sysg start --daemonize -- sh -lc 'pnpm db:migrate && pnpm run seed && pnpm run start:prod'
```
## Where staged units are stored
Generated unit manifests are saved under:
```bash
~/.local/share/systemg/units/*.yaml
```
systemg prunes manifests older than 30 days and retains the newest 200 files
when it stages new units.
<Warning>
Treat this directory as staging space. For a long-lived unit, copy its
generated manifest to a durable path before applying it, then pass that path
to `sysg start --config`. The registered path becomes the supervisor's
source of truth for later restarts.
</Warning>
Once applied, a unit's runtime state—PIDs and service lifecycle state—persists
under `~/.local/share/systemg/projects/__loose__/`. See
[State](/how-it-works/state).