All releases

v0.4.39

Signedpublished September 11, 2026

What changed

  • An agent now hands you a workspace link that works. The workspace details an agent reads over MCP carried a terminal_url that looked like a link you could open, so agents offered it as one — and it always failed, because the browser terminal is reachable only with a short-lived token the dashboard mints per connection, which no field in a tool result can carry. That field is gone, replaced by a dashboard_url pointing at the workspace’s own page in DevGrail: the page that opens a terminal and mints the token itself. The tool descriptions and the MCP guide now say so too, so an agent asked for a terminal sends you there rather than inventing an address. The dashboard terminal is unchanged, and so is what the REST API returns — its terminal_url is only described more honestly, as the base path it has always been.

  • An automation can ask which workspace to work on. A step that runs a script in a workspace had to name that workspace when the automation was written, so doing the same thing to a second workspace meant a second copy of the whole automation. An input can now be a Workspace: the run form offers the workspaces you have, by name, and every step that was pointed at that input gets the one you picked — one automation, whichever workspace you are setting up today. It is checked like everything else a run names, so a workspace deleted since the last run is said so on the form, and the run is refused before it makes anything rather than stopping halfway through.

  • An automation is checked before it runs, not while it runs. An automation stops at its first failing step and does not undo the ones before it, so a workspace refused for its image used to cost you a project and a volume to find out. The run form now checks first and creates nothing: it resolves the inputs you have filled in, then says whether the projects, workspaces, scripts and skills each step names still exist, whether the tools are real ones, whether the script it installs is in the official registry, and whether the image and the CPU and memory sizes are ones this deployment will actually admit. What it finds is listed above the button, by step and field, in the same words the run would have failed with — and when the check finds nothing, it says so, because a warning you only see when something is wrong is one you learn to ignore. Nothing is blocked: a check that could not reach the registry is not proof the script is missing, so Run still runs, after asking once. The check keeps up with you: fixing what it named and saving clears it without a reload, it says how long ago it looked, and Check again re-asks — a workspace deleted in another tab is not something this page is told about. While the definition above it has unsaved edits it says so, because what it checked is the version the server has.

  • A built-in automation can be a starting point. Built-ins ship with DevGrail and cannot be edited, so wanting the OpenCode onboarding with one step changed meant retyping all four by hand. Every automation — built-in or your own — now has a Clone, which makes a copy you own and opens it ready to change. The copy carries the same inputs and the same steps, references between them included, and the original is left exactly as it was.

  • Running an automation caught up with running a script. A run now records the inputs it was given, so the run form keeps them instead of emptying itself the moment the run starts, and fills itself from the last run when you open the page — running the same automation again with one value changed no longer means retyping the rest. Each history entry has a Run again beside it that repeats that run as it was, behind a dialog naming the values it will use, with API keys and secrets shown by name rather than as reference tokens. Credentials are recorded the way script runs record them: as the reference, never the plaintext. And Run on an automation's card opens the page at the run form instead of above the definition, so pressing it no longer means scrolling past the whole automation to find the button you just asked for.

  • A run in progress updates as it happens, and can be stopped. The run history refreshed on a two-second timer, which was most visible in exactly the case that needed it least — a step that is itself a script run, where output is arriving the whole time. Progress now arrives over the same live connection the notification bell uses, and a run that is still going has a stop control: the step in flight is cancelled and nothing after it starts. Stopping undoes nothing, the same as a failure — the run log still names everything that was created — and the step that was interrupted says so, since whatever it had already begun may well have finished. A run left saying "running" because the server restarted under it can finally be closed the same way.

  • The ids a run reports are links. A step's outputs rendered as monospace key=value text, which after a half-finished run meant copying each id into a search box to find out what to clean up. Projects, workspaces, scripts, skills and keys now link to their own pages.

  • An automation step no longer asks you to type things it could offer. The "Create a workspace" step used to take its image as free text, and its CPU and memory caps as strings like 0.5 and 512m: an image the deployment does not admit, or a size above its ceiling, was accepted by the editor and then refused when the run reached Docker — after the project and the volume had been created, which nothing undoes. All three are now chosen from a list, and the sizes on it are the ones this account may actually create, each labelled with what it means, including what leaving the field alone applies. "Download an official script" asks which script rather than for the last segment of a URL copied off another page, with a search box once the registry runs long. And the two yes/no fields — whether the workspace is ephemeral, and whether a download may update copies you already hold — are checkboxes with their explanation beside them. Automations already saved keep working untouched: the words they store still mean what they meant.

  • Choosing skills and scripts for a key an automation mints is a list you tick. The "Create an API key" step used to ask for its skills and its scripts as comma-separated ids typed by hand, with a * for "all of them" buried in the field's description. Both are now the same checkbox list the key editor itself uses: everything you own, built-ins marked as such, and an "all, including ones created later" row above them. A value an earlier step or a run parameter supplies can still stand in the list, and an id whose skill or script has since been deleted is kept and shown rather than quietly dropped.

  • The automation editor got out of the way. Steps now collapse to a line that says what they do, so a six-step automation reads as six lines rather than six stacked forms. A new step picks its action from the catalog laid out under its group headings, with each description visible before the choice is made rather than after, and is then named after what it does — renaming it afterwards rewrites the references later steps make to it instead of silently breaking them, and a move that would carry a step above something it reads is refused. A field naming a project, workspace or script asks where its value comes from, listing an earlier step's output by what produces it and offering a way back to the list of ones that already exist. And what the server would refuse — a duplicate step id, an empty required field, a reference to a parameter nobody declared — is now said beside the step it is about and on the Save button, instead of arriving as a toast once the page has scrolled away.

  • Script libraries are easier to navigate. The scripts page can now search by name, description, or interpreter; filter by any combination of editable, official, and built-in scripts or focus on main scripts and building blocks; and sort by name or recent activity. Bulk export follows those filters and shows how many matching scripts it will export. The view is remembered in the current browser, including its search, filters, and sort order. Built-in and downloaded official scripts cannot be exported, either directly or indirectly through another script's include chain.

  • Notifications now arrive as they are sent. An agent that reports a finished build over send_notification used to sit in the database until the dashboard next asked for it, which was every fifteen seconds. The bell now holds an open connection to the server and is told the moment a notification is written, so the badge and the toast appear at once.

    The old poll has not been removed, only slowed to five minutes, so a browser that cannot hold the connection — an old one, or a proxy that severs it — still keeps up on its own. This is separate from browser push notifications and does not replace them: push is what reaches a phone with the app closed, and it is configured, and can fail, independently.

  • Updating a workspace's image now asks first, and says what it costs. The button on a container's page no longer rebuilds on the click: it opens a confirmation describing what a rebuild keeps and what it starts over.

    It keeps /workspace — that is on a volume and gets remounted — along with the name, SSH port and password, subdomains and restart policy. It starts over the rest of the container: processes are killed rather than asked to stop, so an agent session, a dev server or a script mid-run stops where it is, and the home directory goes with it, which means agent sign-ins, ~/.gitconfig, shell history and anything installed with sudo apt are gone. The old wording mentioned only that /workspace is preserved, which reads as "nothing is lost".

    It is also offered in one place now, and more quietly. The warning banner across the top of the page is gone; a workspace running an older build says so on its Image row, next to the tag it was built from, with the button beside it. The container list used to carry the same one-click rebuild on every drifted workspace, where there is no room to explain any of this — it now marks them and leaves the action to the workspace's own page. A new build of the image is a routine event, not a problem with the workspace.

  • A workspace now says which API keys its agents were given. Open a container and the General tab lists the keys the agents in it were configured to reach the MCP server with, each named alongside the script that set it up. Agents are wired up one at a time — Claude Code, Codex, Gemini CLI and OpenCode each have their own setup script — so a workspace often holds several different keys, and until now the only way to find out which was to go into the container and read an agent's configuration file.

    The list is built from what DevGrail handed the workspace, not from what is in it: setup scripts take the key as a parameter, and a run records that as a reference rather than a value. So the page can name a key without a secret ever being read out of the container, which matters because that is exactly where the key sits in cleartext, in a place the workspace itself controls. Nothing is revealed here — the key's name links to where it is managed, and copying its config stays on the API keys page.

    Two consequences of reading the history: clearing a workspace's run history clears this list, and a key whose setup run failed is still listed, marked, because it did reach the workspace and the setup may be half-applied. A key deleted since is listed too, without its name.

  • Re-running a script now really repeats it. A run in a workspace's history remembers the parameter values it was started with, and two buttons put them back to work: the existing one loads the run into the form to be edited first, and a new Run again repeats it as it was, after showing you what it will use.

    Reuse used to reconstruct a run's parameters from the environment it recorded, which could only ever approximate them. That environment is keyed by variable name and mixes the script's own settings in with what you supplied, so the two could not be told apart afterwards, and it covered the top-level script alone — so anything you filled in for a building block it includes was quietly replaced by that block's default. Secrets came off worst: a secret can be referenced either by itself or by the slot an official script names, and the picker only ever knew the first, so the field came back blank while the form still held the old value. Runs now record the values themselves, per script, across the whole chain, and reuse replays exactly those.

    The credential pickers also stop hiding a value they cannot show. A secret referenced through a slot is named for what it is, and a reference to a key or secret that has since been deleted is flagged in the field instead of leaving it looking empty while the run would still have used it.

    As before, nothing about this stores a credential: what a run remembers is the reference, resolved fresh on each run and redacted from the output. Runs from before this release have no record to replay, so they keep the old behaviour and say so in the confirmation.

  • The getting-started skill now leads with the login that doesn't go stale. Ask an agent what DevGrail can do and it will, before the rest of the tour, offer to point a secret at the credentials file of a workspace you have already signed in — after which every new workspace gets a current login with nothing pasted, and nothing to redo when the token rolls over. It was already possible; it was not what you were told to do first, which is the only moment it is cheap to set up.

  • The coding-agent setup guide now ships with DevGrail. Getting Claude Code, Codex, OpenCode or Gemini CLI running in a workspace — signing in without a browser, wiring up the DevGrail and Context7 MCP servers, where each agent keeps its config, and what the failures actually mean — was expertise you had to find in the official catalog and download before an agent could use it. It is now built in, like the getting-started tour beside it, so an agent on a fresh install can simply load it. Each of the four agents has its own page within the skill, so what an agent acts on is that agent's params and paths rather than a remembered average of all four.

    A step that creates an API key now grants every skill you own by default, instead of only the getting-started one. An agent handed a new key can reach both built-in guides, and anything you have written yourself, without you listing ids on the step — narrow it back to specific skills when a key should see less.

  • An automation can create a workspace without a project. The "Create a workspace" step insisted on one, so an automation that only wanted a workspace had to create a project to put it in, or name an existing one. The Project field is now optional: leave it empty and the workspace is created on its own, the same as one created from the dashboard, ready to be filed into a project whenever there is a reason to. Naming a project still does what it always did, including refusing one that is not yours.

  • The API keys page can be read at a glance. Every key printed its full detail at once — the same paragraph about internal and external connections under each one, and five grant headings of which four usually said "None" — so a handful of keys filled the screen with repetition and none of them stood out. A key is now a single line: its name and prefix, whether it is disabled or flagged for external access, one summary of what it can reach ("12 tools · official registry · all containers (write)"), and when it was last used, or that it never has been. Editing what a key may reach is on that line too, so it no longer costs an expand. Open a key for the config buttons, its switches and the full grant list, where the groups it holds nothing in are simply absent. Granted skills and scripts are named there rather than listed as ids, and the guidance on which config to hand an agent now sits once at the top of the page.

