From e9d37cefcc950a62d9534aa24db643fa46333d9d Mon Sep 17 00:00:00 2001
From: Umputun
+ agterm reads a user-editable, kitty-flavored keymap file at
+ ~/.config/agterm/keymap.conf. It rebinds built-in menu shortcuts and defines custom shell commands bound to keys (and listed in the action
+ palette). The file is optional — a commented starter is written on first launch, and the directory can be changed in
+ Settings ▸ Key Mapping. Three verbs; blank lines and
+ # comments are ignored.
+
- Looking for the full list? Every command, with its arguments, return values, and errors, lives on the
- Command reference →
-
- agterm can be driven from a script over a local unix-domain socket through the companion CLI,
- agtermctl. This is for
- fire-and-forget scripting that manages workspaces and sessions, injects text, invokes control actions, and polls a
- control-event feed for status and lifecycle changes. There is no terminal-output streaming.
+
+ A chord is modifier words (ctrl, cmd,
+ opt,
+ shift) joined by
+ + and a base key (a single
+ character or tab/space/return/delete/left/right/up/down). A Shift-typed symbol is written
+ shift+<base>
+ (e.g. shift+/ for
+ ?,
+ shift+= for
+ +) — the base key, not the
+ shifted symbol. Custom commands may also use a leader sequence
+ (ctrl+a>g), and their chord
+ must include a modifier — a bare key can't shadow a plain terminal key.
- To open a terminal at a directory without the CLI,
- open -a agterm <path> — or
- right-click a folder in Finder and choose Open With ▸ agterm. agterm adds a
- session in that directory to the last-active window. This works when agterm is already running (its usual state); if it
- isn't, launch agterm first, then run the command. The socket equivalent, and the way to place the session precisely, is
- agtermctl session new --cwd <path>.
+
+ global-hotkey takes exactly one
+ chord and binds it system-wide: it summons the quick terminal while any
+ application is frontmost, which no other binding here can do — the rest only fire while agterm has the keyboard. It
+ must carry a modifier, takes no alternatives and no leader sequence, and a second
+ global-hotkey line replaces the
+ first. macOS registers it by physical key position, so it keeps firing on a non-Latin layout. Because the system owns
+ it rather than agterm, it takes no part in the collision rules below. Note which side wins: the system-wide chord
+ takes the key even while agterm is in front, so binding one a menu item already uses means that menu shortcut stops
+ firing. It is unset unless you add the line: agterm ships no default because registering a chord takes it
+ from every other application on the Mac, and that is not a cost to impose on someone who may never summon
+ the panel from outside agterm. Spending it on the chord the in-app binding already uses is allowed and is
+ the way to get one shortcut that works everywhere —
+ global-hotkey ctrl+`
+ makes ⌃` summon the panel
+ from any application, at the price of that chord no longer reaching anything else.
- Each command targets a session or workspace by its UUID, a unique prefix of that UUID (git-style), or the keyword
- active (the selected session /
- current workspace). --target
- defaults to active, so the
- current one rarely needs naming. --target/--workspace take an id, a
- prefix, or active — never a
- name. For workspaces,
- active is the one a new session
- lands in: a workspace you just created in the foreground, otherwise the selected session's, otherwise the last one.
- A newly created workspace stays the target until the selection changes — to a different session or to none —
- or until you delete it or hide it behind the workspace filter.
- workspace select moves the
- target to the workspace you name, an empty one included. So New Session (and
- session new) right after
- creating one lands in the new workspace rather than the one you came from. Mutating commands normally print the
- affected id; batch
- session close and
- session move accept repeated
- --target options and print the
- number of sessions actually changed. Add
- --json for the raw response,
- or --socket PATH to override
- the socket. The exit code is zero on success, non-zero on error.
+
+ One binding can offer several alternatives, joined by
+ | inside a single token with no
+ spaces around it —
+ map cmd+t|ctrl+a>t toggle_scratch
+ fires the action from either, and a command
+ takes alternatives the same way. For a built-in, the first single-chord alternative the menu can carry becomes the menu
+ shortcut; every
+ other alternative, on either verb, is delivered by a key monitor and so must carry a modifier on its first chord. This
+ is also how a built-in gets a leader sequence, because a menu item holds exactly one key equivalent:
+ map ctrl+a>s toggle_split binds
+ the sequence and leaves the action with no menu shortcut at all — its shipped ⌘D is gone rather than kept, and free for
+ another action to claim. A typo in one alternative rejects the whole line, so a mistake can't hide behind a line that
+ half worked; an alternative that merely breaks a rule or collides with an existing binding drops on its own and its
+ siblings keep firing. If a line ends up binding nothing at all, the action simply keeps the shortcut it shipped with.
+
+ Chords are written in Latin and keep working on a non-Latin keyboard layout. A layout that cannot type ASCII —
+ Russian, Greek, Hebrew, Arabic, Thai — resolves every chord by the physical key position, so
+ cmd+o still fires on the key
+ marked O even though it types щ.
+ A layout that can type ASCII binds what it types, so an alternative Latin layout keeps its own letter positions: on
+ Dvorak, cmd+o follows the O you
+ actually type.
- agtermctl pick reads nonblank
- lines or a JSON array of
- {id,label,subtitle?} objects
- from stdin and opens agterm's fuzzy picker. It blocks by default and prints the picked, custom, or cancelled result as
- bare JSON. Add --no-block to
- get the picker id immediately, then use
- pick result or
- pick cancel. The target tree's
- top-level pickPending field
- carries that id while the picker waits.
-
- Typing matches item labels only; a subtitle is shown but never searched, so consequence text on one row cannot filter
- out its safer neighbour. An empty query lists the items in the order they were supplied, so the caller's first item is
- the one Return runs on open.
- --query TEXT prefills the field
- and filters immediately, which ranks by match score and therefore does not preserve that order. With
- --allow-custom the item list may
- be empty, which turns the picker into a plain text prompt: the custom row appears as soon as the query is nonblank,
- whether prefilled by --query or
- typed. An itemless call still reads stdin, so redirect it
- (< /dev/null) or it blocks.
-
+ toggle_fullscreen is the one
+ action with no menu item of its own. macOS adds an "Enter Full Screen" item to the View menu whenever that menu is
+ drawn, and nothing suppresses it, so an item of agterm's own would sit beside it as a duplicate. The binding (⌃⌘F by
+ default) is handled directly instead, which is why the menu entry advertises the system's Globe+F rather than your
+ chord. Both work, and rebinding
+ toggle_fullscreen changes the
+ chord as usual — it just won't show up next to that menu item.
+
- agtermctl reference
+ Custom commands & keys
+
map
+ cmd+shift+l toggle_split
map
+ ctrl+shift+k command_palette
# or to several alternatives, joined by | with no spaces around it
map
+ cmd+t|ctrl+a>t toggle_scratch
# define custom commands ("name" shows in the palette; chord optional)
command
+ "Open in Zed" cmd+shift+e open -a Zed {AGT_SESSION_PWD}
command
+ "Lazygit" ctrl+a>g agtermctl session overlay open 'zsh -lc lazygit'
+ --socket {AGT_SOCKET}
command
+ "Deploy" ./deploy.sh
# one system-wide chord that summons the quick terminal from any application
global-hotkey ctrl+opt+space
- Native picker
+ Bindable built-in actions
-
- agtermctl pick --allow-custom --query "$name" --prompt
- "Rename to" < /dev/null
- id=$(printf '%s\n' alpha beta |
- agtermctl pick --no-block | jq -r '.id')
- agtermctl pick result "$id"
- agtermctl pick cancel "$id"
- agtermctl tree --json | jq -r
- '.result.tree.pickPending // empty'
+ new_window rename_window delete_window
new_workspace rename_workspace delete_workspace
new_session open_directory rename_session duplicate_session
close_session reopen_recent undo_close clear_status
increase_font_size decrease_font_size reset_font_size
toggle_split toggle_horizontal_split toggle_scratch toggle_search
toggle_sidebar toggle_flag toggle_flagged_view
focus_left_pane focus_right_pane focus_workspace toggle_workspace_filter
toggle_workspace_collapse
previous_session next_session first_session last_session
previous_workspace next_workspace
previous_attention_session next_attention_session
quick_terminal session_palette command_palette
custom_command_palette show_attention
select_theme toggle_fullscreen toggle_terminal_zoom
dashboard
- Sessions & workspaces
+ Command tokens
agtermctl tree
# create a workspace, capture its id, open a session in it
ws=$(agtermctl workspace new work)
agtermctl session new --workspace
- "$ws" --cwd ~/src/agterm
# run a command as the session's process (argv-style; wrap in sh -c for shell syntax)
agtermctl session new --command "ssh user@host"
agtermctl session new --command
- "zsh -lc 'make test'" --wait
- # hold open after the command exits (press any key to close); needs --command
agtermctl session new
- --name myhost --workspace-name
- servers --create-workspace
# step / reorder / relocate
agtermctl session go --to next
- # next|prev|first|last
agtermctl session move --to up
- # reorder: up|down|top|bottom
agtermctl session move
- "$ws" # relocate to a workspace
agtermctl session new --after active
- # create right after the current session (--before to precede)
agtermctl session new --cwd ~/src/agterm --no-select
- # create in the background without switching to it
agtermctl session duplicate --target 9f3c
- # a fresh shell in that session's workspace and cwd, right after it
agtermctl session move --after
- 9f3c # place after an anchor (its workspace is used; relocates cross-workspace)
agtermctl session move "$ws" --target 9f3c --target abcd
- # move a batch as one ordered block
agtermctl session close --target 9f3c --target abcd
- # one grace-period undo for the batch
agtermctl workspace go --to next
- # step to the next workspace and select its first session
agtermctl workspace move --to top
- # reorder a workspace
agtermctl workspace new work --collapsed
- # create a workspace closed in the sidebar (fill with session new --no-select)
agtermctl workspace collapse --target 9f3c
- # collapse one workspace; workspace expand re-opens it
agtermctl workspace focus on
- # mark this workspace alone and apply the filter (on|off|toggle|add)
-
agtermctl workspace focus add --target a1b2
- # mark another one without narrowing the tree yet
agtermctl workspace filter on
- # apply the marked set; filter off suspends it without losing the set
-
agtermctl session reveal --target 9f3c
- # reveal the focused pane's cwd in Finder
+ {AGT_SESSION_ID} {AGT_SESSION_NAME} {AGT_SESSION_PWD}
{AGT_WORKSPACE_ID} {AGT_WORKSPACE_NAME}
{AGT_WINDOW_ID} {AGT_WINDOW_NAME}
{AGT_PANE} {AGT_SELECTION} {AGT_SOCKET}
+ Tokens expand at fire time (also exported as
+ $AGT_* env vars on the spawned
+ process). A token is substituted raw into the shell line, so for content you
+ don't control —
+ {AGT_SELECTION}, and also
+ {AGT_SESSION_NAME}/{AGT_SESSION_PWD}
+ (a remote host can set these via OSC) — prefer the matching quoted env var, e.g.
+ "$AGT_SELECTION".
+
+ Open the file with File ▸ Edit Keymap… (or the ⌃⇧P palette): it opens in a + 95% overlay running $VISUAL/$EDITOR + (falling back to vi) and + reloads on quit. Apply edits made elsewhere with + File ▸ Reload Keymap or + agtermctl keymap reload. A + malformed line never discards the rest — it surfaces in the diagnostics list in Settings ▸ Key Mapping while the good + lines still apply. +
++ To check what is actually bound, + agtermctl keymap list prints every + built-in with the binds it resolved to (the menu shortcut first, then any alternatives, joined with + |), the custom commands, + each diagnostic in full, and the key equivalents the menu + bar is really carrying. If a binding will not fire, compare the last two: an action whose chord no menu item holds is + usually a menu problem, not a keymap one. Only the menu shortcut can appear there — an alternative never does, and + neither do + undo_close (⌘Z) and + toggle_fullscreen (⌃⌘F), which a + key monitor delivers rather than a menu item. +
- --wait keeps a "press any key - to close" prompt so you can read the final output; - --block reports only the exit - status (the overlay never captures stdout — a TUI writes its own result file). By default an overlay opens on its - target without switching the active session (full and --size-percent - floating alike); - --follow switches the user to - the target. - session overlay resize changes an - open overlay in place — - --size-percent makes it floating, - --full switches it back — without - restarting the program. A - (overlay) tag in - agtermctl tree marks a session - whose overlay is open. +
+ Looking for the full list? Every command, with its arguments, return values, and errors, lives on the + Command reference → +
+ ++ agterm can be driven from a script over a local unix-domain socket through the companion CLI, + agtermctl. This is for + fire-and-forget scripting that manages workspaces and sessions, injects text, invokes control actions, and polls a + control-event feed for status and lifecycle changes. There is no terminal-output streaming.
-- session overlay copy returns the - selection made inside the overlay and - session overlay text its terminal - buffer. These exist because - session copy and - session text address the pane the - overlay covers: text you highlight in an overlay reads there as - no selection, and - session text --pane right hands - back the shell underneath. Reach for them when the read is not chord-driven: an agent polling from outside, or a - script wanting the selection some time after the fact. A chord already receives the selection of the surface it - fired in, the overlay included, as - $AGT_SELECTION, so a custom - command should use that rather than a later socket read. The buffer one returns a TUI's screen as drawn, wrapped - where it wrapped — for a program's real output, still read the file it writes. +
+ To open a terminal at a directory without the CLI, + open -a agterm <path> — or + right-click a folder in Finder and choose Open With ▸ agterm. agterm adds a + session in that directory to the last-active window. This works when agterm is already running (its usual state); if it + isn't, launch agterm first, then run the command. The socket equivalent, and the way to place the session precisely, is + agtermctl session new --cwd <path>.
-- --pane left|right scopes the - overlay to one split pane instead of the whole session: it covers exactly that pane and leaves the sibling pane - visible and interactive, so an agent working in the split can show a diff or a TUI over its own pane without - blanking the one you are reading. The two panes are independent and may both hold an overlay at once, each with its - own background color. A pane overlay is always full-pane — there is no floating variant, so - --pane cannot combine with - --size-percent and - session overlay resize takes no - --pane — and everything else - matches the session-wide overlay. A non-split session accepts - --pane left, since its shell - reports AGTERM_PANE=left, so a - script can pass --pane "$AGTERM_PANE" - without checking whether the session is split. A pane that is not on screen is refused with - pane not visible; hiding the - split after opening is fine, the program keeps running and reappears when the split comes back. - close, - result, - copy and - text take the same - --pane, ⌘W dismisses the - focused pane's overlay before it would close the session (one on the other pane is not in front of you, so ⌘W keeps - its ordinary meaning), and - agtermctl tree --json reports the - covered panes as paneOverlays. +
+ Each command targets a session or workspace by its UUID, a unique prefix of that UUID (git-style), or the keyword + active (the selected session / + current workspace). --target + defaults to active, so the + current one rarely needs naming. --target/--workspace take an id, a + prefix, or active — never a + name. For workspaces, + active is the one a new session + lands in: a workspace you just created in the foreground, otherwise the selected session's, otherwise the last one. + A newly created workspace stays the target until the selection changes — to a different session or to none — + or until you delete it or hide it behind the workspace filter. + workspace select moves the + target to the workspace you name, an empty one included. So New Session (and + session new) right after + creating one lands in the new workspace rather than the one you came from. Mutating commands normally print the + affected id; batch + session close and + session move accept repeated + --target options and print the + number of sessions actually changed. Add + --json for the raw response, + or --socket PATH to override + the socket. The exit code is zero on success, non-zero on error.
+ agtermctl pick reads nonblank + lines or a JSON array of + {id,label,subtitle?} objects + from stdin and opens agterm's fuzzy picker. It blocks by default and prints the picked, custom, or cancelled result as + bare JSON. Add --no-block to + get the picker id immediately, then use + pick result or + pick cancel. The target tree's + top-level pickPending field + carries that id while the picker waits. +
++ Typing matches item labels only; a subtitle is shown but never searched, so consequence text on one row cannot filter + out its safer neighbour. An empty query lists the items in the order they were supplied, so the caller's first item is + the one Return runs on open. + --query TEXT prefills the field + and filters immediately, which ranks by match score and therefore does not preserve that order. With + --allow-custom the item list may + be empty, which turns the picker into a plain text prompt: the custom row appears as soon as the query is nonblank, + whether prefilled by --query or + typed. An itemless call still reads stdin, so redirect it + (< /dev/null) or it blocks. +
- A HUD carries a message rather than a program, and it is passive: the session keeps first responder and stays - typable under the panel, the terminal behind it is neither dimmed nor click-blocked, and nothing waits for an - answer. It is for the seconds a script or an agent needs before it can show anything, so the session says what is - happening rather than sitting silent. - open is the default - subcommand, so session hud "…" - posts one. - --position - anchors it to any of the nine positions - session background takes — - top-left, - top-center, - top-right, - center-left, - center, - center-right, - bottom-left, - bottom-center, - bottom-right — defaulting to - center, with every anchor off - center holding a margin off that pane edge on its own; a corner is what keeps a panel out of the text you are - reading. The bare - top and - bottom this took before are - still accepted for the middle column. The panel comes from the message on both axes — width from the longest line, height - from the number of them, so a title and a subtitle give a wide, short panel rather than a square one. - --size-percent overrides the - width only, bounded to at most 80% of the pane, so a message never covers the session it is about. - --text-color sets the text's - own color and - --background-color the panel's - backing, so the two halves are independent. - An update replaces the whole message, so - --detail, - --spinner and - --text-color have to be repeated - to survive it. The spinner takes a style — - --spinner-style bar|braille|circle|blocks|dot|none, - which turns it on by itself, with - dot blinking rather than - animating — and an update may switch style in place; - --background-color is the - exception, read once when the panel is created and kept — in the panel and in the read-back — across every - update, which is why an update does not take it at all. -
-- It shares the overlay slot, so a second - hud replaces the first, - session overlay open replaces a - HUD, and ⌘W or - session overlay close takes one - down; a HUD over a running program is refused instead, because a message is replaceable and a program is - not. - session overlay result over a - HUD errors, and - session overlay resize accepts a - percent but refuses --full, - which would cover the session the message is about. - agtermctl tree --json reports - the panel as the session node's - hud object, with - overlay reading false beside it; - there is no event, so a script that needs the state polls the tree. -
- The cookbook collects - complete agtermctl - workflows, each in its own directory with a README and, where it needs one, its scripts: switching the sidebar to a - single project, closing a project's workspaces and bringing them back later, picking a path with - fzf and typing it into the - shell, and giving each tab its own Claude Code or Codex conversation across a restart. They are written to be copied - into your own setup and edited, not only read; - cookbook/CONTRIBUTING.md - has the rules for adding one. -
-- Recipes come from other people as well as the maintainer. Every one is reviewed before it is accepted, but they are - shell scripts you run on your own machine against your own sessions, and several close sessions or delete - workspaces, so read a recipe before you run it. -
- - - -- agterm reads a user-editable, kitty-flavored keymap file at - ~/.config/agterm/keymap.conf. It rebinds built-in menu shortcuts and defines custom shell commands bound to keys (and listed in the action - palette). The file is optional — a commented starter is written on first launch, and the directory can be changed in - Settings ▸ Key Mapping. Three verbs; blank lines and - # comments are ignored. -
+ Overlays +- A chord is modifier words (ctrl, cmd, - opt, - shift) joined by - + and a base key (a single - character or tab/space/return/delete/left/right/up/down). A Shift-typed symbol is written - shift+<base> - (e.g. shift+/ for - ?, - shift+= for - +) — the base key, not the - shifted symbol. Custom commands may also use a leader sequence - (ctrl+a>g), and their chord - must include a modifier — a bare key can't shadow a plain terminal key. + --wait keeps a "press any key + to close" prompt so you can read the final output; + --block reports only the exit + status (the overlay never captures stdout — a TUI writes its own result file). By default an overlay opens on its + target without switching the active session (full and --size-percent + floating alike); + --follow switches the user to + the target. + session overlay resize changes an + open overlay in place — + --size-percent makes it floating, + --full switches it back — without + restarting the program. A + (overlay) tag in + agtermctl tree marks a session + whose overlay is open.
- global-hotkey takes exactly one - chord and binds it system-wide: it summons the quick terminal while any - application is frontmost, which no other binding here can do — the rest only fire while agterm has the keyboard. It - must carry a modifier, takes no alternatives and no leader sequence, and a second - global-hotkey line replaces the - first. macOS registers it by physical key position, so it keeps firing on a non-Latin layout. Because the system owns - it rather than agterm, it takes no part in the collision rules below. Note which side wins: the system-wide chord - takes the key even while agterm is in front, so binding one a menu item already uses means that menu shortcut stops - firing. It is unset unless you add the line: agterm ships no default because registering a chord takes it - from every other application on the Mac, and that is not a cost to impose on someone who may never summon - the panel from outside agterm. Spending it on the chord the in-app binding already uses is allowed and is - the way to get one shortcut that works everywhere — - global-hotkey ctrl+` - makes ⌃` summon the panel - from any application, at the price of that chord no longer reaching anything else. + session overlay copy returns the + selection made inside the overlay and + session overlay text its terminal + buffer. These exist because + session copy and + session text address the pane the + overlay covers: text you highlight in an overlay reads there as + no selection, and + session text --pane right hands + back the shell underneath. Reach for them when the read is not chord-driven: an agent polling from outside, or a + script wanting the selection some time after the fact. A chord already receives the selection of the surface it + fired in, the overlay included, as + $AGT_SELECTION, so a custom + command should use that rather than a later socket read. The buffer one returns a TUI's screen as drawn, wrapped + where it wrapped — for a program's real output, still read the file it writes.
- One binding can offer several alternatives, joined by - | inside a single token with no - spaces around it — - map cmd+t|ctrl+a>t toggle_scratch - fires the action from either, and a command - takes alternatives the same way. For a built-in, the first single-chord alternative the menu can carry becomes the menu - shortcut; every - other alternative, on either verb, is delivered by a key monitor and so must carry a modifier on its first chord. This - is also how a built-in gets a leader sequence, because a menu item holds exactly one key equivalent: - map ctrl+a>s toggle_split binds - the sequence and leaves the action with no menu shortcut at all — its shipped ⌘D is gone rather than kept, and free for - another action to claim. A typo in one alternative rejects the whole line, so a mistake can't hide behind a line that - half worked; an alternative that merely breaks a rule or collides with an existing binding drops on its own and its - siblings keep firing. If a line ends up binding nothing at all, the action simply keeps the shortcut it shipped with. + --pane left|right scopes the + overlay to one split pane instead of the whole session: it covers exactly that pane and leaves the sibling pane + visible and interactive, so an agent working in the split can show a diff or a TUI over its own pane without + blanking the one you are reading. The two panes are independent and may both hold an overlay at once, each with its + own background color. A pane overlay is always full-pane — there is no floating variant, so + --pane cannot combine with + --size-percent and + session overlay resize takes no + --pane — and everything else + matches the session-wide overlay. A non-split session accepts + --pane left, since its shell + reports AGTERM_PANE=left, so a + script can pass --pane "$AGTERM_PANE" + without checking whether the session is split. A pane that is not on screen is refused with + pane not visible; hiding the + split after opening is fine, the program keeps running and reappears when the split comes back. + close, + result, + copy and + text take the same + --pane, ⌘W dismisses the + focused pane's overlay before it would close the session (one on the other pane is not in front of you, so ⌘W keeps + its ordinary meaning), and + agtermctl tree --json reports the + covered panes as paneOverlays. +
+ ++ A HUD carries a message rather than a program, and it is passive: the session keeps first responder and stays + typable under the panel, the terminal behind it is neither dimmed nor click-blocked, and nothing waits for an + answer. It is for the seconds a script or an agent needs before it can show anything, so the session says what is + happening rather than sitting silent. + open is the default + subcommand, so session hud "…" + posts one. + --position + anchors it to any of the nine positions + session background takes — + top-left, + top-center, + top-right, + center-left, + center, + center-right, + bottom-left, + bottom-center, + bottom-right — defaulting to + center, with every anchor off + center holding a margin off that pane edge on its own; a corner is what keeps a panel out of the text you are + reading. The bare + top and + bottom this took before are + still accepted for the middle column. The panel comes from the message on both axes — width from the longest line, height + from the number of them, so a title and a subtitle give a wide, short panel rather than a square one. + --size-percent overrides the + width only, bounded to at most 80% of the pane, so a message never covers the session it is about. + --text-color sets the text's + own color and + --background-color the panel's + backing, so the two halves are independent. + An update replaces the whole message, so + --detail, + --spinner and + --text-color have to be repeated + to survive it. The spinner takes a style — + --spinner-style bar|braille|circle|blocks|dot|none, + which turns it on by itself, with + dot blinking rather than + animating — and an update may switch style in place; + --background-color is the + exception, read once when the panel is created and kept — in the panel and in the read-back — across every + update, which is why an update does not take it at all.
- Chords are written in Latin and keep working on a non-Latin keyboard layout. A layout that cannot type ASCII — - Russian, Greek, Hebrew, Arabic, Thai — resolves every chord by the physical key position, so - cmd+o still fires on the key - marked O even though it types щ. - A layout that can type ASCII binds what it types, so an alternative Latin layout keeps its own letter positions: on - Dvorak, cmd+o follows the O you - actually type. + It shares the overlay slot, so a second + hud replaces the first, + session overlay open replaces a + HUD, and ⌘W or + session overlay close takes one + down; a HUD over a running program is refused instead, because a message is replaceable and a program is + not. + session overlay result over a + HUD errors, and + session overlay resize accepts a + percent but refuses --full, + which would cover the session the message is about. + agtermctl tree --json reports + the panel as the session node's + hud object, with + overlay reading false beside it; + there is no event, so a script that needs the state polls the tree.
- toggle_fullscreen is the one - action with no menu item of its own. macOS adds an "Enter Full Screen" item to the View menu whenever that menu is - drawn, and nothing suppresses it, so an item of agterm's own would sit beside it as a duplicate. The binding (⌃⌘F by - default) is handled directly instead, which is why the menu entry advertises the system's Globe+F rather than your - chord. Both work, and rebinding - toggle_fullscreen changes the - chord as usual — it just won't show up next to that menu item. -
- Tokens expand at fire time (also exported as - $AGT_* env vars on the spawned - process). A token is substituted raw into the shell line, so for content you - don't control — - {AGT_SELECTION}, and also - {AGT_SESSION_NAME}/{AGT_SESSION_PWD} - (a remote host can set these via OSC) — prefer the matching quoted env var, e.g. - "$AGT_SELECTION". -
-- Open the file with File ▸ Edit Keymap… (or the ⌃⇧P palette): it opens in a - 95% overlay running $VISUAL/$EDITOR + The cookbook collects + complete agtermctl + workflows, each in its own directory with a README and, where it needs one, its scripts: switching the sidebar to a + single project, closing a project's workspaces and bringing them back later, picking a path with + fzf and typing it into the + shell, and giving each tab its own Claude Code or Codex conversation across a restart. They are written to be copied + into your own setup and edited, not only read; + cookbook/CONTRIBUTING.md - (falling back to vi) and - reloads on quit. Apply edits made elsewhere with - File ▸ Reload Keymap or - agtermctl keymap reload. A - malformed line never discards the rest — it surfaces in the diagnostics list in Settings ▸ Key Mapping while the good - lines still apply. + has the rules for adding one.
-- To check what is actually bound, - agtermctl keymap list prints every - built-in with the binds it resolved to (the menu shortcut first, then any alternatives, joined with - |), the custom commands, - each diagnostic in full, and the key equivalents the menu - bar is really carrying. If a binding will not fire, compare the last two: an action whose chord no menu item holds is - usually a menu problem, not a keymap one. Only the menu shortcut can appear there — an alternative never does, and - neither do - undo_close (⌘Z) and - toggle_fullscreen (⌃⌘F), which a - key monitor delivers rather than a menu item. +
+ Recipes come from other people as well as the maintainer. Every one is reviewed before it is accepted, but they are + shell scripts you run on your own machine against your own sessions, and several close sessions or delete + workspaces, so read a recipe before you run it.
-+ agterm ships a small set of features on purpose. A great many of the tools you might wish it shipped are one line + in keymap.conf, and the line + stays short because three pieces do the work: a + command turns any shell line + into a named action on a key chord, an overlay gives an interactive program its own temporary terminal over the + session, and any CLI you already have fills that slot. agterm never needs to know what the program is. +
++ So “does agterm have a file browser?” has no yes-or-no answer. You bind the file browser you like, in + one line. The four steps below each add one building block; put the lines in + keymap.conf via + File ▸ Edit Keymap… and apply them with + File ▸ Reload Keymap. +
+ ++ Read the line left to right: + command is the directive, the + quoted text is the name shown in the + Navigate ▸ Custom Commands palette, + ctrl+a>o is the chord that + fires it — Ctrl-A, then O — and everything after that is an ordinary shell line. The chord is + optional: leave it out and the action exists in the palette only. +
++ The building block is session context. Every custom command is handed the + session it fired from — its directory, name, id, and current selection — as + $AGT_* environment variables + and as {AGT_*} tokens + substituted into the line. That is what makes one binding work in every session instead of hard-coding a path. +
+ ++ The building block is the overlay. A custom command on its own runs detached + with no terminal, which suits launching a GUI app but kills a TUI at once, since it has nothing to draw on. An + overlay is a real terminal, so yazi, + lazygit, + htop and the rest behave + normally in it. It opens in the session's own working directory, and it disappears when the program exits, leaving + the shell underneath untouched. +
++ agtermctl is how the line asks + for that terminal: it is agterm's own command-line tool, and opening an overlay is one thing it can do. Step 3 + opens up the rest. +
++ --target "$AGT_SESSION_ID" is + worth understanding rather than copying. + agtermctl does not act on + agterm directly; it sends a request over a socket, and agterm resolves it on arrival. Without a target the request + means “whichever session is selected when this lands”, which is normally the one you pressed the chord + in — but not if you switched in between. The token pins it to the session that fired, so the overlay always + opens where you asked for it. +
+ ++ The building block is the control API. Overlays are one entry in a much + larger catalog: the same + agtermctl creates and renames + sessions, splits panes, moves windows, opens the native picker, reads a session's text back, and posts + notifications. Every state it sets it also reads back, which is what lets a script build a whole layout rather than + fire a single action. +
++ The extra flags are the same idea as + --target above, applied to + every axis this command can drift on. A bare + session new lands in + whichever window is frontmost and whichever workspace is current when the request arrives, and it selects the new + session; the ids pin all three to where the chord was pressed, and + --no-select leaves you where + you were. Keymap lines never wrap, so this one is long: one directive is always one line. +
++ Past a certain size the line becomes a script, and that is where the + cookbook starts: pick a + project from anywhere and open it in its own workspace, park a set of workspaces and bring them back later, or have + each tab resume its own agent conversation after a restart. Those are not one-liners, and the recipes do not + pretend otherwise. +
+ ++ Install the agent skill from Help ▸ Install Agent Skill…, then + ask the agent running in one of your sessions: +
++ The skill carries the keymap syntax, the full command catalog, the context tokens, and the PATH rule, so the agent + writes a working line instead of guessing at one. This step comes last on purpose: an agent without the skill will + still answer, plausibly and wrongly, and by now you can tell the difference. +
+ ++ From here, Custom commands & keys has the full keymap syntax and + the bindable actions, the command reference lists every + agtermctl command with its + arguments, and the cookbook + collects worked recipes to copy and edit. +
+
So “does agterm have a file browser?” has no yes-or-no answer. You bind the file browser you like, in - one line. The four steps below each add one building block; put the lines in - keymap.conf via - File ▸ Edit Keymap… and apply them with + one line. The four steps below each add one building block. +
++ To edit the file yourself, open it with + File ▸ Edit Keymap… and apply your changes with File ▸ Reload Keymap.
@@ -751,19 +772,22 @@- Install the agent skill from Help ▸ Install Agent Skill…, then - ask the agent running in one of your sessions: + This is the normal way to add things, not a shortcut for people who dislike config files. Install the agent skill + from Help ▸ Install Agent Skill…, then ask the agent running + in one of your sessions: