Remote Control Daemon
The Aethrix daemon is a background service that exposes a local HTTP control API. It executes automation projects, manages service simulation servers, and installs extension packages — so CI agents, scripts, and other tools can drive Aethrix without opening Aethrix Studio.
The daemon runs locally on your machine. Each automation run executes in its own child aeth run process, isolated from Aethrix Studio: the daemon has its own state root, settings, and workspace, and never touches Studio's data.
Quickest Scenario
Start the daemon in the background (it returns control immediately):
aeth daemon
The daemon publishes a discovery file with its address and access token:
%APPDATA%\AethrixTech\Aethrix\daemon.json
{
"version": 1,
"pid": 21440,
"port": 52341,
"token": "bTRhbDk…",
"workspace": "C:\\Users\\you\\AppData\\Roaming\\AethrixTech\\Aethrix\\daemon\\workspace",
"startedAt": "2026-09-06T09:00:00Z"
}
Every call (except GET /v1/healthz) requires the token as a bearer header:
TOKEN=$(python -c "import json;print(json.load(open(r'%APPDATA%\AethrixTech\Aethrix\daemon.json'))['token'])")
curl -s http://127.0.0.1:52341/v1/healthz
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:52341/v1/system/info
Run an automation project and fetch its report:
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"projectId":"MyProject/MyProject.aprj","reportFormats":["junit"]}' \
http://127.0.0.1:52341/v1/runs
Build a project's shape without opening Studio — one command per step of it, so a script says what it creates:
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:52341/v1/commands # what this door runs
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"projects/MyProject/MyProject.aprj","parameters":{"suite_name":"Smoke"}}' \
http://127.0.0.1:52341/v1/commands/structure.suite.add
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"projects/MyProject/MyProject.aprj","parameters":{"suite_name":"Smoke","test_case_name":"Login"}}' \
http://127.0.0.1:52341/v1/commands/structure.case.add
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"projects/MyProject/MyProject.aprj","parameters":{"suite_name":"Smoke","test_case_name":"Login","operation_id":"Swagger.PetStore.POST /pet/{petId}"}}' \
http://127.0.0.1:52341/v1/commands/structure.step.send.add
Stop the daemon when done:
aeth daemon --stop
Start and Stop Options
| Option | Description |
|---|---|
| (default) | Start the daemon in the background and return control once it is ready |
--start | Same as the default action (accepted for readability) |
--foreground | Run attached to the terminal; press Ctrl+C to stop |
--stop | Ask a running daemon to shut down gracefully, then stop it |
--workspace <path> | Use a custom workspace root instead of the default daemon state root |
--port <port> | Listen on a fixed TCP port instead of a free ephemeral port |
Rules that apply on a machine:
- One daemon at a time. A machine-wide lock file (
daemon.lock) prevents a second instance. Starting while one runs just reports the existing daemon. - Stale entries are cleaned up. If a previous daemon died without cleaning up, the discovery file is detected as stale and removed.
sim startand the daemon are mutually exclusive. If a backgroundaeth sim startprocess owns the simulation servers,aeth daemonrefuses to start (and vice versa) — one owner per machine.
Isolation from Aethrix Studio
The daemon keeps its own state in %APPDATA%\AethrixTech\Aethrix\daemon (or the --workspace path you give it): settings, workspace, projects, run outputs. Each run spawns a fresh aeth run child process with this state root injected, so:
- Runs use the daemon's environment variables and settings, not Studio's.
- A crashed or cancelled run cannot corrupt the daemon process; it is detected and reported.
- A run can be cancelled cooperatively (stop sentinel) or killed after a grace period.
Authentication
The daemon generates a random token at startup and stores it in daemon.json. Requests must carry Authorization: Bearer <token>; anything else is answered with 401 Unauthorized. GET /v1/healthz is anonymous for liveness probes.
HTTP API Reference
Base URL: http://127.0.0.1:<port>. All bodies are JSON unless noted. A machine-readable OpenAPI document is served at GET /v1/openapi.json.
| Method | Path | Description |
|---|---|---|
| GET | /v1/healthz | Liveness probe (no auth) |
| GET | /v1/system/info | Version, uptime, workspace, run capacity |
| POST | /v1/system/shutdown?force= | Graceful (or forced) shutdown |
| GET | /v1/projects | Discover .aprj files under the workspace |
| POST | /v1/projects?mode=replace|merge | Push a zipped project (binary body) |
| GET | /v1/environments?project=<id> | List project environments (values are never returned) |
| PUT | /v1/environments/variables | Create or update a variable in a project environment |
| GET | /v1/commands | The workspace operations this door runs, read from the command catalog (id, summary, risk, arguments) |
| POST | /v1/commands/<id> | Run one of them against a project: {"project": "…", "parameters": {"suite_name": "…"}}. An argument the command does not declare is refused, and a command not offered to a remote caller is answered 404 |
| POST | /v1/runs | Start a run ({"projectId": "…", "reportFormats": ["junit"]}) |
| GET | /v1/runs | List runs |
| GET | /v1/runs/{id} | Run status, counters, diagnostics |
| POST | /v1/runs/{id}/cancel | Cancel a running job |
| GET | /v1/runs/{id}/report?format=json|junit|sarif|html | Fetch a generated report |
| GET | /v1/events | Server-sent events for all topics |
| GET | /v1/runs/{id}/events | Server-sent events for one run |
| POST | /v1/extensions?force=&fileName= | Install a .pkg extension (binary body) |
| GET | /v1/extensions | List installed extensions |
| GET | /v1/simulations | Simulation servers, routes, responses, base URLs |
| POST | /v1/simulations/start | Start simulation servers ({"server": "HttpServer"} or omit for all) |
| POST | /v1/simulations/stop | Stop simulation servers |
| POST | /v1/simulations/config/import?strategy=… | Import a .mockconfig.json configuration |
| GET | /v1/simulations/responses | List imported responses |
| POST | /v1/simulations/responses | Add one saved response |
Project ids are slash-separated paths relative to the workspace (e.g. MyProject/MyProject.aprj) because the same .aprj file name can exist in several folders.
Pushing a project
Zip a project folder (the .aprj file plus its sibling suites, code, and embedded extension folders) and POST the archive:
cd /path/to/projects
zip -r MyProject.zip MyProject
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
--data-binary @MyProject.zip \
"http://127.0.0.1:52341/v1/projects?mode=replace"
The archive must contain exactly one .aprj file. With mode=replace (default) an existing project with the same name is removed first; merge extracts over it.
Updating a project environment
Variable values are write-only: GET returns names and whether a value is set, never the value itself. Create or update a variable:
curl -s -X PUT -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"MyProject/MyProject.aprj","environment":"staging","name":"baseUrl","value":"https://staging.example.com"}' \
http://127.0.0.1:52341/v1/environments/variables
Omit environment to target the default environment. Password-protected (encrypted) projects cannot be edited through the daemon.
Following a run live
curl -N -H "Authorization: Bearer $TOKEN" http://127.0.0.1:52341/v1/runs/<id>/events
Events are JSON lines over SSE: run started, suite/case completion counters, step progress, and the final result. The same feed powers GET /v1/runs/{id} snapshots.
Simulation Servers Started by Runs
When a run executes Service Simulation - Control test steps (start/stop) or Service Simulation - Update Data steps, and the run was started by the daemon, those steps are routed to the daemon's own simulation endpoints instead of starting a competing server inside the run process. The started servers stay up after the run finishes (until you POST /v1/simulations/stop), so a pipeline can run tests against them.
aeth sim start --background is the standalone (daemon-less) equivalent for CI machines; see Simulation CLI.