Elffuss Braid

Elffuss Braid · pre-alpha · Apache-2.0Elffuss Braid · pre-alfa · Apache-2.0

Many agents. One main. No retry loop.Muchos agentes. Un solo main. Sin reintentos.

Version control for repositories where many agents land changes at the same time.

Control de versiones para repositorios en los que muchos agentes aterrizan cambios a la vez.

Written from scratch in Rust. Each agent commits in its own workspace, and a change that fell behind is rebased onto whatever landed first. Git stays at the edges, so GitHub keeps working.

Escrito desde cero en Rust. Cada agente hace commit en su propio espacio de trabajo, y si un cambio se ha quedado atrás, braid le hace rebase sobre lo que haya aterrizado antes. Git se queda en los bordes, así que GitHub sigue funcionando.

Pre-alpha. Keep your git repository as the source of truth.Pre-alfa: tu repositorio de git sigue siendo la fuente de verdad.

[agent-c] $ braid land
Landed e39b1668831b on main (fast-forward)
[agent-a] $ braid land
Landed on main as e0c85ddea85b, rebased onto e39b1668831b (1 path merged)
[agent-b] $ braid land
65bb04180402 conflicts with main at e0c85ddea85b; main did not move: exit 2
The first line of each landing in the scene below. Two changes land. The third touched the same line as another, so main stays where it was and the conflict comes back as data.La primera línea de cada aterrizaje de la escena que viene a continuación. Entran dos cambios. El tercero tocó la misma línea que otro, así que main se queda donde estaba y el conflicto vuelve como datos.

The sceneLa escena

Three agents, one mainTres agentes, un solo main

1. Three agents, one fileTres agentes, un fichero

Three agents get three small tasks in the same repository. Two of them, A and B, are asked to reword the same line of notes.txt. The third, C, only adds a line at the end. They finish within moments of each other.

Tres agentes reciben tres encargos pequeños en el mismo repositorio. A dos de ellos, A y B, les toca reescribir la misma línea de notes.txt. El tercero, C, solo añade una línea al final. Terminan casi a la vez.

  • agent-a · notes.txt
    - alpha
    + alpha, from a
  • agent-b · notes.txt
    - alpha
    + alpha, from b
  • agent-c · notes.txt
      gamma
    + delta, from c

2. In git, they step on each otherEn git, se pisan

Put them in one checkout and they trip over its single index:

Si trabajan en la misma copia, chocan con el índice, porque solo hay uno:

git
fatal: Unable to create '…/.git/index.lock': File exists.
Another git process seems to be running in this repository, e.g. …

So each one gets a clone of its own, and the fight moves to the push. C gets in first. A is turned away:

Así que cada uno se lleva su propio clon, y la pelea pasa al push. C llega primero. Al agente A le rechazan el suyo:

agent-a · git push
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to '…/remote.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. …

A fetches, rebases and pushes again. B is turned away too: its rebase runs into A's edit, it fixes the conflict and pushes again, and if anyone got in meanwhile, it is turned away once more. Every agent that loses the race runs the same lap: fetch, rebase, push, again. The more agents, the more laps; we counted them in Measured against git. And much of what comes back is text written for people.

A hace fetch, rebase y vuelve a hacer push. Con B pasa lo mismo, pero al hacer rebase choca con el cambio de A: arregla el conflicto, vuelve a empujar y, si alguien ha entrado entretanto, otra vez rechazado. Todo agente que pierde la carrera da la misma vuelta: fetch, rebase, push, y vuelta a empezar. Cuantos más agentes, más vueltas; las contamos en «Medido frente a git». Y buena parte de lo que devuelve git es texto pensado para personas.

3. The same three agents, in braidLos mismos tres, en braid

Braid gives each agent a workspace of its own over one shared store. There is no index to fight over and no staging area: an agent commits what it changed, and lands it. All three commit before anyone lands; then they land as they finish.

Braid da a cada agente su propio espacio de trabajo sobre un único almacén compartido. No hay índice por el que pelearse ni área de preparación: el agente hace commit de lo que ha cambiado y lo aterriza. Los tres hacen commit antes de que aterrice nadie, y luego aterrizan según van terminando.

C is first. Nothing has landed since it started, so its change goes straight in:

C es el primero. No ha aterrizado nada desde que empezó, así que su cambio entra directo:

agent-c
[agent-c] $ braid land
Landed e39b1668831b on main (fast-forward)

A is one changeset behind. It does not fetch and it does not retry: in one short step, braid rebases A's change onto C's and merges the one file both touched.

A va un changeset por detrás. Ni hace fetch ni reintenta: en un solo paso corto, braid le hace rebase sobre el cambio de C y fusiona el único fichero que han tocado los dos.

agent-a
[agent-a] $ braid land
Landed on main as e0c85ddea85b, rebased onto e39b1668831b (1 path merged)
Updated 1 path in the working copy

4. Main did not movemain no se movió

B changed the same line as A. That is a real conflict, and no tool should guess its way through one. Braid stops and leaves main where it was:

