- Python 98.9%
- Shell 1.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
CI / Sanity check (ubuntu-latest) (push) Successful in 24s
- config: agent default_host/ssh_user now empty (server-side must set them) - deploy.sh: SERVER_HOST/USER/REPO_DIR required in environment - roster.toml.example, README, AGENTS.md, spec: placeholders only - move build plan to SDD workspace (kept local, not committed) - AGENTS.md: document public repo hygiene workflow |
||
| .forgejo/workflows | ||
| docs/superpowers/specs | ||
| scripts | ||
| src/roster | ||
| systemd | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| deploy.sh | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| roster.toml.example | ||
| uv.lock | ||
roster
Resident scheduler for the home network. script, llm and agent jobs,
created by you from the CLI or by LLM agents over MCP; results land in
output files and ntfy.
Design doc: docs/superpowers/specs/2026-08-24-roster-design.md.
Architecture
Two systemd user units on the server host:
roster serve— FastAPI JSON API on :4020 plus the 30 s tick loop. Owns the SQLite store (WAL) and runs every job.roster mcp— streamable-HTTP MCP server on :4021 whose eight tools are thin HTTP calls to the API.
The CLI is a thin client too. One mutation path: everything goes through the service process.
Job types:
| type | runs |
|---|---|
script |
an allowlisted executable under [scripts] dir (optional gate script first) |
llm |
one chat completion against an OpenAI-compatible endpoint |
agent |
opencode run --agent <name> on the workstation over SSH |
Schedules: interval (30m, 2h), cron (5-field), at (one-shot;
fires immediately when the time is now/past).
Semantics worth knowing: catch-up window 900 s (older due events are
recorded as skipped(misfire)); no overlapping runs; unreachable LLM
endpoint defers instead of failing (one alert per episode, completion notes
"after N deferrals"); 3 consecutive failures alert once; [SILENT] in
llm/agent output suppresses ntfy but not the file.
Quickstart
uv sync --group dev
cp roster.toml.example ~/.config/roster/roster.toml # then edit ntfy_url/token
mkdir -p ~/.config/roster/scripts
export SERVER_HOST=... SERVER_USER=... SERVER_REPO_DIR=... # deploy target
./deploy.sh # installs + starts both units
roster selftest
roster add --id ping --type script --interval 30m \
--script-path ~/.config/roster/scripts/sample_ping.sh
roster list
roster runs ping
CLI
roster add | list | show | update | pause | resume | run | rm | runs,
plus serve, mcp, selftest, doctor [--reset-locks].
MCP clients
Computer (mcp.json):
{ "type": "http", "url": "http://<server-host>:4021/mcp" }
Workstation opencode: add the same URL as a remote MCP server. Agents can
then schedule work; allow_agent_scheduling = false rejects all mutating
requests from non-CLI clients.
Operations
journalctl --user -u roster -n 100 # engine/API logs
journalctl --user -u roster-mcp -n 100 # MCP logs
roster doctor # integrity check
roster doctor --reset-locks # repair stale running rows