Server stack health application with UI.
cargo build --releaseForeground daemon (default without subcommands):
./target/release/status --config config.jsonDaemon mode (background):
./target/release/status --daemon --config config.jsonLocal API server (API-only mode):
./target/release/status serve --port 5000Local API server with UI (serves HTML templates):
./target/release/status serve --port 5000 --with-uiThen open your browser to http://localhost:5000/login to access the web interface.
Docker operations (requires --features docker):
cargo run --features docker --bin status -- containers
cargo run --features docker --bin status -- restart status- API-only mode: Returns JSON responses for programmatic access
- UI mode (
--with-ui): Serves HTML templates fromtemplates/directory with static files fromstatic/ - Docker container management (list, restart, stop, pause)
- Session-based authentication
- Health check endpoint
- Self-update (beta): remote version check, binary download + SHA256 verify, deploy with backup/rollback
Execute validated shell commands via the local API. The endpoint accepts a transport::Command payload and returns a transport::CommandResult.
- Endpoint:
POST /api/v1/commands/execute - Required fields:
id(string),name(full command line) - Optional:
params.timeout_secs(number) to override the default 60s timeout
Example: run a simple echo
curl -s \
-H 'Content-Type: application/json' \
-X POST http://localhost:5000/api/v1/commands/execute \
-d '{
"id": "cmd-001",
"name": "echo hello from agent",
"params": { "timeout_secs": 10 }
}' | jq .Example: run a short sleep
curl -s \
-H 'Content-Type: application/json' \
-X POST http://localhost:5000/api/v1/commands/execute \
-d '{
"id": "cmd-002",
"name": "sleep 2",
"params": { "timeout_secs": 5 }
}' | jq .Notes:
- Commands are validated by a conservative allowlist and safety checks; see
src/commands/validator.rs. - Disallowed by default: shells (
sh,bash,zsh) and metacharacters like; | & > <. - Absolute paths must match allowed prefixes (defaults:
/tmp,/var/tmp). - Output (
stdout/stderr) andexit_codeare included when available, along with astatusofsuccess,failed,timeout, orkilled.
The agent supports an in-memory command queue for dashboard-driven execution via long-polling. Commands are queued and agents poll for them with configurable timeouts.
GET /api/v1/commands/wait/{hash}?timeout=N- Long-poll for next queued command (default 30s timeout)POST /api/v1/commands/report- Report command execution resultPOST /api/v1/commands/enqueue- Enqueue a command (for testing/local use)
All endpoints require X-Agent-Id header matching the AGENT_ID environment variable.
Start the server with agent ID:
export AGENT_ID=test-agent
cargo r -- serve --port 5000Terminal 1: Long-poll for commands
curl -H 'X-Agent-Id: test-agent' \
'http://localhost:5000/api/v1/commands/wait/demo?timeout=10'Terminal 2: Enqueue a command
curl -s \
-H 'Content-Type: application/json' \
-X POST http://localhost:5000/api/v1/commands/enqueue \
-d '{
"id": "cmd-001",
"name": "echo hello from queue",
"params": {}
}' | jq .The long-poll in Terminal 1 will immediately return the queued command.
Report command result
curl -s \
-H 'Content-Type: application/json' \
-H 'X-Agent-Id: test-agent' \
-X POST http://localhost:5000/api/v1/commands/report \
-d '{
"command_id": "cmd-001",
"status": "success",
"result": {"exit_code": 0, "stdout": "hello from queue\n"},
"error": null
}' | jq .Run the automated demo:
export AGENT_ID=test-agent
./examples/long_poll_demo.shThis script starts a background poller, enqueues a command, and demonstrates the long-poll notification mechanism.
The UI uses Tera templating engine (similar to Jinja2). Templates are located in:
templates/- HTML templates (login.html, index.html, error.html)static/- CSS, JavaScript, and other static assets
- Reads
config.jsonand normalizesapps_infoto structured items. - Subsystems marked with
@todowill be implemented per.ai/GOAL.md.
- Env vars:
UPDATE_SERVER_URLorUPDATE_BINARY_URL, optionalUPDATE_EXPECTED_SHA256,AGENT_ID,UPDATE_STORAGE_PATH - Endpoints:
GET /api/self/version→ current + available (whenUPDATE_SERVER_URLis set)POST /api/self/update/start→ returnsjob_id(requiresX-Agent-Id)GET /api/self/update/status/{id}→ phase: pending|downloading|verifying|completed|failedPOST /api/self/update/deploy→ body:{ "job_id", "install_path?", "service_name?" }; backs up current binary, deploys prepared onePOST /api/self/update/rollback→ restore latest backup
Example (start + deploy):
curl -X POST http://localhost:5000/api/self/update/start \
-H "X-Agent-Id: $AGENT_ID" \
-d '{"version":"1.2.3"}'
curl -X POST http://localhost:5000/api/self/update/deploy \
-H "X-Agent-Id: $AGENT_ID" \
-d '{"job_id":"<returned-id>","service_name":"status-panel"}'