Skip to content

Releases: iotash/iota

0.7.5 - 2026-10-26

Choose a tag to compare

@github-actions github-actions released this 26 Oct 15:42

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 "…" (or iota 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) answers held and 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
    in IOTA_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 another Rate 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 /model tries 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 · ↑ edit hint 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 as key:value, the keys are faint,
    so [srv:search limit:10 query:rust tui] reads as two arguments at a
    glance. … +N args and the … of a call still being written are faint
    too. The text is exactly what it was, and with NO_COLOR set 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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 20 Oct 07:31

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: 0 is an error, not a deadline of nothing. An
    mcp_servers entry with tool_timeout_sec: 0 used 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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 18 Oct 15:52

Release Notes

Changed

  • /tools is 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 login or failed, 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 stays down with
    them, showing why the new start failed, and you can try again. A server you
    have just logged in to with iota mcp login no 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 the brotli feature, 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 showed working with the chat idle until
    the pane was closed. Inside herdr, the shell tool's commands and the MCP
    servers now start without HERDR_ENV, so an agent started there leaves
    the pane to iota. The model is told this in its environment, and the
    herdr command line works as before — a pane it opens with herdr still
    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 stay connected in
    /tools, with nothing said in the chat. Now it shows as down as soon as
    /tools is 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 of Transport closed. This holds for a server
    reconnected from /tools too, 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 with tool_timeout_sec: in its mcp_servers entry.

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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 15 Oct 03:41

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
    Compacting when 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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 13 Oct 16:17

Release Notes

Added

  • /new starts a new session without leaving the chat. The session you
    leave is saved and stays on disk — /session or iota 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 dim New session <id> line marks where the new session
    begins (New session · not saved · /save keeps it when 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. /clear does the same thing and is not listed. A bot's session
    never ends, so a bot refuses /new and says why.

Changed

  • An agent without choices: is offered its model: alone. Since 0.4.0
    it was offered every models: entry, so a model declared for one agent
    showed up in every other agent's /model list. Write choices: 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
    -M or typed in the /model field is still read as the models: entry of
    that name, whether or not it is among the choices — -M fast is the model
    fast stands for, never a model id spelled fast. Only a word no entry has
    is a model id on the current provider.
  • /model rows no longer say what picking them does. A row is the model,
    the models: 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
    /compact with nothing to summarize still says only Nothing 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

  • /session takes the session it switches to as iota resume would.
    The switch restored the session's model tuning but kept the old session's
    record of where each setting came from, so the next /model switch 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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 13 Oct 05:51

Release Notes

Added

  • max_tokens: sets the output ceiling of an Anthropic-dialect model. The
    key goes on a models: entry or an agents: entry, and the agent's wins
    over the model's, as for effort, temperature and top_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 in meta.json with where it came
    from, and iota resume restores 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 /model tab or flag for it, and a
    hand-edited max_tokens: 0 in 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, that iota 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 -M resume (below). A chat that is not
    saved is told to /save first, 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 smaller max_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 truncated block: 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 raise max_tokens:, and that the edit reaches this
    session only after a restart, a resume and a /model switch away and
    back, while a lower effort in /model applies at once; the Responses
    dialect has no such setting, so there it is to lower the effort in
    /model or 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 the providers: name it runs on (session format v2) instead of a
    provider type and a URL, and iota 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.json alone, leaving the transcript and attachments as they are. It
    picks the provider by the endpoint the session recorded: the one entry of
    that type whose url: 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> -M moves the session for good. -M on a resume used
    to change only that run; the session now records the new provider and
    model, so the next plain iota resume continues 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.
  • /model rows 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 the models: 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 -m run 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 — no message_stop, no stop
    reason — was taken as complete, so -m and 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 /model picks that choice. Typing fast, the
    name of a models: entry, sent fast to the provider as a model id; the
    field now reads typed text as -M does, and provider:* 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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 05 Oct 00:14

Release Notes

Added

  • /status shows the version, the mode and the session's title. Three
    new rows: Version, what iota --version prints; Mode, the startup
    card's chat, agent or bot; and Title, 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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 02 Oct 20:27

Release Notes

Added

  • A third mode, bot: one session that never ends. mode: bot on an
    agents: entry makes that agent a bot — everything mode: agent is (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, /session cannot
    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 a remember tool (add, replace or
    remove one line); each write is shown in the transcript, the previous file is
    kept as MEMORY.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-save are
    refused, and so is iota resume <id> of the session a bot owns
    (session <id> belongs to bot coder; run iota run coder). The startup card's
    mode row says chat, agent or bot, each in its own color, and
    iota config init's starter carries a commented-out bot entry.
  • Newlines in the composer. Ctrl+J inserts a line break in every
    terminal. Alt+Enter and Shift+Enter do so where the terminal reports the
    modifier — Alt+Enter in Ghostty and tmux by default, and in Terminal.app
    with Option as Meta; Shift+Enter where the terminal sends it as its own
    key. Elsewhere they are a plain Enter and send the message, as before.
    Ctrl+Enter still sends. In Ghostty's default config Shift+Enter does
    nothing at all; the line keybind = shift+enter=text:\n in 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
    and IOTA_DEBUG_REGION. Everything else is configured in the YAML file.

Changed

  • workspace: true is now mode: agent. agents.<name>.mode takes chat
    (the default — what leaving workspace: out was), agent (what
    workspace: true was, byte for byte) or bot. There is no compatibility
    shim: a config that still says workspace: gets the unknown-key error, whose
    list of keys names mode (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 from Waiting for the model to Waiting for the first token (X-64).
  • One timer format. The status row's job segment and /jobs read 1m 12s
    like every other timer on the screen, where they had their own 1m12s; 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 with Response stalled — a
    heartbeat or a ping event 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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 29 Sep 16:13

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's agent_run declares
    ^agent\_run\_, and DeepSeek, which checks every pattern when 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,
    $schema included, as the server wrote it (X-57).
  • A job's page no longer holds up the prompt while its log grows. The
    /jobs page 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 | sh

Install 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/iota

Download 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

Choose a tag to compare

@github-actions github-actions released this 28 Sep 05:41

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's working then 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 | sh

Install 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/iota

Download 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