De-vendoring upstream code
Pull in upstream model code at a pinned commit with store.repo — no vendored trees, no hand-maintained dep forests, no git clone in your build
store.repo lets you use an upstream model repo without copying its files into your app. You pin a commit, optionally apply a fork delta, and import the upstream modules with normal import syntax. The repo's own dependency list splices straight into yours.
This replaces the old pattern of vendoring a copy of someone else's model code into your repo (which goes stale, bloats the tree, and hides what you changed) and the matching pattern of hand-copying their requirements.txt into your Dependencies.
Forking is encouraged — and fully supported
For anything substantial — larger diffs, production use cases — fork the upstream repo and make your changes there. You get full version control, review, CI, and history on your own diff, which is exactly what a real change deserves.
A fork looks like any other git repo to uRun. store.repo pins by repo@sha, so pointing it at your fork just works — no special path, no separate mechanism:
# Point store.repo at YOUR fork's repo + commit — same spec, your org.
REPO = store.repo("github.com/your-org/restyle-model@<fork-sha>", include=["restyle"])
DEPS = Dependencies(python=[*REPO.deps(), "torch>=2.5.0"])Everything below — the diff= / overlay= deltas applied over someone else's pinned tree — is the way to avoid the overhead of a fork until you actually need one. It's a convenience for small, legible deltas, not a substitute for forking and not the recommended path for anything production-grade.
Declare the repo at module top
The repo handle is declared once, at module top, so its dependencies resolve at build/deploy time:
from urun import App
from urun.core import Dependencies
app = App("restyle")
store = app.store
REPO = store.repo("github.com/org/restyle-model@<sha>", include=["restyle"])
DEPS = Dependencies(python=[*REPO.deps(), "torch>=2.5.0"])The handle does three jobs — declaring it is the whole setup, with no separate materialize step:
store.repo("<spec>@<sha>", include=[...])— materializes the repo (or just theinclude=d subtrees) into the content-addressed store as a tree of lazy byte-leaves. The git tree is fetched once, SHA-pinned and shallow; identical files dedup to one blob. Always pin a commit SHA — an unpinned ref is non-reproducible.REPO.deps()— the upstream's own dependency list, parsed at the pinned SHA from itsrequirements.txt/pyproject.toml[project.dependencies]/setup.pyinstall_requires. Splice it into yourDependencies(python=[...])so you stop hand-maintaining a copy of their dep forest. Selectors shape the splice:extra="name"picks an optional-dependencies extra,exclude=["dep", ...]drops upstream deps by name, andpin_overrides={"dep": "==1.2"}replaces a version spec — overrides apply first, so an overridden dep survives even if also excluded.with REPO:— a scoped context manager. It puts the repo's modules on the import path only inside the block; the real upstream imports happen under the context and the path is removed after.
Import under the context manager
Do the upstream imports inside with REPO: — typically inside your @store.cache loader, so the heavy import happens exactly once:
@store.cache(key="restyle-14b")
def load_model(*, device):
with REPO:
from restyle.pipelines import RestylePipeline # resolves off the store tree
return RestylePipeline.from_pretrained(
store.path("hf://org/restyle-14b")
).to(device)Only weights stay local (*.pth / *.safetensors via store.path("hf://...")); the code comes from store.repo.
Small deltas without a fork: pin + diff
When your change is small enough that a fork would be overkill, keep pointing at the upstream repo and layer a delta on top. For a clean vendor (you use the upstream as-is), pin and import — nothing else. When you have a small delta that changes model behavior, apply it as a real unified/git diff with diff=:
REPO = store.repo(
"github.com/org/restyle-model@<sha>",
include=["restyle"],
diff="fork.patch", # inline diff string OR a path to a .patch file
)diff= applies with git apply, so multi-line edits, new functions, and new imports are all expressible. A hunk that does not apply loud-fails (raises) — it is never silently skipped. For net-new files or whole-file replacements atop the pinned tree, use overlay= (a directory path or a relpath -> bytes|str mapping).
Patch order
Deltas apply deterministically: checkout the pinned @sha → diff → overlay → store the tree. The cache key folds in the identity of every delta, so changing a patch re-materializes the tree while unchanged inputs hit the cache.
deps() splice and diff/overlay don't mix on one repo
urun deploy resolves REPO.deps(...) by static analysis — it never executes your app. A diff=/overlay= delta could rewrite the upstream's dependency metadata, so deploying an app that splices REPO.deps() from a repo that also carries diff=/overlay= aborts loudly — declare the resulting dependencies as literals instead. For the same reason the selector arguments (extra=, exclude=, pin_overrides=) must be literal constants in the app source.
Why this shape
- No vendored trees: your repo holds your app, not a stale copy of someone else's model. The upstream files live content-addressed in the store, deduped across apps and tenants.
- No dep drift:
REPO.deps()reads the upstream's real dependency list at the exact pinned SHA — you can't fall out of sync with a copy. - The delta is visible. A
diff=is the literal patch; a reviewer sees exactly what you changed versus upstream, and a bad hunk fails immediately instead of drifting out of sync. (Past a small patch, a real fork gives you that review surface with full history.) - No build-time
git clone: the fetch is a single SHA-pinned shallow fetch into the content store, lazy on the import side — no per-app git dependency baked into your image.
Scoped `with REPO:` is the default — and compile-safe
with REPO: scopes the import path, not the loaded modules: after the block no new top-level repo import resolves, but everything imported inside it stays importable and resident for the process (normal Python import semantics). A model loaded under the block keeps working — including one traced later by torch.compile.
The scoped form is the app-side idiom — apps do not call REPO.install(). If the upstream code does late top-level imports (a lazy submodule resolved on first use), pre-import those modules inside the block so they're resident before it closes:
with REPO:
from pkg import Thing
import pkg.data.transforms # pre-resolve upstream's lazy imports
import pkg.scheduler.streaming_samplerRelated:
- Dependencies — declaring Python / apt / post-install deps
- Store — the content-addressed store
store.reporides on - Streaming Pipelines — the canonical app shape that uses
store.repo