B cambió la misma línea que A. Eso es un conflicto de verdad, y ahí ninguna herramienta debería ir a ciegas. Braid se para y deja main donde estaba:

agent-bexit 2
[agent-b] $ braid land
65bb04180402 conflicts with main at e0c85ddea85b; main did not move:
  CONTENT       notes.txt  (1 region)
Run `braid update` to bring the conflicts into the working copy.

It exits with status 2. A command line braid cannot parse exits with 2 as well, so to be sure an agent asks for --json: only a conflict prints "outcome": "conflicts", and the conflict itself comes back as data. Each side is named from B's point of view: base is the common ancestor, branch is what main holds now, workspace is B's own change. Lines count from 0 with the end left out, and next says what to run:

Sale con código 2. Un comando que braid no sabe interpretar también sale con 2, así que, para ir sobre seguro, el agente pide --json: solo un conflicto imprime "outcome": "conflicts", y el propio conflicto llega como datos. Cada lado se nombra desde el punto de vista de B: base es el ancestro común, branch lo que tiene main ahora y workspace su propio cambio. Las líneas se cuentan desde 0 y el final del tramo no se incluye; next le dice qué ejecutar:

agent-babridged; braid prints it on one lineabreviado; braid lo imprime en una sola línea
[agent-b] $ braid land --json
{
  …
  "conflicts": [{
    …
    "hunks": [{
      "base": {
        "end": 2, "start": 1,
        "text": "alpha\n" },
      "branch": {
        "end": 2, "start": 1,
        "text": "alpha, from a\n" },
      "workspace": {
        "end": 2, "start": 1,
        "text": "alpha, from b\n" }
    }],
    "kind": "CONTENT",
    "path": "notes.txt",
    …
  }],
  …
  "next": "braid update",
  "operation": null,
  "outcome": "conflicts",
  …
}

B runs braid update. Its copy gets the markers, with C's line already merged below them:

B ejecuta braid update. Su copia recibe las marcas de conflicto, con la línea de C ya fusionada debajo:

agent-bexit 2
[agent-b] $ braid update
65bb04180402 conflicts with e0c85ddea85b; the working copy has the merge so far:
  CONTENT       notes.txt  (1 region)
Fix the files, `braid resolve` the other conflicts, then `braid commit`.
Updated 1 path in the working copy
b/notes.txt
title
<<<<<<< main (e0c85ddea85b)
alpha, from a
=======
alpha, from b
>>>>>>> 65bb04180402 (b: alpha)
beta
gamma
delta, from c

Until the markers are gone, braid status says why a commit would be refused:

Mientras queden marcas, braid status explica por qué no aceptaría el commit:

agent-b
[agent-b] $ braid status
…
Not ready to commit:
  - conflict markers remain in "notes.txt": edit them out

B writes one line that keeps both edits and commits without a new message, so the change keeps its own. Then it lands:

B escribe una línea que recoge las dos ediciones y hace commit sin mensaje nuevo, así que el cambio conserva el suyo. Después aterriza:

agent-b
[agent-b] $ braid commit
Committed 4938acdd0794 (1 path)
Rebase finished at 4938acdd0794; `braid land` when ready
[agent-b] $ braid land
Landed 4938acdd0794 on main (fast-forward)

Start the three landings at the same moment and the order changes from run to run. The shape does not: one goes straight in, one is rebased, one gets the conflict.

Si lanzas los tres aterrizajes a la vez, el orden cambia de una ejecución a otra, pero la forma no: uno entra directo, a otro se le hace rebase y otro se lleva el conflicto.

5. Everyone ends with the same file, and git sees all of itTodos acaban con el mismo fichero, y git lo ve todo

A and C run braid update and get the same file as B. Each line names the agent that last changed it, even through a rebase:

A y C hacen braid update y les llega el mismo fichero que tiene B. Cada línea dice qué agente la cambió por última vez, también tras un rebase:

repoids and dates left outsin ids ni fechas
$ braid blame main notes.txt
f161e3fa5539  seeder   …  1  title
4938acdd0794  agent-b  …  2  alpha, from a and b
f161e3fa5539  seeder   …  3  beta
f161e3fa5539  seeder   …  4  gamma
e39b1668831b  agent-c  …  5  delta, from c

The op log says who did what, and how:

El registro de operaciones cuenta quién hizo qué, y cómo:

repotimes left outsin horas
$ braid op log -n 3
#4  agent-b  land workspace b on main: fast-forward 4938acdd0794 -> 4938acdd0794 (0 paths merged)
    main: e0c85ddea85b -> 4938acdd0794
#3  agent-a  land workspace a on main: rebased a984ef34e1c9 -> e0c85ddea85b (1 path merged)
    main: e39b1668831b -> e0c85ddea85b
#2  agent-c  land workspace c on main: fast-forward e39b1668831b -> e39b1668831b (0 paths merged)
    main: f161e3fa5539 -> e39b1668831b

And git keeps working. One command pushes main to a git remote as a fast-forward, with a lease; history there is never rewritten. Each changeset arrives as one git commit that names its agent in an agent header:

