This document is for contributors working on the avyos codebase day-to-day: how to navigate the repo, how to add services and APIs, common workflows, and debugging tips.
If you’re new, start with:
README.md— project overviewARCHITECTURE.md— system architecture + code mapBUILDING.md— build/run/debug instructions
cmd/— system commands and entrypoints (including PID 1 init and management tools)services/— long-running daemons (system capabilities live here)api/— Sutra API schemas (api.json)pkg/— shared Go packages (Sutra, graphics, filesystem helpers, etc.)tools/— generators and build/dev tools (apigen, image tools,dbg)docs/— documentation and assetsexternal/— boot assets, kernel images, firmware, etc.
- Services:
services/<name>/... - API schema:
api/<name>/api.json(same<name>as the service) - Command/tool:
cmd/<tool>/... - Shared library:
pkg/<area>/...
See BUILDING.md.
- Use
make compile_dbif you’re changing build dependencies frequently. - Prefer small PRs and keep changes localized to one subsystem where possible.
- When modifying a service API, regenerate bindings and update both client + server usage.
- Each service typically exposes a unix socket under
/cache/runtime - Clients connect, send requests, and receive events
- Type-safe bindings are generated from API schemas
- Create/update schema:
api/<service>/api.json
- Run the generator:
go run ./tools/apigen(or the project’s preferred wrapper/target)
- Update:
- server handlers in
services/<service>/ - client calls in commands/apps/services
- server handlers in
- Boot in QEMU and validate end-to-end.
Rule of thumb: if more than one client uses it, it should be a schema + generated binding, not an ad-hoc message format.
- Keep requests/responses minimal and explicit
- Prefer additive changes (new fields, new messages) over breaking renames
- Document new API messages in code comments near handlers (or in
/docsif intended for external use)
A typical service consists of:
- a main entrypoint under
services/<name>/ - configuration under
/avyos/config/<name>/(defaults) and/config/<name>/(overrides) - an API schema (if clients call it)
A service should:
- log clearly on startup and on fatal exit
- create its Sutra endpoint under
/cache/runtime - run under a dedicated service account where applicable
- be startable by PID 1 init / service manager
Apps live under /apps/<id>/:
manifest.jsonexec(native binary or AppImage)icon.png(optional)
Apps should not directly manipulate privileged resources. The intended model is:
- app → Sutra → service (authz enforced by service)
The optional distro rootfs provides access to “normal Linux userland” resources (libraries, codecs, tools) inside a restricted container.
Developer notes:
- the layer is managed by
cmd/distro - keep the container boundary strict: avoid accidental coupling to host paths
- treat
/linuxas least-privileged
services/display— compositor/display serverapi/display— display protocol schemapkg/graphics— client-side framework (QML-like UI files, rendering, input, assets)
- Extend schema in
api/display/api.json - Regenerate bindings
- Implement server-side behavior in
services/display - Update client framework in
pkg/graphics
See the detailed guide in BUILDING.md. Highlights:
- QEMU
DEBUG=1for low-level debugging (-s -S, gdbstub on :1234) tools/dbgclient to interact with the guest viaservices/dbgd- guest-side tools (e.g.,
dlv) for Go userspace debugging
gofmtis required- keep imports clean and deterministic
- services: structured/consistent logging (avoid noisy prints)
- commands: user-friendly output for interactive usage, machine-friendly modes where needed
- return errors with context
- do not swallow errors in system-critical paths (boot/service start)
ARCHITECTURE.md: system decomposition and stable “code map”README.md: non-technical overview + navigation linksBUILDING.md: build/run/debug instructionsDEVELOPERS.md: contributor workflows (this document)- subsystem docs:
docs/<topic>.mdwhen details would clutter these top-level docs