Skip to content

The terminal UI

malac opens a full-screen terminal UI in the spirit of Midnight Commander and byobu. It has a menu bar and your workspace’s tabs at the top, the transcript with an optional sidebar, and a status line and a function-key bar at the bottom. Everything works from the keyboard alone, and everything can also be clicked.

The terminal UI is a client of the daemon: the workspace, its tabs and agents live there. Quitting leaves the agents working, and malac brings you back to the same place, from any folder.

Press F1 (or ? on an empty prompt) at any time for the built-in list of keys, mouse actions and commands.

malac starts the full-screen UI when all of these hold:

  • stdin and stdout are terminals,
  • you did not pass -p, --json or --plain,
  • ui.tui is true (the default),
  • TERM is set and is not dumb.

Otherwise it uses the line-based interface described in Plain mode and scripting. To make the line mode your default:

~/.malac/config.toml
[ui]
tui = false

While the full-screen UI owns the terminal, log output goes to ~/.malac/malac.log instead of stderr (MALAC_LOG still sets the level). If the daemon cannot start, the UI says so and suggests malac --plain or malac -p.

Session Model Mode Agents View Web Help │ 1 api * 2 web ✓ × default
main · review │ Agents
› fix the failing parser tests │ * main
● read src/parser.rs │ * tests
● bash cargo test parser │ bash cargo test
└ test result: FAILED. 3 passed; 1 failed │ Usage
* tests lora/fast 12s › │ in 41.2k · out 2.1k
└ bash cargo test │ Workspace
▌ The parser drops the last token when the input ends │ default
▌ without a newline. Fixed in src/parser.rs:88. │ 2 tabs · daemon 1.0.0
> Ask malac to do something · / for commands · F1 help
* bash cargo test · 14s │ lora/smart │ ask │ ctx 41% │ $0.04 │ 1 agent │ 2 jobs │ 14:32
1Help 2Copy 3Agents 4Model 5Mode 6Tabs 7Resume 8Stop 9Menu 10Quit

A sketch, not a screenshot (* stands for the animated spinner, ▌ for the answer’s green bar): the header, a tab with two agents and the switcher above its transcript, a tool card, a running subagent card, the turn’s answer, the sidebar, the prompt, the status line and the function-key bar.

The menu bar comes first, then the workspace’s tabs, then the workspace’s name on the right (click it to switch workspaces).

Each tab shows its number, its name and a mark: a spinner while it works, ? while it waits for your approval, ✓ when its last turn finished and ✗ when it failed. When more than one tab is open, the active one has a × that closes it. If the tabs do not fit, ‹ and › show that there are more around the active one.

F9, Ctrl+O or Alt+M highlights the menu bar; the underlined letter opens a menu (Session, Model, Mode, Agents, View, Web, Help). ← and → move between menus, ↑ and ↓ between items, Enter or the item’s underlined letter chooses, and Esc, F9 or F10 closes. With the mouse, click a title; once a menu is open, moving over the other titles opens them.

Menu Items
Session New tab here (Ctrl+T), Open folder… (/cd), Open session… (F7), Rename tab…, Close tab (Ctrl+W); New agent in this tab (Ctrl+N), Compact conversation; New workspace…, Switch workspace…, Rename workspace…, Delete workspace…; Quit (F10)
Model All models… (F4), then up to 12 configured models, the current one checked
Mode Ask, Edits, Autopilot (the current one checked), Cycle (F5), for this tab
Agents Agent list…, Agent map… (F3 opens the one used last), New agent in this tab (Ctrl+N), Next agent (Alt+↓), Close this agent, Back to parent (Esc), Stop (F8), then the tab’s agents and subagents
View Sidebar (Ctrl+G), Mouse (Ctrl+S), Thinking; Jobs… (/jobs), Usage and cost, MCP servers, Memories; the control service’s state and Request macOS permissions
Web Show the address, Copy URL, then the address
Help Keys and commands (F1), Check for updates, Install update, Restart the daemon (when idle), Reconnect (Ctrl+R, while disconnected), the versions of this malac and the daemon

Thinking expands or collapses model reasoning everywhere. Close this agent removes an idle agent from the tab; its transcript stays saved.

The View menu’s control line reads, for example, screen granted · accessibility missing, or says that the control service is not connected. Request macOS permissions asks the daemon’s control service to show the system prompts and opens System Settings at what is missing; see Computer and browser control.

Each tab is a project folder with its own agents, configuration and permission mode.

Keys Action
Ctrl+T New tab for the current tab’s folder
Ctrl+W Close the tab; its sessions stay saved. If agents are working there, malac asks before stopping them. The last tab cannot be closed.
Alt+← / Alt+→, Ctrl+PgUp / Ctrl+PgDn Previous or next tab
Ctrl+Shift+PgUp / PgDn Move the tab left or right
Alt+1 … Alt+9 Go to tab 1 to 9
F6 Tab menu: every tab, New tab here, Open folder…, Rename tab…, Close tab
F7 Open a saved session in its folder’s tab; type to filter

Click a tab to switch to it; click its × or middle-click it to close it.

Session → Open folder…, /cd or Tab menu → Open folder… opens a folder browser to start a tab somewhere else. It lists the folders under the current one, recent project folders and your home folder, filtered as you type. Enter or → goes into the highlighted folder, ← or Backspace goes up, ~ jumps home and / to the root. Work in this folder at the top opens the tab there; Ctrl+O or Alt+Enter opens it in the highlighted folder directly. Double-click works like Enter. /cd <path> opens a tab for a path directly, relative to the current tab’s folder or starting with ~.

A tab can hold several top-level agents side by side, for example one fixing a bug while another writes docs. Ctrl+N on an empty prompt (or /clear) starts another agent in the tab. When a tab has more than one, a switcher above the transcript lists them; Alt+↑ and Alt+↓ move between them, or click one.

F3 shows every agent of the workspace, and F3 again switches between the two views:

  • The list: each tab’s agents and subagents with their status, current step and model. Type to filter, Enter opens an agent, Ctrl+X stops it.
  • The map: each agent as a box with its label, model, state, current step, tokens and cost; subagents sit to the right of their parent, joined to it. Arrow keys (or h j k l) move between boxes, Enter opens one, x stops it, the wheel scrolls a large map, Esc closes.

The status line’s agent count opens the map.

The transcript streams the conversation as Markdown, built for reading the answer:

  • Answers stand out. The text that closes a turn, its answer, gets a green bar at its left edge; text the agent writes on the way gets a quiet one. Tool calls sit between them as compact cards.
  • Tool cards show a one-line summary and the first line of the result; expand one to see its full input and output, with edits shown as a diff.
  • Thinking cards hold model reasoning, collapsed.
  • Subagent cards stream their current step; open one to follow its own transcript, with a breadcrumb above it, and press Esc to go back.

Tab moves the focus from the prompt to the transcript:

Keys Action
↑ ↓ (or k j) Select the previous or next entry
[ ] Jump to the previous or next answer
Home End (or g G) First or last entry
Enter or Space Expand a card, or open a subagent
y Copy the entry
b Copy its code block
Tab or Esc Back to the prompt; typing also returns there

PgUp and PgDn scroll at any time. On an empty prompt, Home and End jump to the top and the bottom.

Drag over text in the transcript or the prompt to select it; releasing the button copies it. Double-click selects and copies a word, triple-click a line. Esc clears a selection. F2 or Ctrl+Y copies the last answer.

For the terminal’s own selection instead, Option-drag (iTerm2, Ghostty) or Shift-drag (kitty) bypasses malac, or Ctrl+S turns mouse capture off until you press it again.

Ctrl+G shows or hides the sidebar. It appears by itself on terminals at least 120 columns wide and never below 80. It lists the tab’s agent tree with each agent’s status and current step (click one to open it), the todo list, token usage and cost, the workspace with its tab count and the daemon’s version (click to switch workspaces), and the web UI address (click to copy).

The left side shows the working folder, or while the agent works, what it is doing, for how long, how many prompts are queued, and that F8 stops it. The segments on the right are clickable:

Segment Shows Click
Model The model, as provider/model Model picker
Mode ask, edits or autopilot (highlighted) in this tab Cycle the mode
Context ctx ▰▰▱▱▱ 41%: the share of the model’s context window in use
Tokens and cost Tokens used by the tab’s agents, and the cost when the provider reports it Usage and cost
Agents Running agents (2 agents), or how many subagents there are Agent map
Jobs Running background jobs Jobs view
Approvals ? 2 waiting when permission requests are pending Show them
Web web or web remote Copy the URL
Update update 1.0.1, or restart for 1.0.1 once installed Update dialog
Daemon daemon 0.1.2 running; restart it when idle, when the daemon runs another version than this terminal Restart the daemon
Control control needs permissions or control unavailable Request macOS permissions
Git branch The folder’s branch
Clock The time

On narrow terminals, the less important segments are dropped first. The mode always stays.

Each key is also a button.

Key Label Also Action
F1 Help ? on an empty prompt Keys, mouse actions, commands and how workspaces work
F2 Copy Ctrl+Y Copy the last answer
F3 Agents Agent list or map; F3 again switches
F4 Model Ctrl+P Model picker
F5 Mode Shift+Tab Cycle ask → edits → autopilot for this tab
F6 Tabs Tab menu
F7 Resume Open a saved session
F8 Stop Esc, Ctrl+C while running Stop the turn and its subagents, and drop queued prompts
F9 Menu Ctrl+O, Alt+M Menu bar
F10 Quit Ctrl+D on an empty prompt, Ctrl+C twice Quit this terminal; agents keep working in the daemon
Keys Action
Ctrl+N Start another agent in the tab (on an empty prompt)
Alt+↑ / Alt+↓ Previous or next agent in the tab
Ctrl+R Reconnect to the daemon, starting it if needed
Ctrl+G Show or hide the sidebar
Ctrl+S Turn mouse capture off, to select text with the terminal; again to turn it back on
Ctrl+L Redraw the screen
Esc Clear a selection, close the @ picker, leave a subagent’s view; otherwise stop the running turn
Ctrl+C Stop while running; clear the prompt when it has text; on an empty prompt, press twice to quit
Keys Action
Enter Send, or run the highlighted /command
Shift+Enter, Alt+Enter, Ctrl+J New line. Shift+Enter needs a terminal with the kitty keyboard protocol.
↑ ↓ Move between lines, then through the prompt history
Ctrl+← / →, Alt+B / F Word left or right
Ctrl+A / E, Home / End Start or end of the line
Ctrl+U / K Delete to the start or the end of the line
Alt+Backspace, Ctrl+Backspace Delete the word before the cursor (Alt+D deletes the next one)
@ Attach a file from the tab’s folder
Ctrl+V Attach the image on the clipboard (macOS)
Backspace at the start Remove the last attachment

Typing / lists the matching slash commands: ↑ ↓ choose, Tab completes, Enter runs, Esc hides the list. Two commands exist only here: /cd [folder] opens a folder in a new tab, and /jobs opens the jobs view.

Pasted text, newlines included, goes into the prompt as is. Prompts you send while the agent works are queued and sent in order. The prompt history is shared with the line mode, in ~/.malac/history.txt.

Files and images ride along with a prompt as chips above it:

  • @ file picker. Type @ and part of a name: a fuzzy list of the tab folder’s files appears, honoring .gitignore. ↑ ↓ choose, Enter or Tab attaches, Esc closes.
  • Dropped files. Drop a file on the terminal window: terminals paste its path, and malac turns it into an attachment.
  • Clipboard images. Ctrl+V attaches the image on the clipboard, on macOS.

The daemon reads the files when you send the prompt: text files go in as a fenced block (up to 256 KB), images as images (up to 10 MB), folders as a listing. The transcript shows the paths you attached, not their contents.

F4, Ctrl+P, a click on the model in the status line or /model opens a list of every model from every provider. malac asks each provider for its models in the background; configured models are marked, and providers that cannot be reached show their error. Type to filter, then press Enter: the agent switches to that model from the next message.

When a tool call needs approval, a dialog shows which agent wants to run which tool, a one-line summary (the command, the path or the URL) and the call’s input. The same request appears in every client connected to the daemon, and the dialog closes everywhere once one of them answers.

Keys Action
y Allow this call
a Always: allow this program, or this tool, for the rest of the session
n, Esc, Ctrl+C Deny
← → Tab, then Enter Move between the buttons and press one
d Show the call’s full input
h Hide the dialog; the status line keeps ? 1 waiting, and a click there brings it back

Several requests queue up as “Permission 1 of 3”. For a moment after a dialog appears, keys are ignored, so a keystroke meant for the prompt cannot answer it by accident. See Permissions and autopilot for what “always” remembers.

A new tab opens on a welcome screen with a pixel-art pig (a smaller line-art pig on short terminals). It shows the version, the workspace, the model (click to pick another), the mode (click to cycle), the folder, the web UI address (click to copy), a note when an update is available, a few tips, and the recent sessions in this folder (click one to resume it).

Mouse capture is on by default. You can click:

  • the menu titles and items, the tabs (× or a middle click closes one) and the workspace name,
  • every status line segment and every function key,
  • tool and thinking cards, to expand them, and subagent cards, to open them,
  • the agent switcher, the breadcrumb above a subagent’s transcript, and agents in the sidebar,
  • boxes in the agent map, rows in the pickers and the jobs view, and the buttons in dialogs,
  • the recent sessions on the welcome screen.

Drag selects and copies text, double and triple clicks select a word and a line. A right click on a transcript entry opens a menu with Copy selection (when there is one), Copy, Copy code block, Expand (or Collapse), and for subagents Open and Stop. The wheel scrolls the transcript, the open list or the agent map, and menu items highlight as you move over them.

Copy actions go through OSC 52, the terminal escape sequence for the system clipboard, which Ghostty, Kitty, WezTerm and tmux support. Inside tmux, malac also sends the sequence through tmux to the outer terminal when tmux allows passthrough. On a local Mac (not over SSH), it also copies with pbcopy, which covers Terminal.app and iTerm2 with their default settings.

  • Colors. malac uses 24-bit color when COLORTERM is truecolor or 24bit, and the 256-color palette otherwise. NO_COLOR turns colors off.

  • tmux and byobu. Clicks reach malac only with set -g mouse on, and copying through tmux needs set -g set-clipboard on:

    ~/.tmux.conf
    set -g mouse on
    set -g set-clipboard on
  • Alt on macOS. The Alt shortcuts need the Option key to send Meta: in Terminal.app, Settings → Profiles → Keyboard → Use Option as Meta key; in iTerm2, set the Option key to Esc+ under Profiles → Keys.

  • Function keys on Mac keyboards may need Fn, unless the keyboard settings use F1, F2 and so on as standard function keys. Every function key also has a keyboard alternative and a button.

  • Shift+Enter is only distinguishable in terminals that support the kitty keyboard protocol; Alt+Enter and Ctrl+J work everywhere.

  • Size. The UI needs at least 20 columns by 8 rows.

--plain, ui.tui = false, or a TERM that is dumb or unset gives the line-based interface: streamed output, a › prompt with the same history, and permission prompts you answer with a single key. It is a daemon client too. See Plain mode and scripting.

malac is created by lobirus and released under the MIT license. About malac