Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>herdr-bridgeNew to Visual Studio Code? Get it now.
herdr-bridge

herdr-bridge

clement-micol

|
1 install
| (0) | Free
Bridge from herdr panes to VS Code: attach herdr terminals via vscode:// URIs
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

herdr-bridge for VS Code

herdr-bridge

A small VS Code extension that bridges herdr panes into VS Code. Fire a vscode:// URI from a herdr keybinding or script, and the extension opens an integrated terminal attached to that herdr pane's terminal stream.

How it works

herdr keybinding ──▶ open "vscode://file/<pane cwd>"                        (1)
                ──▶ open "vscode://clement-micol.herdr-bridge/attach?pane=<id>"    (2)
                              │
                              ▼
                    URI handler (extension, in the window focused by (1))
                              │  pane.get over ~/.config/herdr/herdr.sock
                              ▼
                    createTerminal(herdr terminal attach <terminal_id>)

Window routing is deliberately outside the extension. URL (1) is consumed by VS Code's main process, which opens-or-focuses the window for that folder (native dedupe, explicit focus) and never delivers it to extensions. URL (2) is then routed to the most recently focused window — the one (1) just focused — where this extension attaches the terminal. Extension URIs cannot target a window and window-openable URLs cannot reach extensions, so the pair is the whole design. Add &windowId=_blank to (1) to force a fresh window.

The attach URI carries only the pane id; everything else (terminal id, cwd, agent state) is fetched live from the herdr server's unix-socket API, so the link stays correct even if it's opened late or twice.

URI contract

vscode://clement-micol.herdr-bridge/attach?pane=<pane id>
  • pane — a herdr pane id, for example wS:p1. Required, and the only parameter. A raw : is accepted. URL-encoding it (wS%3Ap1) also works.

Example trigger from a herdr-side script:

open "vscode://file/${HERDR_ACTIVE_PANE_CWD}"
open "vscode://clement-micol.herdr-bridge/attach?pane=$HERDR_ACTIVE_PANE_ID"

Requirements

  • The herdr binary on PATH (used to run herdr terminal attach inside the created terminal).
  • A running herdr server (socket at ~/.config/herdr/herdr.sock, protocol 17).

Install

Install from the VS Code Marketplace. This is the normal path.

code --install-extension clement-micol.herdr-bridge

You can also search for herdr-bridge in the Extensions view, or open the Marketplace page.

This is a community extension. It is not affiliated with the herdr project.

If you installed an earlier build, remove it. VS Code treats each old id as a separate extension and keeps them all installed.

code --uninstall-extension afresh.herdr-bridge
code --uninstall-extension herdr.vscode-bridge

Install a build instead

To run an unreleased change, build the .vsix yourself.

npm install
npm run package                   # produces herdr-bridge-<version>.vsix
code --install-extension herdr-bridge-*.vsix

Every CI run also attaches a .vsix artifact, and every release attaches one to its GitHub release.

Set up the herdr shortcut

Add a shell keybinding to ~/.config/herdr/config.toml. This is the working setup, bound to prefix+e:

[keys]
# prefix+e defaults to "open pane scrollback in $EDITOR". Move that out of the
# way first, or the binding below is rejected as a duplicate.
edit_scrollback = "prefix+shift+e"

[[keys.command]]
key = "prefix+e"
type = "shell"
command = "open \"vscode://file/$HERDR_ACTIVE_PANE_CWD\"; open \"vscode://clement-micol.herdr-bridge/attach?pane=$HERDR_ACTIVE_PANE_ID\""
description = "open editor at pane cwd"

Both open calls are needed, in this order. The first focuses the right window, the second attaches the terminal. See How it works above.

herdr exports these variables into a type = "shell" keybinding:

Variable Value
HERDR_ACTIVE_PANE_CWD working directory of the focused pane
HERDR_ACTIVE_PANE_ID pane id of the focused pane, for example wS:p1
HERDR_ACTIVE_TAB_ID tab id of the focused pane
HERDR_ACTIVE_WORKSPACE_ID workspace id of the focused pane

