Integrating
Integrating with your browser and your editor
mechabedo runs beside two programs you already have open all day: the browser you are logged into, and the editor the project is in. Four integrations connect them, and the useful thing to know first is that they do not all run in the same direction.
Drawing the diagram…
| Integration | Direction | What it is for |
|---|---|---|
| The browser extension | mechabedo reaches your browser | A session can look at the running application, or at a page you are logged into |
| Editors as MCP servers | mechabedo reaches your editor | The chat reads and edits the file you have open, in place |
| The mechabedo editor extension | both ways | A session's conversation is in the editor, so are your pinned projects, a session reaches what is open in a VS Code or VSCodium window, and that editor's own agent reaches mechabedo |
| Opening an editor | mechabedo starts your editor | A card, or an agent, opens a directory or a file at a line |
Each one carries its own credential, and none of them is your login session. The table at the end is all four side by side.
The browser
The point is not browser automation. It is that an agent working on something can look at the running thing instead of at the source that was supposed to produce it, and that a page you are already signed into is often where the answer is.
The extension is wxt-mechabedo, MV3, and it works in any Chromium browser (Vivaldi, Chrome, Edge, Brave, Chromium, Arc) and in Firefox.
Install it
mise run ship:local-install-extension --buildThat builds the extension, stages it in a stable directory this checkout owns, and opens the browser's extension page. Vivaldi is the default; --browser names another, and --help lists them. A script cannot finish the browser's own "load unpacked" confirmation, so that last step is yours: pick the directory the command printed. The staged directory does not move, so you do this once and a later run only needs the browser's reload button.
By hand, if you would rather:
mise run ext:build # into wxt-mechabedo/.output/chrome-mv3
mise run ext:build:firefox # into wxt-mechabedo/.output/firefox-mv3Pair it
The extension holds no credential and cannot mint one. A mechabedo page hands it one, and usually without a press: any page you are signed into pairs an extension that has no pairing yet, so installing the extension and opening mechabedo is enough. The routes below are for the rest, and every one ends on the same page.
| You have | Do this |
|---|---|
| A browser already on a mechabedo page | Nothing, if the extension had no pairing. Otherwise Settings > Browser > Pair this browser, which reads Pair with this server when the extension holds another installation |
| A browser with no mechabedo page open | Open the extension popup. It lists servers it has seen, whatever answers on the ports mechabedo usually takes, and takes a typed address. Picking one opens that server's Browser page, and the tab pairs itself once it is signed in. On a desktop installation a fresh browser is not, and its sign-in page points at the row below |
| The desktop app | Settings > Browser, pick a browser, press Open a browser and pair |
| The desktop app, and a browser that is not in its list | Settings > Browser > Copy pairing link, then paste the link into that browser within five minutes |
The third row is the one that matters on a desktop installation, because the app's window is a webview and loads no extensions at all. It cannot pair with itself, so it opens a real browser instead and hands that browser its address:
Drawing the diagram…
The window holds a session and that browser does not, so the window hands over the credential itself: a code in the address, minted for this one address, spent on arrival and gone after five minutes. The browser needs no sign-in for it, so even a tab that stops at the sign-in page pairs its extension.
What the page hands over is browser.pairingToken, a credential of the bridge's own, generated on first run. It opens the bridge socket and nothing else, so it is not a login by another route, and it exists whether or not this installation authenticates anybody. It is held in the extension's local storage, so a browser that has paired is still paired tomorrow; Forget server in the popup is how it is forgotten.
There is one pairing at a time, so a browser serves one installation's sessions. A page never moves a pairing that names another installation on its own: Settings > Browser shows which server the extension holds and offers to pair with this one instead. A tab is recognised as a mechabedo tab separately, by origin, so tabs on other installations are still listed.
A pairing survives the server restarting: the extension reconnects within seconds, and its toolbar button shows … while it does. It does not survive a new pairing token, which is what a profile switch or a settings reset gives the server. The server then turns the extension away by name rather than looking like it is down: the button shows !, the popup says the server no longer accepts the pairing and offers Re-pair, and the next page of that server you open pairs it again by itself.
What a harness may do
Consent lives in the extension, not on the server, and is set in the popup or on Settings > Browser. Seven capabilities, three levels:
| Level | Meaning |
|---|---|
| Off | Refuse |
| mechabedo only | Only tabs on an origin that has identified itself as mechabedo |
| Every tab | Any tab, any request |
| Capability | Tools | Default |
|---|---|---|
| Find and focus tabs | list_tabs, focus_tab, open_tab, reload_tab | mechabedo only |
| Read pages | read_page, query_dom | mechabedo only |
| Change pages | click_element, set_input_value, set_element_text, inject_style, scroll_to | mechabedo only |
| Photograph pages | screenshot_tab | mechabedo only |
| Capture network requests | list_network_requests, get_network_request, clear_network_requests | mechabedo only |
| Fetch URLs | fetch_url | Off |
| Read bookmarks and history | search_bookmarks, list_bookmarks, search_history | Off |
So out of the box a session can drive the application it is working on and nothing else. That is the case the feature exists for, and widening it is meant to be a deliberate press.
The two that start off are off for different reasons. Fetch URLs lends the caller your cookies and your network reach, and "mechabedo only" would leave it able to fetch nothing but mechabedo, so there is no sensible middle level; until you switch it on, fetch_url is answered by the server instead, anonymously. Bookmarks and history additionally needs a browser permission, and only the popup can ask for it, because that request needs a click the extension itself can see.
The popup carries one press that sets finding tabs, reading pages and fetching to every tab: Allow reading any page, for documentation. The defaults are right for driving an application under development and useless for looking something up, and that should not be four decisions.
How a call travels
Five hops, and two boundaries that deliberately do not overlap. The server owns the protocol and decides nothing about what a page may do. The extension owns consent and knows nothing about harnesses.
Drawing the diagram…
Three things about that chain are worth knowing, because they explain most of its behaviour:
- The extension dials out. Nothing can dial in to a service worker, so the socket is opened from the browser and the calls run backwards along it. The heartbeat on it is load-bearing rather than diagnostic: Chromium stops a service worker after thirty seconds of quiet, so the ping is what keeps the extension alive. When it is stopped anyway, an alarm brings it back.
- A caller names a script; it cannot send code. The set of things that can happen to a page is a list in one file, which is the whole safety story on the page side.
- A page and the extension talk in two hops, both through comctx: the page reaches the content script with a
CustomEvent, and the content script reaches the service worker with runtime messaging. The page never addresses the extension directly.
What it deliberately does not do
No debugger protocol, no arbitrary script evaluation, and no writing to a page you have not allowed. Response bodies are not captured either: the network tools give you the request, its headers and a curl line that reproduces it. A screenshot is the visible area of the tab that is showing, not the whole document and not a background tab, because a picture of whatever happened to be in front would be indistinguishable from a working call.
Without the extension: the desktop app's own windows
You do not have to pair anything for a session to look at a page. In the desktop app with no browser paired, the same tools are answered by windows the app opens on its own engine: open_tab opens one, list_tabs reports it, and a session can read it, click and type in it, photograph it and watch what it fetched. That is usually a local dev server the session is working on. With a browser paired, a session can still choose these windows by opening a page with browser: builtin.
The app drives them over a DevTools port it opens on 127.0.0.1 at launch, so a screenshot is the picture the screen shows, canvas and video included, and can be the whole page rather than the visible part. The network log has every request the page made, its body included, and the session's scripts run where the page cannot see or interfere with them. Opening the port costs the app one extra start of its engine at launch, about a fifth of a second.
Those windows are not your browser. They carry none of your logins, so bookmarks and history are still the extension's alone. A session can keep six of them open; past that the one used longest ago closes. Close any of them whenever you like.
The same port is how a session photographs mechabedo's own window when it asks what the app looks like, so the companion's stage, icons and the bottom edge are in that picture as you see them.
It is on by default. Settings > Browser > Built-in browser switches it off, lists the windows sessions have open and brings a hidden one forward. Its DevTools port switch, which works with the built-in browser off too, turns the port off from the next launch: any program on your computer can reach that port, including another account's, and without it both still work, with screenshots redrawn from the page instead. Without the port, the built-in windows open only pages on your own computer, such as files and localhost dev servers. Any other site in them could use the window to open things on your computer, and the port is what lets the app prevent that. When you do pair a browser, that one answers again, and windows already open stay reachable by their tab ids.
Anthropic's own extension is a different thing
Claude in Chrome is not this. It is Anthropic's extension, paired to your claude.ai account through their relay rather than to anything local, and Claude Code serves its tools. mechabedo can offer those tools to every session it starts, which is the switch on Settings > Browser > Claude in Chrome. It is off by default, and the two extensions never meet.
When it does not work
| Symptom | Usually |
|---|---|
| "No extension answered on this page" | The extension is not loaded in this browser, or the page was open before it was. Reload the tab |
| Paired, but a tool says the browser is reconnecting | It lost its connection moments ago and comes back by itself within seconds |
| Paired, but every tool says no browser is connected | The service worker was stopped and has not reconnected. Open the popup, which starts it |
The extension's toolbar button shows ! | The server no longer accepts its pairing, after a profile switch or a settings reset. Re-pair in the popup, or open any page of that server |
| Windows titled "· mechabedo browser" appear | A session opened a page while no browser was paired. They are the desktop app's own, and closing them is fine |
| The desktop app says no browser is paired and the built-in one is off | Settings > Browser > Built-in browser is switched off |
| A built-in window refuses a site with "without DevTools" | The DevTools port is off, or the window could not be reached through it. Switch the port on and restart the app, or pair a browser |
| A tool is refused by name | The capability is at a level that does not cover that tab. The refusal says which one |
Scripting refused on a chrome:// or extension-gallery page | The browser refuses it whatever the level. Finding and focusing such a tab still works |
screenshot_tab says to focus the tab first | It photographs the tab showing in its window, and moving your tabs is a separate act |
| The desktop app offers no pairing button | It only appears in desktop mode with no extension answering, which is the case it exists for |
Your editor
Three separate things that are easy to conflate, because two of them are MCP and one of them is not.
| What it is | Who talks first | |
|---|---|---|
| Rider | Rider runs an MCP server; mechabedo is a client of it | mechabedo |
| VS Code, VSCodium, Visual Studio | The same, if an extension gives the editor an MCP server | mechabedo |
| The mechabedo editor extension | A window that connects out to mechabedo and is reachable from a session afterwards | the editor |
All three are configured on Settings > External IDEs.
Rider
Rider ships an MCP server of its own, and mechabedo ships a preset pointing at it. Switch on Offer its tools to the chat, and check the address against Rider's own Settings | Tools | MCP Server, which is where it prints its HTTP Stream URL. A loopback editor needs no bearer; the field is there for a server that is not on this machine.
What the chat then does with it is deliberately a passthrough: the editor declares its tools, the model reads their descriptions. "Get that controller open in Rider and fix it" becomes a listing, a read of the open file, a transformation, and a write back into the editor, rather than a snippet you have to copy.
The reach is one way
A configured editor's tools go to the chat, not to the harness sessions mechabedo launches. Those are pointed at mechabedo's own MCP endpoint instead.
VS Code and VSCodium
These two have no built-in MCP server, which is why their presets ship with an empty address. You have two ways to close that, and they are not the same thing:
- mechabedo's own extension, below. Nothing to configure, and what it gives a session is more than an MCP server would.
- A third-party MCP extension, if you already run one. Paste its HTTP Stream URL into the preset and switch it on. Only that transport is spoken; an extension offering the older GET-SSE transport will not connect, and the error says so.
The mechabedo editor extension
mise run ext:vscode:install # links it into VSCodium and VS Code
mise run ext:vscode:install --uninstallRestart the editor afterwards. Five jobs, and no configuration for any of them.
It shows the conversation. The session working in the folder the window has open, as its conversation and prompt line: the turns, the tool calls, the questions and permission holds, the / menu and Stop. It opens in an editor tab with mechabedo: Open the conversation, or beside the file tree under the mechabedo icon in the activity bar. A folder with no session offers to start one there.
It looks like the editor rather than like mechabedo: the editor's theme, light, dark or high contrast, and its fonts, following you when you switch theme. The editor's own shortcuts keep working while you type in it, Ctrl+K chords included. The tab is titled after the session, the view's badge counts the sessions waiting on you, and Switch session… in the title bar, or Ctrl+Shift+K, moves to another session or starts one. Closing the tab ends nothing; the session keeps working in the desktop window.
There is nothing to sign in to: the extension asks the running desktop app for a one-time code for that tab. When mechabedo is not running, the tab says so and opens on its own once it is.
It paints the window in the colour the project is pinned with, so an editor window and its card on Home say the same thing. An unpinned folder is left alone: nothing is written, no default colour is invented, and no notification appears, because a wrong colour would say the wrong project.
It keeps your pinned projects, as mechabedo Projects in the Explorer and behind mechabedo: Open a pinned project in the command palette: the same cards as on Home, in the same order, each with its own colour. A window that opens with no folder in it offers them, which is the moment the list is worth having.
The editor stores that list rather than asking for it, so it is there when mechabedo is not running - which, on a machine that has just started, is most of the time. It says when it last synced, and it syncs again by itself when mechabedo comes up or when you open the list; mechabedo: Sync the pinned projects is the button for doing it now. mechabedo.projectsOnLaunch chooses what a window with nothing open shows: the list, the picker, or off.
It makes the window reachable from a session. The extension connects out to mechabedo and holds that socket, so a session can read what you have open, see where the caret is, ask the language servers what is wrong and put a change back. Nothing listens inside the editor, and no port is opened.
Drawing the diagram…
The six tools are in the Editor category, so they reach the agent sessions mechabedo launches and not only the chat:
| Tool | What it answers |
|---|---|
editor_windows | Which windows are connected, their folders and the file each is on |
editor_open_files | What is open in one window, and which has unsaved changes |
editor_selection | The caret, the selection and the selected text |
editor_read | A document as the editor holds it, unsaved edits included |
editor_edit | Replace a range or a whole document, left unsaved so you review it |
editor_diagnostics | What the language servers report, without running a build |
Two behaviours are worth knowing. A tool that does not name a window means the one you last worked in, so with several windows open you rarely have to name one. And an edit arrives unsaved, inside the editor's own undo stack, so you see it as a diff and Ctrl+Z takes it back; a session has to ask to save.
Settings > External IDEs > Windows a session can reach lists what is connected, so you can tell a window that has the extension from one that does not.
It offers mechabedo to the editor's own agent, as an MCP server, using the token it already holds. That gives the editor's agent the logbook, the archive and the rest with nothing configured. This is the half that depends on your editor: it rides VS Code's MCP client, which VSCodium does not ship, so on VSCodium you get the other four jobs and this one quietly does not appear.
There is nothing to pair and no token to copy. A running mechabedo writes ~/.mechabedo/ide/<profile>.json, readable by you alone, with its address and a token it minted for that run, and the extension reads it, much as Claude Code's IDE integration finds its editor. Nothing guesses a port, a quit removes the file, and the token dies with the run. The extension believes the file only when you own it, nobody else can write it, its process is alive and its address is this machine's.
mechabedo.serverUrl and mechabedo.token are for a server somewhere else, and mechabedo.profile picks one when several profiles are running. Beside them are mechabedo.paintOnOpen, mechabedo.elements, mechabedo.projectsOnLaunch and mechabedo.bridge, which is the switch for the fourth job above. The first three are machine settings, so neither a cloned repository's workspace settings nor Settings Sync can change where a token goes.
The colours go into the workspace rather than your user settings, and clearing takes back exactly the keys this extension wrote.
Opening an editor
The last integration is the simplest: mechabedo starting your editor rather than talking to one that is running.
- A Home project card carries a button in its title band that opens that directory. It appears when the machine has an editor and the dashboard is set to draw it.
- An agent has two tools for it,
editor_statusandeditor_open, which open a directory, a.code-workspaceor a file at a line.
Which binary runs is Settings > External IDEs > Opening one: auto, VSCodium or VS Code. auto prefers VSCodium where both are installed, on the reasoning that a machine which has it chose it, and a pinned editor this machine does not have falls back to the one it does, so the setting cannot leave nothing able to open. Opening reuses the window you are looking at rather than adding another to your taskbar.
The credentials, in one place
None of these is your login session, and none of them is interchangeable.
| Integration | Credential | Scope |
|---|---|---|
| Browser extension | browser.pairingToken, generated on first run | The bridge socket and nothing else |
| A harness calling browser tools | A bearer minted for that session, dropped when it ends | That session's tool kit |
| mechabedo's editor extension | A token minted per run into ~/.mechabedo/ide/, dead when the app quits | The MCP endpoint, the editor's own questions, and a single-use ticket for the window's socket |
| An editor's own MCP server | Whatever that editor requires, usually nothing on loopback | mechabedo stores it per entry and reads it nowhere else |
Two consequences follow. A browser can be paired with an installation that has no login at all, which is every desktop app, because the pairing token is not a login. And anything running as you can read server.jsonc and the editor's discovery file, so both are as sensitive as the rest of the profile; Settings > Access rotating the MCP token rotates the editor's as well.
Through a beam neither shortcut applies: a remote browser presents a real session. See Beam.