DGC v0.48.4 is out
Navigate
Install DGC
DGC v0.48.4Edit on GitHub ↗
Features/Looking at a page

drive a real browser to see a deployed or local site

Looking at a page

#

web_fetch gets you an article's text. It cannot run JavaScript, log in, click anything, or tell you whether a page actually rendered. For that DGC drives a real browser.

you › open https://staging.example.com and tell me if the pricing table renders

The agent earns a browser tool when your prompt is about a page that has to run — a deployed or locally served site, a screenshot, a console or network question, or clicking through a flow. It stays out of the way the rest of the time.

What it can do

#
Operation What you get
openNavigates, waits for the page to settle, returns the page structure
snapshotThe current page as roles, names and refs — the model's main way of reading
findElements matching text, with their refs
click · type · select · pressReal input events, then a fresh snapshot
waitBlocks until text appears, capped at 30 seconds
consoleConsole messages since load, with severity
requestsNetwork responses: status, type, and what failed
screenshotA PNG saved under .dgc/screenshots/ (given a url, it opens that page first), shown in the chat, and to the model if it has vision
closeEnds the browser session

A snapshot looks like this, and every [e12] is a handle the model can act on:

- heading level=1 "Sign in" [e1]
- form [e2]
  - textbox "[email protected]" [e4]
  - button "Continue" [e8]

Refs change whenever the page does. After a click that navigates or re-renders, the tool hands back a fresh snapshot, and stale refs fail with a message telling the model to take a new one.

Screenshots and local models

#

A screenshot is only useful if something can look at it. In the editor panel the step that took it shows an image count; open the step to see the image as a thumbnail, and click the thumbnail to open it in a viewer. In the terminal, open the step and click open to hand it to your system's image viewer. Viewed images has the details.

Whether the model can see it is a separate question, and DGC checks rather than guesses. With a vision model the picture is attached for it to read. A model without vision never receives it. If a vision sub-agent model is set, the result says where the screenshot was saved, and the model can ask that vision model about it with view_image (see Sub-agents); either way it is nudged to use snapshot, which is more precise for page structure. If an endpoint turns out not to accept images, DGC caches the rejection for that endpoint/model pair for up to one hour, shared across chats in the same process. Restarting DGC clears it. Check with ollama show <model> — look for vision under Capabilities.

Which browser

#

DGC uses a Chrome or Chromium you already have. It looks at browser_path in ~/.dgc/config.json, then CHROME_PATH, then Playwright's cache, then your PATH, then the usual install locations.

With none, DGC fetches one, once, and the first browser call waits for it:

  • Linux (Debian, Ubuntu and their family): the same Google Chrome DGC downloads for Pip computers. It comes from Google's package repository, checked against Google's signing key, and is unpacked under ~/.dgc/desktop with no admin password. Work runs it as a separate browser: it never shares a Pip's browser, cookies or tabs. It is re-checked for updates once a day.
  • macOS: Google's own Chrome installer. It is opened read-only, and its app is kept under ~/.dgc/browser only when macOS confirms it is intact and signed by Google LLC as Google Chrome. It is re-checked once a week. A Chrome in /Applications or ~/Applications comes first.
  • Windows: DGC runs inside WSL, so this is the Linux row above. A native DGC on Windows (experimental) uses Microsoft Edge, which every Windows 10 and 11 has, or Chrome; it downloads nothing.

A browser_path that is wrong is reported, never replaced by a download, and a download that failed is tried again after an hour, not on every call.

Each session gets its own throwaway profile, so a page never sees your real cookies or logged-in sessions, and the profile is deleted when the session ends.

When Chrome can't use its own sandbox

#

On Ubuntu 23.10 and later, and on other distributions that restrict unprivileged user namespaces, only a Chrome with an AppArmor profile (Google Chrome installed by its package) gets the namespaces its sandbox needs. Any other Chrome or Chromium (Playwright's, the one DGC downloaded) is then started inside a bubblewrap box, which lends them: Chrome's own sandbox runs in it and keeps every page contained, as on any other Linux (chrome://sandbox says "adequately sandboxed"). The box adds what a plain Chrome doesn't have: your home folder, with its keys and tokens, and DGC's environment variables are not in it (not even in bubblewrap's own process). It holds the system read-only, a fresh /tmp, the throwaway profile and Chrome's own files, and it ends with DGC.

bubblewrap has to be allowed to make user namespaces itself, and DGC checks that it is, not just that it is installed: a stock Ubuntu 24.04 has bubblewrap but no AppArmor profile that lets it. There, only a Chrome an admin installed can sandbox itself, so DGC downloads Google Chrome's package (apt checks it against Google's signing key) and the model asks you to install it once:

sudo apt update && sudo apt install ~/.dgc/browser/linux/google-chrome-stable_<version>_<arch>.deb

That puts Chrome in /opt/google/chrome, which Ubuntu's own AppArmor profile covers, and apt keeps it updated. The model is told not to work around it: no browser with --no-sandbox, and no change to browser_allow_unsandboxed. That setting stays yours: it runs the browser without a sandbox, so a page exploit is no longer contained.

Your own Chrome, signed in

#

For a task that needs your logins (your email, a dashboard you're signed in to), the browser can use the Chrome you're running, with signed_in: true. DGC opens a window of its own there and works in that one tab: it never reads or touches your other tabs, never reads cookies or storage, and closes its tab when the session ends. Pips don't use it; they have computers of their own.

Turn it on once in Chrome 144 or later: open chrome://inspect/#remote-debugging and allow remote debugging. Chrome then asks you every time DGC connects, and shows its "controlled by automated test software" banner while it is. DGC finds it through the DevToolsActivePort file Chrome writes in its profile folder (Google Chrome, Chrome Beta, Edge, Brave and Chromium, on Linux, macOS and Windows).

DGC in WSL uses the Chrome you run on Windows. It finds Chrome's profile on the Windows drive and connects straight to it when WSL shares Windows' network (mirrored networking); otherwise Windows PowerShell connects on the Windows side and passes the connection along. Chrome asks you the same way. If WSL interop is turned off in the distro and the network isn't mirrored, DGC says so and how to fix it.

Opening a site asks you first, in every mode, auto included: "Use your signed-in Chrome on mail.google.com?". Allow once is that visit; Always allow saves Browser(signed-in:https://mail.google.com), that site and nothing else. A site is its origin: scheme, host and port, written as Chrome writes it (http://bank.test:80/ and http://BANK.test./ are http://bank.test). A rule written for the throwaway browser never covers your signed-in one, but a deny does, checked against the page the tab is on: Browser(signed-in:*) in deny turns it off, Browser(signed-in:https://site/private*) covers that path, and an ask rule for a site makes clicks and typing there ask too.

Reading and acting happen only on a site you allowed. When a redirect, a click or the page itself takes the tab to another site, DGC reads nothing of it (each read is judged by the page it actually read), and opening that site asks you again. A click or keypress never carries an address. Password, card and one-time-code fields are never read out, alerts are dismissed rather than left blocking the tab, the console and network log start again with each page, and tabs DGC's page opened close with it. Plan mode never uses it.

Permissions

#

Every navigation goes through the same permission gate as any other tool, under the name Browser. Rules are keyed on the URL, so you can allow a host and nothing else:

"allow": ["Browser(https://staging.example.com/*)"]

There is deliberately no operation for running arbitrary JavaScript in the page. The snapshot is built by a fixed first-party script; a model cannot supply its own.

Untrusted by construction

#

Everything the browser returns is web page content, and it comes back labelled as untrusted — the same treatment web_fetch gets. Text on a page is evidence about that page, never an instruction to DGC.

Documentation