Advanced

Agents and remote control

Use the semantic remote API to inspect and control a running Gloom desktop or TUI session.

gloom remote drives a Gloom app running on this machine, terminal (TUI) or desktop. Scripts and local agents read the screen, open panes, pick tickers and arrange layouts by name.

bash
gloom                                   # one terminal: the app
gloom remote help                       # another: the agent guide
gloom remote get app://snapshot --json  # what is on screen

Leave --app out when one app runs. Pass --app tui or --app desktop when both do.

You areUse
A script or local agent on the same machine as the appgloom remote: no account, no network
Claude Code, Codex or another assistant connected to Gloom CloudThe MCP server with Terminal control: the same operations, one MCP for data and the terminal, and the app asks you before an assistant takes over and before anything leaves the app
Anything that needs Cloud data with no app openThe MCP server without Terminal control

For headless data, reports and a screenshot of a function with no app open, use the CLI.

Commands

CommandUse
gloom remote helpAgent-focused usage from the running app
gloom remote schemaResource URIs, operations, request and response shapes
gloom remote get <resource>Read one resource
gloom remote call <operation> [json] [--dry-run]Invoke one operation
gloom remote patch <resource> <json-patch> [--expect-rev rev] [--dry-run]JSON Patch a mutable resource
gloom remote batch <json> [--dry-run]Run a multi-step workflow
gloom remote watch <resource> [--interval ms] [--limit n]Poll for changes

All take --app tui|desktop and --json. --dry-run on call only echoes the payload, with no check of the operation or its fields; on patch it returns the patched result without saving.

When no app answers

With --json the reason is in error.code, with message and details (what to do), and the command exits 1:

error.codeMeans, and what to do
app_not_runningNo app of this profile runs. Start gloom in another terminal, or open the desktop app
app_ambiguousThe terminal and desktop apps both run, and neither is the one started last. Pass --app tui or --app desktop
app_unreachableThe app's port does not answer from here, but nothing proves it gone: usually a sandbox that blocks localhost. Run the command where it can reach 127.0.0.1, or start Gloom again

An endpoint file left by an app that exited without quitting is removed once its process is gone and its port refuses. An unreachable app's file is kept.

Asked for the desktop app while only the terminal app runs:

json
{ "ok": false, "error": { "code": "app_not_running", "message": "The Gloom desktop app is not running.", "details": "The terminal app is: pass --app tui, or leave --app out." } }

Anything else that fails, such as an operation the app refuses, is cli_error.

Read the screen

app://snapshot is what is on screen in one read:

KeyHolds
appFocus and command bar. Read app.focusedPaneId; app.activePanel is deprecated and always left
configSettings and the layouts
panesEach pane, where it is, and whether it has focus
commandBar, formThe command bar, and an open form or the setup dialog
uiThe labelled UI controls
referencesWhere to read what the snapshot leaves out

It leaves out what an agent reads once or rarely:

Left outRead it from
Every resource and operation with its inputgloom remote schema, once
Recipes and caveatsgloom remote help (app://remote/help)
What each pane loaded (runtimeState, a saved layout's paneState)app://pane-state/{paneId}, app://panes, app://config
Unlabelled UI nodesui://tree

app://snapshot/full has all of it inline, the shape the snapshot had before 0.20.5. It is often several times the size: 413 KB against 73 KB with nine panes open.

bash
gloom remote get app://pane-templates --json
gloom remote get ui://tree --json

pane.screenshot returns a pane as a PNG (base64 in image.data, with its pixel size): the focused pane, or paneId from app://panes. Desktop only: the terminal app draws text.

bash
gloom remote call pane.screenshot '{}' --app desktop --json

First-run setup

On a new profile the setup dialog covers the app. app://form (and the snapshot's form) reads "open": true, "kind": "setup", with its step, title, fields by id and buttons:

json
{ "open": true, "kind": "setup", "step": "PORTFOLIO", "title": "What do you hold?",
  "fields": [{ "id": "ticker", "label": "Ticker", "value": "" }, { "id": "shares" }, { "id": "avgCost" }, { "id": "currency" }],
  "buttons": [{ "label": "Skip" }, { "label": "Continue", "disabled": true, "shortcut": "Enter" }] }

While it is open:

  • app.search and app.openCommandBar refuse, and app.closeDialog does not close it.
  • A change made behind it still runs, and its answer carries warnings saying the setup dialog covers it.
  • Its own controls match first in ui.invokeMatching.

Add a ticker and continue, or skip a step:

bash
gloom remote batch '{ "type": "batch", "requests": [
  { "type": "call", "operation": "ui.invokeMatching", "input": { "role": "form-field", "metadata": { "fieldId": "ticker" }, "action": "setValue", "input": "NVDA" } },
  { "type": "call", "operation": "ui.invokeMatching", "input": { "role": "form-field", "metadata": { "fieldId": "ticker" }, "action": "submit" } },
  { "type": "call", "operation": "ui.invokeMatching", "input": { "role": "form", "action": "submit" } }
] }' --json
gloom remote call ui.invokeMatching '{ "role": "button", "label": "Skip", "action": "press" }' --json
  • Submit on the Ticker field adds the position; { "role": "form", "action": "submit" } presses the button Enter would.
  • Skip leaves one step unfilled. A new profile has two steps, Portfolio and Desks.
  • A step can change after the call answers, so read app://form again before the next call.
  • When setup is run again, form.actions includes cancel, which skips all of it.

Open panes

When you know the pane, use a pane operation.

bash
gloom remote call pane.createFromTemplate '{ "templateId": "market-heatmap-pane" }' --json
gloom remote call ticker.pin '{ "symbol": "NVDA", "forceNewPane": true }' --json

For command-bar ranking and aliases, search then activate.

bash
gloom remote batch '{
  "type": "batch",
  "include": ["panes", "commandBar"],
  "requests": [
    { "type": "call", "operation": "app.search", "input": { "mode": "ticker", "query": "NVDA" } },
    { "type": "call", "operation": "commandBar.activateResult", "input": { "index": 0 } }
  ]
}' --json

Arrange the workspace

bash
gloom remote call layout.setGrid '{ "columns": 2 }' --json
gloom remote call layout.focusRegion '{ "region": "right" }' --json
gloom remote call layout.closeFloating '{}' --json
gloom remote call app.switchPanel '{ "panel": "right" }' --json

remote patch works on what remote schema marks patchable: app://config, app://layout/current, app://pane-state/{paneId} and app://pane-settings/{paneId}.

Read the resource and its rev first, then pass --expect-rev, so a stale edit fails instead of overwriting.

Semantic UI fallback

No app-level operation? Target UI nodes by role, label, contained text, metadata, or action.

bash
gloom remote call ui.invokeMatching '{ "role": "button", "label": "Open Help", "action": "press" }' --json

Use it sparingly; higher-level operations survive UI changes.

Concepts

ConceptMeaning
App kindtui and desktop are separate apps; --app picks one
ResourcesState to read: app://snapshot, app://form, app://panes, app://pane-templates, app://commands, app://capabilities, ui://tree
OperationsChanges: app.search, commandBar.activateResult, pane.createFromTemplate, pane.focus, ticker.navigate, layout.setGrid, ui.invokeMatching
CapabilitiesPlugin service operations, for plugin-owned data and side effects. The UI goes through app operations
  • Every operation changes only the local app, except capability.invoke, which runs a plugin capability and can reach external services.
  • watchlist.add and watchlist.remove ask in the app first and answer with what happened. Nothing else asks.