Repository navigation
Releases: basic-automation/Nanna
Release list
Nanna v0.3.42-beta.51
Nanna v0.3.42-beta.51 — Web pages can no longer reach your agent, and a long list of quiet fixes
This release closes a security hole: any web page you visited could connect to Nanna's background
service on your computer and run commands through it. It also fixes more than forty bugs found by
reviewing the board, memory, scheduler, file tools and settings code line by line. Most of them
gave a wrong answer without any error.
Security
Web pages can no longer control Nanna. The background service listens only on your own
computer, but browsers allow any page to open a connection to it. A malicious page could have run
shell commands, read your settings and shut the service down. Connections from web pages are now
refused; the Nanna app and the nanna command line are unaffected.
Settings no longer leak your API keys. Reading or exporting the settings through the background
service returned your API keys and sign-in token in plain text. They are now left out.
nanna server no longer answers web pages. Its chat API, which can use tools, accepted requests
from any web site. It now accepts only requests from programs on your computer.
Your rules for the agent are enforced everywhere. A rule such as "never delete anything under
tests/" was not enforced for shell commands, and the agent could overwrite the file that holds those
rules. Both are fixed, and the agent can no longer erase the records its safety checks rely on.
The board
- A card that the router split off, or that an agent handed on, is no longer stranded with nobody
on it when its run gives up or stalls. - A card no longer goes back to the router when its own agent asked you a question; the answer goes
to that agent. - The limit on retries before Nanna asks you now holds, however busy the card is.
- Text you are typing in a card's description or labels is no longer wiped when the board refreshes.
- A card opened from your Inbox can only be given to someone on that card's own board.
- Deleting an agent releases its open cards back to the router instead of leaving them pointing at
an agent that is gone, and you can now unassign a card. - Renaming, re-dating or deleting a card now updates every open view right away.
- Recurring cards open on the right day: not again on the day you finished them, and on the current
round after the computer was off. - Deadlines written with a time zone are no longer marked overdue before they pass.
- A dependency that could never be finished is now refused, dates that are not real dates are
refused, and reopening or cancelling a card updates everything that follows it.
Memory
- Memory now belongs to the right project. An agent working on one project's card no longer reads
or writes another project's memories. - Consolidation can no longer delete an unrelated memory when it re-folds a card's history.
- A fact you stated is no longer merged into an observation and reworded later.
- Saving a memory no longer fails when the embedding service is briefly unavailable.
- Recalling memories no longer strengthens ones that were never shown.
Scheduled jobs
- A daily job that came due while Nanna was busy runs as soon as it is free, instead of skipping
the day. - Turning a job, or the scheduler, back on no longer runs it immediately off schedule.
- "Run now" no longer freezes Settings and reminders while the job runs.
- Editing a job now saves its new prompt.
Files and tools
- Editing a file with Windows line endings no longer mixes in Unix line endings.
- Searches find matches at the end of lines in Windows-style files, and every match is marked.
find_filespatterns with folders (src/**/*.rs) work without an explicit path.- PDF, image, audio and OCR tools can read files in projects outside your home folder (on a second
drive, for example). Existing installs are updated automatically unless you changed these
permissions yourself. - Paths with
~or an apostrophe no longer break the syntax checks, and.env.localbeside.env
is no longer refused as a copy. - File history no longer fills up with temporary drafts, every saved checkpoint can be listed, and
restoring over a file too large for history to keep is refused instead of losing it. - Web pages in other character sets (Latin-1, Shift-JIS and others) are fetched with their text
intact. - The browser tools keep working after their first use. Before, every browser call after the
first failed until Nanna was restarted. - An MCP server that sends an enormous message can no longer use up Nanna's memory.
Conversations with the model
- Requests sized for a small local model now count the project context, the tool list and the real
size of attached images, so a request that looked small enough no longer overflows the model's
window. - A file the agent re-read to edit is no longer swapped for a "seen before" note on the next step.
- Empty-looking messages that Anthropic rejects are no longer sent, so a session that stored one no
longer fails on every later turn. - When a request is cut to fit, the agent is told; a message too long for the summarizer is no
longer dropped after only its beginning was read.
Settings
- A mistake in
config.tomlcan no longer cause Nanna to overwrite the whole file with defaults.
Settings are also saved safely if the computer loses power. - Your custom system prompt and agent name are now used.
- "Remember my choice" in the close dialog is remembered after a restart.
- Saving one API key no longer copies keys from environment variables into your keyring.
- Changing two settings in quick succession no longer undoes the first.
- The Tools and Memory pages no longer show stale results after a quick switch, the scheduler switch
shows its real state when a change is refused, and a failed settings import now says so.
Command line
nanna configno longer prints your API keys.nanna daemon stopwaits until the daemon has exited, sostopfollowed bystartworks, and
nanna daemon startreports a daemon that fails to start instead of claiming success.--configis honoured bynanna credentials,initandstatus.- First-run key setup saves only your config file and the key you typed, not values from
environment variables.
Under the hood
- Dependencies: Tauri 2.12.3 and its plugins, Nuxt 4.6.1 (it now builds on Windows), uuid
1.28, vue-router 5.4.0. - Held back:
rten0.27 (waiting onocrs) and the newer rustpython parser crates. - The test suite no longer leaves temporary databases in
/tmp.
Still open
- Channel setup (Telegram, Discord and others) still copies environment-variable secrets into the
keyring. Channels are due to be removed. nanna daemon stopon macOS and Windows cannot yet confirm that the recorded process is the
daemon before stopping it.- MCP: a question a server asks you times out after about a minute, and one slow server delays
the tools of the others while Nanna starts.
Nanna v0.3.41-beta.50
Nanna v0.3.41-beta.50 — No more crashes on shutdown (Linux), and a public home
This release fixes the crash that Linux users of the AppImage saw on nearly every reboot, logout
or app close. It also finishes moving the project to its public home at
basic-automation/Nanna.
What's Changed
The Linux daemon no longer crashes when the app closes. The AppImage serves the background
daemon's code from a temporary mount that disappears when the app exits. The daemon keeps running
for up to a second after that to finish saving, so it read code from a mount that was already
gone and crashed partway through its last writes. That was 8 of the 9 unclean exits recorded
between 2026-09-18 and 2026-09-28. The daemon now copies itself and the libraries it uses to
~/.cache/nanna/appimage-daemon/ and runs from there. If the copy fails, it runs as before and
logs a warning. Tested against a real AppImage mount: before the fix, closing the mount crashed
the daemon; after it, the daemon shut down cleanly.
Nanna's public home. The repository is now public at
basic-automation/Nanna:
- Every link, the updater address and the installer publisher now point at Basic Automation.
Apps that are already installed keep updating through GitHub's redirect. - Security reports now go through GitHub's private vulnerability reporting. The old
security@nanna.botandconduct@nanna.botaddresses could not receive mail. - New issue forms, a pull-request template, and an updated README and contributing guide.
- Before publishing, the repository's full history was scanned for credentials. None were found.
Releases can no longer link to the wrong repository. A new check in the release workflow
stops a release whose notes link to a Nanna repository under another owner, because a published
release's notes are not updated afterwards. The updater manifest instructions now take the
repository from the workflow instead of a hardcoded name.
Under the hood
- Dependencies:
vitest4.1.11 for the app's tests, andsource-map-js1.2.2. - Held back:
rten0.27. The OCR engine (ocrs0.13.1) still requiresrten0.26, so
upgrading onlyrtenbreaks the build. It will move with the nextocrsrelease.
Still open
nanna serve's Slack and Discord replies are sent in the HTTP response, where they never
reach the user.browser_actioncannot act on a page across calls, and screenshot size and element options are
ignored.- Two choices are the owner's to make: whether cron should catch up on runs missed while the
computer was off, and whether board dates should use local time instead of UTC.
Nanna v0.3.40-beta.49
Nanna v0.3.40-beta.49 — Ninety fixes from a full audit
This release has no new screens. It is the result of a read-through of the whole daemon, the app,
the chat-app connections and the command line, looking for places where Nanna said one thing and
did another. About 90 of them are fixed here, nearly all with a test that checks the fix. The rest
are listed in the roadmap.
What's Changed
The board and recurring cards
- A recurring card moves to its next round. Completing one used to leave its due and defer
dates where they were, so it came back already overdue. Both dates now move forward by the
recurrence. A recurrence that cannot be read is refused when you save it, and you can clear one. - Cron schedules fire the way cron does. With both a day of the month and a day of the week
set, a schedule ran only on days that matched both. Standard cron runs on either, and so does
Nanna now. - "Run now" behaves like a scheduled run. It is recorded the same way, and a task can no longer
run twice at once because you pressed it during a scheduled run. - The board view holds steady. Switching boards kept showing the old board's cards for a
moment, a slow reply could overwrite a newer one, and sub-cards hidden by a filter vanished with
their parent. All three are fixed. - Smaller board fixes. A bare "defer until" date now actually defers the agent's run. A card
split between agents checks every assignee before creating any part. The router can no longer
take back a card an agent has just started. "Done" checks a card in its own board's workspace. - A long-running card is remembered in full. When a card closes, its history becomes one
memory. For a card with more than 1,000 events, only the first 1,000 were used, and later
activity was never added. Now the start and the end are both used, and the memory is rebuilt
when the card grows.
Memory
- Workspace memories stay in their workspace. A new memory could be merged into a similar
memory from another workspace, or into a global one, which made private text visible
everywhere. Merges now happen only within the same scope. - Searching a small workspace finds its memories. A search looked at the 3×k best matches in
the whole store and then filtered by workspace, so a small workspace often got nothing back. The
search now widens until it has enough matches from that workspace or has looked at everything. - Deleted memories stay deleted. A delete that happened while a memory's search index was
being saved could be undone on the next restart. A memory whose save to disk failed was reported
as saved. Both are fixed. - Edited text is not searched by its old meaning. A search index computed from a memory's old
text could be attached to its new text. It is now discarded, and the old index is also wiped
from disk when a memory is rewritten.
Chat and models
- Token counts for OpenAI-compatible providers. Streamed replies from OpenAI, OpenRouter and
GitHub Models were recorded as using 0 tokens. They now report their real usage, including
cached prompt tokens. - A failing model is held back, then tried again. A model with a poor record was taken out of
use for good. It now waits for a cooldown that grows with each failure and gets tried again
afterwards. - Rate limits are respected. When a provider says how long to wait, Nanna now reads that time
in every format providers use. The wait applies to chat and to card runs. A very large value can
no longer crash the daemon. - A cut-off reply is retried, not used. If a connection dropped in the middle of a tool call,
the half-written call could be repaired and run. It is now treated as a failed request and
retried. - A stopped turn leaves a valid conversation. When a model wrote a tool call as plain text,
Nanna runs it as a real call. If the turn was stopped or ran out of budget first, that call was
saved without a result, which some providers reject on the next message. It is now saved with a
"skipped" result. - Stop stops a running check. Pressing Stop while a task's completion check was running used to
wait for the check to finish, which could take up to 10 minutes. The check is now ended at once.
Tools and scripts
- Tool scripts stay in their folders. A skill could use
..to read or write outside the
folders it was allowed, and a tool you write could replace a built-in tool with the same name.
Both are refused now. - Tools work inside the open workspace. The PDF, image and audio tools, the python tool and
your own tools resolved file paths against the daemon's folder instead of the open project. They
now use the project. A python run also changed the daemon's working folder for good. It now puts
it back when it finishes. - Browser tools close their tabs. Every browser call opened a tab and never closed it, so a
long session could fill memory until Chromium was killed. Each call now closes its tab, and a
browser that crashed is started again on the next call instead of failing until a restart.
Browser errors now report what actually went wrong, and a screenshot reports where it was saved. - Web fetches are limited. A fetch read the whole download before applying its size limit, and
a network error made the tool fail outright. Downloads now stop at 64 MiB, and a network error
is reported to the model.
Chat apps
-
Telegram's allowed users apply to webhooks too. With a webhook URL set, the
allowed_users
list was not checked, so anyone who messaged the bot could use it. It is now checked on every
message. -
Telegram replies are no longer lost to formatting. A reply with an unmatched
_or*,
such as a file name, was refused by Telegram and never arrived. It is now sent again as plain
text. -
Editing a Telegram message no longer runs it again. Fixing a typo used to start a second
turn with a duplicate reply. -
Discord slash commands carry what you typed.
/ask question:"…"reached Nanna as just
"ask", and Discord showed the command as failed. The question is now the message, and Discord
shows "Working on it…" until the reply arrives.
MCP servers
- Your token goes only to its own server. An older-style MCP server could tell Nanna to send
messages, together with your saved token, to a different web address. Nanna now refuses that. - Connections recover. If an MCP server ends the session, Nanna starts a new one and retries,
instead of failing every later call. A dropped connection now fails a call at once instead of
after 60 seconds. - Shutdown closes everything a server started. Closing a local MCP server now also stops any
programs that server started.
The app
- Creating a tool in the Tools page works. The page sent the tool's code under the wrong field
name, so new tools were never created, and edits saved only the description. A new test checks
every call the app makes to the daemon for this kind of mistake. - Settings pages stay in sync. A change made by the daemon or another window now appears in
the open page. A save that fails now shows an error instead of looking successful. - Requests fail fast while the daemon is down. After the daemon dropped its connection, every
request from the app failed with an unclear error and was left waiting in memory; one could hang
for 5 minutes. They are now refused at once until the app reconnects. - Statistics are accurate. The tool and model statistics include failed calls. The "all tools"
average counts every call equally. "Slowest" shows the slowest tool. The usage chart for N days
covers N days, not N+1.
Command line and service
nanna daemon restartwaits for the old daemon to stop. It used to wait half a second, find
the old daemon still running, start nothing and report success. It now waits until the old one
exits, and reports an error if it does not.- Addresses are honored.
nanna daemon status --portandnanna export --daemonreach a daemon
that is not on the default port.nanna mcp servewaits for a long tool call to finish instead
of failing after 30 seconds, and reconnects after the daemon restarts. - The installed service is the daemon you set up.
nanna-daemon installignored your port,
data folder and config file. It also reported success whensystemctlorlaunchctlrefused
the install. Both are fixed. - Settings that fail to save say so. A setting that could not be written to the config file
was reported as saved and then lost on restart. The reply now says it applies until restart
only.nanna doctornow fails a config file that cannot be read. - A broken config file is not overwritten.
nanna credentials import,refresh,setup
andclearreplaced aconfig.tomlwith a typo in it with the default settings. They now leave
it alone and say so, and every other command exceptnanna doctorstops with the parse error
instead of running on the defaults.nanna chatexits at the end of input instead of spinning, and
nanna configshows the file it actually read. - Saved keys are not lost. Running a command such as
nanna mcp secret setwhile the daemon
was running could lose a saved key. Writes to the key file now wait for each other.
Under the hood
- Dependencies: the
tomlcrates and the app's Tauri plugins,marked, Lucide icons,
Playwright and happy-dom are updated. Sixteen dependencies that nothing used were removed, and a
new check (cargo shear) keeps unused ones out. Held back:rustpython-ruff0.16.10 and
rten0.27 (they do not build), Tauri 2.12.2 (it would downgrade parts of the Windows app),
Nuxt 4.6 (its Windows build fails) and TypeScript 7 (only development builds so far). - Status endpoint:
/statusnow reports the number of connected clients and the most recent
error....
Nanna v0.3.39-beta.48
Nanna v0.3.39-beta.48 — A faster Memory page, and a board race closed
This release has no new screens. The Memory page loads faster on large stores, a timing gap that
could take a card away from an agent that had just started on it is closed, and a lot of code that
nothing used is gone.
What's Changed
The Memory page loads faster on a large store. Opening it asks the daemon for every memory at
once. That reply used to be built twice in memory before it was sent: once as a tree of small
pieces, then a full copy of that tree. It is now written straight out once. On a store of 3,927
memories (a 15.8 MB reply) each request took about 79 ms before and about 67 ms now. What the app
receives is unchanged, byte for byte. Memory use after these requests is about the same as before.
A card you start by hand can no longer be taken away at the same moment. Every 5 minutes the
daemon looks for cards that an agent holds but nothing has worked on for 30 minutes, and hands
them back to the board's router. If you pressed Start on such a card at the exact moment of that
check, the card could be handed back while its new run was already working on it. Both now take
turns: either your Start comes first and the card stays with its agent, or the hand-back comes
first and the late Start is refused with "no longer assigned". A card someone commented on or
edited in that moment is also kept.
Response-time histograms for monitoring. /metrics on the health port now includes how long
each tool call and each model request took, in the standard histogram format. A Prometheus or
Grafana setup can chart percentiles over time from it. Before, it showed only a recent 95th
percentile.
Less dead code. About 3,200 lines that nothing called were removed:
- an unused second JavaScript engine (V8, through Deno). It was never compiled into the app, so
the app does not change, but 83 packages leave the dependency list; - 17 old built-in tools. The tools you use are the bundled skills, which are unchanged.
Under the hood
- Dependencies: the turso database moves from 0.8.1 to 0.8.2, plus 37 other compatible
updates. Three updates were held back because they do not build:rustpython-ruff0.16.10,
rten0.27, and Nuxt 4.6.0, whose static build fails on Windows. The GUI stays on Nuxt 4.5.2. - Security audit: four new advisories against
simple-gitare exempted, with the reasons
recorded. It is used only by Nuxt's developer tools, which are switched off in the app you
install. The fixed version cannot be used yet because it would break the development server. - Checked against outside implementations: the MCP compatibility tests now run against the
latest official Rust SDK (3.5.1) and TypeScript SDK (2.3.1). All 11 pass.
Still open
- The built-in offline text recognition (OCR) is compiled into the app, but nothing calls it.
Whether to connect it or remove it is the owner's call. - The router still has no heartbeat card.
- Nanna does not yet run models itself. That waits on the Mummu model runner, which first needs to
move to burn 0.22.0, released 2026-10-06.
Nanna v0.3.38-beta.47
Nanna v0.3.38-beta.47 — Steadier memory use, fewer stuck cards
This release has no new screens. The daemon stops growing after large requests. Cards on the
board no longer get stuck in ways that need a restart. When the daemon dies unexpectedly, you
can now see how it died.
What's Changed
The daemon grows far less with use. Opening the Memory page asks the daemon for every
memory at once. On a real store of 3,730 memories that reply is 14 MB, and building it used to
leave the daemon permanently larger each time. In a test that repeated the request every two
minutes, memory use went from 142 MB at rest to 608 MB, and it was still climbing. Two changes
cut this sharply:
- Listing memories, and the memory statistics on the Settings page, no longer copy every
memory's search vectors just to read the text. - After any reply over 1 MB is sent, the daemon hands the freed memory back to the system. This
takes about 5 ms and runs at most once every 10 seconds.
In the same test, memory use was about 213 MB after the same number of requests that had taken the
old version to 439 MB. It still creeps up slowly, at about a third of the old rate.
Board cards no longer get stuck.
- Stop keeps meaning stop. After about 64 edits or reorders, a card you had stopped could be
treated as abandoned and taken back from its agent. It now stays stopped for as long as you
leave it. - A stopped card you give to someone else starts for them. Its "stopped" note says it stays
with the agent until it is restarted or reassigned. Reassigning it used to leave it stuck in
progress with nobody working on it. Now the new agent picks it up. - A card that comes back unfinished in two different rounds no longer goes straight to you.
The count of failed attempts now starts over once a card has been finished. Previously, a
repeating card that failed once one week and once the next asked you "2 runs could not finish
it" right away.
You can now see how an unexpected crash happened. If the daemon is killed by something it
cannot catch, such as a crash signal or a forced kill, the app now records how it ended. The next
start reports it, for example "the app saw it end by signal 9 (SIGKILL)", where the daemon used to
say only that it had "died through a path no hook could see". nanna doctor has a new
daemon.last_exit check with the same information: whether the daemon is running, stopped
cleanly, or died, and where to look in the logs.
Under the hood
- Toolchain: nightly-2026-10-03. Newer nightlies cannot build Nanna yet: Rust renamed an internal
function, and a library our database depends on still uses the old name. That library has a fix
pending. - Dependencies: postcss 8.5.29, plus three small lockfile updates.
Still open
memory.liststill builds its whole reply in memory before sending it. The memory is now
handed back afterwards, but building the reply directly would also make it faster.- These memory numbers come from a test on a copy of a real store, not from a day of real use.
- If you press Start on a card in the same moment the stall check is releasing it, the start
can still lose. The window is a few milliseconds.
Nanna v0.3.37-beta.46
Nanna v0.3.37-beta.46 — Fewer ways to crash, faster recall
This release has no new screens. It removes several ways the daemon could take itself down, makes
memory search faster, and fixes where future updates are downloaded from.
What's Changed
Memory search is about twice as fast. Nanna was using a memory allocator it inherited from
its database library rather than one anyone chose. Measured against the system allocator, the
search that runs on every recall and every new memory took 11.2 ms at 50,000 memories; it now
takes 4.7 ms. Loading memories at startup got slower (121 ms → 181 ms at 50,000, once per
launch). One C library is gone from the build. After startup, the daemon now returns the memory
that loading used to the system: on a real 3,730-memory store it settles at about 213 MB, down
from about 237 MB.
A tool can no longer take the daemon down with it. When a tool script reads a file, runs a
command, fetches a URL or calls a service, Nanna starts a small worker for that call. If the
worker could not start (for example because the system had run out of file handles), the whole
daemon used to stop. Now that one call fails with an error saying why, and everything else keeps
running. Similarly, if you edit the discover_tools tool so that it no longer parses, startup now
skips that tool with a warning instead of failing.
Updates download from the repository's current home. Since the project moved to
basic-automation/Nanna, each release's update manifest still pointed installers at the old
address. Downloads only worked because GitHub redirects the old address. The manifest generator
now uses the repository's actual name, and new installs check for updates there directly.
Existing installs keep working as before.
Fixes
- GPU vector search handles large stores. Searching more vectors than the graphics card
accepts in one batch was a hard crash. The search now splits the work into batches the card
accepts. (Nanna does not use the GPU path today. This keeps it safe for when it does.) - macOS service install escapes its settings. An install path or argument containing
&or
<produced a launchd file macOS refused to load. Values are now escaped, and that is tested on
every platform.
Under the hood
- The GPU benchmarks reported speed ratios 10^18 times too large, so they could never report a GPU
win. Fixed. With correct numbers, SIMD wins across the tested range (4.3× faster at 10,000
vectors). - New tests: an MCP stream event split at every byte offset, the GPU batch limits (run on an RTX
4070 Ti SUPER), the launchd escaping, and the tool-runtime helper. tokio1.53.2,mio1.2.4,async-recursion1.2 and@lucide/vue1.52. TypeScript 7 is still
on hold untilvue-tscsupports it, andrten0.27 untilocrssupports it.
Still open
- Chat is still there beside the board. Removing it is the next big step.
- Whether to keep the system allocator long term depends on how the daemon's memory use looks over
a full day of running. - The heartbeat is not a board card yet, and the board does not yet follow the Figma design's
final styling.
Nanna v0.3.36-beta.45
Nanna v0.3.36-beta.45 — Cards don't get stuck
The board shipped in the last release. This one is about what happens when the work on a card
goes wrong: a card an agent stopped working on, a model provider that rejects the key, a
provider that says "slow down". Each now ends somewhere you can see, instead of in a card that
sits there.
What's Changed
A card nobody is working goes back to the router. If an agent's card has been in progress
for half an hour with nothing working on it, and you did not stop it yourself, the board's
router takes it back. It says so on the card's thread, then decides again who should do it. A
card that keeps coming back this way ends with a question to you rather than going round
forever, the same as a card agents keep handing back. A card you stopped stays with its agent
until you resume or reassign it.
A rejected API key becomes a question for you. When the model provider refuses an agent's
run outright (an invalid key, an account out of credit, no key set), the card no longer fails or
goes to another agent on the same broken provider. You get a question card that names the error
and says what to fix. The work card waits for it, keeping its agent. Mark the question done once
it is fixed, and the agent starts again.
A rate-limited run waits and tries again. When the provider says too many requests, the card
stays with its agent and says when it will try again (the provider's own wait, else five
minutes). That does not count as a failure.
Choose where Nanna keeps its data. Settings → Data → Data location shows the folder the
daemon keeps its database, memories and logs in, and lets you choose another one or go back to
the default. The daemon reads this when it starts. Until it restarts, the page says it is still
using the old folder, and it never moves your data: copy it there first if you want to keep it.
Fixes
- A board shows its own cards. With the app open twice on different workspaces, a board
could list, and add cards to, whichever workspace the other window last picked. Each board
now names its own workspace.
Under the hood
- turso 0.8.1 (from 0.7.2), built without its full-text search feature. That feature does
not compile on our toolchain (turso#9463),
and Nanna does not use it. Leaving it out removes 34 crates from the build, among them a C
compression library and anlruversion with a soundness advisory (RUSTSEC-2026-0253). Checked
by starting the release daemon against a copy of a real 101 MB database. - 25 app commands nothing called are gone, among them commands that could write workspace
files and tool code. The app no longer links Nanna's scripting engines: its dependency graph
went from 862 crates to 740. - The daemon's status now reports the data folder it is using, and
task.list/
task.quick_addaccept aworkspace_id. - The unused
[memory] extraction_modelsetting is removed. Old config files that still have it
load as before. uuid1.27 and@lucide/vue1.51, plus routine lockfile updates. TypeScript 7 is still on
hold untilvue-tscsupports it.
Still open
- Chat is still there beside the board. Removing it is the next big step.
- The heartbeat is not a board card yet, and the board does not yet follow the Figma design's
final styling. - There is no way yet to back up or export Nanna's data from the app.
The previous release, v0.3.35-beta.44,
added the board.
Nanna v0.3.35-beta.44
Nanna v0.3.35-beta.44 — The Board
Until this release the board existed only inside the daemon: cards, members, the router and
agents working cards were all real, but there was no screen to see them on. Now there is. Open
Board from the top of the left rail.
What's Changed
One line makes a card. Type a card into the line at the top of the board. Tokens fill in
its fields, and everything else is the title:
#labeladds a label,p1–p4sets the priority,@memberassigns it (@meis you).- A date defers the card until that day:
today,tomorrow,friday,next friday,
next week,in 3 days,march 30or2026-12-31. - A date in braces sets the deadline instead:
{friday},{march 30}.
For example, Ship the fix #release p2 @builder tomorrow {friday}. Anything you leave out, the
board's router fills in. If a token is wrong (an @name nobody on the board has, a deadline
that is not a date), the line says why and no card is made.
The board. Four columns: To do, Waiting (cards held up by another card, such as a question
for you), In progress and Done. Sub-cards sit inside their parent card, with a count, or on the
board as cards of their own. Filter by assignee, label, priority, or date (startable now,
deferred, overdue, no deadline). The board updates by itself as the router and agents work.
A card's own view. Click a card to see its thread: progress, questions and verdicts as
members post them, rendered as formatted text. From there you can post, reassign the card,
change its priority, date, deadline, labels and description, see what it waits on and what its
sub-cards are, add a sub-card, start, stop or resume an agent's work on it, and mark it done.
If its "done when" check fails, the card stays open and says why.
Inbox and Upcoming. Inbox lists the cards assigned to you that you can start now: no date,
or a date that has come. Upcoming lists the later ones by day. Both cover every board, and each
card says which board it is on.
Members. Add agents to a board, give each a list of models (best first), capabilities and
notes for the router, or make one your own so it follows you to every board. You can also set
the router's own model list here.
Notifications. You are notified when one of your cards' dates arrives, when its deadline
passes, and when the router or an agent hands you a card, such as a question about their work.
Fixes
- A date can be removed from a card. Clearing a card's date, deadline or description used to
be impossible; now it takes one click. - Listing a large folder gives the same answer on every computer. When a folder had more
entries than the project overview shows, which entries made the cut depended on the disk's
filesystem. It now always keeps the first ones by name.
Under the hood
- New daemon actions:
task.quick_add(one line to one card, optionally as a sub-card) and
task.assigned(a member's open cards on every board). - The app now receives the daemon's card and roster change events, which it used to drop.
- RustPython 0.6. This lifts two version holds:
libc(now 0.2.189) andmalachite-bigint
(now 0.12). Tauri's JavaScript packages now match the 2.12.1 Rust crates. devalue5.9.4 (pulled in by Nuxt), fixing six advisories, three of them high
(GHSA-j22f-vq7h-c4qm,
GHSA-mcm9-63f2-9j32,
GHSA-x5rw-q4pp-hg5g and three lower).
Onenode-forgeadvisory has no fix yet; it only affects Nuxt's development server, which is
not part of the app.- Built with the Rust nightly of 2026-10-02 (rustc 1.101.0).
Still open
- The board shows the workspace selected at the top of the window, or the global board.
- The board does not yet follow the Figma design's final styling.
- The router does not yet notice a card that sits in progress with nobody working it (for
example one you paused), and the heartbeat is not a board card yet. - Chat is still there beside the board. Removing it is the next big step.
The previous release, v0.3.34-beta.43,
made agents start on the cards assigned to them.
Nanna v0.3.34-beta.43
Nanna v0.3.34-beta.43 — Agents Work Their Cards
Until this release, assigning a card to an agent changed a field and nothing else. Now the
assignment is the start signal: the agent works the card straight away, writes its progress and
its result on the card's thread, and either closes the card or hands it back to the router with
the reason. There is still no board screen in the app; everything here works through the
daemon's connection and is what the board client will sit on.
What's Changed
Assigning a card to an agent starts the work. Whether the router assigns it or you do, the
agent starts on the card at once, using the agent's own model list if it has one, otherwise
your chat models, in the card's own workspace. An agent works one card at a time. A card given
to a busy agent waits and starts as soon as the agent finishes. A card with a future date waits
for that date, and a card that waits on another card starts once that card is done. While it
works, the agent shows as busy.
The work is on the card. The agent's working notes appear as progress posts on the card,
and closing it leaves a verdict post: what the acceptance check said, or that no check ran. An
agent works only the card it was given and the sub-cards under it, never a card you add next to
it while it is busy.
A card the agent cannot finish goes back to the router. If the agent gives up, or runs out
of time, tokens or working models, the card is not cancelled. It returns to the router as an
open, unassigned card with the reason posted, and the router decides again (it may pick another
agent). If two attempts in a row fail, the router asks you what should change instead of
trying a third time.
Agents ask you on the board. When an agent working a card needs an answer, it creates a
question card for you, and its own card waits on that one. Nothing sits waiting for a reply.
Once you answer and complete the question card, the agent picks its card up again with your
answer in front of it. An agent cannot close its card on its own word while your answer is
still outstanding.
Agents break work down on the board, and hand parts on. When an agent splits its card
into sub-tasks, they appear as sub-cards under that card and the agent works through them
itself. It can also give a sub-card to another agent, who starts on it straight away while the
first agent leaves it alone; when the other agent finishes, the parent card carries on.
Sub-cards the router splits off for an agent start the same way. An agent can no longer clear
tasks in bulk.
Stopping an agent pauses its card. Cancelling an agent's run leaves the card with that
agent and says so on the thread, so nothing restarts it behind your back. Starting it again
picks up where it stopped. Work the daemon was doing when it shut down picks up again at the
next start.
Fixes
- Background work no longer reaches into your chats. Work that ran in the background, outside
any conversation, could have its "ask the user" questions and its to-do list land in whichever
chat you used last. Each background run now has its own context, and a question from a board
card becomes a question card instead.
Under the hood
- New: starting, checking and stopping one card's run over the daemon's connection (
card_id
ontask.start_run,task.run_statusandtask.cancel_run). - Dependencies: the Tauri 2.12.1 patch line, tiptap 3.31.4, Lucide 1.49, Vitest 5.0.3.
libc
stays at 0.2.186 andmalachite-bigintat 0.9.2 until RustPython releases past 0.5.0. Turso
0.8.1 is out and is the next storage migration. brace-expansion2.1.7 / 5.0.12 (pulled in throughminimatch), fixing three denial-of-service
advisories (GHSA-qhr7-859c-m2p7,
GHSA-6j4f-fj2g-mc7p,
GHSA-q2hr-2g5m-vwhr).
Still open
- There is no board screen in the app yet.
- The router does not yet notice a card that sits in progress with nobody working it (for
example one you paused), and the heartbeat is not a board card yet. - Agents' capability tags do not yet adjust to how they actually perform.
Also in this update
Nanna v0.3.33-beta.42 — The Board Gets a Team
That release was prepared but never published, so it ships here.
What's Changed
The router takes up cards you create on the board. When a workspace or global card is
created through the daemon's connection (not by the chat's own model), that board's Task
Management Agent reads it and decides: assign it, split it into sub-tasks, ask you a question,
or park it. It uses its own model list if one is set, otherwise your chat models. Cards the chat
makes for itself are left alone on purpose, so a question from the router can never stall a chat
mid-task.
Answering the router's question sends the card back to it. When the router asks you
something, it makes a card for you and the original card waits. Now, when you finish that card,
the router decides again with your answer in front of it.
A recurring card goes back to the router each round. A recurring card used to reopen
straight to whoever had it last time. Now it is released and the router places it again.
The router fills in what you left blank. When it assigns a card it can add labels and a
"done when" check. A check you wrote yourself is never replaced.
Agents can join the board. The daemon can now list, add, edit and remove board members. An
agent belongs to one workspace's board, to the global board, or to you personally (a personal
agent follows you to every board). You and each board's router cannot be removed. Every change
is announced to all connected clients. You can also set the router's own model list here.
Fixes
- Every workspace's board has a router, including workspaces opened after boards were
introduced (older ones get theirs at the next start). - A card's labels and tool list have limits: 32 labels of up to 64 bytes each, and 64 tool
names of up to 64 bytes each.
Under the hood
- Dependencies:
softaes0.1.7,playwright-rs0.19,bigdecimal0.4.11,tokio-rustls
0.26.6, andundici8.11.2 (pulled in by Nuxt), fixing a WebSocket denial-of-service advisory
(GHSA-3wwx-pv8p-q78v). - Built with the Rust nightly of 2026-09-28 (rustc 1.101.0).
Nanna v0.3.32-beta.41
Nanna v0.3.32-beta.41 — Stopped Means Stopped
A repair release with one step forward on the task board. The headline fixes are about Python:
a timed-out python.exec used to keep running forever in the background, and any Python script
that imported subprocess quietly took Ctrl-C away from the daemon. Both are fixed, and both
were checked on a real running daemon, not only in tests. The board also gains the first half
of its Task Management Agent: the part that decides who works on a card.
What's Changed
A Python script that runs past its time limit is stopped. The embedded interpreter can't be
stopped from outside, so when a script timed out Nanna reported the timeout and let it keep
running. A while True: loop used a whole CPU core until the daemon restarted. Nanna now
interrupts the script at its next step and keeps interrupting until it stops. On a running
daemon, a runaway loop given a 3-second limit stopped within a moment of timing out.
Python can no longer take Ctrl-C away from the daemon. The interpreter was allowed to install
its own Ctrl-C handler for the whole process. Any script that imported signal did this, and so
does subprocess. After that, Ctrl-C and kill -INT no longer shut the daemon down cleanly.
That permission is now off. Checked on a real daemon: after a script imported both modules,
kill -INT still shut it down cleanly.
The board's router can decide who does a card (not switched on yet). The Task Management
Agent now has its decision-making half. It reads a card, the card's recent thread, the members
of the board and how each has done on past cards, and gives one answer: assign the card, split
it into sub-tasks, ask you a question, or park it with a reason. Every answer is posted on the
card's thread. When it asks you something, it creates a card for you, and the original card waits
until you finish that card. A card that is being worked on is never reassigned. The router is
not switched on yet: while the chat still exists, the router would also pick up the chat's
own to-do cards, and a question from it could stall a chat mid-task. It will be switched on
together with the board.
A card records who created it. Until now the "created" entry named the card's assignee as
its author. That entry now names the actual creator, which the router needs to tell cards it made
itself from new work.
Fixes
- Command output with terminal links is clean.
cargoandls --hyperlinkwrap file paths
in invisible terminal-link codes, and those codes used to leak into the output as
8;;file:///…next to the path. Every kind of terminal escape code is now removed completely. - A missing working directory is reported as a missing directory. Running a command in a
directory that doesn't exist used to fail with "No such file or directory", which looks as if
the command is missing. The error now names the directory. - Scripts can't read an endless file into memory. A script reading
/dev/zero, or a file that
kept growing, read until the daemon ran out of memory. Reads now stop at 64 MiB and say so. - Git context is capped while it is being read. Nanna used to read all of
git status's
output before keeping the first 64 KiB, and a command that never stopped writing used up the
whole timeout and produced nothing. It now stops reading at the limit. - Transparent screenshots are shrunk before sending. An image with a transparent background
couldn't be converted to a smaller JPEG, so it was sent over the provider's size limit and
rejected. The "lower the quality" step also never took effect. Both are fixed. - The list of verified results in a long session no longer grows without limit. It is the
one part of the context that is never summarized. Simple look-around commands (ls,cat,
git status) that succeeded are now counted on one line instead of listed one by one. The
rest are listed newest first within a fixed size, and the list says how many it left out. - Debug copies of prompts are private and size-limited. Copies of prompts saved for
debugging are kept next to the daemon's logs, readable only by you and limited in size. They
used to be written to the shared/tmpfolder, where other users could read them, with no
size limit. - A tool's own
timeoutsetting now applies no matter how the tool is loaded, and an absurdly
large value can no longer overflow to a timeout of a few milliseconds.
Dependencies
Tauri plugins updated (dialog 2.8, fs 2.6, notification 2.5, process 2.4, shell 2.4,
updater 2.13), with the JavaScript packages updated to match. The app was checked by launching it
with its own daemon and driving it through WebDriver.
Still open
- The router is ready but not connected to the board. That connection comes with the board
itself. - Python that is waiting on the network or a file can't be interrupted until the wait ends, and
a script that catches every exception can ignore the interrupt. After 5 seconds Nanna stops
trying and logs a warning. - TypeScript 7 is still blocked on
vue-tsc.