01 / WHY

Built for people, a few pushes an hour.

Agents push, read and land changes continuously. Before agentic mode, these were Golf’s own limits on Cloudflare, and they are the same assumptions most forges make.

One push per repository

A push reserved the whole repository. A second push to any other branch of it got a 409.

Before AM-1

Every push and clone alone

One Workspace object served the deployment. Every clone, fetch and push to every repository ran alone; over 128 queued requests got a 429.

Before AM-1

A lock nobody cleared

If a push’s outcome was unknown, the repository stayed locked. Nothing cleared it automatically.

Before AM-1

Clone to change anything

No multi-file read, no server-side commit, no API tokens and no remote MCP. Merges only worked when the head already contained the base.

Before AM-1

The target: at least 100 agents working in one repository without the forge or the reviewers becoming the bottleneck. Monorepo scale of tens of thousands of merges a day is not the target. The design follows two pieces of writing: Anthropic’s Redesigning source control ↗ and Enroute’s Everyone is doing Git on S3 wrong ↗.

02 / STILL GIT

No new protocol. No new storage engine.

The limits were never in storage. Cloudflare Artifacts already keeps Git on Cloudflare’s storage, so the work is in Golf’s own control path.

Every Git client works

Clone, fetch and push over HTTPS at /git/<owner>/<name>.git. An agent can use the same API token as its Git password, so it needs no separate Git credential.

Server commits are real commits

The Source API encodes blobs, trees and commits exactly as Git does and sends them through receive-pack. Locally, its trees equal Git’s own index for the same edits, and git fsck --strict is clean.

Same rules either way

A push, a Source API commit and an MCP tool call meet the same branch rules, the same branch fence and the same pipeline intake. Rights are rechecked in the D1 statement that reserves the write.

03 / CONCURRENT GIT · AM-1

Three admission classes, not one queue.

Every request to a deployment passes one Workspace Durable Object. AM-1 splits its single queue into classes, so clones and pushes stop waiting for each other. The queue holds 512; beyond that, a 429 says “Workspace is busy. Retry with backoff.”

READ · UP TO 8

Reads overlap

Source, history, diffs and search run side by side, alongside transfers.

Overlaps everything but exclusive
TRANSFER · UP TO 24

Git traffic overlaps

Clone, fetch and push, plus Source API commits and branch updates. They overlap reads and each other; writes are ordered per branch by the D1 fence.

Clone · fetch · push · commit
EXCLUSIVE · ALONE

Authority changes wait

Everything else waits for every running request, transfers included, and fences later admissions. A revocation or settings change never overlaps a push.

Revocations · settings · merges

A fence per branch, not per repository.

A push reserves its branch in git_ref_writes, in the same D1 batch that journals the write and under the same authority check: grant, identity and access versions, rules version and credential.

Measured on hosted

Different branches never wait

Two unsettled writes to one branch conflict. Writes to different branches proceed in parallel. A lost race to the same branch is answered with Git’s own report (“fetch first”), settled as not applied at once, and the repository is not fenced.

Measured on hosted

Unknown outcomes settle by readback

If a sent update does not read back, Golf resends the same compare-and-swap while the branch still holds the old commit: 5 attempts over about 3 seconds. If it stays unknown, only that branch stays fenced. A maintenance sweep reads the ref after 2 minutes and records it applied or not applied, with an audit row.

Unchanged

Merges still hold the repository

A pull request merge reserves the whole repository through write_pending, and a plain push refuses to start while that is set. Rule, settings and merge changes wait for a branch with an unknown outcome to settle.

On the hosted demo, 16 agents pushing to separate branches of one repository went from 0 of 32 pushes landing to 48 of 48; 64 agents went from 0 of 64 to 93 of 93.

04 / SOURCE API · AM-2

Read and commit without a clone.

POST /native/source/<action> with JSON. Commits and branch updates are transfers, ordered per branch by the same D1 fence as a push; reads are reads.

commit

Up to 500 changes against an expected head: content, base64, mode, delete or move. Built as Git objects and sent as one receive-pack update.

Write · transfer

branch

Create a branch from a commit or branch, or delete one with an expected head. The default branch cannot be deleted.

Write · transfer

files

Up to 100 paths at one ref in one call. Text inline, binary as base64, or a reason it was skipped.

Read · 1 MiB a file, 4 MiB total

tree

A listing of a commit, sorted by path, up to 10,000 entries, with truncated shown.

Read · no clone

Compare-and-swap on the branch head

expectedHead is the head your edits are based on, or empty plus base to create the branch. With onStale: "fail", the default, a moved branch returns 409 with currentHead.

With onStale: "merge", Golf merges three ways by path: the base is the expectedHead tree, ours is the current head, theirs is your edited tree. Paths changed on both sides differently return 409 with a conflicts list. There is no line-level merging yet.

Safe to retry

If the head moves again or the provider refuses the update, the read, merge and push are retried, at most 3 attempts in all.

