Two files tell AFK
the rules.
AFK's configuration is versioned with your code. You commit a .afk/ folder; AFK reads it from your base branch at the start of every task — code-enforced, never guessed. Here's the shape of it.
Two files, one contract.
One is machine-parsed and enforced in code. The other is prose for the model. They're deliberately separate — a hard limit never belongs in the advisory file.
.afk/ ├── config.yml # required — machine-parsed, enforced in code └── rules.md # optional — prose, handed to the model
Machine-parsed, code-enforced. Carries the toolchain image, the commands AFK may run, path allow/block lists, limits, the default model, and PR labels. It feeds seven pipeline stages — this is where every guardrail actually lives.
Prose handed to the model — conventions, domain context, "never do X". Advisory; it enforces nothing. Point it at your AGENTS.md / CLAUDE.md rather than duplicating them.
A complete sample.
Drop this into .afk/config.yml, adjust for your repo, and commit it. Every limit here is checked against the final diff in code — not suggested to the model.
version: 1 image: node:22 # your repo's toolchain — reuse the CI image where one exists commands: install: npm ci # CI-appropriate; add --ignore-scripts if a prepare hook wires git hooks test: npm test # the verify oracle AFK runs to check the change (no secrets in v0) lint: npm run lint typecheck: tsc --noEmit build: npm run build paths: allowed: ["src/**", "tests/**", "docs/**", "README.md"] # the only paths the agent may write blocked: ["infra/prod/**"] # never writable, on top of the platform deny list ignore: ["**/*.lock", "pnpm-lock.yaml"] # never read — keeps the context lean limits: maxCost: 2.00 # hard $ ceiling — the run stops dead at the cap maxFilesChanged: 8 # blast radius: no sprawling rewrites maxDiffLines: 500 maxIterations: 10 timeoutMinutes: 20 model: default: anthropic/claude-sonnet-5 # from the allow-list; a request may override per task pr: labels: ["afk"] # AFK opens a draft PR with this label — it never merges
Two optional blocks go further — screenshot: (before/after captures in the PR) and preview: (per-PR deploy previews). Both are inert unless enabled: true:
# ── optional: per-PR deploy previews (Dokploy) ────────────────────────────── preview: enabled: false # spin up a preview deployment for each PR requireLabel: afk-preview # only PRs carrying this label get one (mandatory on public repos) # ── optional: before/after screenshots in the PR body ─────────────────────── screenshot: enabled: false # everything below is inert unless this is true framework: next-app # "next-app" derives routes from changed app-router pages; else "none" routes: ["/dashboard"] # explicit URLs — fallback when a change maps to no route, or the only source when framework is "none" maxRoutes: 3 # capture at most this many routes per task port: 3000 # the port your app listens on readySeconds: 240 # how long to wait for the app to answer (allow for a prod build) viewport: width: 1280 height: 800 env: # applied to the APP container only — never the agent's job container NEXT_PUBLIC_API_URL: "http://localhost:3000" services: # disposable sibling containers on the task network; they die with the task - image: postgres:17-alpine alias: db env: POSTGRES_USER: afk POSTGRES_PASSWORD: afk commands: # run in the app container before it serves, against the services above migrate: pnpm db:push seed: pnpm seed:demo login: # capture authenticated routes by signing in first (seeded demo account only) path: /login email: "demo@example.com" password: "demo-password" selectors: # override if your sign-in form isn't standard email: "input[name=email]" password: "input[name=password]" submit: "button[type=submit]"
screenshot: is live; preview: is planned. Every field here is optional (each has a default) — you only declare what differs from it.
Onboard a repo in three steps.
Install the GitHub App
Install AFK's GitHub App on the repositories you want it to work on. That's what lets it clone, push a branch, and open a draft PR — as afkgnt-app[bot], never as you.
Commit the .afk/ folder
Add .afk/config.yml (and optionally .afk/rules.md) to your default branch. AFK reads them from there at task start — so your rules are versioned right alongside your code.
Register the repo
Point AFK at it once — it reads your committed config live via the App. Then fire tasks from the control room, a terminal, or Telegram, and come back to draft PRs.
The full reference is on GitHub.
This is the overview. For every field, the policy model, the security model and the deploy runbook, read the documentation in the repo.