All releases

v0.4.12

Signedpublished August 21, 2026

What changed

Added

  • Add and remove public subdomains on a running workspace. The workspace detail page now has an Add button beside Subdomains, and a bin icon on each one. Publishing a port, or withdrawing it, takes about a second and leaves the workspace running: your dev server keeps serving, your terminal sessions stay open, nothing restarts.

    Until now a subdomain could only be chosen when the workspace was created. If you decided later that port 5173 should be reachable from the outside, the only route to it was deleting the workspace and building a new one. That is a steep price for a hostname, and it is why the setting was easy to get wrong at a moment when you had not started working yet.

  • Send yourself a test notification. Settings → Notifications has a Send test button. It creates a notification and pushes it to your devices exactly the way your agents' notifications travel, then tells you what happened: how many browsers are registered, how many took it, and a reason for each one that did not. Run it on the device you are checking — every browser and phone registers separately, so a laptop that works tells you nothing about a phone that does not.

    Push notifications fail quietly by nature. A lapsed subscription, a permission revoked in your phone's settings and a preference you forgot you turned off all look identical from the outside: nothing arrives. This turns that silence into a sentence.

  • The contact sent with desktop notifications is yours to set. When DevGrail delivers a desktop notification it has to identify itself to the browser's push service — Mozilla's, Google's, Apple's — with a contact address, so those operators have somewhere to write if a deployment ever starts misbehaving. Until now that address was always your deployment's own web address, with no way to change it. Settings has a Push contact card: put an email address or a URL there and it is what gets sent from the next notification onwards, with no restart. Leave it blank and nothing changes — your deployment's own address is still used, and the card tells you which one that is.

    It is not a link anyone follows and it is never shown to your users; it is an operational contact for whoever runs the push service. Setting it to an address a person actually reads is worth the minute it takes.

Fixed

  • Notifications now arrive on phones promptly instead of eventually. DevGrail was sending notifications at normal priority, which lets Android hold them until the phone next wakes up properly — so a notification meant to interrupt you could turn up an hour later, or get folded into a batch you never noticed. Every notification is now sent at high priority, because every one of them is something you asked to be interrupted for.

  • Notifications no longer stop reaching a device and stay stopped. Browsers periodically retire a device's notification registration and issue a new one — Chrome on Android does it routinely. DevGrail did not notice, so the device silently dropped off and only came back if you happened to open DevGrail in that browser again. It now re-registers itself the moment the browser rotates it, without the app being open.

  • A notification is no longer lost when a push service is briefly busy. A single overloaded moment at Google's or Mozilla's push service used to mean the notification was gone for good. Delivery is now retried.

  • Notifications reach devices again after a deployment restore. A browser registered before a database restore was bound to a security key the server no longer had, and every notification to it failed silently and permanently. The mismatch is now detected and the device re-registers itself.

  • Desktop notifications no longer degrade over time in Chrome. When DevGrail was open and focused, the incoming notification was handled by the in-app popup and no system notification was shown. Chrome treats that as a broken promise and eventually substitutes its own "This site has been updated in the background" message, then withdraws permission altogether. The system notification is now always shown, and dismissed a moment later when you are already looking at the app.

  • Notifications now carry the DevGrail icon rather than a generic browser one.

Container images

registry build 20
amd64747 MB
sha256:797bb62b5a1b38c74da05f1ff2869f468d7f022c08fd1b08ea54502e0c33b305
Download
arm64621 MB
sha256:d3c64d4994f4332228950866c528737d2d0ef25b1616e6a24ddd7e448442f123
Download
registry build 20
amd6445 MB
sha256:ac4bcc89adea793feb7eef4f3a7b4c2de28ebf117c5cd7118015117b5d72266b
Download
arm6444 MB
sha256:6da4b3fc95a27f309be28015d14a75017bdf9daa1ed183d6dfc395fd3f7c397d
Download

Installer files

docker-compose.yml16 KBsha256:80cdf4da7d1527c13fcbe3a8726b9fe67117b47a9152ed13f269abf3e0391ad3
install.sh124 KBsha256:4db138d8bd8e11e64fdade16c54e5e155eba302eeb96bdd445b5b0d7255e1eb8
traefik-dynamic-http.yml5 KBsha256:e344c8efd13c7d84996e2ebfbc75dcee2d995d8538c8a245c89c0e44fad0089b
traefik-dynamic.yml6 KBsha256:d18fa561b8eb7d53b015284e0246b2d05953bf281b65269c1fae3d6883530db6
uninstall.sh31 KBsha256:d8dc586f38e0cf33eadc126d75b303c660e970e55028f60ad4e2872c40cbaa71

Signature

ecdsa-p256-sha256key f1f1eaf642454d65

One signature covers every artifact above. It is made off this host, and neither this site nor the registry behind it can check it — that is the point, and it is why verifying it catches things a checksum from the same server cannot. How to verify it.

Verify devgrail-container (amd64)
curl -fsSL https://web-dev.trixibot.com/api/registry/releases/v0.4.12 -o release.json

# -j, not -r: -r appends a newline the signer never saw, and the check fails.
jq -j '.signature.payload'   release.json > payload
jq -r '.signature.signature' release.json | base64 -d > payload.sig

openssl dgst -sha256 -verify devgrail-release.pem -signature payload.sig payload
# -> Verified OK

# The payload must name this release, so an older signed one cannot be replayed.
head -2 payload

# ...and it must name this exact file. -qxF: whole line, literal.
grep -qxF 'image devgrail-container 20 amd64 797bb62b5a1b38c74da05f1ff2869f468d7f022c08fd1b08ea54502e0c33b305' payload && echo "digest is covered by the signature"
The signed payload — shown for reading, not for verifying

Copy this from the manifest with jq -j, never from this page: the signature covers exact bytes, and rendering here drops the trailing newline the signer included.

devgrail-release-signature-v1
release v0.4.12
asset docker-compose.yml 19 80cdf4da7d1527c13fcbe3a8726b9fe67117b47a9152ed13f269abf3e0391ad3
asset install.sh 19 4db138d8bd8e11e64fdade16c54e5e155eba302eeb96bdd445b5b0d7255e1eb8
asset traefik-dynamic-http.yml 18 e344c8efd13c7d84996e2ebfbc75dcee2d995d8538c8a245c89c0e44fad0089b
asset traefik-dynamic.yml 19 d18fa561b8eb7d53b015284e0246b2d05953bf281b65269c1fae3d6883530db6
asset uninstall.sh 19 d8dc586f38e0cf33eadc126d75b303c660e970e55028f60ad4e2872c40cbaa71
image devgrail-container 20 amd64 797bb62b5a1b38c74da05f1ff2869f468d7f022c08fd1b08ea54502e0c33b305
image devgrail-container 20 arm64 d3c64d4994f4332228950866c528737d2d0ef25b1616e6a24ddd7e448442f123
image devgrail-server 20 amd64 ac4bcc89adea793feb7eef4f3a7b4c2de28ebf117c5cd7118015117b5d72266b
image devgrail-server 20 arm64 6da4b3fc95a27f309be28015d14a75017bdf9daa1ed183d6dfc395fd3f7c397d