Getting Started¶
Build a Ceres project from nothing, run it, and drive it from the CLI. Everything on this page is a real transcript.
Create The Project¶
Write A Component¶
A component is an async Python class. Its annotated attributes are configuration fields, and its @routine methods are background tasks that start with the component and are cancelled when it stops.
# counter.py
from ceres import Component, routine, sleep
class Counter(Component):
initial: int
delta: int = 1
@routine
async def count(self) -> None:
count = self.initial
while True:
self.system.log.info(count)
await sleep(1)
count += self.delta
Configure The Project¶
ceres.yaml declares the database and the component tree.
# ceres.yaml
database:
type: sqlite
path: ./database.sqlite
logging:
events: false
components:
- name: counter-a
class: counter.Counter
arguments:
initial: 5
- name: counter-b
class: counter.Counter
arguments:
initial: 100
delta: -5
class is a Python import path. arguments are passed to the component and validated against its annotations, so a typo or a wrong type fails at load rather than at run.
The database path is relative to the configuration file, and a writable database creates the directories leading to its file, so a fresh project needs nothing made first.
logging.events is off here only to keep the output short. Left on, every lifecycle event is logged as JSON beside your own log lines, which is useful once you are debugging and noisy while you are reading.
Check it before running anything:
Run It¶
[2026-08-06 16:53:11.156] [INFO] [~] Loading configuration from '/path/to/ceres.yaml'.
[2026-08-06 16:53:11.160] [INFO] [~] Database appears empty, running migrations.
[2026-08-06 16:53:11.178] [INFO] [~] Database migrated successfully.
[2026-08-06 16:53:11.179] [INFO] [@counter-a] 5
[2026-08-06 16:53:11.180] [INFO] [@counter-b] 100
[2026-08-06 16:53:12.181] [INFO] [@counter-a] 6
[2026-08-06 16:53:12.181] [INFO] [@counter-b] 95
Migrations run on their own the first time, because the database is empty. Press Ctrl+C to stop.
Drive It From Another Terminal¶
Leave the engine running and open a second terminal in the same directory, with the virtual environment activated. A running engine writes a small file into the project holding a loopback port and a token, and the CLI reads that file and speaks HTTP to it. That is why the CLI has to run inside the project, and why nothing on the network can reach it.
Engine
╭─────────────────────┬─────────┬─────────────────┬─────────────────╮
│ Configuration │ Running │ Web Server Port │ CLI Server Port │
├─────────────────────┼─────────┼─────────────────┼─────────────────┤
│ /path/to/ceres.yaml │ Yes │ (Disabled) │ 50558 │
╰─────────────────────┴─────────┴─────────────────┴─────────────────╯
Components
╭────────────┬─────────┬─────────╮
│ Address │ Enabled │ Running │
├────────────┼─────────┼─────────┤
│ @counter-a │ No │ Yes │
│ @counter-b │ No │ Yes │
╰────────────┴─────────┴─────────╯
"Web Server Port" is (Disabled) until you add a server section. "CLI Server Port" is the loopback port that file names.
Starting And Stopping¶
ceres stop counter-a # Stop one component.
ceres start counter-a # Start it again.
ceres stop all # Stop everything.
The @ prefix on an address is optional on the command line.
Enabling And Disabling¶
Running and enabled are separate. Running is now, enabled is whether the engine starts it next time, which is why both columns exist above.
up and down do both halves at once.
Run It As A Service¶
ceres service start # Write the service file and start it.
ceres status
ceres service stop # Stop it and remove the file.
On Linux this is a SystemD user service, on macOS a LaunchD agent. Deployment covers the production shape.
Add The Web Console¶
Restart the engine and open http://localhost:8080. The console shows component state, logs, messages, and alerts, and can start and stop components. The same data is available over the HTTP API.
Watch Mode¶
Restarts the engine when Python files or the configuration change. For development only.
Next¶
- Components: routines, events, listeners, and records.
- Connections: reaching instruments and parsing what they send.
- Writing a Driver: the two put together, end to end.
- Configuration: every
ceres.yamlkey. - CLI: every command and option.