Y git sigue funcionando. Un solo comando sube main a un remoto de git como fast-forward y con lease: la historia del remoto nunca se reescribe. Cada changeset llega como un commit de git que nombra a su agente en una cabecera agent:

repo
$ braid git sync ../remote.git
Pushed main (4938acdd0794) to main as be3c44e7383b.
$ git -C ../remote.git cat-file commit main
…
agent agent-b
rebased-from 65bb04180402…
…

This scene is one of braid's tests, crates/cli/tests/three_agents.rs, which checks each landing, the conflict, the file all three end with, the op log and the push. CI runs it on every push to main and every pull request. Ids change on every run, because every signature carries its time.

Esta escena es uno de los tests de braid, crates/cli/tests/three_agents.rs, que comprueba cada aterrizaje, el conflicto, el fichero con el que acaban los tres, el registro de operaciones y el push. La integración continua lo ejecuta en cada push a main y en cada pull request. Los ids cambian en cada ejecución, porque cada firma lleva su hora.

Run it yourselfRepítela tú
bash
# with braid on your PATH (see Quick start)
export BRAID_AUTHOR="Ada Lovelace <ada@example.org>"
cd "$(mktemp -d)"
braid init repo
printf 'title\nalpha\nbeta\ngamma\n' > seed.txt
(cd repo && BRAID_AGENT=seeder braid change create --base none \
   --set notes.txt=@../seed.txt -m "Seed the notes" --land main)
for n in a b c; do (cd repo && braid workspace add $n ../$n); done
printf 'title\nalpha, from a\nbeta\ngamma\n'        > a/notes.txt
printf 'title\nalpha, from b\nbeta\ngamma\n'        > b/notes.txt
printf 'title\nalpha\nbeta\ngamma\ndelta, from c\n' > c/notes.txt
(cd a && BRAID_AGENT=agent-a braid commit -m "a: alpha")
(cd b && BRAID_AGENT=agent-b braid commit -m "b: alpha")
(cd c && BRAID_AGENT=agent-c braid commit -m "c: delta")
(cd c && BRAID_AGENT=agent-c braid land)     # fast-forward
(cd a && BRAID_AGENT=agent-a braid land)     # rebased, 1 path merged
(cd b && BRAID_AGENT=agent-b braid land)     # exit status 2: main did not move
(cd b && BRAID_AGENT=agent-b braid update)   # markers in b/notes.txt
printf 'title\nalpha, from a and b\nbeta\ngamma\ndelta, from c\n' > b/notes.txt
(cd b && BRAID_AGENT=agent-b braid commit)   # keeps its message
(cd b && BRAID_AGENT=agent-b braid land)     # fast-forward
(cd a && BRAID_AGENT=agent-a braid update)   # a gets the same file as b
(cd c && BRAID_AGENT=agent-c braid update)   # and so does c
(cd repo && braid op log -n 3)
(cd repo && braid blame main notes.txt)
git init --quiet --bare remote.git
(cd repo && braid git sync ../remote.git)

In progressEn desarrollo

Coming: the hard work in braid, the clean history in git.Próximamente: el trabajo duro en braid, la historia limpia en git.

Today, braid git sync runs when you call it, and every changeset reaches git as a commit of its own. Automatic, curated sync is being built: agents keep landing in braid, and git receives a clean history to read and review. It is not released yet. This section will say how it works once it ships.

Hoy, braid git sync se ejecuta cuando lo lanzas, y cada changeset llega a git como un commit propio. Estamos construyendo una sincronización automática y curada: los agentes siguen aterrizando en braid y git recibe una historia limpia, lista para leer y revisar. Aún no está publicada; cuando lo esté, esta sección contará cómo funciona.

