Skip to main content

darsay

Keep a model forever. Run it tomorrow.

pipx install darsay

darsay archive Qwen/Qwen3-0.6B
darsay run     qwen--qwen3-0.6b "Say hello"

Pinned Hub artifacts — hashed, licensed, and kept in their published formats.
Preserve the bytes. Prove supported selections still run offline.
Python 3.10+ · macOS and Linux · Apache 2.0

PyPI CI Apache 2.0 Python 3.10+ Manifest schema 2.1.0

Start here · Concepts · Examples · All docs · Contributing


The idea in four lines

You have a vault. It holds bundles. A catalog is a list of works you intend to archive — shareable before any payload exists.

Each bundle is one pinned revision of one source: an immutable payload (model/ or data/), a manifest.json of recorded facts, and one file you write by hand (curation.md).

archive puts the snapshot in the vault. run speaks to it offline. export packs it into a single .mvb.tar that any tar can open in 2040. list is the vault as a catalog view; list summer overlays a want-list.

The payload never changes. The Hub can.

  Hugging Face                         your disk
  ────────────                         ─────────
  Qwen/Qwen3-0.6B                      vault/
       │                                 │
       │  darsay archive                 │
       └──────────────►──────────────────┤
                                         │
                          qwen--qwen3-0.6b/<rev>/
                          ├── model/           frozen snapshot
                          ├── manifest.json    recorded facts
                          └── curation.md      your notes
                                         │
                          darsay run ────┘──► tokens, offline
On the Hub In a bundle
A living website A pinned git revision
Can be gated, rewritten, deleted Payload is immutable after archive
“latest” is a moving target The manifest records what was true
You hope it still loads darsay run is offline proof

New here? Take the guided first bundle (~five minutes with a tiny model). Want the mental model in full? Concepts. Want copy-paste recipes? Examples.

Install

Requires Python 3.10+. Isolated CLI tools are the intended way to run a release; see distribution.

pipx install darsay
# or, no install at all:
uvx darsay --help
# or:
uv tool install darsay
Homebrew tap — org tap, not homebrew/core

Unqualified brew install darsay will not find it.

brew install darsay-io/darsay/darsay
Development checkout
python3 -m venv .venv
.venv/bin/pip install -e .                      # core: huggingface_hub only
.venv/bin/pip install -e ".[fast-hash,smoke]"   # + blake3, tokenizers
.venv/bin/pip install -e ".[inference]"         # + transformers/torch for in-process smoke
.venv/bin/pip install -e ".[datasets]"          # + pyarrow for measured dataset row counts
.venv/bin/pip install -e ".[dev]"               # pytest
.venv/bin/pytest                                # unit + integration; see docs/TESTING.md

The extras only serve in-process smoke tests. darsay run needs none of them — hydration builds its own isolated env per engine.

The vault root defaults to ~/darsay (override with --vault or $DARSAY_HOME; --vault works before or after the subcommand). Bundles are gitignored in this checkout — they live on disk or in your backup tier, not in the git repo.

The three verbs

1. Estimate — price the source from Hub metadata. Nothing downloaded.

darsay estimate Qwen/Qwen3.8-27B
Qwen/Qwen3.8-27B @ main -> 1d4bf0f2ff60
  image-text-to-text | license apache-2.0
  archive:      the whole repo — 1 negative set (28 files, 51.7 GiB); nothing here is a print
  parameters:   27.78B BF16  [upstream safetensors metadata]
  precision:    BF16 — 2.00 B/param: about one 16-bit weight copy
  family:       Qwen · generation 3.8 · member 27B  [read from the name]
  architecture: qwen3_5  [config.json]
  lineage:      no parents declared upstream
  payload:      32 files, 51.8 GiB (archive)
  engines:      transformers
  completeness: complete
  download:     ░░░░░░░░░░░░░░░░░░░░░░░░    0.0%   0 B / 51.8 GiB
                nothing banked yet — full 51.8 GiB in 32 files to fetch
  bundle:       ~/darsay/qwen--qwen3.8-27b/1d4bf0f2ff60  (new)
  disk:         needs ~55.5 GiB, free 1022.6 GiB — OK

To archive: darsay archive Qwen/Qwen3.8-27B

