Skip to content

windoze/atto-ui

Repository files navigation

atto-ui

atto-ui is a multi-window terminal UI framework built on Crossterm and Ratatui. The repository contains the Rust runtime, a Node N-API binding, a typed @atto-ui/core JavaScript facade, and a React reconciler package for JSX-driven terminal apps.

Packages

Package Purpose
atto-ui Core Rust crate with desktop chrome, window management, widgets, runtime component trees, themes, and PTY-testable app hosting.
crates/atto-ui-node / @atto-ui/node Native N-API binding exposing AppHost to JavaScript runtimes.
packages/core / @atto-ui/core Typed CommonJS facade, native loader, low-level spec builders, and runtime types.
packages/react / @atto-ui/react React reconciler, JSX host components, event bridge, and render() loop.
crates/atto-ui-node/npm/* Platform binary npm packages used by optional dependencies.
atto CLI External IPC client binary from the root crate for scripted query, invoke, and tree calls over ATTO_UI_SOCKET.
crates/atto-editor-app Multi-window terminal editor app with Explorer, tabs, split views, command palette, file/symbol/search pickers, and LSP-backed editor features.
crates/atto-agent-app Single-window TUI agent app built on atto-ui-chat, with DeepSeek protocol/client modules, local tools, skills, plan mode, context compaction, and deterministic mock PTY fixtures.
crates/atto-ui-terminal Reusable terminal emulator component: PTY sessions, split panes, copy-mode, command blocks, settings, and terminal pane IPC helpers. Powers the multiplexer below.
crates/atm atm (atto terminal multiplexer) — full multi-window terminal app built on atto-ui-terminal, plus a client-side tmux shim binary.

Requirements

  • Rust stable with edition 2024 support.
  • Node.js 22 or newer for local JavaScript tests.
  • Python 3 for PTY integration tests.
  • Bun and Deno are optional locally, but CI validates both runtimes.

Rust Quick Start

cargo build
cargo run --example demo
cargo test --all --all-targets

Useful validation commands:

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --all --all-targets

The deterministic test target used by PTY tests is available with:

cargo run --bin snapshot_app

Scripting And IPC Quick Start

Atto UI apps can expose the in-process DesktopInspector control plane over a Unix domain socket. For crossterm apps, set ATTO_UI_SOCKET before launch; the runner drains requests on the UI thread during each frame:

ATTO_UI_SOCKET=/tmp/atto-ui.sock cargo run --example demo

The root atto CLI is the first external client. It talks to that socket and returns either human-readable output or the raw protocol response with --json:

cargo run --bin atto -- --socket /tmp/atto-ui.sock --json tree
cargo run --bin atto -- --socket /tmp/atto-ui.sock query my-checkbox checked
cargo run --bin atto -- --socket /tmp/atto-ui.sock invoke my-checkbox toggle

The CLI currently covers the generic control-plane methods query, invoke, and tree. Terminal pane methods such as send_keys, capture_pane, split_window, and display_popup are available to Rust apps that register atto_ui_terminal::terminal_pane_ipc_handler(...) on their IpcServer; they are also the backend used by the tmux shim described below.

Terminal Multiplexer Quick Start

Launch atm with your login shell, or pass a command to make the initial terminal window run that command:

cargo run -p atm
cargo run -p atm -- top

atm supports floating terminal windows, tmux-style split panes, pane zoom/resize/close, dead-session restart, OSC title sync, command-block navigation for OSC 133/7 shell integration, local selection/copy-mode, OSC 52/system clipboard integration, tmux DCS passthrough for OSC 52, alt-screen wheel routing, and a File -> Settings window backed by JSON/YAML TerminalConfig.

Key defaults: Ctrl+B is the terminal prefix, Ctrl+B [ enters copy-mode, Ctrl+B % / Ctrl+B " split panes, Ctrl+B o / Ctrl+B Tab focuses the next pane, Ctrl+B + an arrow key selects a pane geometrically, Ctrl+B Ctrl+Arrow resizes the nearest split, Ctrl+B z toggles pane zoom, Ctrl+B x closes the active pane, and Ctrl+B F10 opens the menu while capture is active. Without a saved config, atm uses Ctrl+Shift+L to release capture so plain F10 can reach the menu; saved configs can change the release shortcut.

atm also builds a client-side tmux shim:

cargo build -p atm --bin tmux

When an app both enables the IPC socket and registers the terminal pane IPC handler, TerminalConfig.tmux.inject=true can make child processes see $TMUX / $TMUX_PANE and put the shim directory at the front of PATH. The shim supports common client commands such as send-keys, capture-pane -p, list-panes, split-window, select-pane, break-pane, and display-popup; it is not a tmux server implementation and does not support control mode (-CC).

Configuration is loaded from --config <path> when given, else ATTO_UI_TERMINAL_CONFIG when set, then $XDG_CONFIG_HOME/atto-ui/terminal.yaml, then ~/.config/atto-ui/terminal.yaml. See crates/atm/README.md for feature details, config examples, and focused validation commands.

Themes

The built-in theme presets are dark, light, and turbo. turbo provides the classic Turbo Vision palette with a blue desktop, gray dialog surfaces, cyan menu/status bars, and green selection highlights. Theme JSON/YAML files can opt into a preset before applying overlays:

base: turbo
colors:
  widget-accent:
    fg: yellow

Editor App Quick Start

Launch the editor app with optional files and folders. Folders become workspace roots; files open as tabs. If no folder is supplied, the first file's parent folder becomes the workspace root.

cargo run -p atto-editor-app -- .
cargo run -p atto-editor-app -- path/to/file.rs path/to/project

Key entry points:

Shortcut Action
F10 Open the menu bar.
Ctrl+Q Quit the terminal app.
Ctrl+Shift+P Open the command palette.
Ctrl+P Open the file picker.
Ctrl+Shift+F Open global workspace search.
Ctrl+Alt+K Start the app command prefix and show which-key choices.
F8 / Shift+F8 Jump to next / previous diagnostic.
Ctrl+. Request LSP code actions.
F2 Rename symbol.
Ctrl+Shift+Space Request signature help.
Ctrl+K Ctrl+F Format the active document.
F7 Toggle inlay hints.

LSP support is opt-in. Set ATTO_EDITOR_LSP_CMD_<LANGID> (for example ATTO_EDITOR_LSP_CMD_RUST="rust-analyzer") or the fallback ATTO_EDITOR_LSP_CMD; commands are split on whitespace.

Agent App Quick Start

Launch the agent app from a checkout:

cargo run -p atto-agent-app -- --workspace .

The app selects provider: deepseek when an API key is configured and --mock is not set; otherwise it selects provider: mock and shows a startup notice with next steps unless mock mode was explicitly forced. Live DeepSeek turns stream over HTTP/SSE through the same UI action path as the deterministic mock provider, including structured error display; default tests still avoid external network access. The ignored real-API smoke test can be run manually with:

DEEPSEEK_API_KEY=... cargo test -p atto-agent-app --test deepseek_real_smoke -- --ignored

Useful runtime options include --api-key, --base-url, --model, --temperature, --max-tokens, --workspace, --plan-mode, --config, --transcript, and --mock. Configuration may also come from DEEPSEEK_* / ATTO_AGENT_* environment variables, workspace .atto-agent.toml, and ~/.config/atto-agent/config.toml.

See crates/atto-agent-app/README.md for slash commands, tool and skill behavior, transcript persistence, and validation notes.

JavaScript Quick Start

Build the local native binding before running JS examples or tests from a checkout:

npm run build --prefix crates/atto-ui-node

Low-level @atto-ui/core usage:

const { AppHost, Button, Text, VStack } = require('@atto-ui/core')

const host = new AppHost({ headless: true, cols: 60, rows: 16 })
const callback = host.allocCallback()
const windowId = host.addDynamicWindow('Hello', [1, 1, 40, 8], VStack({ id: 'root' }, [
  Text('Hello from atto-ui', { id: 'title' }),
  Button({ id: 'ok', text: 'OK', onClick: callback }),
]))

host.step()
host.sendEvent(windowId, { type: 'key', key: 'enter' })
console.log(host.drainCallbacks())
host.dispose()

React usage:

const React = require('react')
const { Button, Text, VStack, render } = require('@atto-ui/react')

function App() {
  const [count, setCount] = React.useState(0)
  return React.createElement(VStack, null,
    React.createElement(Text, null, `Count: ${count}`),
    React.createElement(Button, { onClick: () => setCount((value) => value + 1) }, 'Increment'),
  )
}

const handle = render(React.createElement(App), { singleWindow: true })
process.once('SIGINT', () => handle.stop())

JavaScript Validation

npm run typecheck --prefix packages/core
npm test --prefix packages/core
npm run typecheck --prefix packages/react
npm test --prefix packages/react

Runtime compatibility smoke tests:

npm run test:runtime:node --prefix packages/core
npm run test:runtime:bun --prefix packages/core
npm run test:runtime:deno --prefix packages/core

The Deno smoke requires --allow-read --allow-env --allow-run --allow-ffi; the package script supplies those permissions. On POSIX platforms, the Bun and Deno PTY smokes start a real raw-mode terminal app and assert that alternate screen, cursor, mouse capture, and terminal flags are restored on exit. The PTY raw-mode smoke is skipped on Windows.

Documentation

  • docs/NODE_API.md documents the Node binding, @atto-ui/core, React package, component spec shape, events, and runtime compatibility notes.
  • crates/atto-ui-terminal/README.md documents the terminal emulator component, full terminal viewer demo, settings model, shortcuts, and terminal-specific validation commands.
  • docs/RELEASE.md documents CI coverage, the tag-based npm release workflow, and workspace-only app release scope.
  • NODE_BINDING.md is the design record for the Node binding and React host architecture.

CI And Release

CI runs Rust formatting, clippy, full Rust tests, native N-API build, Node/Core/React tests, React PTY/e2e coverage, Bun/Deno compatibility smokes, and npm pack dry-runs.

Publishing is tag-based. Pushing a v* tag runs the release workflow, first repeats the full Linux CI gate, then builds platform .node artifacts on macOS/Linux/Windows, verifies package contents, and publishes platform packages, @atto-ui/node, @atto-ui/core, and @atto-ui/react using NPM_TOKEN.

About

Turbo Vision inspired, feature rich Rust TUI lib with node/react binding

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages