Limux has two control servers:
-
Standalone
limux-control-serverbinary — useslimux_core::DispatcherControlStateand supports the full command vocabulary. Used for tests and for CLI calls when the GUI isn't running.
-
Embedded bridge inside
limux-host-linux—control_bridge.rsonly routes a narrow subset of methods to the GTK main loop. Supportssystem.ping,system.identify,workspace.{current,list,create, select,rename,close},pane.list,pane.surfaces,surface.list,pane.createfor terminal self-spawn,surface.send_text,surface.send_key,surface.read_text,surface.health, andnotification.create. It still does NOT support browser commands.
When the GUI is running, the CLI targets the bridge via the runtime
socket. list-panes / list-panels, terminal new-pane --command ...,
text injection, key-level injection, surface-health, and terminal
read-screen now work against the running host.
Bridge should route unknown methods to a local Dispatcher instance
seeded with live GTK state, OR to dedicated per-method ControlCommand
variants that interrogate the live state. The cleanest path:
- Maintain a
Arc<Mutex<ControlState>>owned by the GTK app, kept in sync with live workspace/pane/surface state. - Bridge falls through unknown methods to
Dispatcher::dispatchon that shared state. - Specific methods that need GTK side-effects (send_text, create_surface,
notification.create) remain as
ControlCommandvariants.
The terminal introspection path is now bridged directly against live GTK state. Remaining proxy work is for deferred browser surface commands and broader dispatcher parity.
Shipped so far (in 6b8eb1a and follow-up bridge work):
surface.send_textandnotification.createnow passallow_name=truetoparse_optional_workspace_target, so peers can address each other by workspace name (--workspace claude) without juggling runtime UUIDs. This is what made phase 5 practical.pane.list,pane.surfaces, andsurface.listnow route on the live GTK bridge, so agents can discover peer panes/surfaces in a running Limux window.surface.send_keynow routes to the exact terminal surface when provided, so agents can send deterministic key-level control such as Ctrl-C.surface.healthandsurface.read_textnow route on the live GTK bridge, so agents can inspect peer terminal health and visible screen text.pane.createnow routes through the GTK bridge for terminal panes. From inside an agent terminal,limux new-pane --direction right --command claudeusesLIMUX_WORKSPACE_ID,LIMUX_SURFACE_ID, andLIMUX_PANE_IDto split the caller's pane, create a new terminal, and launch the command there.
Still open (priority order):
- Browser command bridge parity.
ControlCommand::CreateNotification wired through the bridge into
mark_workspace_unread_with_message + libadwaita toast.
CLI: limux notify [--workspace <id|name>] [--subtitle <…>] [--body <…>] <title>.
Reads hook JSON from stdin, translates the agent-specific event vocabulary
into a notify (and, where useful, an inline send). Drop-in for
~/.claude/settings.json hooks blocks.
limux agent-team [--agents codex,claude[,opencode,gemini]] [--cwd <path>] [--no-launch] [--dry-run]:
- Calls
workspace.createonce per agent withname=<agent>,cwd=<shared>,command=<agent CLI>so each workspace launches the agent automatically. - Bridge now passes
allow_name=truetoparse_optional_workspace_targetforsurface.send_textandnotification.create, so peers address each other by workspace name (limux send --workspace claude …) instead of needing to swap UUIDs. - Writes
AGENTS.mdin the shared cwd documenting:- the peers table (agent → workspace name → workspace ID → launch cmd),
- the
<agent-msg from="…" to="…" id="…" reply-to="…" ts="…">envelope, - the exact
limux sendinvocation for sending and replying, - the
limux notifyescalation path for human input, - the
LIMUX_*env contract every spawned terminal inherits, - editable Policies section (timeouts, size limits, destructive-action gating).
Nice polish, not blockers.
Without a real bridge, every subsequent feature ends up routing around the same hole: the GUI owns the ground truth about surfaces/panes but the CLI can't query it. Fixing this once, properly, makes phases 3–5 small.