Version drift is expensive
The tool can resolve versions from package manifests and lockfiles, then map those versions to source tags, branches, releases, or commits.
Source vendoring for coding-agent repositories
Put the exact upstream source your agents need inside the repo, keep it aligned with your dependency versions, and stop vendor code from drowning your editor, linters, diffs, and history.
bunx ingraft
zero install
subtree / submodule / clone-ignore
Why this exists
Package docs are useful. The actual repository is better. `ingraft` makes source available to coding agents and language tooling without turning every repo into an unreviewable mirror of the internet.
The tool can resolve versions from package manifests and lockfiles, then map those versions to source tags, branches, releases, or commits.
Agents and LSPs need to read upstream code, but review diffs, formatter runs, and lint passes should stay focused on your project.
Small libraries can be subtrees, large repositories can be submodules, and temporary source mirrors can be clone-ignore entries.
The model
Commit a copy under `vendor/` when the source is small enough and you want code review, history, and branch portability.
Pin a repository without importing every file into your own history. Useful for large projects and upstreams you do not want to modify.
Keep source on disk for agents and LSPs while `.gitignore` keeps it out of commits. This is also the fallback for colocated `jj` repos.
Real code, local
Every vendored repo lands under vendor/ as real files — indexable
by your editor's LSP, navigable by Claude / Codex / Cursor, lint-able only if you ask.
Resolve the package, pick the strategy, write source under vendor/.
bunx ingraft add effect-ts/effect
bunx ingraft add zod --strategy subtree
bunx ingraft add convex --strategy submodule Re-resolve every vendor against your lockfile in one call.
bunx ingraft refresh
bunx ingraft update --all
bunx ingraft update effect --to v3.21.2 See the tool surfaces ingraft detected and what it changed.
bunx ingraft doctor
bunx ingraft doctor --fix
bunx ingraft list --json // vendor/effect/src/Effect.ts — fully indexable by your agent
export interface Effect<out A, out E = never, out R = never>
extends Variance<A, E, R>, Pipeable {
readonly [TypeId]: Effect.Variance<A, E, R>
readonly [NodeInspectSymbol]: () => unknown
[Symbol.iterator](): EffectGenerator<Effect<A, E, R>>
}
export const succeed: <A>(value: A) => Effect<A> = core.succeed
export const fail: <E>(error: E) => Effect<never, E> = core.fail
export const sync: <A>(thunk: LazyArg<A>) => Effect<A> = core.sync Workflow
$ ingraft add effect-ts/effect
✓ found package.json, bun.lock, oxlint, Biome, VS Code
✓ resolved effect@3.21.2 → Effect-TS/effect#v3.21.2
↳ strategy subtree (default)
✓ wrote vendor/effect · 2,481 files, 38.6 MB
✓ updated .gitattributes, editor settings, agent notes
$ ingraft doctor
✓ clean 2 vendors synced · 4 tool surfaces configured
→ next try ingraft refresh if you bump versions For agents and humans
ingraft turns upstream source into an intentional project surface:
versioned, observable, editor-aware, and removable when it no longer belongs.