Changelog

A chronological log of Tektona platform updates, covering new features, improvements, deprecations, and notable changes.

2026-09-18

  • tektona template build logs now prints one end of a log instead of all of it. --tail N (-n N) prints only the last N lines, and --head N only the first N. A long build's log no longer scrolls past whole to reach either end. With -f, --tail N prints the last N lines and then follows from there, as docker logs --tail N -f does. Following a running build starts where it is, not at line one. Both flags print the whole log when N is 0, which is the default.

  • A followed build no longer prints a log line twice. When you cancelled a build while tektona template build run or tektona template build logs -f followed it, the last line printed again and the line "the build was cancelled" never showed. The same happened when a step wrote a late line. The CLI now prints every line once, in the order it arrives.

  • A signal you send a process no longer costs it its own exit status. tektona sandbox process signal on a command that traps the signal and exits with a code of its own recorded killed instead of that code. The signal went to the whole group, which held Tektona's own wrapper as well as your command, and the wrapper died before it could collect what your command returned. Your command now runs in a process group of its own, and the signal goes only there. tektona sandbox process stop still records killed, which is what stopping means.

  • Breaking: a sandbox action now answers PUT, not POST. pause, resume, reboot and reset on /v1/sandboxes/{id} moved to PUT. So did the template lifecycle dry run at /settings/template-lifecycle/preview. A POST to one of these paths now answers 405. Tektona's convention is that POST makes a new resource. An action on a sandbox that already exists makes none, and a PUT lets a client retry a timed-out call without a second effect. A create and a fork stay on POST. Move to this release of the CLI and the TypeScript SDK. A hand-written client needs its method changed.

  • The template lifecycle settings page is now one screen. A bar at the top draws the two windows to scale, so you can see how much of a version's life after its last use is spent archived, and it follows what you type. Each rule is one row with a switch, its window and what it takes on the next run. The explanations moved to info icons, and the version list now holds only the versions a rule takes rather than every version it looked at.

  • A build step, a process or a session no longer fails on an image whose entrypoint has already exited. A command inside a sandbox runs in your workload's namespaces, which is what lets systemctl reach systemd there. An image that launches nothing long-lived has none seconds into the boot — alpine's shell reads end-of-input and exits in milliseconds — and the command then failed with nsenter: can't open '/proc/<pid>/ns/pid', reported as the command's own error. A build step on alpine:3.21 failed that way at random while the identical build minutes earlier succeeded. Such a command now runs in the sandbox's own namespaces instead of failing. It sees a different process table from your workload, and a systemctl in it can fail, the same as on an image that ships no nsenter.

  • A build's log now opens at its end, and you scroll up for what came before. The console used to open a build at line one and page towards the end, so on a build of a few thousand lines the reason it failed was several clicks away. It now loads the last lines first and fetches the page above as you scroll up. A running build no longer replays its whole log to the browser before it shows the live tail.

2026-09-17

  • You can now cancel a running template build. Run tektona template build cancel <build-id> (stop and abort do the same thing). Tektona deletes the build sandbox, releases the builder and frees the base image, which takes seconds. The build reads cancelling while that happens and cancelled when it is done. A cancelled build is not a failed build: it publishes no version, it moves no tag, and tektona template build logs <build-id> -f exits zero, so cancelling a build does not fail the job you cancelled it from. Cancelling a build needs the same access as starting one. tektona template build get <build-id> says who cancelled a build, and the API answers the same on every build read. Before this, the only ways out were deleting the template or the build sandbox, and both destroyed the build log.

  • A build now ends on its own after 90 minutes, not after 3 hours. The per-command limit of 45 minutes is gone with it: a command takes what is left of the build's 90 minutes, so one long command is no longer cut short while a build of many short ones ran for hours. A build whose commands legitimately take more than 90 minutes now fails where it used to succeed. Split the work, or cache it in the base image.

2026-09-16

  • A base image stays reusable for as long as builds keep using it. A template build that runs commands converts its base image first, and later builds of the same base reuse that work instead of repeating it. The reuse stopped after 48 hours, whatever happened in between: the retention clock moved only when a sandbox was placed on an image, and no sandbox ever runs on a build's base image — so the base was deleted 48 hours after it was first built, however many builds had reused it since, and the next build paid for the pull and the convert again. On one staging template a single base image had served eighteen builds in under twelve hours and was still on course to be deleted. Tektona now records when a build reads a base image and keeps it for 48 hours from that moment. A base image no build has touched for 48 hours is still removed, so this holds nothing that is no longer wanted.

  • Deleting a template no longer destroys the history of every build it ever ran. A build's record — its status, its error, the timings and the resources it ran on — used to go with the template, and tektona template build get <id> and tektona template build logs <id> then answered not found. The log lines were still in storage the whole time; nothing was left that could reach them. A build you hold the id of now reads after its template is gone, and reports the template as deleted with the name the build recorded. The log reads too, for as long as the log is kept — seven days from when each line was written, unchanged. Such a build is reachable by its id and appears in no list, because a build list reads within a template and there is no longer one to read within. Tektona removes a record whose template has been gone for 90 days. This applies to builds from this release on: the records destroyed before it are gone.

  • tektona sandbox cp, Exec and the desktop now work on a minimal image that ships no nsenter. A session already opened on an image that ships no nsenter, and neither a file transfer nor a desktop command did — so you could log in and still not copy a file into a sandbox. All of them now work there. Such a command sees a different process table from your workload, and a systemctl in it can fail; every image in the Tektona catalog ships nsenter, so nothing changes for them.

  • tektona ssh now works on a minimal image that ships no nsenter. A session now opens on an image that ships no nsenter (util-linux), where every session used to fail with executable file not found in $PATH — the sandbox booted and nothing could log into it. Such a session sees a different process table from your workload, and a systemctl command in it can fail; every image in the Tektona catalog ships nsenter, so nothing changes for them.

  • Breaking: a scripted tektona template rm now needs --yes when the template has build records. Without a terminal on stdin the command stops and deletes nothing. Add --yes to any script or CI job that deletes a template. A template with no build records is unaffected and still deletes in one command. The API's delete also changes: it answers 200 with {"builds": <count>} where it answered 204 with no body. A client that checks for exactly 204 needs updating.

  • Deleting a template now says how many build records go with it, and asks first. tektona template rm used to print Deleted go-dev. and nothing else. A template's build records are the only place a build's status, its error and the resources it ran on are kept, and the build log stays in storage for seven days with nothing left to address it by once the records are gone. The delete now reads This deletes go-dev and its 12 build records. They cannot be recovered. and waits for a y. When it finishes it says what went: Deleted go-dev. 12 build records went with it, and cannot be recovered. A delete a sandbox blocks still goes straight to the refusal that names the sandboxes, because that refusal is what you need and the loss was never going to happen. tektona template get reports the same number, so you can see it first — it is not succeeded plus failed, because a pending or a running build is in neither and the delete takes those too.

  • A second build of a template no longer waits for the first build's commands to finish. Two builds of one template in sequence is normal use, and the second one failed after 15 minutes with another build is already making the image for sha256:…. It was waiting for the base image, and the base image was in storage long before that — the first build only released it when it published, after every command it runs. A build that installs packages runs for minutes, and one whose command hangs runs for the step timeout. The base image is now reusable as soon as its bytes are stored, which is the end of the convert and upload rather than the end of the build. In one measured case that is 111 seconds instead of 45 minutes. The second build then skips the pull and the convert and goes straight to its own commands. A first build that fails after that point no longer discards the base image either, so the next build reuses it.

  • A build whose placement is retried no longer loses what its first attempt recorded. Tektona retries the step that places a build on a builder. Every attempt re-ran the first half of the build — resolving the reference, pulling the layers, writing the image — and each of those steps kept one record, so the retry's timings replaced the first attempt's and a reader could not tell the two apart. Those steps now say which attempt produced them, the same as the build's own commands already did. A build that was not retried reads exactly as before.

  • A terminal opened with tektonactl pty create now sees the same processes and mounts your shell does, and systemctl works in it. It ran outside the sandbox's own namespaces, so systemctl in such a terminal failed — and a second attempt left systemctl failing everywhere else too, including over tektona ssh, until the sandbox restarted. Services themselves kept running throughout; only systemd control was affected. A terminal also starts in the same directory a session starts in.

  • A retried build no longer overwrites what its first attempt recorded. A build whose commands are retried ran every step again, and each step kept one record, so the retry's timings replaced the first attempt's. A step that hung for 45 minutes and was stopped on its timeout read as a step that ran 4 seconds, and the timeout — the failure that consumed the build's time — was the one erased. Every step and every log line now says which attempt produced it. tektona template build logs and tektona template build run print one section per attempt, and a section after the first says · attempt 2 in its header, so a command that appears twice reads as a build that was retried rather than a build that ran the same command twice. The console labels a retried step the same way. Each attempt keeps its own duration, status and exit code. The API sends attempt on every step and every log line, counting from 0. Records written before this release read attempt 0.

  • Two build steps that share a name no longer read as one. A build step is named by the command it ran, so a manifest that runs make twice made two steps with one name — and the CLI and the console folded them into one section, under the first one's status and exit code. A second make that failed after a first that passed reported succeeded. Every step and every log line now carries step_index, and both clients group by it, so each step reports its own outcome. -o json and -o jsonl carry step_index and attempt on a line and on a step, and change in no other way.

  • A build step that failed inside a build that succeeded now says the build continued. Tektona ends every build with a step that hands back the space your commands freed. A failure there does not fail the build: the image works and is only larger than it needs to be. The step still reports the command's real exit code, so the footer read failed · exit 1 in a build that published a version, and there was no way to tell it from the failure that ends a build. The CLI now reads failed, the build continued and is no longer printed in red; the console reads tolerated in amber. The API sends tolerated on the step, and it is absent unless it is true.

  • A container registry you configure as docker.io now supplies its credential. Tektona compares the endpoint you enter against the registry host an image reference carries, and a Docker Hub reference carries index.docker.io. An endpoint of docker.io matched nothing. Every pull from Docker Hub went out with no credential, and Docker Hub limits how many pulls it serves without one. docker.io and index.docker.io now both match, in any capitalisation. You change nothing: a registry you already configured starts working on this release. To confirm it, create a sandbox from a private Docker Hub image, which no anonymous pull can read.

  • Every step of a template build now says what it is doing, and the cleanup step is called trim. Two steps wrote no line at all. The cleanup step, which hands back the space your commands freed, runs fstrim, and fstrim reports only when it finishes — so the log was silent for the whole step, 46 seconds on a 9 GiB image, and then stamped every line at the end. The step that stops the sandbox before its disk is stored said nothing at any point, and its row read 0 lines. Both now print one line when they start. The cleanup step is also renamed: its old name, sysprep, is a Windows tool that does something else. Its type on the API and in -o json is now trim. A build that ran before this release keeps sysprep in its step list, for the seven days those records live.

  • A build that a registry rate-limits now says what raises the limit. The message read the registry rate-limited the pull of elixir:1.17-slim and stopped there. It now adds that a registry limits an anonymous pull more than a pull that carries a credential. A build from a public image can hit this, and the fix is a registry credential for that host on your project. Custom images explains when a project credential covers the pull and when it cannot. A refused pull also stops calling itself anonymous: it now reads the registry refused this build's pull of <image>, because a build carries your credential whenever one applies. Nothing about when a build retries has changed.

  • A file a build step writes to /tmp no longer disappears while the step runs. A few seconds into a sandbox's boot, the guest emptied /tmp, and a command that started earlier lost the files it wrote. The common symptom was a template build that stopped with Unknown error executing apt-key and the command exited 100. apt keeps its signature-check keyring under /tmp, so the repository that failed looked arbitrary. The origin and the transport made no difference. A mktemp with no TMPDIR, and a redirect such as > /tmp/out, lost their files the same way. A sandbox you create and then write to over tektona ssh had the same window. /tmp now survives the boot, so a sandbox keeps the files it writes there. Build the template again from this release on, and the step keeps its files.

  • A build log now says which sandbox a build runs in, and as whom each command ran. The boot step names the managed sandbox it started, the egress network policy it runs under, and the egress proxy profile. Each command's header now says the user and the directory it ran in, for example user app · workdir /srv. A command whose manifest names neither reads from the image. The image declares both, and the sandbox resolves them when the command starts. tektona template build logs and tektona template build run print the same log. The build's step list on the API gains a context object, and a step that runs no command of your manifest has none. -o json and -o jsonl carry the same field and change in no other way.

  • Outbound HTTP and HTTPS from a sandbox no longer fails for a moment just after the sandbox starts or resumes. For a short window after a create or a resume, a new outbound connection from inside the sandbox could be refused. A curl, an apt-get update, a git clone or an npm install in the first seconds could fail to connect. A connection that was already open stayed up. The window closed on its own, so a command that retries got through. Your network policy did not cause this, and no setting controls it.

  • A build from a base image that declares a USER no longer publishes a larger image than it needs to be. Tektona ends every build with a cleanup step. The step hands back the space your commands freed, and it needs root. It ran as the image's USER instead, and failed with fstrim: /: FITRIM ioctl failed: Operation not permitted. The build still reported success. Two builds of the same base measure the difference. The build before the fault handed back 6.3 GiB of free space and stored 1,173,536,491 bytes. The build during it handed back nothing and stored 1,218,951,209 bytes, about 45 MB more. The space a sandbox reserves is the disk size you ask for, so that figure does not change. Every base image that declares a USER was affected, ghcr.io/tektona-ai/sandbox-base and ghcr.io/tektona-ai/desktop-x11 included. Build the template again from this release on, and the new version is the smaller one. A version published before this fix stays as it is: nothing trims an image that is already in storage.

  • A build log now gathers a step's lines under one header. Every line used to carry the name of the step that wrote it. A step's name is the whole command it ran, so one long command pushed every message of that step far to the right. A step is now named once, in a header above its lines. A footer below them reports the status, the exit code of a step that failed, the number of lines and the time it took. Every message starts in the same column, whatever the command is called. tektona template build run and tektona template build logs print the same log. -o json and -o jsonl do not change.

  • The progress line under a build log no longer repeats the command. The line cut the command to fit and added two ellipses: apt-get install -y git …… 49s. It now names the step instead: run… 49s. The step header above the lines still prints the command in full.

  • A build step can now install a package that registers a service. apt-get install -y nginx (or postgresql, redis, docker, openssh-server) failed in a template build: the package unpacked, the unit was enabled, and then its post-install script could not reach systemd to start the service, so the build stopped with dpkg: error processing package. Nothing in your manifest works around it now, and the /usr/sbin/policy-rc.d hook that some builds carried can go. The service starts during the build and comes up on its own in every sandbox created from the published image.

  • A process now sees the same processes and the same mounts a shell does. tektona sandbox process run, tektonactl process start, an autostart process and a build step all ran outside the namespaces your tektona ssh session runs in, so systemctl, journalctl and ps answered differently depending on which door the command came through. They now run in the same place. Two consequences worth knowing: a process sees the sandbox's own process table, so a PID a process reads is the PID a shell reads; and a process no longer outlives the sandbox's main workload — if that workload exits, the processes stop with it, the way open SSH sessions already did.

  • A second build from the same base image no longer stalls. After a build that ran commands succeeded, the next build from that base image waited 15 minutes and then failed with another build is already making the image for sha256:…, naming a build that had already finished. The base image is now reusable as soon as the first build succeeds, so the second build skips the pull and the convert. A build that ends without releasing the base image — one that is cancelled or killed, or one whose template you deleted — no longer blocks the next build either: Tektona reclaims the base image within two minutes.

  • A build that waits for another build's image now says what it waits for. A build waiting for the image another build is making reports pending, which reads as "queued, nothing started". Such a build now carries a sentence beside that status. It says what the build waits for, and how long it waits before it fails. tektona template build get prints it beside the status, and the console shows it on the build page. The API sends it as wait_reason. A build that waits for a builder is unchanged, because pending already means that.

  • Breaking: a process with no user now runs as the image's USER, not as root. This covers tektona sandbox process run, a template build's commands, and any process started through the API. tektona ssh, file transfers and the desktop already ran as that user, so a process and a session now write files with the same owner — a process used to leave root-owned files in the home directory your next SSH session starts in. Most images, Ubuntu and Alpine included, declare no USER, so nothing changes for them. On an image that declares one, a command that needs root now needs --user root (or user: root on a build step). A process with no --cwd also starts where a session starts: the image's WORKDIR, then that user's home. A process now gets every group its user belongs to, so a user in the docker group reaches the docker socket from a process as well as from a shell. tektonactl process is unchanged — inside the sandbox a process still runs as whoever ran the command.

  • An autostart process you created before this release may change user at its next restart. An autostart definition that names no user means "I never said", and that now resolves to the image's USER — so on an image that declares one, a process that has been relaunching as root writes as that user after the next reboot. If it needs root, set it explicitly: tektona sandbox process run <id> --name <name> --autostart --user root -- <command>.

  • tektona template build run -o json now prints JSON and nothing else. On the build that creates the template, the command printed Created <name>. ahead of the first frame. The output was then not a JSON document, so a script that read the build id out of it failed on the first character. A later build of the same template was never affected, because it creates nothing. -o jsonl behaved the same way and is fixed too. Without -o json the line is unchanged.

  • tektona/desktop now starts from the 0.6.0 desktop image. The template used ghcr.io/tektona-ai/desktop-x11:0.5.0. It now uses 0.6.0, and :default moves to the version built from it. A sandbox records a version, not a tag, so a sandbox you already created keeps the image it started from. To pin the older image, use the version id the sandbox reports. tektona/sandbox-base is unchanged.

  • tektona template build run org/base-ubuntu --image ubuntu:24.04 now works. The command sent the whole reference as the template's name, and a name holds neither a slash nor a colon, so it failed with metadata.name: expected string to match pattern and never named the reference. This hit the first build of a template, the one that creates it, for org/<name>, project/<name> and any reference carrying a tag, go-dev:stable included. A later build of the same template always worked, and so did -f <manifest>. The scope still selects the template, and the tag still moves onto the version the build publishes. tektona template init now refuses a scoped name too, rather than write a file that the next command cannot read.

2026-09-15

  • A template build can now run commands on the base image, so "Ubuntu plus a few packages" needs no image of your own. Pass --run once per command, or list them under spec.build.steps in a manifest, and they run in the order you wrote them. --build-env, --build-user and --build-workdir say what they run with, and --build-egress-network-policy and --build-egress-proxy-profile say what network they run on. The result is baked into the version, so every sandbox created from it starts with your packages already installed. The build stops at the first command that fails and publishes no version, and tektona template build logs <build-id> shows each command's output. A build that names no commands is unchanged.

  • A template's page and the template list now say how much storage a template uses. The figure was already on the API and in tektona template get. The console showed it nowhere. An image two versions share counts once. The figure says what the template holds, not what deleting it frees: two templates that pull the same base image both report it. A dash means Tektona records no size for these images.

  • tektona template build run now takes -d for --detach. tektona sandbox process run already uses -d for the same thing. tektona template create takes it too.

  • fstrim in a sandbox now frees disk space. The command always reported success, and released nothing: the sandbox disk dropped the request. A sandbox's disk grew for ever, and a paused sandbox carried every byte it ever wrote. Run fstrim -v / after you delete large files, and the space goes back to the node. A first release of this fix reached only part of the disk and still freed nothing, so the space comes back from this release on. A sandbox that is already running keeps the old behaviour until you restart it.

  • API responses no longer carry a $schema field. Every response body had one, and the URL in it pointed at a schema document that does not exist. The same endpoint answers under more than one base path, and the published API document renames schemas when it joins the services together, so the link never resolved. The OpenAPI document is the contract. Clients that read $schema must stop; the field is gone from the spec and from the generated SDKs.

  • VS Code and Zed now use the sandbox command. Use tektona sandbox vscode and tektona sandbox zed.

