Open-source project
Lum1104/dsh-browser avatar
Lum1104/dsh-browser

dsh-browser addresses pages by number and never asks the model to look at a screenshot

Chrome sidebar extension that lets DeepSeek Harness operate your browser directly, no vision capabilities required. 一款 Chrome 侧边栏扩展程序,可让 DeepSeek Harness 直接操控您的浏览器,无需视觉能力。

764 stars57 forksTypeScriptMIT

At a glance

What is it?
Lum1104's workspace joins a bridge plugin for DeepSeek Harness to a Chrome or Firefox MV3 extension, so the agent drives the tabs you are already logged into. The interesting parts are the text-only page channel, the one-tab binding, the loopback-only gateway, and an npm name that belongs to a different project.
Who is it for?
Choose dsh-browser when you want an agent to work inside the browser profile you already use, with your own logins, instead of a headless copy that has to be re-authenticated every run.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Pages become a numbered inventory, and screenshots never happen

The channel the model sees is text, and the design commitment is specific. A page is converted into structured text: title, URL, main text, and a numbered inventory of interactive elements. The model then addresses elements by that number rather than describing where they are or asking for coordinates. `browser_snapshot` produces that structure, and passing `delta: true` returns only what changed since the previous snapshot.

The boundary is stated in the same breath as the feature: browser tools never capture screenshots. Multimodal chat in dsh runs on a separate path, and the side panel accepts PNG, JPEG, WebP and GIF attachments when the host advertises image support. So a user can attach a picture of the page they are looking at, while the browser tool chain itself stays blind. That distinction matters when you reason about what an agent can and cannot infer: it knows the DOM as text and the numbers you gave it, not what the page looks like.

One other piece of the same idea is pointing rather than describing. Text highlighted in the page appears in the composer and is sent with your next message as fenced, attributed page content. The quote is captured only while a panel is open, and nothing is sent until you send the message.

Thirteen tools, and a rule that binds them to one tab

The tool surface is small enough to read in one pass. Read a page with `browser_snapshot`. Act on it with `browser_click` for links, buttons and checkboxes, `browser_type` for form input, `browser_press` for keys such as Enter, Tab, Escape and arrows, and `browser_scroll` for up, down, top and bottom. Navigate with `browser_navigate`, `browser_open_tab`, `browser_back`, `browser_forward` and `browser_reload`. Recover context with `browser_get_text` for lazy-loaded or partial pages and `browser_wait` for page-load and render-settle detection.

The tab machinery is where the constraints live. `browser_list_tabs` returns accessible tabs with stable IDs, titles, URLs, window and index metadata, and both active and controlled state. `browser_follow_tab` binds later browser tools to a tab from that list without activating it, and `browser_close_tab` closes one from the same list. Opening a URL in a new tab takes `active: false` to keep the current tab in front.

Two implementation notes are worth keeping. `browser_type` claims React and Vue compatible input, and its `replace` option clears the field before typing rather than appending into it. Images go out through `session.prompt` and `session.attachment`, which are gated on host capability and also cover image-only prompts and durable history previews.

The privacy claim is narrow: two field types, masked

The stated privacy boundary is exact rather than general. Passwords and payment card values are always rendered as a run of bullet characters and never leave the page. That is the whole claim, and it is a narrow one.

What it means in practice is that form masking applies to two categories of value. Everything else the page holds is sent as page text: article bodies, search terms, account names, order history, whatever the snapshot includes. Masked form fields are named as part of the snapshot structure, so the mask is a property of the serialization step rather than a separate filter you can audit in the extension.

Two other mechanisms reduce what gets transmitted. Delta snapshots return only changes, which keeps repeated polling from resending an entire page on every tool call. And the selection quoting path is inert until you act: the quote is captured only while a panel is open, and nothing is sent until you send the message. Neither changes the baseline, where a full snapshot of whatever tab is controlled is the input to every decision the model makes.

The gateway rejects non-loopback callers and binds to one tab

Because the extension runs in a browser that already holds your sessions, the bridge is where the security argument has to hold up. Three mechanisms are named for that.

Authenticated handshakes protect remote connections, so a connection to the bridge is not trusted merely because it reached it. Privileged gateway methods reject callers that are not on loopback, which keeps the powerful half of the interface local even when a remote path exists. And the extension binds tools to one user-controlled tab, so a tool call cannot be steered to a tab you did not hand over.

The tab binding is the piece that shapes everyday use as much as it shapes security. Tabs are listed, chosen and then followed, and later tool calls bind to the chosen one. Closing a tab goes through the same handle. This is why `active: false` matters when opening a second tab: the new tab is opened without taking the one you were reading out of front, which is a usability decision and a limit on surprise at the same time.

What the documentation does not spell out is the failure side: no failure behaviour is described for a page that refuses to serialize, for a tab that closes mid-call, or for what the agent sees when the snapshot inventory numbers shift between two snapshots. Delta updates are offered, but the stability of a number across snapshots is a question the tool table does not answer.

`dsh plugin` cannot do this install, and the one-liner only does Chrome

The first structural fact is that this is not a single plugin. It contains both a dsh bridge plugin and a browser extension, so the standard `dsh plugin` command alone cannot install it, and a one-line installer is provided instead. On macOS and Linux that is a curl pipe into bash; on Windows it is a PowerShell one-liner that downloads to a temp path and runs with execution policy bypass.

sh
curl -fsSL https://raw.githubusercontent.com/Lum1104/dsh-browser/refs/heads/main/scripts/install.sh | bash

Requirements are Node.js `^22.19` or `>=24`, Corepack with pnpm, and Chrome 116+ or Firefox 140+. Windows additionally needs Windows PowerShell 5.1, which ships with Windows, or PowerShell 7+. The workspace pins dsh `0.2.0-rc.2` as the minimum supported runtime and states that older releases are not supported; the manifest matches that with exact pins, no caret ranges, on every `@deepseek-ai/dsh-*` dependency it names, alongside `@deepseek-ai/cordis-plugin-group` at `~1.0.4`.

What the installer does is worth noting step by step: it downloads `main`, builds and registers the bridge plugin, builds the Chrome extension into `~/.dsh/browser-extension`, and opens `chrome://extensions`. First install means loading that directory as an unpacked extension; updates mean clicking Reload; and dsh has to be restarted if it was already running. The stated scope of that convenience is narrow: the one-line installer currently sets up the Chrome build. Firefox appears in the requirements and in a release title, but not in the automated path.

The npm name dsh-browser belongs to a different project

The clearest warning in the README is about a name collision. The unscoped `dsh-browser` package on npm belongs to a different project and is not affiliated with this one. This project is not published to npm at all, and the instruction is to use the installer.

The manifest backs that up: the root package is marked `"private": true`, which is why a plain `npm install dsh-browser` cannot be the right move, and why a `package-lock.json` style single package layout is not what you get. It is a pnpm workspace declared in `pnpm-workspace.yaml`, with `packageManager` set to `[email protected]`, and the four tracked directories are the plugin, the extension, the installers and the benchmark:

code
packages/browser/bridge-browser/
  cordis.patch.yml
extensions/dsh-browser/
scripts/install.sh
scripts/install.ps1

The tree also holds `.npmrc`, `README.i18n.yaml` alongside `README.md` and `README.zh.md`, a `benchmark/` directory, and an `.agents/` directory. Version numbers run slightly ahead of the tags: the manifest reads 0.1.4 while the newest published release is v0.1.3, whose title covers Firefox, cross-platform setup and contextual sessions, and the first public release was v0.1.1 on 21 August 2026.

The benchmark is paired and seeded, and it measures one harness against one baseline

The performance section reports a paired run of 60 trials dated 18 August 2026, with both backends completing all 30 assigned runs. dsh Browser Control is given a mean end-to-end latency of 5.32 s and 3.4 mean browser tool calls; the matched Playwright baseline is given 6.67 s and 4.7 calls. The duration ratio is given as 1.24 with a 95% confidence interval of 1.16 to 1.34, which is restated as Playwright taking about 24% longer, or dsh Browser Control cutting latency by about 20% and saving 1.35 s per task on average.

The methodology is stated rather than implied: six browser tasks, five deterministic seeds, the same dsh profile and the same model, `deepseek-v4-flash`, with page state validated independently, and a reproduction guide in `benchmark/README.md`. The seeds and the paired design are what make the interval meaningful rather than decorative.

The scope is what to hold in mind. This is one model on one date over six tasks, comparing one harness against a baseline configured to match it. It says nothing about sites that block automation, about login flows, or about any model other than the one named, and a 1.24 ratio on six tasks is a measurement of that comparison rather than a general claim about browser automation.

Editorial conclusion

Choose dsh-browser when you want an agent to work inside the browser profile you already use, with your own logins, instead of a headless copy that has to be re-authenticated every run. The privacy story is narrower than the marketing line suggests and worth reading closely: passwords and payment card values are masked before they leave the page, but every other field you fill is sent as page text, so treat any session with a live account as a session where the model can read what is on screen. Three things to check first. That your dsh runtime matches the exact pin, 0.2.0-rc.2, since older releases are not supported and the pin is not a caret range. That you want the manual extension load, because `dsh plugin` cannot do this install and the one-line installer sets up the Chrome build only, whatever the requirements line says about Firefox. And that you are not reaching for the npm package named dsh-browser, which belongs to another project; this one is marked private and is installed from source.

Frequently asked questions

Does dsh-browser take screenshots of the pages it controls?

No. Browser operation is text only: pages become structured text with a numbered inventory of interactive elements, and the model addresses those elements by number. The browser tools never capture screenshots. The side panel separately accepts PNG, JPEG, WebP and GIF attachments when the host advertises image support.

How do I install the dsh-browser extension?

The standard `dsh plugin` command cannot install it, because the integration is both a bridge plugin and a browser extension. Use the one-line installer for your platform, which downloads main, builds and registers the bridge plugin, builds the Chrome extension into ~/.dsh/browser-extension, and opens chrome://extensions, where you load that directory as an unpacked extension. Requirements are Node.js ^22.19 or >=24, Corepack with pnpm, and Chrome 116+ or Firefox 140+.

What does dsh-browser do with passwords and payment card values?

They are always rendered as a run of bullet characters and never leave the page. That is the stated privacy boundary, and it is limited to those two categories. Masked form fields are part of the structured snapshot, and `delta: true` returns only changes since the previous snapshot.

Can I install dsh-browser from npm?

No, and the name is a trap. The unscoped `dsh-browser` package on npm belongs to a different project and is not affiliated with this one. This project is not published as an npm package and its root package is marked private, so the installer is the supported route.

How does the dsh-browser bridge restrict remote access?

Authenticated handshakes protect remote connections, privileged gateway methods reject callers that are not on loopback, and the extension binds tools to one user-controlled tab. Tabs are listed with stable IDs and then followed with browser_follow_tab, which binds later tool calls without activating that tab.

Official sources

  1. Issues
  2. License: MIT
  3. Lum1104/dsh-browser on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lum1104-dsh-browser.svg)](https://hysenlabs.com/projects/lum1104-dsh-browser)