Skip to content

Argue with Packages, Not Your Colleagues

Sharing context between humans working with AI — one S3 bucket, open-source quilt3, no signup.

You run a coding agent most of the day. But when you hand work to a colleague, you send them a document — and everything that produced it (the decisions, the dead ends, the exact inputs) stays behind in a chat session that's about to evaporate.

Here's the alternative: put the context in a versioned package in your own S3 bucket, argue with Claude until it's right, and send your colleague one immutable link. They don't read a document. They ask their Claude about it.

See It Before You Build It

A worked example lives in a public bucket, next to the tutorial package this post is drawn from:

  • demo/wellplates-input — the context a human approved: raw well-plate measurements and the analysis brief.
  • demo/wellplates-output — what the agent produced: an H1N1 neutralisation analysis. Open its metadata: it pins the exact input revision it consumed. Not "the latest version" — that revision.

(That demo is just a public catalog rendering of plain S3 objects; on your own bucket you'll browse the same thing with uvx quilt3 or aws s3 cp.)

Better: don't just look at it — receive it. Paste this into Claude Code right now, no bucket, no setup:

This is a Quilt package pinned to an exact revision: quilt+s3://agent-context-spec#package=demo/wellplates-output@2379e3bb2e608616e02bf93a638c72c517cadc6ecb9bf4611b0b988eba0fc09c. The link decodes as bucket / package name / top hash. Using uvx quilt3 (quilt3 install NAME --registry s3://BUCKET --top-hash HASH --dest ./review/), fetch it, find the input revision it declares and fetch that too, then tell me where the work stands.

Two minutes, and you've just been the colleague. The rest of this post is how to be the sender.

What You Need

Claude Code (or any coding agent with shell access), an S3 bucket you control, AWS credentials in your shell, and uv. No signup, no catalog account, no new database — quilt3 is open-source Python and the context lives in your bucket. Everything in this post except the postscript uses the released version of quilt3.

Three Steps

1. No install — run it with uv.

uvx quilt3 --version

2. Package your input — the thing you keep re-explaining. At the end of a working session — while the conversation still holds the context — paste into Claude Code:

Write out the context I keep re-explaining — the brief, the key decisions, the rejected approaches — as markdown files in ./context/, then push that directory as an immutable Quilt package: uvx quilt3 push USER/PROJECT-input --dir ./context --registry s3://MY-BUCKET --message "what this context is". Give me back a link that pins the exact revision — quilt+s3://MY-BUCKET#package=USER/PROJECT-input@FULL-64-CHAR-HASH — and update the --top-hash in my project instructions to the new revision.

3. Give your worker agent a standing instruction:

Fetch your input with uvx quilt3 install USER/PROJECT-input --registry s3://MY-BUCKET --top-hash HASH --dest ./input/ and treat ./input/ as read-only ground truth — stage what you produce in ./output/, never in ./input/. When I approve a result ("ship it"), push ./output/ as USER/PROJECT-output with a commit message that says what the revision accomplishes and names the exact input revision it consumed. Give me back a link that pins the exact revision — quilt+s3://MY-BUCKET#package=USER/PROJECT-output@FULL-64-CHAR-HASH; the full hash is the content of s3://MY-BUCKET/.quilt/named_packages/USER/PROJECT-output/latest.

Drop that in your project instructions and stop thinking about it. Re-pushing the input means re-pinning — the pin is the point — and step 2's prompt updates the pin for you.

And when the result isn't right — argue:

That's not quite right — revise X and push a new revision. Give me both links, then diff the two revisions and tell me what changed. (Install them to separate directories and diff, or use Package.diff from the Python API.)

Two Gotchas (Both Are the Feature)

  1. Use the full 64-character hash in any link you send. A shorter prefix works today — quilt3 resolves unique prefixes — but a prefix that's unique now can stop resolving as revisions accumulate; the full hash resolves forever. A link that can change out from under your colleague isn't a handoff, it's a race condition. (Push output shortens the hash; the full one is the content of s3://MY-BUCKET/.quilt/named_packages/USER/PROJECT-input/latest — your agent reads it back on its own when your prompt asks for the full hash.)
  2. Packages are immutable, and that's your undo. Told Claude to let 'er rip and it wasn't quite right? Push again. Every revision is kept, nothing is ever lost, and the old link still means exactly what it meant when you sent it. That goes for your collaborators too — anyone can push, nobody can destroy, so nobody has to ask permission first.

Now Send the Link

Send your colleague the output link — and this prompt, to paste into their own Claude:

This is a Quilt package pinned to an exact revision: OUTPUT-LINK. The link decodes as bucket / package name / top hash. Using uvx quilt3 (quilt3 install NAME --registry s3://BUCKET --top-hash HASH --dest ./review/), fetch it, find the input revision named in its commit message (or in agent_context.inputs if present) and fetch that too, then tell me where the work stands.

(One prerequisite: same AWS account works out of the box. Cross-account, have Claude handle it:)

Grant AWS account ACCOUNT-ID read-only access to s3://MY-BUCKET: add a bucket-policy statement allowing s3:GetObject and s3:GetObjectVersion on the bucket's objects and s3:ListBucket on the bucket — merged with the existing bucket policy, not replacing it. Show me the policy before applying it, and warn me if the bucket uses KMS encryption — they'll also need kms:Decrypt on the key.

You argued with your Claude. They argue with theirs. The package — plain S3 objects you can read back with aws s3 cp, no vendor required — holds the state in between. When they have a take, they push it as THEM/PROJECT-review to their bucket and send you the link back (same access note, other direction). Now you're arguing with packages, not each other.

Next time you're about to paste a project summary into Slack, do this instead — and when someone asks how, send them the tutorial package. This post is a rendering of its README; the original is, of course, a package too.

Everything above runs on your own bucket with open-source tools, and always will. When a whole team is sharing packages this way and wants search, visualization, and access control on top of the same buckets, that's what the Quilt stack adds — same packages, same S3, nothing to migrate.

Postscript: Machine-Readable Provenance

Everything above records provenance by convention — the input revision lives in a commit message a human wrote. Agent Context, an experimental convention in the quilt3 8.1 prerelease, upgrades it to structured metadata a machine can validate: the agent declares itself and its inputs, quilt3 stamps what it observed at write time, and an optional bucket workflow checks the shape of every push. The demo/wellplates-output metadata is exactly this. It's self-reported — informative, not proof; your bucket's access logs are the corroboration.

To try it, pin the prerelease (uvx 'quilt3==8.1.0a1'), add --agent-context to the push, and note that a push with that flag always produces a new top hash — even when the files didn't change — so --dedupe won't skip. The full standing-instruction upgrade and the bucket gate live in the tutorial package: agent-instructions.md and workflow/config.yml.


The full specification is in agent-context/spec; the implementation is in quiltdata/quilt.

Comments