An idempotencyKey replayed with the same inputs returns the original response without a second commit; other inputs get 409. A sent write that cannot be read back holds the repository until maintenance settles it, within minutes; the same key then returns the original response.

REQUEST
POST /native/source/commit
Authorization: Bearer golf_pat_…
Content-Type: application/json
Connect-Protocol-Version: 1

{"repository": {"owner": "alice", "name": "project"},
 "branch": "agent/fix-login",
 "expectedHead": "<40-hex head you edited>",
 "message": "Fix login redirect",
 "changes": [
   {"path": "src/login.js", "content": "export …\n"},
   {"path": "bin/run", "content": "#!/bin/sh\n", "mode": "executable"},
   {"path": "old.txt", "delete": true},
   {"path": "docs/new.md", "from": "docs/old.md"}],
 "onStale": "merge",
 "idempotencyKey": "<uuid v4>"}
RESPONSE
{"repositoryId": "1", "branch": "agent/fix-login", "commitId": "…", "treeId": "…",
 "previousHead": "…", "merged": false,
 "changedPaths": [{"path": "src/login.js", "change": "modified"}]}

previousHead is empty when the branch was created. With merged: true, changedPaths compares against the head that was merged onto. Author and committer are the caller’s account.

Limits: 500 changes, 8 MiB of decoded content in total, 4 MiB a file, 64 KiB messages, 12 MiB of JSON. Paths are literal, with no .git segment. Every limit refusal names the limit.

On the hosted demo, 16 writers committing to a branch each through the Source API made 48 of 48 commits at 1.85 per second, p50 8.3 s, with no clone. On one shared branch with onStale: "merge", merges could not keep up with 16 writers: 13 of 63 succeeded, and 49 were refused after 3 merge attempts. The landing queue in AM-4 addresses that case.

05 / AGENT ACCESS · AM-3

A token that can only narrow.

Coding agents reach Golf with a personal API token. The same token works for remote MCP, the Source API and HTTPS Git.

Verified on hosted

golf_pat_ tokens

Scoped to a list of up to 100 repositories or all you can access, read or write, and an optional write branch pattern such as agent/*. With a pattern, writes to other branches and to tags are refused. Lifetimes run from 1 hour to 90 days, with up to 50 active tokens per account.

Never more than you

Every call caps the token by its owner’s current grant; a write token never administers. Changing the account’s login, email or active state ends every token at once. Revocation, expiry and account changes take effect on the next request, and a revoked token mid-request writes nothing.

Never on browser routes

Tokens are accepted only on /mcp, /native/source/* and the three Smart HTTP Git routes, and refused with 401 everywhere else, including account routes. Only the SHA-256 is stored; the secret is shown once. Create, revoke and scope refusals are audited.

Remote MCP at /mcp.

A stateless Streamable HTTP server with JSON responses. Each tool builds a request to the route the web UI uses and runs it with the caller’s own credential, so grants, token scope, feature policy, branch rules, the ref fence and audit are exactly the UI’s.

11 read tools

repo_overview, list_tree, read_files, search_code, list_commits, compare, get_issue, list_issues, get_pull_request, pull_request_diff, pipeline_status.

search_code is semantic search and needs the index.

4 write tools

commit_changes, create_branch, open_pull_request, comment.

Only write tokens see them. commit_changes and create_branch are transfers; other writes are exclusive. A refusal carries Golf’s message and data such as currentHead or conflicts. Results are capped at 256 KiB with a truncated flag.

CLAUDE CODE
claude mcp add --transport http golf <origin>/mcp --header "Authorization: Bearer <token>"

Verified on hosted: Claude Code was connected to the hosted demo’s /mcp with a token limited to one repository and agent/*, with no Access headers. Using only MCP tools it read the repository, created agent/mcp-subtract, committed a function with tests, opened a pull request and commented on it. A commit to main was refused by the branch scope, and /mcp without a token and the token on a browser route both answered 401. The token page also shows Codex and OpenCode setups; those have not been run against Golf.

06 / LANDING AT AGENT SPEED · AM-4

Policy decides. People keep the sensitive paths.

Agentic mode is a per-repository setting, off by default. Golf evaluates every open pull request against it and shows the result in a Landing panel. It does not land, queue or revert anything on its own yet.

How an agent change lands under agentic mode: the land policy compares changed paths, required checks and author kind; low-risk changes with passing checks land on their own, sensitive paths need a non-author, non-agent approver, and checks run on the base after landing with automatic revert.
The landing path. The policy is built; landing on its own, checks after landing and automatic revert are in progress.
Built · not yet on hosted

Diverged merges and squash

Native merges now use a three-way tree merge from the single merge base. Squash writes one commit with the base as its only parent. Paths both sides changed differently are refused before any write, up to 50 listed with reasons. Lines inside a file are never merged.

Built · not yet on hosted

The land policy

A pure function returns land, needs_person, waiting_checks or blocked, with every reason. Risk is sensitive if any path matches a sensitive pattern, low if every path matches a low-risk one, and normal otherwise.

Built · not yet on hosted

Approvals that count

Only writers’ reviews count. A qualifying approval comes from a writer who is not the author and not an agent, and only for the current head. Any writer’s requested changes cancel approvals. API tokens cannot submit reviews.

The agentic mode setting and its defaults when nothing is saved. Every change needs the version it read.
FieldDefaultMeaning
enabledOffEvaluate pull requests against this policy. While off, every pull request needs a person.
lowRiskPathsdocs/**, **/*.mdPatterns for low-risk paths.
sensitivePaths.github/**, .forgejo/**, .gitlab-ci.yml, deploy/**, **/CODEOWNERSAlways need approval by a writer who is not the author and not an agent.
landWithoutPersonOffA change may land without a reviewer only if every changed path is low-risk and every required check passed.
requiredChecksNone listedNames of checks that must pass. Empty means every pipeline that ran on the head commit.
revertOnFailureOnStored for automatic reverts. Golf does not revert anything yet.

