CityRP Documentation Repository

Cloud agents

Last updated

How to set up a cloud agent (Claude Code on the web, or a Cursor cloud agent) so that it works on the live repository.

This repository lives on Gitea. Neither Claude nor Cursor can clone from Gitea, so both start from the GitHub mirror at limelight-development/cityrp2. That mirror is up to eight hours behind, and anything pushed to it is wiped on the next sync. A startup script, .claude/hooks/session-start.sh, moves every cloud session off the mirror and onto Gitea before the agent starts work. If it cannot, it stops the session rather than let the agent work on stale code.

Everything below is setup for that script. How it works and what its output means is in cloud-sessions.md.

A Gitea token

Both tools need a Gitea access token. Create one under Settings → Applications on Gitea with:

  • repository: read and write, to fetch and push branches
  • issue: read and write, to open pull requests and work with issues through tea
  • organization: read, for the org-wide issue labels

Treat it like a password. It goes into the tool's secret store below, never into a file in the repo.

Claude Code on the web

  1. Create a cloud environment for the GitHub repository limelight-development/cityrp2.

  2. Add two environment variables to it:

    Variable Value
    GITEA_INSTANCE_URL https://gitea.limelightgaming.net
    GITEA_TOKEN your token
  3. Start a session. The script runs from .claude/settings.json with no further setup.

Cursor cloud agents

Warning

Not yet tested. The pieces are in place, but nobody has run a Cursor cloud agent through them yet. Read What the first run needs to check before relying on one.

  1. Connect Cursor to the GitHub repository limelight-development/cityrp2.

  2. In the Cursor dashboard, under Cloud Agents, add three secrets:

    Secret Value
    GITEA_INSTANCE_URL https://gitea.limelightgaming.net
    GITEA_TOKEN your token
    CURSOR_CLOUD_AGENT true

    CURSOR_CLOUD_AGENT is not a secret, but the Secrets tab is how Cursor hands a variable to the agent. The script uses it to tell a Cursor cloud agent from someone's own machine, because Cursor does not set a variable of its own for that.

  3. Start an agent. .cursor/environment.json runs the script as its start command every time an agent boots, and lets the agent reach Gitea through Cursor's network allowlist.

What the first run needs to check

  • The script ran. The agent's startup output should include [gitea-remote] lines, and git remote -v in the agent should show gitea.limelightgaming.net, not github.com. If it shows GitHub, stop there: the agent is on the mirror.
  • The tools are still there. A repository's .cursor/environment.json takes priority over an environment saved in the Cursor dashboard. If you had a saved environment with glualint and lua-language-server installed, check they still work. If they are gone, the file needs your snapshot's ID added as "snapshot".
  • Where the agent's work goes. When a Cursor agent finishes, it pushes a branch and opens a pull request. Cursor only knows how to open pull requests on GitHub. Check whether the branch lands on Gitea, on GitHub, or nowhere, and whether Cursor reports an error. A branch on GitHub is lost at the next mirror sync, so copy anything worth keeping to Gitea by hand.
  • tea is available. Pull requests for this repository go through tea. If Cursor's image does not have it, note that too.

Trying a change before it reaches master

Cursor reads .cursor/environment.json from the GitHub mirror, so a change to it or to the script only reaches Cursor once the mirror has synced it. The mirror syncs every eight hours. A repository admin can sync it now:

tea api -X POST '/repos/limelight-development/cityrp2/push_mirrors-sync?x=1'