Skip to main content

agterm

Drive agterm, a native macOS terminal, through its agtermctl CLI and local control socket. Use when running inside an agterm session and asked to control the terminal: create, rename, close, select or reorder sessions and workspaces; split panes; toggle the scratch terminal; run a program in an overlay and read its exit status; post a HUD panel or a desktop notification; show a native picker with caller-supplied choices or a question dialog with named buttons; display an image inline; type into a session, copy its selection or search its scrollback; manage windows; change font size; set the theme; reload or edit the keymap, the event hooks and the agterm-scoped ghostty config; subscribe to status, notification, lifecycle, pane-visibility and tree-change events. Covers the window/workspace/session addressing model and the AGTERM_* environment a spawned shell sees, attaching a session running on another Mac, the cookbook recipes, the running version, and diagnosing problems or filing an agterm bug or feature re

Ir para a instalação

Informações da origem

Repositório
umputun/agterm
Última atividade na origem
15 de setembro de 2026 às 06:56
Idioma detectado do SKILL.md
inglês
Estrelas
606
Forks
76

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Explorador de arquivos
6 arquivos

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
agterm
description
Drive agterm, a native macOS terminal, through its agtermctl CLI and local control socket. Use when running inside an agterm session and asked to control the terminal: create, rename, close, select or reorder sessions and workspaces; split panes; toggle the scratch terminal; run a program in an overlay and read its exit status; post a HUD panel or a desktop notification; show a native picker with caller-supplied choices or a question dialog with named buttons; display an image inline; type into a session, copy its selection or search its scrollback; manage windows; change font size; set the theme; reload or edit the keymap, the event hooks and the agterm-scoped ghostty config; subscribe to status, notification, lifecycle, pane-visibility and tree-change events. Covers the window/workspace/session addressing model and the AGTERM_* environment a spawned shell sees, attaching a session running on another Mac, the cookbook recipes, the running version, and diagnosing problems or filing an agterm bug or feature request.
when_to_use
Trigger on: agterm, agtermctl, AGTERM_SESSION_ID, and, from inside a session, plain requests such as split the pane, close the overlay, show a message over the session, show a question dialog, agtermctl ask, show an image inline, search the scrollback, attach a session from another Mac, what recipes are there, the keymap editor will not open.
allowed-tools
Bash(agtermctl *)
<!-- agterm-skill --> # Driving agterm agterm is a native macOS terminal. It exposes a programmatic control channel over a local unix socket, driven by the companion CLI `agtermctl`. Use it to build and steer terminal layouts, run programs in overlays, type into sessions, notify the user in the exact session you are working in, and subscribe to control events. Events cover status, notifications, session lifecycle, split and scratch pane visibility, and structural tree changes; `hooks.conf` runs a shell line on any of them. They do not stream terminal output; use `session text` to read a buffer. ## Am I inside agterm? Each shell agterm spawns gets these environment variables. Check `AGTERM_ENABLED` before assuming the control channel is available: - `AGTERM_ENABLED=1` — this shell runs inside agterm. - `AGTERM_SESSION_ID` — the current session's UUID (the session this shell belongs to). - `AGTERM_WINDOW_ID` / `AGTERM_WORKSPACE_ID` — the owning window / workspace UUIDs. - `AGTERM_SOCKET` — the absolute path to the control socket this app bound. - `AGTERM_PANE` / `AGTERM_PANE_ID`: the surface's spawn role (`left`|`right`|`scratch`) and stable per-surface token. The role is not rewritten after promotion or swap; the token resolves the LIVE slot. Prefer `--pane-id "$AGTERM_PANE_ID"` where supported, including `session status`, `session restore` and `session text`. The agent-status hook forwards both values for compatibility. - `TERM_PROGRAM=agterm` / `TERM_PROGRAM_VERSION` (agterm's version): the terminal identity, replacing the `ghostty` pair embedded libghostty would set. A tool that decides a capability from a list of terminal names (Claude Code's OSC 8 hyperlinks) needs its own override; see troubleshooting.md. The quick terminal is scratch (not in the tree) and belongs to no window, so of the `AGTERM_*` variables it only gets `AGTERM_ENABLED` and `AGTERM_SOCKET` (no session/workspace/window ids). An untargeted `agtermctl` run from it therefore resolves the active window like any other caller. These variables are inherited by every process the session's shell spawns — including long-lived daemons that outlive the shell. A tmux/screen server, a session manager (agent-deck and the like), or any background service started from inside a session captures the spawning session's `AGTERM_*` and passes it to every child it ever creates, so status hooks running in those children resolve `$AGTERM_SESSION_ID` to the session that happened to start the daemon and report to the WRONG session. Before starting such a process from inside agterm, scrub the variables (`env -u AGTERM_ENABLED -u AGTERM_PANE -u AGTERM_PANE_ID -u AGTERM_SESSION_ID -u AGTERM_SOCKET -u AGTERM_WINDOW_ID -u AGTERM_WORKSPACE_ID <cmd>`); see troubleshooting.md ("agent-status glyph updates the wrong session") for diagnosing and fixing an already-poisoned tmux server. ## Running agtermctl `agtermctl` must be on PATH (install it from agterm's **Help ▸ Install Command Line Tool…**). If it is not on PATH, the user can install it, or you invoke it by absolute path. - The socket path auto-resolves; usually no `--socket` is needed. To be explicit, pass `--socket "$AGTERM_SOCKET"`. - `--socket` and other options go **after** the subcommand: `agtermctl tree --json`, not `agtermctl --json tree`. - Add `--json` to any command to get the raw JSON response (machine-readable). Without it, ordinary mutations print `ok`, batch close/move prints the affected session count, and `tree`/`list` print a human listing. - Commands other than `events` make one request per invocation. `events` polls with a fresh connection for each request. Mutating commands return the affected/new id; batch session mutations return the number actually changed. Create commands (`session new`, `session duplicate`, `workspace new`, `window new`) print the new id. ## The model A **window** is the top level: a named bundle rendered in its own on-screen macOS window. Each window holds a tree of **workspaces**, each holding **sessions**. A session has a primary shell and can also have: a **split** pane (a second shell side by side), a **scratch** terminal (a third full-coverage shell, toggled like the split), and an ephemeral **overlay** (runs one program on top, then vanishes). An overlay covers the whole session, or with `--pane left|right` exactly one split pane, leaving the sibling pane visible and usable. The same session-wide slot also holds a **HUD** (`session hud`), a small passive panel carrying a message instead of a program. A HUD can use the whole session or one pane as its placement bounds. The session keeps focus and stays typable under it. One slot, so a session shows either a HUD or a program overlay, never both. Separately, the app has one **quick terminal** (a scratch shell in a floating panel at 90% of the focused screen capped at 1100x700, or whatever share Settings sets instead; not part of the tree and not owned by a window). Inspect the live tree any time with `agtermctl tree --json` (workspaces → sessions, each with `id`, `name`, `cwd`, `splitCwd`, `title`, `active`, `split`, `overlay`, `hud`, `ask`, `scratch`, `status`, `background`, `surfaces`). `title` is the raw OSC terminal title (e.g. a remote host over SSH), omitted when none was reported — read it when a session's local `cwd` is stale because it's connected to a remote. `splitCwd` is the split pane's last reported directory, falling back to its restored directory, then the primary cwd. It is present for a shown or hidden split and omitted without one or on older servers. `surfaces[].id` is the control address for `surface zoom` and `surface cursor` (`left`, `right`, `scratch`, `overlay`, `overlay-left`, or `overlay-right`), including hidden-but-alive split/scratch surfaces. The tree object also carries read-only top-level fields — `idleMs` (ms since the last user input in the window), `autoFollowMs` (the Auto-follow timeout in ms, omitted when Disabled), `sidebarVisible` (whether the window's sidebar is currently shown — the read side of the write-only `sidebar` command), `sidebarMode` (`tree` or `flagged` — the read side of `sidebar mode`), `sidebarWidth` (the sidebar divider position in points — the read side of `sidebar width`, on `tree` only), `workspaceFilter`, `quickVisible` (whether the quick terminal is shown — the read side of the write-only `quick` command; app-level, so every window reports the same value), `zoomedSurface`, the four `dashboard*` fields, `pickPending`, `askPending` (GUI asks only), and `app` (the serving app's `version`, plus `commit` when the build recorded one — the same value `agtermctl version` returns). reference.md lists every one with its exact shape. List windows with `agtermctl window list --json`; each window also reports `autoFollowMs`, `sidebarVisible`, `geometry` (the live frame `{x, y, width, height, display}` in the units `window move`/`window resize` take — the read side, so record it then restore the exact frame), and `fullscreen`/`zoomed`/`minimized` (the read side of `window fullscreen`/`window zoom`/`window minimize`, so a script can act idempotently) — all omitted for a closed window, but not the live `idleMs`, which is `tree`-only. A MINIMIZED window still reports its `geometry` (the frame it comes back to), so a re-align script can include it. ## Addressing Commands that target a session or workspace take `--target` (default `active`): - `active` — the selected session / current workspace. - a full UUID (case-insensitive), or a unique **prefix** of one (git-style). Zero matches → `notFound` error; two or more → `ambiguous` error listing candidates. `window.*` commands take the window id/prefix/`active` as a positional argument. Other commands accept a global `--window <id|prefix|active>` to operate on a specific window's tree (default: the frontmost). Scripts rarely type ids: create with `*.new` (capture the returned id), or act on `active`. **Agents: `active` is almost never your own session.** `active` is the session the USER has selected in the GUI; your shell runs in `$AGTERM_SESSION_ID`, and the user is usually on a different session while you work. For any session-scoped command meant to act on *this* session — `session overlay open`, `session scratch`, `session type`, `session text`, `session background`, `session status`, `session copy`, … — pass `--target "$AGTERM_SESSION_ID"`. Omit it and you open overlays / type into whatever the user has selected, not your own session. ## Restore modes **Settings ▸ General ▸ Restore sessions** is global and takes effect after restarting agterm: - **Fresh shells** restores the saved windows, workspaces, sessions, directories, and split layout with new shells. - **Re-run commands** starts each captured foreground command again. It does not reconnect to the old process. - **Live sessions** runs every primary and split pane through zmx and reattaches to the same process. It requires zsh as the macOS login shell. Scratch, overlay, and quick terminals stay temporary. On a clean quit, agterm leaves live daemons running and captures each open pane's foreground command as a fallback. A surviving daemon ignores that payload on the next launch. If an orderly machine restart removed the daemon, zmx creates it with the captured command and the pane remains live. A pane starts a fresh shell instead when its window was closed before quit, a hard power loss or force quit skipped capture, or the command is denylisted or carries a control character. SIGTERM leaves live daemons running but skips capture. `tree --json` is the only backing indicator: primary and split entries report `surfaces[].backedByZmx`, and the session-level `backedByZmx` is true only when every existing primary or split is backed. The sidebar has no zmx glyph. Switching to Fresh shells or Re-run commands and restarting ends every detached live process in the state directory. A launch that still requests Live sessions but cannot use it preserves those processes. Reattach keeps usable text, TUI state, and normal colors. It does not retain inline images, earlier OSC 133 prompt markers, program-changed palette entries, or hyperlink metadata already attached to cells. New output after reattach behaves normally. ## Launching a program in a session **Bind it at creation.** `session new --command` (and `scratch --command`) makes the program the session process, so no shell line is involved: ```bash agtermctl session new --cwd ~/proj --name worker \ --command "zsh -lc 'claude \"\$(cat ~/brief.md)\"'" # GUI PATH: wrap a non-default binary ``` In Fresh shells and Re-run commands modes, the session closes when this command exits unless `--wait` holds the final output. In Live sessions mode the command is a create-only zmx payload, which bypasses the 1,024-byte PTY input cap. A surviving daemon ignores the payload; a new daemon runs it, then starts the persistent shell. The shell stays open after it exits and `--wait` adds no hold prompt. After a clean quit, a missing daemon replays the captured running command inside a new persistent shell. The exclusions above start a fresh shell. `session type` drives an ALREADY-RUNNING program — it is not a launcher. Its keystrokes land in a line buffer you do not own: a newline submits (a multi-line brief becomes N premature Enters), and the user or a concurrent agent writes to that same buffer. An untargeted `session type` from another agent hits whatever is `active`, and `session new` focuses — so a just-created session is briefly `active`, a stray prompt concatenates with yours, and the program starts on the merged line. (`--no-select` skips the focus, but the newline and shared-buffer hazards of `type`-as-launcher remain — `--command` is still the rule.) After `--command`, confirm in `tree --json` that the new node's `foreground` shows your program running, not a bare shell prompt. ## Command summary Run `agtermctl <area> <cmd> --help` for exact flags. Full detail in **reference.md**; worked examples in **examples.md**; installable community workflows in **cookbook.md**. **tree** — print the workspace/session tree (`--json` for structured). Each session node carries `foreground`/`splitForeground` (the live argv of each pane's foreground process, omitted when the pane is at its shell prompt, or running a setuid/setgid program like `top` or `sudo` whose argv macOS won't expose) — i.e. what each pane is currently running — `foregroundShell`/`splitForegroundShell` (the shell holding each pane's foreground as a basename, present exactly when that pane's `foreground` is omitted because a shell holds it, so an EXISTING pane with neither is one whose process could not be read; check `hasSplit` before reading the split pair. Not a claim the pane is at a prompt and never permission to type — a builtin like `read` runs inside the shell), `restoreCommand`/`splitRestoreCommand` (each pane's persisted restore-command override set via `session restore` — the read side: omitted = auto-capture, `""` = pinned to nothing (a plain shell), a command = the shell line that runs on the next launch), `status` (the agent-status set via `session status`: `active`|`completed`|`blocked`, omitted when idle), `statusPane` (which pane set that status: `left` (main) | `right` (split) | `scratch`, from `session status --pane`, omitted when unset or idle), `statusBlink`/`statusColor`/`statusShape` (the status glyph's `--blink` flag, its `--color` `#rrggbb` tint and its `--shape` silhouette from `session status`, omitted when idle / not blinking / using the configured color or shape — the tint and the silhouette report the per-call override only), `statusChangedAt` (when that status was last set, in epoch seconds — the same clock as an event's `ts`; omitted when idle, and refreshed by a re-push of the SAME status, so `now - statusChangedAt` is how long ago the status was last written — normally the agent's own push, though a pane promotion re-tags the indicator and counts too; ephemeral, so it does not survive a restart), `background` (the background spec — image/text watermark or solid color — set via `session background`, omitted when none — the read side of set/clear), `unseen` (the unseen-notification badge count — raised by `notify`/OSC 9/777, cleared by `session seen`; omitted when zero), `commandWait`/`splitCommandWait` (whether either pane's `--command` was created with `--wait` to hold open after exit, the read side of `session new --wait`; each omitted for a plain or non-holding pane), `overlaySizePercent` (an open overlay's floating-panel percent 1-100, omitted for a full-pane overlay or no overlay so gate on `overlay` first; the read side of `session overlay resize` for a record-then-restore zoom), `paneOverlays` (the panes covered by their own overlay — `["left"]`, `["right"]` or `["left","right"]`, omitted when neither is; the read side of `session overlay open --pane`, independent of the session-wide `overlay` flag), `hud` (the message panel occupying the session-wide slot — `{message, detail?, spinner, backgroundColor?, textColor?, sizePercent?, heightPercent?, position, pane?}`, the two percents being the panel's width and height shares — omitted when none is up; the read side of `session hud`. `position` and `spinner` always report the EFFECTIVE value, `center` and a static panel's `none` included, so a caller who omitted them never has to know the defaults; `spinner` names the STYLE, so `none` is what a caller echoes back to turn one off. While a HUD is up the node's `overlay` reads `false` and `overlaySizePercent` is omitted, so a poll for "is a program covering this session" cannot mistake a message for one; HUD state is poll-only, no event announces it), `realized` (whether the session's MAIN pane has a live terminal; `false` means no shell was spawned. `session text` then answers `session not realized` without realizing anything; `session type` brings up a restored main pane still waiting its turn in a launch that replays commands, while any other unrealized cause can still exhaust its poll and fail the same way. `session new` returns `ok` for a model entry, which is weaker — libghostty will not create a surface while the display is asleep, so a session created by a scheduled job overnight stays unrealized until the displays wake and then recovers itself. Poll this after an unattended create), `backedByZmx` (true only when every existing primary/split pane is currently zmx-backed; primary/split entries in `surfaces` report their own Boolean, while scratch and overlays omit it), `liveAttribution` and `splitLiveAttribution` (local Live pane attribution, including hidden splits; [values and omission rules](reference.md#tree)), `remoteHost` (the machine an attached session came from, the read side of `zmx attach`; omitted for a local session, and never present after a relaunch because a remote session is not persisted), `hasSplit` (whether a second pane exists at all, shown or hidden; omitted when there is none — read this rather than `split`, which is false for a split hidden with ⌘D even though its pane is still alive), `splitAxis` (`vertical` for left/right or `horizontal` for top/bottom; omitted without a split), `splitRatio` (the primary-pane divider fraction 0.05-0.95 of the area below the titlebar, of a session that has a split — shown or hidden; omitted when there's no split, or while the split has never been shown — a shown split always reports a value, 0.5 when nothing set one) — the read side of `session resize`, record it to restore the exact divider), `splitFocused` (which pane holds focus in a session that has a split: `true` = split/right/bottom, `false` = primary/left/top; omitted when there's no split; the read side of `session focus`, record it to restore focus), and `surfaces` (`id`, `kind`, `active`, `visible`, and `backedByZmx` on primary/split entries) for `surface zoom` and `surface cursor`. The tree top level carries `zoomedSurface` (the control id of the currently zoomed surface, omitted when nothing is zoomed — the read side of `surface zoom`, so a script can check the zoom state and record-then-restore). It also carries the read side of the `dashboard` command (all omitted when no dashboard is open): `dashboardMembers` (the pane refs the open dashboard shows, in grid order — `<session-id>:left` for a primary pane, `<session-id>:right` for a split pane, so a split session appears as both), `dashboardHighlighted` (the highlighted cell's pane ref — the one Enter jumps into, focusing that exact pane), `dashboardFontSize` (the absolute font size in points applied to the cells, omitted when untouched), and `dashboardFontMode` (`auto`|`fixed`|`untouched`). The top level also carries `pickPending`, the id of the native picker currently awaiting an answer in that window, omitted when no pick is pending. **events**: continuously print control events, subscribing from the current tail when no cursor is given. Use `--json` for one bare event object per line; filter with repeatable or comma-separated `--kind` over `status`, `notify`, `session.created`, `session.closed`, `tree.changed`, `pane.split`, `pane.scratch`, `remote.opened` and `remote.closed`; resume with paired `--run RUN --after SEQ`; and set page size with `--limit 1...1000`. The app retains 4,096 events for one process run. Cursor run changes, expiry, and ahead-of-tail errors are fatal and are never silently rebaselined. There is no terminal-output event stream. **workspace** — `workspace new [name] [--collapsed]` (`--collapsed` creates it closed in the sidebar so you can fill it with `session new --no-select` without it opening, and keeps it out of the focus set; a plain create joins the marked set while the filter is applied, so it is visible) · `workspace rename <name>` · `workspace delete` · `workspace select` · `workspace go --to next|prev` (step the CURRENT workspace one place through the sidebar's visible order, wrapping, and select the first session of the one it lands on — relative, so no `--target`, and unaffected by whether a workspace is collapsed; `workspace move` REORDERS instead) · `workspace move --to up|down|top|bottom` · `workspace focus [on|off|toggle|add]` (mark ONE workspace in the sidebar's focus set — `on` marks it alone and applies the filter, `off` unmarks it, `toggle` (default) replace-toggles, and `add` marks it alongside the others WITHOUT switching the filter on; read membership back from the tree workspace node's `focused` flag) · `workspace filter [on|off|toggle]` (apply or suspend that filter for the whole window WITHOUT losing the marked set — no `--target`; read it back from the tree top-level `workspaceFilter`. Build a working set with
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub