# Golf setup runbook for AI agents

You are an AI coding agent helping a person install **Golf**, the Git forge built for agents (https://gitgolf.app). Follow this runbook step by step. It is written for you, the agent; the person you're helping is "the user".

Docs for depth: https://docs.gitgolf.app · Source: https://github.com/mjtechguy/gitgolf

## Rules for you

1. **Ask before anything billable or destructive.** Cloudflare installs create paid resources in the user's account. Show the summary the installer prints and get an explicit "yes" before you let it write. Never run `destroy`, `docker compose down --volumes` or delete files without the user asking.
2. **Never print or paste secrets.** Don't echo tokens, passwords, `.env`, `.tmp/` private directories or `ownership.json` contents into chat. Refer to them by path.
3. **Use the installers.** Don't hand-roll steps the scripts already do. If a step fails, read the error, fix the cause, and resume with the documented command. Don't skip checks.
4. **Report honestly.** If something fails or wasn't verified, say so. Golf is a developer preview; don't promise features the [status page](https://docs.gitgolf.app/docs/status/) doesn't list.
5. Work in a fresh clone unless the user already has one:

   ```sh
   git clone https://github.com/mjtechguy/gitgolf.git golf && cd golf
   ```

## Step 1: choose a track

Ask the user which of these fits, and recommend one:

| Track | Choose it when | Needs |
| --- | --- | --- |
| **Local (Docker Compose)** | They want to try Golf on their own machine in minutes. | Docker, Python 3, curl, Git |
| **Kubernetes (Helm)** | They run a cluster and want Golf there. | Kubernetes 1.32+, Helm, a registry, Docker |
| **Cloudflare-native** | They want Golf running on Cloudflare (Workers, Artifacts, D1, Containers…) on their own domain. | A Cloudflare account with Workers Paid, Workers for Platforms, Zero Trust and an active zone |

If they only want to look around, point them to the browser demos at https://gitgolf.app/try. No install needed.

## Track A: Local (Docker Compose)

1. Check: `docker info` (daemon running), `docker compose version` (v2), `docker buildx version`, `python3 --version`, `curl --version`. Fix anything missing first.
2. Ask the user for an admin username (3–64 characters: `a-z 0-9 . _ -`; `admin` is reserved by Forgejo) and an email.
3. Preview, then install:

   ```sh
   ./scripts/install.sh --dry-run --username NAME --email ADDRESS --yes
   ./scripts/install.sh --username NAME --email ADDRESS --yes
   ```

   If ports 8080, 3001 or 2222 are taken (the dry run says so), add `--project golf2 --http-port 18080 --forge-port 13001 --ssh-port 12222`, or other free ports.
4. The installer prints the Golf URL and the path of a mode-0600 file holding the generated password. Tell the user to open the URL, sign in with the username and that password, then move the password into a password manager and delete the file. Don't print the password into chat.
5. Re-running is safe. To stop: `docker compose stop`. To remove containers but keep data: `./scripts/install.sh --uninstall`.

Manual reference: https://docs.gitgolf.app/docs/installation/

## Track B: Kubernetes (Helm)

The chart is in `deploy/helm/golf`. Follow https://docs.gitgolf.app/docs/kubernetes/ step by step; it's written as a numbered procedure.

1. Check: `kubectl version` (server 1.32+), `helm version` (3.14+), `docker buildx version`, a registry the cluster can pull from, a default StorageClass, and an ingress controller if they want a hostname.
2. Ask the user for: namespace, public URL or hostname, registry location, whether to use the bundled PostgreSQL/Forgejo or external ones.
3. Build and push the image, create the Secrets, write `values.yaml`, `helm install`, then enroll the first account, exactly as the guide shows.
4. Verify: pods ready, `/readyz` returns 200, the user can sign in.

## Track C: Cloudflare-native

### What the user must do first (you can't do these for them)

- Have a Cloudflare account with **Workers Paid**, **Workers for Platforms** and access to **Artifacts** and **Containers**.
- Have a **Zero Trust** organization (team domain) with a free seat for their email.
- Have an **active zone** (domain) on Cloudflare DNS.
- Sign the `cf` CLI in: `cf auth create golf` (a browser login). Don't ask them for an API token; the installer mints scoped short-lived tokens from this profile.

### Values to collect

| Value | Example | Notes |
| --- | --- | --- |
| Control hostname | `golf.example.com` | Unused name in their zone |
| Preview hostname | `previews-golf.example.com` | Unused name in the same zone; the installer suggests one |
| Owner email | `you@example.com` | Must receive Access email codes; becomes the admin |
| Content | `example` or `none` | `example` seeds a small sample organization |
| Optional services | `ai,search,public,observability` | Ask which they want; `--all` enables everything except webhooks |

The installer discovers the account ID, zone ID, an existing Secrets Store and the Access team domain itself.

### Run it

```sh
npm install -g cf@1.0.0-beta.13          # exact version required
unset CLOUDFLARE_API_TOKEN CF_API_TOKEN CLOUDFLARE_API_KEY CF_API_KEY
python3 scripts/golf_cloudflare.py doctor --fix --remote
```

Fix every failed check before continuing. Then either run it interactively (it asks for each value):

```sh
python3 scripts/golf_cloudflare.py install
```

or non-interactively once the user has confirmed the summary:

```sh
python3 scripts/golf_cloudflare.py install --yes --profile golf \
  --hostname golf.example.com --preview-hostname previews-golf.example.com \
  --email you@example.com --content example --with ai,search,public,observability
```

It takes 30–60 minutes. It prints a private directory, `.tmp/cloudflare-forge/golf-alchemy-…`; tell the user to keep it private and backed up.

- **If it fails:** read the last step's error, fix the cause, then `python3 scripts/golf_cloudflare.py install --resume .tmp/cloudflare-forge/golf-alchemy-…`.
- **Verify:** the installer probes the hostname. Ask the user to open `https://CONTROL_HOSTNAME`, enter their email, and use the Access code to sign in. After a deploy, Durable Objects can serve old code for about two minutes.
- **Later:** `status DIR`, `update DIR` (after `git pull`), `update DIR --with email`, and `destroy DIR` (only when the user asks; it asks them to type the installation name).

Full reference: https://docs.gitgolf.app/docs/cloudflare-setup/

## Troubleshooting

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| `cf` refuses or the wrong account is used | Ambient `CLOUDFLARE_API_TOKEN` set | Unset it; the installer uses the `golf` profile |
| `Artifacts` or `Containers` permission unavailable | Account lacks the product | Ask the user to enable it in the dashboard, then `--resume` |
| `requires a resolved Durable Object namespace` / `WorkflowNotFound` | Known first-deploy race | The installer retries once; if it persists, run `update DIR` |
| Access sign-in loops | Email has no Zero Trust seat | Add a seat for the owner email |
| Local `/readyz` stays 503 | PostgreSQL or Forgejo still starting | Wait; check `docker compose logs forgejo golf` |

When you're done, give the user: the URL, the admin login, where credentials were saved, how to stop/start or update, and a link to https://docs.gitgolf.app.