Container images

registry build 31
amd64808 MB
sha256:50957d8a646719d6500b11a832f43f296dec4b6e39d2e5e86950ee34677bea69
Download
arm64677 MB
sha256:f82a7cccd564e3eccfea4cb320bcc318fbf46419b68968873459a3d4d2148dc5
Download
registry build 59
amd6446 MB
sha256:141a3e527b3b95c11fcd91d8bf746767715df54d8b792380de768cee4dea8ca2
Download
arm6445 MB
sha256:7499a8ba053ec55df8e744ac2e26217302cee2db0e7e553d363dd2f860a2b37f
Download

Installer files

docker-compose.yml21 KBsha256:9435825d98455a4d03e0d82c72afac4e64b14faa0d087312147e4b1c3714e8bd
install.sh176 KBsha256:ee5052c1552dd5c34c2d33716aa92f6384ca7464b59ff224785ab986a102f466
traefik-dynamic-http.yml5 KBsha256:e344c8efd13c7d84996e2ebfbc75dcee2d995d8538c8a245c89c0e44fad0089b
traefik-dynamic.yml6 KBsha256:d18fa561b8eb7d53b015284e0246b2d05953bf281b65269c1fae3d6883530db6
uninstall.sh57 KBsha256:abe80c2eaab7a8dd0c23073939f58487a4a0bca5a6aef303e489b2ecb2ceca40

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.39 -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 31 amd64 50957d8a646719d6500b11a832f43f296dec4b6e39d2e5e86950ee34677bea69' 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.39
asset docker-compose.yml 47 9435825d98455a4d03e0d82c72afac4e64b14faa0d087312147e4b1c3714e8bd
asset install.sh 47 ee5052c1552dd5c34c2d33716aa92f6384ca7464b59ff224785ab986a102f466
asset traefik-dynamic-http.yml 46 e344c8efd13c7d84996e2ebfbc75dcee2d995d8538c8a245c89c0e44fad0089b
asset traefik-dynamic.yml 47 d18fa561b8eb7d53b015284e0246b2d05953bf281b65269c1fae3d6883530db6
asset uninstall.sh 47 abe80c2eaab7a8dd0c23073939f58487a4a0bca5a6aef303e489b2ecb2ceca40
image devgrail-container 31 amd64 50957d8a646719d6500b11a832f43f296dec4b6e39d2e5e86950ee34677bea69
image devgrail-container 31 arm64 f82a7cccd564e3eccfea4cb320bcc318fbf46419b68968873459a3d4d2148dc5
image devgrail-server 59 amd64 141a3e527b3b95c11fcd91d8bf746767715df54d8b792380de768cee4dea8ca2
image devgrail-server 59 arm64 7499a8ba053ec55df8e744ac2e26217302cee2db0e7e553d363dd2f860a2b37f