How does Crab connect to Git?
Git calls Crab at two extension points: a filter changes file representation, and a remote helper moves repository state.
Crab does not patch Git. Git calls it through two standard extension points:
- A filter process turns a tracked file into a pointer during add, then turns that pointer back into file bytes during checkout.
- A remote helper handles fetch and push for
crab://remotes.
GIT EXTENSION TRACE
Two Git hooks, one backed pointer contract
Git starts the clean filter
Git streams a tracked file through the long-running filter process.
Invariant: Path selection comes from .gitattributes.
Follow one model through Git
vision-search/
├── src/train.py
└── models/encoder.safetensors # 8 GBThe Python file stays an ordinary Git blob. The model takes a second data path, but both paths still belong to one commit.
| Command | Git invokes | Result |
|---|---|---|
git add | Filter clean | Git gets a pointer; Crab stages chunks |
crab add | Native parallel add path | The same pointer and staging result |
git push | git-remote-crab | Git and Crab dependencies become durable |
crab push | Native concurrent push path | The same durable repository outcome |
git fetch | git-remote-crab | Git receives commits, trees, and pointer blobs |
git checkout | Filter smudge | Worktree gets a pointer or verified file bytes |
crab hydrate | Crab reconstructor | A pointer becomes verified file bytes |
1. Add calls the clean filter
First, select the model path:
crab track '*.safetensors'
git add .gitattributes
git check-attr filter -- models/encoder.safetensorscrab track writes this rule:
*.safetensors filter=crab diff=crab merge=crab -textGit's filter attribute decides which file content crosses the clean/smudge boundary. The check should report filter: crab.
Now use Git's add path so the filter boundary is visible, then inspect Git's copy:
git add models/encoder.safetensors
git show :models/encoder.safetensorsThe worktree still holds 8 GB. Crab streams those bytes through hashing and content-defined chunking, saves the ordered recipe in local staging, and gives Git a compact pointer.
For many large files, crab add reaches the same index and staging state through Crab's parallel native path instead of Git's serial filter requests. The trace below shows that optimized route.
COMMAND TRACE 02
crab add chooses and prepares the representation
Resolve Git attributes
Each path is classified with the same .gitattributes rules that Git uses for its filter process.
The staged blob has this shape:
version https://crab.dev/spec/v1
file-hash <64-hex BLAKE3>
size 8589934592An optional shard hint may also appear. It can speed lookup, but the file hash remains the identity Crab verifies.
Git now has two IDs for two different things:
| Identity | Names |
|---|---|
| Git blob object ID | The pointer text stored in the commit |
Crab file-hash | The original 8 GB file bytes |
If Crab cannot stage a complete recipe, clean returns an error. It does not hand Git a pointer that only looks valid.
2. Push calls the remote helper
Git sees a URL such as crab://team-data/vision-search and looks for git-remote-crab. That follows Git's standard remote-helper contract: helpers advertise capabilities, list refs, and handle fetch or push batches over standard input and output.
git remote get-url origin
git commit -m "Train encoder v1"
git pushThe helper finds every pointer reachable from the proposed branch. It prepares two immutable lanes:
- Git commits, trees, and pointer blobs become a Git pack.
- New chunks and reconstruction metadata become xorbs and shards.
The ref moves only after both lanes pass closure checks. crab push reaches the same repository outcome through Crab's native concurrent pipeline rather than Git's helper loop.
TRANSACTION TRACE 03
Push makes dependencies durable, then moves the ref
Discover the complete push closure
The helper walks reachable Git objects and parses Crab pointers before opening any large-file metadata path.
Local staging connects clean to push. Clean does not know which branch or remote will use the pointer, so it keeps the recipe and new bytes until publication. After a successful push, another client can reconstruct the file from canonical remote state.
To confirm the visible result:
git rev-parse HEAD
git ls-remote origin "refs/heads/$(git branch --show-current)"The two commit IDs should match.
3. Fetch moves Git history first
On another client:
git fetch origin
git show FETCH_HEAD:models/encoder.safetensorsgit fetch asks the helper to list refs and import the required Git packs. The model arrives as its pointer blob. Fetch does not need to download 8 GB just to let Git inspect the commit.
This distinction is useful when debugging:
- If Git cannot see the commit, inspect the remote helper.
- If Git sees the pointer but cannot rebuild the model, inspect Crab metadata and object access.
4. Checkout calls the smudge filter
During checkout, Git sends the stored blob to smudge. Ordinary blobs pass through unchanged. A Crab pointer can remain a pointer for a lazy checkout or resolve to complete file bytes.
git checkout FETCH_HEAD -- models/encoder.safetensors
crab status
crab hydrate models/encoder.safetensorscrab hydrate makes the read path explicit: resolve the recipe, locate every chunk, plan object-store ranges, reconstruct in order, and verify the final BLAKE3 hash before replacing the pointer.
READ TRACE 05
A pointer becomes byte-identical worktree content
Git supplies the pointer
The Git graph stays compact and reveals the content identity without embedding the large file in the pack.
Two clients can therefore check out the same commit with different local working sets. The committed pointer does not change.
Why the filter stays alive
Git's long-running filter process handles many paths during one Git command. Git and Crab first agree on protocol version 2 and the supported operations:
git-filter-client
version=2
capability=clean
capability=smudge
capability=delayKeeping one process alive avoids starting Crab and reopening indexes for every model. Each path still receives its own status and content response.
The optional delay capability lets checkout continue while eligible files reconstruct in the background. It changes scheduling, not integrity: the final result is complete verified bytes or an error.
Protocol output belongs to Git. Human debug text on standard output can break packet or line framing, so Crab sends diagnostics through its logging boundary.
One file, two extension points
- 1.gitattributes selects models/encoder.safetensors.
- 2Clean stages its recipe and returns a pointer to Git.
- 3Git commits the pointer with ordinary source blobs.
- 4git-remote-crab uploads both dependency lanes, then moves the ref.
- 5Another client fetches the commit and pointer.
- 6Smudge or hydrate reconstructs and verifies the original model.
The pointer is the handoff. Clean creates it with local backing state; the helper publishes it with durable backing state; hydration uses it to verify the returned bytes.
Debug the first broken boundary
git check-attr filter -- models/encoder.safetensors
git show :models/encoder.safetensors
git remote -v
git ls-remote origin
crab status
crab doctor
crab fsck| Symptom | Inspect first |
|---|---|
| Git stages the complete model | .gitattributes, filter installation, and clean |
git add reports a filter error | Local staging, chunking, or pointer creation |
| The remote appears to have no refs | Helper installation, remote URL, or credentials |
| Fetch succeeds but hydration fails | Recipe, shard, xorb, or object-store read access |
| Push uploads data but rejects the branch | Pointer closure or a stale destination ref |
Start with the earliest failed check. Changing the remote helper cannot repair a path that never entered clean, and changing the filter cannot repair a missing remote xorb.
Source map
| Contract | Implementation |
|---|---|
| Invocation dispatch | crab/src/main.rs |
| Tracking attributes | crab/src/cmd/track.rs |
| Filter protocol | crab/src/git/filter_process.rs |
| Clean and smudge | crab/src/git/clean.rs, crab/src/git/smudge.rs |
| Remote-helper protocol | crab/src/git/remote_helper.rs |
Continue with How do you work with Crab after the first push? to turn these integration points into a repeatable team workflow.
KNOWLEDGE PROOF
Check the decision, not your memory.
Which Git extension points does Crab use for a tracked model and a remote push?