SUI Desktop is a native app window with projects, streaming chats, tool
approvals, SSH workspaces, a browser preview and element/area annotations.
It has a light and a dark theme, a collapsible sidebar, and a customizable
slime companion that works, hops, and asks beside your conversation without
ever covering it. The Rust agent runs on the machine holding the workspace;
remote previews use SSH port forwarding. The app can install SUI on an SSH
host and configure providers from its connection screen. Choose Add a provider →
ChatGPT → Continue with ChatGPT to connect an eligible ChatGPT plan without an
API key. Sign in once, then choose any account model beside the message box. OpenAI API, Ollama, and compatible APIs
have separate setup options. Choose local folders
with the system picker, or select an alias from ~/.ssh/config and browse
folders on the SSH host. Recent workspaces are remembered per host. See
desktop/README.md for build, setup, the Mac update button,
and the current notarization limitation.
The terminal UI remains available.
Click the model badge above the desktop composer to search all visible models from each connected ChatGPT account, alongside profiles configured on the host. Sign-in does not require selecting or pinning a model. Sui stores the account catalog and reasoning metadata privately on the workspace host for 15 minutes; Refresh models fetches it again. Account changes invalidate the saved catalog, and a failed refresh shows an explicit warning when using older cached choices.
Model switching is available between turns. Selecting a different model or reasoning level starts a new chat, preserves your draft, and keeps the previous chat in recent chats. Saved chats retain their model and reasoning level. ChatGPT reasoning choices and defaults come from the selected model's catalog; unsupported catalog modes appear disabled. Other providers use known model capabilities. The mode selector offers Ask before changes, Auto edits, and YOLO for the current chat, including while an approval is waiting. YOLO allows file edits and simple inspection commands; arbitrary scripts, potentially destructive commands, web access, and browser actions still ask. A pending action can be approved once while switching to YOLO. Long command previews scroll inside the approval card so its buttons stay reachable.
Drag PNG, JPEG, or WebP images onto the app, paste them, or use the attachment
button, then press Send. Up to four images, 4 MiB each and 8 MiB total, travel
over the existing SSH connection to the workspace host. ChatGPT image support
comes from account catalog metadata; other providers need trusted
image_input = true configuration. Image attachments are kept in private,
integrity-checked replay files on that host, outside journal text and exports.
Reopening Desktop reconnects to the last workspace and resumes its chat; connection settings contain no credentials or saved approvals. A session interrupted during a tool call can be recovered into a fresh run with its outcome marked unknown. Recovery never reruns historical commands.
If an SSH host reports an older CLI, choose Install or update SUI on SSH host and retry. Desktop checks compatibility before invoking provider commands.
Mac Desktop releases from 0.11.6 use ad-hoc signatures, without Apple Developer ID signing or notarization. To install one, run the explicit installer:
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/fordft/sui/releases/latest/download/install-desktop.sh | shIt verifies the matching Apple Silicon or Intel DMG checksum and app signatures,
then installs to ~/Applications/SUI Desktop.app and removes download quarantine
from that app only. Direct DMG downloads still require macOS approval. Releases
before 0.11.6 do not include this installer.
Cache-first multi-agent coding harness. A strong model decomposes and audits; cheap workers implement in isolated git worktrees; deterministic gates decide what ships. Ships with a mouse-enabled terminal UI — configure providers, run tasks, and watch every step from one screen.
sui # the TUI — everything happens here
sui --mission # TUI in mission mode (orchestrator → workers → auditor)
sui --yolo # auto-approve everything (same flag as the `a` key)
sui "fix the bug" # headless one-shot — no UIPick one — Homebrew (recommended, macOS + Linux) or the shell installer. Don't stack both: they install the same binaries to different prefixes, and whichever comes first on PATH wins.
brew install fordft/tap/sui-ai
suiThe sui-ai formula installs prebuilt binaries (sui, sui-mission,
sui-certify) — no Rust or compilation needed. Update with
brew upgrade sui-ai; remove with brew uninstall sui-ai (your config,
credentials, and journals are never touched).
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/fordft/sui/releases/latest/download/sui-installer.sh | shChecksum-verified alternative (recommended — also checks for a foreign
sui on your PATH):
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/fordft/sui/releases/latest/download/install.sh | shInstalls to ~/.sui/bin (user-owned, no sudo). If ~/.sui/bin isn't on
your PATH yet, launch with the absolute path: ~/.sui/bin/sui.
Prefer to inspect first?
curl -LsSf -o sui-installer.sh \
https://github.com/fordft/sui/releases/latest/download/sui-installer.sh
less sui-installer.sh
sh sui-installer.shName-collision note — the Mysten blockchain toolchain also ships a
sui command. The shell installer always targets ~/.sui/bin and never
touches another installation; install.sh additionally warns when a
different sui already owns the name on PATH.
Rollback — pin a release:
SUI_TAG=v0.4.2 sh -c "$(curl -LsSf \
https://github.com/fordft/sui/releases/download/v0.4.2/install.sh)"Choose a provider per role — solo, orchestrator, worker, and auditor can each use a different profile. Settings → "+ add provider" includes:
| Provider | Connection |
|---|---|
| OpenAI / ChatGPT Codex | Browser sign-in; native Responses API |
| GitHub Copilot | GitHub device sign-in; requires Copilot access |
| Ollama | Local OpenAI-compatible server; no API key required |
| Custom OpenAI-compatible | Your endpoint, with optional API key |
| DeepSeek / OpenRouter | Existing API-key presets |
For accounts, choose Sign in in the provider form. Sui opens a browser; Copilot shows a device code, and Codex waits for a local callback. Esc cancels sign-in. Choose a model, save the profile, and assign it to a role.
The same setup works from the CLI:
sui auth codex
sui auth copilot
sui auth ollama --model your-installed-model
sui auth openai-compatible --base-url http://localhost:8000/v1 --model your-modelThe alias sui login --provider copilot also works. Bare sui auth keeps
its existing Codex behavior. Use --manual on SSH/headless machines for
Codex; Copilot's device flow already works across machines. Local or custom
endpoints accept --key-env YOUR_API_KEY_VAR when authentication is needed.
Ollama must be running and the chosen model must be installed.
Model pickers fetch the provider's catalog, including the signed-in Codex and Copilot account catalogs. You can always type an exact model ID. Catalog entries describe provider claims; access and tool support still need a successful request/certification.
Account tokens live in separate owner-only files under ~/.config/sui/,
refresh automatically, and stay out of profiles, journals, model messages,
and exports. SUI_HOME relocates this directory and the global config.
Copilot refreshes are serialized across workers and Sui processes.
Subscription cost remains unknown; usage is shown only when the provider
reports it. Provider login grants no web-tool or destructive-tool permissions.
These native account integrations use the same provider protocols examined in jcode; see third-party notices. Account eligibility and upstream authentication/API changes can affect access. Real account login and inference remain unverified until exercised with your own account.
DeepSeek, OpenRouter, a local proxy — anything that serves
/v1/chat/completions. Configure in the TUI setup screen or
~/.config/sui/config.toml:
[profiles.cheap]
base_url = "https://api.deepseek.com/v1"
model = "deepseek-chat"
key_env = "DEEPSEEK_API_KEY"
pricing = { input = 0.28, cached = 0.028, output = 0.42 } # $/MTokCredentials entered in-app are masked and stored per your choice: OS keyring, plaintext config, session-only, or env var. On headless machines with no keyring, the config-file store is the default.
Already ran codex login? That's all you need — Sui detects
~/.codex/auth.json and auto-registers a codex profile (model follows
your Codex CLI config). Pick it in Settings → any role, or pass
--control-profile codex / --worker-profile codex to sui-mission. No
API key, no TOML.
To customize, an explicit profile wins over the auto-registered one — or use Settings → "+ add provider" → "ChatGPT (Codex OAuth)":
[profiles.codex]
kind = "codex-oauth"
model = "gpt-5.5"No Codex CLI login? Sign in directly: sui auth (browser flow;
--manual pastes the callback URL for headless/SSH). This calls the
Codex backend's Responses API — subscription access, not API billing,
so cost fields report unknown rather than zero. Tokens refresh
transparently and never touch journals or prompts.
All roles run Sui's native agent loop with a model/provider profile. The Codex OAuth profile uses the Responses API through this same loop.
ACP executable-agent support has been removed. Remove legacy [agents] tables and replace acp: values in [ui] roles with native profile names. Missions use --control-profile, --worker-profile and optional --auditor-profile. The old --*-agent flags and acp-bridge command are unavailable. Configuration is never rewritten automatically; historical journals remain available through export.
First run opens setup — add a profile, pick models per role, type a
task. The main screen puts the conversation first, with a growing multiline
composer and compact header. Completed activity folds to one line
(3 reqs · 7 tools · 12s); final answers and failed-step excerpts stay
visible. Headings, fenced code, and quotes get distinct styles; their
original text remains available for selection and details. Expand activity
for bounded previews or open its details. A running timer and explicit
approval state show what is happening; a finished run displays its runtime
outcome without implying verification.
Rendered from the TUI's own frame buffer at 150×46 with the animation clock pinned — in a terminal the slime hops, blinks, and follows your typing.
Terminal capture using a local mock provider. More views: empty screen, command palette, permission prompt, terminal-native colors on a light background.
Commands and views: Ctrl+P or the clickable header opens a searchable
palette. Type to filter, use ↑↓ and Enter to choose, or Esc to return to
your draft. The palette sizes to its results and keeps the selected row
visible. Chat, Tasks, Changes, Usage, and Settings remain available;
Ctrl+T cycles views and Esc returns to Chat. Existing /solo, /mission,
/export, and /help commands still work.
Tasks, Changes, and Usage scroll independently with the wheel, arrow keys,
Page Up/Down, and Home/End. Their position indicators show when more content
is available. Usage keeps each agent/model pair separate: — means a
measurement is missing, 0 means a reported zero, and + (partial) marks
totals with missing measurements.
Usage also shows a token-weighted cache percentage, with measured-request coverage. Only complete, non-estimated input/cache pairs with cached ≤ input enter the percentage; failed or missing-usage requests remain in its coverage denominator. First requests in each observed session/epoch and subsequent requests have separate rates. The latest epoch, request purpose and first-delta latency are shown when recorded. Observed model/prefix/tool/guidance/cache-key changes are local diagnostics; provider TTL/routing causes remain unknown.
Appearance: Settings → theme switches between slime (default: black and
deep blue with an azure gel slime), dark, and terminal (your terminal's
foreground, background, and ANSI colors). The preference persists as
[ui].theme. No special font is required; NO_COLOR is respected. Solo
starts with the sidebar hidden; Mission shows agents and run status at widths
of 110 columns or more. Ctrl+B toggles it; Tasks remains accessible on
narrow screens.
The slime and motion: the home screen is a small animated world. A
pixel-art slime blinks, hops, follows your typing with its eyes, naps when
you leave it alone, and squishes when you click it; a short splash plays at
launch (any key skips it). While a task runs, the composer border flows,
status text shimmers, and a companion slime keeps you company under short
transcripts; a successful run ends with a burst of bubbles. Once a
conversation is under way, a small slime lives in a lane just above the
composer: it runs back and forth while a task works, hops when it succeeds,
slumps when it fails, bounces and asks ? when it needs your approval, and
naps when you leave it alone. The lane is reserved rows, so the slime never
covers transcript text; it costs 2–3 transcript rows on terminals at least 26
rows tall and does not appear on shorter ones. Click it to poke it. Empty
Tasks, Changes, and Usage views get a napping slime. Everything here is
presentation: it never reaches model requests, journals, or exports.
- Pixel art needs a truecolor terminal (
COLORTERM=truecolor). WithNO_COLOR, theterminaltheme, or a terminal that announces less, Sui draws a text slime instead. - Settings → motion (or Cycle motion in the palette) chooses
full,calm(~8 fps, no splash, bubbles, or confetti — the default over SSH), oroff(frames are static). It persists as[ui].motion;SUI_MOTIONoverrides it for one launch.
Input and keys: Enter sends · Ctrl+N inserts a newline · ↑ recalls
history from an empty composer · Tab focuses activity · v opens selected
step details · Ctrl+R cycles reasoning · Ctrl+O switches Solo/Mission ·
Ctrl+S stops · Ctrl+Q quits · F1 opens help. The composer grows to six
text rows, then scrolls to keep the cursor visible. Editing respects
Unicode grapheme boundaries. Editing a recalled task makes it your draft;
history navigation no longer replaces that edited text. A draft entered
during a run is kept until you send it after the run finishes. Mode changes
are available after the current run stops.
Ctrl+B, Ctrl+O, Ctrl+R, and F1 also work while activity has keyboard focus.
Changing reasoning visibility keeps the selected activity when it remains visible.
Mouse (also over SSH): wheel scrolls, click expands activity or opens
commands, drag selects and auto-copies via OSC52. Shift+drag uses native
terminal selection. Toggle capture in Settings → mouse.
Mutating tool calls ask first: y approves once, a approves for the
session (AUTO in the header), n/Esc denies. Enter never approves.
Browser, terminal and web consent do not enable local AUTO.
Permission previews scroll with ↑↓, PageUp/PageDown, or the wheel;
decision buttons remain fixed and clickable. Ctrl+S and Ctrl+Q work
inside prompts. An ask arriving while you type in a dialog is queued;
closing the dialog surfaces it without treating typed text as approval.
Native agents get two first-class tools — web_search and web_fetch —
backed by Exa's hosted MCP service. Off by default;
enable in Settings → web research (off/ask/auto) or
[web] access = "ask" in global config. Anonymous access works but is
rate-limited; an optional Exa API key (Settings → exa api key, or
SUI_EXA_API_KEY) raises usage.
Search results come back as source IDs ([S1], title, URL, snippet) —
snippets are labeled snippets, not fetched pages. web_fetch(url) reads
one source as bounded Markdown; cached hits are labeled with their age.
The policy is independent of tool auto-approve: YOLO never turns web
access on or bypasses ask. In ask mode, y permits one request and
a grants web access to the current native agent, separately from local
tools. Changing web settings revokes that grant; the next Solo task uses
the current settings while keeping its conversation. Queries/requested
URLs leave the machine. Unsafe
targets — private/link-local/metadata IPs, credential-bearing or
secret-shaped URLs, non-http(s) schemes — are refused before anything is
sent. Per-run request caps apply across all workers in a mission.
Ask Sui to test a web or terminal interface directly. Native agents have
browser, terminal, and view_image tools; Sui opens and owns the
sessions. No monitor, desktop, Xvfb, separate Playwright CLI, or ttyd
server is required, including on Ubuntu over SSH.
browser: open a URL, inspect an accessibility snapshot, click/fill by role and exact name or CSS selector, press keys, resize, screenshot, close.terminal: start a real program with arguments in the workspace, type/press keys, resize, inspect the interpreted terminal screen, screenshot, close. ANSI cursor movement and alternate screens are rendered with xterm, rather than treated as a raw output log.view_image: send a workspace PNG/JPEG/WebP (up to 4 MiB) as image input.
On first use, independent UI consent covers downloading pinned Playwright/xterm packages and Chromium into the user cache. Later sessions reuse the cache. The server needs Node.js 20+, npm, and Chromium system libraries; Sui does not install privileged OS packages. No project dependencies are modified. Session processes are killed on cancellation, timeout, close, or agent drop. Each native agent owns its own sessions.
Browser requests and WebSockets are restricted to HTTP(S)/WS(S) on
localhost, 127.0.0.1, and [::1], including redirect destinations.
Service workers and downloads are disabled. To authorize unattended UI
sessions, set [browser] approved = true in global user config;
allow_remote = true separately permits remote traffic, and
auto_install = false prevents automatic dependency downloads. Project
config, YOLO, and web-research settings cannot enable these permissions.
This is an automation guard, not an OS sandbox; terminal programs run
with user privileges and a scrubbed environment, like the bash tool.
Image-capable API profiles must declare image_input = true in trusted
[provider] or [profiles.<name>] config. Codex OAuth defaults to image
input. Text-only profiles still use snapshots and can save screenshots,
but receive an explicit visual review unverified result. Images stay
in memory unless the tool requests a workspace-relative path; image
bytes are never placed in journals or exports. Browser screenshots mask
password fields and elements marked data-sui-private; snapshots exclude
these fields too, and fill refuses private/password targets. Use test data.
Screenshots are viewport captures. Check persisted application state as
well as appearance before declaring a flow verified.
The real browser/PTY integration test is opt-in because it can download dependencies:
cargo test --test ui_headless -- --include-ignoredNative agents can call inventory directly in Solo or any Mission role;
there is no server, index command or configuration to start separately.
files lists workspace-relative paths. symbols locates named functions,
methods, types and other declarations using Tree-sitter, with file and
1-based start/end lines for the next read_file call. For example:
{"action":"symbols","query":"checkout","path":"src","limit":20}Queries are literal, case-insensitive substrings of names or paths.
Symbol extraction supports Rust, JavaScript/JSX, TypeScript/TSX, Python
and Go. Other languages remain discoverable through files and shell
search. Common forms include trait signatures, type aliases and direct
function/class bindings, including parentheses and TypeScript assertions.
Names are retained in full when they fit the output budget. This is a
syntax inventory; it does not resolve references, dynamic dispatch,
macro expansion or a semantic call graph.
Each call scans current files, including uncommitted edits and new files,
inside that agent's workspace/worktree. Ignore rules are loaded only from
bounded, regular, non-symlink files within that workspace: .ignore takes
precedence over .gitignore, then in-workspace .git/info/exclude.
Each control file is limited to 64 KiB and each rule line to 4 KiB.
Unsafe, oversized, unreadable, non-UTF-8, NUL-containing or malformed rules
prune the affected subtree and mark the scan partial with an ignore warning.
Global excludes and outside-workspace Git metadata are not read;
a worktree's .git pointer is not followed, while its workspace ignore
files still apply.
Symlinks, dependency/metadata directories and known credential-file names
are always excluded. Root target, build, dist and coverage
directories are skipped by default; an explicit path bypasses this default
exclusion while still respecting workspace ignore rules and safety checks.
Source directories such as src/build and src/target remain visible.
No files are written, and no local parse cache or index is maintained.
Results stay in appended tool history; no changing repo map is inserted
into the stable prompt.
Scans have a three-second cooperative budget, a 10,000-entry enumeration
budget before filtering, 32 MiB of source/ignore input and 500,000-node
limits. bytes_read includes rejected input; source files over 512 KiB
are skipped using metadata before reading. Cancel waits for the worker
to observe cancellation and finish; these limits do not impose a hard
timeout on stalled remote filesystems. Output defaults to 50 rows (max
200) with a 24 KiB row budget. Skipped files, syntax errors, unsupported
files and truncation are reported; partial results never prove a symbol
is absent. Narrow path or query when needed.
Adding this tool changes the native tool/system signature. Sessions from v0.5.0 and earlier remain inspectable/exportable, but Resume requires the same recorded signature and therefore a matching older binary. Start a new session to use inventory.
Native agents can call code_context in Solo and Mission roles to collect
bounded source regions in one tool result. It runs inside Sui on headless
servers, using the embedded parsers; there is no separate command, language
server, model call or network service to start.
{"action":"search","query":"cache usage tokens","path":".","limit":5,"max_bytes":12000}Search uses concrete terms from the task: identifiers, paths and source text. Whitespace-separated terms match case-insensitively; more covered terms and name/path matches rank higher. Results are lexical candidates, with one selected region per file (default five files, maximum twenty), including eligible tests, documentation and configuration. They contain numbered source excerpts, selection reasons and source hashes. Matching names or text does not prove that two symbols refer to each other or that every relevant file was found. For a task in another language, the agent can supply identifiers or terms used in the codebase.
{"action":"read","path":"src/tui/usage.rs","line":50,"max_bytes":12000}Read selects the enclosing syntax definition around a known 1-based line,
with nearby documentation, attributes, enclosing type headers and bounded
imports where recognized. Plain text and unsupported syntax use a line
window. Follow the output's source locations to expand with another
code_context read or read_file; use code_intel separately when Rust
semantic definitions or references are needed.
The complete tool result is bounded by max_bytes (default 12,000, range
1,024–24,000). This is a byte budget; actual provider tokens still come from
provider usage. Omitted regions and incomplete scans are explicit. Source is
observed from current files and hashed, rather than summarized by a second
model. Hashes identify the bytes read; they do not establish an atomic
repository snapshot or prove that the task has enough context.
omitted counts matching files that were not returned;
omitted_source_lines counts gaps within returned excerpts. Scan coverage,
parser coverage and excerpt completeness are reported separately.
The tool shares inventory's bounded traversal, ignore policy, credential exclusions and regular-file checks. Files containing recognized credential formats or credential-like literal assignments are withheld before hashing, parsing, caching or returning source. Incomplete credential literals are also withheld. This is a heuristic: unusual or dynamically assembled secrets can evade it, and realistic example tokens can cause a file to be withheld. Accepted excerpts remain exact source. A per-agent in-memory cache reuses syntax facts only after checking freshly read source content. Ignore rules are rechecked on each call; worktrees do not share the cache. Local parse cache counters are separate from provider prompt-cache usage. Every call returns actual excerpts, including cache hits and calls after compaction. Results append to tool history; the stable prompt is not rewritten. The shared scan budgets are three cooperative seconds, 10,000 entries, 32 MiB of source/ignore input, 512 KiB per source and 500,000 syntax nodes. The cache holds at most 128 entries and 2 MiB of accounted syntax/key data; this is not a process-memory limit. Cancellation joins the worker, while stalled filesystem calls must return before cooperative cleanup can finish.
Adding code_context changes the native tool/system signature. Start a new
session after updating Sui; older sessions remain inspectable/exportable,
and Resume requires their recorded signature.
patch_files lets a native agent preview and then apply exact replacements
across existing UTF-8 workspace files. Preview is read-only; apply uses the
same ordered edits and the returned preview_id:
{"action":"preview","edits":[{"path":"src/lib.rs","old_str":"old text","new_str":"new text"}]}
{"action":"apply","preview_id":"<ID from preview>","edits":[{"path":"src/lib.rs","old_str":"old text","new_str":"new text"}]}Preview returns a bounded -/+ replacement diff (not a complete unified
file diff), file/edit counts, and an ID calculated from the edits and original
file bytes. If the diff exceeds 12,000 bytes, split the patch; no apply ID is
issued. Every old string must match exactly once at its step; multiple
edits to one file run in order. Apply rejects changed files or edits and
requires ordinary local mutation approval (preview does not). Read the source
before editing and run tests after applying. New files still use write_file.
The tool limits one patch to 20 replacements, 128 KiB of input text, 512 KiB per file and 2 MiB of total source. It refuses symlinks and non-regular files, stages output next to each target, preserves file permissions and attempts to restore earlier files if a later write fails. Multi-file updates are not crash-atomic or protected against concurrent filesystem writers; a power loss or failed rollback may leave a partial patch. On rollback failure the backup is retained at the path reported in the error for manual recovery.
Adding patch_files changes the native tool/system signature. Start a new
session after updating; older sessions remain inspectable/exportable and
Resume requires their original signature.
session_info is a read-only native tool for the current conversation: it
returns the session/run IDs, workspace, journal path, export command, and
bounded recorded tool/request activity. It reads no other sessions or
credentials and grants no permissions. After Resume, it reports the new run's
paths while retaining the conversation identity and recorded observations.
Its schema also requires a new session after updating Sui.
Sui's Rust Bash result renderer reduces recognized Cargo and Git diffstat output
before appending it to model history. Compaction needs no extra executable,
package, shell hook, service or model request.
The Bash tool defaults to output: "auto". For a simple cargo test,
build, check or clippy invocation, completed, untruncated exit-zero
captures can collapse validated passing-test records and compilation
progress. Test totals, ignored tests, warnings and unrecognized text stay
in their original order. Failures, timeouts, cancellation, structured output
and shell compositions keep the existing capture behavior. A compact view
is used only when its complete envelope is smaller than the original.
Pipe read failures or unfinished drains mark the capture truncated and
bypass compaction; timed-out reader tasks are aborted and joined.
For literal git diff --stat commands (optionally --cached/--staged,
--no-color, --no-ext-diff and literal paths after --), Sui removes only
the +/- histogram suffixes of a complete validated stat. Displayed file
names, including Git's abbreviations/quoting, per-file total changes, binary
byte counts and the insertion/deletion footer stay exact. The removed graphs
can convey approximate per-file proportions; per_file_counts: total_changes_only makes that limitation explicit. Use raw output to inspect
those graphs; --numstat remains raw for exact per-file additions/deletions.
Patches, other formats/flags, uncertain rows or totals, and small captures
that would grow after metadata all retain the original envelope.
{"command":"cargo test","output":"auto"}Compacted results report output_compacted, collapsed line counts,
original_bytes, rendered_bytes and raw_output_id. These are captured
text measurements, not provider token savings, billing or prompt-cache hits.
Git results report stat_graphs_removed instead of Cargo line counts.
Use bash with output: "raw" to bypass compaction, or recover the existing
capture without rerunning a command:
{"id":"<raw_output_id>","offset":0,"max_bytes":12000}read_tool_output returns exact UTF-8 pages with byte offsets and more /
next_offset; the whole page envelope is bounded to max_bytes (1,024–24,000).
Original captures are held only in the owning agent's memory: at most eight
entries and 512 KiB of stored text, with a 128 KiB per-entry limit. Eviction
or a session restart expires handles and returns an explicit error. Existing
head/tail capture limits still apply; omitted process bytes cannot be recovered.
The initial Bash journal entry stores the compact view. Requested recovery
pages become ordinary tool history and journal entries.
The stable native prompt also asks for concise prose while retaining negation, conditions, identifiers, units, errors, evidence and uncertainty. Source code, public documentation and structured deliverable shapes stay exact. Tool arguments/defaults live in the frozen schemas; the prompt keeps workflow and evidence rules without repeating those definitions. Reading raw pages adds requests/history, so recovering an entire capture can cost more than using raw output initially. No universal savings percentage is claimed. This changes the native tool/system signature; start a new session after updating. History is never rewritten by output compaction.
Native agents can call code_intel for Rust definitions, references and
file diagnostics in Solo or Mission worktrees. Sui starts and owns a
language-server process on demand, over stdio. It works on headless servers
without an editor, display, separate server command or external agent harness.
The installed Rust toolchain must include the rust-analyzer and rust-src
components; Sui does not download or install them at runtime. No additional
Sui configuration is needed.
{"action":"definition","path":"src/lib.rs","line":12,"column":9}
{"action":"references","path":"src/lib.rs","line":12,"column":9,"limit":20}
{"action":"diagnostics","path":"src/lib.rs"}line and column are 1-based. Columns count Unicode scalar characters,
rather than bytes or LSP UTF-16 units; returned locations use the same
convention. Definition and reference queries require both coordinates.
Results stay within the agent's workspace, exclude unsafe paths and symlinks,
and report omitted locations. Read the relevant region before editing.
This tool uses the normal local execution approval, like bash;
session approval and Auto/YOLO apply. Build scripts, procedural macros and
check-on-save are disabled, and Cargo metadata runs with --offline and
--locked. rust-analyzer.toml in the inspected workspace tree, including
nested files, is unsupported because it can override server policy.
Before each call, a presence-only scan ignores Git ignore rules, examines
at most 10,000 entries and 128 directory levels, and uses a cooperative
three-second budget. It skips inventory's mandatory metadata, dependency
and credential exclusions plus root target, build, dist and coverage
directories. Visible symlinks, inaccessible paths or exhausted scan limits
make configuration coverage unknown and close the session. This check is
scoped to that tree and runs between calls; local Rust/Cargo tooling still
runs with user privileges, and these settings are not an OS sandbox.
Each agent's workspace owns its own lazy session. Sui invalidates it before
file edits, shell commands and terminal actions that may change files;
the next query starts a fresh session. Results report project_mode: cargo
when the workspace root contains a regular Cargo.toml. Otherwise,
project_mode: detached analyzes one standalone file at a time, and
switching files reinitializes the language server. Standalone results are
always partial because coverage across files is unknown. Nested Cargo
projects are not discovered from the repository root; start Sui in their
Cargo root, or include them in the root Cargo workspace.
Initialization/readiness has a 60-second deadline and each query a
30-second deadline. Transient ContentModified or retriggerable
ServerCancelled responses receive at most three additional attempts,
25 milliseconds apart, within that query deadline. These retries stay
inside the same tool call and add no model/provider request. Cancellation,
timeouts and protocol failures close the session, kill its process group
and attempt to reap it within three seconds. An unavailable server or
unsupported operation produces an explicit error; Sui does not substitute
syntax matches for semantic results. Stopping an agent also closes its idle
language backend; successful turns can reuse the workspace session.
Source files read for queries and returned positions are limited to 512 KiB each and 32 MiB total per call. Output defaults to 50 rows, with a maximum of 200 and a 24 KiB row budget; these limits do not cap the server's internal workspace indexing. Result processing examines at most 4,096 records under a cooperative three-second budget; remaining records count as omitted. Cancellation waits for the processing worker to stop and closes the backend. Filesystem calls must return before cooperative cleanup can finish. Invalid semantic responses produce an error and reset the backend.
Check file_in_project (true, false or unknown), analysis_health,
analysis_complete and results_omitted. Complete analysis requires a
healthy Cargo backend, confirmed membership of the queried file and no
omitted results. Unlinked files and unknown membership remain partial.
Loading or missing dependencies can also make observations partial.
Empty results do not prove absence.
Diagnostics are native analyzer observations, not cargo check or test
acceptance proof.
The schema is appended after inventory and remains frozen for each run. Adding code intelligence changes the tool/system signature: older sessions remain inspectable/exportable, but Resume rejects a mismatched signature. Start a new session to use the new tool.
Native agents carry a small always-on scan (outcome · correctness ·
interaction · failure/recovery · security · performance · compatibility ·
maintainability · verification — including concerns the user didn't
name) plus a compact index of engineering guides. At task start, Sui
selects up to three relevant lenses from task cues + project facts
(detected manifests/deps) and injects them into the run — labeled
runtime guidance, not user requirements. The skill tool loads any
other lens on demand. Guides inform judgment; they never add
requirements, permissions, or scope. Bundled lenses: product-exploration,
debugging (+ async/subprocess references), code-review (+ rust/python/
typescript references), tui-quality, first-run-experience,
release-verification.
sui --mission or sui-mission headless:
sui-mission --control-profile strong --worker-profile cheap \
--auditor-profile strong --task "..." The runtime — not the model — owns scheduling, worktrees, contract
validation, ownership checks, acceptance commands, integration, and
bounded repair/escalation. Your original checkout is never modified;
accepted work lands on a sui-mission-* branch.
Open Ctrl+P → Recent sessions / Resume, or type /resume, then choose a
recorded session for the current workspace. The searchable list shows up to 30
recent native sessions. Your draft stays in the composer. The conversation,
recorded tool results and Usage return without running any old tool calls.
Saved checks are historical evidence and need rechecking against current code.
Headless/SSH entry points use the same recovery path:
sui --resume latest "continue the task"
sui --resume <run-id> # opens the TUI on a terminalRecovery creates a fresh private run with a copy of the journal and verified opaque replay sidecars; the source journal stays unchanged. It retains the native session identity, request sequence and context epoch. Current permission settings apply; approvals recorded in the old journal never grant permission. Cache reuse still depends on the provider, its retention and routing.
The recorded profile/model, wire adapter, tool schemas, system contract and project guidance must still match. An active session, unfinished turn or tool call, damaged journal, missing/tampered sidecar, or memory-only image observation is refused explicitly by CLI/TUI recovery. Desktop may recover a complete journal ending in an interrupted turn, marking unresolved tool outcomes unknown in a new fork. It never reruns those commands. Desktop image attachments with verified private replay files can resume; older memory-only tool observations cannot. Recovery is bounded to 32 MiB of journal and 64 MiB of replay state. Missions use their own lifecycle and cannot be resumed this way. Sessions recorded before resume headers were introduced remain exportable; they cannot promise the same request header and are marked unavailable.
Every run journals to ~/.local/share/sui/runs/<run-id>/ — requests,
messages, tool calls with exit codes, mission gates, audit verdicts:
sui export --latest # newest run for the current workspace
sui export --run <run-id> # a specific run
sui export --run <id> --format json
sui export --run <id> --include-diff # bounded git diff of accepted workIn the TUI: Settings → export run report, or /export in the input —
works during a run (labeled partial). Reports land at
~/.local/share/sui/exports/<run-id>/report.md (mode 0600), built from
journals with credentials redacted best-effort; missing data shows
"Not recorded"/"Unknown", never invented. Review before sharing —
reports contain project code. No API calls needed.
Reports show request failures, automatic retries, and failed task outcomes even when a later turn succeeds. Status describes the latest recorded outcome; the declared completion state remains a claim. Missing usage is flagged and totals include only recorded buckets.
- Global
~/.config/sui/config.toml— providers, profiles, trusted agents, UI settings. The only place credentials live. - Project
sui.toml— workspace prefs only. API keys and[agents]here are ignored; a project file that redirectsbase_urlto an untrusted endpoint is gated interactively and hard-fails headless. - State
~/.local/share/sui/— journals, run reports, history.
See sui.example.toml for the full annotated schema.
If a provider rejects a model name containing picker details such as
ctx=272000, tools, or $2.00/$8.00per-M, check the profile's model
in the global config. Earlier builds could save the entire display label.
Replace it with the exact model ID from that provider's catalog, then
restart Sui. Context size, tool support, and pricing are display metadata;
they are never part of the selected model ID. A corrected ID still needs
to be available to your provider account.
Update: brew upgrade sui-ai or rerun the installer — config,
credentials, and journals are preserved; only ~/.sui/bin/* is replaced.
Uninstall: remove ~/.sui/bin. Delete ~/.config/sui and
~/.local/share/sui only if you want the state gone.
Prebuilt binaries: macOS (Apple Silicon, Intel), Linux x86-64 and ARM64 — GNU builds link against glibc 2.35 (Ubuntu 22.04 baseline); older distros and Alpine/musl are not covered. Native Windows is not packaged (WSL2 works).
Runtime: git and bash for workspace/mission operations; the
target project's own toolchain for its builds/tests. Headless Linux is
supported — without a desktop credential service, keys fall back to
session/env storage, and sui auth codex --manual handles login.
Profiles default to Chat Completions. Set kind = "openai-responses" in a
trusted global profile to use a compatible /v1/responses endpoint directly.
This keeps Responses usage fields (including reported zero cache reads and
writes) and encrypted reasoning for tool continuation. It also avoids token
count changes introduced by some gateways' Chat conversion paths. Sui never
subtracts a guessed gateway overhead. sui-certify reports a token-weighted
cache rate with measured-request coverage; missing fields remain unknown.
Pricing uses separate uncached, cache-read, and cache-write input buckets.
An incomplete count or required price makes the estimate unknown.
With [agent] context_compaction = true (default), the native loop requests a
summary near 80% of its context budget. The request appends a summary instruction
while preserving model, tool schemas, settings and the existing conversation.
A completed bounded summary becomes a journaled context checkpoint in a new
epoch, retaining the latest text task verbatim. Summary generation counts toward
request limits and usage. Tool calls from a summarization request are never
executed. Failed or insufficient summaries preserve the old history; input
already above the hard budget still stops. A summary provides context, not
runtime verification or permission. Set context_compaction = false to retain
the original stop-at-budget behavior.
Each checkpoint also carries a bounded runtime record of actual tool dispositions, exit codes, command observations, and provider failures. Generated summary claims cannot override that record. Omitted older records are counted; the original journal preserves them. Runtime observations are evidence, not mission gates, permission grants, or proof that current code still passes.
Transient provider failures (connection/timeouts, HTTP 408/429/5xx, retryable
stream errors, or a stream ending without its terminal event) automatically
retry the pending request. Backoff starts at 0.5 seconds and caps at 30 seconds;
retries continue until recovery, Stop/Ctrl-C, or a mission task deadline. They
do not consume max_turns, duplicate the user message, rerun earlier tool
results, or execute incomplete tool calls. Each attempt has its own request ID
and usage coverage; unreported usage stays unknown. The UI shows retry progress.
Authentication, permission, invalid-request, quota and output-limit failures need attention rather than repeated identical requests. Their safe diagnostic is recorded for the next turn. HTTP status and recognized provider error codes are retained; arbitrary provider error payloads are excluded because they may echo credentials. Context/iteration exhaustion reports unfinished work rather than a successful task. Tool failures remain visible to the agent so it can diagnose, repair, and verify within the current permissions and limits.
Opaque reasoning for journal replay lives in bounded, owner-only, hash-verified
replay-*.json sidecars next to the journal. Sidecar contents are excluded from
exports. Keep them with the journal for exact Responses replay; a missing or
modified sidecar fails replay explicitly. Image-bearing history still cannot
claim exact replay from text-only journals. Gateway/backend caching controls
require separate capability verification; an API-compatible endpoint need not
support explicit breakpoints or public API diagnostics.
- Changes tab shows status +
diff --stat, not full diffs. - Per-worker transcript panes are not implemented; journals under
~/.local/share/sui/runshold the full record. - Provider/model behavior is
UNVERIFIEDuntilsui-certifyruns against real credentials — installation proves nothing about a provider's tool-calling or cache behavior. - Comparison clones isolate repositories, not the filesystem — a misbehaving agent could inspect siblings.
- codex-oauth rides your ChatGPT subscription — requests count against
your Codex rate windows, and reuse of
~/.codex/auth.jsonassumes the file-based store (keyring-stored credentials aren't readable).
Sui is licensed under the MIT License.

