gitai is an open source Git server for coding agents, inspired by Anthropic's internal Scion. Each agent writes under its own token, but only in standalone mode is the agent kept from naming a different user.
gitai binds each coding agent’s writes to its own token. One config flag decides whether that holds
Published October 23, 2026 · Last reviewed October 23, 2026
In May 2026 Anthropic merged about 2,500 code changes a day. By September it was merging more than 30,000, and source control, builds and CI, all built for human-scale work, had become the bottleneck.12 On October 13 the company described Scion, the server-centric version control system it built to replace its Git setup, and called it “by no means a suitable replacement for git for general use.”1 The Register reports there will be no open source release.3
Two days later an independent developer published an MIT-licensed server that implements the publicly described design on top of ordinary Git repositories. It shipped as open_scion and was renamed gitai (repository feder-cr/git-ai) the next day.4 Four more releases followed in eight days, the latest, v0.4.0, on October 23.5 That morning the repository had about 970 GitHub stars, which measures attention, not production use.6
Anthropic’s post is mostly about speed. The more useful part of gitai is smaller and easier to check: its documentation says exactly which caller identity a write is judged by, and which deployment setting makes that guarantee disappear. That boundary is worth understanding before anyone generalizes from “each agent has its own token” to “we know who did this.”
What shipped: an open source take on a design Anthropic kept in-house
Scion moves the work to the server: instead of every client holding a full copy of a monorepo with almost 100 GB of history, the server answers history questions, creates commits and runs merges, and each update is a changeset in a write-ahead log.1 The post mentions access control and per-directory permissions but does not describe how Scion identifies an agent.
gitai is not that system, and its README says it is “not affiliated with or endorsed by Anthropic.”7 It starts from a fork of Gitaly, GitLab’s Git RPC server, leaving out upstream’s non-MIT ee/ directory, and adds a layer it calls Graft: per-agent tokens, an RPC allowlist, branch policies, server-side landing with a compare-and-swap per reference, a changeset log and a review service. Its identity model is the maintainer’s own design, and the README marks interfaces as subject to change before 1.0.7
The README’s headline benchmark compares gitai with the same server with batching turned off, not with ordinary Git hosting, in two runs on one 16-core machine with a shared file that “conflicts by design.”8 It shows that batching helps this server under contention, and nothing broader.
Follow one write: five fields that all look like “who did this”
Take one agent, configured as a [[graft.agent]] entry with its own token_file, asking a standalone gitai server to land a change on a protected branch. The request touches five things that could each be read as “who did this,” and gitai treats them differently.
- The credential. The server compares the token in constant time and takes the caller’s identity from it. In the security document’s words: “Agent identity is taken from the token, never from the request.”9
- The request’s identity fields. Gitaly requests carry
gl_idandgl_username. For a caller with an agent token, the request-defaults code sets both to the agent’s name “even when the client sent another value.”10 It does not compare the two first; it overwrites. Callers using the shared token keep whatever they sent. - The policy actor.
[[graft.policy]]rules decide which actors may update which references, including theHEADsymbolic ref, so an agent cannot repointHEADaround a protected branch. A differentgl_idfrom the client does not change the decision.11 - The changeset actor. The log records the token’s identity: the agent’s name, or
sharedfor the shared token. When the server batches concurrent lands into one update, the batch entry’s actor isgraft-batchand each member keeps its agent’s name, though a member list longer than 32 KiB is cut and flagged as incomplete.1112 - The committer and the author. The committer name and email of new commits are kept as the client sent them, and author fields come from the client’s own commits.11 They are text the client supplies.
In standalone mode, then, the token, the policy actor and the changeset actor all name the same configured agent, while the author and committer fields can say anything. Reviews follow the token too, so one agent cannot approve as another, but the review document adds that “landing does not check reviews yet.”913
Those agreeing fields are a local label the operator wrote into a config file, bound to a secret the operator handed out. They say this credential made this change. They do not say which person or company the agent works for, whether that person approved this change, or anything a party outside the server could check, and gitai does not claim they do. An IETF Internet-Draft on agent identity, revised on October 1, names the same gap: a workload identity alone “may not identify the user or organization accountable” for what an agent does.14
How GitHub and GitLab label agent writes
The hosted platforms draw the same line between what a client claims and what the server knows, and some go further. GitHub’s Copilot cloud agent (formerly the Copilot coding agent) authors its own commits and lists the person who assigned the task as co-author, and since April 3 it has signed every commit it makes.15 On October 12 GitHub opened a limited preview of push attribution for Enterprise customers. It records the authenticated pusher next to each commit, because “Commit author and committer fields are just strings that the pushing client supplies.”16 GitLab’s composite identity, generally available since GitLab 18.8, “combines two identities into a single token”: the agent’s service account and the person who started the request, with the lower of the two roles applied.17
gitai’s agent token covers the first half of that pair. It names the agent. Nothing in it names the person who set the agent running, and signed changesets are still a roadmap item.11
The flag that moves the boundary
Everything above assumes one setting. With graft.standalone = true it does its own access checks and hooks and needs no GitLab. Otherwise it sits behind GitLab the way upstream Gitaly does, and GitLab’s /allowed endpoint makes the access decision.11
The server installs the request defaults that write the agent’s name into the identity fields only when graft.standalone is true, and only on its external listener.18 The limitations document spells out what follows when they are off: with agents configured but standalone mode disabled, the gl_id and gl_username an agent sends reach GitLab’s /allowed check unchanged, “so an agent can act as any GitLab user.”11
The same agent with the same token can therefore end up with two identities: in standalone mode it cannot claim another actor, and behind GitLab the identity checked is whatever the agent typed.
Version 0.4.0, released on October 23, took one agent rule out from under the flag: agents can no longer write the server’s own refs/graft/ references in any mode.5 The identity overwrite still depends on standalone mode.
The second exception is the shared token, the upstream Gitaly credential that operators keep. The limitations document calls it an administrative credential whose holder can act as any user, as with upstream Gitaly and GitLab, and the security document says it is an operator credential, not an agent.119 If an agent’s runtime can reach that secret, per-agent tokens stop meaning much, and the log records shared instead of a name.
None of this is an exploit. The project documents its own boundary, and the practical reading is narrow:
- What per-agent tokens guarantee depends on the deployment, and standalone mode is off by default.19 Check
graft.standalonebefore relying on it. - Keep the shared token out of every agent’s environment.
- Treat commit author and committer fields as client input in either mode.
”Success” needs evidence: what the releases fixed and what the log can miss
Authority is one half of trusting an agent’s write. The other half is whether “done” means done, and two fixes in v0.2.0, released on October 18, are about that.20
The first concerns committer dates. The release notes say landing decisions are now “exact when committer dates are skewed”: an inexact history check could refuse an already landed commit or merge it a second time, and the rebase operations, which come from Gitaly, had the same exposure.20 Committer dates are client-supplied text, the same field the previous sections said not to trust. Here the text fed a correctness decision, not attribution.
The second concerns squashes. UserSquash, an RPC inherited from Gitaly that agents can call only if an operator adds it to graft.agent_rpcs, could report success without a commit when a merge failed for a reason other than a conflict.9 A caller that trusts the return value would carry on as if its change had been squashed. Version 0.3.1 fixed a related case, in which a land answered already_landed for a branch that did not exist.21
The changeset log, the record of what happened, has documented edges too:11
- Only reference updates that pass through Gitaly’s transaction path are recorded. Tools that write to the repository directly are not.
- With the default file log, a recording error cannot undo an update git has already committed, so the log can miss it; each loss is counted in a metric. With the optional storage core in authoritative mode, the log is written in the same database transaction as the update.
- Signed changesets and a verifiable export of the log are on a roadmap the project says is not a commitment.
So the log is careful operational evidence kept by the operator, not a tamper-evident audit trail a third party could verify. Our look at Strands Box found the same shape one layer down: decision records that belonged to the operator, unsigned, with every agent inside the sandbox named self.
How this connects to Tobira
gitai answers a question inside one organization: may this credential change this branch? Tobira works on a different question, the one that comes up when an agent leaves the systems its operator controls and meets a stranger’s agent: whom does the agent represent, and do both humans want to be introduced? A Tobira @handle gives the person or company an agent represents an address another agent can look up (the network had 729 agents per Tobira internal data, September 2026), and mutual reveal shares contact details only after both sides agree. None of that replaces repository authorization, tests or audit logs. It sits next to them, at the relationship boundary a repository token was never meant to cover.
What to remember
- gitai is not Scion. It is an independent MIT-licensed Gitaly fork, first published as open_scion, built from Anthropic’s public description of an internal system.
- The token names the agent, not the person. In standalone mode the token, the policy actor and the changeset actor agree. Commit author and committer text is whatever the client sent. GitHub and GitLab now record more: the pusher, a signature, or the person who started the agent.
- One flag decides whether it holds. With
graft.standaloneoff, an agent’sgl_idandgl_usernamereach GitLab’s/allowedcheck unchanged, and the shared token can act as any user in every mode. - Success reports and the log are the operator’s evidence. The releases fixed false successes. The default log can miss updates, reviews do not gate landing yet, and signing is only on the roadmap.
Anthropic’s 30,000 merges a day land on a server nobody outside the company can run. The open implementation ships with its boundary written down: one setting, graft.standalone, in a file called LIMITATIONS.md.
Frequently asked questions
What is gitai?
gitai (repository feder-cr/git-ai) is an open source, Git-compatible version control server for many coding agents working at once. It is MIT licensed, forked from GitLab’s Gitaly, and adds per-agent tokens, branch policies, server-side landing and a changeset log. It was first published as open_scion on October 15, 2026, renamed the next day, and reached v0.4.0 on October 23. It implements the publicly described design of Anthropic’s internal Scion and is not affiliated with Anthropic.
Can an agent act as another user in gitai?
It depends on the deployment. In standalone mode, an agent token cannot claim another actor: the server overwrites the request’s identity fields with the agent’s name. With agents configured but standalone mode off, the documentation says the identity fields an agent sends reach GitLab’s /allowed check unchanged, so the agent can act as any GitLab user. The shared token is an administrative credential in every mode.
How do GitHub and GitLab label agent writes?
GitHub’s Copilot cloud agent authors its commits, lists the person who assigned the task as co-author and signs every commit. GitHub is also previewing push attribution for Enterprise customers, which records the authenticated pusher next to each commit. GitLab’s composite identity puts the agent’s service account and the person who started it into one token. gitai’s agent token names only the agent.
Does gitai’s changeset log prove who did what?
It records which configured token made each reference update that passed through Gitaly’s transaction path. Direct repository writes are not recorded, the default file log can miss an update when recording fails, and signed changesets with a verifiable export are only on the roadmap. It does not identify the human or company behind an agent.
Sources
Footnotes
-
Nick G. and the Anthropic source control team, “Redesigning source control at Anthropic,” Anthropic Engineering, October 13, 2026, updated October 15 with more detail on prior art (Google’s Piper, Meta’s Sapling and Mononoke): about 2,500 merged changes a day in May 2026 and over 30,000 a day by September; infrastructure built for human scale became the bottleneck; main branch history almost 100 GB; the server answers history and blame, creates commits and runs merges and rebases; changesets in a write-ahead log; an access control system and per-directory permissions are mentioned but not described. anthropic.com ↩ ↩2 ↩3
-
Simon Willison, “Redesigning source control at Anthropic,” October 13, 2026: the 2,500 and 30,000 merges a day figures, with an update on the Piper and Sapling prior art. simonwillison.net ↩
-
Thomas Claburn, “Anthropic reinvents source control as Claude floods the world with code,” The Register, October 13, 2026: Anthropic says Scion is not right for general use, and The Register reports there will be no open source release. theregister.com ↩
-
feder-cr/git-ai, the v0.1.0 tag of October 15, 2026 on commit
3a496a3, annotated as the first public release of open_scion 0.1.0, github.com ; commit81602edof October 16, 2026, which renames the project to gitai (repository git-ai), github.com. The v0.1.0 release page now carries the gitai name. ↩ -
feder-cr/git-ai, release v0.4.0, published October 23, 2026: agents can no longer write
refs/graft/in any mode,SSHUploadArchiveis closed to agents, and operation RPCs read branch names exactly. github.com ↩ ↩2 -
feder-cr/git-ai repository page, viewed October 23, 2026: about 970 stars (972 that morning); created October 15, 2026; the README and LICENSE state MIT. Stars measure attention, not adoption. github.com ↩
-
feder-cr/git-ai, README at the v0.4.0 tag (commit
7fa012f), read October 23, 2026: an independent implementation of the publicly described design, not affiliated with Anthropic; a fork of Gitaly without the non-MITee/directory; the Graft features; interfaces may change before 1.0; the headline benchmark against the same server with batching off. github.com ↩ ↩2 -
feder-cr/git-ai,
doc/graft/BENCH.mdat7fa012f: Intel Core Ultra 7 255H, 16 logical CPUs, WSL2; a synthetic workload in which a shared file conflicts by design (a 20% conflict rate); high machine load during the runs; the maintainer asks readers to quote the figures with the machine and rerun before comparing. github.com ↩ -
feder-cr/git-ai,
doc/graft/AGENT-SECURITY.mdat7fa012f, read October 23, 2026: per-agenttoken_filecompared in constant time; identity from the token, not the request; the built-in RPC allowlist for agents (ininternal/gitaly/server/auth/agent_methods.go, the operation RPCsUserLand,UserCommitFiles,UserCreateBranchandUserDeleteBranch), extended only throughgraft.agent_rpcs; reviews record the token’s identity, so an agent cannot approve as another agent; the shared token is an operator credential, not an agent. github.com ↩ ↩2 ↩3 ↩4 -
feder-cr/git-ai,
internal/graft/requestdefaults/requestdefaults.goat7fa012f: the package comment describes a standalone server; identity fields of an agent-token caller are always set to the agent name, overwriting what the client sent; shared-token and anonymous callers keep their values. github.com ↩ -
feder-cr/git-ai,
doc/graft/LIMITATIONS.mdat7fa012f, read October 23, 2026: the policy decides on the token’s agent name in standalone mode and a client-sentgl_iddoes not change that; committer name and email kept as sent; the shared token is an administrative credential that can act as any user; the changeset actor is the token identity; the request defaults run only whengraft.standalone = true, and otherwise agent-sentgl_idandgl_usernamepass to GitLab’s/allowedcheck unchanged; only updates through the transaction path are recorded; with the file log a recording error cannot fail an update and losses are counted, while authoritative mode writes the log in the update’s transaction; signed changesets and a verifiable export are on the roadmap, which is not a commitment. github.com ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 -
feder-cr/git-ai,
doc/graft/LAND-BATCHING.mdat7fa012f: a combined update is made as the synthetic usergraft-batch, recorded with that actor, and its members carry the real actors. github.com ↩ -
feder-cr/git-ai,
doc/graft/REVIEW.mdat7fa012f: phase 5a stops at review state; a required approved review and per-directory write permissions are planned for phase 5b. github.com ↩ -
Y. Ni, C. P. Liu and M. Richardson, “WIMSE Applicability for AI Agents,” draft-ni-wimse-ai-agent-identity-03, October 1, 2026, an Informational Internet-Draft and work in progress, not a standard. ietf.org ↩
-
GitHub Changelog, “Trace any Copilot coding agent commit to its session logs,” March 20, 2026: commits are authored by Copilot with the person who gave the task as co-author, github.blog; “Copilot cloud agent signs its commits,” April 3, 2026, github.blog ↩
-
GitHub Changelog, “Push attribution for commits in limited public preview,” October 12, 2026: a durable, authenticated pusher identity for each commit, shown next to author and committer, and a rule that blocks pushes whose committer does not match the pusher; limited preview for GitHub Enterprise customers. github.blog ↩
-
GitLab Docs, “Composite identity,” read October 23, 2026: a service account (the agent) and the human who started the request in one token; the flow gets the lower of the user’s role and the service account’s Developer role; agent commits are attributed to the service account and merge requests a flow creates to the human; introduced in GitLab 18.3, generally available in 18.8. docs.gitlab.com ↩
-
feder-cr/git-ai,
internal/gitaly/server/server.goat7fa012f, lines 157 to 181: the request-defaults interceptors are installed only on the external server and only whenGraft.Standaloneis set. github.com ↩ -
feder-cr/git-ai,
doc/graft/CONFIGURATION.mdat7fa012f:standaloneis a boolean that defaults tofalse; request defaults are applied on the external server in standalone mode. github.com ↩ -
feder-cr/git-ai, release v0.2.0, published October 18, 2026 (UTC): landing decisions exact under skewed committer dates, with the rebase paths fixed too;
UserSquashno longer reports success with an empty commit when a merge fails for a reason other than a conflict; faster landing decisions. The commit history shows the inexact landing check was introduced and fixed on October 18, before the tag. github.com ↩ ↩2 -
feder-cr/git-ai, release v0.3.1, published October 22, 2026:
UserLandresolves its branch by its exact name and no longer answersalready_landedfor a branch that does not exist (pull request #6). github.com ↩