Reference
The Nest format.
A Nest is one JSON manifest plus files stored under their sha256 checksums. The format and its escape-hatch script are Apache-2.0, and the script brings a nest's files and dependencies back and checks every file using only bash, curl, jq, sha256sum, tar and uv, with no Renest software installed.
The promise this format exists for: the files and dependencies of anything you packed can be brought back on a bare machine and every file checked against its recorded sha256, without Renest —
bash,curl,jq,sha256sum(orshasum),taranduvare enough. The specification and that script are Apache-2.0, so the promise outlives us.
A Nest on disk is a manifest and a folder of files
A Nest is a directory tree, identical in your bucket, on our hosted drive, and in the local library:
nests/<nest-id>/manifest.json # the single source of truth
blobs/sha256/<first-2>/<sha256> # content-addressed bytes, one file per sha256
There is no database, no sidecar state, no proprietary container. Copying a Nest is
cp -r. Uploading and downloading are plain byte copies — no format conversion, no sync
engine.
The manifest (v2.12)
One JSON file describes everything a successful run depended on. Top-level fields:
| Field | What it records |
|---|---|
format_version | Spec version, currently "2.12". This tool can read 2.0 through 2.12; 1.x is refused outright — a one-time clean break taken while there were no real users. |
id, name, created_at | Identity: 26-character ULID, human name, pack timestamp. |
base_image | The container image the run happened on — tag and digest. Optional: a packer that cannot determine it leaves the block out rather than writing a placeholder. |
runtime | Python and CUDA runtime parameters, as probed, not as hoped. Since 2.10 this includes how much system memory the packing machine could use, so a restore onto a machine with a lower ceiling gets a warning before anything loads — a warning, never a refusal, and a missing reading is recorded as missing, not guessed. Since 2.12 it can also list, per custom node package, the machine libraries that package's own compiled files declare they need — covering nodes the working run never loaded. Also a warning, never a refusal. |
gpu, fingerprint | The machine the run was captured on. gpu is what the pre-flight check reads before refusing a card the setup was never compiled for. |
code_deps | Every code dependency — the host application, its extensions, your own scripts and config: the role it played, the exact commit where there is one, plus an archive of the working tree as it actually was, so a restore survives upstream disappearing. |
python_lock | The dependency lock, reinstalled with uv. It is the environment's own requirements.lock, uv.lock or requirements.txt when there is one (first found wins), packed as bytes, restored to the environment root and checked like any other file; otherwise the list of installed packages read from the environment's own interpreter. The lockfile itself is optional — some environments genuinely have none. Since 2.11 it also records which index a vendor-only pin came from, for the lines no direct download address could be recorded for: read off the installed package's own metadata, never guessed from the version suffix, and shown to whoever repairs the lock rather than handed to the installer. |
files | Every model/asset: path, sha256, size, kind, and a licence block. Two switches: shareable (does this byte travel on a hand-off) and serving_scope (may it be served across users). Undetermined licence ⇒ gated, deny-by-default. |
entrypoint | How the working run was started: exit code for a one-shot fine-tuning run, an HTTP probe for an image-generation server. |
adapters | Scene glue, one key per framework (comfyui, kohya, llamafactory) — for ComfyUI, the workflow JSON that was proven to run. Unknown keys pass through as opaque objects, so a fourth framework needs no version bump. |
evidence | Since 2.11: whether anyone ever saw this environment work, and how strong that proof is. An environment packed as it stands carries no such proof, and says so — rather than looking identical to one packed off a run that finished. Absent means nobody looked; none means somebody looked and there was nothing. It is a disclosure, never a reason to refuse a restore: a nest nobody watched work still restores, with every file checked. |
post_install, creation, api_deps, derived_from | Post-install command, provenance, the external API services this format honestly cannot archive, and (reserved, nothing writes it yet) which nest this one was made from. |
Required: format_version, id, created_at, runtime, code_deps, python_lock,
files. Everything else is optional, and a packer that cannot obtain a field omits it —
placeholder text is an error, absence is honest.
The full JSON Schema ships inside the renest package under specs/, and
renest lint validates any manifest against it offline — no network, no account.
Every file is stored once under its sha256
Every byte-carrying thing — models, code archives, lockfiles — is stored once under its
sha256, in blobs/sha256/<first-2>/<sha256>. sha256 and nothing else: it is what
Civitai, HuggingFace and the archival ecosystem speak, so a Nest can name its assets in
a way the rest of the world recognizes. The sha256 says the bytes are the ones recorded;
it does not promise that what the app produces from them will be identical.
Every file is checked against its sha256 when it arrives, and the escape-hatch script
checks every file again at the end. renest restore resumes an interrupted restore
without reading the files an earlier run already confirmed (it checks their size), unless
you pass --reverify; renest verify checks every file at any time.
The escape hatch is part of the spec
Every nest carries the script itself, at .renest/escape/restore.sh. It is a bash
script (not POSIX sh) and depends only on curl / jq / sha256sum (or shasum) / tar / uv
plus the stock tools every base system ships. It reads the same manifest, fetches the same
files, unpacks the code archives (it never clones), reinstalls the dependencies from the
lock, and checks every file against its sha256 — with the Renest tool nowhere on the
machine. It does not start the app; its exit code 0 means the files and dependencies are
back and checked. Any format change that would break this script is, by our own
rules, not shippable.
Format versions only ever add
- Format changes bump
format_version, and nothing after2.0has tightened anything, so every2.xnest still reads. A reader meeting a newer minor of the same major warns and carries on — rejecting it would turn a nest that would have restored into a brick. - The schema, the escape-hatch script and the linter move in the same change — the spec is never ahead of what you can verify.
- The pack tool never writes private state outside the manifest. If it's not in the manifest, it doesn't exist.
Three licence layers, deliberately not the same
The format and its script are open; the plugin follows ComfyUI; the tool is source-available:
- Genuinely open (Apache-2.0): this format specification, the JSON Schema, the worked examples and the escape-hatch script. Use, modify and redistribute them freely. These are the parts that have to outlive us for the promise above to mean anything.
- The ComfyUI plugin (GPL-3.0-or-later): it runs inside the ComfyUI process, so it follows that ecosystem's rules. It lives in its own repository.
- The
renestcommand-line tool — source-available, and not open-source software: the code is published in full; read it, audit it, modify and redistribute it, including inside a business. Any individual may use it on their own data forever, unconditionally. The one thing the licence withholds is using it to offer third parties a commercial service competing with the Renest hosted service (licensing). The full text ships with the package asLICENSE-CLI.
The hosted drive is operated by the authors of this project — same format either way, no lock-in in either direction.
These docs describe renest 0.1.15, the latest release.