main. For the product vision, see Immutable releases.Getting started: immutable releases (clawql-release)
This guide walks through Layer 0 end to end: parallel workspaces → signed artifacts → IPFS staging → optional Lit/x402 encryption → Arweave permanence → verify and pull.
Vision (why): Immutable releases · source docs/vision/clawql-hybrid-decentralized-github-alternative.md
CLI package: packages/clawql-release
What you get
| Step | Command | Outcome |
|---|---|---|
| Init | clawql-release init | .clawql/release.json, signed commits by default |
| Workspaces | immutable-volume snapshot | Parallel git-worktree or rift CoW checkouts |
| Golden image | golden-image build | Signed attestations (+ cosign/syft when installed) |
| Publish | publish --stage-ipfs --permanent | Manifest + Merkle root; staged then permanent |
| Paid / private | publish --encrypt --price "…" | Lit condition + x402 access metadata |
| Consume | verify / pull | Tamper check; decrypt when paid |
Day-to-day collaboration stays on Radicle (primary) with GitHub as a mirror. Official releases become permanent and verifiable on Arweave (via ar.io when configured).
Prerequisites
- Node.js ≥ 22
- Git (for worktrees and commit signing)
- From a ClawQL checkout (or any repo using the CLI):
npm ci
npm run build -w clawql-core
npm run build -w clawql-release
# binary: npx clawql-release … or clawql release …
Optional tools (used when present):
| Tool | Role |
|---|---|
rift-snapshot (rift) | Fast CoW workspaces (needs btrfs / APFS / XFS reflinks) |
ipfs (Kubo) | Real IPFS CIDs instead of local content-addressed staging |
rad | Radicle push as primary git surface |
gh | Attach manifest to a GitHub Release (mirror) |
cosign / syft | Container signatures / SBOM generation |
Path A — dry-run (start here)
No wallets, no daemons. Proves the full control plane locally or in CI.
export CLAWQL_RELEASE_DRY_RUN=1
clawql-release init
# Parallel agent-style workspaces
clawql-release immutable-volume snapshot --backend git-worktree --name agent-a
clawql-release immutable-volume snapshot --backend git-worktree --name agent-b
clawql-release immutable-volume snapshot --backend rift --name rift-a
# Fixture artifacts (replace with real SBOM / digests in production)
printf '%s\n' '{"bomFormat":"CycloneDX","specVersion":"1.5","version":1}' > /tmp/sbom.cdx.json
clawql-release golden-image build \
--image-digest clawql-mcp=sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
clawql-release publish --tag v0.0.0-local \
--sbom /tmp/sbom.cdx.json \
--image-digest clawql-mcp=sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
--stage-ipfs --permanent --encrypt --price "0.01 USDC" \
--dry-run
# Print tx id from the publish output, then:
clawql-release verify local_<…>
clawql-release pull local_<…> --rift
One-shot CI/local script (same flow GitHub Actions runs):
CLAWQL_RELEASE_DRY_RUN=1 node scripts/release/ci-pipeline-e2e.mjs
Workflow: .github/workflows/clawql-release-pipeline.yml
Dry-run stores live under .clawql/ (gitignored):
| Path | Purpose |
|---|---|
.clawql/ipfs-staging/ | Content-addressed staging (clawql-cid:sha256:…) |
.clawql/arweave/<tx>/ | Permanent bundle stand-in |
.clawql/escrow/ | Content-encryption keys for Lit dry-run release |
.clawql/keys/ | Ed25519 release signing + optional SSH commit signing |
.clawql/workspaces/ | Snapshot metadata + git-worktree roots |
.rifts/ | Rift CLI or local fallback workspaces |
Path B — real workspaces (laptop)
Git worktree (always available)
clawql-release immutable-volume snapshot --backend git-worktree --name feature-42
cd .clawql/workspaces/git-worktree/feature-42
# edit / test / commit as usual (shared object store with the main repo)
List / remove:
clawql-release immutable-volume list
clawql-release immutable-volume remove --name feature-42
Rift CoW (when the filesystem supports it)
npm install --prefix ~/.local/clawql-rift rift-snapshot
export PATH="$HOME/.local/clawql-rift/node_modules/.bin:$PATH"
rift init # must succeed on btrfs / APFS / XFS with reflinks
clawql-release immutable-volume snapshot --backend rift --name agent-42
If rift init fails with “copy-on-write cloning unavailable” (typical on ext4 / overlay / many CI runners), clawql-release still creates a local fallback under .rifts/ for provenance. True CoW needs a capable volume — use a laptop APFS volume, a btrfs disk, or a self-hosted runner with that FS.
Path C — full publish (production-shaped)
1. Collect artifacts
Build your SBOM, npm pack, and record image digests (from GHCR / cosign):
# examples — adjust to your pipeline
npm pack
# syft . -o cyclonedx-json=sbom.cdx.json
# skopeo inspect … → digests
2. Snapshot the build environment
clawql-release immutable-volume snapshot --backend rift --name build-$(date -u +%Y%m%d)
# or: --backend git-worktree
3. Golden image attestations
clawql-release golden-image build \
--version 7.1.0 \
--image-digest clawql-mcp=sha256:YOUR_DIGEST
4. Publish
Public release (GitHub mirror + IPFS staging + Arweave):
# Omit CLAWQL_RELEASE_DRY_RUN for live backends when tools/env are set
clawql-release publish --tag v7.1.0 \
--sbom sbom.cdx.json \
--npm-tgz clawql-mcp-7.1.0.tgz \
--image-digest clawql-mcp=sha256:YOUR_DIGEST \
--stage-ipfs --permanent --github
Paid / private release:
clawql-release publish --tag v7.1.0 \
--sbom sbom.cdx.json \
--stage-ipfs --permanent \
--encrypt --price "0.50 USDC"
5. Verify and pull
clawql-release verify releases/v7.1.0/manifest.json
clawql-release verify <arweave-tx-id>
clawql-release pull <arweave-tx-id> --rift
# Paid bundles: present PAYMENT-SIGNATURE / dry-run receipt; Lit releases the CEK
clawql release … is the same surface via the main ClawQL CLI.
Configuration
clawql-release init writes .clawql/release.json. Useful fields:
{
"version": 1,
"outputDir": "releases",
"requireSignedCommits": true,
"workspaceBackend": "git-worktree",
"collaboration": {
"primary": "radicle",
"githubMirrorUrl": "https://github.com/org/repo"
},
"permanence": {
"arweaveGateway": "https://arweave.net",
"dryRun": true
},
"access": {
"defaultPrice": "0.50 USDC",
"asset": "USDC",
"network": "base-sepolia"
}
}
Signed commits: init enables commit.gpgsign when a signing identity exists, or configures an SSH key under .clawql/keys/. Opt out with requireSignedCommits: false.
Live network knobs (laptop / self-hosted — not hosted Actions wallets)
| Env | Enables |
|---|---|
CLAWQL_RELEASE_DRY_RUN=1 / CLAWQL_RELEASE_MODE=local | Force local backends (CI default) |
| (ipfs on PATH) | Real ipfs add CIDs |
CLAWQL_IPFS_GATEWAY | HTTP gateway base for IPFS |
CLAWQL_ARWEAVE_WALLET_JWK | ar.io / Turbo upload path |
CLAWQL_ARIO_TURBO_URL | Turbo endpoint |
CLAWQL_ARWEAVE_GATEWAY / CLAWQL_ARIO_GATEWAY | Fetch/verify gateways |
CLAWQL_X402_ENFORCE=1 | Live facilitator verify |
CLAWQL_X402_FACILITATOR_URL | Facilitator base URL |
CLAWQL_X402_WALLET / CLAWQL_X402_NETWORK | Payment metadata defaults |
CLAWQL_LIT_NETWORK | Lit network label for key release |
Do not put spendable Arweave wallets in GitHub Actions secrets for the dry-run workflow. Prefer laptop or a self-hosted runner for one small live --permanent publish.
Maturity of live adapters
| Backend | Dry-run / local | Live |
|---|---|---|
| git-worktree | Full | Full |
| rift | Fallback under .rifts/ | Full when rift + CoW FS work |
| IPFS staging | clawql-cid:sha256:… | Kubo when ipfs is available |
| Ed25519 manifest/artifacts | Full | Full |
| Arweave / ar.io | .clawql/arweave/<tx>/ | Env-gated Turbo path (harden with a real wallet on laptop) |
| Lit + x402 | Escrow CEK + dry-run receipt | Soft facilitator / Lit hooks — validate on testnet before production |
What the manifest records
Every publish writes releases/<tag>/manifest.json (schema v0.2) including:
repository.commit+ dirty flagartifacts.*/images.*with SHA-256 (+ Ed25519 signatures)merkleRootover those leavesbuildEnvironment(worktree / rift snapshot ancestry when present)collaboration(Radicle primary + GitHub mirror banner)staging.ipfs·permanence.arweave·access(public or paid)
Runtime checks:
clawql doctor --smokeresolvesreleases/v\{version\}/manifest.jsonwhen presentCLAWQL_RELEASE_MANIFEST=/path/to/manifest.jsonverifies at MCP startup (strict withCLAWQL_RELEASE_MANIFEST_STRICT=1or production)
Container digests are also verified with cosign separately — see docs/security/golden-image-pipeline.md.
Suggested learning order
- Dry-run —
ci-pipeline-e2e.mjsor Path A above - Parallel worktrees on your laptop — Path B
- Rift CoW on APFS/btrfs if you run many agents
- Local Kubo — publish with
--stage-ipfswithout dry-run - One tiny Arweave publish with a funded wallet outside CI
- x402 + Lit testnet for a paid decrypt round-trip
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Manifest records dirty git tree | Uncommitted tracked changes at collect | Commit or stash; untracked .clawql/ / .rifts/ are ignored |
rift init fails (no reflinks) | ext4 / overlay / cloud VM | Use git-worktree or a CoW-capable volume |
verify fails signature | Wrong key / tampered file | Re-publish; check .clawql/keys/ |
No Arweave tx on --permanent | Dry-run or missing wallet | Expected under CLAWQL_RELEASE_DRY_RUN; set wallet only on trusted hosts |
| Pull decrypt fails | Missing escrow / payment | Check .clawql/escrow/<tag>.key or live Lit+x402 config |
Related docs
- Vision: Immutable releases
- Short reference (MVP-era notes):
clawql-release-mvp.md - Package README:
packages/clawql-release/README.md - Golden images:
docs/security/golden-image-pipeline.md - Modularization Layer 0:
docs/vision/clawql-modularization-v2.md