Skip to content

docs: runnable partial-clone worked example#8

Merged
ivarvong merged 2 commits into
mainfrom
examples-partial-clone-demo
Jul 2, 2026
Merged

docs: runnable partial-clone worked example#8
ivarvong merged 2 commits into
mainfrom
examples-partial-clone-demo

Conversation

@ivarvong

@ivarvong ivarvong commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Read one file from a git repo without downloading the repo — 32 lines, standalone, pure Elixir.

elixir examples/partial_clone_demo.exs

The script Mix.installs the published package (no checkout needed), clones elixir-ai-tools/just_bash under a blob:none filter — protocol v2 partial clone: refs + commits + trees cross the wire, file contents don't — reads README.md, and lets Repository.memory_report/1 account for every object fetched:

after clone   : %{blob_count: 0, tree_count: 616, cache_bytes: 363300}
read README.md:  15873 bytes — "# JustBash"
after one read: %{blob_count: 1, tree_count: 616, cache_bytes: 369585}
ls /:  21 entries — blob_count still 1

Each line is one claim:

  • blob_count: 0 after clone — the filter held; nothing was shipped speculatively.
  • FS.size/3 before the read returns {:error, :not_local} instead of fetching. The size probe is a gate: a caller (an agent loop, say) decides whether to pull a blob before paying for it.
  • blob_count: 0 → 1 around read_path/3 — reading one file fetched exactly one blob. No readahead, no surprise pack.
  • FS.ls afterwards doesn't move the count: trees are local, so navigating the repo is free after a filtered clone.

No printing framework, no control-group second clone — the 0 → 1 transition brackets the read, which is the whole proof. All state lives in the %Repository{} value the caller threads; there is no process, ETS table, or daemon behind it.

A protocol note, and a follow-up. The example uses filter: {:blob, :none} deliberately rather than lazy: true. A bare lazy clone defers everything — but its on-demand fetch is a want <sha> with no filter, and git upload-pack answers a commit want with the commit's entire reachable graph. So the first read_path on a bare-lazy repo hauls in the whole repository. The README quick-start currently pairs lazy: true with torvalds/linux, which would do exactly that on first read; the fix is either correcting that example or making lazy: true imply blob:none when the server advertises filter support. Tracked as a follow-up, decided separately from this PR.

Also here: the README links the example from its partial-clone section, and .formatter.exs now covers examples/ so the script stays format-gated in CI.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VEo6srWr3aFwhtwaXDTCZZ

ivarvong and others added 2 commits July 2, 2026 08:11
examples/partial_clone_demo.exs — Mix.install of the published
package, blob:none partial clone of a public repo, one file read,
and a memory_report/1 comparison against an eager clone proving
exactly one blob crossed the wire (1 of 1,906 blobs; 358 KB of
5.7 MB compressed, measured against GitHub).

Also demos the FS.size/3 gate: {:error, :not_local} before the
read (no fetch triggered), O(1) from cache after.

README links it from the partial-clone section; .formatter.exs
now covers examples/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VEo6srWr3aFwhtwaXDTCZZ
Print plumbing (thousands-separator regex, padded-column report)
replaced with Map.take + IO.inspect; the eager-clone control group
dropped — the blob_count: 0 -> 1 transition around the single read
is the proof, and a free FS.ls afterward shows navigation doesn't
move it. 67 lines -> 32, one network clone + one blob fetch.

(FS.walk was considered for the file-count denominator but
correctly refuses :lazy repositories; ls has no such guard since
it reads one local tree.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VEo6srWr3aFwhtwaXDTCZZ
@ivarvong
ivarvong merged commit f7f095f into main Jul 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant