Quickstart
This walkthrough takes you from zero to a signed release that a client successfully applies. It uses the local filesystem backend and a Python HTTP server in place of S3 + CloudFront, so you can run the whole thing on one machine.
Install
go install github.com/ethan-mdev/patchline/cmd/patchline@latestGenerate a signing keypair
patchline keygen \ --private-out ./patchline.key \ --public-out ./patchline.pubThe private key is written with mode 0600. Keep it out of your repo.
Publish a build
Assuming your build artifacts live in ./dist:
patchline publish \ --app-id com.example.game \ --version 1.0.0 \ --channel beta \ --output ./release-output \ --signing-key ./patchline.key \ ./distThis scans ./dist, hashes every file with SHA-256, writes the content-addressed objects to ./release-output/objects/sha256/..., signs the release manifest with your private key, and writes both releases/1.0.0/manifest.json and channels/beta/manifest.json.
Serve the release tree
Any static HTTP server works:
python -m http.server 8080 --directory ./release-outputApply on a client
patchline apply \ --app-id com.example.game \ --channel beta \ --base-url http://localhost:8080 \ --public-key ./patchline.pub \ --install-dir ./installThe client fetches channels/beta/manifest.json, verifies the Ed25519 signature against the literal payload bytes, plans which local files differ from the manifest, downloads the missing/changed objects, and atomically swaps them in.
Promote to stable
Once you’re happy with beta:
patchline promote \ --version 1.0.0 \ --channel stable \ --signing-key ./patchline.keyThis rewrites channels/stable/manifest.json to point at the existing v1.0.0 release. No file uploads, no rescanning — just a single pointer move.
Next steps
- Concepts: Channels — how promote, rollback, and gc fit together.
- CLI Reference — every command and every flag.
- Use a
patchline.yamlnext to the CLI to avoid repeating common flags. The config supports${VAR}interpolation so CI can inject secrets without committing them.