How it worksCómo funciona

  1. Three workspaces, a, b and c, each with its own working copy and no index, sit on one shared store: immutable objects named by BLAKE3, and an append-only op log.
  2. The agents commit in parallel.
  3. Landing is one short step, taken in turn.
  4. c passes straight through: fast-forward.
  5. a bends over c's strand: rebased, 1 path merged.
  6. b hits a knot: conflict, exit 2, main did not move. It goes back to update, fix and commit, then passes: fast-forward.
  7. The strands braid into main, which git sync sends to any git remote as a fast-forward, with a lease.
  8. Planned: a server, a daemon and caches.
  1. Tres espacios de trabajo, a, b y c, cada uno con su propia copia y sin índice, sobre un único almacén compartido: objetos inmutables con nombre BLAKE3 y un registro de operaciones que solo crece.
  2. Los agentes hacen commit en paralelo.
  3. Aterrizar es un paso corto, por turnos.
  4. c pasa directo: fast-forward.
  5. a se cruza por encima de la hebra de c: rebased, 1 path merged.
  6. b choca con un nudo: conflicto, exit 2, main no se movió. Vuelve atrás para hacer update, arreglar y hacer commit, y luego pasa: fast-forward.
  7. Las hebras se trenzan en main, que git sync manda a cualquier remoto de git como fast-forward, con lease.
  8. Previsto: un servidor, un daemon y cachés.
  1. Everything is an immutable object named by its BLAKE3 hash: file contents, directories and changesets. Objects are never rewritten in place; the exact bytes are in docs/spec/format-v1.md, with golden vectors.
  2. A changeset records the files that changed against its first parent, plus the root tree it produces. History, blame and rebase read that short list, and the root id still commits to the whole repository.
  3. Agents commit in parallel, each in its own workspace. Landing is the one step they take in turn, and it is short: a fast-forward, or a rebase path by path that merges only the files both sides touched. Conflicts come back as data, and the branch does not move.
  4. Many processes share one store without a daemon. Segments are leased with locks the kernel releases if a process dies, objects reach the disk before anything that refers to them, and an append-only op log records every ref change, so braid undo can step back.
  5. Planned (milestones 6 and 7): the same API at every tier, so a local store, a per-machine daemon, a cache and a server all answer the same requests. The daemon, the cache and the server do not exist yet.
  1. Todo es un objeto inmutable que se nombra por su hash BLAKE3: el contenido de los ficheros, los directorios y los changesets. Ningún objeto se reescribe en su sitio; los bytes exactos están en docs/spec/format-v1.md, con vectores de referencia.
  2. Un changeset registra los ficheros que cambiaron respecto a su primer padre, más el árbol raíz que resulta. La historia, blame y el rebase leen esa lista corta, y el id de la raíz sigue fijando el estado de todo el repositorio.
  3. Los agentes hacen commit en paralelo, cada uno en su propio espacio de trabajo. Aterrizar es el único paso que dan por turnos, y es corto: un fast-forward, o un rebase ruta a ruta que solo fusiona los ficheros que han tocado los dos lados. Los conflictos vuelven como datos, y la rama no se mueve.
  4. Muchos procesos comparten un almacén sin daemon. Los segmentos se reservan con cerrojos que el kernel libera si un proceso muere, los objetos llegan al disco antes que lo que apunta a ellos, y un registro de operaciones que solo crece apunta cada cambio de ref, para que braid undo pueda dar marcha atrás.
  5. Previsto (fases 6 y 7): la misma API en cada nivel, de modo que un almacén local, un daemon por máquina, una caché y un servidor respondan a las mismas peticiones. El daemon, la caché y el servidor aún no existen.

Braid starts from ideas Anthropic published about Scion, its internal source control system (Redesigning source control at Anthropic): changesets stored against the first parent, server-side merges, minimal branch state, immutable objects any cache can serve. Braid is an independent implementation: it contains no Anthropic code and is not affiliated with or endorsed by Anthropic.

Braid parte de ideas que Anthropic publicó sobre Scion, su sistema interno de control de versiones (Redesigning source control at Anthropic): changesets guardados respecto al primer padre, fusiones en el servidor, ramas con un estado mínimo y objetos inmutables que cualquier caché puede servir. Braid es una implementación independiente: no contiene código de Anthropic y no tiene relación con Anthropic ni cuenta con su respaldo.

Quick startPrimeros pasos

Braid stores history, moves it in and out of git bit for bit, and gives each agent a workspace of its own. Build it, then import a git repository, this one for a start:

Braid guarda historia, la mete y la saca de git bit a bit, y da a cada agente su propio espacio de trabajo. Compílalo e importa un repositorio de git; para empezar, este mismo:

bash
git clone https://github.com/KikoCis/elffuss-braid
cd elffuss-braid
cargo build --release
export PATH="$PWD/target/release:$PATH"
SRC="$PWD"                       # this clone; another repository works too, with
                                 # its branch for main and one of its files for README.md

braid init /tmp/demo
cd /tmp/demo
braid git import "$SRC"          # every local branch and tag
braid log main -n 5
braid log main -- README.md      # only the changes to a path
braid blame main README.md       # who last changed each line
braid show main --json
braid fsck
braid stats        # objects by kind, and how they are stored: whole, deltas, chunks

Exporting writes the same commits back, with the same ids:

Al exportar se escriben los mismos commits, con los mismos ids:

bash
git init --bare /tmp/mirror.git
braid git export /tmp/mirror.git

Ids can be checked with any BLAKE3 implementation, for example the reference b3sum tool. In the clone, it prints the id that braid hash-object README.md gives:

Los ids se pueden comprobar con cualquier implementación de BLAKE3, por ejemplo la herramienta de referencia b3sum. En el clon, imprime el mismo id que da braid hash-object README.md:

bash
cd "$SRC"         # the clone, where README.md is
b3sum --derive-key "elffuss-braid 2026 blob v1" README.md

Needs Rust 1.89 or newer. CI tests Linux and other Unix-like systems; Windows is not tested yet.

Necesita Rust 1.89 o posterior. La integración continua prueba Linux y otros sistemas tipo Unix; Windows aún no se prueba.

Many agents on one repositoryMuchos agentes en un repositorio

Each agent gets its own workspace. There is no staging area and no shared index: an agent commits what it changed and lands it, and braid rebases it onto whatever the others landed first.

