Releases: y0sif/taria
Release list
v0.2.0
The first release you can install. All three crates are on crates.io, the wire format has a specification someone can implement from, and what an agent is told about typing now matches what the app does with it. Nothing on the wire moved: PROTOCOL_VERSION stays 1 and stays frozen.
Highlights
The wire protocol has a specification. docs/architecture.md used to defer the per-message detail to the rustdoc on crates/taria, which is a fine answer for a Rust adopter and no answer at all for someone writing an adapter for another framework in another language. docs/protocol.md is that answer: framing, handshake, every message with a literal line, both vocabularies with their degrade rules, the acknowledgement model, connection ownership, the key grammar, the limits with their units, and what a version bump costs. Ten normative facts existed only in code and are written down for the first time, including that AgentInput is tagged on kind while the envelopes are tagged on type, that the 1 MiB line cap counts bytes, excludes the newline, and breaks the connection rather than skipping a line, and that tree depth counts the root as level one. Every literal line in it is real output, either lifted from the frozen test vectors or captured from a live session, the cap included: 1048576 content bytes parse and one more closes the connection.
Typing is described the way the app actually consumes it. The text an agent reads still carried the v0 model. AgentInput::Text said it was "lowered by the adapter into one key event per character", and the MCP instructions told every agent on connect to use type_text for "anything you would otherwise spell out with key". That second sentence is the conflation that once cost a task: one type_text of "deploy" lowered through the key handler, met the list's d binding, and was answered y by its own next character. Typing is now described where an agent meets it. Text goes to whatever surface the app puts typing into and never through its key bindings, a newline arrives as Enter and submits, a tab arrives as Tab, carriage returns are dropped, and an app with nothing accepting typing answers ignored rather than erroring.
ignored covers every kind of input, not just acts. It was documented act-first in both the protocol and the bridge's answer, so neither covered text sent into a surface that takes none, nor a key the grammar refuses. Both now list every kind that can earn it, and state the line the demo app was alone in knowing: a key that parses but is bound to nothing is delivered, not ignored, the same verdict a person gets for pressing an unbound key.
Action::Focus says what advertising it promises. It had no documentation at all, which left "focus the target first" as advice with no way to follow it. It now states that an act with it puts the keyboard on that node and the next snapshot shows that node focused, so an agent can check the move landed rather than assume it, and that set_value is not a focus call even in an app that moves the keyboard as a side effect of one. The other six built-in actions got their first documentation in the same pass.
The demo advertises the way in. Making focus the documented way to aim typing while the reference app advertised it nowhere left the advice without a worked example. An agent driving the demo found the hole on its first run: it wanted the keyboard and nothing else, saw only set_value, and ended up letting set_value carry an entire task title to get there. The input now advertises focus while the keyboard is elsewhere, the mirror of the dismiss it already advertised while holding it, and reports ignored where the act would do nothing, so the tree and the verdict agree.
Where taria sits, in writing. docs/comparison.md puts taria beside ht, tmux send-keys, and the PTY and MCP drivers, including the cases where one of those is the right answer: an app you did not write is out of reach for taria, and that is not a compromise, it is the only thing that works. A README FAQ answers what the docs previously answered only by implication.
A tag ships binaries. taria-mcp is what a person installs, so a tag now builds it for x86_64 and aarch64 Linux and for both macOS architectures, each tarball with its sha256. CI also checks the MSRV the crates promise, on a pinned 1.88, which nothing verified before.
Install
Driving an app that speaks taria:
cargo install taria-mcp --locked
Or take a prebuilt tarball from the assets below. Then point your harness at it, with the app's label:
claude mcp add taria -- taria-mcp --app <label>
Writing a TUI app that agents should be able to use:
cargo add taria-ratatui
It re-exports the protocol crate, so taria::{Action, IdSpace, Node, Role} is reachable as taria_ratatui::taria::{...} without a second dependency. docs/integration-guide.md walks through the retrofit.
Upgrade
Nothing to migrate. PROTOCOL_VERSION stays 1, no message or type gained or lost a field, and no published crate's Rust API changed.
If you were on a git dependency, the registry is now the shorter path: taria-ratatui = "0.2" in place of the git line. Tracking main still works if you want it.
If your app matches on AgentInput, this is a good moment to check that the wildcard arm the compiler asks for is not swallowing Text. Deleting a Text arm leaves the build and default clippy green while every type_text is answered ignored, which is how an app migrating from v0 loses typing without hearing about it. clippy::wildcard_enum_match_arm catches it.
Full Changelog: v0.1.0...v0.2.0