
# How it works

## Hosts

```text
people ─┐
        ├─► your TLS proxy or tunnel ─► Acahti control plane ─► Runner
agents ─┘
```

| Host | Runs |
|---|---|
| Control plane | The gateway image `ghcr.io/acahti-ai/acahti`, Forgejo, Woodpecker server, and PostgreSQL, in Docker Compose under `~/acahti`. No pipelines run here |
| Runner | One Woodpecker agent that executes jobs. Parallelism follows the host's CPU and memory |

## The gateway

The Go gateway is the only public application. The web app, MCP, and the REST API all call one internal catalog, so every surface sees the same data and the same permissions.

| Path | Client | Backend |
|---|---|---|
| `/ui/*` | People in the browser | Catalog |
| `/mcp` | IDE agents | Catalog |
| `/acahti/v1` | CLI, scripts | Catalog |
| `/<org>/<repo>.git` | Git | Proxied to Forgejo as the authenticated user |
| `/api/packages/*` | npm, pip, uv | Proxied to Forgejo as the authenticated user |
| `/hooks/*` | Forgejo, Woodpecker | Index updates and live events |

Lists, the Board, and navigation read from the gateway's own index in PostgreSQL. Forgejo webhooks keep repository data current; the gateway polls Woodpecker's queue and reconciles pipeline history every minute. File contents, diffs, and running step logs are read live from the kernels; failed steps' logs are kept in the index.

## Pipelines

A push or pull request triggers Woodpecker. Before a job starts, the gateway expands its YAML: official pipes become `acahti-pipe` calls, named secrets become environment, and every step gets the run's Acahti identity (`ACAHTI_USER`, `ACAHTI_TOKEN`, `ACAHTI_ROOT_URL`, `ACAHTI_ORG`): the account of the head commit's author, falling back to the account that started the run. The gateway polls Woodpecker's queue every few seconds and reconciles its history every minute into the index, where `checks_wait`, the Inbox, and the Board read them. See [Pipelines](pipelines.md).

## Data

All state is under `ACAHTI_DATA` as bind mounts. Once data exists, never run `docker compose down -v`.

| Directory | Contents |
|---|---|
| `postgres/` | Databases for Forgejo, Woodpecker, and the gateway |
| `forgejo/` | Git repositories and Forgejo state |
| `woodpecker/` | Woodpecker server state |
| `gateway/` | Invites, passwords, OAuth clients and refresh tokens, personal Access Tokens, Argos run files |

Back up PostgreSQL and `ACAHTI_DATA` before every upgrade.

## Independent plugins

Phaevo is a separately maintained GitHub service. A plugin's signed descriptor contributes a header tab with its own icon, a sidebar, pages and MCP operations. The kernel verifies source provenance, resolves live identity and controls access grants and installation state. Tickets, Todos, Docs, Chat and Argos are built into the gateway and need no plugin installation.

Every plugin supports the same install, upgrade, enable, disable and uninstall controls. Source release pipelines own deployment and data migrations; uninstall retains application data. Users see the pages and actions their current permissions allow.

Agents discover accessible installations through `whoami.plugins`. Source repositories and documentation are linked from the installation metadata.
