How It Works
Projects
A project is a durable namespace that groups a set of services. Its identity
is its id — the key under the projects: map in your manifest. Because a single
resident supervisor can host many projects at once — and a single config file
can declare many projects — projects are how systemg keeps unrelated (or
related) workloads cleanly separated inside one running daemon.
Info
One supervisor, many projects. You can run a database stack, a web API, and a
batch of cron units as three independent projects under the same systemg
process. They share the runtime but keep separate state, logs, and status —
and you target each one by id with -p/--project.
Declaring a project
Projects live under the projects: map, keyed by id. One file can declare many:
version: "2"
projects:
arbitration:
name: Arbitration
services:
worker:
command: "python worker.py"
gamecast:
services:
api:
command: "python api.py"
Each key is the project id. Start the whole file and all its projects boot; the first project becomes the primary and the rest register behind it. See Configuration for the full schema.
Warning
Treat the project id as durable runtime identity. Changing it does not rename a
project — it creates a new namespace, and the old one's running services
become orphaned state (visible under sysg status --all). Rename freely with
name; never rename by editing the id.
Note
Top-level services: with no project form a loose bundle — they still run,
and their state persists under projects/__loose__/. The older singular
project: block still parses (with a deprecation warning) for existing
single-project manifests; convert them with
sysg migrate. Prefer the projects: map
once more than one project shares a supervisor.
-p/--project vs -c/--config
These two flags answer different questions, and knowing which to reach for is the single most useful thing about projects.
| Flag | What it does |
|---|---|
-c / --config | Loads and registers the config file on disk — every project it declares, plus any loose bundle. Use it the first time you start, or when you want to reload the manifest from a specific path. |
-p / --project | Targets a single project already registered with the running supervisor, by its id. No file path required. |
The mental model: -c is bring this file's projects into the supervisor from
disk; -p is act on one project the supervisor already knows about.
Info
-c <file> operates on the file as a whole. sysg status -c stack.yaml shows
every project the file declares, not just the first — the file identifies
"everything here," and -p narrows to one.
# First start: register the project from its config
$ sysg start -c services/arbitration.yaml
# From now on, target it by id — no config path needed
$ sysg status -p arbitration
$ sysg logs -p arbitration -s worker
$ sysg restart -p arbitration
$ sysg stop -p arbitration
Info
Every registered project stores the config path it was started from. That's
why -p alone is enough for later commands — systemg looks up the project's
recorded manifest for you. This is what makes multi-project workflows
ergonomic: you register once with -c, then drive everything by -p.
How -p relates to sysg restart
restart -p <id> is where the stored config path pays off:
$ sysg restart -p arbitration
When --config is omitted, restart --project reuses the config path the
supervisor already recorded for that project and reloads it from disk. Manifest
changes are applied on reload:
- services added since the last load start
- services removed from the manifest stop
- changed commands take effect
You do not need to pass -c again once the project has a known config path.
Pass -c explicitly only when you want to reload from a different file.
Warning
If the config you point at declares a different project.id than the one you
target, systemg refuses the operation rather than silently switching
namespaces. The flag, the config, and any service selector prefix must all
agree on the project.
Qualified service selectors
Anywhere you name a service, you can qualify it with its project using
project_id/service_name:
$ sysg restart -s arbitration/worker
$ sysg logs -s gamecast-dev/api
This is equivalent to passing -p plus the bare service name. If you supply
both a selector prefix and -p, they must match.
Warning
A mismatch is an error, not a best-effort guess:
project flag 'arbitration' does not match service selector project 'gamecast-dev'
systemg would rather stop than act on the wrong project.
Info
When a service name is unambiguous — it exists in exactly one registered
project — you can drop the project qualifier entirely and systemg resolves it
for you. If the same service name lives in multiple projects, systemg
refuses and asks you to disambiguate with -p.
-p per command
-p/--project is accepted across the commands that act on running projects:
| Command | Effect of -p <id> |
|---|---|
start | Start (or start a single service within) the named project. |
stop | Stop the named project's services. Use --supervisor to shut everything down. |
restart | Reload the project's stored manifest and restart its services. |
status | Scope the status table to one project. |
logs | Filter tailed logs to one project. |
inspect | Inspect a service within a specific project. |