Note that HERDR_PANE_ID is a different variable. It is set inside a pane's own shell, not in a keybinding, and it is empty here.

Then check the file and load it into the running server:

herdr config check
herdr server reload-config

Use it

  1. Focus the herdr pane that you want to open.
  2. Press prefix+e.
  3. Approve the two first-use prompts (see below).

VS Code opens or focuses the window for that pane's directory. A terminal named herdr: <pane id> appears in that window, attached to the pane's terminal stream. The pane keeps running in herdr — this is a second view of the same terminal, not a copy.

Two one-time prompts appear on first use. Both offer an "always allow" option:

  • VS Code asks to confirm the vscode://file/ URL, because an external app sent it.
  • VS Code asks to allow the attach URI to reach this extension.

To open a fresh window instead of reusing one, add &windowId=_blank to the vscode://file/ URL.

If nothing happens

Symptom Cause
No window opens The vscode://file/ URL was blocked at the confirmation prompt.
Window opens, no terminal The attach URI was blocked, or the extension is not installed.
Error herdr socket error The herdr server is not running.
Error failed to attach to pane The pane id is stale. Press prefix+e again from the pane.

Protocol notes (for future work)

The herdr socket speaks newline-delimited JSON. Facts learned empirically, not all obvious from the schema (herdr api schema --json):

  • Requests are {"id": "<string>", "method": ..., "params": {...}} — id must be a string, params is required even when empty.
  • The server is one-request-per-connection: it closes the socket after each response. HerdrClient therefore opens a fresh connection per request.
  • Undispatchable requests (unknown method, malformed JSON) come back with "id": "" rather than echoing the request id.
  • events.subscribe is the exception to one-shot: that connection stays open and streams {"event": ..., "data": ...} messages (no id). Not used by the extension yet.

Develop

npm run watch            # tsc in watch mode
npm run lint
npm test                 # vscode-test

To debug, open this folder in VS Code and press F5. That launches an Extension Development Host with the extension loaded from source.

Release

Two GitHub Actions workflows live in .github/workflows/.

Workflow Trigger What it does
ci.yml push to main, pull request lint, compile, test, package, upload the .vsix as an artifact
release.yml push of a v*.*.* tag the same checks, then publish to the Marketplace and create a GitHub release

One-time setup

  1. Create a publisher named clement-micol at the Marketplace management page.
  2. Create an Azure DevOps personal access token with the scope Marketplace → Manage.
  3. Add the token as the repository secret VSCE_PAT, with gh secret set VSCE_PAT.

Use the same Microsoft account for the Azure DevOps organization and for the publisher. Two different accounts produce a confusing "you do not have permission to publish" error.

The token problem, as of August 2026

The VS Code documentation tells you to set the token organization to All accessible organizations. That is a global PAT, and Azure DevOps blocked creation of new ones on 2026-03-15. Existing ones stop working on 2026-12-01.

So create an organization-scoped token instead. Whether the Marketplace accepts one for publishing is an open question — see microsoft/vscode#322741. Test it with a real publish before you depend on it.

If it does not work, publish by hand until Microsoft resolves the issue:

npx @vscode/vsce login clement-micol
npm run package
npx @vscode/vsce publish --packagePath herdr-bridge-*.vsix

The documented replacement is Microsoft Entra ID with workload identity federation. It costs nothing, but the published flow assumes Azure Pipelines and an Azure DevOps service connection. It does not map onto GitHub Actions today.

Cut a release

npm version patch          # or minor / major — updates package.json
git push origin main --follow-tags

The tag must match the version in package.json. The workflow checks this and fails if the two differ. Update CHANGELOG.md before you tag.

To rehearse without publishing, run the Release workflow by hand with dry_run enabled. It builds and attaches the .vsix but skips the publish step.

Source layout

  • src/herdrClient.ts — minimal client for the herdr socket API (one connection per request, promise-based, safe when herdr is down).
  • src/extension.ts — the onUri activation and the attach flow; all VS Code-facing logic.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft