---
title: "Fir: version control built for agents · Frazer"
description: "Frazer Fir is version control and code review for teams whose code is mostly written by agents: a workspace per session on the server, pull requests that keep their identity through every rebase, a merge queue that keeps up with agents, and search that is exact at any commit. Git comes in and goes out."
url: https://frazer.ai/source
index: https://frazer.ai/llms.txt
tokens: 4642
---

> For agents: every page on frazer.ai is indexed at https://frazer.ai/llms.txt.

# Fir: version control built for agents · Frazer

**Fir**  Frazer version control

# Version control built for agents.  
Not a layer over git.

Frazer Fir is version control and code review for teams whose code is mostly written by agents. Every session works in its own workspace on the server, every pull request keeps its identity through every rebase, the merge queue keeps up with agents, and search is exact at any commit. Bring your git history in, and take it out whenever you like.

[Import a repository](https://frazer.ai/start?product=source) [Frazer CI on Fir](https://frazer.ai/ci)

`fir` for Linux, macOS and Windows  VS Code and JetBrains  Frazer app and console  API and MCP

Pull requests

One identity through every rebase, stacks, conflicts stored as data

Workspaces

One per session, on the server, a snapshot on every tool call

Merging

A merge queue per protected branch; deploys read `main@verified`

Leaving

Export to plain git at any time, history intact

```
$ fir status
ws/s-81f2 · lena/retry-errors · base main@48213
$ fir stack
○ #483  Log every webhook retry        v1  checks …
◉ #482  Retry payment webhooks on 5xx  v3  checks ✓
$ fir pr merge 482 --auto
queued  main · merge queue · risk 0.62
merged  main@48217 · verified at 48219
```

```
→ search_code { "queries": [{ "literal": "retryable(" }],
                "at": "ws/s-81f2" }
← 6 matches · main@48213 + overlay · complete
→ edit_file { "path": "libs/go/retry/budget.go",
    "old": "MaxAttempts = 3", "new": "MaxAttempts = 5" }
← snapshot 42 · parse ok
→ merge_pull_request { "pull_request": 482, "auto_merge": true }
← queued on main · merge queue
```

```
$ frazer source repositories import \
    --from https://git.acme.example/storefront.git --plan
Plan  import storefront.git → acme/storefront
  history   8,412 commits · original IDs kept
  owners    CODEOWNERS → 6 OWNERS files, 4 teams
  ignore    .gitignore → .fir/ignore · LFS → content
  lint      7 git calls in CI and scripts, each replaced
  rehearse  one-way, read-only until cutover
```

00 · A pull request, as a reviewer sees it Fig. 1 · product UI, demo data

*A pull request in the Fir console, product UI with demo data: #482 “Retry payment webhooks on 5xx” in acme/storefront, version 3, pull request 2 of a stack of 3, from the branch lena/retry-errors into main, written by the agent coder for lena and waiting for 1 approval. The screen shows the stack and its versions, the pull request’s intent labeled as untrusted text from an issue with no drift, the diff with a Reviewer finding reproduced at version 2 and resolved at version 3, the merge policy with its risk score, the approval rules with 2 of 3 met, the evidence at version 3 and the creation record with attested fields.*

Fig. 1: a pull request in the Fir console as a reviewer sees it, product UI with demo data.

A

**Intent, labeled by trust** What the pull request is for. Text copied from an issue, as here, is labeled untrusted; the Reviewer checks the diff against it.

B

**A stack, every version kept** Pull requests keep their identity through every rebase; comparing versions hides rebase-only edits.

C

**Findings as objects** Keyed to the pull request: reproduced at version 2, resolved at version 3, never copied between versions.

D

**Rules decide who approves** OWNERS files and pull request classes set the approvals; the verifier’s PASS names this version.

01 · No legacy

## No git underneath.  
Nothing to work around.

Git was built for people sending patches. At agent scale its parts become the bottleneck: a hash being phased out, a protocol that grows with history, an index file per clone, branch names every server must agree on.

Fir replaces each part instead of wrapping it. Git stays at the boundary, as a format we read on the way in and write on the way out.

Git and Fir, part by part

|  | In git | In Fir |
| --- | --- | --- |
| Object IDs | SHA-1, with a move to SHA-256 under way for years | BLAKE3, each ID tagged with its algorithm, so a new hash is a rehash |
| Fetching | A protocol whose cost grows with history; large replies that cannot resume | Wanted objects only, immutable and cached in every site; every request resumes |
| Maintenance | Packfiles, gc and repack on clients and servers | Immutable segments; nothing for clients to maintain |
| Working copy | An index file per clone, ignore rules that differ per machine | What is on disk is the next commit, with no staging step; one .fir/ignore per repository |
| Unit of work | A branch of commits that every rebase rewrites | Pull requests that keep one identity through every rebase; protected branches with sequence numbers |
| History | A full clone of every commit on every machine | History on demand; virtual and sparse workspaces |
| Rules | Hook scripts on laptops that nobody can enforce | Checks on the server, on every snapshot and every merge |
| Rewrites | rebase -i, stash and cherry-pick, many commands per intent | One call each: split, squash, reorder, absorb, backport |
| Signatures | GPG keys on every laptop and sandbox | Signatures bound to identity; the server attests for agents |

02 · In and out Fig. 2

## Bring your history in.  
Take it out whenever you like.

Import reads any git repository with its full history and keeps every original commit ID, so old links and tags still resolve. A rehearsal copy follows the repository one way until you are ready to move.

Export writes a plain git repository at any time. That is our promise of no lock-in, and an exit drill proves it every quarter.

**Fig. 2** Import, rehearse, cut over; export at any time one-way in, one-way out

1.  **Inventory** Size, history, large files, submodules, and a lint that lists every git call in the repository, its CI and its build scripts, with the replacement for each.
    
2.  **Import** Full history in. Owners, branch rules and ignore files become OWNERS files, path rules and merge policies you can read before you accept them.
    
3.  **Rehearse** For at least a week, agents, CI and devboxes read the Fir copy while people keep writing on git. Compare speed, cost and success.
    
4.  **Cut over** In one window: git becomes read-only, a final sync runs, the copy becomes writable and open pull requests move over to Fir.
    

03 · Pull requests Fig. 3

## Pull requests that keep their identity.  
Every version kept.

A pull request is one piece of work with a number that survives every rebase. Each update adds a version, and review compares any two, with rebase-only edits set apart from the author’s.

Branches stay simple: `main` and a few protected branches with numbered commits, plus your own branches if you want them.

**Fig. 3** A stack, the versions of one pull request, and the activity log demo data

1.  ### One identity per pull request
    
    An agent or a person names work by its pull request number. Rebases and amendments make new versions, never new pull requests.
    
2.  ### Stacks that rebase themselves
    
    Update a pull request and the server rebases every one stacked above it. A stack merges as one batch.
    
3.  ### Conflicts as data
    
    A conflicted pull request can be reviewed, rebased and repaired. It cannot merge until it is resolved.
    
4.  ### Undo anything
    
    Every snapshot, rebase and merge is in the activity log. Undo restores the state before it; a merged pull request is reverted, never erased.
    
5.  ### History in one call
    
    Split, squash, reorder, absorb, move a hunk or backport, each one call with a dry-run plan.
    
6.  ### Two writers, no lost write
    
    Every rewrite names the version it replaces. A stale write fails or is kept as a divergent version to resolve.
    

04 · Merging and @verified Fig. 4

## Merge at agent rates.  
Deploy only what passed.

Every protected branch has a merge queue. It takes pull requests in batches, fair across agent fleets, campaigns and people, rebases each in memory and moves the branch with one compare-and-swap. Nothing is announced before it can be read.

Merged is not the same as deployable. `main@verified` moves only to commits whose checks passed after merging, and it is what deploys, seeds and new agent work read.

**Fig. 4** Batches move the branch; main@verified follows only green commits; a culprit is found and reverted demo data

-   direct
    
    ### Merge now, verify after
    
    The pull request merges once its own checks pass. CI verifies the branch in ranges; a failure is bisected and the culprit reverted.
    
    right for
    
    Leaf code, tests, docs, most agent pull requests
    
    rate
    
    High
    
-   queue
    
    ### Verify on the tip, then merge
    
    The pull request is checked on top of the current tip. Pull requests with separate paths and build targets never wait for each other.
    
    right for
    
    Schemas, migrations, auth, release branches
    
    rate
    
    Lower, never starved
    
-   hybrid · default
    
    ### Chosen per pull request
    
    A risk score picks direct or queue for each pull request from its class, paths, author and evidence. Paths with a fixed policy always use it.
    
    right for
    
    Most repositories
    
    shown
    
    The score and its inputs, on the pull request
    

05 · Search Fig. 5

## Search that is exact.  
At any commit, in any workspace.

Fir owns the content and computes its index as part of every commit, so a search answers at the commit you name, including the edits in your workspace that are not saved yet.

Agents search in batches of up to 16 queries with capped replies, the way they already work. People get the same engine in the console, the CLI and the editor.

*Fir search in the console, product UI with demo data: the regex pgxpool\.(New|NewWithConfig)\( in the Go code of the repository acme/storefront at main@48213, plus the agent workspace ws/s-9c04. 5 matches in 4 files; the reply names the commit it resolved, how far the index reached, the 1 file read from the workspace overlay, and that it is complete. A side panel shows the symbol pgxpool.NewWithConfig with 31 precise references in 18 files, sealed paths not searched, and the same query for agents: the search_code tool, batches of up to 16 queries, a reply capped at 312 tokens.*

**Fig. 5** One Go query at main@48213, plus an agent’s workspace that is not snapshotted yet product UI, demo data

-   **Literal, regex and symbols** Path and language filters, definitions and references, counts per file first.
-   **Exact at any commit** Every reply says the commit it answered and whether it is complete. Nothing is silently cut.
-   **Your workspace included** The index at your base, plus a scan of what you have not snapshotted yet.
-   **Permission-aware** Sealed paths are never searched for people without access, and nothing leaks through scores.

06 · Workspaces Fig. 6

## A workspace for every session.  
Nothing is ever lost.

Each agent session, person’s task or CI job that writes gets a workspace on the server: a base, a sparse profile and a chain of snapshots. Agents that only use the API never mount anything; those with a shell get a virtual or sparse checkout.

A sandbox that dies loses seconds of work at most. Forking a workspace copies nothing, so three attempts at one task cost one checkout.

**Fig. 6** Snapshots, undo and a three-way fork in one agent session demo data

07 · Provenance Fig. 7

## Who and what wrote every line.  
Recorded when it is written.

Every pull request carries a creation record: who asked, which agent and harness, which model, which session and prompt. Each field says whether the server attested it or the client only asserted it, and only attested fields count as evidence.

At merge the cell signs the record with the evidence that let the pull request merge. AI-blame reads it per line; exports carry it with the code.

*AI-blame on services/payments/webhook/deliverer.go in acme/storefront at main@48241, product UI with demo data. Lines by amara carry the label “no agent evidence”, lines imported from git are “unattested”, and two lines from the agent coder working for lena are “attested”. The creation record of that pull request, #483 version 2, lists the principal, on behalf of, session, agent and harness, model and prompt as attested by the server, and the tool call and client as asserted by the client. At merge on main@48231 the cell signed the evidence (checks, approvals, verifier, risk), verifiable offline and exported as git notes and a sidecar.*

**Fig. 7** AI-blame on one file: a person’s lines, imported history and an agent’s lines product UI, demo data

“No agent evidence” means just that: a person can paste an agent’s output, so blame never claims a line was written by hand. The number that matters is the share of merged lines with attested provenance.

08 · Every way in

## Your editor, your terminal,  
and every agent harness.

Files are ordinary files on disk, so every editor, compiler and test runner works unchanged. Adapters for agent harnesses replace their git calls with Fir’s, and a skill teaches the rest.

-   ### fir CLI
    
    Linux, macOS and Windows. JSON everywhere, no prompts, `--dry-run` on every write.
    
-   ### VS Code
    
    Workspace edits, snapshots, the stack, inline review and the AI-blame gutter.
    
-   ### JetBrains
    
    The same, through the IntelliJ version-control API.
    
-   ### Frazer app
    
    Pull requests and the review queue next to the agent sessions that made them.
    
-   ### Console
    
    Repositories, pull requests, branches and the merge queue, imports and exports, search, settings.
    
-   ### MCP tools
    
    A small default toolset: read, outline, search, edit, diff, snapshot, merge, blame.
    
-   ### API and SDKs
    
    Connect, gRPC and REST from one contract; Go, TypeScript, Python and Rust.
    
-   ### Go module proxy
    
    Go modules resolve from Fir, with no git anywhere in the build.
    

09 · Performance

## Fast where agents spend their time.  
Every number is a target until measured.

These are the targets Fir is built and tested against, on a large monorepo with a warm site cache. Each becomes a claim only when we publish the measurement, the method and the commit that produced it.

Fir’s performance targets per operation, p50 and p99, and how each is met

| Operation | p50 | p99 | How |
| --- | --- | --- | --- |
| New agent workspace, created or forked | ≤ 300 mstarget | ≤ 1 starget | A row and a lazy mount; no files copied |
| Read-only checkout in a CI job | ≤ 1 starget | ≤ 3 starget | A cache in the site, prefetched when the job is queued |
| Status | ≤ 10 mstarget | ≤ 50 mstarget | A file-watcher journal |
| Snapshot of 10 files | ≤ 100 mstarget | ≤ 400 mstarget | Written on the server, no packing |
| Clean rebase | ≤ 150 mstarget | ≤ 600 mstarget | On the server, in time proportional to the diff |
| Merge, request to readable | ≤ 400 mstarget | ≤ 2 starget | Batches, one compare-and-swap each |
| Merges on one branch | ≥ 500 a secondtarget | — | Clean pull requests in batches of up to 64 |
| Exact search, selective query | ≤ 10 mstarget | ≤ 100 mstarget | An n-gram index in every site |
| Context pack for an agent, 32k tokens | ≤ 150 mstarget | ≤ 500 mstarget | Byte-identical across replicas, so prompt caches stay warm |

10 · Pricing

## No seats for agents.  
Pay for what you store.

Stacks, review, automated approvals and the merge queue carry no price of their own. Fir charges for the data it stores, counted once after deduplication. On your own servers, its caches, search and daemons are part of the per-core fee.

[See every price](https://frazer.ai/pricing#lines)

Your servers **Included**: caches, search and daemons, in $1.50 per physical core per month

Stored data $0.012 per GiB-month, counted once after deduplication

Workspaces, merges, search **Free**, within fair use and per-project quotas

Model work Summaries and repairs at the LLM gateway’s rates: the provider’s list price plus 5 %, or your own key at no fee

Egress No egress fees within fair use

Seats **None**, for people or agents

Questions

## Fir, answered.

[Frazer CI on Fir](https://frazer.ai/ci)

Is Fir compatible with git?

No, on purpose. Fir has its own object format, protocol and pull request model, built for agents at scale. Git is a format Fir reads and writes at the boundary: import brings a repository in with its full history, and export writes plain git whenever you ask.

Can we leave?

Yes, at any time. Export writes a plain git repository: imported history comes back bit for bit with its original commit IDs, and work done in Fir becomes ordinary commits. Review comments, approvals, checks and provenance travel in a sidecar. The exit drill shows it working on a test repository.

What about tools that only speak git?

Before you move, a lint lists every git call in the repository, its CI and its build scripts, with the replacement: `FIR_REVISION` and `fir describe` for version stamps, server-side rules for hooks, Frazer CI for CI, the Go module proxy for Go modules. A read-only publish mirror to GitHub or GitLab serves tools that need to see the code there.

Do our editors and build tools still work?

Yes. Files are ordinary files on disk, so editors, compilers and test runners work unchanged. The VS Code extension and the JetBrains plugin add pull requests, stacks, review and AI-blame; agents use the API and MCP tools directly.

Where does it run?

Managed in every Frazer site, with a cache next to your runners, devboxes and agents, on your servers or ours. Reads keep working when the cell is down. Running Fir on your own infrastructure, with no Frazer cell, is the enterprise edition: the same binaries on Postgres and any S3-compatible store. [Talk to us](https://frazer.ai/contact?topic=enterprise).

## More in Build and ship

-   [**Frazer CI** Native CI on Frazer Runners](https://frazer.ai/ci)
-   [**GitHub runners** GitHub Actions in a microVM](https://frazer.ai/runners/github)
-   [**Cache** One cache for CI and boxes](https://frazer.ai/runners/github#cache)
-   [**Registry** Images and models, signed](https://frazer.ai/registry)
-   [**Environments and GitOps** Connect a repo, roll out](https://frazer.ai/gitops)
-   [**Templates and previews** A preview per pull request](https://frazer.ai/previews)

## Bring one repository.  
Keep your history, and your way out.

[Import a repository](https://frazer.ai/start?product=source) [Frazer CI on Fir](https://frazer.ai/ci)