Cada agente tiene su propio espacio de trabajo. No hay área de preparación ni índice compartido: el agente hace commit de lo que ha cambiado y lo aterriza, y braid le hace rebase sobre lo que hayan aterrizado antes los demás.

bash
cd /tmp/demo                         # any braid repository
export BRAID_AUTHOR="Ada Lovelace <ada@example.org>"
export BRAID_AGENT=agent-1           # recorded with everything this agent does
braid workspace add agent-1          # ./agent-1, tracking main
cd agent-1
echo 'fn main() {}' > main.rs
braid status
braid commit -m "Add main.rs"
braid land                           # fast-forward, or a rebase onto main

Every change to a branch or ref (imports, landings, syncs) is in the op log, and braid undo steps back through them, newest first. Here it takes the landing back, and the changeset stays in the workspace, ready to land again:

Cada cambio de una rama o una ref (importaciones, aterrizajes, sincronizaciones) queda en el registro de operaciones, y braid undo los deshace uno a uno, del más reciente hacia atrás. Aquí deshace el aterrizaje, y el changeset sigue en el espacio de trabajo, listo para aterrizar otra vez:

bash
braid op log      # who did what, newest first
braid undo        # takes the landing back

What an agent can rely onCon qué puede contar un agente

  • IdentityIdentidad

    BRAID_AGENT is written into the op log and into every changeset the agent makes, and survives rebases; changesets imported from git name no agent. BRAID_AUTHOR signs the changesets the agent commits, or creates without a checkout, and the ones it remakes in a rebase. A merge made by git sync is signed instead with the agent label and the email in .braid/config, or <agent>@example.org.

    BRAID_AGENT queda escrito en el registro de operaciones y en cada changeset que crea el agente, y sobrevive a los rebases; los changesets importados de git no nombran agente. BRAID_AUTHOR firma los changesets que el agente crea, con commit o sin checkout, y los que rehace en un rebase. Una fusión hecha por git sync, en cambio, se firma con la etiqueta del agente y el correo de .braid/config, o con <agente>@example.org.

  • OutputSalida

    --json on every command; change create always prints JSON.

    --json en todos los comandos; change create imprime siempre JSON.

  • Exit statusCódigo de salida

    0 done, 1 failed, 2 conflicts (the branch did not move), or a command line braid could not parse; with --json only a conflict prints "outcome": "conflicts".

    0 hecho, 1 fallo, 2 conflictos (la rama no se movió) o un comando que braid no sabe interpretar; con --json solo el conflicto imprime "outcome": "conflicts".

  • StatusEstado

    braid status --json gives behind_by, unlanded, ready_to_commit and blocking, which lists the same reasons braid commit refuses with.

    braid status --json da behind_by, unlanded, ready_to_commit y blocking, que lista los mismos motivos por los que braid commit se niega.

  • Secrets guardGuarda de secretos

    New .env*, *.pem and id_* files, and files over 1 MiB, wait for braid track. --force leaves them out.

    Los ficheros nuevos .env*, *.pem e id_*, y los de más de 1 MiB, esperan a braid track. --force los deja fuera.

  • Short idsIds cortos

    Six hex digits or more. An ambiguous one is an error that lists the candidates.

    Seis dígitos hexadecimales o más. Uno ambiguo es un error que lista los candidatos.

  • Conflict kindsTipos de conflicto

    CONTENT, MODIFY_DELETE, MODE, DF, DIR_REMOVED, CASE. braid resolve settles the ones that are not about content.

    CONTENT, MODIFY_DELETE, MODE, DF, DIR_REMOVED, CASE. braid resolve zanja los que no son de contenido.

  • Checkouts

    They never follow symlinks, and nothing from repository content is ever run.

    Nunca siguen enlaces simbólicos, y nunca se ejecuta nada que venga del contenido del repositorio.

  • No checkoutSin checkout

    braid change create makes a changeset without a working copy, and can land it. --expect takes the full blob id the agent read; a mismatch is refused.

    braid change create crea un changeset sin copia de trabajo, y puede aterrizarlo. --expect recibe el id completo del blob que el agente leyó; si no coincide, se rechaza.

    # READ_ID: the full blob id the agent read
    braid change create --base main --set src/lib.rs=@new-lib.rs \
      --expect src/lib.rs="$READ_ID" -m "Fix the parser" --land main

Working with gitTrabajar con git

Repositories come in with their whole history, and git hosts keep working as mirrors.

Los repositorios entran con toda su historia, y los servidores de git siguen funcionando como espejos.

ImportImportarbraid git import

Goes through gitoxide and brings every local branch and tag; to bring every branch of a remote, import a git clone --mirror. Each commit is exported again as it is imported, and the import stops unless its id comes back the same. Running it again imports only what is new. A braid branch or tag follows git's only forward: when braid has work git does not have, or the two have diverged, it stays where it is, and the import lists it under kept with the reason. To keep a branch in step with a git remote, use git sync. Shallow and SHA-256 repositories are refused for now.

