cc-window-control
The window and view control plane — arrange the app's own windows, open and pop out views, and steer the knowledge-graph canvas.
The sibling control plane to cc-terminals: where that server drives the terminal workspace, this one drives the shell itself. Its 28 tools fall into three groups — windows (list the topology, focus, move, resize, minimize, maximize, tile, and arrange), views (open any view, pop a view out into its own window), and the graph canvas (search and select nodes, focus and fit, pan and zoom the Cortex graph). Like its sibling it reaches the running desktop app through a local control endpoint, not a background daemon.
Its scope is deliberately narrow: it maneuvers Command Center's own windows only — it does not touch any other application on your desktop. Within that scope it is what makes spatial requests workable for agents and for Voice: "put the graph on the left and the terminals on the right" becomes a couple of tile calls, and "show me the neighborhood of this document" becomes a search-select-focus sequence on the canvas. Every action is visible on your screen as it happens — this plane moves what you are already looking at, which is its own kind of audit.
How your agents use it
- "Set up my review screen." —
view_showto open the views,view_popoutfor a second window,window_tileorwindow_arrangeto lay them out across the monitor. - "Show me where this document sits in the graph." —
graph_searchto find the node,graph_selectandgraph_focus_nodeto center it,graph_fitto frame the neighborhood — the canvas moves while the agent explains what you are seeing. - "Which windows are open right now?" —
window_topologyreturns the live layout an agent can reason about before rearranging anything.
Prerequisites
The desktop app must be running; the control endpoint is written at app startup and the plane's settings live in the configuration reference. No keys and no model cost — these tools only move the app you already have open.
Tool reference
| Tool | Parameters | What it does |
|---|---|---|
window_ping | — | Round-trip health check against the Command Center's WINDOW control server. Returns {pong:true} when reachable, or a structured error if the CC app isn't running with CC_WINDOW_CONTROL=1. Distinct from terminal_ping (a separate plane). |
window_topology | — | SENSE-FIRST — the mandated first call before placing/moving/closing any window. Returns {monitors, focused_window, windows}: monitors are POSITIONAL 1-based (index 1 = leftmost) with primary/is_current/spatial(left|center|right)/name/position/size/work_area/scale_factor; windows list every CC window with {label, kind(main|view|terminal-workspace|pane|widget), view_id|target, monitor_index, position, size, focused, visible, minimized, maximized}. Use this to resolve 'monitor 2' → the index, 'this screen' → is_current:true, and 'the cortex window' → its label. Read-only. |
view_list | — | List the Command Center's feature views AND each view's internal tabs — [{view_id, label, poppable, tabs:[{id,label}]}]. THE single discovery call for in-app navigation: map a spoken name ('cortex', 'the graph', 'reports') to a view_id + tab id, then call view_show / view_popout with `tab` (and/or `select`). Static catalog; no CC round-trip. Read-only. |
view_show | view_id*: string, tab: string, select: object | Navigate to a feature view — the default for a bare 'open X' / 'go to X' / 'show me X' (NO new window is created). REALM-AWARE: if the view is ALREADY popped out in its own window, that window is focused + deep-linked instead of duplicating the view in the main window; otherwise the MAIN window navigates. e.g. 'open cortex' → view_show(cortex); 'open cortex on the lint tab' → view_show(cortex, tab='lint'). Optional `tab` + `select` (a content node). For CORTEX GRAPH interactions (select/search/camera on the knowledge graph) prefer the graph_* tools — they are the precise, realm-routed surface with read-backs; use view_show only to open/navigate. For 'pop out X' / 'put X on monitor N' / 'X in a new window' use view_popout instead. |
view_popout | view_id*: string, tab: string, select: object, monitor: object, anchor: string, fraction: number, margin: integer, target: string | Open (or focus) a feature view in its OWN window, optionally placed on a monitor AND deep-linked — the default for 'pop out X' / 'X in a new window' / 'put X on monitor N (left half)'. e.g. 'pop out cortex on my second monitor, left half' → view_popout(view_id='cortex', monitor=2, anchor='left'); 'pop out documents on monitor 2 showing this digest' → view_popout(view_id='documents', monitor=2, anchor='right', select={kind:'file', path:'…session_digest…md'}). Placement is flash-free (rect computed server-side); the tab/select land race-free via the window's ?nav suffix. Omit monitor/anchor to open at the view's default. For Terminals, pass the workspace id as `target` (Terminals pops out per-workspace). |
email_open | account*: string, folder*: string, uid: string, popout: boolean, monitor: object, anchor: string | OPEN / SHOW an email item in the Command Center's Email view for the operator — a specific message, a draft you just wrote, or a Sent/Archive item, in ANY configured account. Flat convenience over view_show(select={kind:'email'}). DISCOVER first with the email tools: email_list_accounts (the account id), email_list_folders (the REAL folder name), email_list_messages/email_search (the uid) — or reuse the uid returned by email_save_draft*. Omit `uid` to just open that folder's message LIST. Shows in place by default (focuses an existing Email pop-out, else navigates the main window); set popout=true (and optional monitor/anchor) to open it in its OWN window on a monitor. DISPLAY only — reading/managing/sending mail is the email tools' job. |
window_arrange | target*: string, anchor*: string, monitor: object, fraction: number, margin: integer | The PRIMARY maneuver verb — snap a window to a semantic anchor on a monitor's work area. e.g. 'move cortex to the left half of monitor 2' → window_arrange(target='view-cortex', anchor='left', monitor=2). Half/third/quarter tiling, work-area maximize, center — all via `anchor`. |
window_move | target*: string, monitor: object, x: integer, y: integer | Move a window to a precise position (WORK-AREA-relative: x,y = offset from the target monitor's top-left work-area corner). For semantic placement ('left half') prefer window_arrange. Size is unchanged. |
window_resize | target*: string, width: integer, height: integer, fraction: number, monitor: object | Resize a window. Give explicit width+height (physical px), OR a `fraction` of the (optional) monitor's work area (default 0.5). Position is unchanged. |
window_set_bounds | target*: string, monitor: object, x*: integer, y*: integer, w*: integer, h*: integer | Escape hatch — set an explicit window rectangle (WORK-AREA-relative x,y + w,h, physical px) on an optional monitor. For precise/power placement; prefer window_arrange for the common cases. |
window_tile | items*: array, monitor: object | Lay out MULTIPLE windows at once on one monitor — e.g. 'put observer left and cortex right' → window_tile(items=[{target:'view-observer',anchor:'left'},{target:'view-cortex',anchor:'right'}], monitor=1). Each item is {target, anchor, fraction?}; a top-level `monitor` applies to all (per-item `monitor` overrides). Skips windows it can't place (voice-widget/dictation-overlay are best excluded). |
window_focus | target*: string | Raise + focus a window (bring it to the foreground). NB: Windows foreground-lock may only flash the taskbar when the request comes from a background app — the result reports the real outcome. |
window_minimize | target*: string | Minimize a window. REFUSES 'main' (minimizing the main window suspends the JS that hosts the control bridge). Prefer defocusing over minimizing a window running live voice/terminal. |
window_maximize | target*: string, monitor: object | Maximize a window to fill its monitor's WORK AREA (the taskbar stays visible — this is NOT native maximize, which would cover the taskbar on a frameless window). Pre-maximize bounds are remembered so window_restore returns to them. Optional `monitor` maximizes onto a specific screen. |
window_restore | target*: string | Undo a maximize (back to the remembered pre-maximize bounds) or a minimize (un-minimize). The inverse of window_maximize / window_minimize. |
window_close | target*: string | Close a pop-out window (e.g. 'close the cortex pop-out' → window_close(target='view-cortex')). REFUSES 'main' (that would quit Command Center). Uses a graceful close: a window with unsaved changes prompts the operator and the result is {requested:true} (the close may be deferred); a terminal-workspace window docks back into the main. Sense-first — check window_topology; don't close the operator's actively-focused window without confirmation. |
graph_state | include_visible: boolean, visible_limit: integer | SENSE-FIRST for the Cortex graph — read the live state of the knowledge-graph visualization: which window hosts it (realm), the open tab, the active surface (graph-pane | overview), workspace + render mode, loading flag, node/edge counts, current selection WITH the selected node's properties (selected_node_info: id/label/type/path — the path is Documents-open ready), search term + match count, view toggles, and the camera {x,y,ratio}. Pass include_visible:true for a bounded sample of the nodes currently on screen (id/label/type + layout x,y + screen px). Also the poll target while a graph_show load is in progress (loading=false = done). Read-only. |
graph_node_positions | node_ids: array, visible_only: boolean, limit: integer | Read node POSITIONS from the rendered graph — layout coordinates + on-canvas screen pixels + hidden/on_screen flags, batched. Pass node_ids for specific nodes (missing ids come back found:false), or omit to sweep the visible nodes (bounded by limit, truncated flag set when capped). This is how you 'see the space' before focusing/panning. Read-only. |
graph_find_nodes | query*: string, limit: integer | Find nodes in the CURRENTLY RENDERED graph by NAME — ranked matching (exact label > label prefix > contains > id contains; closest-to-root first). THE cheap resolver for 'the documents node' → its full path id, scoped to what is actually on the canvas (unlike the arcadedb corpus-wide tools). Returns [{id, label, type, depth}]. Read-only. |
graph_show | workspace: string, mode: string, reference_edges: boolean | Change WHICH graph is shown — switch the workspace, toggle the root Entities layer (mode: structure|entities; root-type workspaces only — others always render entities), and/or toggle the cross-document reference-edge overlay. Drives the MOUNTED surface IN PLACE (the Overview widget's own workspace dropdown, or the Workspaces tree) — it never hijacks the operator's tab; only when no graph canvas is on screen does it open the Workspaces surface (seeding the workspace so it never lands on an empty 'Select a workspace' state). The ack returns immediately with loading:true — poll graph_state until loading=false (a cold workspace load can take seconds; the voice session is never blocked). |
graph_select | node_id: string, node_ids: array, focus: boolean, workspace: string | Select a node on the current graph (the single-click equivalent — teal ring + the node details panel opens), or several nodes at once via node_ids (multi-select — the bulk-action panel opens). Optional focus:true also centers the camera on a single selected node. The ack returns the node's PROPERTIES — id/label/type + `path` (Folder/Document ids ARE file paths: pass it straight to view_show/view_popout(documents, select={kind:'file'|'folder', path}) to open it) + parent_path/about/last_modified, and for a FOLDER its immediate children (subfolder + file names, capped, with honest totals). The node must exist in the CURRENTLY RENDERED graph — switch first with graph_show if needed. If Cortex is closed, a single-node select auto-opens it carrying the selection. |
graph_select_downstream | node_id*: string, additive: boolean, list_paths: boolean | The DOUBLE-CLICK equivalent — select a folder node plus its ENTIRE downstream subtree (all subfolders + files), using the exact same descendant walk the canvas's double-click uses. additive:true ADDS the subtree to the current selection (the shift+double-click behavior); default REPLACES it. The ack describes the folder's CONTENTS: root node properties (incl. `path`), subtree totals {subfolders, files}, and the immediate children's NAMES (capped, honest totals). Pass list_paths:true to also get the full descendant path list (capped 200). Selecting 2+ nodes opens the bulk-action panel. On a non-folder node it selects just that node. |
graph_deselect | node_ids: array | Clear the graph selection (the click-empty-canvas equivalent). Omit node_ids to clear EVERYTHING (single selection + multi-select set); pass node_ids to remove just those from the multi-select set. |
graph_search | term*: string | Type into the graph search box — non-matching nodes HIDE (a filter, not a highlight; layout untouched). Matches against node name/label/id/description/summary, case-insensitive. term:'' CLEARS the search (the X button). The ack reports the match count. Note: the search also auto-clears when the workspace switches. |
graph_focus_node | node_id*: string, ratio: number, select: boolean | Center the camera on a node (with optional zoom ratio) — the PREFERRED way to 'go to / look at node X' (beats manual pan/zoom). ALSO SELECTS the node by default (focused = chosen; pass select:false for a camera-only move) and the ack returns the node's properties incl. `path` — so a follow-up 'open this in documents' needs no search. ratio: 0.05 = very close … 2.5 = far out (omit to keep the current zoom). |
graph_zoom | direction: string, steps: integer, ratio: number | Zoom the graph camera. direction:'in'|'out' applies `steps` UI-button-sized (×1.25) zoom steps in ONE smooth animation — default 2 steps per call for a clearly visible change (use 3 for a big jump; the operator's own buttons/wheel sensitivity is untouched). Or pass an absolute ratio (0.05 = very close … 2.5 = far out; 1 ≈ the fitted view). Rapid successive calls COMPOUND correctly (each builds on the pending target). Returns the camera state. |
graph_pan | dx: number, dy: number | Pan the graph view by a FRACTION of the viewport: dx=0.5 looks half a screen further RIGHT, dy=-0.25 a quarter screen UP. For 'go to node X' prefer graph_focus_node; for 'show everything' prefer graph_fit. Returns the camera state. |
graph_fit | — | Reset the camera to frame the WHOLE graph (the 'Fit to view' button) — the fastest way to recover from any zoom/pan state. |
Where to go next
- Cortex — the graph canvas these tools steer
- Voice — the assistant that uses this plane for spoken window and canvas control
- cc-terminals — the sibling plane for the terminal workspace