Package Exports
- @git-stunts/git-cas
- @git-stunts/git-cas/schema
- @git-stunts/git-cas/service
Readme
@git-stunts/git-cas
JESSIE, STOP—
Hold on. He’s turning Git into a blob store. Let him cook.
Most potent clone available on GitHub (legally).
Git, freebased: pure CAS that’ll knock your SHAs off. LFS hates this repo.
Git isn’t source control.
Git is a content-addressed object database.
We use the object database.
git-cas chunks files into Git blobs (dedupe for free), optionally encrypts them, and emits a manifest + a real Git tree so you can commit/tag/ref it like any other artifact.
What you get
- Dedupe for free Git already hashes objects. We just lean into it.
- Chunked storage big files become stable, reusable blobs.
- Optional AES-256-GCM encryption store secrets without leaking plaintext into the ODB.
- Compression gzip before encryption — smaller blobs, same round-trip.
- Passphrase encryption derive keys from passphrases via PBKDF2 or scrypt — no raw key management.
- Merkle manifests large files auto-split into sub-manifests for scalability.
- Manifests a tiny explicit index of chunks + metadata (JSON/CBOR).
- Tree output generates standard Git trees so assets snap into commits cleanly.
- Full round-trip store, tree, and restore — get your bytes back, verified.
- Lifecycle management
readManifest,deleteAsset,findOrphanedChunks— inspect trees, plan deletions, audit storage. - Vault GC-safe ref-based storage. One ref (
refs/cas/vault) indexes all assets by slug. No more silent data loss fromgit gc.
Use it for: binary assets, build artifacts, model weights, data packs, secret bundles, weird experiments, etc.
What's new in v2.0.0
Compression — compression: { algorithm: 'gzip' } on store(). Compression runs before encryption. Decompression on restore() is automatic.
Passphrase-based encryption — Pass passphrase instead of encryptionKey. Keys are derived via PBKDF2 (default) or scrypt. KDF parameters are stored in the manifest for deterministic re-derivation. Use deriveKey() directly for manual control.
Merkle tree manifests — When chunk count exceeds merkleThreshold (default: 1000), manifests are automatically split into sub-manifests stored as separate blobs. readManifest() transparently reconstitutes them. Full backward compatibility with v1 manifests.
See CHANGELOG.md for the full list of changes.
What's new in v3.1.0
Interactive vault dashboard — git cas vault dashboard launches a full TUI with split-pane layout, manifest detail view, keyboard navigation, and real-time filtering. Browse entries, inspect chunks, and view encryption status without memorizing CLI flags.
Progress bars — store and restore now show animated progress with throughput reporting. Suppress with --quiet.
Pretty history — git cas vault history --pretty renders a color-coded, paginated timeline of vault commits.
Inspect command — git cas inspect <tree-oid> renders manifest details with chunk table, encryption info, and compression badges.
See CHANGELOG.md for the full list of changes.
Install
npm install @git-stunts/git-casnpx jsr add @git-stunts/git-casUsage (Node API)
import GitPlumbing from '@git-stunts/plumbing';
import ContentAddressableStore from '@git-stunts/cas';
const git = new GitPlumbing({ cwd: './assets-repo' });
const cas = new ContentAddressableStore({ plumbing: git });
// Store a file -> returns a manifest (chunk list + metadata)
const manifest = await cas.storeFile({
filePath: './image.png',
slug: 'my-image',
encryptionKey: myKeyBuffer, // optional (32 bytes)
});
// Turn the manifest into a Git tree OID
const treeOid = await cas.createTree({ manifest });
// Restore later — get your bytes back, integrity-verified
await cas.restoreFile({ manifest, outputPath: './restored.png' });
// Read the manifest back from a tree OID
const m = await cas.readManifest({ treeOid });
// Lifecycle: inspect deletion impact, find orphaned chunks
const { slug, chunksOrphaned } = await cas.deleteAsset({ treeOid });
const { referenced, total } = await cas.findOrphanedChunks({ treeOids: [treeOid] });
// v2.0.0: Compressed + passphrase-encrypted store
const manifest2 = await cas.storeFile({
filePath: './image.png',
slug: 'my-image',
passphrase: 'my secret passphrase',
compression: { algorithm: 'gzip' },
});CLI (git plugin)
git-cas installs as a Git subcommand:
# Store a file — prints manifest JSON
git cas store ./image.png --slug my-image
# Store and vault the tree OID (GC-safe)
git cas store ./image.png --slug my-image --tree
# Restore from a vault slug
git cas restore --slug my-image --out ./restored.png
# Restore from a direct tree OID
git cas restore --oid <tree-oid> --out ./restored.png
# Vault management
git cas vault init
git cas vault list
git cas vault info my-image
git cas vault remove my-image
git cas vault history
# Encrypted vault round-trip (passphrase via env var or --vault-passphrase flag)
export GIT_CAS_PASSPHRASE="secret"
git cas vault init
git cas store ./secret.bin --slug vault-entry --tree
git cas restore --slug vault-entry --out ./decrypted.binWhen to use git-cas (and when not to)
"I just want screenshots in my README"
Use an orphan branch. Seriously. It's 5 git commands, zero dependencies, and GitHub renders the images inline. Google "git orphan branch assets" — that's all you need. git-cas is overkill for public images and demo GIFs.
"I need encrypted secrets / large binaries / deduplicated assets in a Git repo"
That's git-cas. The orphan branch gives you none of:
| Orphan branch | git-cas | |
|---|---|---|
| Encryption | None — plaintext forever in history | AES-256-GCM + passphrase KDF |
| Large files | Bloats git clone for everyone |
Chunked, restored on demand |
| Dedup | None | Chunk-level content addressing |
| Integrity | Git SHA-1 | SHA-256 per chunk + GCM auth tag |
| Lifecycle | git rm (still in reflog) |
Vault with audit trail + git gc reclaims |
| Compression | None | gzip before encryption |
"Why not Git LFS?"
Because sometimes you want the Git object database to be the store — deterministic, content-addressed, locally replicable, commit-addressable — with no external server, no LFS endpoint, and no second system to manage.
If your team uses GitHub and needs file locking + web UI previews, use LFS. If you want encrypted, self-contained, server-free binary storage that travels with git clone, use git-cas.
THIS HASH’LL KNOCK YOUR SHAs OFF! FIRST COMMIT’S FREE, MAN.
License
Apache-2.0 Copyright © 2026 James Ross
Built by FLYING ROBOTS