The `##` command language: a tiny shell for driving your whole workspace
Menus don't compose and agents can't click them. Every rysh capability — panes, sessions, sharing, agents — is a typed ## command on the input line.
Every power tool eventually faces the same interface decision: menus or language?
Menus are discoverable and dead-ended — you can click them, but you can't script them, compose them, or hand them to an automation. Languages are the opposite: a learning curve that pays compound interest.
Terminals settled this argument decades ago. So when we built rysh, the multiplexer itself got a language too. It's spelled ##.
One prefix, the whole platform
In any rysh pane, a line starting with ## doesn't go to your shell and doesn't go to the AI — it's a system command, interpreted by the workspace itself. The family tree:
##help # discover everything below
##tab … # tab operations
##pane … # pane operations (name, listen, unlisten, …)
##panegroup … / ##pg … # pane-group operations
##public / ##private # control what leaves this pane
##snap # workspace snapshot
##session … # session management
##share … / ##unshare … # collaboration
##upstream … # remote shares
##raw # toggle raw terminal mode
##agent … # autonomous agents
##humanoid … # agents on external channels
Same input line as your shell commands and your prompts. Double-Escape flips who you're talking to (shell vs AI); ## addresses the room itself.
A guided tour in six commands
Name things. ##pane name builder gives the active pane a given-name (unique per lane; Ctrl+P r does the same interactively). Names matter because everything else takes them as arguments.
Wire panes together. ##pane listen builder subscribes your pane to the builder pane's redacted output stream; ##pane unlisten disconnects. This one command is the foundation of cross-pane observation and pipeline events.
Manage sessions without leaving your seat.
##session # info about this session
##session list # all sessions, current marked >
##session switch qa # ensure qa's daemon runs (spawn if stopped)
##session reload # flush workspace state to KV now
These run daemon-side through the session registry — which is why they behave identically in the CLI and the desktop app. The UI is just the messenger.
Share your work, precisely.
##share pane view # remote collaborators can watch this pane
##share pane control # …or drive it
##share tab # share a whole tab; ##share panegroup works too
##share list # what am I sharing?
##share status # upstream connection health
##unshare pane # stop
Subscribe to someone else's.
##upstream shares # what's available on the upstream server
##upstream subscribe <id> # watch a remote share from a local pane
##upstream send "make test" # send input (control-mode shares only)
##upstream unsubscribe
Set your privacy boundary. ##private routes subsequent output to a private buffer that never reaches any shared stream; ##public reopens the tap. Redaction is automatic; this is the manual override.
Beyond commands, two more prefixes complete the input grammar: @agent-name <prompt> addresses an autonomous agent by name, @@agent-name stop|activate|deactivate controls one, and ##> lines are pipeline events — signals other panes react to. The ##agent and ##humanoid families (spawning agents from markdown skill files, wiring them to Slack/email/website chat) are deep enough to deserve their own articles.
Why a language beats a settings panel
1. It composes with everything that speaks text. The killer consequence: rysh send delivers input to a pane in a running or detached session — including ## commands:
rysh send myproject "##share pane view" --mode shell
rysh send myproject "##session reload"
Your multiplexer's controls just became scriptable from cron, CI, SSH, anything. A menu can't do that.
2. Agents can drive the room too. Rysh agents have workspace-aware tools — inspecting panes, sending input to other panes, listing agents. The ## language means the workspace's capabilities are expressible in the medium agents already work in: text. An agent that can be told "share your pane when you're done" lives in a different universe from one whose environment is controlled by mouse-only chrome.
3. One path, no drift. Every ## command is parsed and routed through the same actor pipeline as everything else — published to the workspace inbox as a typed message, dispatched to the owning actor (workspace, tab, pane), executed sequentially in its mailbox. Command output comes back on its own dedicated stream (.output.rysh — one of the pane's four output streams), so system chatter never pollutes your shell/AI transcript. There is no privileged UI backdoor that behaves differently from the language. The language is the interface.
Keybindings for the hands, language for the system
To be clear: rysh is not keyboard-hostile. Ctrl+P/Ctrl+T/Ctrl+S/Ctrl+L modes handle the split-rotate-resize choreography your hands do a hundred times a day — spatial actions belong on keys.
The division of labor is deliberate: keybindings for reflexes, ## for semantics. Splitting a pane is a reflex. "Subscribe this pane to that one's output, redacted" is a sentence — and sentences deserve a grammar, not a chord.
Learn six commands and the multiplexer stops being an app you operate and becomes a system you address — and so can your scripts, and so can your agents. That's the point of a command language: everyone who speaks text gets to be a power user, including the colleagues you spawned from a markdown file.
Rysh is early. Want to help decide what the language grows next? Become a design partner: rysh.ai/design-partner
Related: rysh send: headless control · ##pane listen