Seam

Compare to git

Git's verbs keep git's names. Here is each common git command next to the seam command that does its job, and then what works differently.

Commands side by side

gitseamNotes
git initseam quilts new <slug>main starts at an empty root commit.
git cloneseam checkout <rev> --quilt <q> --dir <folder> [-- paths]Writes files only, no history. Name paths for a sparse checkout.
git switch -c <branch>seam square open "<title>" --quilt <q> [--dir <folder>]A square starts at the tip of main.
git switch <branch>seam checkout sq:<id>Inside a block folder with nothing uncommitted.
git branchseam square list [--mine] [--all]Open squares, or every square with --all.
git statusseam statusIn a block folder. Also says what merged under you.
git add + git commitseam commit -m "<message>" [paths]No staging area.
git push(nothing)A commit is on the server when it is made.
git pull --rebaseseam rebaseMoves the square onto the tip and updates the folder.
git diffseam diffYour uncommitted changes, in a block folder.
git diff a bseam diff a b, seam diff a..bAlso --stat and --name-only.
git logseam log [rev] [-n 20] [--oneline] [-- paths]Newest first. Ranges like main~5..main work.
git showseam show <rev> [--stat | --name-only]
git blameseam blame <path>[@rev]Computed by the server, with the patch of each line.
git show rev:pathseam cat <path>@<rev>Writes the file's bytes to stdout.
git ls-tree -rseam ls [rev] [paths]
git merge + push to mainseam merge [sq:<id>] --into mainRebased onto the tip as one patch, on the server.
git merge <other>seam merge sq:<other>In your block: a two-parent commit in your square.
git rebase [--onto]seam rebase [--onto <rev>]Conflicts are kept in the square; it never stops halfway.
git cherry-pickseam cherry-pick <rev>Into your square, as a new commit.
git revertseam revert patch:<n>Opens a new square that undoes the patch; merge it.
git checkout --oursseam resolve <path> --oursAlso --theirs, --base, --suggestion, --side n, --delete.
git branch -Dseam square abandonKept and readable; seam square reopen brings it back.
git merge --squash a bseam square fold --into sq:<id>One square's work becomes one commit in another.
git add -p into two branchesseam square split <paths,...> <paths,...>Each group of paths moves to a new square.
git fast-importseam import git <path>Once, into a new quilt.
git fast-exportseam export git <dir>One way, to a branch of a plain git repo.

Inside a block folder the quilt and the square come from the folder. Anywhere else, name them with --quilt <slug> and --square sq:<id>.

What is different

No local history

A git clone carries every commit. A block folder carries only files, plus .seam/block.json saying which quilt, square and commit they came from. log, show, blame and diffs between revisions are answered by the server. That keeps a checkout small and never stale, and it means you need to be online.

The server merges

Merging into main is one call. The server replays your square onto the current tip, combines changes to different parts of the same file, writes one commit and moves main with a compare-and-swap. If another merge won the race, it retries by itself, up to five attempts in all; after three lost races the merge waits its turn for the line, so it does land. There is no merge queue and nothing to pull first.

Because each square lands as one commit, main is a straight line of patches. Two-parent commits only happen inside squares.

Squares instead of branches

A square is not a name pointing at a commit. It is a record with an id, a title, a state and a holder: the one member who may commit to it. You hand it to someone else with seam square handoff. Abandoning a square does not delete its commits; they stay readable by id.

Patch numbers

Each merge into main gets the next number. patch:412 always names the same change, and main~3 is three patches back. seam log --oneline shows the number beside each commit: [main:412].

Conflicts are data

Git stops a merge with conflicts and waits for --continue or --abort. Quilt never stops halfway. A clash is stored in the commit as a conflict: each side, its base, and who made each side. The square carries it and keeps working; you can commit, rebase and hand it off. Only merging into main waits until it is settled. Read a conflicted file in the form you like: seam cat <path>@sq:<id> --format diff (the default), snapshot or git (classic <<<<<<< markers, two sides only).

Authors are members

There is no --author. Each commit records the signed-in member, with the AI tool it came through (Author: builder <agent:5c1e…> via claude) and, for an agent, the person it works for.

What git has that Seam does not

Some of these are left out on purpose. Others are in the design and not built yet.

Left out

  • Push, pull, fetch and remotes. There is one server and it has every commit when it is made.
  • The staging area and stash. Commit names paths when you want only some files; uncommitted work stays in its folder.
  • Merge commits on main. Every square merges as one rebased patch.
  • Hand-written authors and dates. The server records who you are and when.

Import and export

Import

$ seam import git ./my-app [--into <slug>] [--validate]
  • Reads the repo on your computer and makes a new quilt. Each commit on HEAD's first-parent chain becomes a patch on main.
  • The side commits of a merge become the commits of that patch's square. A square from a merge commit like Merge pull request #12 from ada/fix takes the branch name as its title.
  • Authors become stub members, stub:<email>, so blame and log keep their names.
  • Each imported commit remembers its git sha: seam show git:4d5bb0f finds it.
  • --validate compares every patch's files with its git commit when the import is done.
  • Only HEAD's history is imported. Other branches, tags and submodules are not.

Export

$ seam export git ../my-app-git --quilt my-app [--line main] [--branch <name>]
  • Writes each patch of the line as one commit on a branch (named after the line unless you pass --branch). A folder that does not exist yet becomes a new bare repo.
  • Run it again to add the patches merged since. It keeps its place in quilt-export.json inside the git directory.
  • The same patch always gives the same git commit id, on any machine.
  • Each commit message ends with trailers: Quilt-Commit, Quilt-Square, Quilt-Patch and Quilt-Author, plus Quilt-On-Behalf-Of and Quilt-Task when they apply.
  • Authors keep the email from a git import; everyone else gets a noreply address such as <name>@agents.noreply.heyquilt.com.
  • It is one way. If the branch moved since the last export, the export refuses and asks for a new branch or repo. It never merges or forces.

Ready to try it? Get started walks through an import from the beginning.