# One Werkator Instance Serves a Set of Repositories **Status:** - proposed: 2026-09-01 - accepted: 2026-09-01 - rejected: - - superseded: - **Decision [accepted]:** The founding tenet "one instance per repository" is revised to "one instance per repository *set*": a Werkator instance aggregates self-contained repositories listed in an instance registry, sharing one service, one port, one UI, one watcher schedule, and one global executor cap. Implementation is planned as `docs/plan/22-multi-repo.md`; this ADR records the decision and its shape, not the code. ## Context and Problem Statement "One instance per repository" (docs/Werkator-Konzept.md) does not scale even to two repositories on a Hostsharing Managed Webspace: building Werkbaum next to Werkator on mih34 would need a second service, a second assigned port, a second tunnel or domain, a second UI and metrics page. Every repository multiplies operations while the instance-level resources could be shared. ### Technical Background Everything repository-specific already lives inside the repository or is keyed by it: machine config with secrets, build results, auto-build slots, worktrees, and buildenvs under `.git/werkator/`; the artifact store under a per-repo key. An instance can therefore aggregate repositories without absorbing their state — adding or removing a repository is a registry entry, never a data migration, and single-repo mode stays the degenerate case (a registry of one, implicitly the current working directory). ## Considered Options * One instance per repository set (registry + aggregation) — chosen * A federation dashboard proxying several single-repo instances * Status quo: one instance, one repository ### One Instance per Repository Set Good: - One service, port, UI, tunnel/domain, metrics page for any number of repositories. - Repositories stay self-contained; per-repo secrets, history, and pinning semantics are untouched. - Global concurrency control across all repositories. Bad: - The repo dimension must be threaded through executor pools, watcher cycle, routes, and UI — the largest refactor since the rewrite (mitigated by a behavior-preserving `RepoContext` session first). - Instance-level and repo-level configuration must be split cleanly (see below). ### Federation Dashboard over Single-Repo Instances Rejected: less invasive, but it keeps N services, N ports, and N tunnels — it solves only the UI aggregation, not the operations burden that motivated the change. ### Status Quo Rejected: on a webspace, ports and domains are the scarce, manually assigned resource; per-repository services do not scale there. ## Decision Outcome One instance per repository set, with the configuration split decided 2026-09-01: - **Instance config** lives in `~/.werkator.yml` in the home directory of the user running the instance — one instance per OS user, matching the platform model. It carries `server.*` (port, domain/public base URL, nginx), the repository registry, the control token, the global `executor.maxConcurrent`, and the watcher schedule. The file name stays `.werkator.yml` in all three locations; the location carries the meaning. - **Repo defaults** may live in the home file, but only in an explicit `defaults:` block, merged *below* every repository's own layers (home defaults → committed project config → repo machine config → branch layer); pinning semantics are unchanged. Accepted cost: secrets may then live in two places. - **Repo config** stays in each repository: the committed `.werkator.yml` and the machine config in its `.git/werkator/`. - Instance keys found in a repo's machine config are ignored with a warning naming both files once a home config exists — never merged silently. - When a home config with a registry exists, `werkator server` serves the registry regardless of the current directory; without one it serves the current directory exactly as before. - Repository names (routes, UI) default to the directory basename, are overridable per registry entry, and duplicates abort the start loudly. Consequences: `docs/Werkator-Konzept.md` and AGENTS.md change their wording when the implementation lands (plan step 22 sessions B–D); until then this ADR documents the target and the existing behavior remains accurate.