Changelog
Notable releases of Nodal-Agents, newest first.
Notable releases, newest first — this page is the repository's CHANGELOG.md,
generated at build time. Pre-1.0: minor versions can carry breaking changes.
Every release is published to npm as nodal-agents and tagged on GitHub —
upgrade in place with nodal-agents update (your data is preserved).
v0.9.3 — Sep 25, 2026
A release about long runs and about who decides. A turn no longer dies on a
300 s wall clock: it streams under two silence clocks, resumes from what it had
written, and Stop really stops it, in a job as in the chat. What a run may cost
and how long it may work is now set by the workspace, and each agent has its
own budget, API providers and coding CLIs counted together; a run stopped by a
budget delivers what it wrote instead of losing it. A shell command is judged
per kind of action, and the owner answers an approval without leaving the
conversation. Agents can also write audio files from text, and the Delivered
card now shows, plays and downloads a delivered image, track or video. Twenty
pull requests, six migrations (0123 to 0128).
Upgrading: what changes for you
MAX_COST_PER_JOB_USDis no longer read. The ceiling of one run lives in Settings, Safety, Run budget (default $2, the value the runner applied until now; 0 means none). A runner that still has the variable logsmax_cost_env_ignored.- The coding-CLI daily budget becomes the agent's daily budget, and only for agents it applied to (CLI runtime or code-task tool). It now also counts the agent's API calls. Agents on the Codex runtime were exempt before and now get an active ceiling ($10 a day by default): check their Settings, Budget.
- "Run commands" is no longer a Yolo switch. It has the three choices of
every other tool (run without asking, ask, block), and each agent has a shell
checklist per kind of action. Agents that were on Yolo keep running every
kind without asking (migration
0125).
Long runs
- A turn streams under two silence clocks instead of one 300 s wall clock: the wait for the first token (120 s, longer on a large context or a high reasoning effort) and the silence between tokens (60 s). Reasoning counts as activity; a local endpoint has neither clock. A turn cut mid-writing resumes from its partial text instead of being replayed identically. (#449)
- Stop stops. In the chat, Send becomes Stop while the agent answers, and Stop ends the answer, including on the Claude Code and Codex runtimes. (#459)
- Chat replies run under the same clocks as a job turn and leave their
llm_callsrow, so a long reply is observed and a mute one ends. (#466) - A page opened while the agent is answering shows the answer as it is written, instead of hiding it until it is finished. (#502)
- An error the provider sends as a plain object keeps its message and code: it is retried when it should be, and never said as "[object Object]". (#479)
Budgets
- The workspace sets what a run may cost and how long it may work (Settings, Safety, Run budget). A stop on a budget delivers what the run wrote, then a line saying why it stopped. An agent can set its own wait for the first word. (#495)
- One budget per agent, daily and monthly, in the agent's Settings, with a warning threshold. API providers and coding CLIs are counted together, in the workspace time zone. (#496)
Control
- A shell command is judged per kind of action read from the programs it runs: inline code, deleting files, installing software, downloading, stopping programs, system settings. Each kind is allowed, asked or never, per agent. It is a reading of the command, not a sandbox: it does not follow what a script does once it runs. (#476, #497)
- "Run commands" has the three choices of every other tool. (#481)
- A pending approval is answered in the conversation, with the same card as the Approvals page. (#482)
- "Never for this agent" on an approval card refuses the call and sets that kind of action to Never, once confirmed. (#486)
Files and media
- Agents write audio files from text with the new
generate_speechtool (Gemini 3.8 Flash TTS and Flash Lite TTS through OpenRouter, WAV output). It is switched on per agent in the Tools tab and uses the workspace OpenRouter key. The delivery proof reads a WAV by its header. (#488, #489) - The Delivered card shows, plays and downloads a delivered image, audio or video file. The file is served only if that run wrote it, inside the workspace folders, from a closed list of types. (#493)
- Choosing a folder in Browse… adds it to the agent at once; no second Add click. (#467)
- A run opened from the MCP folder keeps the sidebar on Work. (#500)
Under the hood
- The
.pgtest files share one Postgres per run, one fresh database each, so the full suite no longer fails at random. (#499) - A test that compared a Windows short path with a real path is fixed; the Windows CI is green again. (#503)
- A shared link to the docs site shows a preview image. (#460)
v0.9.2 — Sep 23, 2026
A release about saying the right thing. A run whose agent answered through
Telegram and acknowledged with a status showed, under its own header, a
delegation line replayed from a turn of a week earlier: the page repeated the
last thing said in the transcript instead of the answer that was delivered. Both
halves of that are fixed, in the runner and on the page. The model catalogue
catches up with what OpenRouter actually serves, fourteen models in and three
dead identifiers out of the picker; an agent already set to one of those three
keeps getting a 404 until its owner picks a model that is served. And the
documentation now says the words a person types, which is what the in-product
search scores on. Fourteen pull requests, one migration
(0122_entities_drop_memory_curation_enabled).
Models
- Fourteen models join the OpenRouter catalogue. Xiaomi MiMo V2.6 Flash, Pro and Pro UltraSpeed, GLM 5.3 FlashX, Grok 4.6 and 4.7, DeepSeek V4 Pro and V4.1 Flash, GPT-5.6 Sol, Sol Pro and Terra, GPT-6 Astra and Astra Pro, and Claude Fable 5.1. Every window, price, modality and capability is read off OpenRouter's own API rather than typed, and each entry says in a comment which call answered it. (#413, #430)
- Three Anthropic identifiers OpenRouter does not serve leave the catalogue.
claude-opus-4.7-fast,4.8-fastand5-fastwere offered in the picker and returned a 404 to any agent set to one: OpenRouter lists none of them and serves no endpoint for them. The three choices are gone from the picker; an agent already set to one still gets a 404 until its owner chooses a model that is served. Their non-fast siblings stay, and a test pins both facts. (#429)
Runs and pages
- A run's result comes from its own turn. A turn that answers through a messaging tool and acknowledges with a status writes no text of its own, and the reader that fills an empty result took the last assistant text in the transcript, which starts with the replayed thread history. Since 15 September a Telegram turn of that shape could inherit an older delegation ledger line as its result. Both readers now work on the slice of the transcript that belongs to the current turn. (#427)
- The run page reads the delivered result, not the last announcement. The page was never given the result to read, so it fell back to the last prose of the run. On a run that published its answer and then said "I'm posting it now", the reply is what reads under the header and the announcement stays in the activity. (#431)
- The Memory page says what its agent chips do: Written by. The row filters by the agent that wrote the fact, and read as an assignment. The default chip says Anyone. (#428)
- History group headers and project shelf rows use the tighter spacing they were designed with. 8px of vertical padding instead of 12; the base padding used to override what each row asked for. (#433)
Files and projects
- The first manifest of a new repository makes it a code project. Writing a
package.jsoninto an empty folder left it classified as a plain folder until something else was written, because only the folder's existing contents were read. The file being written is now read too. (#435) - The workspace probe and the checkpoints resolve git before spawning it. Two
callers still launched
gitby its bare name over a folder agents write in. Both resolve the binary the way the rest of the product already does. With no git on the machine, the probe declines and renders nothing, and the snapshot store fails loud with the message the owner already saw. (#436)
Documentation and site
- The documentation says the words a person types. The in-product
nodal_docstool scores on the vocabulary of the pages themselves, so "remember something for later" and "how do I approve a command" reached the wrong page or none. The memory concept page, the shell-commands guide and the dashboard reference now carry those phrasings in their own headings and leads, rather than a synonym list hidden in the tool. (#437) - The changelog page of the site is this file. It was a hand-kept copy that
stopped at 0.9.0 while the repository carried 0.9.1, because a release had to
write the same entries twice. The page is now generated from
CHANGELOG.mdbefore every docs build, like the reference pages. (#432)
Upgrade
- One migration,
0122_entities_drop_memory_curation_enabled. The memory curator loses a per-workspace switch no screen ever exposed; the global kill-switch and the per-fact pin remain the two ways to hold it back.nodal-agents updateapplies it, and there is nothing to do by hand. (#418)
Under the hood
- Two end-to-end assertions catch up with decisions already shipped, and the documentation site is measured like every other package. (#407, #408)
v0.9.1 — Sep 21, 2026
A release about the product knowing itself. Asked on a fresh install whether Telegram could be configured, the agent answered that Telegram was not supported and offered to build an MCP server, while Telegram ships with its own tab in that agent's settings. The documentation is now a knowledge base every agent can read, with the reflex to read it before calling anything impossible, and the prompt names the four messaging channels and the two kinds of automation.
The rest is about seeing what is happening and being able to stop it. A Stop
button sits on the three screens where a person actually watches a run, the rail
carries a dot while something is live, a delivered file waiting for an eye is
counted in the attention pill, and a command that left nothing observable is said
rather than passed over in silence. Settings shows what a workspace weighs and
how long its last safety snapshot took, before a refusal rather than after, and
the launcher refuses to serve a database a migration was skipped on and can
repair it. Twenty-one pull requests, two migrations
(0118_agent_jobs_deliverable_check_due and 0119_job_checkpoints_snapshot_ms).
A release about approvals, and about what the product says of its own work. On 21 September an owner answered "Always for this server" and the tool kept asking, because a narrower rule was deciding without any screen saying so. The approval card now shows the rules that decided, in the order the gate reads them, and they are changed right there. A request with no stated reason is not posed at all. A rule written during a run applies to the run it was answered on. A request nobody answers expires, and its job goes back to work. And a red proof reopens the run for one repair turn instead of ending on a failure nobody could act on.
Later the same day, thirty-eight more pull requests and two migrations, in the same release.
Approvals
- An approval request with no stated reason is not posed at all. (#359)
- The approval card shows the rules that decided, and lets you change them there. (#360)
- An approval card opens when it waits, and folds away once decided. (#365)
- The approval shield is warn coloured, and one caret folds the whole card. (#368)
- An approval rule written mid-run applies to the run it was answered on. (#374)
- The approval card has two states, Open and Close, and nothing between. (#381)
- An unanswered approval request expires, and its job goes back to work. (#384)
- The Approvals tab speaks to the owner, not to the model. (#387)
- A rule confined to a folder says which folder, and says what saving costs. (#390)
- A rule can be set on one tool of an MCP server, not only on the whole server. (#393)
- Trusting an MCP server says what it costs a folder-confined rule. (#403)
- Answering an approval clears the rail's count at once. (#339)
- The Approvals page follows the bar instead of going stale. (#348)
Delivery inset
- Stop where the person looks, a delivery inset that says Stopped, and no Open run to the page you are on. (#335)
- Working in the running colour while the job runs, and Stop at the top right of the box. (#337)
- Checks are counted while the run works, "no file change seen", and Open run is a button on the right. (#342)
- Each command in the delivery inset says why it ran. (#376)
- The delivery inset shows the diff of each created or modified file. (#380)
- The proof verdict is a word, not the colour of the check mark. (#383)
- The delivery inset says the proof passed after a repair, and counts the last try only. (#389)
- The file diff plates in the delivery inset run edge to edge. (#396)
- The "+N -M" of a file counts the diff the plaque draws, from one engine. (#397)
- Every command in the delivery inset says how it ended. (#398)
Runs and proof
- A red proof reopens the run for one repair turn before it completes. (#379)
- The repair turns after a failed proof are a workspace setting, next to what else bounds a run. (#392)
Projects
- The Projects page is called Projects, and a removed project is not on it. (#367)
- A hidden project can be forgotten, and its folder stays where it is. (#378)
- A forgotten project stays forgotten: its folder is excluded from detection. (#388)
Sidebar and rail
- The reading density toggle is gone: a thread opens folded, a run page opens unfolded. (#341)
- The rail's live dot moves to the right edge, beside the count. (#345)
- The Logs cell carries no live dot, and the count behind it goes too. (#351)
- No numbered badge on a channel folder. (#353)
- The unread dot takes the colour of activity, and red keeps what must be answered. (#355)
- The rail says Scheduled and Runs, with the icons the owner drew. (#400)
Quality portal
- The jobs in flight are cards in a Running column, not a strip. (#343)
- The Running column reads GitHub in the browser, not at build time. (#366)
Site
- Homepage: the hero's nav and column sit in the page container, only the picture bleeds. (#334)
- Homepage: the hero on the design's width with three pillars, a titled screens band, and one claim style on every section. (#336)
Upgrade
- Two migrations,
0120_excluded_project_pathsand0121_entities_proof_repair_attempts.nodal-agents updateapplies them, and there is nothing to do by hand.
The agent knows the platform it runs in
- The documentation ships with the product, and a tool reads it.
nodal_docsanswers a question with the two or three sections of the manual that address it, each with its page, its heading and a link. The index is built from the committed pages and travels inside the package next to the migrations, so a fresh clone answers without building anything first. The match is lexical, offline and deterministic, because this runs inside a model turn. The Telegram guide is corrected on the way: the bot token goes on the Channels tab, and the page that could not say where to click was the one the question was about. (#319) - The reflex to consult it, and channels and automations in the prompt. A
baseline skill,
platform-support, tells an agent that it runs inside Nodal-Agents and to read the documentation before declaring anything unsupported, impossible or in need of being built. It is injected only when the agent actually holds the tool it names, and it fails closed. The discoverability block now lists the messaging channels the agent is not yet bound to and the two kinds of automation, so "I cannot run on a schedule" stops being the answer to a question that has a screen behind it. An existing install needs nothing but a restart. (#329)
Watching a run, and stopping it
- A Stop button where a person watches a run. Cancelling used to mean finding
/jobs/[id], which is not where anyone watches work. One button now sits on the run page, on the thread while a turn is running and on a code session. It confirms in the product's own dialog and says what stopping means rather than promising a kill: the run and everything it delegated stop at the next check, and a model call already in flight finishes on its own. (#325) - The rail says what is running. Logs carries a beating dot while any run is live, Work carries one while any conversation it lists is live, and the cell's name carries the count for a reader who does not see colour. Both read the snapshot the sidebar already polls, on its own cadence: no second query, and no second truth. (#314)
- A deliverable waiting for a look is counted in the attention pill. The pill counted an approval pending and a question asked, and stopped there, because no column said that a deliverable awaited a human eye. One does now, written by the runner in the same transaction as the terminal status, so a crash cannot leave a run that delivered with nothing saying so. The wait is carried by the head of the chain, the run a person opens, and only opening that run or its thread clears it: a message that left on Telegram made nobody look at anything. Migration 0118. (#317)
- A command nobody saw is said. A turn whose only action was a shell command
with no constated write rendered nothing at all: no delivery inset, because it
is not work, and no note, because nothing was unclassified. The inset now
follows that turn too, names the command and marks it
nothing observed, and its header reads Ran instead of Delivered. Not "did nothing": what is missing is the observation, and the wording says that. (#327)
The product carries its own marks
- One logo, everywhere. The collie on the N replaces the letter tile of the rail and the mobile bar, the diamond of the first-run screen, and the terminal prompt on the login page, which told a person arriving at the product that it was a command-line tool. Three marks for one product became one, drawn by one component from one file, and the browser tab points at that same file. (#322)
- An empty section never ends with "See all", and PROJECTS gets a "+". "No Project Yet" followed by "See all" announced seeing all of nothing. The row is dropped only when the read answered that there are no rows; loading and a failed read keep it, which is exactly when opening the page by hand helps. The path to create is the "+" on the section title, the same one CRON and WEBHOOKS carry. (#315)
- The "+" on CRON and WEBHOOKS opens the creation form. It pointed at the page one was already looking at, so the click changed nothing. It now says which form to open, the page opens it on arrival, and closing the form drops the parameter so a reload does not reopen it. (#302)
- A row folds when it is narrow. In the "Skills attached" grid of an agent's Overview tab, a two-word name overflowed its column and drew its second line over the slug and the Open button; the connector rows of the same tab ran into the "on" pill the same way. The rule belongs to the row component rather than to each caller, and a browser journey measures the boxes. (#318)
What the owner sees before a refusal
- A workspace says what it weighs, and how long its last snapshot took. On the evening of 19 September a shared folder reached 3.3 GB, the safety snapshot blew its budget, every write was refused, and nothing on any screen had said the folder was growing. Both facts now sit under each workspace name in Settings, from the same measure the refusal uses, never a second one. A snapshot that succeeds leaves its duration behind now, which is the case worth seeing coming. A folder that does not exist yet, one that cannot be read and a snapshot that was never timed each get their own sentence instead of a zero. Migration 0119. (#324)
- The launcher refuses to serve a database a migration was skipped on.
Drizzle's migrator compares each entry against the last applied row, so a
migration merged after a more recent one is skipped in silence and for good.
That is how a table lost a column on 20 September with nothing at boot saying
why. At every boot the journal is now read against the applied history: any gap
is named, Postgres is stopped, and the refusal carries the exact command to
repair.
nodal-agents up --repair-migrationsapplies the missing entries in order, each in its own transaction, and reads the check again rather than assuming it worked. (#323)
The site, and the documentation
- The homepage opens on a hero band. The illustration fills a full-bleed
section, with the version pill, the two-line title, the install terminal and
the two buttons held to the left so the picture keeps its right half, and the
nav sitting on the illustration as the handed-over design composes it. Every
value that design states lands at 1440 and travels by
clamp()on other widths. The version on the pill is read from the published package and never typed. The site also took the new logo, and the two product screenshots were retaken on 0.9.0 at the same size. (#305, #307, #309, #320) - The documentation is brought back up to the product. It had not moved since 0.8.6, and six releases had landed since. Thirty-one hand-written pages were read sentence by sentence against the code, twenty-seven were corrected, and two concept pages were added for what was documented nowhere: what proves a run, and what a project is. Five reference sections that answered 404 now have an index, written by the generator from its own output, so the list cannot go stale. (#304)
The CI, and the quality portal
- The CI is split, and a pull request answers in eight minutes. One
sequential job needed twenty-three minutes to reach the build and was then
cancelled by its own budget on a green tree. It becomes checks, five test
shards and a build, each with its own cache lineage and a budget set at twice
its measurement, so "the build broke" and "the suite grew" are two different
red marks. The Windows job moves to pushes on
mainand a nightly, having cost twenty-nine minutes on every pull request without ever finding a fault the Linux job had missed. Wall clock, first job started to last job finished: eight minutes twenty. (#312) - A deploy of
mainis never dropped, and the portal says when the site was last deployed. GitHub keeps one pending run per concurrency group, so the deploy of a merge was cancelled by the run of that same pull request closing, and nothing said so. The one gate that could lose a deploy for good is removed, with the reasoning written beside it. The portal now carries a line saying when the site was last deployed, from which commit and by which event, and what happened to the runs since. The commit is named only for a push run, the only event whose recorded head is the commit that was built. (#313, #321) - The quality portal shows the jobs in flight. The board is derived from
issues and pull requests, so a morning with every issue closed showed nothing
while three review passes, six CI watchers and a forty-minute
release:checkwere running. A strip above the Kanban now names each job, where it runs, since when and what it waits for. A source that did not answer says so, and is never rendered as nothing running: an empty strip means the machine is idle only when every source spoke. (#326)
v0.9.0 — Sep 20, 2026
A release about the shape of the product. The sidebar became a rail of the owner's five boards with a panel for the active one, settings became a list where each setting opens beside it, a project opens on its conversations with its folder docked to the right, and the screen the product opens on is now an empty conversation rather than a dashboard. Back links were taken out everywhere, by the owner's decision, because the sidebar already says where you are.
Underneath, a run's delivered files are read from git rather than from what the
agent said it wrote, a run records how its own result was produced, a reviewer's
own commands are recorded as proof of the work they reviewed, and two guards were
added against work the product was paying for twice. Thirty-seven pull requests,
seven migrations (0111_agent_may_change_team through
0117_agent_jobs_result_kind).
The sidebar, and the screens it opens onto
- A rail of five boards, each opening its own panel. The single column of 0.8.11 becomes a rail whose cells are the owner's five boards, Work, Agents, Run, Approvals and Settings, each opening a 300px panel; Logs navigates and Help opens the documentation. The active board is derived from the route and from nothing else, so two tabs on the same address show the same panel and a shared link opens what it promises. The sections that exist only in the database are read through one bounded shared reader on the sidebar's single cadence, and a project in the list says whether it carries an unread conversation. (#235, #279)
- "See all" outlives an empty list, wherever a section carries it permanently: on a fresh install the workspaces page was reachable from nowhere. And a settings row lights up when its own setting is the one open. The four rows point at one path with different query parameters, so comparing on the path lit all four and comparing on the whole address lit none; the rule reads the path, then every parameter the entry writes. (#279)
- An inspector docked to the right edge, which pushes the page.
DockedPanelis a third pattern next toDrawerandModal: no backdrop, no trap. The list on its left stays visible and stays clickable, so a reader walks from one row to the next without closing anything. (#233) - Settings is one list, and each setting opens in the panel. Eleven stacked
blocks become a filterable list in four families, Access, Safety, Workspace and
Advanced. Nothing is edited on the page itself. The open setting is carried in
the address (
/settings?open=network), and Cancel and Save sit at the bottom of the panel without a single form changing its logic. (#237) - A new conversation opens a centred empty thread, and that is the default
screen. The root route renders a conversation that has not started. No
conversation row is written before the first message, and none survives a failed
one, so a thread opened and closed without a word no longer sits in the inbox
forever. The Dashboard is unchanged and lives at
/dashboard. (#250) - Back links are removed everywhere. The owner's decision of 2026-09-19: "Remove the back buttons EVERYWHERE." The work bar now carries context and actions only, and you move through the product by the sidebar. (#243)
- One Switch, one look. The MCP server toggle read as disabled when it was on, because the component owned the geometry and every caller passed its own colours. Two colour languages coexisted; the component owns the look now. (#238)
Work is a folder you open
- Workspaces is the only projects page. One list, two kinds of row: a registered project, and a folder an agent wrote in that nobody declared, which can be registered or hidden. The row shows the four facts that help you find a project and nothing else. A registered row is dated by the day it entered the registry, not by the day its row happened to be written. (#225)
- A project opens on its activity, and its folder sits beside it. Opening a
project used to land in one conversation and hide every other story, including
the runs started from the CLI or from an MCP client. It now opens on one sorted
list of conversations and sessions. "Files & proof" stopped being a second
screen: it is a docked panel, open by default, and
/codegoes to Workspaces. (#226) - An automation opens on its own page. One route serves a schedule and a webhook alike. Header, settings card of five rows, the last ten runs with their cost over thirty days, and what a routine has remembered. "Scheduled" leaves the menu. (#224)
- Nodal can initialise git in a project folder. An option, off by default, offered in the New project form and in the project's settings. Nothing touches a folder without it. It exists because the git constat below is the only reading that sees what a command wrote without naming it, and someone who starts a project from Telegram has no repository to read. (#244)
What a run really wrote, and what really proved it
- A run says how its result was produced.
agent_jobs.resultheld the text a run delivered and nothing on the row said where that text came from, so two screens guessed, each in its own way and each wrong in a case already seen. The runner writes the fact when it writes the text, and both screens read it: aresult_kindcolumn with two values and no default, because the terminal gates do not hand over the same kind of text, and a default would have filed an orchestrator's compiled tasks under the same mark as an agent's own words. Migration 0117. (#276) - Writes are constated by git when the project is a repository. The runner
reads
git status --porcelainbefore a shell command or a harness run and again after it, and the delta is the constat. Arun_commandthat writes ten files without naming one used to produce, for the product, nothing at all. The Files block shows that list, the constat is stored rather than dying with the call, and the per-file label is git's own word, which can say "deleted" where a tool name could not. (#227) - A reviewer's verifications are recorded, and the verdict sits next to
"Delivered". On one run a reviewer ran six real browser scenarios and
verification_runsheld zero rows for the job; the only proof kept was the developer's own check that the JavaScript parses. A reviewer's commands now carry over to the work they reviewed. (#228) - The failure hint is persisted, so the screen reads the runner's own word. The runner already named the gesture a failure calls for as a typed field, and it died in memory for want of a column. The screen re-derived it from the error code, which worked while the mapping lived in two places. (#272)
- The thread's tool rows go through the audit-row redaction gate. The run page's rows had gone through it since 0.8.11; the thread masked two fields of three and let the tool input travel raw. The field is masked at the door rather than at the use, so a field added tomorrow is covered without anyone thinking about it. (#270)
- Every dot in the thread was grey. A server-rendered view read its colour
tables from two
'use client'modules, where an export is a client reference and not a value, so the fallback colour took over in silence. The unit tests imported the real modules and rendered green in front of it. (#268) - The thread's chat-or-work verdict reads the constated write. A terminal card counted a turn as work by the mere fact of existing. A card proves a command ran, never that it wrote anything, and that was the last place this reader still believed a declaration. It reads the constated rows now, and a command with none no longer decides work on its own. (#283)
- A review verdict is masked before it reaches a screen. Both readers of the recorded verdict parsed the tool output raw and let the reviewer's own free text travel unmasked onto four screens, while the same secret in the same row was masked everywhere else. A reviewer who quotes a failing command or a config path had put a bearer token on screen in clear. (#289)
- A refused command names the checkpoint's real cause. A checkpoint that cannot finish still refuses the write, which is the whole contract; what changes is what it tells the reader. The refusal carries a typed code and the facts measured at that moment, the workspace size, its file count and the limit, instead of one sentence for every cause. (#262)
- A write raises the project epoch, not only the intent. A proof was judged stale by comparing a project's epoch and its manifest on both sides of it, and neither witness saw the sequence where one job captures the epoch, proves the tree as it stands, and a second job writes invalid content in between. (#269)
Threads carry a person, and an answer as it is written
- An unread state per person and per thread. The product kept no read state at all, so the dot in front of a thread could only mean "waits for you, or running". A read belongs to whoever read: the thread the owner just opened is not read by a teammate. The marker is written when a thread is opened on the dashboard, and never because a message went out on a channel. (#223)
- The chat reply is shown as it is written. A dashboard turn returned its whole reply at once; it now appears word by word while the turn runs, through a route handler that repeats the server action's checks, because a server action cannot relay a stream. (#221)
- The thread's prose verdict rule reads the line after "Verdict". The rule claimed to read a verdict written on the line below that word, and read a renderer that returns only the first readable line of the first block, so the branch never fired. A reviewer who titles a section and puts the sentence under it had said their verdict, and hiding it was a lost line, not caution. It is only the fallback for delegates that recorded nothing, so repairing it costs nothing where a typed verdict exists. (#278)
Two guards against paying twice, and one record that travels whole
- The delegation outcome travels typed, not as text. A delegation record was typed between a parent and its own child and free text everywhere else, so a grandchild's failure reached the grandparent only as prose. The sub-tree's outcome now travels as a map written by the harness from its own bookkeeping, specialist by specialist, and a repair made elsewhere in the tree clears a failure that had travelled up. The sentence a reader sees is a rendering of that map, never a source anyone reads back. (#275)
- A second review of the same thing is refused, not run. A delegation is refused only when the same reviewer is asked for the same target and nothing completed in between. Every condition is read on rows, none on text similarity, and no recognisable target means no guard. An orchestrator that has a PR reviewed, has the findings fixed and asks again is asking about a target that changed, and goes through. (#220)
- An agent does not recompose its own team. A per-agent setting,
may_change_team, off by default: with it off the three team meta-tools are not in the list the runner computes, so the model never sees them. Every agent that already exists is turned off by the migration, including the orchestrator that rearranged two teams overnight on 2026-09-15. (#222)
Installing, and building
- The install names npm's script gate before it bites. npm skips the install
scripts of
@embedded-postgres/<platform>, the package carrying the Postgres binaries Nodal boots. The install page, the docs landing, the CLI reference, the self-hosting guide and the README now say what the warning block means and give the command;upsays it after the fact. (#257) - The web build's heap floor follows a measurement again. The floor doubled to 24 576 MB on 19 September because the build died and the number was raised until it stopped. The need had not doubled: the measured local peak is 13 069 MB, and the whole pack build fits on a 16 GB CI runner with no override at all. Every pack build now reports its own peak, so the next jump is visible the day it happens. (#277)
- Delegating expires the parent's cache, and the run says what that costs. A sequential delegation always outlasts a provider's prompt cache, so the parent re-pays its whole prefix at fresh-input rate on every resume, by construction, about a fifth of a run's bill. Nothing billed changes. The cost is read from the call itself, on six conditions, never estimated, and shown. Resuming a parent without resending its context is a separate ticket. (#266)
Chores, and the quality portal
- The minor findings of the #88 reviews, sorted and closed. The sixteen minor
findings of the fourteen after-the-fact reviews, plus two the owner left as
comments. Every line was found again by content on
mainrather than by the line number the report gave: several had moved and two no longer existed. (#273) apps/qais linted like every other package. Turbo runs a package's lint task only when the package declares one, and the portal declared none, so it was filed as nonexistent and passed over without a word. It held an ESLint error nobody saw. A guard now requires every workspace package to declare the script. (#253)- The root ESLint config and
apps/webcan no longer say two things. One is what a person runs by hand, the other is what CI runs, and they disagreed in both directions: the root config found 100 errors on the app where the package's own lint found none. A rule only one of them applies is a rule nobody sees. (#274) - A package left out of the coverage measurement says which, and why. A deliberate exclusion and a measurement that failed rendered identically, as an empty column. They are now four named states, the exclusion and its reason live in one place, and a failed measurement leaves a marker instead of vanishing. (#259)
- The browser journeys hold on to anchors, not to paint. Thirteen journeys still aimed at a layout class or a rendered word, and on 10 August one rounded corner becoming a rounder one turned eight of them red at once, silently, without a single feature being broken. Every element they aim at now carries a stable anchor, and the gestures that reach them are written once. It also repairs the screen proof of talking to an agent, red since the 19 September measurement. (#293)
- The
cijob gets the same 35-minute budget asci-windows. It had 25, and spent 23 of them before the build step started, so a run whose unit tests drifted by two minutes died on its own clock with every check green. (#294)
v0.8.11 — Sep 19, 2026
A release about reading a run without opening a chat. A run now has a page of its own, the same one whether it came from a schedule, from the Code screen or from an MCP client, and the thread reads a delegated review from the record the reviewer wrote rather than from a guess at its prose. The sidebar was redrawn on the owner's own list, and fourteen pull requests merged without a review in September were read after the fact; the four findings that still held are fixed here. No new capability; every change went through Reviewer C, and every finding was closed by a test that failed first.
A run is a board to follow, not a thread to read
- One page for every run.
/scheduled/<id>,/jobs/<id>and/code/<id>render the same page: a header card with the request, the agent, the origin, the model and seven figures (cost, duration, tokens in and out, cache reads, files changed, activity), then what was delivered, the review, the verification, the files of a code run, and the whole activity, always open. A run opens at the top and never scrolls itself. The old Code process detail and its private components are gone; the Code list links to the run page. - The run says which run it is. The full identifier sits under the header, selectable, with a copy button, on all three routes.
- The review is read once. The same run showed its verdicts from the Code screen and none from the MCP folder, because two loaders read two things. They now share one reader, ordered by the sequence the tool wrote in, parsed by the orchestration's own parser. A verdict carries the reviewer's full report, rendered in the Review block. When a run carries a recorded verdict, its own reply is not repeated above the block: the review is the answer.
- Audit rows are masked at the gate. The card, the raw output and the input of every tool row go through one redaction before any screen or summary sees them, on the run page and in the conversation thread alike.
- Real zero, real title. A cost or a duration that is genuinely zero
prints
0; a dash means absent. The header title is the first line of the request, cut at sixty characters, whole on hover.
The thread reads the verdict the reviewer recorded
- A delegation's head says the recorded verdict. Since the
review_verdicttool writes a typed record, the thread reads that row instead of the first line of the child's prose, which could say the opposite. The head readsApproved, orChanges requested · 2 blockers, 1 minor, only the severities that exist; the recorded summary sits in the body. A refusal after a success leaves the delegate with no verdict, as the reviewer meant. A row that breaks its own contract is logged and skipped, never a truncated verdict. - A child job carries its verdict and its redaction together. The delegate's result and error are masked like the parent's.
Channels, as drawn, and the sidebar on the owner's list
- An MCP folder in Channels. Runs started from outside Nodal, through the MCP server or the API, get their own folder, paged fifty at a time, with multi-select delete that refuses to orphan a live delegation. A task sent from the dashboard no longer lands there.
- The sidebar. Three hundred pixels wide, written once. "Spaces" reads "Workspaces", "Home" reads "Dashboard". LLM provider leads the Operate group, Settings follows Logs. The bottom group is "About Nodal-Agents", with Documentation, Join Discord (the Discord icon, the link icon to the right) and a link to the public quality board. The Code entry left the rail; its pages stay reachable by link. Channels folds with a chevron; each folder folds too, and open shows its five latest threads, bounded in SQL, with a "See all" arrow to the full list. A dot in front of each thread is red when the thread waits for you or has a run in progress, grey otherwise; there is no read state, and the dot does not pretend one. Every row of the rail has one shape, hover and selection running edge to edge, chevron included, and Channels and Nodal chats no longer share an icon.
- The Files block of a code run is the feed's file block. One diff plate, budgeted at eighty lines, with the redaction applied before the diff is extracted: a key written into a file no longer shows in Files.
- Unfolding never moves the view. A block opened by the reader grows in place, whatever its size; the follow-the-bottom mode switches off only if the reader has not scrolled since the gesture. Proven in the browser.
A failed run says the gesture it calls for
- A provider refusal names its remedy. When a provider rejects a request for a model, the failure carries a typed hint and the screen says "Try another model for this agent", on the run and in the delegation block. The code, its prefix and the hint live in one shared module. A job's error is redacted at the feed gate like its result.
- A restart never leaves a job processing with nobody on it. Jobs whose
runner stopped answering are reclaimed after a liveness window and marked
runner_restarted; a parent is woken only if the child it waited for is the one that died. - A late timeout keeps the turns already done. A single-turn timeout is replayed instead of discarding the whole job, and a provider failure that hides a timeout is recognised as one.
- Gemini gets the schema subset it accepts, on every route. Tool schemas are sanitised by model family on the OpenRouter route too.
- A 429 that asks to retry is transient. OpenRouter's "could not verify available credits" was read as an exhausted quota; the classifier now names its cases.
- A harness reports its writes, the disk confirms them. Files a CLI harness reports as written are checked on disk and scoped to that run; a deletion is confirmed by absence; a run that times out confirms nothing.
- A directory target no longer counts as a write.
- A recorded verdict is the job's deliverable. Tool calls carry a write sequence, and the delegation outcome carries the verdict the reviewer recorded, so the parent reads it instead of the prose.
The quality portal
- The board says where a review stands, read from the review-pass comments of each pull request, with what it could not parse said aloud.
- Done is a seven-day window, merged pull requests included, and the two dates are in UTC and say so.
- Every card says which release it belongs to, and the release chip
filters the board; the chip now hides the cards it sets aside (the card
rule's
display:flexused to beat thehiddenattribute). - The scope journey says which dialog it proves, and the unfold journey proves in the browser that a reader's scroll is kept.
Fourteen pull requests read after the fact
Merged on September 13 without a review when the quota was exhausted, they
were read by Reviewer C against today's main. Ten held. Four findings still
stood and are fixed here: a file write classified twice, before and after the
hook, so a project declared in between left its verification state unfindable;
the portal's guard against </script> in embedded JSON replaced < by <;
a capability or a journey that wavered without a single red had no link to
the run that holds its trace (the finding as reported, a link to a wrong run,
did not exist); a side-effect import swallowed a journey's header. The minor
findings are filed for 0.9.0.
v0.8.10 — Sep 16, 2026
A release about trust in what Nodal tells you. The launcher no longer kills a process it cannot identify, Postgres keeps a log so a crash can be read instead of guessed, an agent's work is credited only when the file on disk really changed, and the quality portal reports what nobody verified rather than painting it green. Every one of the six changes went through review passes before merging, and every finding was closed by a test that failed first.
The launcher stops what is yours, and nothing else
- No recorded pid is killed unproven.
upanddownused to signal the numbers they had written down at the last start. Windows recycles numbers, so a process that took the place of a dead worker could be killed in its stead. A pid is now signalled only when a fresh reading of the process table agrees on its name and its creation time. When the table cannot be read, nothing is signalled and the line says so. - A Postgres that is not yours survives a tree kill. A service Nodal started can start a Postgres of its own; the tree kill now walks around it.
uprefuses to kill a healthy stack it did not start. A live install on the configured ports was treated as leftovers to clean up. It is now named, with its pids, andupstops there.- Postgres keeps a log.
~/.nodalai/logs/postgres/, one directory per data directory, rotated daily. A backend crash can now be read instead of attributed by guesswork. downnever sits silently. The graceful stop has a budget; past it,downreports what the postmaster is still doing and the exact command to end it, for a pid it confirmed. A wrong database password fails at once instead of waiting three minutes with a live cluster left behind.
An agent's work is credited when the disk says so
- A write is recognised by its content. The fingerprint of a file carried its size and a timestamp whose resolution depends on the filesystem, up to two seconds on FAT. It now carries a hash of the content: a rewrite of the same size in the same second is seen.
- A refused read is not an absent file. A file the runner cannot open after the tool ran is neither credited nor invented; the line says it could not read it.
- A project is a project everywhere. Six places decided whether a folder was a code project; some asked for the manifest, some for the marker. They now share one rule, and a job is attached to the project the agent meant to write in, never to a registered subfolder of it. A folder you hid from the Code screen stays hidden in the agent's context too.
- The chat states how delegation happens instead of ordering it. The system prompt of the chat no longer contains an imperative the chat cannot carry out.
The quality portal says what nobody verified
- The portal checks the release itself. It reads what npm serves, what the repository carries, and names the gap, prerelease versions included. When npm does not answer, it says "unreachable at <time>" rather than showing a stale figure.
- A card opened by an agent must carry proof. Any issue or pull request
that bears the agent footer and no
## Verifiedsection with a command and its output is flagged, so "done" always comes with evidence. - A journey nobody plays is red, not grey. The portal reads the CI workflows themselves, comments excluded, to know which end-to-end journeys actually run; a journey no workflow plays is red, and a workflow the portal cannot read is said to be unreadable rather than counted as green. Two journeys only one machine could ever play were retired.
- The homepage reads the nightly measurement. The figures on the docs
homepage were typed by hand and compared to the live snapshot, which turned
mainred after every nightly measurement. They are now derived from the snapshot at build time, rounded down, and a missing or absurd figure stops the build naming the field. release:checkrefuses to run over a live dev stack. Building in place used to overwrite the running dashboard and empty the package folder. The check now probes the configured ports first, on both address families, and fails loud on an unreadable configuration instead of falling back to defaults.
Fixes
- End-to-end journeys clean up their own credentials, and only their own. A journey deleted every test credential of its type, including those of a run on another machine sharing the database. Each run now marks what it creates and removes only that.
- A delegated job that produced nothing is a failure, not a completed job. The parent no longer tells you the work is "launched" when the specialist returned no deliverable; the failure is delivered, in the harness's own words.
v0.8.9 — Sep 9, 2026
Nodal now proves what it builds. Until this release its verification engine had never run once — not in your install, not in any install. Agents also gained a purpose you choose at creation, and the chat thread stopped lying about which conversation it was in.
Your agents prove their own work
- Verification had never run. Not once. The engine existed, the screen existed, and the table that records proof had been empty since day one — in every install. The reason was a question no one wanted to answer: Nodal asked you which commands prove your project. You don't know, and it isn't your job to know. The agent that built the thing now declares how to check it, and Nodal runs that check when the work ends. A project turns green or red with the command that decided it, and the output that explains it.
- What an agent already ran is what it declares. These are not new powers: the syntax check, the build, the request against a server it started — it ran them while working. They were simply never recorded. Declaring them is now subject to the same approval rules as running them, so nothing slips past the gate you set.
- A deliverable is what was aimed at. A finished app used to be listed with twenty unverified deliverables, including archive folders it never touched — because a shell declares everything it could write. The guard stays that wide; the screen no longer does.
Every agent gets a purpose, at creation
- "What should this agent do?" Creating an agent starts from what you want it for, not from an empty form. Recipes pre-fill the model, the tools and the autonomy that fit — and everything stays editable, because nothing exists in the database until you click.
- Connectors are recommended, never imposed. A recipe suggests what it would use; you decide what it gets.
The chat thread tells the truth
- A chat row now opens the thread your next message will land in. It could
open another one: the screen picked the most recently touched thread while
the runner picks the most recently opened one. Typing
/new, then having earlier work finish, was enough to split them. - Channels and dashboard conversations are two lists. One row per chat — named after the person or room at the other end, not after the first message ever sent in it. A ten-day-old Telegram thread no longer carries the title of the app you asked for at its start.
- Threads scroll like a messenger. A thread opens at its last message and follows new ones, but only if you were already at the bottom — reading back through history stays put.
- An agent's own send is no longer mistaken for your reply. Sending a message returned an identifier that the model sometimes read as if you had typed it, and answered.
Scheduled runs remember what they did
- A routine keeps its own state. It used to store "what I last announced" as a memory, searched back in plain language — and a memory that got cleaned up made it announce a release twice on a public Discord. State is now a value it owns, read and written without a model.
- Memories stop filling with logbook entries. More than a third of an agent's memory was routine reports. Memory is what an agent knows about you.
Projects, and the folder they live in
- A project can no longer contain another project. Creating one on a folder that already holds projects produced two entries for the same work, one swallowing the other. Junctions and simultaneous creations are covered too.
- Naming a project's folder is optional. Leave it empty and it takes the project's name.
Faster, cheaper conversations
- A chat turn costs about half of what it did. Every turn silently made a second full-size call to re-ask a question whose answer depended on none of the context it was sending — roughly nine thousand tokens, on every message, including "hello". It now sends what the question actually needs.
Fixes
- Signing in over the local network works again. The dashboard answered 500 in LAN mode since v0.8.7.
- A chat turn's token count is no longer zero. Turns that don't go through a job had nothing to attribute their model calls to.
v0.8.8 — Aug 28, 2026
Your bot tokens stop being readable in the database, a Slack bot that loses its connection comes back on its own, and a database outage no longer destroys the log that would explain it.
Every credential is now encrypted at rest
- Bot tokens leave the clear. The Discord, Slack, WhatsApp and Telegram credentials — and the secret that authenticates your inbound webhooks — were the last values stored readable in the database. They are now encrypted with the same key as your API keys and OAuth credentials. Existing installs are migrated on the next start, in place, with nothing to do.
- Reading the database is no longer enough to use them. A webhook secret is compared after decryption, so a copy of your database does not let anyone fire your agents.
- A credential that cannot be decrypted says so. Restoring a backup without its key used to look exactly like "no bot configured here". It now fails loudly, naming the file to restore.
A Slack bot that drops comes back
- A revoked or rotated token no longer leaves an agent silently offline. When the connection died for good, nothing brought it back — the bot simply stopped answering, with a single line in a log nobody was reading. The connection is now re-established on its own, with the credentials as they stand at that moment, so rotating a token is enough to recover.
- Retries slow down instead of hammering. A token that is wrong forever is retried on a widening interval rather than every 30 seconds, and stops writing a line each time.
A database outage no longer erases its own explanation
- Repeated failures collapse. With the database unreachable, seventeen places wrote the same failure every 30 seconds — one real log had 7 412 such lines out of 61 359. Since logs rotate, a long outage pushed out the earlier lines that said why it started. The first failure is still logged in full, repeats are counted, and recovery says how many there were.
- Failures say what actually went wrong. A failing query used to be logged with the SQL and nothing else. The underlying reason — connection refused, authentication failed, a missing table — now appears with it.
Also
- GLM 5.3 Flash joins the model catalogue: a larger context than GLM 5.3, roughly nineteen times cheaper, and it can read images.
v0.8.7 — Aug 27, 2026
Your agents work in the folder you gave them, the Code tab shows what they actually built, and a coding CLI can now be an agent — Codex as well as Claude Code.
An agent writes where you told it to
- The folder you attach is the folder it uses. Four runs in a row had
delivered into the shared hand-off area while a real project folder sat
attached and unused. The cause was not disobedience: the system prompt
announced
## Workspace, singular, while the tools saw two — so the agent wrote to the only one it knew about, then reported a path that existed nowhere. The prompt now lists exactly what the tools have. - The shared workspace is named for what it is — the hand-off area between agents, not the place your deliverables go. Every agent keeps it: taking it away from agents that have their own folder would cut them off from the rest of the team.
- Git awareness reaches the right folder. The repository probe pointed at the shared area instead of the attached project.
The Code tab stops guessing
- It shows the folders your agents wrote in — and gives you two gestures:
rename and hide. Seven different definitions of "real code" were tried and
dropped, each breaking on a real case: file extensions, the agent's skills, a
package.jsonat the root, a checkbox on the agent, a checkbox on the folder. What replaces them is not an eighth guess. - Hiding reaches the agents too. A hidden project leaves the
## Runtimeblock of every agent in the workspace — not just the screen. The folder on disk is never touched, and one click brings it back. - The name you choose travels. Rename a project and your agents hear it under that name; "modify the client portal" finally designates something.
- A deleted folder stops producing a ghost project. Its session stays, under "Other sessions" — it did happen.
An agent can be a coding CLI — Codex included
- Codex is selectable next to Claude Code (agent → Overview → Model). The whole turn is served by that CLI: Nodal keeps the perimeter — folders, budget, approvals, channels — and relays its answer verbatim.
- Write mode works on Windows. It silently did nothing:
--sandbox workspace-writewas passed, the turn completed normally, and the model answered "the environment forbids all writing" with no error anywhere. Codex has no default confinement mechanism on Windows and must be told which one to use — a setting that lives in your own config, which Nodal deliberately ignores to keep your personal MCP servers out of its runs. Measured over four runs, one variable at a time; the confinement itself was re-measured before shipping the fix, and still refuses to write outside the working directory. - Codex reports no cost, and the screen says so instead of offering a dollar cap that cannot bound anything.
Agents stop reporting work they did not do
- An orchestrator announced "app delivered and reviewed by Reviewer C (2
passes)" four times in one day, naming the reviewer and the number of passes.
No delegation, no write, no file. It was not lying — it was completing a
pattern, because nothing in its history distinguished a real hand-off from an
invented one. Delegation now leaves a structural trace on the turn that made
it, so a turn without delegation carries no line at all — that contrast is
what was missing. The most useful case is
no tool used: the delegation happened and produced nothing, where prose can claim otherwise.
Hardening — twenty-eight review passes, twenty-four findings
The most serious ones were not in this release's new code. They were asleep in code that runs every day, and the new work brought them to light:
- Tool output was written to the audit trail in clear text — the content of every file a CLI session read, tokens included. The tool path had redacted it from the start; the runtime path never had, for Claude as well as Codex.
- A tool restriction could be lifted by switching harness. An agent with tools explicitly removed got them back when moved to a provider that cannot enforce that kind of ban. It now refuses the turn and says why.
- The single-writer lock could be bypassed by spelling.
C:/Commonandc:\commonproduced two separate locks, so two write sessions could edit the same files at once. - The anti-loop guard undercounted parallel tool calls — six simultaneous calls counted as one, so the more a model parallelised, the less budget it consumed.
- Also: locks leaking when prompt assembly failed, a killed turn reporting success, a failed file change counted as a changed file, and a session resuming with the other CLI's session id after a harness switch.
v0.8.6 — Aug 23, 2026
Your terminal can now hand work to your agents, and the dashboard follows you to your phone — without either path being able to brick your install.
Nodal as an MCP server, connectable in one line
claude mcp add nodal -- nodal-agents mcp serve. That is the whole setup. The newmcp serveCLI command resolves the database from your own install's config — noDATABASE_URLto know, no secret pasted into a client config, and it works on any npm install, not just a dev checkout. Settings shows the exact command with a Copy button.- One tool,
run_task. An external MCP client (your terminal, a coding agent) hands a request to your root agent — or a chosen agent by slug. The job runs through the normal loop: approvals, audit, budgets, and it can never touch the configuration tools. Off by default; a switch in Settings turns it on, and turning it off also cuts clients that are already connected. - Jobs start immediately.
run_taskwakes the worker on creation like every other channel — measured before the fix, an MCP job waited ~2½ minutes for the periodic sweep. - The server exits when your client disconnects. Closing stdin used to leave an orphan process holding Postgres connections; now both launchers close the pool and exit cleanly.
LAN access that cannot dead-end
- The LAN toggle keeps your config bootable. Switching to LAN used to be able to write a config the CLI refuses to start (network bind + no-password mode) — bricking the stack until a manual edit. The toggle now enables sign-in in the same write and says so.
- An existing install gets a claim screen, not a dead login. An install born without a password that switches to sign-in used to hit a wall: no password to sign in with, sign-up closed because the owner already exists. The login page now detects that state and offers Create your account — attached to the existing owner, so agents, settings and history stay exactly as they are. Validated end-to-end on a real migrated install, phone included.
- Copy buttons work over plain-HTTP LAN. The clipboard API is blocked on http; copy blocks now fall back so the button works exactly where LAN users need it.
Hardening
- The MCP job path was reviewed adversarially: the worker wake-up uses
127.0.0.1(neverlocalhost, which can silently resolve to IPv6 on Windows), rejected notifications are reported instead of swallowed, a deactivated agent is refused on every call, and a job insert that cannot report its id fails loud instead of answering success. - ~30 vulnerable transitive dependencies pinned to patched versions across the
workspace (hono, fast-uri, brace-expansion, js-yaml, nanoid, postcss, qs,
body-parser, ip-address, vite, turbo) — and the pnpm overrides that were
silently ignored since pnpm 10 moved to
pnpm-workspace.yaml, where they actually apply.
v0.8.5 — Aug 21, 2026
Fixes a package that broke itself weeks after it was published. If you installed 0.8.0 or 0.8.1, upgrade — a fresh install of either is dead on arrival today.
- Every install since Aug 3 got a dashboard that crashed before it rendered. The
published package ships a pre-compiled Next.js bundle, but declared 43 of its 46
runtime dependencies as floating
^ranges. The daynext@16.3.0was published, npm started pairing a 16.3 runtime with a 16.2.6 build, and the server died onTypeError: Cannot read properties of undefined (reading 'validationLevel')before any application code ran. Installs of 0.8.1 made before Aug 3 were unaffected. - A pre-compiled bundle now ships pinned to the exact versions it was built
against.
build-packrewrites all 46 runtime dependencies to their exact installed versions and fails the build if any range survives. A published package can no longer re-resolve its own runtime months later. - Next.js 16.3. The workspace, the pack and the docs site all move to 16.3.0, and
the pack was booted from an isolated install before release — every dashboard page
served, not just
/api/health.
Coding under your subscription
- Agents can delegate development work to a coding CLI. A new
code_tasktool hands a scoped task to Claude Code or Codex running under your own subscription, streams the work back, and records what was actually changed. Which CLI provider an agent uses is set per agent. - A Code tab. Mission control for everything your agents write: files touched, the diff of the selected file, the activity trail per turn, and token accounting broken down per model.
- Inference is now traceable. Every LLM call and tool call is persisted and wired to the transcript, so a run can be read back after the fact instead of guessed at.
Connectors and skills
- Cloudflare connector. Deploy what your agents build straight to Workers, with the compatibility date pinned on every deploy.
- ComfyUI in the MCP catalog, via the official local
comfy-mcpserver. - The review loop closes. Agents can request a review of their own work, and the verify-before-done skill picked up what the community version did better.
Security — the audit is fully closed
- A stranger can no longer take over your bot. A bot's username is public, and whoever messaged it first used to become its owner — so between pasting the token and sending your own first message, anyone who had found the bot could take your place, task your agent, and receive its approval cards. The first message now only requests ownership; you approve it from the dashboard. Telegram, Discord, Slack and WhatsApp.
- You see a skill update before it reaches your agents. Updating a community skill used to show a category ("content changes") for text that goes straight into the system prompt of every agent holding it. You now get the actual diff, and the install refuses if upstream changed after you read it — consent applies to the text you saw, not to whatever the repo holds at click time.
- Narrower Google access, and honest about the rest. Google Calendar no longer asks for permission to delete your calendars. Drive, Sheets and Docs still need full access for their tools to work at all — so the product now says exactly how far that reaches, in plain language, before Google's consent screen.
- Command injection through
cmd.execlosed — prompts are passed over stdin, never through a shell argument. Two independent reviews were run to closure.
Reliability
- Office tools, one format at a time. Spreadsheet, Document and Presentation editing are now separate skills. An agent that only touches workbooks stops carrying the Word and PowerPoint tool definitions — roughly 3,000 tokens off every turn, and 5,800 for a documents-only agent. The all-formats skill still exists.
- A failed start now tells you what failed. When a service doesn't come up, the
CLI names which one it is still waiting for, how long it has waited, and prints the
tail of that service's own log — where the actual cause has been sitting all along.
downalso verifies Postgres actually stopped before saying it did, and an orphaned Postgres is detected by its data directory rather than by an open port, which is the only way to see one that crashed during startup. - Ctrl+C is honoured from the moment Postgres starts, not five minutes later — interrupting a slow first boot no longer leaves a database running behind.
- Interrupting the dev server no longer strands a Next.js process on :3000.
Ctrl+C under a
.cmdlauncher makes Windows destroy the whole process group at once, the CLI's own cleanup included, mid-run — so cleanup cannot live there. The process tree is now recorded while the services are healthy, and the next start sweeps whatever survived, matching each process by creation time so a recycled PID is never mistaken for one of ours. It also reaches the deepest Turbopack worker, which holds no port and was therefore invisible to any port scan. uprefuses to kill a process it did not start. A port it wants may be held by your own dev server; it now says so and stops, instead of freeing the port by destroying someone else's work.downstopped crying wolf about Postgres.pg_ctl stopreturns when the signal is delivered, not when the postmaster is gone, so a stuck-database warning was firing on a database that was merely still on its way out.- Upgrades are tested against the real published package. A new smoke test
installs
nodal-agents@0.8.1from npm, configures it, then installs this build over the top and checks it boots, serves a real page, keepspg-data, and leaves the master key byte-identical — a changed key would make every stored credential permanently unreadable, silently. Fresh installs were already covered; the upgrade path, which is the one most people take, was not. - Windows is now in CI, alongside the Linux suite, the Playwright smoke and approvals specs, and the packaging smoke. Every finding from the 0.8.1 audit is closed.
v0.8.1 — Jul 31, 2026
Fixes a broken 0.8.0 package: on a fresh machine the dashboard could not render at all. If you installed 0.8.0, upgrade.
- Every dashboard page returned HTTP 500 on a fresh install. The published
0.8.0 tarball was missing 7 of the 40 server chunks its own pages require — the
Next.js standalone output dropped them while copying the build, and nothing in
the release pipeline compared what the build asks for against what ships. The
home, agents, jobs, memories, settings, logs, MCP, automations, approvals,
connectors, skills and onboarding pages were all affected.
/api/healthkept answering 200 throughout, so the CLI reported the runner as healthy. - The pack now ships the real build, and proves it.
build-packcopies the build's own.next/serverover the standalone copy, then fails loudly if any page still requires a chunk that isn't there.verify-installruns the same check against an installed copy, and both are covered by tests that now run in CI.
v0.8.0 — The Office Release · Jul 22, 2026
Your agents step into the workplace: they can now read your Outlook mail and author real Office documents, choose how hard they think, and the platform got a deep reliability pass — a remote tool server that hangs can no longer freeze an agent, and a stuttering agent can no longer flood your workspace with duplicates.
Highlights
- Microsoft 365, connected. A native Microsoft OAuth connector plus an Outlook mail toolset — your agents authenticate to M365 and work your mailbox, alongside the existing Google/Notion/Airtable connectors.
- Agents that author documents. A local office-authoring toolset builds real
.docx,.pptx, and.xlsxfiles — multi-section documents, slides, spreadsheets with charts and pivots — with loud, honest failures when something can't be produced (no silent half-files). - Choose how hard your agent thinks. Each agent gets a reasoning-effort setting (Auto / Off / low → max). The dashboard only offers the levels a model actually supports, and the choice applies per link of the fallback chain.
- Community skills, kept in sync — on your terms. Installed skills track upstream updates with a badge and a notification bell. Updates are a true three-way merge: if you've edited a skill's scripts locally and upstream also changed, you get a "Keep your version" option instead of a silent overwrite — and script authorization is revoked before any new file is written, so an update can never run un-vetted code. Skills also show where they came from (provenance) and a redesigned Tools view makes capabilities ON/OFF the primary control.
- Rate limits handled gracefully. LLM 429/529 responses are retried with a capped
Retry-Afterbackoff, and fast-failover to a fallback model when one is configured — no more a single provider hiccup killing a job.
Reliability & fixes
- A hung MCP server can't freeze your agent. Each remote tool-server connection gets its own network dispatcher, so one server whose event stream hangs no longer starves every tool call behind it (previously froze the whole agent for a minute per call).
- No more duplicate connectors. Creating a connector is now idempotent — an agent that stutters can't register the same connector eight times; a same-name duplicate fails loudly, while genuinely different instances (two accounts, same provider) still work.
- Delegated workers stay in their lane. A sub-agent no longer speaks on your channels or self-publishes status cards — delivery is the orchestrator's job — and it can no longer overwrite shared workflow templates in place.
- Routines get a safety net. Creating a scheduled routine that references a tool the agent doesn't have (or an ambiguous non-capability like "your state") now surfaces a warning at creation time.
- Honest delivery. A Telegram send that times out is no longer blindly retried (the message was likely delivered) — it's reported as ambiguous instead of duplicated.
- Leaner and faster. A pre-0.8 audit dropped dead tables and columns, added a missing index, batched N+1 queries, tightened fetch timeouts, and hardened process-level error handling. Typography moved fully onto the design-system token scale, and a new Table primitive standardizes data tables across the dashboard.
v0.7.95 — The Living Design System Release · Jul 16, 2026
The design system stopped being a snapshot and became a loop: the Figma library and the code are now mechanically tied together, checked by machine in both directions, and the last stock-browser UI (the select dropdown) was brought under the system.
Highlights
- Figma ↔ code, closed loop. All 73 shared UI components are mapped to the Figma library via Code Connect. A drift detector (
figma:drift) fails when a component, variant, or mapping diverges between the file and the repo, a DS lockfile (figma:ds-lock/ds-diff) captures the library state, and a lint guard blocks any arbitrary text size from sneaking past the type ramp. - The select menu finally speaks DS. Dropdowns use the new customizable-select standard (
appearance: base-select, Chrome/Edge): the open menu renders the design-system panel — paper surface, popover shadow, hover/selected states, the DS caret and check glyphs — with grouped options getting real section headers (styled<optgroup>legends). Other browsers keep their native picker, cleanly. Placeholders now grey out like every other field, and the field is pixel-checked against the Figma spec by machine (47 automated conformance checks). - Agents page, redesigned. Orchestrators are cards with their workers inside; dragging a worker across cards reassigns it. Delete moved to a type-to-confirm danger zone in Settings, and channel connections live in an in-page Channels tab.
- Pick where notifications land. Schedules and webhooks gained a "Notify via" selector — results go to the channel you chose (Telegram, Discord, Slack), and if that channel isn't connected the run fails loudly instead of falling back silently.
- Docs, audited page by page. Ten pages corrected against the real code, four end-to-end channel connection guides (Discord, Slack, WhatsApp, event triggers), and the README now documents the dev command that actually boots the stack.
- Fixes. Multichannel transport resolves the reply channel per conversation; incoming webhooks moved to
/wh/v1; an MCP server failing to load its tools no longer kills the whole job; sidebar labels no longer clip letter descenders; segmented controls no longer render a phantom empty segment; the dead "+ New connector" button is gone.
v0.7.9 — The Design System Release · Jul 13, 2026
The entire dashboard was brought under one enforced design system: every interactive element is now a shared component, consistency is guaranteed by CI rather than vigilance, and the whole thing was verified page by page in both themes. Plus the Google Gemini provider was rebuilt.
Highlights
- One visual language, enforced. Buttons, inputs, selects, badges, pills, menus, and modals were all migrated onto a set of shared UI primitives (245 hand-styled raw elements replaced). A lint rule now makes any raw
button/input/select/textareaoutside the component library fail the build, so the consistency can't silently drift back. Verified route by route, modal by modal, in light and dark. - Edit is always a modal. List editing no longer expands an inline accordion that pushes the page around; every edit opens a non-dismissable dialog (backdrop and Escape inert, Save/Cancel only), with one canonical footer template used site-wide — never zero, never two action rows.
- One row-action grammar. Per-row actions are icon-only squares with a mandatory tooltip; one concept = one verb = one icon; Delete/Disconnect/Uninstall is always last; no kebab menus for standard actions.
- End-to-end channel connection guides. Connecting an agent to Discord, Slack, WhatsApp, or Telegram now has a step-by-step guide — app/token setup, the ownership DM, the invite, and a "verify it works" check — written from the real handler code and shown in a cleanly formatted modal.
- Google Gemini, rebuilt. Native and OpenRouter Gemini paths were reworked: thought-signature round-tripping on tool-call parts (native returns a hard 400 without it), native thinking config, and a 3.x-only native catalog — so tool-calling agents run correctly on Gemini.
- Polish. The Settings page body was widened to match every other page (it had been a third narrower). Learned Skills now reuses the Skills page's per-agent assign/unassign toggle list, so you can finally unassign a learned skill. Slack logs a clear line on connection, and the file-sending tools resolve relative paths against the workspace.
v0.7.8 — The Everywhere Release · Jul 12, 2026
Your agents now live everywhere you already talk: Discord, Slack, and WhatsApp join Telegram. Plus event-triggered automations, agents that can no longer misstate what they did, and a new LLM provider. (Versions 0.7.6 and 0.7.7 were never published; their work ships here.)
Highlights
- Four messaging channels. Connect any agent to Discord (server mentions — including the role mentions Discord's autocomplete really inserts — DMs, and tappable approval buttons), Slack (Socket Mode, with a ready-to-paste app manifest right in the dashboard), and WhatsApp (QR pairing; unofficial-API caveat shown up front), alongside Telegram. Same security model everywhere: the first private conversation claims ownership, every other conversation needs your explicit approval, one owner per agent per channel — guaranteed by the database.
- Channels your agents actually know. Each agent sees which platforms it's connected to and can list the real servers, channels, and conversations it has access to (and which are approved) instead of denying a connection it has.
- Event triggers. Scheduled watchers know exactly "what's new since last run", carry a daily budget, and never overlap themselves; inbound webhooks let an external service start a job directly — timing-safe token check, payload isolation against prompt injection, rate-limited, managed from the dashboard.
- Agents can't deny their own actions anymore. Every exchange carries a structural record of the actions it performed; a delegating agent's thread shows what its sub-tasks actually did (tools called, result); and an agent that tries to assert platform state without checking gets stopped by the runtime and made to verify first.
- No more silent replies. The delivery guard that kept Telegram jobs honest now covers Discord and Slack too: a job physically cannot complete without its reply reaching your channel.
- Moonshot/Kimi, native. Kimi K2.6 and K2.7 Code as a first-class provider (thinking handled correctly, temperature managed server-side, and a strict tool-schema sanitizer that also protects Kimi models routed through OpenRouter). Model pickers now show which models can use tools, and a model that can't is blocked from the orchestrator role.
- Onboarding, revamped. The get-acquainted interview no longer shows up in your Chats afterwards, and setup ends with a real choice of messaging channels (brand icons, not emojis).
Approval authority (from the unpublished 0.7.6)
- Approval cards always go to the bot owner. When someone you've authorized to talk to your bot (a guest chat) triggers an action that needs approval, the ✅/❌ card now lands in your private chat with the bot — never in the guest's. Previously a guest authorized via a private DM could tap ✅ on their own gated action and self-approve; that hole is closed, and guest-triggered approvals in groups no longer leak the card into the group either. Your own actions are unaffected. (Per-guest capability profiles — restricting which actions a guest can even request — are designed and coming next.)
- Scheduled reports and Telegram deliveries reach you, not a group. A cron's success summary (and the dashboard's "send result via Telegram") used to target the last chat the agent was spoken to in — which a group message silently overwrote, so a report could leak into a group the moment someone @-mentioned the agent there. These now always deliver to the owner's private chat. A schedule can still be given an explicit target chat when you deliberately want it to post somewhere specific.
- Redesigned chat page. The conversation view is rebuilt from the ground up: messages in a centered column, agent replies with a lime avatar and a clean name/text layout, dark bubbles for your messages, a floating rounded input, and a distinct Conversations panel. Same speed, same features — just far nicer to look at, in both light and dark themes.
Communication security (full audit — 11 findings, all fixed)
- Agents can only message chats you've approved. Every Telegram send tool (messages, images, files, media) now verifies an explicit target chat against your approved-chats list — an agent can never message an arbitrary chat id it learned or guessed, and a delegated worker using the entity's bot token is held to the same list. Sends are also hard-capped per job, so a runaway loop can't spam you.
- Files an agent sends are confined to its own space.
send_file/send_imageused to read any path on the machine — a prompt-injected agent could exfiltrate config or credential files. Sources are now confined to the agent's workspaces, the skill store, and the temp dir; remote fetches are size-capped while streaming and blocked from link-local/metadata addresses, including via redirects. (Localhost stays available — your ComfyUI flow is untouched.) /askrespects each agent's own guest list. Relaying a message to a sibling agent (/ask finance-bot …) now requires the chat to be approved for the target agent — otherwise the owner gets a confirmation card naming that agent. A relay can never claim bot ownership.- One owner per bot, guaranteed. A database constraint makes duplicate owner claims impossible (a race between two first contacts could previously mint two co-owners); requester names on approval cards are sanitized against impersonation tricks; group mentions only trigger on exact @username matches and on replies to this bot.
Scheduled runs got smarter
- Cron jobs know "since when". Every scheduled run now carries its schedule's previous fire time in context ("Previous run of this schedule: …"), so a watcher-style agent can reliably act only on what's new — no more re-announcing old items or depending on fragile memory. The groundwork for event-triggered automations.
- Silent schedules can still speak up. A schedule with success-notifications off now lets its agent message you (the owner) when it decides something is worth saying — check a feed every 15 minutes, stay silent when nothing changed, ping you the moment something new appears.
- Freshly attached MCP servers work on their first job. Tool caches are stored complete at install time, and a server that fails to spawn is logged loudly instead of silently contributing zero tools.
v0.7.5 — The Trustworthy Orchestrator · Jul 8, 2026
A deep security-hardening wave, and a rebuilt approval & delegation experience — born from a forensic audit of real jobs that were slow, noisy, and occasionally wrong.
Approvals you can actually read — and that don't stall your job
- Approval cards now lead with the WHY. Three levels: the agent's stated purpose, then a plain-language impact line computed by the platform from the same classifiers the security gate uses (
Runs `rm` — destructive or heavy…/Runs `curl` → `head` — no destructive pattern detected), then the full technical detail. Identical on Telegram and the dashboard. - Approving is instant now. When you approve within ~2 minutes, the job continues in-process — no more full restart per approval (which cost 80-105 s each, MCP reconnections included). Approvals that take longer still suspend safely and resume as before.
- MCP servers connect lazily. A job no longer spawns every attached MCP server at startup — the toolset builds from a cache and a server is only spawned the first time one of its tools is actually called.
Delegation that delivers
- Delegated workers can deliver to you directly. A worker generating your image now inherits the entity's Telegram delivery tools and sends it itself — and the orchestrator is told
[livraison effectuée]so it never re-delivers or mislabels a delivered job as failed. - Orchestrator discipline, built in. Every orchestrator now carries intrinsic rules: pass parameters in the brief (don't do the worker's prep), never edit a shared template to smuggle in run parameters, never prescribe a tool the target agent doesn't have. Briefs naming an unavailable tool get an immediate warning.
- Shared files are protected. Overwriting an existing file in the shared workspace now requires approval (in both gated autonomy modes) — your saved templates can't be silently corrupted anymore. Your own attached workspaces (e.g. an Obsidian vault) are never gated, and creating new files never asks.
- Memory that corrects itself. Every agent must now mark a memory fact outdated the moment it proves false in practice (and save the verified correction); workers save durable discoveries before finishing; and "lessons" that micromanage other agents or ban discovery can no longer be saved.
Jobs page: conversations, not noise
- A 10-message chat with your agent is now one expandable 💬 row (exchanges, time range, aggregated cost) instead of ten identical job rows. Real work — tools, delegations — stays as full rows. Your existing history is regrouped automatically on upgrade.
Security hardening (full audit remediation)
- Secrets stay secret. MCP stdio subprocesses no longer inherit the full process environment (a third-party server could read your keys); API keys are redacted from tool-call audit logs; a CI secret-scanner blocks hardcoded credentials from ever reaching the repo again.
- Context windows respected per model. The runner now knows each model's real context window (catalog, stored value, or auto-probed from LM Studio) instead of assuming 128K — small local models no longer die silently mid-conversation, and overflow fails loud instead of corrupting.
- Plus: credential helpers moved out of the server-action surface,
create_mcp/attach_mcpgated as code execution, SSRF guards on MCP URLs, timeouts on all Google clients, security headers, signup closed once an owner exists, bounded results across a dozen adapters, and memory injection that finally counts as usage (your useful facts stop being archived by the curator).
v0.7.2 — Platform Audit Fixes · Jul 7, 2026
Twelve security and reliability fixes from an external-grade platform audit.
Highlights
- Delegation can't run away. Depth/fan-out caps enforced at the delegation point, cost-cap checkpoints mid-job, and cancellation is respected everywhere — a cancelled job stays cancelled.
- Authorization tightened. Approval endpoints check entity ownership (no cross-tenant IDOR), bearer tokens are entity-scoped, and the code-execution master switch is owner-only on LAN installs.
- Runtime hygiene. Child processes run with a scrubbed environment; per-model context limits and cost accounting checkpoints keep long jobs honest.
v0.7.0 — Scalable Memory · Jul 2, 2026
Memory that stays fast and relevant as it grows.
Highlights
- Full-text search inside agent memory. Facts are indexed (Postgres FTS + GIN) and ranked by real relevance to the task at hand, not just recency — the agent surfaces the right fact even with hundreds stored.
- A memory curator. A bounded background pass distills oversized facts, merges near-duplicates, archives what's provably unused, and re-scores importance from actual usage. On by default, per-entity switch.
- Pin what matters. Star a fact in the dashboard to lock its importance — the curator can never archive or down-rank what you pinned.
v0.6.8 — First-Run Experience · Jul 1, 2026
A fresh install lands on a capable agent that can search the web and matches the autonomy you asked for.
Highlights
- Web search out of the box.
web_searchis now a real, always-on tool: it uses your Tavily or Firecrawl connector if you have one, and otherwise falls back to a free, best-effort DuckDuckGo search — so a brand-new install can look things up immediately. If the free path is rate-limited or blocked, it says so and guides you to add a Tavily key for reliable results (and switches to it automatically once you do). - Onboarding sets your autonomy for real. The get-acquainted interview's "should I take initiative or stick to exactly what you ask?" answer now drives the agent's actual autonomy level — three modes (Take initiative / Balanced / Ask first), shown on a confirmation screen you can adjust, changeable anytime in Settings → Autonomy. It used to only land in memory. And the first agent now arrives with its ROOT powers enabled, not locked down — capable from minute one instead of asking to confirm everything (a local/personal install; the autonomy level is the guard-rail).
- Built-in tools, documented. A new auto-generated reference lists all 51 built-in tools (
web_search, file ops, memory,dashboard_publish, the ROOT meta-tools…) with each one's risk level and how it's unlocked — generated from the tool registry so it can't drift.
v0.6.7 — Boot Regression Fix · Jul 1, 2026
Undoes a 0.6.5 packaging change that broke nodal-agents up on fresh installs.
Highlights
- Fixed: the runner failed to start on a fresh install. 0.6.5 bundled the
node-fetchchain into the tarball to silence one last benign deprecation notice — butnode-fetch@3is ESM-only, and frozen into the package it displaced the CommonJSnode-fetch@2that the Notion SDK loads viarequire(), crashing the runner at import (Cannot find module 'node-fetch') so it never became healthy. Now onlyexceljsis bundled (CommonJS, self-contained): the scary warnings (glob"security",inflight"memory leak") stay gone, and the one benignnode-domexceptionnotice returns — a fine trade for a runner that actually boots. The generous 5-minute first-run health budget from 0.6.6 stays.
v0.6.6 — Fresh-Machine Boot Fix · Jul 1, 2026
A fresh install on a clean machine could time out on its first launch — fixed.
Highlights
- First run no longer times out on a clean machine. The runner's health-check budget was 60s, but the very first
nodal-agents upon a fresh machine is heavy — embedded-postgres fetches its ~70MB binary at runtime (more so when npm script-approval blocks its postinstall), and the runner loads a large module graph off a cold disk cache — which could blow past 60s and tear the stack down (did not become healthy within 60000ms). The cold-start budget is now 5 minutes and env-overridable (NODALAI_RUNNER_HEALTH_MS/NODALAI_WEB_HEALTH_MS). If it ever still times out, a retry runs warm (binary cached, modules loaded) and comes up fast — and the error message now says exactly that.
v0.6.5 — The Frictionless Release · Jul 1, 2026
Install and first run, cleaned up: a silent install, a browser-first setup with no account, and a welcome chat that never traps you.
Highlights
- A silent install.
npm install -g nodal-agentsno longer prints the scarynpm warn deprecatedlines —glob"widely publicized security vulnerabilities",inflight"leaks memory", and the rest. They were stale transitive deps ofexceljs(not reachable vulns, just upstream cruft); since npmoverridesdon't reach a global install, the fix bundlesexceljsand the tiny fetch chain inside the published tarball. Same bytes a user downloads, zero warnings. - Browser-first first run. A fresh
nodal-agents upasks nothing in the terminal. It boots with a sensible default and opens the dashboard straight to a guided setup — connect a model, create your first agent, meet it.nodal-agents initstill exists for LAN / auth / terminal setup and Docker. - No account by default. Local installs run in
local-truston loopback — no sign-up wall. Auth is opt-in, for LAN / multi-user. - A welcome chat that never traps you. At the end of the get-acquainted interview, the Continue button now appears as soon as you've answered the questions (it no longer waits on a done-marker that smaller/local models forget to emit), and a Skip for now button is always visible so a slow model can't strand you.
v0.6.4 — Onboarding Restored · Jul 1, 2026
A fresh install no longer locks you out — the real first-run flow is back.
Highlights
- Fixed: every fresh install was locked out. A workspace with no agents yet (the default state right after install — no agent is seeded by design) was redirected to an unfinished onboarding placeholder ("Migration WIP") and trapped there, with no way to reach the dashboard or create an agent. The real guided first-run flow is restored and wired back in: connect a model → create your first agent → a short welcome interview where the orchestrator introduces itself, gets to know you (your name, where you're based, what you want help with), and saves that to memory. It had been built and tested but parked on a side branch and excluded from a past release for lint errors; those are fixed and it's merged.
- Documentation, greatly expanded. A full reference pass: auto-generated catalog references (every connector and its tools grouped by read/write/destructive, MCP servers, models with vision/reasoning flags, ROOT grants — generated from the catalogs so they can't drift), plus new pages for connecting tools (per-connector OAuth/API-key setup), troubleshooting/FAQ, the CLI, the dashboard, operating & observability, the HTTP API, and workspaces. Several inaccuracies vs the code corrected.
v0.6.3 — The Design Pass · Jun 30, 2026
Every screen now wears the same skin — one header, one toolbar, one set of rules.
Highlights
- One header, one toolbar, everywhere. Every page renders a single shared shell: a full-width navbar (page title + lede on the left; global search, notifications, theme on the right; a bottom rule), and beneath it a consistent toolbar — filter tabs + search + a single create button. Create buttons follow one colour convention (agents = lime, skills = coral, connectors = blue, everything else = white), always top-right, always labelled "New …". No more per-page drift.
- Runs, as a delegation tree. The Runs page is now a delegation-aware table: each orchestrator sits directly above the runs it delegated, role colour-coded by a left accent, with trigger icons (cron / Telegram / dashboard), abbreviated token counts, and the real provider-reported cost.
- Skills, rebuilt. Two views — Assigned (a management table) and Library (the whole catalog as uniform tiles), filtered by content category (Development, Finance, Office, Media, Design…) instead of the old source split. Category pills on every tile; one-click install from any community source.
- Long lists collapse. OAuth scope URLs, required built-ins, and "used by" connectors now show as a compact "N items" pill you hover to expand — no more columns blown off the table. Credentials moved from cards to a matching table.
- Know when to update. The sidebar shows your running version and, when npm has a newer one, an "Update available" badge with the one-line
nodal-agents updatecommand. - All-English UI. The community-skill catalog and connector descriptions are fully translated.
- Also: Poyo image connector + VidIQ added to the catalogs · the full Telegram media surface (
send_file/send_video/send_audio/send_voice, not just images) · a Weekly ⇄ Daily toggle on the home activity chart · a copy button + shortened path for the shared workspace in Settings · the unused Billing menu removed · the sidebar widened to 244px.
v0.6.2 — The Recall Release · Jun 28, 2026
Your agents remember — within a conversation, and across everything they've ever done.
Highlights
- Conversations that hold the thread. Session memory now measures a pause from when the agent's reply was delivered, not from when the job started — so a slow task (a render, a deep research run) no longer makes your quick follow-up look like an hour of silence that wipes the conversation. The idle reset widened (30 min → 4 h), the history budget grew, the reply's tail (its conclusion / next-step) is kept instead of chopped, and a job that failed but spoke to you stays in the thread. Measured on a real 122-message conversation: amnesia dropped from 39% to 13% (the rest are genuinely new sessions).
- Two-tier memory. Injected memory is now ranked by relevance to the task at hand — not just global importance — so the budget surfaces facts about this request. Every job's transcript is full-text searchable on demand via the new always-on
search_historytool: durable recall of anything the team has ever done, at zero standing context cost. And a background memory curator distills oversized facts, merges duplicates, and prunes the stale — never touching what you entered by hand. - 3D & creative connectors. Blender, Unity, Unreal Engine, KeyShot, and Photoshop (cross-platform) join the MCP marketplace under a new Creative category — each with a real brand icon.
- A longer MCP tool timeout (heavy tools like renders no longer time out at 60 s), and a fix for an order-dependent CI flake.
v0.6.1 — The Vision Release · Jun 27, 2026
Send a picture on Telegram and your agents can actually look at it.
Highlights
- Inbound images. A photo sent on Telegram now starts a job — it was silently dropped before (the handler only read text, never the caption). The image is saved to your shared workspace (
telegram/<chat>/<job>.<ext>), reachable by the agent's file tools, and handed to the model — so "describe this image" works. - Vision routing, by real capability. Each model's image support is read from the providers themselves (OpenRouter's
/api/v1/models+ models.dev) and surfaced in the orchestrator's team view. A text-only orchestrator routes the picture to a vision-capable teammate — the image travels with the delegation — or tells you plainly if none can see it. No guessing, refreshable with one script.
v0.6.0 — The Clarity Release · Jun 25, 2026
Approvals that explain themselves, chat hand-offs that stay faithful, and session memory that knows when a conversation is over.
Highlights
- Approvals in plain language. Every gated action (shell command, skill script, bundle write) now leads with the agent's own one-line explanation of what it's doing and why — plus a ⚠️ impact line when it deletes, installs, or spends — instead of a wall of raw shell. On Telegram and in the dashboard.
- Faithful chat hand-offs. When the dashboard chat escalates your request to a worker, your exact words now travel with it — no more silently reworded instructions. A 30-minute idle gap starts a fresh conversation, so a thread you return to hours later doesn't drag yesterday's context into a new request.
- Role-aware delivery. Delegated workers hand results back to their orchestrator instead of double-delivering to you; the "how to structure and where to send" lives in a reusable skill, so a bare "research X" is enough.
- A shared workspace link in Settings, and a complete README rewrite.
v0.5.5 — The Autonomy Release · Jun 23, 2026
Real autonomy levels, a curated community catalogue, and agents that stop making things up.
Highlights
- Three real autonomy levels per workspace ROOT —
propose-confirm,destructive_gate(auto-run ordinary work, still gate anything destructive), andfully_autonomous— enforced at execution time, not just in the UI. - A 40-skill Community catalogue — install any of them with one click, every path verified.
- Google Calendar connector, and an entity-scoped skill store.
- Anti-confabulation team blocks — orchestrators describe their real team instead of inventing teammates, and delegated sub-agents suspend/resume cleanly across an approval.
v0.5.0 — The Self-Improving Release · Jun 15, 2026
A closed learning loop, native frontier-OSS endpoints, and one orchestrator that does both delegation styles.
Highlights
- A closed learning loop (opt-in). After a substantial job an agent reflects and writes itself a reusable skill; a weekly curator consolidates and prunes them. Review, assign, or revoke every learned skill from the dashboard.
- Native DeepSeek & MiniMax endpoints alongside OpenRouter — pick the route per key, with reasoning round-tripped across tool calls so reasoning models don't degrade mid-task.
- Unified orchestrator — every orchestrator gets both delegation styles and commits to one per request: route to a specialist and resume on its result, or fan work out to a parallel task board and compile it.
- Install any community
SKILL.mdfrom GitHub, skills.sh, or ClawHub — pure HTTPS, SSRF allow-list, zip-slip guard, scripts flagged and never run. - A real-dollar cost cap per job (from the provider's actually-billed cost), plus a no-false-success guard that refuses to report "done" when an action failed.
v0.4.4 — The Context Release · Jun 4, 2026
Long jobs stay inside the window, failures become diagnosable, and delivery only happens when there's somewhere to deliver.
Highlights
- Context compaction — stale tool output is evicted before the window overflows, keeping the recent turns intact.
- Real provider errors — failures surface the actual upstream message and persist the full transcript, instead of an opaque "provider returned error."
- Channel-aware delivery — an agent only reaches for
telegram_send_messagewhen there's a resolvable recipient, killing phantom sends on dashboard/API jobs.
v0.4.3 — The Reasoning Release · Jun 3, 2026
Highlights
- Reasoning models, round-tripped. A reasoning model's hidden chain-of-thought is now replayed across tool calls (via the official OpenRouter SDK), so MiniMax M3, DeepSeek, and friends keep reasoning on multi-turn tasks instead of stalling.
- Fixed an orchestrator that would narrate an action without performing it (poisoned history — escalations are now replayed with their
run_task).
v0.3.7 — The Root Agent Release · May 30, 2026
Highlights
- A self-extending ROOT agent. Designate your first orchestrator as the workspace ROOT and let it create skills, create agents and assign them, and stand up MCP servers + connectors on your behalf — each gated by a per-grant toggle and an autonomy level.
- Provisioning verifies before it writes (an MCP server is connected and its tools listed first); skill authoring is grounded in the workspace's real tools.
v0.3.0 — The Workspaces Release · May 28–29, 2026
Highlights
- Multiple isolated workspaces on one install (personal vs work), switchable from the sidebar — each with its own agents, skills, connectors, jobs, and memory.
- Office files — edit Excel in place, create Word & PowerPoint, inside the agent's workspace.
- One-command upgrade (
nodal-agents update) with a boot version notice. - A reworked Skills library (Assigned / Custom / Built-in) and a richer connector + MCP marketplace.
v0.1.0-beta — First public beta · May 13, 2026
The first published build: a local-first, multi-agent platform on embedded Postgres — team orchestration, per-agent models, persistent memory, Telegram, and connectors, in two commands.
For the full commit-level history, see the GitHub releases.