β¨ feat(git0): add partial downloads and lazy history attachment - #106
Conversation
`main()` printed the banner before parsing arguments and then `downloadRepoAndSetup()` printed it again, so the most common invocation of all β `git0 owner/repo` β rendered the logo twice and looked broken. Deleting one of the calls would have fixed the common case and left the paths that reach a download without going through `main()` unbranded, so `printLogo` is now idempotent instead: every call site can still say "show the branding here" and the user sees it exactly once. `resetLogo()` lets the tests drive several flows through one process. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23
A link copied out of the GitHub UI already says which folder or file you want β `/tree/main/packages/react-dom`, `/blob/master/.continue/agents/x.yaml` β and git0 threw that away and downloaded the repository around it. It is now read and honoured. Entries outside the path are dropped in tar's parser, ahead of the unpacker's `strip`, so they are skipped in the stream and never written; the requested subtree is then hoisted to the root of the target folder, which reads dir-vs-file off the disk rather than guessing at a strip depth the `owner/repo/some/path` shorthand cannot supply. The folder is named after the path rather than the repository, because downloading `debate-ai.com/.continue/agents` into a folder called `debate-ai.com` claims to hold a site and holds two config files. Also adds `--path`, `--branch`/`--ref`, and flag parsing in its own module so it is testable without executing `cli.ts`'s top-level `main()`. A failed tarball request now reports the repository and branch instead of leaving an empty directory for the next step to trip over. `..` in a sub-path is rejected rather than normalized away: the value becomes a prefix match and then a path join, and the only honest reading of `packages/../../etc` in a "download this folder" argument is that something is wrong with it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23
`--history` ends in the same state `git clone` would have left you in β a working tree with a full `.git` beside it, `git log` working, `git status` clean β without giving up the speed that is git0's whole point. The ordering is the feature. A clone is serial: the remote counts and packs every object in the history, sends the pack, and only then writes files you can run. A codeload tarball is a pre-made, cached, already-compressed snapshot that extracts while it downloads. And history is the one part of a clone that nothing on the critical path waits for β `bun install` does not need `git log` β so it is started after extraction finishes and awaited at the very end, overlapping the IDE launch and the dependency install rather than blocking them. Mechanically: bare clone into a temp directory, renamed into place only once it succeeds so an interrupted download leaves no half-written `.git`; `core.bare` flipped; origin's fetch refspec restored; `git reset --mixed HEAD` to populate the index from HEAD without touching the extracted files. A failed fetch is reported and swallowed β a missing `git` or a dropped connection should cost the user their history, not the project they are already working in. `--history-only` is the other half: a bare clone into `<repo>.git` with no working files, or `--mirror` for every ref, for a backup or a host-to-host move. `benchmark/` measures the claim rather than asserting it β time to files (when the project can run) separately from time to history, across `git clone`, `git clone --depth=1`, git0 and `git0 --history`. It is a `.bench.ts`, so `bun test` does not collect it and it never runs in CI; its pure reporting helpers are unit-tested. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23
git0 has a site, and nothing in the README pointed at it. The badge catalog already carries a `website` badge; what was missing was a `websiteUrl` for package headers. It is read off `homepage` rather than a list kept in the script β npm already asks for that field and renders it, so a package with a site has usually filled it in, and the ones that have not left it at the GitHub tree URL the publish flow writes. A badge back to the page you are already on is noise, so a `github.com` homepage yields no badge and every other package's header is unchanged. git0's own `homepage` now points at the site instead of its directory on GitHub, which is also what npm should have been showing. The README gains the link and documents both new features: partial paths, and `--history` with the reasoning for why fetching history last is faster than cloning it first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23
The skill is the documentation agents actually load, so it gains the new invocations, a flag table, the mechanics of hoisting and of the bare-to- working conversion, and the four new failure messages with their causes. The package note records the three things a future change is most likely to undo by accident: `printLogo`'s guard is the fix and not a redundancy, `normalizeSubPath` rejecting `..` is a boundary check and not tidying, and awaiting the history download earlier silently gives back the speed the feature exists to keep. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23
`bun run readmes:check` was already failing on master for these four β their generated headers had drifted from what `sync-package-readmes.mjs` produces. Unrelated to the git0 work in this branch, but CI fails on the whole repo, so the generator's own output is brought back in line. No hand edits. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
master's version-bump commit moved git0 to 0.2.99 while this branch had already moved it to 0.3.0 for the new flags. Resolved to 0.3.0 β it is ahead of master's patch bump, and the new public behaviour (`--path`, `--branch`, `--history`, `--history-only`, `--mirror`) is a minor, not a patch. That version line was the only conflict; everything else merged cleanly. Revalidated after the merge: 134 tests pass, the bundle builds, and `readmes:check` is clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23
The three red Vercel checks are not this PR's
The cause is "postinstall": "fumadocs-mdx && drizzle-kit push"
Why it isn't this branch:
No fix for it exists anywhere yet, so there is nothing to port into this PR, and fixing it here would mean editing a package this change has no business touching ( Proposed patch, as a separate change: --- a/packages/api2ai-mcp-generator/package.json
+++ b/packages/api2ai-mcp-generator/package.json
- "postinstall": "fumadocs-mdx && drizzle-kit push",Worth doing on its own merits beyond unblocking CI: This PR's own state: I have no way to re-run a Vercel deployment, so I am not spending a re-run on this. Generated by Claude Code |
Codecov Reportβ Patch coverage is π’ Thoughts on this report? Let us know! |
#106 landed as a squash commit, so this branch shares no commits with the result even though master already carries every line of it. Merging master back in realigns the two: the merge-base becomes master's tip, and what is left on this branch is the one commit that has not landed yet β the CI install fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23
Adds support for downloading individual files or folders from a repository, and optionally attaching full Git history after extraction completes. This lets users download just the parts they need while keeping the initial download fast.
Key changes
Partial path downloads: New
normalizeSubPath(),subPathFilter(), andhoistSubPath()functions enable filtering the tarball to a single file or folder and moving it to the extraction root, sogit0 owner/repo/tree/main/packages/uidownloads only that folder.Git history attachment: New
history.tsmodule withattachGitHistory()andattachGitHistoryLazily()to fetch.giteither immediately or in the background after extraction. The lazy variant lets files be on disk andbun installstart while history downloads.URL parsing:
parseTarget()ingithub-api.tsreads GitHub URLs including/tree/and/blob/links, extracting branch and path information so users can paste links directly.CLI flags: New
args.tsparser and--path,--branch,--history,--history-only, and--mirrorflags. The--pathflag also works as a shorthand (git0 owner/repo/path/to/folder).Comprehensive tests: New test suites for sub-path normalization, filtering, hoisting, history attachment, argument parsing, and target parsing. Benchmark suite comparing tarball + lazy history vs.
git clonestrategies.Documentation: Updated README with usage examples, new features, and benchmark results. Added
benchmark/README.mdexplaining why the tarball approach wins on time-to-files.Implementation details
.git.printLogo()function is now idempotent to prevent duplicate branding when multiple entry points print it.https://claude.ai/code/session_01KULWViqKDCNmcShYttoU23