Exits non-zero when free space is insufficient, so it doubles as a guard in scripts. The payload names its scope: repository, selection, or classified archive. precision: explains one complete weight variant's bytes per parameter; family: places the work in its lineage (Concepts). GGUF packs list each variant with the total of all its shards; --variants lists other repositories in the quantized ecosystem. --include '*Q4_K_M*' prices the matching variant inside a GGUF pack. For example, the 321B-parameter GLM-5.3-Flash GGUF repository contains 2.315 TiB across twelve variants, while its UD-Q4_K_XL weights occupy 186.0 GiB (case study). Archive totals can include several variants and unresolved weights; classification does not choose one precision for you. When a partial archive already exists, the download block prices the resume instead — verified, partial, and unverified bytes are banked, and only the remainder counts against disk:

  download:     ██████▋░░░░░░░░░░░░░░░░░   27.4%   14.2 GiB / 51.8 GiB
                banked 14.2 GiB = 12.1 GiB verified in 8 files + 2.1 GiB partial in 1 file
                still to fetch 37.6 GiB in 24 files

2. Archive — pin a revision, fetch bytes, hash them, write the manifest.

darsay archive Qwen/Qwen3-0.6B

Ctrl-C is fine. Budgets are fine. The same command resumes:

darsay archive Qwen/Qwen3.8-27B --max-gb 10     # tonight
darsay archive Qwen/Qwen3.8-27B --max-gb 10     # tomorrow
darsay archive Qwen/Qwen3.8-27B                 # finish, verify, register

3. Run — isolated env, fully offline, payload untouched.

darsay run qwen--qwen3-0.6b "Say hello"

Or skip the tool and point any Hugging Face-compatible loader at the payload:

from pathlib import Path
from transformers import AutoModelForCausalLM, AutoTokenizer

path = Path.home() / "darsay/qwen--qwen3-0.6b/<rev>/model"
tok = AutoTokenizer.from_pretrained(path)
model = AutoModelForCausalLM.from_pretrained(path)

No unpacking. No conversion. The archived files are the model.

A bundle

vault/qwen--qwen3-0.6b/<revision12>/
├── model/              # immutable payload: selected upstream files, byte-for-byte
├── manifest.json       # machine-readable record — the source of truth
├── README.md           # human-readable summary, generated from the manifest
├── SHA256SUMS          # the payload's hash list: `sha256sum -c` verifies it with no darsay
├── VERIFICATION.md     # latest verification report
├── verification.json   # verification history (last 50 runs)
├── curation.md         # curator's notes — the only hand-edited file
├── exports.json        # log of single-file exports (after first export)
├── hydration.json      # runnable-env record + run history (after first hydrate)
├── transfer.json       # disposable resumable-transfer ledger
├── transfer.lock       # transient writer lock (only during archive/assemble)
└── LICENSE             # upstream license text, surfaced at the root

The payload under model/ (or data/ for datasets, code/ for repositories) is immutable after archiving; the bundle hash covers it alone.

What the manifest records
Section Contents
identity name, publisher, release date; family, generation, member, variants, formats, size — read from the name
source provider, address, pinned commit, transfer accounting, mirrors, signatures, popularity + tags at archive time
licensing SPDX id, license files, commercial / redistribution / modification / attribution flags, patent grant, trademark terms
inventory per-file size + SHA-256 (+BLAKE3), upstream checksum match, deterministic bundle hash
model_metadata parameter count by dtype (from safetensors headers — no torch), release precision and bytes per parameter, architecture, context, tokenizer, languages
runtime engines from shipped formats, estimated min RAM/VRAM, measured hardware from darsay run
validation checksum verification, completeness, tokenizer + inference smoke tests
lineage parents as upstream declares them (finetune, adapter, merge, quantized, trained-on); finetunes, quantizations, GGUF prints at archive time
archive date, host, storage tier, backups, last integrity check
security integrity status, unexpected-change flags, trust level
curation historical significance, capabilities, limitations, notes (via curation.md)

schema_version is recorded in every manifest. Field-by-field reference: docs/MANIFEST.md.

Commands

You want to… Type
Price a source, download nothing darsay estimate Qwen/Qwen3.8-27B
Keep it darsay archive Qwen/Qwen3-0.6B
Talk to it darsay run qwen--qwen3-0.6b "Say hello"
See what you have darsay list (STATUS / SOURCE / HAVE; path in --json / info)
Share a want-list darsay catalog new summer then list summer / archive --next summer
Read a catalog as a family tree darsay list summer --sort family — FAMILY and PRECISION columns on every row
Hold a place for an API-only model darsay catalog add summer https://www.qwencloud.com/models/qwen3.8-max-0902 — a closed work, in its family, no price
Disk use darsay du
Stop before the disk fills on by default (2 GiB floor, exit 10); darsay config shows it, --min-free 10G raises it
Leave bandwidth for everyone else darsay archive Qwen/Qwen3.8-27B --max-rate 5M (or max_rate = "5M" in config.toml)
Survive a dropped network nothing to type — the panel reads offline, keeps what arrived, resumes when it is back (--max-offline 4h waits longer)
Put it on another disk darsay mv qwen--qwen3-0.6b /Volumes/big — verifies the copy, then removes the source. rsync into <name>/<rev>/ is just as valid, always; mv after an rsync hashes the copy in place and copies nothing that matched
Keep a verified backup copy darsay cp qwen--qwen3-0.6b /Volumes/backup — verified there; both manifests record the replica
Delete a bundle darsay rm qwen--qwen3-0.6b --yes
Re-hash and compare darsay verify qwen--qwen3-0.6b — or, with no darsay at all, sha256sum -c SHA256SUMS in the bundle
Keep a NAS vault from being read back over the wire darsay --vault /Volumes/nas/vault config host.ssh=root@nas once (a key: ssh-copy-id root@nas; darsay never types a password) — the vault's path on the NAS is found and checked, not typed; verify, mv, and cp then hash on the NAS itself, which needs only sh and sha256sum, and mv / cp prove it answers before they copy
Diagnose the whole vault darsay doctor (offline; --fix is journaled and undoable)
Pack one file for a USB drive darsay export qwen--qwen3-0.6b -o /backups
Bring that file back darsay import /backups/<file>.mvb.tar
Take in a bundle from an older darsay darsay migrate <bundle> — re-reads its record under the current schema, offline; the payload is untouched (-n to read the plan, --all for the whole vault)

Source refs are provider-qualified — huggingface:Qwen/Qwen3-0.6B, huggingface:datasets/owner/name, github:owner/repo. Unprefixed owner/name / datasets/owner/name and huggingface.co URLs are Hugging Face shorthand; a github.com repository URL is GitHub's. An unprefixed owner/name that exists only as a dataset is resolved at pin time to huggingface:datasets/owner/name. A repository archives as a code bundle (Code bundles).

The rest of the CLI
darsay estimate Qwen/Qwen3.8-27B --variants
darsay estimate unsloth/Qwen3.8-27B-GGUF --include '*Q4_K_M*'
darsay archive  unsloth/Qwen3.8-27B-GGUF --include '*Q4_K_M*'
darsay classify OBLITERATUS/Qwen3.8-27B-OBLITERATED   # negative/print verdicts per weight set
darsay archive  OBLITERATUS/Qwen3.8-27B-OBLITERATED --full   # every published file and layout
darsay estimate datasets/saidutta69/fable-5-premium
darsay archive  datasets/saidutta69/fable-5-premium
darsay archive  github:MiaAI-Lab/Qwen3.8-Flash-Next-Single-DGX-Spark   # a repository at a commit, payload under code/
darsay archive  Qwen/Qwen3.8-27B --revision v1.0      # pin a tag or commit instead of main
darsay archive  Qwen/Qwen3.8-27B --max-gb 10          # pause; rerun to resume
darsay archive  Qwen/Qwen3.8-27B --min-free 10G       # pause below 10 GiB free
darsay archive  Qwen/Qwen3.8-27B --yes                # bank what fits even if the disk cannot hold it all
darsay archive  Qwen/Qwen3.8-27B --max-rate 5M        # cap at 5 MiB/s
darsay archive  Qwen/Qwen3.8-27B --max-offline 4h     # wait out a lost network longer
darsay config                                         # effective settings + config files
darsay doctor                                         # offline diagnostics; writes evidence only
darsay doctor --fix --json                            # low-risk repairs + stable automation output
darsay doctor undo latest                             # restore the prior bytes/state
darsay archive  Qwen/Qwen3.8-27B --dry-run            # verified / partial / missing
darsay archive  Qwen/Qwen3.8-27B --shard 1/3 --max-gb 20
darsay --vault ./combined assemble /usb/alice/<bundle> /usb/bob/<bundle>
darsay --vault /Volumes/big assemble ~/darsay/<bundle> --handoff   # partial: hand verified files over, keep a skeleton
darsay migrate  <bundle>                              # a record from an older darsay → this schema; payload untouched
darsay migrate  --all -n                              # every such record in the vault: the plan, nothing written
darsay mv       <bundle> /Volumes/big                 # registered: rename or copy+verify, then remove the source
darsay cp       <bundle> /Volumes/backup              # registered: verified copy; source kept, replica recorded
darsay list --json
darsay du
darsay rm       <bundle> --yes
darsay complete zsh                                   # eval "$(darsay complete zsh)"
darsay smoke    <bundle> [--inference]
darsay info     <bundle>                              # path, id, or unique prefix
darsay regen    <bundle>                              # rebuild README after editing curation.md
darsay hydrate  <bundle> [--dry-run]
darsay envs [--prune]
darsay dehydrate <bundle>
darsay rm       <bundle> -n                           # -n / --dry-run: same checks, nothing written

