Repository navigation
Releases: iotash/iota
Releases · iotash/iota
Release list
0.7.5 - 2026-10-26
Release Notes
Added
- Other programs can message a running chat. Each interactive iota now
listens on a private Unix socket, and a script, a CI hook or another iota
can send it a line:iota resume <id> -m "…"(oriota run <bot> -m "…"
for a running bot) used to refuse a session that was open elsewhere — it
now hands the message to that chat and prints its receipt (woken,
queued,held, or why not:blocked,too-large,refused,
flooded). The message reaches the model at the next safe point — right
away when the chat is idle, between tool calls when it is busy, never in
the middle of one — as a dim[message from …]line, not as something you
typed, and a leading/is never run as a command. The model is told it
came from another process and is nobody's approval. A chat whose tools run
without asking (auto_run,auto_write) answersheldand asks you
before the model reads it. A message is not held back after a rate limit
or an Esc the way a finished job's notice is: it goes at once, as
something you typed would. Programs started from the chat find the socket
inIOTA_SOCKET. Only the same OS user can connect; there is no network
listener. Not available on Windows yet.
Fixed
- Hitting a provider's rate limit or usage cap no longer turns into an
endless loop, and Esc really stops. When a request was refused with
429 and retrying didn't help, every background job that finished started
a new attempt and printed anotherRate limited (429)error. Now iota
stops on its own: notices from finished jobs wait (each one says so in a
dim line), and while some are waiting iota tries once more later — when
the provider says it may (retry-after), otherwise after a minute, then
less and less often, at most every 30 minutes. Sending a message tries at
once and takes the waiting notices with it; switching to another model or
another provider with/modeltries at once there. What you type is
never overtaken by these automatic tries, and a notice is no longer lost
when its turn is refused by a rate limit (any other failure still drops
it, as before). The provider's own message, with its reset time if it
gives one, is still shown. Pressing Esc now also holds the notices
queued behind the turn you stopped: they go with your next message
instead of starting new turns. A 429 now gets at most three more tries
(it used to be ten), and a provider asking to wait more than a minute —
with a 429 or any other error — is no longer waited out silently: iota
stops and holds until then (a day at the most, however long it asks),
unless the provider explicitly insists on being retried. - The queue's
· ↑ edithint no longer promises what ↑ can't do. ↑
only brings back a message you typed — never the notice of a finished
background job — yet a queue holding nothing but such notices still
ended in· ↑ edit, and pressing ↑ did nothing. The hint now shows only
while the queue holds something you typed.
Changed
- Tool-call labels are easier to read. The
[shell ls -la]-style label
on every tool call — while the call is being written, while it runs, and
in the line it leaves behind — is no longer one block of cyan. The
brackets are faint, the tool's name is bold cyan, and what follows it is
cyan; when a call shows its arguments askey:value, the keys are faint,
so[srv:search limit:10 query:rust tui]reads as two arguments at a
glance.… +N argsand the…of a call still being written are faint
too. The text is exactly what it was, and withNO_COLORset the label is
plain text as before. - tokio is 1.54.1 (RUSTSEC-2026-0386). The advisory is about
AsyncFd's constructors, which neither iota nor any crate it builds on
calls, so it never applied. - rustls-webpki is 0.103.16 (RUSTSEC-2026-0382). It now rejects
certificate chains through the distrusted emSign intermediates, whose
private keys are public. This mattered on Linux, where iota checks a
server's certificate itself against the system's trusted roots; on macOS
and Windows the operating system checks it.
Install iota 0.7.5
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.7.5/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.7.5/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.7.5
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.7.4 - 2026-10-20
Release Notes
Fixed
- A reply that failed after it streamed is no longer sent again and
again. In an interactive session, when a stream broke at its very end —
after the whole answer was on screen — iota retried the request, which
printed the same answer again, up to ten times; a provider that fails the
same way every time looked like an endless loop. Once text has reached the
screen, a failure is now shown once and not retried, and what arrived is
kept (marked as possibly incomplete), together with the tool calls the
turn already ran. A failure before any text arrives is still retried as
before. tool_timeout_sec: 0is an error, not a deadline of nothing. An
mcp_serversentry withtool_timeout_sec: 0used to make every call to
that server time out the moment it was made. It is now refused when a
run that uses that server starts, naming the server:
config mcp_servers.<name>.tool_timeout_sec 0: want 1 or more. 0 does not
mean "no deadline": the deadline is what gives a headless run or a bot —
which have no Esc — its turn back from a server that stopped answering.
For a tool that runs long, write a large number instead.
Install iota 0.7.4
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.7.4/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.7.4/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.7.4
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.7.3 - 2026-10-18
Release Notes
Changed
/toolsis one list of where the tools come from. The two tabs, Tools
and MCP, are now one list:built in(the tools iota ships with) and then
each MCP server, with how many tools it has and how it stands —
connected,connecting…,down,needs loginorfailed, with the
reason in a few words. Enter opens a page for that source: for a server
its endpoint, transport, login, tool names, call timeout, the full reason
it failed (its stderr included) and its tools; Esc goes back to the list.- An MCP server can be reconnected from
/tools. Press Enter on a
server's page: it reconnects in the background, the page shows it
happening and how it went, and the chat gets one line —
MCP db reconnected · 3 tools, or why it did not. A reconnect that fails
does not take a server's tools away: one that had tools staysdownwith
them, showing why the new start failed, and you can try again. A server you
have just logged in to withiota mcp loginno longer needs a restart of
the chat to use the new login. - MCP failures say what happened and what to do. A server that did not
connect used to be reported with the library's own words — generic Rust
type names,when send initialize request, and sometimes a proxy's whole
HTML error page — with the actual reason buried or missing. Now the notice
is one line that names the server, what went wrong, and what to check:
⚠ MCP nb: can't reach https://example.com/mcp: connection refused — check the url, and that the server is running · details in /tools. A 404, a 5xx,
a web page where the MCP endpoint should be, a command that is not
installed, a server that exits during startup (its last stderr line is
shown), a handshake that never finishes and a rejected header are each
worded the same way. The full cause chain and the server's stderr are on
the server's page in/tools, and under the warning in a headless run. - rustls is 0.23.46 (RUSTSEC-2026-0346, -0347, -0348, -0349). iota keeps
no session store of its own, does not use Encrypted Client Hello and does
not enable thebrotlifeature, so the first three never applied. The
fourth did: a network attacker who answered one connection could make
later connections to the same host fall back from the post-quantum hybrid
key exchange to X25519 alone — a loss of post-quantum protection, with no
key exposed and no server authentication bypassed.
Fixed
- Resizing a slow or busy iota no longer breaks the screen for good.
When iota was starved of CPU — run at background priority, or on a machine
under heavy load — and the terminal took more than two seconds to answer
one of the cursor-position questions a resize asks, every later answer was
the one before it. After that, resizing the window could draw the prompt
in the middle of the screen with its top line gone and lose the last lines
of a reply, and every later resize in that session could do it again. iota
now tells its own answer from a late one, ignores the late one and waits
a little longer for its own. A slow machine now makes a resize slower, and
at worst a drag repeats a few of a reply's last lines in the scrollback;
nothing is lost, and the prompt stays whole at the bottom. - A herdr pane no longer stays "working" after an agent is run from the
chat. When the model ran another agent from the shell —claude -p …,
say — that agent's herdr integration took over iota's pane, and herdr then
ignored iota for good: the pane showedworkingwith the chat idle until
the pane was closed. Inside herdr, the shell tool's commands and the MCP
servers now start withoutHERDR_ENV, so an agent started there leaves
the pane to iota. The model is told this in its environment, and the
herdrcommand line works as before — a pane it opens withherdrstill
gets its own herdr identity, so an agent started in a pane of its own
reports there as it should. - A job that finished while no model was chosen no longer keeps the host
busy. If a background job's result woke a chat that had no model yet,
and the model choice was then cancelled, the host (herdr, cmux, the
terminal's progress indicator) went on showing the chat as busy until the
next turn. It now shows it idle. - An MCP server that stops mid-session is shown as stopped. A stdio
server that exited — killed, or crashed — used to stayconnectedin
/tools, with nothing said in the chat. Now it shows asdownas soon as
/toolsis opened or a call finds it gone, and the chat says so once, with
the last line the server wrote to stderr:⚠ MCP db: exited (its last stderr line: "RuntimeError: database connection lost") — its tools will fail until it is reconnected from /tools · details in /tools. Its tools
stay available to the model, and every call to them answers with a
sentence that says the server has exited and that it can be reconnected
from/tools— instead ofTransport closed. This holds for a server
reconnected from/toolstoo, even when no server connected when the
chat started. - A tool call an MCP server never answers no longer hangs forever. Every
MCP tool call now has a deadline, 30 minutes by default, after which it is
given up and the model is told why. A server whose tools legitimately run
longer can raise it withtool_timeout_sec:in itsmcp_serversentry.
Install iota 0.7.3
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.7.3/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.7.3/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.7.3
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.7.2 - 2026-10-15
Release Notes
Changed
- The status row says the chat is busy for the whole turn. It used to
show a spinner only while waiting for the model and go blank once the reply
started or a tool ran. Now one busy segment stays up from the moment you
send a message until the turn is over, and names what the turn is doing:
Waiting for the model,Thinking,Responding,Running tools, or
Compactingwhen it compacts the context before sending. Its clock counts
the whole turn, and stops while the turn waits for you to answer an
approval or a question. Which tool is running, and for how long, is still
shown on the tool's own line above the input.(ESC to cancel)now appears
only on the status row. When the turn ends with a background job still
running, the status row just shows the job, without a spinner.
Fixed
- A tool call the model keeps talking after is shown while it runs. When
a model wrote more text after composing a tool call, the call could run
with nothing on screen — its line appeared only once it had finished, its
clock starting there — or under the placeholder it had while being written
([write_file …]) instead of its own header with its arguments.
Install iota 0.7.2
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.7.2/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.7.2/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.7.2
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.7.1 - 2026-10-13
Release Notes
Added
/newstarts a new session without leaving the chat. The session you
leave is saved and stays on disk —/sessionoriota resume <id>brings
it back. The new one has its own id, in the same place, and keeps what the
chat was running under: the model and its settings (including any you
changed by hand), the system prompt, the tools and MCP servers, the
directory, and whether the chat is being saved at all. It starts with an
empty conversation, no attachments and the token counts at zero. The screen
is not cleared; a dimNew session <id>line marks where the new session
begins (New session · not saved · /save keeps itwhen the chat is not
being saved). Background jobs keep running, and their results go to the new
session. An unsaved chat a model has replied in asks before it is
discarded./cleardoes the same thing and is not listed. A bot's session
never ends, so a bot refuses/newand says why.
Changed
- An agent without
choices:is offered itsmodel:alone. Since 0.4.0
it was offered everymodels:entry, so a model declared for one agent
showed up in every other agent's/modellist. Writechoices:to offer
more; an agent that names no model at all still gets every entry. A model
outside the choices is still allowed, with a warning. A bare word given to
-Mor typed in the/modelfield is still read as themodels:entry of
that name, whether or not it is among the choices —-M fastis the model
faststands for, never a model id spelledfast. Only a word no entry has
is a model id on the current provider. /modelrows no longer say what picking them does. A row is the model,
themodels:entries that name it in brackets, and(current)on the one
the chat is running;(moves the chat)and(needs a new session)are
gone. The pick reports itself —Model switched to … on …, the
confirmation before a chat that has replied moves, or the refusal in a bot.- A compaction in progress shows in the transcript, not on the status
row.Compacting context…is the spinner row thinking uses, raised while
the summary is written and replaced by the outcome when it is done. A
/compactwith nothing to summarize still says onlyNothing to compact yet. - ruzstd is 0.9.1 (RUSTSEC-2026-0344). It only ever decompressed the token
table built into the binary, never input from outside.
Fixed
/sessiontakes the session it switches to asiota resumewould.
The switch restored the session's model tuning but kept the old session's
record of where each setting came from, so the next/modelswitch could
drop a setting you had made by hand, or keep one the old model's config had
supplied. A setting the session never recorded kept the old session's
value too; it now comes from the config, as on resume. And declining the
offer to compact no longer silences that offer in the session you switch to.
Install iota 0.7.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.7.1/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.7.1/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.7.1
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.7.0 - 2026-10-13
Release Notes
Added
max_tokens:sets the output ceiling of an Anthropic-dialect model. The
key goes on amodels:entry or anagents:entry, and the agent's wins
over the model's, as foreffort,temperatureandtop_p. It must be 1 or
more (config max_tokens 0: want 1 or more). A new session and a/model
switch evaluate it, the session records it inmeta.jsonwith where it came
from, andiota resumerestores what was recorded — the default included —
whatever the config says today; a bot takes it from its config each start.
Thinking counts toward it. There is no/modeltab or flag for it, and a
hand-editedmax_tokens: 0in a session is ignored. On any
other provider type the key does nothing and says so
(Warning: `max_tokens` does not apply to provider type … (ignored)).- A chat can move to another provider from
/model. A row on another
endpoint used to be refused with "start a new session there". Before the
first reply, picking it now moves the chat there. After a reply, iota first
saves the chat, then tells you how many earlier replies carry
provider-specific payload (reasoning, provider-side tool state) the target
does not replay, thatiota resume <id>continues on the new model
afterwards, and that picking the old row moves it back — and asks
Move this chat to <provider>:<model>?before anything changes. Your
settings come along as they do on a-Mresume (below). A chat that is not
saved is told to/savefirst, a model of another kind (an image model for
a chat) is still refused, and a bot never moves: its config does.
Changed
- The Anthropic dialect asks for up to 32000 output tokens, not 4096. A
thinking model could spend all of 4096 thinking and be cut off before it
wrote a word. The ceiling is a bound, not a charge: tokens are billed as
they are produced. An endpoint that caps lower answers a too-large value
with an error, so set a smallermax_tokens:for such a model. - An output the ceiling cut off is an error, never the answer. On the
Anthropic dialect (stop_reason: max_tokens) and on the Responses dialect
(response.incomplete: max_output_tokens), the chat shows a red
Output truncatedblock: what cut it, the tool call it was composing if
any (dropped, by name — it does not run), and what to do. On Anthropic
that is where to raisemax_tokens:, and that the edit reaches this
session only after a restart, a resume and a/modelswitch away and
back, while a lower effort in/modelapplies at once; the Responses
dialect has no such setting, so there it is to lower the effort in
/modelor ask for a shorter reply. Text the model did write is kept,
marked incomplete; with no text or completed tool rounds to keep, the turn
is rolled back, though what the request cost still counts in the session
totals. A cut is not retried — the same request would hit the same
ceiling. A half-finished thought is no longer
shown, saved or sent back to the model as the reply. With-m, a cut fails
the run (exit 1,Error: output truncated — …, nothing saved), a cut-off
compaction summary fails instead of replacing the history with a fragment,
and a cut-off title leaves the placeholder title. - Sessions record their provider by name, and resume there. A session now
stores theproviders:name it runs on (session format v2) instead of a
provider type and a URL, andiota resume— and/session— opens that
provider from the config, as if-M <provider>:<model>had been typed. A
name the config no longer defines is an error that says how to resume it
elsewhere (… which the config does not define; resume it elsewhere with -M <provider>:<model>), never a quiet fall back to another endpoint, and
a missing key on the agent's own endpoint no longer stops a session that
runs on another. Resuming replies another dialect wrote says how many carry
payload this one does not replay. Sessions written by earlier versions
(format v1) are no longer read: opening one is an error that names
scripts/session-v1-to-v2.py, which converts them once. The script only
reports what it would change until you add--write; it rewrites
meta.jsonalone, leaving the transcript and attachments as they are. It
picks the provider by the endpoint the session recorded: the one entry of
that type whoseurl:is that URL, or the type's built-in provider when
the session ran on the default endpoint. When that does not settle it (no
entry matches, two do, or another type's entry has taken the built-in's
name), it reports the bundle and leaves it as it is for--map TYPE=NAME
to decide. iota resume <id> -Mmoves the session for good.-Mon a resume used
to change only that run; the session now records the new provider and
model, so the next plainiota resumecontinues there. What you set by
hand — effort, temperature,top_p, the output ceiling — comes along unless
the config there sets it; what the old endpoint's config supplied stays
behind. The warning says so./modelrows read the same wherever the chat is. A row is
provider:model, or just the model when every choice is on one provider,
followed by themodels:entries that name it in brackets
(relay:vendor/fast [fast]). What picking it does is an annotation beside
it, like(current):(moves the chat), or(needs a new session)in a
bot.- Anthropic calls without tools stream too. A
-mrun with no tools, the
compaction summary and the title used a non-streaming request, which sends
nothing until the whole output exists and could outlast the 120 s wait for
a response. They now use the stream the chat uses, so an
Anthropic-compatible endpoint that cannot stream now fails there instead of
answering.
Fixed
- An Anthropic stream that stops early is an error, not an answer. A
response that ended before the message did — nomessage_stop, no stop
reason — was taken as complete, so-mand a compaction could succeed on a
fragment. - A failing request without tools is sent 11 times, not 121. A turn
that offered the model no tools retried inside a retry, so one failing
request (a 5xx, a dropped connection) could go out up to 121 times with
minutes of backoff. Every model call now has one set of ten retries. - Typing a choice's name in
/modelpicks that choice. Typingfast, the
name of amodels:entry, sentfastto the provider as a model id; the
field now reads typed text as-Mdoes, andprovider:*picks nothing.
Install iota 0.7.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.7.0/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.7.0/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.7.0
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.6.1 - 2026-10-04
Release Notes
Added
/statusshows the version, the mode and the session's title. Three
new rows:Version, whatiota --versionprints;Mode, the startup
card'schat,agentorbot; andTitle, the name the window shows —
for a chat that is not being saved too. A chat with no name yet, before its
first message or resumed from a session that never got one, says
(untitled). The page now ends Version, Mode, Session, Title.
Changed
- The Linux builds need glibc 2.28, and the install script asks for no
more. The Linux binaries are now built against glibc 2.28
(manylinux_2_28) instead of 2.34, so they also run on RHEL 8, Debian 11 and
Ubuntu 20.04. The shell installer takes its minimum from the build machine,
and until now that was 2.35 — more than the binary needed — so on the
RHEL 9 family and Amazon Linux 2023 (glibc 2.34)iota-installer.sh
refused a binary that would have run there. Both now say 2.28.
Fixed
- Local time on Windows is local. The Windows build shipped without a
time-zone database, so every local time iota showed or sent was UTC — above
all the date an agent is told is today: east of UTC it was yesterday's until
UTC caught up (until 08:00 in UTC+8), and west of it, tomorrow's in the
evening. The database is now built into the Windows binary, which grows by
about 0.2 MiB; macOS and Linux read the system's, as before.
Install iota 0.6.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.6.1/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.6.1/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.6.1
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.6.0 - 2026-10-02
Release Notes
Added
- A third mode,
bot: one session that never ends.mode: boton an
agents:entry makes that agent a bot — everythingmode: agentis (the
AGENTS.md chain, the skills), plus one session that belongs to it.
iota run <name>opens that session wherever you left it: the bot's
directory,~/.iota/bots/<name>/, holds a pointer to it, so a bot has no
/new, no picker and no resume to remember — close the pane, start it again
tomorrow, and the conversation goes on. A bot that has been away for an hour
or more, or that starts in a different project, is told so when it resumes.
The session is kept under~/.iota/sessions/like any other, but it opens
only as its bot: the session picker does not offer it,/sessioncannot
delete it, and an edited system prompt or model in the config takes effect
on the next start (X-58). - A bot remembers. Its session log is the full record; on top of it sits
~/.iota/bots/<name>/MEMORY.md, a Markdown file of at most 8 KiB with three
sections —## User,## Project: <name>,## Open threads— that goes out
with every request, the project sections cut to the project the bot is
running in. The model writes it through aremembertool (add, replace or
remove one line); each write is shown in the transcript, the previous file is
kept asMEMORY.md.prev, and a line you wrote yourself is one the model may
not change. It is a plain file: edit it while the bot runs and the next
request carries your version. - A bot compacts by itself. When the context passes the bot's threshold,
the bot first gets a turn to save what should outlive the compaction to its
memory (the memory flush), then compacts — without asking, since nobody may
be there to answer. The compaction keeps your last message and what came
after it verbatim. A compaction that fails twice in a row tells the host
(bot <name>: compaction failing — …) and waits for the context to grow
before it tries again (X-63). - What a bot needs, checked before it starts. A bot needs a chat model that
reports token usage and can call tools, and a context window of at least
32k; anything less is refused before a file is created
(bot "coder" needs a context window of at least 32k, this one is 8.2k). A
bot runs interactively and saved:iota run <bot> -m …and--no-saveare
refused, and so isiota resume <id>of the session a bot owns
(session <id> belongs to bot coder; run iota run coder). The startup card's
mode row sayschat,agentorbot, each in its own color, and
iota config init's starter carries a commented-out bot entry. - Newlines in the composer.
Ctrl+Jinserts a line break in every
terminal.Alt+EnterandShift+Enterdo so where the terminal reports the
modifier —Alt+Enterin Ghostty and tmux by default, and in Terminal.app
with Option as Meta;Shift+Enterwhere the terminal sends it as its own
key. Elsewhere they are a plain Enter and send the message, as before.
Ctrl+Enterstill sends. In Ghostty's default configShift+Enterdoes
nothing at all; the linekeybind = shift+enter=text:\nin Ghostty's config
makes it a newline, through tmux too. The composer now grows by the rows a
draft wraps to, and a queued multi-line message shows its breaks as⏎
(X-65). - The environment variables, written down. The README has a table of the
four a user might reach for:IOTA_SHELL,IOTA_GIT_BASH_PATH,IOTA_LOG
andIOTA_DEBUG_REGION. Everything else is configured in the YAML file.
Changed
workspace: trueis nowmode: agent.agents.<name>.modetakeschat
(the default — what leavingworkspace:out was),agent(what
workspace: truewas, byte for byte) orbot. There is no compatibility
shim: a config that still saysworkspace:gets the unknown-key error, whose
list of keys namesmode(X-58).- One process writes a session at a time. Two terminals that resumed the
same session used to interleave two conversations in one log. The second
iota resume <id>is now refused (session <id> is open in another iota process (pid N)), and/session's Delete tab skips a session that is open
elsewhere. On a filesystem that cannot lock (some NFS and SMB mounts), iota
refuses to open or delete a session there rather than write without the lock
(X-60). - A compaction carries the previous summary forward. The summary an earlier
compaction left was fed to the next one as if you had said it, so every pass
summarized a summary. It now goes in as the previous summary, to be carried
forward or dropped where resolved (X-62). - A compaction keeps your last turn, not the notice after it. A host notice
— a background job's completion, for one — that arrived after your last
message used to take its place as the start of the kept tail, and your
message went into the summary. The tail now starts at your last message, in
every mode (X-63). - The busy row says when the model has answered. Once the response has
started, the row moves fromWaiting for the modeltoWaiting for the first token(X-64). - One timer format. The status row's job segment and
/jobsread1m 12s
like every other timer on the screen, where they had their own1m12s; a
job's first second reads<1s.
Fixed
- A provider that stops sending no longer hangs the turn forever. A stream
that sends no byte for 300 seconds now fails withResponse stalled— a
heartbeat or apingevent keeps it alive — and is not retried, since a
retry would sit out the whole wait again. What the turn finished before the
stall stays: its tool calls and their results, and the partial reply, marked
as cut short. The bound is fixed, not a setting. Connections now time out
after 15 seconds, and HTTP/2 connections are pinged while a stream is open,
so a dead link is noticed beside the 120-second wait for the response's
headers that was already there (X-64). - A finished answer is no longer taken for a stall. A stream ends at its
protocol's end —[DONE],message_stop,response.completed— rather than
when the server closes the body, which some relays never do (X-64). - The session title no longer holds up the next message or the exit. The
pass that names a new session could keep the composer, ESC and Ctrl+C waiting
for up to 30 seconds before the next message and before the exit. Nothing
waits on it now; an exit gives it up and the placeholder name stands (X-64). - Closing the terminal no longer loses the turn in progress. A hangup
(SIGHUP — closing the window or the pane, killing the tmux server) used to
end iota on the spot; it now takes the SIGTERM path: the running turn is
interrupted, what it finished is saved, the MCP servers are closed, and iota
exits even though the terminal is gone. A second SIGTERM forces the exit. - An interactive iota ended by SIGTERM or SIGHUP exits 130, after the same
wind-down as a normal exit, as a headless run already did; Ctrl+D is still a
clean 0 (I-03). - A session left with an unanswered tool call loads and keeps working. A
crash or power loss in the middle of a tool round could leave the log ending
on a call with no result, and every later request was refused by the
provider. A resume now answers such calls as interrupted and says so; and a
record too long for the log to read back is cut to fit when it is written,
instead of making the session unreadable (X-61).
Install iota 0.6.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.6.0/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.6.0/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.6.0
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.5.2 - 2026-09-29
Release Notes
Fixed
- An MCP tool whose schema escapes a character needlessly no longer fails
the turn. JSON Schema's regexes are the Unicode-mode dialect, where an
escape like\_is an error; exa'sagent_rundeclares
^agent\_run\_, and DeepSeek, which checks everypatternwhen the
schema names its$schema, refused every request that carried the tool.
iota now drops such backslashes when it lists a server's tools — the
pattern matches the same strings — and leaves the rest of the schema,
$schemaincluded, as the server wrote it (X-57). - A job's page no longer holds up the prompt while its log grows. The
/jobspage read the job's log on every refresh from the loop that draws
the screen; it now reads it off that loop, once a refresh, never more than
a fixed number of bytes, and for as long as the page is open — output from
a command the job left running in the background still shows (X-50). - The host no longer shows iota idle while a job's end is still to be
taken. The host's state followed the count of running jobs, so when one
job ended as another started the count did not move: herdr, cmux or the
terminal's progress could show iota idle before it had taken the ended
job's notice, and a job that never started could keep it busy. Each end now
reaches the host as its own event, in the order the jobs changed (X-50).
Install iota 0.5.2
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.5.2/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.5.2/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.5.2
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.5.1 - 2026-09-28
Release Notes
Fixed
- A reply streaming through a narrowing no longer loses its last lines. A
line laid out for the wider window and printed while the window was being
made narrower went in under the blank rows the resize had left above the
prompt; when the drag ended, when the next line came or when the prompt
grew, iota took those rows back as blank and the line went with them. Such a
line now fills the blank rows first, and only what does not fit is inserted
above them, so none of the three touches a printed line (X-52). /jobs, the status row and the host no longer hold on to a job that has
ended. When two jobs changed at nearly the same moment, the older of the
two updates could arrive last: the list, the status row's job segment and
the host'sworkingthen stayed on a set of jobs that was no longer the one
running. The updates now go out in the order they were taken, so the last
one is the running set (X-50).
Install iota 0.5.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/iotash/iota/releases/download/v0.5.1/iota-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/iotash/iota/releases/download/v0.5.1/iota-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install iotash/tap/iotaDownload iota 0.5.1
| File | Platform | Checksum |
|---|---|---|
| iota-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| iota-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| iota-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| iota-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| iota-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |