systemg 0.58.2

An agent-friendly general process composer.
Documentation
---
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).