~/vimma $ less docs/agent-workspace.md

page 2/5 · docs/agent-workspace

The agent workspace

Local AI agents, such as Claude Code, Codex, opencode or GitHub Copilot, can use Vimma through vimma-ctl mcp, an MCP server. They reach one workspace only, agent, with its own cookies and logins, and every request asks you first.

off until you turn it on

Agents cannot reach Vimma until you type :mcp on and answer y. They never see your other workspaces, the private workspace or your logins there, and :mcp off disconnects them at once.

Connect an agent

  1. Build vimma-ctl and put it on your PATH (vimma-ctl, step 2).
  2. In Vimma, type :mcp on and press y.
  3. Add the server to your agent's tool. For Claude Code: claude mcp add --transport stdio --scope user vimma -- vimma-ctl mcp; for Codex: codex mcp add vimma -- vimma-ctl mcp. Other tools take the same command, vimma-ctl mcp, in their MCP settings.
  4. Ask the agent to open a page in Vimma's agent workspace. Its request appears at the foot of the window, and nothing happens until you answer.

Answer a request

Each request names the agent, the tool and what it touches: the tab's title and address, or the address it wants to open.

ToPress
Allow it oncey
Allow this tool for this agent for 15 minutes (a bare a: 10)15a
Deny itn, Esc or Enter
Deny it and ignore this agent until it reconnectsx
Answer a request that is waitingctrl+b shift+a

The question never interrupts your typing: while you type, or with focus in a text field, it waits, and the status bar says ◇ agent 1?. An unanswered request is denied after 50 seconds.

What an agent can do

  • List the agent workspace's tabs, read a tab's text (marked as untrusted web content), open an http or https address there, and close one of its tabs.
  • Download files, each after a question; they go to ~/Downloads/vimma-agent/ only, and Vimma never opens them.
  • Nothing else: pages there get no permission prompts and no pop-ups, and links to other apps open nothing.

To share a page of yours with an agent, move its tab to the agent workspace (m in the ctrl+b w picker). It is reopened with the agent workspace's cookies, never yours. :mcp revoke ends every grant, and :mcp forget clears the agent workspace's logins.

All the keys for this page

The default bindings, as Vimma's own ctrl+b ? overlay lists them. Name is the action's name, which you use to remap it or to run it as a : command. Every key is on the keys page.

Agents (3)

ActionKeysName
Agents (MCP): :mcp on, off or forgetno default keymcp_command
Answer the waiting agent request (none: revoke grants)ctrl+b shift+aagent_prompt
Full control for a while: :control on <minutes>, offno default keycontrol_command

Details

Everything below is Vimma's own user guide for this topic, in full: every edge case and exception. You do not need it to get started.

Agent workspace