Pasa por gitoxide y trae todas las ramas locales y etiquetas; para traer todas las ramas de un remoto, importa un git clone --mirror. Cada commit se vuelve a exportar al importarlo, y la importación se detiene si su id no sale idéntico. Si se repite, solo importa lo nuevo. Una rama o etiqueta de braid solo sigue a la de git hacia delante: si braid tiene trabajo que git no tiene, o los dos han divergido, se queda donde está, y la importación la lista en kept con el motivo. Para mantener una rama al día con un remoto de git, usa git sync. Los clones superficiales y los repositorios SHA-256 se rechazan por ahora.

ExportExportarbraid git export

Writes braid refs, and everything they reach, into a git repository with the same ids. Changesets made in braid export deterministically, with their agent as a commit header. Git refs of the same names are overwritten, so export into a new repository; to keep an existing remote in step, use git sync.

Escribe las refs de braid, y todo lo que alcanzan, en un repositorio de git con los mismos ids. Los changesets hechos en braid se exportan de forma determinista, con su agente como cabecera del commit. Las refs de git con el mismo nombre se sobrescriben: exporta a un repositorio nuevo y, para mantener al día un remoto que ya existe, usa git sync.

SyncSincronizarbraid git sync
  • It fetches and imports the remote branch, then fast-forwards braid or pushes braid's branch, merging first when both moved.
  • The remote only ever fast-forwards: the push carries a lease on what was just fetched, and history there is never rewritten.
  • Conflicts move nothing and exit 2; a refused push exits 1.
  • --dry-run writes nothing, and --json names the outcome.
  • Hace fetch de la rama remota y la importa; después hace fast-forward en braid o push de la rama de braid, y antes fusiona si se han movido las dos.
  • El remoto solo avanza en fast-forward: el push lleva un lease sobre lo que se acaba de traer, y allí la historia nunca se reescribe.
  • Los conflictos no mueven nada y salen con 2; un push rechazado sale con 1.
  • --dry-run no escribe nada, y --json nombra el resultado.
braid git sync https://github.com/you/project.git --branch main
braid git sync https://github.com/you/project.git --dry-run --json

Braid contains no code from git (GPLv2). It reads and writes git data with gitoxide (MIT or Apache-2.0); git sync also runs the git binary as a subprocess, to set up its mirror, fetch and push.

Braid no contiene código de git (GPLv2). Lee y escribe datos de git con gitoxide (MIT o Apache-2.0); git sync además ejecuta el binario de git como subproceso, para preparar su espejo, hacer fetch y hacer push.

Measured against gitMedido frente a git

  • Ratios are braid / git for the same work on the same machine; below 1 means braid is faster or smaller.
  • braid and git run in alternating order, with warm caches, and the result is the median.
  • Each scenario checks both tools did the same work. A failed check is reported as an error, never as a number.
  • Git runs with its defaults, with automatic gc and maintenance turned off.
  • Only ratios and git's retry counts are published, never times or sizes, together with the script.
  • Not measured: cold caches, git's fsmonitor daemon or feature.manyFiles, and transfers between machines (there is no server yet).
  • Cada ratio es braid / git para el mismo trabajo en la misma máquina; por debajo de 1, braid es más rápido o más pequeño.
  • braid y git se ejecutan en orden alterno, con las cachés calientes, y el resultado es la mediana.
  • Cada escenario comprueba que las dos herramientas hicieron el mismo trabajo. Una comprobación fallida sale como error, nunca como número.
  • Git se ejecuta con su configuración por defecto, con el gc y el mantenimiento automáticos desactivados.
  • Solo se publican ratios y los reintentos de git, nunca tiempos ni tamaños, junto con el script.
  • No se mide: cachés frías, el daemon fsmonitor de git o feature.manyFiles, ni transferencias entre máquinas (aún no hay servidor).

One run of bench/run.py, measuring braid at commit 5330054 on one machine. Run the script before relying on any number.

Una sola ejecución de bench/run.py, que mide braid en el commit 5330054 en una máquina. Ejecuta el script antes de fiarte de ningún número.