2026-09-14

  • An archived tektona/* template leaves your template list. A retired Tektona template sat in every organization's and every project's list, badged Archived, and nobody could activate it, delete it or create from it. Your own archived templates stay listed, because you can activate them again. Every archived template is still readable at its own address.

  • Breaking: tektona/ubuntu is now tektona/sandbox-base, and the old name no longer resolves. There is no alias: a create, a template read or a --template filter that names tektona/ubuntu is refused with a not-found error. The new name is the image the template is built from, ghcr.io/tektona-ai/sandbox-base. Update your scripts, your SDK calls and your saved references to tektona/sandbox-base. The template itself is the same row renamed, so every version id and every tag it carries still resolves, and :default still points at the version Tektona recommends. Sandboxes you already created are unaffected: a sandbox records a version, not a name, so it keeps running, pausing, resuming and forking. tektona/desktop is unchanged.

  • The Helm charts now refuse five values that used to install a broken cluster. domains.sandboxIngress, domains.agentlinkTrustDomain and domains.sshHost are required, in both charts where each one applies: empty rendered an empty host name into the API, the relay and the access gateway, and an empty certificate SAN. auth.jwksUrl and auth.userinfoUrl are required too: empty derived a Zitadel path from the issuer, which is wrong for every other provider, and every token check then failed against a chart that installed cleanly. Read both URLs from <issuer>/.well-known/openid-configuration.

  • Both Helm charts now refuse a route or a metrics object the cluster cannot apply. ingress.kind: HTTPRoute renders a Gateway API route, and metrics.podMonitor.create renders a Prometheus operator PodMonitor. Neither set of definitions comes with the charts, and a cluster without them failed the apply with no matches for kind, which named no value. The render now stops and names the value and the missing API. ingress.kind: none and metrics.podMonitor.create: false, the defaults, are unaffected.

  • The runner chart now refuses an egress gateway with no certificate authority, and sends the inspection sidecar the NATS address of your cluster. The sidecar reads that authority at startup and exits without it, and the old default created none, so the egress gateway restarted for ever on a clean install. Set egress.certificate.create to issue it with cert-manager, or name your own secret in egress.injectCaSecret; the render refuses a release with neither. The sidecar also carried the staging NATS address in its image, so the inspected egress path only worked on a cluster whose NATS is named nats-leaf.tektona-system.svc. It now takes the address from messaging.url, and needs no value of its own.

  • The runner chart now defaults to one NATS server, and says so when the two JetStream domains disagree. messaging.leafDomain changes from leaf to hub. The old default suited a cluster with a leaf server on every node, and on a single-server cluster the runner exited because the leaf domain never answered. Set messaging.leafDomain and messaging.hubUrl together for a leaf topology; the chart refuses a leaf domain that differs from messaging.hubDomain while messaging.hubUrl is empty. The control-plane chart refuses nats.config.merge.jetstream.domain that differs from messaging.jetStreamDomain.

  • Archiving a template no longer freezes its storage. The lifecycle rules used to skip every version under an archived template, so a template you archived instead of deleting held every byte for as long as it sat there. The rules now restart each version's window from the moment you archived the template, and reclaim from there. Activating the template clears that moment.

  • The lifecycle delete rule never takes the 3 newest versions of a template. So a template you archive and come back to a year later still has versions to activate, rather than an empty shelf. The archive rule is unchanged: archiving is reversible and frees nothing.

  • A version now says whether a sandbox create through it works, and which level refuses. A version under an archived template still reads state: active, because archiving a template writes nothing on a version — so it looked creatable and the create failed later. tektona template version get, tektona template tag get and the listings now name the effective answer beside the state, and the console shows it on the Versions and Tags tabs. The new creatable and create_refused_by fields carry it on the API.

  • New: tektona template version prune <template-ref> removes every unused version of a template in one command. A version is unused when no tag points at it and no sandbox records it. It lists what it removes and asks first; --yes skips the question. It never removes a version a tag points at, and never one a sandbox records — a paused sandbox counts, one whose teardown has not finished counts, and so does every fork. The console offers the same action on the Versions tab.

  • tektona template get says what an archived template still holds in storage. Archiving refuses new sandboxes and frees nothing on its own, and the screen a reader opens after archiving now says so.

  • A project's Templates tab now reports a failed template list. The page read two lists, the project's and the organization's, and reported only the first. A failure of the second left every organization template missing, with nothing on screen to say so. The page now reads one list, which carries the project's templates, the organization's and the Tektona catalogue.

2026-09-13

  • A sandbox now names the template it started from, not only the version id. tektona sandbox get prints a Template block with the reference, the tag and the resolved version, and tektona sandbox ls --wide adds a TEMPLATE column. The template object on POST /v1/sandboxes, GET /v1/sandboxes/{id} and the sandbox listing gains reference, name and scope beside tag and version_id. A version id alone named nothing you could look up, because no route reads a version without its template. The version is still the one the create resolved, so a tag that moves later does not change it. A sandbox whose template was deleted keeps its version id and tag and reports no reference.

  • A build page in the console now lists the build's steps, each over its own log. Until now the page was one flat log, and finding what a step did meant reading the whole build. Every step is a row: its position, its type, its status and how long it took. A step that is running counts up, and its lines arrive live. Click a step to fold its output away.

  • tektona sandbox get and tektona sandbox ls now report the template a sandbox started from. The create answered with the template, and reading the same sandbox back answered with none, so -o json gave "template": null for a sandbox that plainly had one. The record always held it; the two read paths dropped it on the way out.

  • A sandbox whose runner node is gone now finishes its delete. The delete waited for the node to confirm the teardown, so a node that never came back left the sandbox in deleting for ever — and that sandbox blocked its template's delete, which has no override. The delete now completes on its own once nothing answers the node and the node has answered nothing for 15 minutes. A node that is only slow still gets the wait.

2026-09-12

  • Breaking: tektona sandbox ls --all is now --include-deleted, and the -A shorthand is gone. The same rename applies to tektona admin sandbox ls. The flag never meant "all sandboxes" — it adds the ones whose delete has started or finished — and next to --all-projects it read as the same axis when the two are different: --include-deleted widens which states are listed, --all-projects and --scope widen whose and where. There is no alias, so a script passing --all or -A to either listing must be updated. tektona sandbox rm --all is unchanged: there it really does mean all of them.

  • A template delete is now refused while a sandbox uses it. tektona template rm stops when a sandbox records any version of the template, and names up to 5 of them with a count of the rest and the command that lists all of them. There is no override: delete those sandboxes first, or archive the template to refuse new ones and leave the existing ones alone. A paused sandbox counts, one whose teardown has not finished counts, and so does every fork — a fork inherits the version its parent recorded. A template nothing uses is still deleted by one command, with no prompt. tektona template get and tektona template ls now report the same count, so you see it before you delete.

2026-09-11

  • Breaking: a sandbox now starts from a template, and never from an image. tektona sandbox create --image <ref> is gone, and so is the image field on POST /v1/sandboxes. A create that still sends one is refused with 422 and told to create a template first. Name a template instead: tektona sandbox create tektona/ubuntu, or build your own image into a template with tektona template create my-app --image <ref> and create from that. --image is unchanged on tektona template create, tektona template build run and tektona template init. Sandboxes you created from an image before today keep running, pausing, resuming and forking.

  • One template can now carry at most 500 tags. You can still move or remove an existing tag at this limit. A request for a new tag returns 422 and names the template. A build that requests a new tag fails and publishes no version.

  • tektona template init takes --image, and the file it writes is a third of the length. tektona template init go-dev --image ubuntu:24.04 puts the image straight into spec.build.image, so the file is ready to build without an edit. The file is 32 lines rather than 85: it is a file to start from, not the documentation, and the schema line at the top is what tells your editor the keys, their types and their bounds.

  • tektona template version get and tektona template tag get read one version and one tag. Both print the same version block, so a version reads the same way whichever command reached it: its state, tags, base image and digest, size, build, the sandbox size, user, workdir and environment a sandbox made from it gets, and the lifecycle rule coming for it. tag get prints the tag above that block, and says when an archived version stops a create through the tag. The tag listing's STATE column becomes VERSION STATE, beside POINTS AT VERSION, because a tag has no state of its own — the state is always the version's. The base image moves to the end of that table.

  • A tag write now names the tag, not a compound reference. Deleting a tag answered Deleted hermes:1231., which reads as the template going with it. It now says Deleted tag 1231 of hermes. The version it pointed at stays., matching what a version delete already said. Setting a tag names it the same way: Tag 1231 of hermes points at 01M25RVH….

  • rm is now the name of every delete command, not an alias on two of them. tektona template rm and tektona sandbox rm are the commands; delete and d still work, and so does destroy on a sandbox. Ten commands delete something, and eight already led with rm. The two that did not printed their usage as delete when you typed rm, which read as a different command from the rm beside it — tektona template rm next to tektona template version rm and tektona template tag rm.

  • tektona template ls now says what each template holds. Three columns join the listing: VERSIONS, TAGS and STORAGE. Until now the table said only the name, the scope and the status, so finding out how much a template held meant reading each one with tektona template get. VERSIONS counts the archived versions as well as the active ones, because an archived version still holds storage. STORAGE counts an image two of the template's versions share once, and it says what the template holds rather than what deleting it frees. It is blank for a template whose images all predate the size the platform records now.

  • Breaking: a template tag no longer sends version_id. A tag carries the version it points at, so version_id only repeated version.id. A script that reads t.version_id must read t.version.id now. The change covers the tag list, the single tag read and the tag move. The tag move still takes version_id in its request body, because a write names the version by id. The console and the generated clients already read the new shape.

  • A forked sandbox now knows its own name. A fork starts the child from the parent's memory and a copy of its disk, so the child answered to the parent's name. hostname, /etc/hostname, /etc/hosts and $TEKTONA_SANDBOX_ID all reported the sandbox it was forked from. They report the child now. Shells and commands started after the fork see the new name. A program that was already running keeps the name it read at startup. Entries you added to /etc/hosts before the fork stay. A sandbox whose hostname you set yourself keeps the name you chose. The child also takes a machine-id of its own, which the next boot of that sandbox uses.

  • You can now list the sandboxes that hold one template, or one template version. tektona sandbox ls --template go-dev shows the sandboxes built from a template, whichever version each holds, and --template-version <id> narrows it to one version. tektona sandbox ls covers the sandboxes you can see; tektona admin sandbox ls takes the same two flags and covers every owner's. The API takes them as template and template_version on the sandbox list. A version delete is refused while a sandbox still records the version, and the refusal names at most 20 ids. Now you can list the rest. Add --all to include the sandboxes whose delete has started or finished.

2026-09-10

  • A template built from an image alone now works straight away. tektona template create go-dev --image ubuntu:24.04 moves the default tag onto the version it builds, so tektona sandbox create go-dev starts from it. A bare reference resolves the default tag and nothing else, so a first version that carried no tag left a template no sandbox could start. Name --tag to use another one. A build on a template that already has versions still moves no tag unless you ask, which is what lets you build a version and test it before promoting it. tektona template build run go-dev --image <image> also creates the template when it does not exist yet, the way -f already did, so the same command works whether or not you have built that template before. A build still moves no tag unless you name one, creating the template included.

  • A tag now moves onto a version without a build. tektona template tag set go-dev stable <version-id> points a tag at any version of the template, and creates the tag when it does not exist. Until now the only way to move a tag was to run a build with --tag, so promoting a version you had already built and tested meant building it again. The version may be an older one, which is how you roll back. tektona template tag rm go-dev old deletes a tag and leaves its version in place, still reachable by its id. The listing moves from tektona template tags <name> to tektona template tag ls <name>, and versions move the same way: tektona template versions <name> is now tektona template version ls <name>, with archive and activate as commands under it rather than a --template-version flag on the template's own verbs.

  • Breaking: tektonactl get is now tektonactl info. The command prints the same sandbox id, uptime and image. The names get and show no longer work, so change any script or agent prompt that uses them. tektonactl info --output json prints the same fields as JSON, with the keys sandbox_id, uptime_ms and image_id. tektonactl info id prints the id alone, with no trailing newline, for a script that puts the id straight into a file or a string. tektonactl info sandbox-id does the same.

  • tektonactl info now reports a forked sandbox's own id. A fork starts the child from the parent's memory, and the command read the id that memory held. It printed the parent's id for the whole life of the child. It prints the child's own id now.

2026-09-09

  • Breaking: a template build sends its template and its project as objects. The build response replaces the flat template_id, template_name and project_name with one template object, holding id, name and display_name, and one project object, holding name and display_name. This is the same shape a project already sends its organization under org. A script that reads b.template_name must read b.template.name, one that reads b.template_id must read b.template.id, and one that reads b.project_name must read b.project.name. project is absent on a build of an organization's own template, exactly as project_name was, and template.display_name is absent when the template carries no label. The change covers GET /v1/template-builds/{buildId}, both build lists and the build submit. The console and the generated clients already read the new shape.

  • A project template's reference is now the bare name. The API sent project/go-dev and now sends go-dev. The prefix carried nothing, because a reference with no prefix already means the project scope. An organization template keeps org/<name> and a Tektona one keeps tektona/<name>, where the prefix is the whole difference between them. Both forms still resolve, so project/go-dev in a script or a saved command still starts the same sandbox. A script that compares a template's reference to project/<name> exactly must compare it to the bare name now.

2026-09-08

  • Forking a sandbox right after you pause it no longer fails. A pause returns as soon as the sandbox stops, and Tektona then copies its disk (and, for a hibernate, its memory) to object storage in the background. A fork issued in that window used to be refused after 45 seconds with "pause artifact is not durable yet". The copy takes as long as the sandbox is big, so the bigger the sandbox the more often it happened. A fork now branches the paused disk as soon as the sandbox has stopped, whether or not the copy has finished.

  • The TypeScript SDK now covers the template API. @tektona/sdk reaches templates, versions, tags, builds and lifecycle settings through its generated namespace, and sandbox.create takes a template where it needed an image. It also adds the sandbox egress proxy profile calls and the desktop status call. Its types read the snake_case keys the API sends now.

  • Breaking: the project list sends the organization as an object. GET /v1/projects gave each project a flat org string and an org_display_name beside it. It now sends one org object with id, name and display_name, the same organization reference a single project already carries under owner. The key org changed from a string to an object, so a script that reads p.org as a name must read p.org.name, and one that reads p.org_display_name must read p.org.display_name. A single project's owner.org gained display_name and is otherwise unchanged. The console, the CLI and the generated clients already read the new shape.

  • Breaking: every key the API sends is now snake_case. The template, the build and the resize responses were the last that were not. displayName is display_name, createdAt is created_at, updatedAt is updated_at, baseImage is base_image, imageBytes is image_bytes, archivedAt is archived_at, archivedBy is archived_by, pendingRule is pending_rule, pendingRuleAt is pending_rule_at, buildId is build_id, storedBytes is stored_bytes, defaultResources is default_resources, templateId is template_id, templateName is template_name, projectName is project_name, imageRef is image_ref, resolvedDigest is resolved_digest, tagsOnSuccess is tags_on_success, versionId is version_id, startedAt is started_at, finishedAt is finished_at, stepName is step_name, exitCode is exit_code, and appliesImmediately is applies_immediately. The tag write takes version_id in its body. Path parameters keep the names they had. The console, the CLI and the generated clients already read the new keys. Update any script that reads these fields by name. A template manifest file keeps its own camelCase keys, because it is a file you write and not a response the API sends.

  • A template version now carries its tags and its build. List a template's versions, or read one, and each carries tags with every name that resolves to it, and build_id with the build that published it. Reading a version no longer means listing the template's tags and builds beside it and matching them up by id. tags is empty when no tag points at the version, which is the version an automatic rule can take. build_id is absent when no build produced the version. A rebuild that resolved to the same image and the same sandbox defaults published no new version, so the id names the build that created it. The console's Versions tab reads one list instead of three, and a version's own page reaches its build however old that build is, rather than only while it stays in the last 50.

  • Breaking: an empty list of allowed egress policies now allows no policy. An organization's allowed_policies takes three values. null allows every policy, a list allows exactly the policies in it, and leaving the field out of the request keeps the current setting. An empty list is a list of no policies, so no sandbox can start in that organization until you change it. It used to mean the same as null. Sending null did nothing at all, so there was no way to lift a restriction through the API. The console's "Allow all policies" now really lifts it. An organization that already holds an empty list is moved to null, so nothing changes for it.

2026-09-07

  • A template now says how much it holds. List templates, or read one, and each carries stats: its versions split into active and archived, how many tags it has, how many builds succeeded and how many failed, and the bytes object storage keeps for it. A build that is still pending or running is in neither build count. The storage figure counts an image shared between two versions once, and it says what the template holds rather than what deleting it frees, because two templates that pull the same base image share one copy. It reads 0 for a template whose images all predate the size Tektona records now, so it can be short but is never inflated.

  • Breaking: a template version reports its base image as an object. baseImageRef is replaced by baseImage, with ref for the image the build asked for and digest for what that resolved to. The digest names the base the image started from, so it identifies the running bytes only for a version that ran no build commands. Either half can be missing, and the object is absent for a version built before Tektona recorded them. The console shows the digest under the reference in the Versions and Tags tables, and in full on a version's own page.

  • The tag dialog now suggests recent versions. Click into "Point to version" and the most recent versions drop down, each with its full id, its base image and its state. Pick one to fill the field. The field still takes any version id you type, because a template can hold more versions than the list shows.

  • A template tag now carries the version it points at. List a template's tags, or read one, and every tag arrives with the whole version under version: its state, its base image and when it was built. Reading a tag no longer means listing the versions as well and matching them up by id. The tag write answers the same shape. The console's Tags tab reads one list instead of two.

  • Breaking: a template description is capped at 80 characters. It was 1024, which is a paragraph, and every surface renders a description on one line. Create and update refuse a longer one with a 422 that names the field. A description saved earlier that is longer still reads back as it was, and editing that template needs it shortened first — the same as the line-break rule. The console's description box is a single-line input now rather than a three-row text area, because a line break was never accepted.

2026-09-04

  • A template's Versions tab now says what the rules will do to each version. A Lifecycle column reads Archives in 12d, Deletes on the next sweep, or Kept by a tag, and a version's own page says the same with a line on what to do about it. You no longer have to open a settings page to find out that a version is about to go. No row is ever blank: a version no rule will take reads as Not scheduled, and its page says plainly that a tag is not what is keeping it and that this can change on its own.

  • You can tag a template version from the console. Open Edit tags from a version row — beside the verdict that just told you the version is going — from a tag row, or from the version's own page. Add a tag, move one here from another version, or take one off. A tag is the only exemption from the archive and delete rules, so the dialog says so. Tagging an archived version is allowed: it warns that a create through that tag fails until the version is active again.

  • Settings now has a Template Lifecycle page, for an organization and for a project. It holds the four values that decide when a version is archived and when it is permanently deleted. Each value says whether it is set here or inherited, and from which scope, and one click resets it back to inheritance. The two rules read as one chain: the page states how many days pass between a version's last use and its permanent deletion.

  • The page runs a dry run as you type, before you save anything. It reports how many versions each rule takes on its next run and how that differs from your saved values, with a sample of the versions and the reason for each. Archiving frees no storage, so the archive rule shows zero and says why. The delete figure is what the storage collector eventually reclaims on a later pass, not what the rule frees. When a scope holds more versions than one dry run reads, every number is shown as a floor.

  • A template version now tells you when a rule will take it. Read a version, or list a template's versions, and each one carries pendingRule and pendingRuleAt: which rule is coming for it, and the date. An active version carries the date it is archived. A version a rule archived carries the date it is permanently deleted. Both fields are absent when no rule will take the version — because a tag exempts it, because a sandbox holds it, because its template is archived, or because you turned the rule off. Tag the version to keep it.

2026-09-03

  • Tektona now archives and deletes unused template versions for you. Two rules run for every organization and project, and both are on. A version that no sandbox has used for 30 days is archived. A version a rule archived is permanently deleted 7 days later. That deletion cannot be undone. Tag a version to exempt it from both rules. A version that a sandbox still holds is never counted as unused, and its clock starts again when the last sandbox goes. A version you archive yourself is never deleted by a rule. Versions under an archived template are left alone, and so is the tektona/* catalogue. Neither rule reaches back over history: each window starts when you turn that rule on.

  • You can change when each rule runs, for a project or for an organization. GET and PUT /settings/template-lifecycle at either scope. There are four values: each rule on or off, how many days a version stays unused before it is archived (1 to 60), and how many days it stays archived before it is deleted (1 to 30). A project's own value applies. A project that sets none takes its organization's, and an organization that sets none takes the platform default. The read reports the value in force and the scope it came from. A PUT replaces the whole scope, so a field you leave out goes back to inheriting. Reading needs read access; writing needs the admin role.

  • You can see what the template lifecycle rules would take before you save a setting. POST your proposed values to /settings/template-lifecycle/preview, for a project or an organization, and read back how many versions each rule takes on its next run, how that differs from your saved values, and a sample of the versions with the reason for each — including the ones a tag keeps. Nothing is written. Archiving frees no storage, so the archive rule reports zero bytes; the delete rule's figure is what storage the collector eventually reclaims, and an image two versions share counts once.

  • You can now tag a template version yourself. PUT a tag onto any version of an organization or project template, move it to another version, or delete it. Until now a tag appeared only as a side effect of a build, and could only ever move to a newer version — so there was no way to name an older version or to take a tag off. A tag may point at an archived version; creating a sandbox through it fails until the version is active again.

  • Deleting a template now works. It used to be refused for any template that had ever built a version, which was every template in practice. Deleting one removes the template, its versions and their tags together, including versions that running or paused sandboxes started from — those sandboxes keep running on the image they already hold, but the record of which version they came from goes with the template. Deleting a single version still refuses while a sandbox references it. It cannot be undone. Archiving a template hides it from the create menu reversibly instead, and leaves every version exactly as it was.

  • Deleting a version now deletes its tags with it. A tag pointing at the version used to block the delete until you moved or removed it by hand. The delete takes them now, in one step. A reference like go-dev:stable then stops resolving, and a tag write points it at another version. A sandbox that records the version still blocks the delete.

  • A sandbox releases its template version only when its teardown finishes. Deleting a sandbox used to free the version and its stored image as soon as you asked. Both are held now until the sandbox is really gone, so nothing reclaims the image a shutting-down machine still reads. A stalled teardown keeps the version undeletable until it completes.

  • Archiving a version no longer requires moving its tags first. The tag stays where it is and keeps naming the version. Creating a sandbox through that tag fails while the version is archived, and activating the version makes the tag work again.

  • An archived version keeps its stored image. Archiving takes a version out of the create menu and nothing else, so its bytes stay and can be brought back by activating it. Deleting a version or a template does not free the storage there and then. It only lets the image go. The collector then removes an image that no version and no sandbox still needs, about two days after its last use.

2026-09-02

  • A running build counts its time up as it runs. The duration on a build's page and in every build list ticks once a second while the build is going, instead of waiting for the next poll. A build that has not started yet shows no duration at all: its wait in the queue is not build time.

  • You can delete one version of a template. The row menu on the Versions tab and the version's own page both offer it. A sandbox that records the version blocks the delete, and so does a tag that still points at it — the refusal names what is in the way. Deleting a version cannot be undone; archiving still hides one from the create menu reversibly.

  • A template name can now be 80 characters, up from 63. The grammar is unchanged: lowercase letters, digits and hyphens, starting with a letter. Every route that names a template accepts the longer name, and so does the manifest's metadata.name. Existing names keep working.

  • Creating and updating a secret now opens a modal. The form is two or three fields, so it opens in the middle of the screen instead of sliding in from the side. A project secret's visibility is now two options, Shared and Personal, each with its own line of explanation.

  • The icon rail now takes you back where you left off. Sandboxes opens on the organization or project you last had open, so leaving a project to look at its sandboxes shows that project's. Orgs & projects reopens the page you were last reading there, tab and all. Your browser remembers both, so the two surfaces keep their own place.

  • Switching organization or project now keeps you on the same page. Pick a scope from the sidebar switcher, the breadcrumb or the mobile tree, and you land on the section you were reading — Templates, Secrets, Members, Egress Network Policies or the settings pages — in the scope you picked. A section the new scope does not have, such as a project's Repositories, opens its dashboard instead. A detail page opens the list it belongs to: one scope's template is not another's.

  • A template's page is now four tabs, and a version has a page of its own. Overview counts the template's tags, builds and versions and lists the newest three of each; Tags, Builds and Versions hold the full tables. A version's page carries the sandbox defaults a create takes from it, the tags that resolve to it, and every reference that reaches it. Open one from a version row, from the tag that points at it, or by pasting its id. A tektona/* template has no Builds tab: Tektona builds the catalogue, so those builds are not the organization's to read.

  • A project's template list now shows the organization's templates too. It returns three groups, in this order: the project's own templates, then the organization's, then the Tektona catalogue. Each group is in name order. You could already create a sandbox from an organization template; now you can find one without being told its name. A project and its organization may both hold a template called go-dev — the list returns both, and scope tells them apart. An organization list is unchanged, and still shows no project's templates.

  • You can search every template list. Add q to a template, version, tag or build list. A template matches on the start of its name, or a word in its display name or description; a version on the start of its id, or a word in the base image reference; a tag on the start of the tag or of the version id it points at; a build on the start of its id, its template's name, or the tag it asked for. Send q with every page of a filtered list — the cursor carries the position, not the filter.

  • Breaking: both template lists are paginated. They return the same pagination object every other list returns, and take cursor and limit. A list serves 50 templates by default and 200 at most, so a client that read the whole list in one response now reads pagination.next_cursor and asks again.

  • tektona template init names the file after the template. tektona template init go-dev writes ./go-dev.template.tektona.yaml rather than one fixed name, so a repository holds one file per template and a second init no longer collides with the first. Name a path to write somewhere else.

  • A build log line now carries the name of its step, not a number. tektona template build logs labels each line with the step that wrote it, such as [pull]. A build that succeeds also prints the digest it resolved, which is what makes the version reproducible, and names every tag it moved rather than one.

2026-09-01

  • Breaking: a build response is smaller, and it now says which digest it built. requestedTag is now tagsOnSuccess, a list that is [] when the build moves no tag, and the new resolvedDigest names the exact image the reference resolved to. A step no longer carries index or params, and a log line no longer carries stepIndex, stepType or cursor — the stream marks each step with a frame of its own, and the cursor rides the event id. The log route takes cursor in place of after, returns the same pagination object every other list returns, and no longer narrows to one step.

  • An image pulled with one of your registry credentials now stays inside the project that pulled it. It is stored under that registry, at an address no other project can name, and the project is recorded as its owner. Another organization, and another project of your own organization, no longer reach it. They keep their own copy of the same reference, so nobody is blocked and nobody waits.

  • A public image is unchanged. It carries no owner, and every project that names it shares one copy.

  • tektona template now reads and writes the current template shape. A manifest's spec holds two blocks: build, what the version is built from, and sandbox, what a sandbox made from it gets. spec.defaultResources and spec.runtime are gone. One rule replaces the old split: metadata costs nothing, and everything under spec mints a version.

  • tektona template update now writes the display name and the description only. The --default-* flags moved to create and build, and --runtime-env, --runtime-user and --runtime-workdir are now --sandbox-env, --sandbox-user and --sandbox-workdir. A resize costs a build, which names the same image again.

  • tektona template build run with no --tag moves no tag, and says so. It names the version id and the sandbox create --template-version that reaches it, so a version you build to test is not lost.

  • tektona template info now shows the disk each version needs. A new SIZE column carries the unpacked image, rounded up to the GiB a --disk has to clear. It also gained --state, --limit and a three-state --tagged: left out it lists every version, --tagged lists the versions a tag points at, and --tagged=false lists the rest — which is how you find the version an untagged build published.

  • tektona template ls no longer shows version, tag and image columns. Those read one template at a time now, so the columns cost a request per row. Run tektona template get <template-ref> for them. The command needs an organization in your CLI context.

2026-08-31

  • You can read one Tektona template again. GET /v1/system-templates/{name} returns it, and /versions, /versions/{versionId}, /tags and /tags/{tag} sit under it — the same four reads, filters and pages every other template answers. A tektona/* template now reads exactly like one of your own. It stays read-only, and it stays out of your own names: tektona/ubuntu is not reachable at /v1/orgs/{org}/templates/ubuntu.

  • The console's Tektona templates open again. A catalogue row is clickable and has a detail page with its versions and its tags. The page is read-only whatever your role in the organization: no organization or project role grants anything over the Tektona catalogue, so it offers no edit, archive, activate or delete.

  • You can now delete one version of a template. DELETE /v1/orgs/{org}/templates/{name}/versions/{versionId}, and the project twin. A sandbox that records that version blocks the delete, including a paused or stopped sandbox. The refusal names every blocking sandbox by id. A version that a tag still points at also blocks the delete. The shared template image survives until no sandbox uses it.

2026-08-30

  • Breaking: GET /v1/system-templates is gone. Both template lists now return the tektona/* templates as well, after the templates the organization or the project owns. Each group is in name order, so you read your own names first and find the Tektona catalogue below them.

  • Breaking: archive and activate are now PUT, not POST. This covers all four: archive and activate a template, and archive and activate one of its versions. The paths are unchanged. Archiving twice leaves the template archived, so the verb now says so.

  • Breaking: a template no longer carries versions and tags in its response. Read them from GET .../templates/{name}/versions and .../tags, which page with a cursor and narrow by state and tagged. A template gains a version per build, so the embedded lists grew without bound and could not be filtered.

  • The console's Templates list now shows the Tektona templates in place of the System tab. They come after your own. The list no longer has a Newest version column: a version reads from the template's own route, one template at a time, so the column cost a request per row. Open a template to see its versions and tags.

  • What a sandbox gets now belongs to a template version, not to the template. A version records the CPU, memory, disk, user, workdir and environment a sandbox created from it starts with. A user has to exist in the image, so pinning a version now pins that too. A build carries these values in a new sandbox block beside build, and template update writes the display name and the description only.

  • A build that omits the sandbox block keeps the template's existing defaults. Templates created before this change hold their defaults on the template itself. The first build of one that states no sandbox block takes those values rather than publishing a version with none, so a sandbox does not silently drop to the platform's own sizes. State the block to change them.

  • A build that names no tag now moves no tag. It used to move default. The version it publishes is still reachable: pass its id to sandbox create. This is what lets you build a version, test it, and name it afterwards.

  • A template version now reports the disk its image needs. imageBytes is the unpacked size, so you can see what a create has to ask for before it is refused.

  • Updating a template no longer takes an If-Match header. It wrote two prose fields and guarded them against an edit of those same two fields. Template updates are now last-write-wins.

  • The console no longer offers to save or fill a secret's value. The browser and password managers read the value box as a password field. They suggested saved credentials, and they offered to remember the new secret. Both secret fields now refuse autofill, and the example text is gone.

  • The console now shows its loader when you change organization or project. A page kept the previous scope's numbers on screen while the new ones loaded. The figures looked live, but they belonged to the scope you left. Every page under an organization or a project now clears first.

  • A new egress proxy profile now opens its own page. The console left you on the list, so you had to find the new row to add rules. It now takes you to the new profile.

  • Template state badges now have a color. Active and archived both read as gray badges. Active is now green, and archived is amber.

  • A sandbox whose VM dies is no longer listed as running until its machine restarts. If nothing saw the VM stop, the sandbox stayed listed as running and every connection to it failed. The machine now looks every two minutes and reports such a sandbox as suspended, with its disk intact so it can be resumed.

  • A template's versions and tags now read on their own, a page at a time. Reading a template returned every version it had ever built, with no way to ask for the active ones, the tagged ones or the last ten. Four new endpoints per scope list and read them: GET .../templates/{name}/versions, .../versions/{versionId}, .../tags and .../tags/{tag}. The version list narrows by state and by tagged, and pages with a cursor and a limit like the build list.

  • A template description may no longer contain a line break. A description is rendered on one line in the create menu, in tektona template ls and in the console, where a newline broke the row. Create and update both refuse one now, with a 422 that names the field. A description saved earlier with a newline still reads back as it was; editing that template needs the line break taken out before the update is accepted. A display name is capped at 128 characters and a description at 1024, stated on both endpoints.

  • Self-hosting: install Tektona with the tektona-control-plane and tektona-runner Helm charts. See Validate the Helm Charts.

  • Self-hosting: connect your identity provider, with a Microsoft Entra ID example. See Configure Sign-On.

2026-08-28

  • An image reference with no tag now means :latest, the same as docker pull. Tektona refused an image that named no tag and no digest, and refused :latest without a digest. Both now work: --image fedora and --image fedora:latest start the same sandbox, and a template build accepts them too. A build still records the digest it resolved, so the version you get is reproducible. A versioned tag or a digest is still the clearer choice, because :latest moves.

  • A build that reuses a stored image now says so, instead of reporting an upload it did not make. Building a template from an image Tektona already holds skips the pull, the conversion and the upload. The last log line still came from the upload step, so the log jumped from step 0 to step 5 with nothing in between, and said it had published a version that an earlier build minted. It now sits on the resolve step and says the version already covers those bytes. Only the tag moved.

  • Organization and project admins can now manage templates in the console. The console can create, edit, archive, and activate templates. It can delete templates that have no versions. It can also archive or activate untagged versions.

  • Organization responses now include your organization role. The your_role field is owner, admin, or member on get and list responses.

  • You can now build a template from any common base image. A build refused every image that ships no init system, which is all of the widely used bases: ubuntu:24.04, debian:12, node:22-bookworm, python:3.13-bookworm, golang:1.25-bookworm and ruby:3.4-bookworm. None of them needs one. Tektona's init is the first process in the sandbox, and it runs your image's ENTRYPOINT or CMD. A build no longer looks for an init. An image with no shell also builds now, and the build log says that tektona ssh will not open a session in it.

  • A build's step list no longer carries traceId. The field pointed at a record in Tektona's own observability system, which you cannot read and could not act on. To see what a step did, read the build log narrowed to that step's index.

  • An image build of an organization template no longer waits for another organization's builds. Builds of templates that belong to an organization but to no project all shared one limit of two, across every organization and the tektona/* images as well. One organization could use both slots and hold up everyone else. Each organization now has its own limit, projects keep theirs, and the tektona/* images have their own.

  • A build held up by that limit now says which builds filled it. The message said "this project" even for a template that belongs to no project, and counted builds the reader could not see. It now names the project, the organization or the Tektona catalog, and counts only that group.

  • Tektona now provides templates, so a new project starts a sandbox with no setup. tektona/ubuntu starts the headless Ubuntu 24.04 image and tektona/desktop starts the desktop one. Leave the tag off and you get :default, which points at the version Tektona currently recommends. Everyone can read and start from them; only Tektona changes them. See Official Images.

  • A single template version can now be archived. Archiving took the whole template out of the create menu, or nothing. You can now archive one version and leave the rest creatable, and activate it again later. A version a tag still points at is refused: run a build with that tag to move it to a newer version, then archive again. The refusal names the tag.

  • A create from an archived template or version is now refused. Archiving took a template out of the create menu in name only, and a create still started a sandbox from it. The create now stops before anything is written, and the message names what is archived. Sandboxes already running are unaffected: an archived template and an archived version both start, restart, resume and fork as before.

  • A sandbox from a template can be rebooted and resized again after its image is reclaimed. The platform re-downloads an image that a node no longer holds. For a template image it looked in the wrong place, so the reboot or the resize failed instead. It now uses the same address the sandbox started from.

  • A sandbox created from a template now starts. Every such create failed with boot_failed, because the platform looked for the template's image in the wrong place in storage. It now reads the image from the address the build recorded.

  • An image build interrupted by a platform update now reports at once. A build still running when its builder was replaced was cut off without a word, and it stayed at "running" for up to seven more minutes before it was marked failed. It now says why it stopped as soon as it stops, and a sandbox create waiting behind it reaches the next builder within seconds instead of after about ten minutes.

  • A failed image build now reads as one sentence about your image. The reason ended with the raw text of the error underneath it, which for a storage or disk failure named our storage address and file paths inside the builder. None of that was yours to act on. The reason now names the phase, what broke and the image you asked for. Our operators still get the full text.

  • tektona template manages the templates sandboxes start from. Write a commented manifest with tektona template init, create and build with tektona template create and tektona template build run, and read one with tektona template ls and tektona template info. A build waits and prints its steps and log as they arrive, and exits non-zero when it fails. tektona template build logs <build-id> reads any build, running or finished.

  • tektona template update no longer overwrites someone else's change. Changing one field reads the template and sends the whole thing back, so two people editing at once could lose a change. The command now tells the API which version it read, and a write that would clobber a newer one is refused with a message saying to run it again. tektona template update -f is unchanged: it applies the file you wrote.

  • A version can be archived, activated and deleted on its own. tektona template version archive go-dev <version-id> refuses a create from one version and leaves the rest creatable; activate puts it back. A version a tag still points at is refused, and the message names the tag. tektona template version rm deletes a version and every tag pointing at it, and a sandbox that records the version blocks the delete. tektona template archive <name> acts on the whole template, and now says plainly that a create from it is refused.

  • tektona sandbox create takes a template. tektona sandbox create go-dev, go-dev:stable, org/go-dev or tektona/ubuntu. The template supplies the CPU, memory, disk and environment the sandbox starts with, and the resource flags override those one field at a time, so --cpu 8 keeps the template's memory. --template-version pins an exact version and ignores the tag. --image still works.

  • A sandbox create now says what it could not find. A create that named a template nobody had built reported that the project was not found, and sent you to check a context that was correct. It now prints what the API could not find.

2026-08-27

  • A build log you watch live now ends with the reason the build failed. The stream closed one line before it, so anyone watching saw the build stop and had to reload the page to read why.

  • A build stopped by something outside its own steps now says so in its log. A cancelled or expired build run put its reason on the build alone, and the log below it had no line for the event.

  • A page of a build's log now reports where to continue the way every other list does. It returned a nextCursor field of its own. It now returns a pagination object with next_cursor and has_more. A page that ends on the last line no longer gives a cursor that returns nothing. The log reports no total, because it grows while you read it.

  • A failed image build now gives its reason as an error in the build log. The log recorded that line as information, so a log filtered to errors showed nothing for a build that failed. A build that stopped while it resolved the image reference also showed the same sentence twice. The reason now appears once, at error.

  • A sandbox whose image cannot be built here now fails at once. A create needing more build room than the platform has kept retrying until it timed out, then failed for a reason nobody could act on. It now fails immediately with image_too_large and both numbers: the room the image needs, and the room there is.

  • A template build now says how far unpacking has got. Unpacking is the longest part of a build, and the log said nothing while it ran, so a slow build and a stuck one looked the same. The build log now adds a line for each layer — extracted layer 3 of 27, 118 MiB in 12s — as soon as that layer is on disk and checked.

  • An image build now checks every layer against its digest. A registry that served different bytes for a layer produced an image the build accepted. Each layer is now checked, and one that does not match fails the build and names the layer.

  • A layer that does not match its digest now fails the build at once. It was retried up to four times first, and every attempt read the same bytes from the same registry and failed the same way. A layer the registry cut short is still retried, because those bytes can arrive on the next attempt.

  • A sandbox can start from a template. POST /v1/sandboxes now takes a template reference — go-dev, go-dev:stable, or tektona/ubuntu:24.04 — instead of an image. The template supplies default CPU, memory, disk and environment variables, and anything the create sets wins. The sandbox reports the exact version it started from, plus the tag it asked for, so the answer survives the tag moving later. The image field still works.

  • A second build of an image you already built now finishes. The build found the image in storage, skipped the work, and then never reported a result. It stayed at "running" for good, wrote no template version, and held an open log stream open. It now publishes the version and ends.

  • A create always checks that you can pull the image. A build that found the image already in storage reported it ready without asking the registry. It now asks every time, with your own registry credential. A reference you cannot pull fails the create.

  • A sandbox that has to build its image no longer stalls when the platform is updated. A create that was queued behind another image build could wait about ten minutes. It now reaches the next builder within seconds.

  • An image build no longer says your image is too big when it is not. One slow builder could end a build for good with "unpacks to more than the builder allows". The platform now checks its builders over several minutes before it says that, and a build it cannot place waits for room instead.

  • An image build names the right reason more often. A build stopped by a platform update said the registry did not answer. A registry that reset the connection or answered the login step wrongly said nothing at all. Both now say what happened, and both are retried.

2026-08-24

  • The Add members dialog no longer jumps. Adding a user to the list changed the dialog's height and shifted the whole dialog up or down. It now grows downward from a fixed position near the top of the screen.

2026-08-23

  • Lifecycle timeouts read as plain durations. tektona sandbox get, tektona sandbox lifecycle and tektona project lifecycle-defaults printed the duration the server stores it in, so 15 days showed as 360h0m0s. They now print 15 days, and tektona sandbox lifecycle ends with one line saying what the sandbox does.

  • The console and the CLI use the same names for lifecycle settings. Both now say Pause when idle, How to pause, Resume on access and Delete when paused. The --auto-pause, --auto-pause-mode, --auto-resume and --auto-delete flags are unchanged.

2026-08-22

  • Forking a sandbox is about 70% faster. A fork of a busy sandbox took about 10.4 seconds and now takes about 3.0 seconds. The more memory the sandbox is using, the more you save. Nothing changed about how you fork.

  • A sandbox comes back from a pause about 1.4 seconds faster. It waited a set amount of time before it answered again, whether or not it was ready. It now answers as soon as it is ready.

  • Auto-pause finishes about 3 times faster. Saving a sandbox's memory took between 1.2 and 6.5 seconds and now takes about half a second. The node frees up sooner, so your next sandbox starts sooner.

2026-08-21

  • Sandboxes can reach external private addresses that overlap Kubernetes networks. Domains and allowed CIDRs now use the node external route.

  • The dashboard is now the first page of an organization or project. The overview pages are gone. /orgs/acme/projects/app/dashboard becomes /orgs/acme/projects/app.

  • The org and sandbox sidebar keeps your closed choice on reload. Before, it flashed open for a moment, and its show button appeared late.

  • The left rail now opens the sidebar when you enter Sandboxes or Orgs & projects. From inside the orgs surface it goes straight to the open organization, without a flash of a redirect page.

2026-08-20

  • Sandboxes start about 280 ms faster. Every tektona sandbox create saves roughly that. A desktop sandbox now starts in about the same time as a plain one. Nothing changed about how you create a sandbox.

  • The sandbox list can pause, resume and delete again. Every one of those actions was greyed out.

  • Pause, resume and delete now show a spinner while they run. The list and the sandbox page refresh as soon as the state changes.

  • The terminal and the desktop of a paused sandbox are now reachable. Each tab offers a resume button. The shortcut buttons on the sandbox overview are gone; use the tabs.

2026-08-19

  • A sandbox that reports running can now reach a host you gave it credentials for. Right after tektona sandbox create (or tektona sandbox wait), a clone or an API call to such a host failed for a few seconds — most often with a certificate error — and worked after a short sleep. The sandbox told the platform which network slot it uses only once it was already running, so the egress proxy set up the host too late. The sandbox now reports the slot before it boots, and the proxy is ready when the sandbox is.

  • A short command over SSH no longer loses its output or reports exit 255. tektona sandbox ssh <id> -- <command> could print nothing and say the sandbox was unreachable, for a command that ran and exited normally. It happened when the sandbox finished before the gateway finished sending it an empty stdin.

  • tektona sandbox create now says what actually happened. It printed "Image is still building" for every state except running. A create that failed before any build started sent you to look at the image build. It now names a failure as a failure, and points at tektona sandbox info for the step that failed. It also tells you when a create waits for room on a node, and when nothing works on the sandbox any more.

  • A sandbox that comes back from a pause, a reboot or a fork now fails if its program never starts. It read running for good, with nothing running inside it. It also held its share of the node the whole time. The platform now asks the sandbox, and fails it about a minute later if its program never started. The platform stops its machine too, so the node gets the cpu and memory back. The disk stays until you delete the sandbox. A sandbox that stops answering is not affected, and keeps running as before.

  • Deleting a sandbox while it starts, comes back from a pause, or reboots now removes it completely. The delete and the other operation ran at the same time, so the machine could keep a running VM for a sandbox you had already deleted, on a network address the next sandbox then got. The delete now stops the other operation first, and still answers at once.

  • An image that runs as a non-root user now boots when it ships an init system. If your image named no ENTRYPOINT and no CMD, Tektona started the init system in the image and gave it your image's USER. An init system cannot run as a non-root process, so the sandbox never came up. USER now applies to a workload your image names; an init system Tektona starts on your behalf runs as root. Your sessions, remote commands, file transfers and desktop still run as your image's USER.

  • A sandbox no longer runs a sleep infinity process you did not ask for. An image that declares no ENTRYPOINT and no CMD and ships no init system got a sleep infinity process to keep the sandbox up. Nothing needed it: the sandbox stays up on its own. Such an image now runs nothing at all, and the sandbox is still usable over SSH. Your image never has to supply a long-running process.

2026-08-18

  • A new sandbox whose program never starts now fails in about a minute. It stayed in starting for five minutes before the platform gave up. The runner now reports the timeout as soon as its start budget runs out, and only where the sandbox confirms the program never started.

  • A start that fails now gives the node its cpu, memory and disk back. The machine of a sandbox that broke before it ever ran stayed up, and its share of the node stayed held. The next create on a full node had to wait for a person to delete it. A sandbox that ran keeps its disk and its saved state, as before.

  • A deleted sandbox now always gives its machine resources back. A sandbox deleted while it was paused, hibernated or in error kept its VM, memory, disk and network slot on the machine for good. The machine lost that capacity silently, and creates on it failed later as if the cluster were full. A delete now reaches the machine whatever state the sandbox was in.

  • A process environment inside a sandbox now stays with the user that started it. The in-sandbox control socket reported the environment of every process and every autostart entry to any guest user that asked it. It now reports an environment only to the process's own user, and to root. No tektonactl command showed it, so a leak needed a program written against the socket.

  • A gateway restart now ends an open process log or terminal stream cleanly. The connection dropped with no close message, so a client saw a network fault instead of a clean end. The stream now closes with a close message.

  • A sandbox desktop can no longer take ownership of files outside its home. Preparing a desktop session created and took ownership of the directory named by $HOME. An image whose user had no home directory pointed that at /, so the session took ownership of everything at the top of the filesystem. A $HOME that is not a real home directory is now refused, and the session prepares root's home instead.

  • A sandbox that starts your session outside $HOME is easier to spot. When your image's WORKDIR is not the session user's home, a tool that creates a directory with ~ and then writes to a path relative to the session uses two different places, and an editor uploading its remote server fails with No such file or directory. Make WORKDIR the session user's home directory, or add ENV HOME=<WORKDIR> to the image. See Custom images.

  • A statically linked program no longer fails to start in a sandbox. On some images a tool built against musl exited immediately with os error 2, because the session's working directory was entered from outside the sandbox's own view of the filesystem.

  • A relative path in tektona sandbox cp --user now lands in that user's home. It resolved against the image user's home instead, so an upload to a plain file name failed with permission denied. It now lands where tektona ssh --user starts, as it already did without --user.

  • The desktop session now uses the same $HOME as an SSH session. An image that sets ENV HOME had the desktop write its files into the image user's passwd home instead. Both now use the image's HOME.

  • tektona sandbox ls now shows every sandbox you have. It hid a sandbox that waited for room on a node (queued), one that restarted (rebooting), and one that failed on the platform side (error). --all now also shows the deleted ones, which it never did before.

  • Open a sandbox directory in local VS Code or Zed. tektona vscode <sandbox-id> and tektona zed <sandbox-id> open the sandbox workdir over SSH, or a directory you name. With a registered SSH key the window stays open past the one-hour token, and the address the editor stores holds no credential. The editors run their own ssh, which takes no key path, so a key outside the default ~/.ssh names needs an IdentityFile entry in ~/.ssh/config. Without one these two commands stop and name the fix, even where tektona ssh works.

  • Fixed the network rules for a sandbox that comes back after a node problem. In some cases the rules were not applied again. They are now applied every time the sandbox comes back.

  • Fixed a case where a sandbox did not finish starting. In some situations a new sandbox stayed in starting and never became usable. A create that does not come up now fails within its deadline instead of waiting.

  • A sandbox from an image with no command now starts. Such an image needed a sleep program inside it to start. Without one the sandbox stayed in starting, then failed. It now starts and is usable.

  • Connecting to a sandbox that is still coming up now waits for it. SSH and preview URLs refused a sandbox whose image was still building, or that waited for room on a node, and reported it as unusable. They now wait for it to come up, as they already did for a sandbox in starting.

  • A percent-encoded address now survives the egress boundary. An encoded character in a URL path was decoded before the request went out, which changed the address and made the server answer 404. The path now reaches the server as you sent it.

  • A wildcard rule host now injects. A rule for *.example.com was accepted and reached, but it never added its value to a request. It now credentials every host under that domain. Where two rules set the same header, a rule that names the host wins over one that wildcards its domain.

  • An international rule host now works. A rule host written in Unicode, such as bücher.de, matched nothing, so the rule never fired. Unicode and punycode spellings now match the same traffic. A host that is not a valid international domain name is refused when you add the rule, instead of being stored and never firing.

  • A wildcard rule host over a known public suffix is now refused. * reaches every host a sandbox talks to, and *.com, *.co.uk and *.pages.dev reach every host a stranger can register there. A rule stored before this check is now ignored, and its traffic goes out with no value added. A wildcard still sends your secret to every host under the domain you name, so prefer an exact host.

  • Plain HTTP to a host a rule binds now reaches the server. It got a 400 from the proxy instead. The request now goes through, with no value added — a rule never credentials a cleartext request, so use https:// for every address a rule binds.

  • A git credential for one repository no longer blocks the rest of its host. Registering a repository put the whole host behind the credential, so any other address on it was refused. Other addresses now go through, and carry no credential.

  • The CLI can now connect with your registered SSH key. Run tektona ctx identity set ~/.ssh/id_ed25519 once, and tektona ssh, tektona sandbox cp and tektona sandbox port-forward use that key. tektona ssh --print then prints a command that does not expire, so you can paste it into ~/.ssh/config or an editor. tektona ctx identity clear returns to a short-lived token.

  • tektona ssh now works on Windows. It stopped with "not supported by windows" and never started ssh.

  • tektona ssh --print now prints every option the CLI uses. The printed command left out the authentication options, so it did not always behave like the connection the CLI makes.

  • A short storage fault no longer keeps a paused sandbox on one machine. When a sandbox pauses, its disk (and memory, for a paused sandbox that keeps its memory) is copied to object storage. A failed copy was marked as missing for good, and nothing tried again: the machine kept the local files and the sandbox could only start again there. The copy is now sent again up to four times before the pause reports a failure.

2026-08-17

  • Registered SSH public keys can now open sandbox sessions. Editors can reconnect without storing an expiring access token in their workspace data.

  • The console now has an SSH keys page. Add your public key there, and see when each key last opened a session.

  • Pausing a sandbox now saves its disk and memory faster. More upload parts now run at the same time, which speeds up pauses and forks after hibernation.

2026-08-16

  • A dropdown with a search field no longer opens the keyboard on a phone. The field took the focus as the dropdown opened, and the keyboard covered the list you came to read. Tap the field to search.

  • The new thread form now fits a phone screen. The label column squeezed every control, so words broke across lines and long text ran past the screen edge. Labels now sit above the controls on a narrow screen.

  • Statistics on a phone now fit the screen. A project overview stacked six full-height cards, and a dashboard nine, so the numbers took several screens of scrolling. Counts now sit two to a row in a compact block, and grow back to one row on a wide screen.

  • The console no longer signs you out after an hour away. Opening it again sent you to the login page, because the refresh token was not attached to a page load — only to calls made by a tab that was already open. A session now lasts as long as its refresh token.

  • A text field on a phone no longer hides the page header. Focusing one scrolled the header off the top of the screen. The keyboard now shrinks the page instead.

  • The console on a phone now gives the whole screen to the page. The bottom bar and the org/project tree took a third of the screen before the content started. Navigation opens as a drawer from the button in the page header, and the scope crumb beside it opens your orgs and projects.

  • --user no longer replaces the shell your sandbox was created with. tektona ssh <id> --user root took the shell from root's passwd entry, so a sandbox created with --env SHELL=/bin/dash gave that session /bin/bash. A named user still brings its own HOME, USER and LOGNAME. The shell now follows the documented order for every SSH session: --env first, then your image's ENV SHELL, then the passwd entry.

  • SHELL now names a shell that runs. For an image whose USER cannot log in, SHELL held the passwd entry /sbin/nologin. The session ran a working shell, but an editor started what SHELL named and got "This account is not available". SHELL now names the shell the session starts.

2026-08-15

  • A malformed --user now names the problem. tektona ssh <id> --user "root+evil" ended in an authentication failure, which sent you to check your credentials instead of the name. tektona ssh and tektona sandbox cp now check the name before they connect, and say what a name may be.

  • Resuming a paused sandbox is now about twice as fast. The larger the sandbox, the more it saves. Forking a sandbox gets the same speed-up. A sandbox paused before today resumes as it did before.

  • A session now says where it came from. SSH_CONNECTION and SSH_CLIENT name the two ends of your connection, and SSH_TTY names the terminal when you asked for one. tmux and screen read these to tell a remote session from a local one, and a shell prompt often names the client.

  • A session opened with --user now gets that user's home. It kept the image user's HOME and started in its home directory, so --user root on an image whose USER is dev gave a root shell sitting in /home/dev — every ~/… write landing in another user's home or failing. Without --user, your image's ENV HOME still wins.

  • A --user your image does not have now says so. It was reported as sandbox unreachable, so a typo looked like a broken sandbox.

  • --user now picks the user a session runs as. tektona ssh <id> --user root and tektona sandbox cp --user root run that one session as the user you name, instead of your image's USER. Give it a name from your image or a uid. A name your image does not have fails the session rather than falling back to another user.

  • An SSH session now runs as your image's user. It ran as root whatever the image said, so a file you created over SSH belonged to root and the workload could not write it. The shell, a remote command and tektona sandbox cp now all run as the image USER, the way sshd runs a login as the user that authenticated. An image with no USER line, or with USER root, is unchanged.

  • An interactive SSH session now starts a login shell. /etc/profile and /etc/profile.d/* never ran, so a PATH set there was missing from the session. A remote command now runs through your shell rather than /bin/sh, though — like ssh host -- cmd — it is not a login shell and reads no profile. A login shell reads ~/.bash_profile, not ~/.bashrc: an image that only appends to ~/.bashrc needs a ~/.bash_profile that sources it.

  • An SSH session now carries the user's groups. A USER in the image's docker group now reaches the docker socket over SSH, and the workload started by ENTRYPOINT gets the same groups.

  • A USER that cannot log in no longer locks you out. useradd -r assigns /usr/sbin/nologin, and honouring it would end every SSH session with "This account is currently not available". Those shells are now ignored in favour of a working one.

2026-08-14

  • An editor now opens the login shell from your image. It no longer falls back to sh when the image names another shell.

  • A remote command now gets a terminal when it requests one. ssh -tt <host> -- <command> now gives the command a terminal device.

  • Remote commands that read stdin now exit after the client closes it.

  • An SSH shell without a terminal now has clean pipes. ssh -T no longer echoes input, adds terminal line endings, or prints a prompt. VS Code Remote SSH now runs its setup script through the shell channel.

  • A repository with a blank default branch now says main. A repository registered before Tektona filled the branch in kept an empty one, so a clone followed whatever the server called HEAD instead of a named branch. Those repositories now read main, the same value a new one gets. A repository with a branch already set keeps it.

  • Pausing a sandbox is now about twice as fast. Forking a sandbox gets the same speed-up.

  • A screenshot now reports the size of the image it returns. Every screenshot said 1280x720, whatever resolution the desktop ran at, so an agent that scaled click coordinates from those numbers clicked the wrong place. The width and height now come from the captured image.

  • Your own image can now run a desktop. desktop start accepted only Tektona's desktop-x11 image, and refused every other one by name — including an image that had a working desktop. Add an executable /etc/tektona/desktop-session to your image and Tektona runs it. It decides the window manager, the wallpaper and the applications. Tektona starts the X server first, so the script only puts things on the screen. See Connect over VNC.

  • A desktop that fails to start now says so. desktop start reported success as soon as it launched the desktop, so a missing program left you with "Desktop started" and a black screen. It now waits for the display and reports what went wrong.

  • tektona sandbox desktop help now names the images it works on. The command said only "Start the desktop environment in a sandbox", so there was no way to know it needs a desktop image.

  • You can now check the desktop from outside the sandbox. tektona sandbox desktop status <id> prints active or inactive. Before, only tektonactl desktop status could tell you, and that needs an SSH session.

  • A registered repository can now be changed from the CLI. To correct a name, a URL or a default branch, you had to delete the repository and add it again. That stripped it from every git credential that covered it. tektona repository update changes one field and keeps the rest. tektona repository ls --default shows the default repo set alone. get, update and rm also accept the repository ID, not only the name or URL.

  • A URL that two repositories share now reports the clash. Two repositories can hold the same URL, because only the name is unique in a project. A command that took such a URL — tektona repository rm, or tektona git-credential --repo — picked one of them at random. It now names the count and asks for the ID instead.

2026-08-13

  • A new agent skill teaches your coding agent the TypeScript SDK. tektona-typescript-sdk joins tektona-cli and tektonactl in the agent-skills package. It covers @tektona/sdk — sandboxes from code, process streaming, pagination, and typed errors.

  • Resizing a sandbox no longer changes what its past usage cost. The usage numbers read the size the sandbox has now. A sandbox that ran a month at 2 GiB and then grew to 32 GiB showed the whole month at 32 GiB. Each size is now recorded when it takes effect. Every day is priced at the size the sandbox ran at on that day. Sandboxes that existed before today keep the numbers they had.

  • A prompt that is sent again no longer makes the agent do the work twice. A retry of the same prompt started a second turn, so the agent could do the same work — and the same commits and pull requests — twice. A retry now gets back the turn that is already running.

  • tmux and screen now start in a tektonactl terminal. In an image whose workload runs as a non-root user, a terminal opened with tektonactl pty create got a terminal device owned by root. The session itself worked, but anything that re-opens the terminal by name — tmux, screen, script — failed with a permission error. The device now belongs to the user that opened the session.

  • A tektonactl process or terminal now starts in its own home. A process or terminal started by a non-root user kept root's HOME, so a shell read root's dotfiles and reported that it could not open them. HOME, USER and LOGNAME now name the user the process runs as.

  • Process output and terminal scrollback are now readable only by their owner. Reading them needs the same ownership as stopping or typing into them. tektonactl ps and tektonactl pty ls still list everything: they say what is running, not what it printed.

  • The sandbox desktop now runs as your image's user, and only that user and root can reach it. An image that declares no user, or declares root — including Tektona's own desktop-x11 — is unchanged.

2026-08-12

  • The first sandbox of an image on a machine no longer fails while the image is still downloading. A create was given two minutes to finish, and a machine that did not have the image yet spent longer than that fetching it, so the sandbox was reported as failed for an image that was about to be ready. A create now has ten minutes, which covers fetching an image of a few GB.

  • tektona sandbox wait now waits ten minutes by default. A create that fetches its image can take that long, and the old five-minute default reported a timeout on a sandbox that was still coming up. Pass --timeout for a different budget.

  • A late pause no longer breaks a sandbox that can still be resumed. If a pause command reached the machine after the sandbox had already stopped there, the sandbox went to error and could only be deleted, although its disk was intact. It is now reported as suspended and can be resumed.

  • Starting a sandbox from a large image no longer fails now and then on a storage error. The download asked the image store to check with every part that the image is still the same one. Some stores refuse that check on a large image and answer with an error. The download now makes the check itself, on the version the store reports with each part. An image that is replaced during a download is still caught.

  • A repeated create now returns the sandbox that is already running. A client that sends the same create twice — after a timeout, or on a retry — gets one sandbox back rather than a second attempt.

  • Starting a process with wait now waits for its last output too. The call came back the moment the process finished, before its final output and its record were written, so reading the logs right after could miss the last lines.

  • A Ctrl-C that does not reach the process now tells you. While attached, if the process neither prints anything nor stops within 5 seconds of a Ctrl-C, the CLI says so and offers to press it again or stop the process. A Ctrl-C the CLI could not send at all is reported on the error stream.

  • A refused process stream now tries again with a new token. The token that opens a process log or attach stream lasts 60 seconds, and the CLI used only the token it took at the start. If that token was refused — it ran out on a slow connection, or it was cancelled early — the command stopped with a permission error. tektona sandbox process logs and tektona sandbox process attach now take a new token and connect again.

  • A sandbox no longer fails when its image is replaced during the download. An image that was replaced late in the download stopped the download and left the sandbox in error. The download now starts over once and takes the new image. An image that is replaced a second time still fails.

  • A failed fork now leaves the source sandbox untouched. Work done in the source after the fork is kept, and its next pause saves it.

  • A create that failed placement now says placement_failed. The failure reported the reason internal, which is what a create says when it cannot name the cause at all. It now names the real cause, and still says that sending the request again may work.

  • A create that failed for want of room now says so in its history. No capacity, a queue wait that ran out, and an unreadable placement were all recorded as scheduling_failed. They now read no_capacity, queue_wait_expired and invalid_placement, so the history says whether waiting or asking for less can help.

  • A slow reboot now settles once the sandbox reports in. A reboot that takes longer than expected leaves the sandbox running rather than reporting an error, and closing the connection during a reboot no longer leaves it in rebooting.

  • An automatic delete is now named as one in the sandbox's history. It was previously recorded as a delete made through the API.

  • A sandbox that stopped on its own can now be resumed at once. It was reported as suspended, but every resume was refused with "already registered". A resume now works immediately, from the disk the sandbox had.

  • A VNC session no longer stops working after an hour. The token behind the connection lasts an hour, and both tektona vnc and the console viewer held the first one for as long as they ran. An hour in, every reconnect was refused: tektona vnc printed upstream connection failed on a loop and the console viewer stayed on a black screen, and only restarting the command or reloading the page fixed it. Both now renew the token when it runs out. A fault that will not clear is also reported once now, instead of once per reconnect for as long as the command runs.

  • Opening a shared ?tab=vnc link now connects. The console's VNC tab only started a session when you clicked the tab, so a link straight to it waited forever on "Loading...".

  • tektonactl now runs a process or terminal as the user who started it. A user who is not root may name only itself in --user, group included, and may only attach to, type into, signal, resize, stop or set autostart on what it started itself. Run tektonactl as root and nothing changes.

  • A process or terminal started for a user who is not root gets that user's login group only. It does not get the user's other groups. If a command fails on a group permission it used to have, this is why.

  • A negative --timeout or --max-log-bytes on a process is now refused. A negative timeout was accepted and then dropped, so the process ran with no timeout at all. Both tektona and tektonactl now report the bad value and start nothing.

  • A terminal session's log limit is now held at 128 MB. An out-of-range limit is capped rather than accepted. Terminal session logs are also no longer readable by anything else in the sandbox.

  • An outsized terminal window is now held at the maximum. Asking for more than 65,535 columns or rows no longer produces a tiny window.

  • The VNC viewer now shows the receive and send rates for the sandbox you are watching. They sit at the top of the window in whole units — 240 KB/s, 1.5 MB/s. Before, rates were shown only above the grid, so a viewer on a single sandbox showed none.

  • The VNC viewer no longer shows a "Grid" button for a single sandbox. There is no grid of one to go back to.

  • A failed sandbox create now says whether trying again can work. A create that lost a race came back as a server error, which tells you not to retry — and retrying is exactly what fixes it. A failed create now names the reason it failed and says whether sending it again may work. The tektona CLI prints that reason instead of always reporting no capacity, and says the API is unreachable when that is what happened.

  • A failed sandbox create now names the step that actually failed. A sandbox that would not boot was reported as a failed image build, because the reason was taken from what the sandbox was doing rather than from what the failing step said. A create that fails now reports boot_failed, build_failed, disk_too_small or scheduling_failed for what happened, and one that ran out of time reports create_timeout.

  • A failed sandbox create no longer blames a lack of capacity when that is not the cause. It now reports the failure it actually hit. Only a real capacity shortage says there is no room.

2026-08-11

  • A sandbox now says whether Tektona manages it. Sandboxes carry a read-only managed field, true when Tektona made the sandbox and not you. You cannot set it.

2026-08-09

  • A thread now has a team chat. People working on the same thread can read its history, post to it, and see who is typing, separately from the agent's own conversation. The chat streams live, and a client that drops off is sent whatever it missed when it comes back.

2026-08-07

  • A resume no longer fails on a damaged local copy of a sandbox. If the copy kept nearby could not be read, the resume used it anyway instead of falling back to the saved one, and the sandbox failed to start. A resume now falls back automatically.

  • Image downloads cope better with a busy or changing registry. A download that cannot succeed now fails at once instead of retrying, and a throttled download waits long enough to get through. An image replaced in the first moments of a download is picked up in its new version; replaced later in the download it still fails.

  • A repeated resume now returns the sandbox that is already running. A second resume request for the same sandbox succeeds instead of reporting an error.

  • A console connection to a deleted sandbox now stops retrying immediately. A stale VNC session previously repeated the same failed lookup before giving up.

  • A sandbox stopped by platform maintenance is now reported as suspended. Its disk is intact, so it can be resumed. Sandboxes still listed as running from before this change are corrected automatically.

2026-08-06

  • Typing text on the desktop no longer stops at the first accented character. tektonactl desktop type delivered only the part of the text before the first character outside plain ASCII — an umlaut, an accent, an en-dash or an emoji — so "Grüße" arrived as "Gr". The full text is now typed.

  • Typing multi-line text now breaks lines the same way everywhere. Over VNC, line breaks and tabs were dropped entirely, so multi-line text arrived as a single run-on line with no error reported. Through tektonactl desktop type, a line break was sent as a key some applications ignore. Both now press Return, and tabs press Tab.

  • A failed tektonactl desktop command now says what went wrong. A missing tool was reported in terms you could not act on, a command that timed out reported only exited -1, and some failures produced an empty message.

  • tektona sandbox screenshot no longer opens the image in a viewer by default. It saves the file and stops. Pass --open to open it; the old --no-open flag is gone, since that is now the default.

2026-08-05

  • Resuming a paused sandbox no longer fails for capacity the sandbox already holds. A resume was asked to find room for a disk that was already reserved for it, so a resume needing 10 GB could be refused with 15 GB free. A resume is no longer charged for the disk it is returning to.

  • A sandbox that stopped on its own is now reported as suspended, with vm_crashed in its transition history. It can be resumed — its disk is intact.

  • A resume right after a pause no longer stalls. For a short window after a pause, a resume could spend about half a minute looking for a saved copy that had not finished being written, and then give up. A resume in that window now works. If there is no room for it, you get a capacity error to retry instead.

  • A vanished VNC or browser-terminal connection no longer keeps the sandbox awake. When a viewer's connection died without closing — a laptop going to sleep, a dropped network path — the session stayed open indefinitely, which held the sandbox active and prevented auto-pause. The session now ends shortly after the viewer goes silent.

  • A hibernate that cannot save memory now keeps the sandbox instead of failing it. It completes as a suspend: the disk is saved and the sandbox restarts from cold on resume, but its running processes are lost. The transition history gives the reason as partial_memory_image. A hibernate that fails while the sandbox is still running is unchanged — it still reports a failure and leaves the sandbox running.

  • tektona sandbox pause now waits for the sandbox to finish pausing. The API accepts a pause and answers immediately, so the old message reported a duration that had nothing to do with the pause. It now waits by default, prints the state the sandbox actually reached, and takes --wait=false to return as soon as the pause is accepted.

  • tektona sandbox wait --state hibernated no longer sits until it times out when the sandbox suspended instead. It says which state the sandbox settled in and stops.

  • Resizing a sandbox that is starting, pausing, resuming or rebooting is now refused instead of silently applied. A resize during a pause left the sandbox recorded at a size it did not have. Wait for the sandbox to settle and resize then; resizing a running or paused sandbox is unchanged.

2026-08-04

  • The TypeScript SDK no longer requires a terminal size to allocate a PTY. process.start and process.run now accept tty: true and partial sizes like tty: { cols: 200 }; anything unspecified uses the server default of 120x40. Passing an explicit { cols, rows } works as before.

  • Signing in from another application now returns you to it. A sign-in that started somewhere else completed on the Tektona login page but then landed on the Tektona dashboard instead of going back. The login page now sends you back to the application that asked.

2026-08-03

  • Sandbox state no longer includes an unreachable completed value. A clean entrypoint exit keeps the sandbox running and usable, so APIs and the CLI now expose only states the platform can actually produce.

  • Revoking a preview URL now reports when the API refuses the request. tektona sandbox revoke-preview previously claimed success when the sandbox was not found or the caller lacked access, even though no token was revoked. It now prints the API error and exits with a failure status.

2026-07-31

  • Sandbox scripts can pass --yes consistently when pausing or resizing. tektona sandbox pause and tektona sandbox resize now accept -y and --yes as no-ops instead of rejecting them as unknown flags; neither command requires confirmation.

  • A forked sandbox now inherits its parent's egress restrictions. A fork could reach hosts its parent blocks, and showed an empty egress network policy. A fork now inherits the parent's egress network policy, egress proxy profile, and public/private setting, so a copy is contained exactly like the sandbox it came from.

2026-07-30

  • A lifecycle command that fails now tells you why. Pause, resume, reboot and reset each answered with the same generic message for every possible failure, and a process that would not start said only start process failed. All of them now carry the real cause, and a create or resume refused for lack of capacity says so explicitly.

  • Repeating an action a sandbox is already doing now succeeds instead of failing. Pausing a paused sandbox, resuming one that is already coming up, or rebooting one that is already rebooting answered with an error. Each now returns success without doing the work twice, so a client that retries after a timeout no longer has to guess whether its first call landed.

2026-07-29

  • tektona ssh to an unreachable sandbox now fails with a message instead of going quiet. It sat for a while and then exited with no output at all, which looked like the command had hung. It now prints sandbox unreachable and exits with a failure status, so scripts see the failure too.

2026-07-28

  • Growing a running sandbox's disk now gives it the space right away. tektona sandbox resize --disk reported that the change applied immediately, but the extra space only showed up after a restart. df now reflects the new size as soon as the command returns.

  • Auto-pause now scales to sandboxes with a lot of memory. A large sandbox needs longer to pause than the previous fixed limit allowed, so its auto-pause could fail. Tektona now allows time in proportion to the sandbox's memory.

  • A CLI command rejected for an out-of-range value now says which value and what the limit is. tektona sandbox resize ... --disk 40 answered only validation failed, leaving no way to tell which flag was at fault. Each rejected value is now listed beneath the error with the limit it exceeded. This covers every CLI command, not just resize.

  • Platform updates no longer cut off sessions in progress. A routine update used to sever every active SSH session, file transfer, port forward, browser terminal and VNC session at once. An update now stops accepting new connections first, lets a file transfer or port forward finish (up to a few minutes), and gives interactive sessions a moment to flush. Your sandboxes keep running across the update as before.

  • The egress proxy profile list no longer runs off the side of the page. A profile with more than a couple of rules spelled out every rule and header on one line, pushing the scope, rule count and actions menu off screen. Each row now names the domains the profile injects into, up to three, and keeps its width. Clicking a row opens the profile, where you can add, edit and remove its rules.

  • Video and other full-screen motion over VNC is far smoother. Photographic regions that change often are now sent as JPEG, while text and static areas stay lossless. Previously everything was lossless — fine for text, hopeless for video.

  • The VNC picture is sharper, at no cost in bandwidth or frame rate.

  • A frozen or black VNC session now recovers by itself. Both the console viewer and tektona vnc reconnect when a session stops delivering or is cut short by a sandbox reboot, instead of leaving the picture stuck on its last frame until you restart the viewer. An idle sandbox is left undisturbed. The Disconnect button is gone, since the viewer now reconnects on its own, and the throughput meter shows real numbers instead of always reading 0 B/s.

2026-07-27

  • The browser terminal now closes properly when the shell exits. Typing exit dropped the connection without telling the browser why, which looks exactly like losing your network connection. The session now ends with a normal close carrying the shell's exit code.

  • tektona vnc no longer opens black when the desktop isn't running yet. Opening it before tektona sandbox desktop start could leave the viewer black even afterwards, and the only way back was running the command again. One tektona vnc now works whether or not the desktop was already running.

  • An unexpected sandbox restart is now recorded and reported. If a sandbox restarts on its own — after running out of memory, or a reboot from inside — it previously left no trace, even though every running process was lost. The restart now appears in the sandbox's history with a best-effort cause, and restart_count, last_restarted_at and last_restart_reason are included when you fetch a sandbox, so a client that only checks status can tell it happened, when, and why.

  • Files written to /tmp in a sandbox no longer count against its memory. /tmp now lives on the sandbox's disk rather than in RAM, so large temporary files (build output, extracted archives, scratch data) use disk space instead of competing with your program for memory. Pausing a sandbox is also faster, because throwaway files in /tmp are no longer saved with it.

  • tektona sandbox cp is around eight times faster on large files. It now downloads at about the speed scp reaches over the same connection.

2026-07-26

  • Fetching an organization or project you can't access now returns "not found" instead of "forbidden". Asking for the details of an org you're not a member of, or a project you have no access to, previously answered 403 — which confirmed the org or project existed. It now answers 404, the same as a name that doesn't exist, so an outsider can't tell the two apart.

  • Requests now answer 503 rather than 401 when Tektona cannot check your credentials. A 401 said the credential was bad even when the real problem was that the service verifying it was unreachable, which sent people to rotate keys that were fine.

2026-07-24

  • "Disk allocated" on the organization and project dashboards is now accurate. A sandbox still waiting to start was counted before its disk existed, inflating the figure, and the tooltip described the number incorrectly.

2026-07-23

  • Signing in from a login page you left open now works. Previously a page that had been sitting for more than ten minutes failed with a "token exchange failed" error; the sign-in form now starts a new sign-in when you submit, however long the page has been open. A sign-in link that can't be completed sends you back to a fresh login page instead of an error page.

  • A mistyped organization URL now shows a clear "not found" page instead of the access-denied message, which is now reserved for organizations that exist but you're not a member of.

  • Profile pictures load faster. Uploaded pictures are downscaled to a small thumbnail and served everywhere a person appears — member lists, the rail, hover cards — instead of the full-size upload.

  • Click a profile picture to enlarge it. A profile's picture opens full size in a lightbox.

  • Add a job title to your profile. It shows under your name on your profile and in the hover card, like a headline.

2026-07-22

  • A sandbox no longer runs out of disk part way through its life. A sandbox could be started where its disk did not genuinely fit, and then hit "no space left on device" while running. A sandbox is now only started where the disk it asked for is available for its whole life.

  • Your profile is now editable in the console. Personal Settings is where you set your username, display name, bio, company, website, social links, and profile picture. Your name and picture now show up across the console straight away, without signing out and back in.

  • Profiles have a page. Visit /@handle to see someone's profile.

  • Members lists show profile pictures. Organization and project member lists now show each person's picture instead of a letter.

  • Sandbox forking is more reliable. A round of fixes to tektona sandbox fork: forking a running or paused sandbox, forking the same sandbox repeatedly, and pausing, resuming, and resizing a forked sandbox all behave as expected. A child starts from the parent's filesystem as it stood at the moment of the fork.

  • Idle sandboxes pause more reliably. The automatic idle pause now confirms the sandbox has stopped before recording it as paused, and a sandbox that would previously have stayed awake indefinitely is now paused.

  • A sandbox create that loses its connection now finishes cleanly. The sandbox pauses and cleans up normally, and a create that fails reports an error rather than staying in "scheduling".

  • Pausing a sandbox now flushes its filesystem first. tektona sandbox pause --mode suspend writes out what the sandbox still held in memory before stopping it.

  • The CLI now retries a connection that fails before it reaches the API. A connection that stalls while being established is retried for up to three minutes instead of failing the command. A refused connection or an unreachable API URL still fails immediately.

2026-07-20

  • SSH connections to a sandbox now end when the sandbox pauses, so clients notice straight away and reconnect on their own once it resumes.

  • The CLI now ships its third-party license notices. Every release archive and npm package includes a THIRD_PARTY_NOTICES.txt listing the copyright and permission notices of the open-source software compiled into the tektona binary. Homebrew installs place it alongside the binary in the Caskroom.

  • Your account now has a username and a public profile. Every user gets a unique, case-insensitive handle (lowercase letters, numbers, and hyphens, up to 39 characters). Existing accounts were assigned one derived from their email address, and you can change it at any time. You can also set a display name, bio, company, website, and social links.

  • Upload a profile picture. Add a PNG, JPEG, WebP, or GIF (up to 5 MB) to your account, or remove it again.

2026-07-17

  • The console sign-in screen got a new look. The static photo next to the sign-in form is replaced by a live topographic map — slowly shifting terrain drawn as contour lines — with the Tektona mark floating above it on a liquid-glass tile. The animation is disabled for users who prefer reduced motion.

2026-07-14

  • The Sandboxes section got a cleaner, live overview. A sidebar lists your organizations and their projects for picking the scope at a glance, live Running/Paused/Total counts double as filters, the list is searchable by ID, image, or project, and the table focuses on what each sandbox is and its current state — per-sandbox configuration details moved to the sandbox's detail page.

  • Light mode is back. A theme switcher in the left rail toggles between light, dark, and system; every console page now renders correctly in both themes.

2026-07-13

  • The console is now organized into Development, Sandboxes, and Settings. A left-hand rail switches between the three, and Development gains workspaces — named tab layouts with split views that persist across sessions.

  • DNS-over-HTTPS is now also blocked over HTTP/3. Well-known public DoH resolvers are blocked on HTTP/3 in addition to HTTPS, and clients fall back to the standard DNS path automatically. As before, you can use a specific DoH resolver by adding its exact host to your egress network policy's allow list.

2026-07-11

  • Sandbox disk size is now honored on every image. The writable filesystem inside a sandbox now grows to fill the disk you request, whatever the base image. Previously, many minimal images — Alpine, distroless, and -slim variants — silently kept only their built-in filesystem size, often tens of megabytes, so --disk had no effect and large writes failed with "no space left on device".

  • Resizing CPU or memory no longer breaks resume. A CPU/memory resize now applies on the sandbox's next reboot instead of its next resume. Previously, resizing memory (or CPU) and then hibernating and resuming could leave the sandbox in an error state, because a paused sandbox can only resume at the size it was paused at. Resume now restores the sandbox at that size, and the resize takes effect the next time you reboot it. Disk growth is unchanged.

  • HTTP/3 now works through the egress domain filter. Outbound QUIC / HTTP-3 (UDP port 443) to an allowed domain is now inspected and permitted instead of being blocked, so allowed domains work over HTTP/3 while denied and uninspectable traffic is still dropped.

  • DNS-over-HTTPS is blocked by default so egress policies stay effective. Sandboxes no longer resolve names through well-known public DoH resolvers (e.g. Google, Cloudflare, Quad9) by default; those endpoints are blocked so DNS falls back to the standard resolver the platform inspects. This keeps allowed domains reachable on non-HTTP ports and keeps egress filtering consistent. To use a specific DoH resolver, add its exact host to your egress network policy's allow list. Plain HTTPS to those providers' other services is unaffected.

  • SSH and VNC access now shrugs off connection floods. Repeated connection attempts and failed authentications are rate-limited per client address, so port scanners and floods can't degrade sandbox access. Normal usage — even many parallel SSH sessions and port forwards — is unaffected.

  • Attaching or detaching a sandbox's egress proxy profile now confirms the change is active before succeeding. tektona sandbox egress-proxy set/unset report an error if the change was saved but could not be confirmed on the sandbox (it still applies automatically once the sandbox is reachable — retry to confirm); paused sandboxes must be resumed first, and detaching when no profile is attached now says so instead of silently succeeding.

  • Detaching an egress proxy profile now cuts the injected credential off immediately. Previously, after detaching (or switching) a profile on a running sandbox, an already-cached credential could keep being injected for a while. Attach, switch, and detach now all take effect on new connections right away.

  • The first agent message on a fresh sandbox now answers in seconds. A readiness check could stall the whole first message for well over a minute. The first message now goes through as soon as the agent is up.

  • Attach or switch an egress proxy profile on an existing sandbox. tektona sandbox egress-proxy set <sandbox-id> <profile> attaches a profile (or replaces the current one) and unset detaches it — no recreate needed, and a running sandbox picks the change up within seconds.

  • Sandbox reboot no longer fails for sandboxes created before the latest platform update. Rebooting (or resetting) such a sandbox could fail and leave it in an error state; the reboot now comes up with the platform's current agent, like a resume does.

  • The coding agent works again after a sandbox reboot. Previously, after tektona sandbox reboot (or reset) the sandbox's agent never reconnected, so agent messages failed until the sandbox was recreated. The agent now comes back automatically within seconds of the reboot completing.

  • First message to a freshly created sandbox no longer fails while the agent finishes initializing. Previously, the very first agent message could error if the agent's one-time startup took long, and only a retry went through. The message now waits for the agent to come up and is delivered on the first attempt.

  • Egress proxy rule changes now apply to running sandboxes immediately. Adding, updating, or deleting an injection rule on an egress proxy profile now reaches every running sandbox attached to that profile within a second or two, instead of relying on a periodic refresh — no restart needed.

  • Multiple egress proxy rules for the same host now all apply. Previously, when several rules targeted one host (e.g. an API key from one rule and a tenant header from another), only one rule took effect and the others were silently ignored. All matching rules now inject together; if two rules set the same header, the more specific rule wins.

  • Agent event streams now include tool results. Subscribers to a sandbox's agent event stream previously saw each tool call but never its outcome; a tool_result event now follows every tool_call, carrying the tool's output or error.

  • Remove egress proxy rules from the CLI. tektona egress-proxy rule rm <profile> <rule-id> removes an injection rule from a profile, and tektona egress-proxy show now lists each rule's id so you can find the one to remove.

2026-07-10

  • The first preview request to a paused sandbox no longer stalls. In some situations — when the preview had served traffic shortly before the sandbox paused — the first request after the pause hung and failed instead of waking the sandbox, and only a second attempt would load. The first request now wakes the sandbox and serves promptly.

  • Full-mode forks are now reachable from outside right away. A sandbox forked with --mode full kept the parent's network address, so its preview URLs and forwarded ports returned 502 until a reboot — even though the preserved processes were running fine. The fork now comes up with its own address and its previews work immediately.

  • Long commands over tektona ssh <id> -- <command> no longer disconnect after 5 minutes. In some situations, a one-shot exec session could be closed about 5 minutes after the client's stdin closed, cutting off a command — such as a long build or test run — still running at that point. The session now stays open until the command actually finishes.

  • New repositories default their branch to main. Registering a repository without specifying a default branch now stores main instead of a blank branch, so the CLI and API show a real branch. Pass --default-branch (CLI) or default_branch (API) to choose another.

  • Register project repositories from the CLI. The new tektona repository command (alias repo) lists, adds, shows, and removes the git repositories a credential can unlock — e.g. tektona repository create --url https://gitlab.com/group/app. Previously this was only possible in the console or the SDK, so tektona git-credential create --repo … had no CLI way to register the repo it referenced.

  • Secret injection and outbound HTTP(S) now work immediately after a sandbox starts. Previously, the first web requests from a freshly created or resumed sandbox — including requests relying on egress secret injection or git credentials — could fail for a few seconds until the network configuration caught up, forcing a wait-and-retry. The configuration is now in place before the sandbox is reported running.

  • process run --shell runs shell one-liners. tektona sandbox process run -s <id> -- 'apt update && apt install -y nginx' runs the command line through a shell inside the sandbox (bash when the image has it, sh otherwise), so &&, pipes, and globs work. Without the flag, the command remains an exact argument vector.

  • More reliable hibernate and resume. In some situations, resuming a hibernated sandbox could lose its in-memory state; resume now reliably restores the sandbox exactly as it was paused.

  • More reliable full forks. In some situations, a full fork (disk + memory) could start without the source's in-memory state. During a full fork, connections into the source sandbox (shells, agent sessions) drop briefly and reconnect within a couple of seconds.

  • Better handling of failed pauses. In some situations, a failed pause could show the sandbox as paused or hold up later pauses; a failing pause now leaves the sandbox running and is retried on the next idle check.

2026-07-09

  • tektona ssh into a sleeping sandbox now wakes it for you. Running tektona ssh <id> against a paused sandbox shows a Resuming sandbox… indicator while it wakes and connects once it's ready, even if waking takes a little while.

  • process ls --autostart shows an accurate last-run state. Each autostart process now reflects its most recent run — never before it has started, then its real outcome once it finishes — instead of staying stuck on running.

2026-07-08

  • Refinements to sandbox process management. Following the launch, process ls now shows only running processes by default (newest first), with an AUTOSTART column marking autostart-managed processes and -a/--all to include finished ones; long commands are truncated to keep the table readable. process get and process logs keep working by name after a process finishes, and process stop reports already finished for a process that has ended rather than claiming to stop it. process run now returns a non-zero exit code when a command is killed or times out, so scripts and CI can tell it didn't finish cleanly. Process listings expose each running process's pid over the API and SDK, and process commands against a deleted sandbox now return a clear sandbox <id> not found.

  • tektona ssh <id> -- <command> keeps stderr separate from stdout. Command output over SSH now delivers stderr on its own stream, so 2>/dev/null and piping stdout alone behave as expected. Interactive shells are unchanged.

  • tektona sandbox delete lists multiple sandboxes one per line. The delete confirmation now prints each sandbox on its own line so you can review what's about to be deleted.

  • More reliable sandbox and process operations during platform updates. Creating, deleting, or managing a sandbox — and running process commands — could occasionally fail while the platform was being updated. These operations now retry automatically and succeed once the update settles.

2026-07-06

  • Run, stream, and manage processes inside a sandbox. Start one-off commands, background servers, and interactive shells from the CLI (tektona sandbox process), the HTTP API, the TypeScript SDK, or in-sandbox with tektonactl process. Processes belong to the sandbox — they survive disconnects and are addressable by id or a memorable name (auto-generated, like quantum-phoenix, when you don't set one) — with live log tailing, attach/reattach, graceful stop and signals, autostart on every boot, and per-process control over pause behavior and keeping the sandbox awake.

2026-07-05

  • API responses now include rate-limit headers. Requests are rate limited per user/API key — and per client IP before authentication — with generous defaults that normal CLI, SDK, and automation traffic stays under, plus a separate tighter budget for sandbox creation. Each response carries X-RateLimit-Limit-{throttler}, X-RateLimit-Remaining-{throttler}, and X-RateLimit-Reset-{throttler} (throttler = general, sandbox-create, or ip) describing your current budget. Exceeding a limit returns 429 Too Many Requests with a Retry-After header; the TypeScript SDK's RateLimitError now exposes throttler, limit, remaining, and resetSeconds.

  • The CLI tells you when you hit a rate limit and retries for you. When the API throttles a request, tektona prints a notice with the server-suggested wait, then retries automatically after it (a few attempts). If the requested wait is long, the command fails right away with the time to retry instead of hanging.

2026-07-04

  • Stored secrets are now cryptographically bound to their identity. Encrypted secrets, git credentials, and registry credentials are now sealed so a stored value cannot be moved to another record and still decrypt. Values written before this change keep working, and nothing needs to be re-created.

2026-07-04

  • Private preview URLs no longer leak their access token via the browser Referer. Responses served over a token-bearing preview URL now send Referrer-Policy: no-referrer, so cross-origin requests made by the previewed page don't carry the token-containing hostname to third-party hosts.

2026-07-03

  • Resuming a sandbox right after pausing it is now reliable. Waking a sandbox during the brief window when its paused state is still uploading no longer leaves it stuck or flipped to an error state, and later actions like reboot keep working.

  • Reboot is now orderly and no longer loses recently written files. tektona sandbox reboot now stops your processes (SIGTERM, then SIGKILL) and flushes the filesystem before restarting, so files written shortly before the reboot survive it; an unresponsive sandbox falls back to a hard reset. A new tektona sandbox reset performs an unconditional hard reset (like pulling the power) for an unresponsive sandbox — un-synced files may be lost.

  • Deleting a project now works once its sandboxes are gone, and keeps usage history. A project can be deleted after all of its sandboxes are deleted; sandboxes that still exist — running or paused — must be deleted first. Deletion now preserves the project's past sandbox usage for billing history instead of erasing it, and the project's name becomes available for reuse.

  • Lifecycle settings can be set on tektona sandbox create. Pass --auto-pause, --auto-pause-mode, --auto-resume, or --auto-delete at create time instead of creating first and running sandbox lifecycle; any you omit inherit the project/platform default.

  • Slimmer tektona sandbox ls output. The egress proxy profile column moved to the --wide view to keep the default listing narrow.

  • Sandboxes now auto-pause after 15 minutes idle by default. New sandboxes hibernate after 15 minutes with no activity and auto-resume on the next access. Compute billing stops at the idle deadline even if the pause itself lands a little later. Change or disable it per sandbox or per project.

  • Auto-delete is available as an opt-in retention window. Off by default — paused sandboxes are kept until you delete them. Set an auto-delete window per sandbox or per project to delete a paused sandbox that long after it was paused.

  • Lifecycle settings are now three-tier. Auto-pause, pause mode, auto-resume, and auto-delete resolve from a per-sandbox override, then the project default, then the platform default — each set to a value, never, or inherit. Manage them in the console, API, or CLI: tektona sandbox get shows the effective values and which tier supplied each, tektona sandbox lifecycle sets a sandbox's own overrides, and the new tektona project lifecycle-defaults sets project-wide defaults.

  • Paused sandboxes wake on any access. Opening an SSH or VNC session, loading a preview URL, or sending an agent request to a paused sandbox now resumes it automatically — previously only SSH and VNC woke it.

  • Auto-pause no longer pauses sandboxes that are in use. Sandboxes now detect activity from live SSH, VNC, and terminal sessions, traffic to preview ports, agent activity, and outbound transfers, so the idle timer only counts genuinely idle time.

  • tektona sandbox get shows a clearer, fuller picture. Details are now grouped into sections (Network, Lifecycle, History) with the egress network policy and egress proxy profile always shown, the idle-lifecycle settings (auto-pause, auto-pause mode, auto-resume, auto-destroy), your sharing level and access, and — new — the last 50 state transitions. Use --history=N to change how many to show or --no-history to hide them.

  • tektona sandbox create now shows the egress network policy and egress proxy profile in its create summary.

  • API: the single-sandbox endpoint now returns project, sharing, and access. GET /v1/sandboxes/{id} now includes the sandbox's project, share_type, and your access level, matching what the list endpoint already returned. The project object (on get and list) also now carries the project's name (URL-safe identifier) and display_name; its slug field still returns the identifier but is deprecated — read name instead.

2026-07-02

  • New desktop and base image release (0.4.3). Installing a service with apt (e.g. nginx) now starts it automatically, just like on a regular Ubuntu machine — previously it stayed stopped with a policy-rc.d returned 101 notice until started by hand. Use it with tektona sandbox create -i ghcr.io/tektona-ai/desktop-x11:0.4.3.

  • Faster sandbox starts. Desktop-image sandboxes boot roughly twice as fast, and the first start from an image that isn't cached yet completes much sooner.

  • More reliable sandbox creation. Creates no longer occasionally stall for 30 seconds or fail spuriously during rapid create-and-delete bursts.

  • @tektona/sdk 0.3.0 — org/project sandbox settings moved (breaking). The default-sandbox-settings methods now live on the resource they configure: tek.org.getSandboxSettings() / updateSandboxSettings() and tek.project.getSandboxSettings() / updateSandboxSettings(). They were previously on tek.sandbox (getOrgSettings/updateOrgSettings/getProjectSettings/updateProjectSettings) — update those call sites.

2026-07-01

  • New desktop and base image release (0.4.2). Fixes the bundled installations of the Codex, opencode, and Claude AI coding agents so they run out of the box. Use it with tektona sandbox create -i ghcr.io/tektona-ai/desktop-x11:0.4.2.

  • Fixed sandbox create --env variables not being applied in some cases. Environment variables set at create time are now reliably available in the sandbox's shells.

  • @tektona/sdk 0.2.1 — the package now allows importing @tektona/sdk/package.json, so tools that read the package manifest (e.g. for the version) work again.

  • The TypeScript SDK (@tektona/sdk 0.2.0) now covers the full public API. Every resource is reachable from one client — sandboxes, secrets, projects, organizations, container registries, git repositories, git credentials, egress network policies, and locations — with create/list/get/update/delete where the API supports them. Highlights:

    • Set a default org/project once on the client (new Tektona({ org, project })) and override per call.
    • Every list() is cursor-paginated and returns a Page; listAll() auto-pages the whole set.
    • Full sandbox control — pause/resume/reboot/fork/resize, sharing & transfer, idle-lifecycle config, listening ports, transitions, and egress injection rules — with grouped sub-namespaces (sandbox.ssh, sandbox.vnc, sandbox.desktop, sandbox.preview).
    • Typed, instanceof-friendly errors.

2026-06-30

  • TypeScript SDK groundwork for full API coverage. @tektona/sdk now exposes a service per API resource off the client, supports a client-level default org/project scope (overridable per call), cursor pagination on every list() (plus a listAll() async iterator), and a richer typed error hierarchy (ApiError with statusCode; AuthenticationError 401 and AuthorizationError 403 are now distinct). New calls: sandbox.list/get/delete and location.list.

  • Manage organizations and projects from the CLI with tektona org and tektona project — list, show, create, and update orgs and projects, with an interactive wizard on a terminal or a fully scriptable flag-only path for agents and CI. Updating edits the display name and settings; the name is fixed once created.

  • get is the canonical verb for reading a single resourcetektona org get, tektona project get, tektona sandbox get, and tektonactl get (kubectl-style). The previous show/info names keep working as aliases, so existing commands and scripts are unaffected.

2026-06-29

  • One reference grammar for egress network policies and egress proxy profiles. Both --egress-network-policy and --egress-proxy-profile now use the same scope-keyword prefixes: tektona/<name> (system), org/<name> (organization), project/<name> (project), and a bare <name> as a strict alias for project/<name>. Breaking: a bare name now always means the project scope — previously a bare network-policy name resolved to the org and the project keyword was org/project/<name>. Existing sandboxes are migrated automatically so their effective egress is unchanged; use the explicit org/<name> form for an org-scoped resource. tektona egress-network-policy ls and info now also surface project-scoped policies.

  • Clearer error for an invalid egress network policy reference. Creating a sandbox (or setting a project/org default) with an egress network policy reference that isn't one of tektona/<name>, org/<name>, project/<name>, or a bare <name> is now rejected with a clear message instead of being accepted and silently falling back to no policy.

2026-06-28

  • Sandbox placement now accounts for disk. A sandbox's disk is reserved for it, so a sandbox is no longer started where it cannot keep the space it asked for. A paused sandbox does not tie up disk it is not using.

  • Faster first-time sandbox creation. The first create from an image Tektona has not seen before is quicker. Repeat creates from the same image are unaffected.

  • tektona sandbox cp accepts a bare sandbox id. You can now write tektona sandbox cp file.txt <sandbox-id> without the trailing colon; it uploads to the sandbox's working directory, the same as <sandbox-id>:.

2026-06-27

  • Cleaner CLI tables. CLI listings now print plain, borderless columns instead of boxed tables for easier reading.

  • Egress columns in the sandbox list. The sandbox list now includes each sandbox's egress network policy and attached egress proxy profile; the owner moved to the wide view.

  • Egress proxy profile in the sandbox API. Sandbox API responses now include the egress proxy profile attached to a sandbox. The egress network policy and egress proxy profile are returned as objects with a name (rather than a bare string), leaving room to carry more detail later.

  • tektona secret ls shows when each secret was last updated. The listing now includes an UPDATED column.

  • Clearer egress policy details. tektona egress-network-policy info now always lists the full allowed and denied entries for both domains and CIDRs — empty lists are shown explicitly as (none) instead of being hidden.

  • Clearer tektona egress-proxy ls output. The listing now auto-sizes its columns, marks the project default with a *, and shows each profile's rule domains (truncated with +N) instead of a bare rule count. The redundant scope column was dropped.

2026-06-26

  • Fixed sandbox egress sometimes failing after resume. Resuming a paused sandbox could leave its HTTP/HTTPS egress broken while DNS kept working. Egress now keeps working after a resume.

  • The network works the moment a sandbox is running. A sandbox is no longer reported as running until its network is actually usable, so tektona sandbox wait --state running followed immediately by network use (e.g. apt-get in CI) no longer fails with connection-refused. Sandboxes with a restrictive egress policy still start normally.

  • tektona ssh works from locked-down networks. Some networks (for example CI runners) only allow outbound web ports and block the default SSH port 2222, so tektona ssh, sandbox cp, and port-forwarding would time out. Tektona now also accepts SSH on 9443, and the CLI automatically picks a reachable port (preferring 9443, falling back to 2222) — update to the latest CLI to get it. Existing setups keep working unchanged.

2026-06-22

  • Sandboxes no longer lose egress after platform maintenance. Egress rules could silently stop being applied, so a sandbox lost its allowed domains without anything reporting it. Rules are now re-applied automatically.

  • Sandboxes no longer occasionally start with broken egress. A sandbox could come up unable to reach any allowed domain, with TLS connections refused. Egress now works on every start.

2026-06-19

  • Allowed domains no longer time out after a while. Long-running sandboxes could intermittently lose connectivity to a still-allowed domain (connections hanging or timing out) once the domain's DNS record expired, because the resolved IP was dropped from the egress allowlist a moment before it was renewed. Allowed IPs are now held with a grace margin so re-resolution refreshes them in time, keeping allowed domains continuously reachable.

2026-06-10

  • Edit a git credential. You can now update a git credential's token, repositories, forge, and display name from the console or with the new tektona git-credential CLI. Each credential also gets a stable slug-style name (unique per scope, fixed after create) that the CLI uses to address it, and a rotated token takes effect on running sandboxes within a few seconds.

  • Update a secret's value in place. tektona secret set <key> now updates an existing secret instead of erroring; the new value is re-injected into running sandboxes' egress traffic within a few seconds, with no recreate or pause/resume.

  • Reboot no longer intermittently fails. tektona sandbox reboot could occasionally return an error (or appear to hang) even though the sandbox had come back up. Reboot now reports success once the sandbox is running again.

  • Private registry image builds. Sandboxes can now pull base images from private registries you've configured for the project; the build authenticates with the registry credential instead of failing anonymously.

  • Git credentials take an explicit forge. Creating a git credential now requires a forge field (github or gitlab) instead of the old kind; the backend no longer infers the forge from the repository host. A credential still unlocks one or more registered project repositories with a single token, and the token is never returned by the API.

  • Git credentials rely on your egress network policy for reachability. A git credential authenticates the request but no longer implicitly opens the forge host. The project's egress network policy must allow it (for example github.com or gitlab.com), otherwise the sandbox cannot reach the repository.

  • Egress config applies to running sandboxes. Editing an egress network policy (reachable domains) or an egress proxy profile (injection rules) now takes effect on already-running sandboxes within a few seconds, with no recreate or pause/resume needed. Adding the first proxy rule to a sandbox that started without one begins injection live, and newly allowed domains become reachable live.

  • Console. You can now update a secret's value from the Secrets page.

  • Console. Added project Secrets, Egress Proxy Profiles, and Git Credentials tabs.

  • Console. Egress proxy profiles now open a details view showing their injection rules.

  • Console. Egress proxy profiles can now be edited after creation from the profile details page, including adding, editing, and removing rules and setting a profile as the project default.

  • Sandboxes verify TLS for passthrough hosts. Sandboxes now trust both the egress proxy CA and the image's public root certificates, so tools like git and curl can verify hosts that are not injected. Previously only injected hosts verified, so cloning a public GitHub repository failed with a certificate error.

2026-06-09

  • Dashboard disk stats fix. A sandbox that failed no longer keeps counting toward "disk allocated" or accruing disk GiB-hours afterwards. Disk now stops accruing the moment the sandbox reaches its final state.

  • Secrets. Secrets can now be stored at org, project, or personal scope and injected into sandbox egress traffic without ever entering the sandbox. Resolution follows personal → project → org precedence.

  • Egress proxy profiles. Named profiles bundle injection rules and attach to sandboxes (a project default or tektona sandbox create --egress-proxy-profile <name>).

  • New CLI. tektona secret set/ls/rm and tektona egress-proxy apply/ls/show/rm (plus egress-proxy rule add).

  • Git tokens. Git tokens are now injected at the egress boundary, scoped to the exact repos they unlock, so the token never enters the sandbox.

  • tektonactl ca cert. Prints the sandbox's egress CA so in-sandbox tools with their own trust store (e.g. Java keytool) can import it.

  • Breaking: "network policy" renamed to "egress network policy." The API routes (/v1/.../egress-network-policies), the sandbox field (egress_network_policy), the CLI command (tektona egress-network-policy) and flag (--egress-network-policy, alias --egress-policy, with the old --network flag removed), and the SDK surface all use the new name. There is no compatibility shim.

2026-06-08

  • Renamed concept. "Network Policy" is now called "Egress Network Policy" across the console, docs, and CLI help text.

2026-06-05

  • View deleted sandboxes. Deleted sandboxes can now be surfaced with an include_deleted option and a toggle in the console, instead of disappearing from view.

2026-06-04

  • Sandbox ownership & sharing. Every sandbox now has an explicit owner and can be shared with project members across a use / manage access ladder, with ownership transfer and admin oversight.
  • Org and project sandbox dashboards. New console dashboards summarize sandbox activity per organization and per project.
  • Repo-scoped git credentials. A single git token can now cover many repositories through path matching, project repositories can be referenced directly, and credential endpoints are unified under one scope.
  • Cleaner sandbox ls. The owner column is hidden when listing your own sandboxes, and ownership and share-type columns moved after the core columns.
  • Admin sandbox tooling. New admin sandbox info shows details for any sandbox, and admin sandbox ls now includes the image.

2026-06-03

  • Exact sandbox disk sizing. Sandbox disks are provisioned at exactly the requested size, and creation is rejected with a clear message (including the image size) when the image is larger than the requested disk.
  • Console fixes. Locked dark mode, corrected the VNC viewport height, and fixed the in-browser terminal scrollbar.

2026-06-02

  • Reboot a sandbox. New tektona sandbox reboot performs a cold reboot in place, preserving the committed disk and IP address.
  • Simpler sandbox create. Removed the --verbose flag.

2026-05-30

  • Resize a sandbox. New tektona sandbox resize and resize API, with live disk growth applied to running sandboxes.
  • Egress network policy deny-lists. Egress network policies support domain and CIDR deny-lists alongside allow-lists, editable from the console.
  • List listening ports. A sandbox's listening ports can now be listed, with the owning process resolved for each one.

2026-05-29

  • Copy files to and from a sandbox. New tektona sandbox cp for SFTP-based local ⇄ sandbox file copy.

  • List projects non-interactively. New tektona project ls.

  • Sessions start in the image working directory. Shell, exec, and SFTP sessions now land in the image's WORKDIR, with a sensible $HOME fallback.

  • CLI update notice. The CLI tells you when a newer version is available.

On this page