Every profile has a workspace named agent, for local AI agents (Claude Code, Codex, opencode, Copilot) to use through vimma-ctl mcp. It is a workspace like the others, with a container of its own, so its cookies and logins are apart from main, work and the rest. An agent only ever reaches this workspace, and every request asks you first. To let one in, see Connecting an agent's tool.

  • Made for you. A new profile gets it after main; an existing one at its next start. It is cyan, with the fingerprint icon. It has no tabs until you move one in (or an agent opens one), so it loads nothing. If you already have a workspace named agent (your own, or one in [workspaces]), that one is used and no second one is made.
  • Not in the cycle. ctrl+b ) / ctrl+b (, ]w / [w, :wn / :wp skip it, and the ctrl+^ of another workspace never lands on it. You go there on purpose: the workspace picker, where it is the last normal row (◇ agent), or :ws agent. In it, ctrl+^ goes back to where you came from. It always sorts last, so :ws 1…:ws N keep their places.
  • Emptied, never deleted. ctrl+b shift+d in it asks Close the 2 tabs of "agent"? It stays, with its cookies and logins (:mcp forget clears them). y/N: its tabs close and its container stays. It never counts as the last workspace, so main (or your last other one) stays too. Renaming it is refused (its name is [mcp] workspace in config.toml); to use another name, set [mcp] workspace. The old one then becomes an ordinary workspace.
  • Sharing a tab with an agent is moving it there (m in the picker, or :wsmove agent), after a y/N. The tab is reopened with the agent workspace's cookies, never yours.
CommandWhat it does
:mcpSays whether agents are on or off, which workspace is theirs, and how many agents, questions and grants.
:mcp onAsks Let local AI agents ask to use the "agent" workspace? Every request asks you first. y/N, then on.
:mcp offTurns agents off, without a question. Connected agents are disconnected and their grants end.
:mcp revokeEnds every time-limited grant you gave agents, at once.
:mcp forgetAsks, then deletes the agent workspace's cookies and site data (its logins). The workspace stays.
ctrl+b shift+aAnswers the waiting agent request; with none, offers to end every grant.
:control on 15Turns full control (vimma-ctl) on for 15 minutes, after a y/N; :control off ends it now.
  • When the agent workspace is one of yours rather than one Vimma made, :mcp on warns: "agent" is your own workspace (3 tabs, its own logins). Agents will be able to read it. y/N.
  • :mcp on|off is remembered in the pref vimma.mcp.enabled. [mcp] enabled in config.toml wins over it; then :mcp on|off changes nothing and says to edit the file.
  • about:vimma's Agents (MCP) section shows the switch, full control's state and the agent workspace's tab count.

Connecting an agent's tool

vimma-ctl mcp is the MCP server your agent's tool starts. It speaks MCP over its standard input and output, connects to Vimma as an agent (never with full control), and offers four tools:

ToolWhat the agent can do
vimma_tabsList the agent workspace's tabs: id, address, title, whether it is loading.
vimma_read_pageRead a tab's text, as Markdown or plain text, marked as untrusted web content.
vimma_openOpen an http or https address in a new background tab there, or in one of its tabs.
vimma_close_tabClose one of its tabs.
  1. Build vimma-ctl (Scripting with vimma-ctl, step 2) and put it on your PATH.

  2. In Vimma, :mcp on and y. Full control (vimma.control.enabled) can stay off: agents do not need it, and it is safer off.

  3. Add the server to your tool. Claude Code (tested with 2.1.287):

    claude mcp add --transport stdio --scope user vimma -- vimma-ctl mcp

    Codex CLI (the line checked with 0.160.0): codex mcp add vimma -- vimma-ctl mcp. Other tools (opencode, GitHub Copilot) take the same command, vimma-ctl mcp, in their MCP server settings. For a profile other than your default one: vimma-ctl --profile DIR mcp.

  1. Ask the agent, for example "open https://example.com in Vimma's agent workspace and tell me its heading". Each call waits for your answer on the question line; the agent says it is waiting.
  • What the agent gets. A read comes back as a line saying where the text is from and that it is untrusted, then the text between <untrusted-web-content> delimiters a page cannot close. A denial comes back as The user denied this request in Vimma., and a question nobody answers within [mcp] ask_timeout (50 s) as No answer in Vimma within 50 s; treated as denied. Codex gives up on a tool call after 60 s by default (tool_timeout_sec): raise it if you raise ask_timeout.
  • When it cannot reach Vimma, the call says what to do: Vimma is not running…, MCP is off in Vimma: run :mcp on…, or This Vimma is too old for MCP…. initialize and the tool list work without Vimma, so the tool shows the server as connected either way.
  • One connection per agent session. It opens at the agent's first call and stays while the session runs; ◇ agent in the status bar shows it. Grants belong to it: when the session ends (or Vimma restarts), they end, and the next session asks again.
  • Cancelling a call in the agent (Esc in Claude Code) takes its question off the line.

Answering an agent

Each request an agent makes appears as one line at the foot of the window, above the status bar:

◇ claude-code wants vimma_read_page: 2 "Pull requests · vimma-browser/vimma" github.com/vimma-browser/vimma/pulls   y once · 10a for 10 min · n deny · x mute

It names the agent (as the agent calls itself), the tool, and what it touches: the tab's place, title and address for a read or a close, the whole address for an open (its host in bold), the number of agent tabs for the tab list.

KeyAnswer
yAllow this request once.
a count, then aAllow this agent's use of this tool for that many minutes (15a); a bare a gives 10.
n, Esc or EnterDeny it.
xDeny it and everything else this agent asked, and ignore it until it reconnects.
BackspaceTake back a digit of the count.
  • Nothing else answers. Any other key does nothing and the line stays; a key held down from before never counts; and for its first second the line takes no key at all (the hint appears when it is ready), so a key meant for something else cannot answer it. That second starts again whenever the window comes to the front or leaves it, and with every key pressed before it is up. A prompt, picker or the command line you open over the line gets your keys; the question waits and comes back when it closes.
  • It never interrupts your typing. It opens by itself only when the window is in front, focus is not in a text field, you have not pressed a key for 1.5 s, and no other prompt, picker or panel is open. Otherwise it waits, and the status bar says ◇ agent 1?; press ctrl+b shift+a to answer it then. It never takes focus: answer, and you carry on where you were. If you click into a text field while it shows, it goes back to waiting.
  • One at a time, oldest first. An agent may have 4 waiting, and all agents 16. With no answer within 50 s ([mcp] ask_timeout) the request is denied (agent request timed out (denied)). Three noes in a row from one agent ignore it for a minute.
  • Not in front? When Vimma's window is not the one you are using, it is marked urgent (on Hyprland, the workspace is highlighted) and a desktop notification says, for example, claude-code asks to use Vimma's agent workspace (read a page). It carries no address or title and no buttons: you answer in Vimma. [mcp] notify = false turns the notification off.
  • Grants show. ◇ agent 14m counts down the shortest one, and each request a grant lets through shows a notice (claude-code read "Pull requests · vimma-browser/vimma" (grant, 14m left)). :mcp revoke, or ctrl+b shift+a with nothing waiting and then y, ends them all. A grant also ends when the agent disconnects or :mcp off runs, and is never written to disk.

Full control while agents are on

An agent with a shell can read the control socket's token like any program of yours. So while agents are on (:mcp on), each new vimma-ctl connection with full control (keys in your window, every workspace) asks in the same line: ◇ vimma-ctl wants full control — y/N. y lets that one connection in, anything else from n, Esc, Enter or x refuses it, and nothing is remembered: the next one asks again. The line shows the code vimma-ctl printed in your terminal (vimma-ctl with code 7F3K wants full control): answer y only if it is the same, since another program could have asked at the same moment. vimma-ctl waits for your answer and says so; refused, it prints full control refused and exits 4. With agents off, nothing asks.

:control on 15 turns full control (the pref vimma.control.enabled) on for 15 minutes after a y/N, and then off again, even across a restart; :control off turns it off now, and :control says whether it is on and how long is left. Turning it on in about:config sets no end time.

What pages in the agent workspace may do

Pages there run with nobody watching, so they get less than yours:

  • No permission prompts. A request for your location, notifications, camera, microphone, screen, MIDI, persistent storage, the local network and the rest is refused without a prompt.
  • No pop-ups. window.open and links that open a new window or tab do nothing there.
  • No other apps. A link to mailto:, zoommtg: or another app's protocol opens nothing.
  • Downloads ask, and are kept apart. See Downloads from the agent workspace.
  • If you change [mcp] workspace, the new agent workspace's open tabs are reloaded once, so these rules apply to the pages already in them.

Downloads from the agent workspace

An agent (or a page in the agent workspace) may download files, but each one asks first, in the same line as every other request:

◇ claude-code wants vimma_download: "report.pdf" 2.1 MB application/pdf (.pdf) from example.com

It shows the file's name, its size (or unknown size), its type and extension and the site it comes from, never the full address. y, n, x and a count with a work as for any request; a vimma_download grant lets that agent's next downloads through without asking. A download counts as the agent's only when it is the address the agent itself opened (vimma_open), right then. Anything else, such as a page the agent opened downloading something later, says a page in the agent workspace wants vimma_download and takes only y or n, whatever grants you gave.

  • Kept apart. Files are saved only to ~/Downloads/vimma-agent/ ([mcp] download_dir), never to your Downloads folder, with mode 0600: no one else can read them and nothing can run them. Until a file has passed every check it keeps a .part name there. The folder itself is kept private (mode 0700). It may not be your home folder, your Downloads folder, a hidden folder of your home (such as ~/.local/bin), or /tmp, /var/tmp or /dev/shm. If the folder is not yours or cannot be made private, every agent download is refused, with a notice that says why.
  • Never opened. Vimma never opens an agent's download, offers no "open with", and refuses to open one from the downloads list later (agent downloads are never opened by Vimma). Open it yourself from the folder once you trust it.
  • **Dangerous files ask with !.** Programs and libraries (ELF, Windows and macOS programs, also found by their first bytes), scripts (.sh, .py, .js, .desktop, a #! line …), installers and packages (.deb, .rpm, .AppImage, .flatpak, .msi, .dmg …), and archives Vimma cannot look inside (.tar.gz, .7z, .rar …) end the question with — ⚠ a script (or what it is). y and grants do nothing there: only ! allows that one file. A .zip is checked by the entries it lists (it is never unpacked). If one is a dangerous file, has an exec bit, is a symbolic link, or would unpack outside its folder (../, /…), the zip asks with !. Some dangers show only once the file is in: an ELF named data.bin, or a program inside what was allowed as a script. Then a second question asks before the file gets its name, and n deletes it.
  • https only. A download over plain http:, or one a page's script made (blob:, data:), is refused (refused download "a.txt": not https).
  • A size cap. Over [mcp] download_max_mb (200 MB by default, 1 to 4096) it is refused, or stopped and deleted once it grows past it when the server did not say its size.
  • ClamAV, if you have it (below). Each file is scanned before it leaves its .part name, and a file ClamAV flags is deleted (deleted download "a.zip": ClamAV found …). Sometimes ClamAV fails, takes over five minutes, or cannot look inside a file (encrypted, or over its limits). Then the line asks — ⚠ not scanned: ClamAV failed; keep it?: y keeps it unscanned, anything else deletes it. The notice says saved "report.pdf" to ~/Downloads/vimma-agent, scanned (ClamAV), not fully scanned (ClamAV) or not scanned. Vimma has no download reputation service of its own: Firefox's Safe Browsing checks downloads only in a build with a Google key.
  • Your own saves are yours. Save Page (ctrl+s), Save Link As and Save Image As in an agent tab ask nothing and save where you choose, as in any workspace: an agent cannot press them.
[mcp]
download_dir = "~/Downloads/vimma-agent"  # ~/… or /…; never ~ or your Downloads folder itself
download_max_mb = 200
Virus scanning with ClamAV

ClamAV is optional, and Vimma does not ship it. If the system's clamscan is installed, Vimma uses it on every agent download. That means /usr/bin/clamscan or /usr/local/bin/clamscan, owned by root, never a copy found on your PATH. Without it, the notices say not scanned. Vimma does not update ClamAV or its virus definitions: your system's freshclam does.

On Omarchy and Arch:

sudo pacman -S clamav
sudo freshclam                                   # the first download of the definitions
sudo systemctl enable --now clamav-freshclam     # keeps them up to date

On Debian and Ubuntu, install clamav; the clamav-freshclam service keeps the definitions current. On Fedora, install clamav clamav-update and run sudo freshclam.

Two limits for now, both planned follow-ups:

  • Vimma does not yet notice stale definitions. Keep freshclam running, or scans use whatever definitions you last downloaded.
  • clamscan loads its whole database for each file. A scan takes a while and about 1 GB of memory.

The guide at the top is written for this site; the details are built from Vimma's docs/guide.md at 52f2481 (2026-10-15), and the keys from docs/bindings.json at 52f2481 (2026-10-15).

Keys

This site

Keyboard shortcuts for this website
j kscroll down, up
d uhalf a page down, up
gg Gtop, bottom
/search the docs, or filter the keys
] [next, previous docs page
g hgo home
g dgo to the docs
g kgo to keys
g igo to install
g ago to about
?this help; Esc or q closes it, and in here / filters Vimma's keys

In Vimma

Every default binding, grouped as Vimma's own ctrl+b ? groups them. The same list is on the keys page.

Loading…