What was comparedQué se comparóbraid / gitReproducePara repetirlo
Import tmux 3.5a, 10,287 commits: braid init + braid git import vs git clone --no-local --bareImportar tmux 3.5a, 10 287 commits: braid init + braid git import frente a git clone --no-local --bare17.6python3 bench/run.py --only import
Import it and check it out: braid init + braid git import + braid workspace add vs git clone --no-localImportarlo y hacer checkout: braid init + braid git import + braid workspace add frente a git clone --no-local17.1python3 bench/run.py --only import
Size after that import: du of .braid/store vs the bare clone after git gc --aggressiveTamaño tras esa importación: du de .braid/store frente al clon bare tras git gc --aggressive25.1python3 bench/run.py --only store
Status of a tree of 100,000 files, clean: braid status vs git status, no untracked cache, no fsmonitorStatus de un árbol de 100 000 ficheros, sin cambios: braid status frente a git status, sin untracked cache ni fsmonitor2.6python3 bench/run.py --only status
Status of that tree, clean: braid status vs git status with core.untrackedCache=true, no fsmonitorStatus de ese árbol, sin cambios: braid status frente a git status con core.untrackedCache=true, sin fsmonitor5.8python3 bench/run.py --only status
Status of that tree, 10 files modified: braid status vs git status, no untracked cache, no fsmonitorStatus de ese árbol con 10 ficheros modificados: braid status frente a git status, sin untracked cache ni fsmonitor3.0python3 bench/run.py --only status
Status of that tree, 10 files modified: braid status vs git status with core.untrackedCache=true, no fsmonitorStatus de ese árbol con 10 ficheros modificados: braid status frente a git status con core.untrackedCache=true, sin fsmonitor5.7python3 bench/run.py --only status
Commit one changed file of that tree: braid commit vs git add + git commitCommit de un fichero modificado de ese árbol: braid commit frente a git add + git commit5.0python3 bench/run.py --only commit
Commit one new file in a directory of 20,000 files, 200 times: braid commit vs git add + git commitCommit de un fichero nuevo en un directorio de 20 000 ficheros, 200 veces: braid commit frente a git add + git commit1.8python3 bench/run.py --only wide
Commit one new file in that directory without a working copy, 200 times: braid change create --land vs git add + git commitCommit de un fichero nuevo en ese directorio sin copia de trabajo, 200 veces: braid change create --land frente a git add + git commit0.9python3 bench/run.py --only wide
4 agents land 10 commits each, at once: braid commit + braid land, a workspace each, vs git commit + git push, a clone each, with git pull --rebase and a new push when rejected4 agentes aterrizan 10 commits cada uno, a la vez: braid commit + braid land, cada uno en su espacio de trabajo, frente a git commit + git push, cada uno en su clon, con git pull --rebase y un nuevo push cuando se lo rechazan0.4python3 bench/run.py --only agents
8 agents, the same8 agentes, igual0.3python3 bench/run.py --only agents
16 agents, the same16 agentes, igual0.2python3 bench/run.py --only agents
Newest 1,000 changesets of tmux: braid log -n 1000 vs git log --first-parent -n 1000 --format=%H after git gc --aggressiveLos 1000 changesets más recientes de tmux: braid log -n 1000 frente a git log --first-parent -n 1000 --format=%H tras git gc --aggressive1.7python3 bench/run.py --only history

Git retried each push 1.1, 2.5 and 5.2 times on average with 4, 8 and 16 agents; no braid agent retried, and nearly every landing was a rebase.

Git reintentó cada push 1,1, 2,5 y 5,2 veces de media con 4, 8 y 16 agentes; ningún agente de braid reintentó, y casi todos los aterrizajes fueron un rebase.

In that run, braid was faster when many agents landed at once, and slower at importing and storing history, and at status and commit on a large tree.

En esa ejecución, braid fue más rápido cuando muchos agentes aterrizaban a la vez, y más lento al importar y guardar historia, y en status y commit sobre un árbol grande.

This run predates later work on storage and speed: deltas, chunked large files, editing a large directory in place, a parallel working-copy walk and lazy index lookups. log -- path and blame came later too, and are not in this table.

Esta ejecución es anterior a lo que se ha hecho después en almacenamiento y velocidad: deltas, ficheros grandes troceados, la edición en su sitio de los directorios grandes, un recorrido en paralelo de la copia de trabajo y búsquedas perezosas en los índices. log -- path y blame también llegaron después y no están en esta tabla.

What is checkedQué se comprueba

GuaranteeGarantíaHow it is checkedCómo se comprueba
Landing and importing only move a branch forward; braid undo and braid ref set can move it back.Aterrizar e importar solo hacen avanzar la rama; braid undo y braid ref set pueden hacerla retroceder. Simulation invariant I1, checked after every step (crates/sim).Invariante I1 de la simulación, comprobada tras cada paso (crates/sim).
A conflict leaves the branch where it was and exits 2.Un conflicto deja la rama donde estaba y sale con 2. I5; three_agents.rs.I5; three_agents.rs.
No lost update.Ninguna actualización se pierde. I3: the head's tree equals an independent reference model, file by file.I3: el árbol de la cabeza coincide, fichero a fichero, con un modelo de referencia independiente.
A changeset lands at most once, even with lost answers or duplicate requests.Un changeset aterriza como mucho una vez, aunque se pierdan respuestas o lleguen peticiones duplicadas. I4, with those faults injected; every seed reproduces its run.I4, con esos fallos inyectados; cada semilla reproduce su ejecución.
Changes to unrelated paths land the same in either order.Los cambios en rutas que no tienen que ver entre sí aterrizan igual en cualquier orden. I7, plus property tests.I7, más tests de propiedades.
A crash or power loss leaves a consistent store.Una caída o un corte de luz dejan el almacén coherente. The power-loss model and random process kills.El modelo de cortes de luz y procesos matados al azar.
Ids can be recomputed from the spec alone.Los ids se pueden recalcular solo con la especificación. docs/spec/check_vectors.py with b3sum, in CI.docs/spec/check_vectors.py con b3sum, en la integración continua.
Every imported git commit exports back to the same id.Todo commit de git importado se exporta de vuelta con el mismo id. Checked on every import; CI round-trips this repository's own history.Se comprueba en cada importación; la integración continua hace la ida y vuelta con la historia de este mismo repositorio.
log -- path, merge bases and blame agree with git.log -- path, las bases de fusión y blame coinciden con git. Differential tests, apart from two documented differences in blame.Tests diferenciales, salvo dos diferencias documentadas en blame.
Checkouts write nothing outside the workspace.Los checkouts no escriben nada fuera del espacio de trabajo. crates/wc/tests/hostile.rs.
No unsafe Rust in braid's own crates.Nada de Rust unsafe en los crates propios de braid. #![forbid(unsafe_code)] in every library crate; denied workspace-wide.#![forbid(unsafe_code)] en cada crate de biblioteca; denegado en todo el workspace.
Trees, changesets, names, the git map and git objects are fuzzed.Los árboles, los changesets, los nombres, el mapa de git y los objetos de git pasan por fuzzing. Five cargo-fuzz targets, a minute each in CI.Cinco objetivos de cargo-fuzz, un minuto cada uno en la integración continua.