Every command that writes — archive, assemble, import, export, migrate, mv, cp, rm, regen, hydrate, run, dehydrate, envs --prune, the catalog verbs, estimate CATALOG — takes -n / --dry-run: the same checks, the same report in the conditional, nothing written, and the real command to paste.

Adding another host is a source provider, not a new CLI: docs/SOURCES.md.

When you need more

Pause, resume, share the work. Ctrl-C, --max-gb, a dropped network, a USB stick, --shard 1/3 with a collaborator. Partial bundles are relocatable. Incremental transfer · recipe

Datasets and code are the same shape. A dataset is datasets/owner/name, payload under data/; a GitHub repository is github:owner/repo, payload under code/. Everything else is identical. Datasets · Code bundles · recipe

Export is a plain tar. Deterministic .mvb.tar, marker first, no compression, recoverable with stock tar. MVB format · recipe

Choose the scope; preserve the evidence. A publisher release, a variant pack, and one selected quant are different collections. Derived does not mean disposable. Every size names its scope; only same-bundle, hash-identical weight twins are omitted automatically. Quantization

verify re-hashes the payload against the manifest and exits non-zero on drift — suitable for cron. import fully re-hashes before a bundle enters the vault; failures register nothing.

run hydrates first: picks an engine from what the payload ships (safetensors → transformers, GGUF → llama-cpp), builds a dedicated venv outside the bundle under <vault>/.runtime/, and infers with HF_HUB_OFFLINE=1. Envs are disposable. Design: docs/HYDRATION.md.

Documentation

Start here Then When you need the spec
Getting started Concepts · Examples Documentation home · North star
Manifest MVB format the two documents a 2040 reader still needs
Hydration · Incremental · Datasets Sources · Quantization how the verbs actually work
Design Distribution · Testing why Python, how a release is consumed, what CI keeps

The tool is replaceable. The formats are not — plain JSON and plain tar, each documented for recovery without darsay. Full rationale: docs/DESIGN.md.

License

Apache License 2.0. See LICENSE. Bundles record upstream model and dataset licenses separately in manifest.json; those do not change the license of this tool.

Metadata

Release files for darsay 0.14.19

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for darsay 0.14.19
File Size Uploaded
darsay-0.14.19.tar.gz 2.7 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for darsay 0.14.19
File Interpreter ABI Platform
darsay-0.14.19-py3-none-any.whl Python 3 none any Details

Total release size: 3.0 MB

Release files / darsay-0.14.19.tar.gz

Download URL darsay-0.14.19.tar.gz
Size 2.7 MB
Tags Source
SHA-256 checksum
How to use checksums
a7284de9048b62df66a86feea6963c55036396e73541cbe9be7e19a085877ba7
BLAKE2b-256 checksum
How to use checksums
ab883e205852cd96fbceec7ac32ad759ddace60f6ad1d645448136b215e2ac51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / darsay-0.14.19-py3-none-any.whl

Download URL darsay-0.14.19-py3-none-any.whl
Size 332.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e2c9a40f650be3deda8c9d86fd65ee5ff4eb37d524fb6b903095f675bbf77316
BLAKE2b-256 checksum
How to use checksums
45a0723b5fd113f99533481de0904e758b8924e21c9c6c10144fd4ee8dfe0d2c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release history Release notifications | RSS feed

0.20.1

2 release files

0.20.0

2 release files

0.19.2

2 release files

0.19.1

2 release files

0.19.0

2 release files

0.18.0

2 release files

0.17.7

2 release files

0.17.6

2 release files

0.17.3

2 release files

0.17.2

2 release files

0.17.1

2 release files

0.17.0

2 release files

0.16.5

2 release files

0.16.4

2 release files

0.16.3

2 release files

0.16.2

2 release files

This release

0.14.19 This release

2 release files

0.14.8

2 release files

0.14.7

2 release files

0.14.6

2 release files

0.14.5

2 release files

0.14.4

2 release files

0.14.3

2 release files

0.14.2

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page