Docs
How GitButler Code works: your space, organizations, pull requests, and the grit commands that go with them.
Getting started
GitButler Code hosts Git repositories over HTTPS. You work with them through Grit, a Git engine and command line written in Rust, or with any Git client.
Install Grit, then sign in. grit login opens GitButler Code in your browser to approve the sign-in, and stores an access token with your credential helper.
curl -fsSL https://grit-scm.com/install | sh grit login
GitButler Code is Grit's default host, so commands that take <owner>/<project> without a URL use https://code.gitbutler.com.
To use plain Git, make a token on the Tokens page. Git sends it as the password for fetches and pushes. There is no SSH.
Your space
Your handle is your working space. Projects at /<you>/<project> are private to you, like the copy on your laptop. Nobody else sees them, including the members of your organizations.
Push any branch you like. A push to a name you don't have yet creates the project:
grit push <you>/<project> <branch>
Your branches stay private until you share one or propose one in a pull request.
Organizations
Organizations are domains. Claim one on the Organizations page and prove it with a DNS TXT record:
Name _gitbutler-code.<domain> Type TXT Value gitbutler-code-verification=<token>
Whoever proves a domain becomes its first owner. No domain yet? <you>.gitbutler.dev is already yours and needs no proof.
Owners add and remove members. Members open projects and integrate pull requests.
Owners can also let people join by email: with Anyone with a verified @<domain> email address joins as a member checked on the organization's page, everyone who has verified an address at the domain becomes a member, now and whenever they verify one later. Add and verify addresses under Settings → Emails: GitButler Code mails a link to each address, and a verified address belongs to one account.
Canonical projects and your copy
An organization's projects live at /<domain>/<project>. Each is public, so anyone can clone it, or members only. Nobody pushes to them, owners included. Their main branch moves only when a pull request is integrated.
Your copy of a canonical project lives in your space, at /<you>/<project>. Make one with Copy into on the project's page, or let grit clone or grit sync make it for you. Your copy follows upstream: upstream's branches, usually just main, are read-only in it and brought to upstream's tip whenever your copy is used. Put your work on branches of other names.
grit clone https://code.gitbutler.com/<domain>/<project>
Syncing with grit sync
grit sync keeps a clone of a GitButler Code project and your space in step, in both directions. It:
- fetches the project and your space,
- fast-forwards your main to upstream's main,
- brings down the branches in your space that you don't have, and fast-forwards the ones that are behind,
- pushes every active branch to your space. A branch is active unless it is main, a branch your copy follows from upstream, or already merged into main.
grit sync
A branch that has moved on both sides is reported and left alone, never overwritten. Bring the two together with grit pull --rebase on that branch, then sync again.
When you clone an organization's project with grit clone, Grit points pushes at your space (it sets remote.origin.pushurl), so grit push and git push go to your copy while fetches still come from the organization. grit sync sets this up too, in a clone made some other way.
Pull requests and grit integrate
Propose a branch of your copy for the canonical project from its page, or go straight to:
https://code.gitbutler.com/<you>/<project>/pulls/new/<branch>
Opening a pull request copies the branch into the canonical repository as refs/pull/<n>/head, so everyone who can read the project sees those commits and nothing else of yours. Pushing to the branch again updates the pull request.
A member integrates it with a merge commit (Merge branch '<you>/<branch>' into main), or GitButler Code refuses and names the conflicting paths.
grit integrate
In a clone, grit integrate <branch> pushes the branch to your space and merges it into its target:
- In a copy of an organization's project, it merges into the organization's main, through a pull request that is integrated at once. This needs you to be a member. If you aren't, it tells you so and gives you the link to propose the branch instead.
- In a project of your own, it merges into that project's main.
grit integrate <branch> [--without <user>]
For a shared branch, it waits for everyone's changes unless you leave someone out with --without, and ends the share once merged.
In a snapshot checkout, grit integrate checks the branch in and merges it into the checkout's target branch, then refreshes the checkout.
Snapshot checkouts and slices
For part of a large project, check out a snapshot instead of cloning the whole history. grit checkout downloads one snapshot of main, cut down to the paths you need, and builds a normal Git repository around it. Commit as usual, then grit checkin grafts your commits back onto the real history.
grit checkout https://code.gitbutler.com/<owner>/<project> [slice] grit checkin
A slice names a part of a project people work on. Slices live in .grit/slices.toml on main, versioned with the code, so every checkout sees the same ones:
[slices.lib] description = "The library everything builds on" paths = ["grit-lib"]
grit slice lists a project's slices and adds new ones. Slices can take folders from anywhere in the project, and they can overlap.
History API
Ask the server about history instead of cloning it. GitButler Code serves gj's history RPC for every project:
POST https://code.gitbutler.com/.grit/rpc/<owner>/<project>/<method>
The methods are info (refs), graph (commit graph rows), commits, objects and prefetch (commit bodies, trees and blobs), history (the commits that changed a path), and has and update (compare-and-swap pushes). The server holds the whole history, so answers are exact even from a one-commit checkout.
Requests use the same tokens and the same access rules as Git: send the token as a bearer token or the basic-auth password. Nobody updates an organization's projects this way either.
Large files
A project can keep large files out of its history log. It is off by default. A project's owner (for a canonical project, the organization's owners) turns it on with a size limit under the project page's Settings tab. Once it is on, the project's Code menu shows how to clone it. It can't be turned off again, and projects with it on can't be copied or proposed from yet.
Pushes are unchanged. To clone, make a partial clone that fetches large files from the project's large-file store as they are checked out. The Large files page shows these commands with the project's own key and limit:
grit clone --blobs auto \
--config remote.lop.url=https://code.gitbutler.com/.grit/lop/<key> \
--config remote.lop.promisor=true \
--config promisor.acceptFromServer=knownUrl \
https://code.gitbutler.com/<owner>/<project>
git clone --filter=blob:limit=<limit> \
-c remote.lop.url=https://code.gitbutler.com/.grit/lop/<key> \
-c remote.lop.promisor=true \
-c promisor.acceptFromServer=knownUrl \
https://code.gitbutler.com/<owner>/<project> # Git 2.49 or newer
A clone without the filter, or Git before 2.49, fails on files only the store holds.
Agents
Hand your agent the prompt from the home page. It installs Grit, reads the docs written for agents, and learns where its work goes: its own branches in your space, proposed back when they're ready.
To set an agent up by hand, point it at grit-scm.com/llms.txt and the agent guide, and save the Grit skill where it will find it:
mkdir -p .agents/skills/grit && grit skill > .agents/skills/grit/SKILL.md
Agents should pass --markdown to every grit command, read the result from stdout, and check the exit code. Use --json instead when a script needs to parse the output. If an agent isn't signed in, it should ask you to run grit login.
Git compatibility
GitButler Code serves Git's smart HTTP protocol, versions 0, 1 and 2, through Grit, so any Git client works: clone, fetch and push as usual. It is HTTPS only; there is no SSH. Use a token from the Tokens page as the password, or let grit login store one for you.
git clone https://code.gitbutler.com/<owner>/<project>
For everything else Grit does, see the Grit docs.