# AGENTS.md — guidelines for coding agents ## Project **cheapo** — CLI in Go (Cobra) to fetch and observe current free game offers. Later planned: exposing the tools as an MCP server (see README.md, section "Roadmap / MCP"). ## Reference project **free-games-claimer** — https://github.com/DoSpamu/free-games-claimer (fork of https://github.com/vogler/free-games-claimer). How it gets the free-games info: - The fork (DoSpamu) is only an overlay (runner `run.js`, Discord notify, logger) on the upstream Docker image. The actual logic lives upstream in `vogler/free-games-claimer` (`epic-games.js`, `prime-gaming.js`, `gog.js`, `steam-games.js`, `aliexpress.js`). - Upstream uses **Playwright (Firefox)** with a persistent session: it opens the store page "Free Games", detects games via the locator `a:has(span:text-is("Free Now"))`, follows the links and claims them in the browser (login per cookie session, 2FA via OTP key, captcha handling). - **Important (comment in `epic-games.js`, ~line 151):** the page is built from the JSON of the public backend: `https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions` (filter `data.Catalog.searchStore.elements` on active `promotions.promotionalOffers` with 100 % discount; slug preferably from `catalogNs.mappings[0].pageSlug`, since `urlSlug` is sometimes wrong). - **Our approach (Go):** we query this endpoint **directly** — no browser, no login needed, as long as we only want to *detect* (list + watch). The actual *claiming* of the games (like in the reference project) is deliberate **not** part of this project. ## Toolchain & linting - Go ≥ 1.27 (`go version`). - **Formatting:** `gofmt -w .` (mandatory before every commit; CI checks `gofmt -l .` = empty). - **Linting/analysis:** `gopls` (install: `go install golang.org/x/tools/gopls@latest`). Use in editors as LSP; additionally `go vet ./...` before every commit. - Build & test: ```bash go build ./... && go vet ./... && go test ./... gofmt -l . # must be empty ``` ## Conventions - Module path: `gogs.netdome.biz/paul/cheapo`. - CLI framework: **Cobra** (`github.com/spf13/cobra`), commands in `cmd/cheapo/main.go`. - Internal code under `internal/` (epic: store client, watch: polling/eventing). - Wrap errors with context: `fmt.Errorf("epic: ...: %w", err)`. - User-facing strings in German (CLI output, help texts, error messages), code comments in English. - New store platforms (Prime, GOG, …) follow the `epic` package pattern (client + `GetFreeGames(ctx)`), so `watch` can stay generic.