About walrus-quilts
walrus-quilts is a skill for developers using Walrus storage. It explains how to batch small files into one storage unit and retrieve them by identifier, tag, or QuiltPatchId, with guidance for the CLI, TypeScript SDK, and HTTP API.
Key features
- 01Batch multiple small files into a quilt
- 02Read by identifier, tag, or QuiltPatchId
- 03Cover CLI, TypeScript SDK, and HTTP API
- 04Explain lifecycle limits for an entire quilt
Use cases
- 01Batch many small files to amortize metadata overhead
- 02Retrieve quilt files by identifier or tag
- 03Decide whether files are suitable for quilting
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ mystenlabs/ walrus-skills --skill walrus-quiltsAfter installing, type/walrus-quiltsin Claude Code to confirm it loaded.
Bundled filesevals/evals.json
Details
From the project READMEWalrus Quilts
Source constraint: All information in this skill is sourced from the Walrus quilt CLI documentation and quilt HTTP API documentation. When extending this skill, only pull from these sources.
A quilt batches multiple blobs into a single Walrus storage unit, significantly reducing overhead and cost for storing many small files. Individual blobs within a quilt are retrieved by their QuiltPatchId or identifier, not their standard BlobId.
All patterns in this skill are derived from:
If unsure about any quilt operation, fetch the relevant page before answering.
Related skills
| Topic | Skill | Load when |
|---|---|---|
| CLI basics | walrus-cli | General CLI installation, configuration, and single-blob operations |
| HTTP API basics | walrus-http-api | Single-blob HTTP store/read |
| Blob lifecycle | walrus-blob-lifecycle | Extending, deleting, sharing (applies to entire quilts) |
Skill Content
Key concepts
-
Quilt. A single Walrus storage unit that contains multiple blobs. On-chain, a quilt is represented as one
BlobSui object. Storage cost is based on the total quilt size, not per-blob, which saves overhead for many small files. -
QuiltPatchId. A unique ID for each blob within a quilt. It is derived from the quilt contents, so a blob's
QuiltPatchIdchanges if the quilt is recreated with different contents. This is not the same as a standardBlobId. -
Identifier. A human-readable name for a blob within a quilt (for example, the filename). Identifiers must be unique within a quilt and cannot start with
_. The field name_metadatais reserved for Walrus-native metadata. -
Lifecycle applies to the whole quilt. You cannot delete, extend, or share individual blobs inside a quilt. Operations like
delete,extend, andshareapply to the entire quilt.
Decision guide
Quilt is the right choice only when every row points to it; if any row points to a regular blob, store that item as a regular blob.
| Dimension | Use Quilt when | Use a regular blob when |
|---|---|---|
| File count | Many items you can batch (tens to hundreds, up to 666 per QuiltV1) | One item, or items that never arrive together |
| Individual size | Each item is small, typically under 10 MiB | An item approaches the ~4 GiB per-patch limit, or is large enough that overhead is negligible |
| Lifecycle | Items share a lifetime (store, extend, retire together) | An item needs its own delete, extend, or share schedule |
| Addressing | Identifier or tag lookup is acceptable | You need content-derived BlobIds; a QuiltPatchId depends on the whole quilt |
| Retrieval | Items are read individually and occasionally | Every item is a hot, independently cached object |
Pitfalls the docs call out: a single-file quilt adds QuiltPatchId indirection with no cost benefit; grouping items with mismatched lifetimes forces you to carry the whole quilt for the longest-lived item; and applications that look items up by a hash of their contents need regular blobs or their own identifier-to-content mapping.
TypeScript SDK
client.walrus.writeFiles({ files, epochs, deletable, signer }) stores all the files of one call as a single quilt, and getFiles({ ids }) / getBlob({ blobId }).files({ identifiers | tags | ids }) read patches back by identifier, tag, or quilt ID. See walrus-ts-sdk.
CLI: Storing quilts### CLI: Storing quilts
Store from directories with --paths
# Store all files from a directory recursively
walrus store-quilt --epochs 5 --paths ./my-assets/
# Store from multiple directories
walrus store-quilt --epochs 10 --paths ./images/ ./documents/ ./data.json
Filenames become identifiers. All identifiers must be unique within the quilt. Glob patterns are supported.
Store with custom identifiers and tags using --blobs
walrus store-quilt \
--blobs '{"path":"photo.jpg","identifier":"walrus","tags":{"color":"grey","size":"medium"}}' \
'{"path":"icon.png","identifier":"seal","tags":{"color":"grey","size":"small"}}' \
--epochs 5
If identifier is omitted or null, the filename is used.
Lifetime options
Same as regular walrus store: --epochs, --earliest-expiry-time, or --end-epoch.
CLI: Reading from quilts
Read by identifiers
walrus read-quilt --out ./downloads/ \
--quilt-id <QUILT_BLOB_ID> --identifiers walrus.jpg another-walrus.jpg
Read by tags
# Download all blobs tagged with species=cat
walrus read-quilt --out ./downloads/ \
--quilt-id <QUILT_BLOB_ID> --tag species cat
Read by QuiltPatchId
walrus read-quilt --out ./downloads/ \
--quilt-patch-ids <PATCH_ID_1> <PATCH_ID_2>
List all patches in a quilt
walrus list-patches-in-quilt <QUILT_BLOB_ID>
Returns all patches with their identifiers and QuiltPatchId values.
HTTP API: Storing quilts
Store quilts via multipart form upload to the publisher:
# Store 2 files with custom identifiers
curl -X PUT "$PUBLISHER/v1/quilts?epochs=5" \
-F "[email protected]" \
-F "[email protected]"
The form field name becomes the identifier. All regular blob query parameters (epochs, permanent, deletable, send_object_to) also work for quilts.
Store with Walrus-native metadata tags
curl -X PUT "$PUBLISHER/v1/quilts?epochs=5" \
-F "[email protected]" \
-F "[email protected]" \
-F '_metadata=[
{"identifier": "quilt-manual", "tags": {"creator": "walrus", "version": "1.0"}},
{"identifier": "logo-2025", "tags": {"type": "logo", "format": "png"}}
]'
Store response
The response includes the quilt blobId and individual storedQuiltBlobs with quiltPatchId values:
{
"blobStoreResult": {
"newlyCreated": {
"blobObject": {
"id": "0xe6ac...bc02",
"blobId": "6XUOE-Q5-nAXHRifN6n9nomVDtHZQbGuAkW3PjlBuKo",
"size": 1782224,
"storage": { "startEpoch": 103, "endEpoch": 104, "storageSize": 72040000 },
"deletable": false
},
"cost": 12075000
}
},
"storedQuiltBlobs": [
{ "identifier": "another_walrus.jpg", "quiltPatchId": "6XUOE-...BAQD..." },
{ "identifier": "walrus.jpg", "quiltPatchId": "6XUOE-...B0AB..." }
]
}
HTTP API: Reading from quilts
# Read by QuiltPatchId
curl "$AGGREGATOR/v1/blobs/by-quilt-patch-id/<PATCH_ID>"
# Read by quilt ID + identifier
curl "$AGGREGATOR/v1/blobs/by-quilt-id/<QUILT_BLOB_ID>/walrus.jpg"
Only one blob per request is supported currently. Bulk retrieval from a quilt in a single request is not yet available.
Response headers
Both methods return raw blob bytes. Metadata is returned as HTTP headers:
X-Quilt-Patch-Identifier: The blob's identifier within the quiltETag: The patch ID or quilt ID for caching
When to use quilts vs individual blobs
| Scenario | Recommendation |
|---|---|
| Many small files (<10 MB each) | Quilt. Each individual blob has ~64 MB of per-blob metadata overhead. Quilts amortize this across all files. |
| Lots of small JSON documents | Quilt. Individual store calls for tiny blobs are very cost-inefficient. |
| One large file (>10 MB) | Individual blob. No benefit from quilting a single file. |
| Files that need independent lifecycle | Individual blobs. You cannot delete/extend individual files in a quilt. |
| Static website assets | Quilt. Walrus Sites uses quilts internally for this reason. |
The per-blob metadata overhead means storing a 1 KB JSON blob individually costs about the same as storing a 64 MB file. Quilts eliminate this by packing everything into one storage unit.
Rules
- Identifiers must be unique within a quilt. Duplicate identifiers cause the store operation to fail.
- Identifiers cannot start with
_. The_metadatafield name is reserved for Walrus-native metadata. - Lifecycle operations apply to the entire quilt. You cannot delete, extend, or share individual blobs inside a quilt.
- QuiltPatchId is not a BlobId. A blob's
QuiltPatchIdis specific to the quilt it belongs to. The same file content in a different quilt gets a differentQuiltPatchId. - Use quilts for many small files. Quilts reduce per-blob overhead. For a single large file, use regular
walrus store. - Content-addressing still applies. The same quilt content always produces the same quilt blob ID.
Common mistakes
- Trying to delete a single blob from a quilt. You must delete the entire quilt. Individual blobs cannot be removed.
- Using a BlobId to read from a quilt. Blobs within a quilt are identified by
QuiltPatchIdoridentifier, not standardBlobId. - Duplicate filenames across directories. When using
--pathswith multiple directories, if two files have the same name, the identifiers collide and the store fails. - Expecting bulk HTTP reads. Currently only one blob per HTTP request is supported for quilt reads.
- Storing many small blobs individually instead of as a quilt. This is the most common cost mistake. Each individual blob incurs ~64 MB of metadata overhead. A batch of 100 small JSON files stored individually costs roughly 100x more than quilting them together.