ctl

Brief

Every Terminal Delight window listens on its own control socket, and the same binary is the client. terminal-delight ctl lets a script, a keybinding, a status bar or an agent's own shell change a running window without touching any terminal in it.

terminal-delight ctl tab name "deploy"
terminal-delight ctl mcp on
terminal-delight ctl doc beside /home/you/notes/plan.md

It names and groups tabs, turns panes to their workbench, opens documents, switches the MCP server, picks a skin, and hands a new terminal to a window. Each command gets one line back, ok or err with the reason. By default it talks to the windows on your active Hyprland workspace, or the window you're running in for tab commands; --all or --pid choose others.

Technical lists every command and its reply.

Technical

The control socket

Each window, scratch windows included, listens at $XDG_RUNTIME_DIR/terminal-delight/ctl-<pid>.sock, in a directory kept at 0700. The client sends one line and reads one line back, then the connection closes. Effects are queued to the window, so ok means the command was accepted. The CLI checks your command against the window's grammar before sending, so a typo fails at once with the usage line.1

Which windows#

FlagTargets
noneEvery window on the active Hyprland workspace. For tabs: the window you're running in.
--workspace active|<name-or-id>The windows on that workspace.
--allEvery window with a socket.
--pid <N>One window.

tab … always means your own tab and refuses a scope flag. adopt and tabs go to the first target only; everything else goes to every target. Each reply prints as <pid> <reply>. A window with no socket prints err no control socket (older build — reopen this terminal).

Exit codes: 0 when at least one window answered with something other than err; 2 when nothing matched or every reply was err; 1 for a usage error.

The client waits 800 ms for a reply. If a window takes longer, the client prints err unreachable … — swept stale socket and deletes that window's socket, although the window is alive. Until the window restarts, neither ctl nor terminal-delight mcp can reach it. The bench and doc commands and mcp rpc can take longer than that on a busy window. It's tracked in issue 796.

Commands#

After terminal-delight ctlReplyDoes
pingpongIs it there.
whoamiok <session> <window-pid>Which session a window holds.
paint on|off|toggleokThe palette overlay over every pane.
paint statuson or off
skin <name>, skin themeok <name>Pick a skin, or follow the theme's.
skin statusactive=<id> known=<ids>
bench on|off|toggleokEvery pane to its workbench, or its terminal.
bench choose <n>e.g. ok pane 3Answer the question waiting on the bench with option n (1 to 20).
bench submitSend the open round of answers.
bench say <text>Type a line to the focused pane's agent through the bench, and send it.
bench type <text>The same without sending.
doc here <path>Float a document over the focused pane. The path must be absolute.
doc beside <path>Open it in a pane beside the focused one.
doc close, doc scroll <pixels>Close the floating document; scroll a document pane.
mcp statusenabled=on writes=off expose=agents events=on
mcp on|off, mcp writes on|off, mcp expose agents|allokThe MCP switches, saved with the session.
mcp rpc <json>the JSON-RPC answerOne MCP call. mcp-none for a notification.
adopt --cwd <dir> [--run <cmd>]okOpen a new pane in a directory, running a command. Used by SUPER+ALT+T on Omarchy.
tab name [<text>]ok 1Name your own tab; no text clears it.
tab group <name>, tab ungroupok 1Put your own tab in a group, or take it out.
tabs <json>ok <n>Several tab operations at once; see below.

Tab operations#

tabs takes a JSON array, or {"ops": […]}. Each operation has an op:

opFields
namename, a string or null
groupgroup, and optionally color and text_color for a new group
ungroupnone
colorcolor and/or text_color; null clears
group_colorgroup, color, text_color
collapsegroup, collapsed

A tab operation names its tab with exactly one of tab (its index, which changes when tabs move) or pane (a shell pid in it, which doesn't). Colours are #rrggbb. An error says which operation failed: tabs: op 2: ….

terminal-delight ctl tabs '[{"op":"name","pane":4121,"name":"api"},{"op":"group","pane":4121,"group":"backend","color":"#3ec6d1"}]'

What would prove this wrong#

No ctl command writes bytes into a terminal's input except bench say and bench type, which go to the agent through the bench on purpose. Any other command that does is a bug.

Sources

  1. The grammar, the client and the replies: ctl.rs.