A feature policy at installation, organization or repository level can turn agentic mode off, never require it. Path patterns use an anchored matcher with *, ? and whole-segment **; it never builds a regular expression.

In progress

A landing queue without a global lock

Land merges onto the current base head with the tree merge. The base update is a compare-and-swap: if stale, Golf retries up to 5 times against the new head. Overlapping paths go to needs_rebase. Different branches never wait on each other.

In progress

Checks after landing, then revert

The base push starts pipelines as usual. If a required check fails on a landed agent change and revertOnFailure is on, Golf commits a revert through the Source API, comments on the pull request and raises an issue for the original requester.

07 / AGENTIC INBOX · AM-5

Review the intent, approve in batches.

In progress. The repository’s agents page becomes an inbox, with live updates from the repository activity stream.

In progress

Four queues

In progress, ready to land, needs a person (sensitive paths, conflicts or failed checks), and recently landed with revert. Approve and land selected items in one batch.

In progress

Intent and risk summaries

Workers AI writes, for each agent pull request, what the change is for, which areas it touches and which risks it may have. Marked as AI-written, regenerated on a new head, and never a replacement for the diff.

In progress

Agent branches out of the way

Agent and token-pattern branches are hidden from the default branch list behind a toggle, and deleted automatically after landing or closing.

08 / MEASURED, NOT CLAIMED

Before and after, on a hosted deployment.

Measured on the hosted demo with the agent speed bench against eight repositories, 20 seconds per step. The evidence files are checked into the product repository.

Successes over attempts, rate and median latency. Baseline is before AM-1; after is AM-1 to AM-3.
ScenarioAgentsBaselineAfter
S2 · branch per agent, one repository160 of 3248 of 48
S2 · branch per agent, one repository640 of 6493 of 93
S3 · a repository per agent1621 of 24 at 0.38/s, p50 24 s48 of 48 at 2.19/s, p50 7.6 s
S3 · a repository per agent6451 of 64, p50 76 s93 of 93 at 1.6/s, p50 37 s
S4 · shallow clones under push load16p50 19.6 sp50 10.3 s; background pushes 39 of 39
S4 · shallow clones under push load6462 of 166 (104 refused, 429)70 of 70; background pushes 75 of 75
S6 · Source API commits, branch per writer16New in AM-248 of 48 at 1.85/s, p50 8.3 s
S6 · Source API commits, branch per writer64New in AM-261 of 93; 32 client timeouts at 60 s
S6 · Source API commits, one shared branch16New in AM-213 of 63; 49 refused after 3 merge attempts

The ceiling: total throughput levels off near 2 writes per second for a deployment. That is the single Workspace object plus the provider. The next step is a per-repository RepositoryWrites Durable Object for transfers, with the D1 fence and authority checks staying authoritative. Not yet measured on hosted: the AM-4 merges and landing panel, and API reads under push load.

09 / WHERE IT RUNS

Cloudflare-native first.

Agentic mode is built on the Cloudflare-native deployment: Artifacts for Git, D1 for the fence and journals, and Workers with Durable Objects for admission.

On Cloudflare

Concurrent Git, the Source API, API tokens, remote MCP and the land policy run there today. When Cloudflare Access protects an installation, token requests on /mcp, /native/source/ and /git/ pass to the Worker with cookies stripped; every other request still needs Access.

Self-hosted

The Docker and Kubernetes track has a local, read-only MCP server in the golf CLI, over stdio. Remote MCP, the Source API and agentic mode are not part of it today. Self-hosted track ↗

10 / GO DEEPER

The exact contracts.

Field-level behavior, error codes and the current status live in the documentation.

Agentic mode guide

The setting, path patterns, policy rules and milestones.

Read the guide ↗

Status and evidence

What has shipped, what has been verified on hosted and what is still open.

Read the status ↗

Point an agent at it.

See the milestones as they land, or connect the coding agents you already use.

Search Golf

32 pages and guides

Tab through results · Enter to open · Escape to close