Local stores run in ordered mode: a power loss may lose the newest operations, but never leaves the store inconsistent.

Los almacenes locales funcionan en modo ordered: un corte de luz puede perder las operaciones más recientes, pero nunca deja el almacén incoherente.

What is honest about thisSin letra pequeña

  • Pre-alpha: keep git as the source of truth, and nothing only in braid.
  • Speed and size against git are in Measured against git, as ratios from one run of the script, with the commit measured: check them before relying on braid for speed.
  • One machine for now. There is no server, daemon or cache yet, and repositories move between machines only through git.
  • Nothing is ever removed from a store; there is no garbage collection yet.
  • Format v1 is frozen. Storage and protocols can still change, and an older braid refuses a newer store rather than guess.
  • Merges are textual: two changes can merge cleanly and still break the build.
  • log -- path and blame follow first parents and do not follow renames.
  • Shallow and SHA-256 git repositories are refused for now.
  • CI tests Linux and other Unix-like systems; Windows is not tested yet.
  • Milestones 0–4 are done. 5 is in progress: deltas, chunked large files, derived indexes, blame and the benchmark script are in. 6 and 7 are planned.
  • Pre-alfa: deja git como fuente de verdad, y no guardes nada solo en braid.
  • La velocidad y el tamaño frente a git están en «Medido frente a git», como ratios de una ejecución del script y con el commit medido: compruébalos antes de contar con la velocidad de braid.
  • Por ahora, una sola máquina. Aún no hay servidor, daemon ni caché, y los repositorios solo pasan de una máquina a otra a través de git.
  • Nunca se borra nada de un almacén; aún no hay recolección de basura.
  • El formato v1 está congelado. El almacenamiento y los protocolos aún pueden cambiar, y un braid antiguo rechaza un almacén más nuevo en vez de adivinar.
  • Las fusiones son textuales: dos cambios pueden fusionarse limpiamente y aun así romper la compilación.
  • log -- path y blame siguen los primeros padres y no siguen los renombrados.
  • Los clones superficiales y los repositorios SHA-256 de git se rechazan por ahora.
  • La integración continua prueba Linux y otros sistemas tipo Unix; Windows aún no se prueba.
  • Las fases 0 a 4 están terminadas. La 5 está en marcha: ya están los deltas, los ficheros grandes troceados, los índices derivados, blame y el script de benchmarks. La 6 y la 7 están previstas.

Braid starts from ideas Anthropic published about Scion, its internal source control system. It is an independent implementation: it contains no Anthropic code and is not affiliated with or endorsed by Anthropic.

Braid parte de ideas que Anthropic publicó sobre Scion, su sistema interno de control de versiones. Es una implementación independiente: no contiene código de Anthropic y no tiene relación con Anthropic ni cuenta con su respaldo.

Credits: Jujutsu, for the operation log and undo; Sapling, for history served at scale, and compressing a file version against the previous one; gitoxide, for the git bridge; BLAKE3, FastCDC, prolly trees and imara-diff.

Créditos: Jujutsu, por el registro de operaciones y el deshacer; Sapling, por servir historia a gran escala y comprimir cada versión de un fichero respecto a la anterior; gitoxide, por el puente con git; BLAKE3, FastCDC, los prolly trees e imara-diff.

Part of ElffussParte de Elffuss

Braid is part of Elffuss, a family of tools for building software with agents.

Braid forma parte de Elffuss, una familia de herramientas para construir software con agentes.

On GitHubEn GitHub

  • elffuss the shared browser-agent core behind Code and Claw.el núcleo de agente de navegador que comparten Code y Claw.
  • elffuss-code an IDE with an AI agent that runs entirely in your browser.un IDE con un agente de IA que corre entero en tu navegador.
  • elffuss-claw an agentic OS in your browser, with apps generated on demand.un sistema operativo agéntico en tu navegador, con apps que se generan al pedirlas.
  • elffuss-translator real-time conversation translation in the browser.traducción de conversaciones en tiempo real, en el navegador.