Rysh Documentation
Rysh is an agentic terminal multiplexer designed for AI-driven software development. It combines the workspace management of tools like tmux and Zellij with autonomous AI agent capabilities in every pane. Each pane is both a real terminal (backed by a PTY) and an AI agent workspace, letting you seamlessly switch between shell commands and LLM-powered development.
Key Highlights
- Tabs & stacked panes — Organize your workspace with tabs, columns, and card-deck pane stacks.
- AI agent per pane — Toggle between shell and AI prompt mode with Double-Escape.
- 40+ built-in tools — File ops, git, bash, code search, web search, background execution, durable project memory, and more.
- Extensible toolbox — Add external MCP servers as tools, or turn any API spec into governed agent tools with Rysh Forge.
- Cross-pane coordination — Agents discover each other, share context, send commands, and spawn real sub-agents.
- Session persistence — Detach and reattach sessions with full state restoration.
- Remote collaboration — Share panes with collaborators via the upstream server in view or control mode.
- Interactive terminal — Full support for vim, htop, less, nano, and other curses programs, with predictive local echo.
- Mobile app — View and control shared panes, tab layouts, and a remote file browser from iOS.
- Secret redaction — Credentials are automatically redacted from shared output.
Installation
Rysh ships as a single self-contained binary with no runtime dependencies. Choose the method that matches your platform.
ry. The installed binary is named ry, with
rysh available as an alternate name. Both invoke the same client/daemon application —
the examples below use ry.
One-line Installer (all platforms)
The fastest way to install on any Unix-like system:
curl -fsSL https://packages.rysh.ai/install.sh | sh
/usr/local/bin. No sudo required if that path is writable.
macOS — Homebrew
The recommended method on macOS. Works on both Intel and Apple Silicon.
# Add the Rysh tap and install
brew tap rysh-ai/rysh
brew install rysh
Or in one line:
brew tap rysh-ai/rysh && brew install rysh
Upgrade to a new version:
brew upgrade rysh
Linux — Debian / Ubuntu (APT)
# Add the Rysh APT repository
curl -fsSL https://packages.rysh.ai/apt/rysh-gpg.asc | sudo tee /usr/share/keyrings/rysh.asc > /dev/null
echo "deb [signed-by=/usr/share/keyrings/rysh.asc] https://packages.rysh.ai/apt stable main" \
| sudo tee /etc/apt/sources.list.d/rysh.list
# Install
sudo apt-get update
sudo apt-get install -y rysh
Linux — Red Hat / Fedora / CentOS (RPM)
# Add the Rysh RPM repository
sudo curl -fsSL https://packages.rysh.ai/rpm/rysh.repo \
-o /etc/yum.repos.d/rysh.repo
# Install
sudo dnf install rysh # Fedora / RHEL 8+
# or
sudo yum install rysh # CentOS 7 / older RHEL
Windows — Chocolatey
choco install rysh
Windows — WinGet
winget install RyshAI.Rysh
Build from Source
Requires Go 1.21+.
# Clone the repository
git clone https://github.com/rysh-ai/rysh-cli.git
cd rysh-cli
# Build the binary
go build -o rysh .
# Move to your PATH
sudo mv rysh /usr/local/bin/
Verify Installation
ry --version
# ry 0.1.0 (commit: ..., built: ...)
Requirements
- A terminal emulator — any modern terminal (iTerm2, Alacritty, kitty, GNOME Terminal, Windows Terminal).
- Go 1.21+ — only required when building from source.
- Anthropic API key (optional) — for direct Claude API integration via the Messages API. Without it, Rysh falls back to the
claudeCLI adapter.
Quick Start
Get up and running in under a minute:
# Start Rysh with the default session
ry
# Or start with a named session
ry my-project
# Create a new pane
# Press Ctrl+N in normal mode
# Switch to AI prompt mode
# Press Escape twice (Double-Escape)
# Type a prompt and press Enter
> refactor the auth middleware and write tests
# Switch back to shell mode
# Press Escape twice again
Configuration
Rysh loads configuration from rysh.config in the current working directory or
~/.config/rysh/rysh.config, using TOML format. Environment variables override
file settings.
Configuration File Example
# ~/.config/rysh/rysh.config
[provider]
name = "claude" # LLM provider name
api_key = "sk-ant-..." # Anthropic API key
api_url = "" # Custom API endpoint (optional)
model = "claude-opus-4-5" # Model (defaults: claude-opus-4-5 / claude-sonnet-4-*)
max_tokens = 8192 # Max response tokens
system_prompt = "" # Custom system prompt file path
[ui]
shell = "/bin/zsh" # Shell binary (defaults to $SHELL)
initial_tabs = 1 # Number of tabs on startup
initial_panes = 1 # Panes per tab on startup
[session]
dir = "~/.local/state/rysh/sessions"
[upstream]
enabled = false # Enable remote collaboration
url = "wss://rysh.ai" # Upstream server URL
api_key = "" # Upstream API key
auto_share = false
default_share_mode = "view" # "view" or "control"
reconnect_interval = "5s"
max_reconnect_attempts = 10
Environment Variables
| Variable | Description | Default |
|---|---|---|
RYSH_PROVIDER | LLM provider name | claude |
RYSH_API_KEY | Anthropic API key | — |
RYSH_API_URL | Custom API endpoint URL | — |
RYSH_MODEL | Model name | — |
RYSH_MAX_TOKENS | Max response tokens | 8192 |
RYSH_SYSTEM_PROMPT | System prompt file path | — |
RYSH_CLAUDE_CMD | Claude CLI binary path | claude |
RYSH_BRAVE_API_KEY | Brave Search API key (for web_search tool) | — |
RYSH_SESSION | Default session name | — |
RYSH_SESSION_DIR | Session registry directory | ~/.local/state/rysh/sessions |
RYSH_INITIAL_TABS | Number of initial tabs | 1 |
RYSH_INITIAL_PANES | Panes per tab on startup | 1 |
RYSH_UPSTREAM_ENABLED | Enable upstream collaboration | false |
RYSH_UPSTREAM_URL | Upstream server URL | — |
RYSH_UPSTREAM_API_KEY | Upstream API key | — |
RYSH_UPSTREAM_SHARE_MODE | Default share mode: view or control | view |
Tabs & Panes
Rysh organizes everything into a clear hierarchy. A workspace holds tabs; each tab is a screen of lanes (vertical columns); each lane holds one or more pane groups (row slots); and each pane group holds a rotating stack of panes. This is conceptually similar to Zellij but specialized for agentic software development. There is no separate “window” concept.
| Level | Role |
|---|---|
| Workspace | A configured set of tabs with its own upstream/API key. The cloud tenancy boundary (identified by UUID). |
| Tab | A screen of lanes (one tab visible at a time). Owns pipeline state. |
| Lane | A vertical column with a horizontal width weight (flex). |
| Pane group | A row slot within a lane with a vertical height weight (rowFlex); holds a stack of panes. |
| Pane | One conversation surface: a PTY shell and/or an LLM agent. |
Tab Basics
- Tabs are the top-level organizational unit.
- Switch between tabs with [ and ], or Alt+Left/Right.
- Create new tabs with Ctrl+T then n.
- Jump to a specific tab by index with Ctrl+T then 1–9.
Pane Basics
- Each pane is a real terminal session backed by a PTY-attached shell process.
- Each pane is also an autonomous AI agent workspace.
- Create new panes with Ctrl+N (split right) or Ctrl+P then n.
- Cycle between panes with Tab or Alt+Up/Down.
- Close a pane with Ctrl+P then x.
- Click a pane with the mouse to focus it.
Lanes, Pane Groups & Stacks
Within a tab, lanes are the columns and pane groups are the row slots inside a lane. Each pane group holds one or more stacked panes.
Column Layout (Lanes)
Lanes are arranged horizontally as columns, each with a flex weight that determines its share of horizontal space. Creating a new pane (Ctrl+N or Ctrl+P then n) adds a new column to the right. A grid seeds an R×C arrangement of lanes and groups in one shot.
Vertical Splits (Split Down)
Groups can be split vertically within the same column using Ctrl+P then v. This creates a new pane group stacked below the current one in the same column, with vertical space distributed proportionally.
Stacked Panes (Card Deck)
Each pane group can hold multiple panes stacked like a deck of cards. Only the top pane (index 0) is visible and accepts input. Background panes are shown as title bars at the bottom of the active pane's content area.
- Add a stacked pane: Ctrl+P then s.
- Enter stack mode: Ctrl+S.
- Rotate next (front to back): j, Down, Right, or l.
- Rotate prev (back to front): k, Up, Left, or h.
- Exit stack mode: Esc, ., or Ctrl+S.
Input Modes
Each pane has an independent input mode that determines how your input is processed. Toggle between modes with Double-Escape (press Escape twice).
| Mode | Behavior | Toggle |
|---|---|---|
| Shell | Input is executed as a shell command in the pane's PTY. | Esc Esc |
| Prompt | Input is sent to the configured LLM provider as an AI prompt. |
## are always treated as Rysh
system commands, regardless of the current input mode. The exception is lines starting
with ##>, which are pipeline events.
Interactive Terminal Support
Rysh fully supports interactive terminal programs like vim, htop,
less, nano, and top. This is powered by a built-in
virtual terminal emulator that provides a full 2D screen buffer.
How It Works
- Auto-detection: When the terminal emulator detects alternate screen buffer activation (e.g., when you launch vim), the pane automatically enters raw mode.
- Keystroke forwarding: In raw mode, all keystrokes (except Ctrl+O) are forwarded as raw bytes to the PTY for minimal latency.
- VT rendering: The TUI renders the terminal emulator's screen buffer directly instead of the plain text output buffer.
- Exit: When the program exits (alternate screen deactivated), raw mode ends automatically.
Predictive Local Echo
To keep typing responsive over the network, the interactive (xterm) terminal applies predictive local echo: typed characters are echoed immediately on the client and then reconciled against the authoritative PTY output as it streams back. This hides round-trip latency for shells and editors without desynchronizing the screen.
Scrollback (Copy Mode)
Interactive (raw) panes keep a scrollback buffer you can page through via copy mode — so you can scroll back over a full-screen program's history even while it's running. On the mobile app the same scrollback is available with touch scrolling, and subscribers of a shared pane get their own scrollback too.
Shared Interactive Terminals
Interactive, full-screen programs (vim, htop, Claude Code) also render correctly
inside shared panes — the remote viewer reconstructs the live terminal
screen, including a CSS scale-to-fit layout and replay on reconnect. This is what powers the
interactive terminal in the Rysh mobile app.
Escape Hatch
Ctrl+O is the escape hatch from raw mode. It enters prefix mode, from which you can switch panes, switch tabs, or detach the session. After the prefix action completes, you return to raw mode.
Manual Toggle
Use the ##raw system command to manually toggle raw mode when auto-detection
is not desired.
TERM=xterm-256color for full
terminal capability reporting. Initial PTY size is 80×24, then updated on first render.
Global Keybindings
These keybindings work in normal mode (when no special mode is active):
| Keybinding | Action |
|---|---|
| Ctrl+N | Create a new pane (split right) in the active tab |
| Tab | Cycle to the next pane in the active tab |
| [ | Switch to the previous tab |
| ] | Switch to the next tab |
| Alt+Left | Switch to the previous tab |
| Alt+Right | Switch to the next tab |
| Alt+Up | Switch to the previous pane |
| Alt+Down | Switch to the next pane |
| Alt+B | Previous tab (macOS Meta fallback) |
| Alt+F | Next tab (macOS Meta fallback) |
| Esc Esc | Toggle input mode (shell / prompt) |
| Ctrl+P | Enter pane mode |
| Ctrl+T | Enter tab mode |
| Ctrl+S | Enter stack mode |
| Ctrl+O | Enter prefix mode (tmux-style) |
| Alt+P | Enter Alt-P prefix mode |
| Ctrl+Space | Enter navigate mode |
| Ctrl+L | Enter layout mode |
Mouse Support
- Click a pane to focus it.
- Drag to select text within a pane.
- Release to copy the selection to the clipboard.
Pane Mode Ctrl+P
Pane mode provides Zellij-style pane management:
| Key | Action |
|---|---|
| n | Create a new pane (split right) |
| v | Create a split-down pane group (vertical split in same column) |
| s | Create a stacked pane (on top of the active group's stack) |
| x | Close the active pane (when more than one exists) |
| r | Enter resize mode |
| d | Detach the session |
| Alt+Up | Move to the previous pane |
| Alt+Down | Move to the next pane |
| Esc / . / Ctrl+P | Exit pane mode |
Tab Mode Ctrl+T
Tab mode follows Zellij-style tab navigation:
| Key | Action |
|---|---|
| n | Create a new tab |
| 1–9 | Jump directly to tab by index |
| Alt+Left | Move to the previous tab |
| Alt+Right | Move to the next tab |
| Esc / . / Ctrl+T | Exit tab mode |
Stack Mode Ctrl+S
Stack mode navigates stacked panes within the active pane group:
| Key | Action |
|---|---|
| j / Down / Right / l | Rotate to the next stacked pane (front moves to back) |
| k / Up / Left / h | Rotate to the previous stacked pane (back moves to front) |
| Esc / . / Ctrl+S | Exit stack mode |
Resize Mode
Enter resize mode from pane mode with r:
| Key | Action |
|---|---|
| h / Left / k / Up | Shrink the active pane |
| l / Right / j / Down | Grow the active pane |
| Esc / . | Return to pane mode |
| Ctrl+P | Return to normal mode |
Raw Mode (Interactive Programs)
Raw mode is automatically activated when a pane detects alternate screen buffer usage (e.g., vim, htop, less, nano). In raw mode:
- All keystrokes are forwarded as raw bytes to the PTY.
- The TUI renders the terminal emulator screen buffer directly.
- Ctrl+O is the escape hatch — enters prefix mode.
- From prefix mode: d detaches, any other key cancels and returns to raw mode.
- Use
##rawto manually toggle raw mode.
AI Agent per Pane
Every pane in Rysh is an autonomous AI agent workspace. When you switch to prompt mode (Double-Escape), your input is sent to the configured LLM provider. The AI agent can then use built-in tools to read files, edit code, run commands, search the web, and coordinate with other agents.
How It Works
- Each pane manages its own PTY, output buffers, and state independently.
- Every pane has a dedicated AI agent that handles prompt execution with tool use.
- The agent orchestrates tool calls with approval flows and cancellation semantics.
- A new prompt cancels any in-flight completion (“last-prompt-wins” semantics).
Provider
Agents talk to the model through a single AgenticProvider abstraction backed by the
Anthropic Claude Messages API. The orchestrator prefers streaming
when available and falls back to non-streaming. Key behaviors:
- Prompt caching is on by default to reduce token cost on long conversations.
- Extended thinking is supported for harder reasoning steps.
- Resilience — transient errors are retried inside the provider (exponential backoff) with optional model fallback.
- Reported token usage feeds context compaction so long sessions stay within the model's context window.
AI responses are rendered as markdown before being appended to the pane output buffer.
Agent Capabilities
- Real sub-agents — the
sub_agenttool spawns a genuine child agent with its own context window and a focused toolset (depth-limited); only its summary returns to the parent. - Multimodal input — attach an image to a prompt with
##image <path>. - Durable project memory — agents read and write
RYSH.md, auto-loaded into the system prompt each session (see Project Memory). - Live observability —
##agent metricsexposes per-tool / LLM metrics (Prometheus), and##agent reload-promptshot-reloads prompt overrides without a restart. - Headless agents & humanoids — run autonomous agents with no PTY, or “humanoids” that answer Slack and email; both can be defined declaratively in
SKILL.mdfiles and spawned with##agent/##humanoid.
Built-in & Dynamic Tools
Every AI agent has access to a comprehensive toolkit for reading, writing, searching, building, and coordinating across your workspace. Beyond the 40+ built-in tools below, the registry is extensible at runtime — MCP servers and Rysh Forge integrations register additional tools that flow through the same approval and redaction path.
Core Tools
| Tool | Description |
|---|---|
bash | Execute shell commands in the pane's PTY |
ls | Lightweight directory listing |
file_read | Read file contents |
file_edit | Edit a file with diff preview and approval |
multi_edit | Atomic multi-hunk file replacement |
file_write | Write a new file with approval |
apply_patch | Apply unified diff patches |
glob | File pattern matching |
grep | Content search with regex support |
web_search | Search the web via Brave Search API |
web_fetch | Fetch and parse web page content |
Git Tools
| Tool | Description |
|---|---|
git_status | Show working tree status |
git_diff | Show file diffs |
git_log | View commit history |
git_commit | Create a commit (requires approval) |
Code Intelligence
| Tool | Description |
|---|---|
tree | Directory tree visualization |
symbol_search | Find declarations and symbols in code |
Process & Environment
| Tool | Description |
|---|---|
process_list | List running processes |
port_check | Check if a port is in use |
env_read | Read environment variables (with secret redaction) |
Testing & Build
| Tool | Description |
|---|---|
test_run | Run tests with structured results |
lint | Run vet, staticcheck, or golangci-lint |
build | Build the project |
Background Execution
| Tool | Description |
|---|---|
bash_background | Start a background session (returns session ID) |
bash_output | Read output from a background session, or list all sessions |
kill_shell | Terminate a background session (requires approval) |
monitor | Watch a long-running command and stream its output (requires approval) |
Workspace Awareness
| Tool | Description |
|---|---|
ask_user | Ask the user a question mid-task and block on the answer |
pane_inspect | Inspect another pane's state and output |
pane_send | Send commands to another pane |
agents_list | List all panes and agents in the workspace |
session_history | Retrieve conversation history from any pane |
sub_agent | Spawn a real child agent with its own context window and toolset |
todo | Per-pane task list (persisted across sessions) |
memory_edit | Read/append/write durable project memory (RYSH.md) |
clipboard | Read/write system clipboard |
context_store | Store key-value context shared across agents |
context_recall | Recall stored context from the shared store |
project_notes | Shared project notes (.rysh-notes.md) |
list_tools | List all available tools |
Tool Approval Flow
Tools that modify files or execute commands require explicit approval before execution. Rysh uses two approval strategies:
Preview-First Approval
Used by: file_edit, multi_edit, file_write, apply_patch.
- The tool executes and generates a diff preview.
- The diff is shown to you for review.
- You approve or reject the change.
- On approval, the change is applied. On rejection, it is discarded.
Pre-Approval
Used by: bash, bash_background, kill_shell, git_commit.
- The tool description and parameters are shown to you.
- You approve or reject the execution.
- On approval, the command is executed. On rejection, it is skipped.
Loop Detection
Rysh tracks a sliding window of recent tool calls. After 3 identical calls with the same parameters, execution is blocked to prevent infinite tool-use loops.
Multi-Agent Coordination
One of Rysh's most powerful features is the ability for AI agents across different panes to discover and coordinate with each other.
Agent Discovery
The agents_list tool lets any agent enumerate all panes in the workspace, including
their current status, mode, and last command. This enables agents to understand the broader
workspace context.
Cross-Pane Communication
pane_inspect— Read another pane's output, status, and configuration.pane_send— Send a shell command or AI prompt to another pane.session_history— Retrieve the full conversation history from any pane.
Shared Context
context_store/context_recall— Store and retrieve key-value context accessible by all agents in the workspace.project_notes— Shared.rysh-notes.mdfile accessible by all agents.
##pane listen with pipeline events to build
automated multi-phase workflows where one agent's output triggers another agent's actions.
Project Memory
Rysh gives agents durable, per-project memory in a plain Markdown file named
RYSH.md at the project root. It persists facts, conventions, and decisions across
sessions so an agent doesn't relearn your project every time.
- Auto-loaded — the contents of
RYSH.mdare injected into the agent's system prompt at the start of every session. - Agent-editable — the
memory_edittool canread,append, orwritethe file (writes require approval); it is capped at 64 KB. - Human-editable — it's just a Markdown file, so you can curate it by hand and commit it to your repo.
context_store — RYSH.md is the
long-lived knowledge base for the project itself.
LLM Provider
Rysh routes every agent through a single AgenticProvider interface. The shipped
implementation targets the Anthropic Claude Messages API; the same engine
powers local CLI agents and server-side panes — only the tool registry differs.
| Aspect | Details |
|---|---|
| Default models | claude-opus-4-5 and claude-sonnet-4-* (configurable via model / RYSH_MODEL) |
| Transport | Streaming preferred, non-streaming fallback |
| Optimizations | Prompt caching on by default, extended thinking supported |
| Resilience | In-provider retry with exponential backoff and optional model fallback |
| Requirement | Anthropic API key (RYSH_API_KEY or [provider] api_key) |
Rysh Forge — API Specs to Agent Tools
Rysh Forge turns a machine-readable API specification into governed, agent-callable tools — and, as side artifacts, SDKs, Markdown docs, and a standalone MCP server. Point Forge at a spec and every operation becomes a tool your agents can call, with auth, retries, and response trimming handled for you.
Inputs & Outputs
- Ingest — OpenAPI 3.x, GraphQL, and gRPC specifications normalize into one intermediate representation.
- Generate — targets include
rysh-toolpack(live agent tools),docs,mcp-server, andgo-sdk/ts-sdk/py-sdk/java-sdk.
Governance (avoiding tool explosion)
- Exposure mode — small APIs expose one tool per operation; large APIs (above ~50 operations) automatically collapse to just three meta-tools (
list_endpoints,get_endpoint_schema,invoke_endpoint) for a constant context footprint. - Approval — mutating endpoints can require approval before they run.
- Response trimming — an injected
jq_filterargument keeps only the fields the agent needs, so large responses don't flood the context window. - Secret hygiene — only environment-variable names are stored; credential values are never persisted.
Using It
- CLI:
ry forge add,ry forge generate,ry forge list,ry forge targets. - In-session:
##integration(alias##int) —list,enable <name>,disable <name>,tools <name>,remove <name>. Integrations live under.rysh/forge/and re-register at startup.
MCP Client — Consume External MCP Servers
Rysh is a Model Context Protocol client: it connects to external MCP servers, discovers their tools, and registers each as a first-class agent tool. MCP tools enter the same shared registry every pane uses, so they flow through the normal tool-use, approval, and audit path — indistinguishable from built-in tools.
- Transports —
stdio(spawn a child process speaking JSON-RPC) orhttp(Streamable HTTP). - Commands —
##mcp add <name> {http <url> | stdio <cmd> [args]}, pluslist,tools <name>,reconnect <name>,remove <name>. - Config — servers are persisted per-project in
.rysh/mcp.json(git-checkable) and reconnected at startup. - Flags —
--approvegates every call from a server,--prefixnamespaces tool names,--header/--envpass credentials.
Scoped & Shared Tools
Dynamic tools (from Forge or MCP) can be scoped so they are only visible where you want them, and shared so collaborators can use a forged API live across sessions.
Scopes
- Enable an integration or MCP server at a specific scope — workspace, tab, lane, pane group, or pane — with
--scope(e.g.##integration enable <name> --scope tab,##mcp add … --scope pane). - Tool visibility updates live per pane; spawned agents and humanoids inherit the invoking pane's scope.
- Scopes are persisted, so a pane keeps its scoped tools across daemon restarts.
Forged-API Sharing
- Share a forged API with other sessions using
##forge share api <name>and subscribe from another machine with##forge subscribe. ##forge sharesintrospects active shares and subscriptions, including the per-workspace allow/block policy.- The owner executes the underlying operations; subscribers invoke them through the share, with server-side quota and rate limiting.
Declarative Startup Configuration
Instead of running ##forge commands by hand, you can declare integrations and
subscriptions per workspace in your config file. On startup Rysh applies them
automatically — add → enable (at a scope) → optionally share for
sources, and subscribe for consumers:
[[workspace]]
name = "backend"
[workspace.forge]
# Source side: make these APIs live on startup
[[workspace.forge.integrations]]
name = "weather" # integration name (tool prefix)
spec = "~/specs/weather.json" # OpenAPI/GraphQL spec
base_url = "https://api.example.com" # required if the spec server is relative
source = "openapi" # openapi | graphql (inferred when empty)
credential_env = "WEATHER_API_KEY" # env var holding the key (optional)
enable_scope = "tab" # pane | panegroup | lane | tab (empty ⇒ added, not enabled)
share = true # auto-share via the upstream
# Subscriber side: mount remote shared APIs on startup
[[workspace.forge.subscribe]]
api = "weather"
scope = "tab" # pane | panegroup | lane | tab (default tab)
System Commands Reference
Lines starting with ## are Rysh system commands. They are processed regardless
of the current input mode (shell or prompt).
| Command | Description |
|---|---|
##help | Show available system commands |
##workspace / ##ws | Workspace management (list, create) and delete entities by id |
##tab | Tab management (create, rename by id, list, list-panes) |
##pane | Pane management (create, rename by id, list --tab, listen, unlisten) |
##panegroup / ##pg | Pane group management |
##lane | Lane (column) management |
##new | Create layout entities (e.g. ##new grid 2x2, ##new stack) |
##cmd | Run a command targeting the originating pane's tab/lane/group |
##hop | Jump focus between panes/tabs |
##history / ##h | Show conversation/command history |
##public | Mark pane output as public (visible in shared context) |
##private | Mark pane output as private |
##snap | Take a snapshot of the workspace state |
##share pane [view|control] | Share the active pane with remote collaborators |
##share panegroup [view|control] | Share the active pane group |
##share tab [view|control] | Share the active tab |
##share list | List all active shares |
##share status | Show upstream connection status |
##unshare pane | Stop sharing the active pane |
##unshare panegroup | Stop sharing the active pane group |
##unshare tab | Stop sharing the active tab |
##upstream shares | List available shares on the upstream server |
##upstream subscribe <shareID> | Subscribe to a remote share |
##upstream unsubscribe | Stop subscribing to a remote share |
##upstream send <text> | Send a command to a remote pane (control mode) |
##raw | Manually toggle raw mode for interactive programs |
##agent | Manage headless agents (spawn, metrics, reload-prompts) |
##humanoid | Manage humanoids (spawn agents with Slack/email channels) |
##integration / ##int | Rysh Forge integrations (list, enable, disable, tools, remove) |
##mcp | External MCP servers (add, list, tools, reconnect, remove) |
##forge share / ##forge subscribe | Share / subscribe to a forged API across sessions |
##image <path> | Attach an image to the next AI prompt (multimodal input) |
Pipeline Events
Lines starting with ##> are pipeline events that bypass the PTY entirely.
They are published directly to the pane's output stream as clean event lines, enabling
powerful automation workflows between panes.
Event Processing
- When a pane receives
##>input, it publishes the event directly to the output stream without shell echo or prompt prefix. - The event flows through the shared output pipeline (with secret redaction applied).
- Any pane listening to this pane's output receives and processes the event.
Event Types
| Event Pattern | Behavior |
|---|---|
##>event:print:<payload> |
Forwards <payload> to the listening pane without alias prefix. |
##>event:ai:softdev:<lang>:<phase> |
Triggers the AI agent on the listening pane with a contextual prompt including accumulated context from the source pane. |
##>event:sh:softdev:<lang>:<phase> |
Runs a shell command on the listening pane (e.g., go test -v ./... for unit_testing). |
Softdev Phases (Go)
Supported phases for the golang language key:
planning— Architecture and implementation planningdevelopment— Code writing and implementationlinting— Static analysis and code qualityunit_testing— Unit test executionintegration_testing— Integration test executiondeployment— Build and deploymonitoring— Health checks and monitoring
Pane Listening
Panes can subscribe to each other's shared output, enabling real-time context sharing between agents.
Usage
# Subscribe to another pane's shared output
##pane listen <pane-id-or-alias>
# Stop listening
##pane unlisten
How It Works
- When you run
##pane listen, the pane starts subscribing to the target pane's shared output stream. - Text output is forwarded to the listening pane with an alias prefix (e.g.,
[pane-2]). - Pipeline events (
##>event:...) are intercepted and dispatched to trigger AI prompts or shell commands on the listening pane. - This enables powerful multi-agent workflows where one pane's output drives another pane's actions.
Session Management
Rysh maintains a local session registry on disk, enabling you to detach, reattach, and manage multiple sessions — similar to tmux or screen.
Session States
| State | Description |
|---|---|
running | Session is actively running with a TUI attached. |
detached | Session is running in the background without a TUI. |
stopped | Session has been cleanly exited. |
Session Registry
Session records are stored at ~/.local/state/rysh/sessions/.
Each record includes the session name, working directory path, state, PID, and update time.
Detaching & Reattaching
- Detach with Ctrl+O then d, or Ctrl+P then d.
- Reattach with
ry attach <session-name>. - Detach remotely with
ry detach <session-name>(sends SIGUSR1).
CLI Commands
The ry binary (alias rysh) supports the following CLI subcommands:
##-equivalents. Beyond session lifecycle,
ry exposes entity subcommands — ry tab, ry lane,
ry pane, ry pane-group, ry stacked-pane,
ry pipeline (each with list/create/delete
verbs) — plus flag forms (--pane, --cmd, --share)
that mirror the in-TUI ## system commands, so you can script Rysh without attaching a TUI.
| Command | Description |
|---|---|
ry | Start the UI with the default session name. |
ry <session-name> | Start the UI using the specified session name. |
ry attach <session-name> | Reattach to a stopped or detached session. |
ry detach <session-name> | Gracefully detach a running session (sends SIGUSR1). |
ry list-sessions | List all known sessions with their states. |
ry delete-session <name> | Delete a session (removes record, kills process, deletes session data). |
ry send <session> <input> |
Send input to a pane without attaching a TUI. Options: --pane <id>, --mode shell|prompt. |
# Start a new session
ry my-project
# Detach the session (from keyboard)
# Press Ctrl+O then d
# List sessions
ry list-sessions
# Reattach
ry attach my-project
# Send a command to a running session
ry send my-project "go test ./..." --mode shell
# Delete a session
ry delete-session my-project
Persistence
Rysh automatically persists your workspace state so that sessions survive restarts. All tab structure, pane output, history, mode, and status are saved and restored seamlessly.
What Gets Persisted
| Scope | Contents |
|---|---|
| Workspace | Tab structure, pane references, active indices |
| Per Pane | Output buffers (shell, AI, chat, system), command history, status, mode, last command |
Persistence Behavior
- Startup: Rysh attempts to restore from the saved state. If restoration fails, it bootstraps fresh tabs and panes.
- Shutdown: All state is flushed to disk.
- Runtime: Workspace state persists on every change. Per-pane writes are throttled (at most once per 2 seconds) to avoid write storms.
Session Data
Session data is stored per session at ~/.local/state/rysh/.
Deleting a session also removes its data directory.
Sharing Panes
Rysh supports sharing panes, pane groups, and entire tabs with remote collaborators via the upstream server. Two sharing modes are available:
| Mode | Capabilities |
|---|---|
| View | Remote collaborators can see the pane's output in real-time. Read-only. |
| Control | Remote collaborators can see output and send commands to the pane. Includes a configurable command blocklist for safety. |
Sharing Commands
# Share the active pane in view mode
##share pane view
# Share in control mode
##share pane control
# Share a pane group or tab
##share panegroup view
##share tab control
# List active shares
##share list
# Check upstream status
##share status
# Stop sharing
##unshare pane
##unshare panegroup
##unshare tab
How Sharing Works
- When you share a pane, its output is forwarded to the upstream server in real time.
- In control mode, the upstream server can also relay inbound commands from remote users.
- Secrets are automatically redacted before any output leaves your local session.
- Remote collaborators subscribe to your share and see the output in their own Rysh instance.
Upstream Server
The Rysh upstream server (rysh-server) acts as a collaboration hub for sharing
panes across sessions and users. It is an optional component for teams that need remote
collaboration.
Server Stack
- Go + Gin HTTP/WebSocket API.
- Embedded NATS server (with JetStream) — the cross-machine messaging backbone.
- PostgreSQL via GORM for data persistence.
- Firebase social auth plus email/password (HS256 JWT + rotating refresh tokens).
- Stripe integration for subscription billing.
- Server-side agentic panes — powering the Chrome extension and the embeddable chatbot widget.
- React + Vite frontend dashboard.
Multi-Tenant Isolation
The embedded NATS server is flat, so isolation is enforced at the WebSocket proxy by a
streaming subject-ACL that confines every client to its own workspace subtree
(ws.{workspaceID}.> and _INBOX.). A client can never publish to or
subscribe to another workspace's subjects.
Upstream Commands
# List available remote shares
##upstream shares
# Subscribe to a remote share
##upstream subscribe <shareID>
# Unsubscribe
##upstream unsubscribe
# Send a command to a remote pane (control mode)
##upstream send <text>
Remote Share Listening
When you subscribe to a remote share, Rysh connects to the upstream server and forwards
the remote pane's output to your local pane, prefixed with [remote:alias].
In control mode, you can also send commands back to the remote pane.
Secret Redaction
Security is built into Rysh's sharing architecture. Automatic secret redaction is applied before any output leaves your local session.
- All pane output passes through a redaction layer before being shared.
- Common secret patterns (API keys, tokens, passwords, etc.) are automatically detected and masked.
- Only redacted output is forwarded to remote collaborators or the upstream server.
- Your raw credentials never leave your local session.
##private for sensitive panes to
ensure complete protection.
Remote File Browser
Shared panes expose a read-only file browser so collaborators (and the mobile app) can navigate and view files from the machine that owns the share — without opening a shell.
How It Works
- The upstream server exposes
fs.list,fs.read, andfs.statoperations scoped to a share. - The server holds no local filesystem access — it only authorizes the request and relays it over NATS to the share source, which performs the read and answers.
- Directory listings, text files (chunked for large files), and images are returned; a payload cap guards oversized reads.
- Access is available to authenticated subscribers and via public token links for view shares.
Rysh Mobile App
Rysh Mobile is a native iOS app (React Native) for viewing and controlling your Rysh workspaces on the go. Sign in with email/password or Google, then connect to your upstream workspaces.
Features
- Shared panes — view live pane output in real time; in control mode, send commands back to the pane.
- Multi-pane tab layouts — view shared tabs with their full lane / pane-group / stacked-pane layout.
- Interactive terminal — an embedded xterm.js terminal renders full-screen TUI programs (vim, Claude Code) with scale-to-fit, device-rotation handling, and replay on reconnect.
- Per-pane scrollback with touch scrolling, terminal focus control, and an overflow menu.
- File browser & viewer — browse a shared pane's filesystem and open text files and images, backed by the remote file browser.
- Workspaces & billing — manage workspaces (addressed by ID), members, connections, chatbots, and subscription/billing.
- Resilient auth — access tokens refresh automatically across REST and WebSocket, prompting re-login only on failure.
##share from your terminal — a single pane or a whole
tab — becomes viewable (and controllable) from your phone.
Actor & Message-Bus Architecture
Rysh is built on a fully message-driven architecture with two foundations:
a supervised actor model (protoactor-go) for concurrency, and
NATS as the universal message bus. Every component — workspaces, tabs,
lanes, pane groups, panes, and AI agents — is an independent actor that communicates by
passing messages, never by sharing memory.
Everything is an Actor
The daemon hosts a supervised actor tree
(workspace → tab → lane → pane group → pane). Each actor
processes one message at a time, so its state needs no locks:
- Tabs manage their lane layout and respond to navigation, creation, and deletion messages.
- Lanes & pane groups handle column/row layout and stack rotation.
- Panes manage their PTY, output buffers, and status — each operating independently.
- AI agents handle prompt execution, tool use, and orchestration within their own actor.
The NATS Message Bus
The daemon embeds a NATS server (with JetStream KV for persistence). The TUI is a pure NATS client — it never reads daemon state directly, it only sends and receives messages over NATS. Every message is a typed Go struct serialized into a compact JSON envelope:
{
"t": "MsgConversationAppend", // type tag (discriminator)
"r": "_INBOX.abc...", // reply-to subject ("" = fire-and-forget)
"p": { /* the inner message, embedded JSON */ }
}
Subjects are namespaced per session (e.g. {session}.pane.{id}.output,
{session}.pane.{id}.inbox). Cross-machine sharing uses a workspace-scoped scheme
(ws.{workspaceID}.share.{shareID}.…) that the upstream server confines each
client to.
rysh-proto module publishes Protobuf reference
schemas (conversationpb, panemsgpb, memorypb,
envelopepb) that document these message shapes. The actual NATS wire
format is JSON — the canonical serialization types are the Go structs in
rysh-shared/msg.
Why Event-Driven?
- Natural isolation: Each pane and agent runs independently, so a slow AI response in one pane never blocks another.
- Built-in coordination: Because everything communicates through events, agents can naturally discover each other, share context, and coordinate workflows.
- Scalable: Adding more panes, tabs, or agents doesn't create contention — events are processed independently.
- Reliable persistence: Events drive state changes, making it straightforward to persist and restore workspace state.
Agent Awareness
Because every pane and its AI agent are part of the same event-driven system, agents have natural awareness of the broader workspace context.
How Agents See Each Other
- Each agent can enumerate all other panes and agents in the workspace.
- Agents can inspect another pane's output, status, mode, and command history.
- Agents can send commands (shell or AI prompts) to other panes.
- A shared key-value store allows agents to persist and retrieve context collaboratively.
Real-Time Context Sharing
When a pane listens to another pane's output (##pane listen), its agent
receives a continuous stream of context from the source pane. This enables workflows like:
- A “planner” agent that monitors a “developer” agent and provides feedback.
- A “tester” agent that automatically runs tests when a “developer” agent finishes writing code.
- Pipeline events (
##>event:...) that chain multiple agents through structured development phases.
Subscription Plans
The Rysh upstream server integrates Stripe for subscription billing. New users are automatically placed on a free tier; paid tiers raise the per-plan limits. Each plan caps the following dimensions (a value of 0 means unlimited):
| Limit | Applies to |
|---|---|
MaxWorkspaces | Workspaces you can create on the server |
MaxSessions | Concurrent sessions connected to the upstream |
MaxPanes | Panes within a connected workspace |
MaxConnections | External channel integrations (Slack, email, …) |
MaxChatbots / MaxChatbotSessions | Embeddable chatbot widgets and their live sessions |
ChatbotMessagesPerDay / ChatbotHistoryDays | Per-day chatbot message quota and transcript retention |
Enforcement
- Workspaces: Enforced when creating new workspaces on the server.
- Sessions: Enforced when connecting to the upstream server.
- Panes: Enforced when creating new panes in a connected workspace.
- The rysh daemon checks limits before creation via the server's
/api/resource/*endpoints; the Stripe webhook keeps the active plan in sync.