Routing links to workspaces
Routing puts each link where it belongs without you thinking about it. Send GitHub to your work workspace, or every link Slack opens, and it arrives there with that workspace's logins, wherever you clicked it.
Write your first rule
- Go to a site that belongs in a workspace, such as
github.com. - Type
:route add workand press Enter. Vimma appends a rule for the site toconfig.toml. - From now on, an address you type, a bookmark or a link from another app on that site opens in
work.
Or write the rules yourself in config.toml. The first rule that matches, top to bottom, wins:
schema = 2 [[routes]] domain = "github.com" # the site and its subdomains workspace = "work" [[routes]] app = "slack" # every link Slack opens workspace = "work"
Commands
| To | Type |
|---|---|
| See every rule, and which one matches this tab | :route |
Send this site to this workspace, or to work | :route add, :route add work |
| Move this tab to the workspace its rule names | :route move |
Good to know
- Rules apply to what you open: an address you type,
:open, a bookmark, a link from another app. A link a page opens stays in that page's workspace, so no site can open another with your other logins; the status bar names the workspace its rule would choose, and:route movetakes it there. - Routing by app works through
vimma-open, which Vimma's packages set up as the browser's command. A link from an app Vimma cannot name (a Flatpak, say) follows thedomainandurlrules only. - Private windows are never routed.
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.
Routing: which workspace a link opens in
[[routes]] rules in config.toml send a site, or every link an app opens, to a workspace (and its container), as Zen's Space Routing does. Each rule names a workspace and what it matches; the first rule that matches, top to bottom, wins.
schema = 2
[[routes]]
domain = "github.com" # github.com and its subdomains (gist.github.com), any port
workspace = "work"
[[routes]]
domain = "*.corp.example" # only subdomains: jira.corp.example, not corp.example
workspace = "work"
[[routes]]
app = "slack" # every link Slack opens
workspace = "work"
[[routes]]
app = "discord"
domain = "youtube.com" # both must match: YouTube links from Discord
workspace = "personal"
[[routes]]
url = "file:///home/me/notes/" # a URL prefix: the way to route file:, about: and the like
workspace = "notes"
- **
domain** matcheshttpandhttpspages only, on whole labels (github.comis notnotgithub.com), whatever the port; Unicode names work written either way (bücher.exampleorxn--bcher-kva.example), and an IP address matches only itself. - **
app** is the name of the program that opened the link, asvimma-opensees it (below). - Order is the precedence. Put the rule that matters most first: with
app = "slack"abovedomain = "youtube.com", a YouTube link from Slack goes towork. - A rule naming a workspace that does not exist is skipped (
:routesays so).
Where rules apply: an address you type in the URL bar or with :open / :tabnew, a bookmark, a link from another app and a new window opened on a URL: what you or Vimma open. A link a page opens (a click, middle-click, F hints, target=_blank, a pop-up) stays in that page's workspace, because a page could otherwise open any site with another workspace's logins; when you look at such a tab, the status bar names the workspace its rule would choose and :route move moves it. Opened in front, the tab takes you to its workspace; opened in the background, it waits there and the status bar says opened in "work". If you typed the address on an empty new tab, that tab is closed.
Where they do not: a page that navigates in its own tab (a click, a redirect, a sign-in bounce) is never moved, because moving reopens the page and would break the load. The status bar says github.com goes to "work" (route 1): :route move instead; :route move moves the tab there (it loses its back/forward history, as any move does). A container you chose yourself ("Open Link in New Container Tab") is kept. Private windows are never routed.
By application. Vimma's packages install vimma-open and make it the desktop entry's command, so when Slack, Discord, a terminal or Neovim opens a link, vimma-open looks up which program asked (through /proc, skipping xdg-open, gio and shells) and tells Vimma. A link you open from a shell counts as the terminal's. Apps in Flatpak (they go through the desktop portal), apps started through systemd (uwsm app) and links opened while the asking program has already exited have no app: only domain and url rules apply to them. To see what an app is called, run vimma-open https://example.com from it, or look at its process name (ps -o comm), lower-cased.
Commands.
| Command | What it does |
|---|---|
:route | Opens about:vimma's Routing section: every rule in force, and which one matches the tab you were on. |
:route add, :route add work | Adds a domain rule for this site (its host without www.) to the end of config.toml, for this or the named workspace. |
:route move | Moves this tab to the workspace its rule names. |
:route add refuses a site an earlier rule already routes (it names the rule), a config.toml that has errors, and a file without schema = 2. It only ever appends to the file.
Known limits
Vimma is pre-alpha. What does not work yet, or works with a catch, is listed on the known limits page:
The guide at the top is written for this site; the details are built from Vimma's docs/guide.md and bindings.md at 1050bcc (2026-10-10).