Skip to content
ƒtsforgev0.58.0
38

Research in your Chrome

7 min read

web_fetch and web_browse see the public web as a logged-out stranger. The Chrome bridge lets the agent read pages in your browser instead, with your cookies and logins. It uses a small tsforge Chrome extension, and the agent’s tabs live in a “tsforge” tab group so you can always see which ones it is using.

Pair it with a local model and long research is free. Open a forum thread you’re logged into and say:

I've opened a forum thread in my active tab. Read the whole thread (every page) and save notes.

The agent adopts the tab and reads it chunk by chunk, following “next page” and “show more replies”. It appends findings to notes/<topic>.md as it goes, then summarises.

The extension enforces this itself. It does not rely on the agent behaving, because page text is written by strangers and may try to instruct the agent.

  • Clickable: real links, pagination, <summary>, and expanders (“Show 12 more replies”, aria-expanded toggles). Nothing else gets a click number.
  • Never clickable: anything in a form, inputs, editable areas, submit buttons, download links, and non-http links. Short labels that name an action (Reply, Like, Post, Delete, Log out, Subscribe, Add to cart…) and GET links that look like actions (/logout, ?action=delete, CSRF tokens) are also refused.
  • The click policy runs again on the live element at click time. A page that swaps a link for a form button after the read gets refused.
  • Links are followed by the extension (tabs.update), not by page scripts, so target=_blank can’t escape the group.
  • The agent may only act on tabs in the tsforge group. It can adopt one of your tabs only when that tab is active, or when you clicked the tsforge toolbar button on it.
  • Only http(s) pages. Private and loopback hosts (routers, intranet, the bridge itself) are blocked unless you set TSFORGE_BROWSER_ALLOW_PRIVATE=1.
  • There are no typing, posting or form-filling tools.

Remaining risk: injected text could still ask the agent to open a URL that carries something it read. Other tabs are unreadable unless you share them, which limits this, but review what a research session did if the pages were hostile.

  1. Build the extension (from a tsforge checkout):

    Terminal window
    bun run --cwd packages/chrome-extension build
  2. Open chrome://extensions, turn on Developer mode, click Load unpacked, and pick packages/chrome-extension/dist. The extension ID is fixed, so tsforge recognises it on any machine.

  3. Start tsforge with the bridge on, or flip Chrome browser in /config:

    Terminal window
    TSFORGE_BROWSER=1 tsforge # once; or set "browser": true in ~/.tsforge/config.json (or toggle it in /config) and it sticks

    The boot chip reads browser · waiting for the Chrome extension.

  4. Run /browser. It prints the pairing token, which is stored in ~/.tsforge/browser-token. Paste it into the extension’s options page (it opens on install) and save. The chip and /browser switch to connected within a few seconds.

The extension reconnects by itself whenever tsforge starts, and keeps retrying (with backoff) while tsforge isn’t running.

ToolWhat it does
browser_tabslist your tabs: which are in the tsforge group, which is active
browser_adoptmove your tab (active or shared) into the group
browser_open / browser_navigateopen a URL in a new group tab / load one (or go back)
browser_readthe page as markdown in ~6000-char chunks (chunk 2/7), with inline refs like [12 link: text](url) and [13 expand: Show more]
browser_clickclick a ref from the last read: follow a link, next page, expand replies
browser_scrollscroll (down, page, bottom) for infinite-scroll pages
browser_screenshotsave a PNG for read_image (only with a vision backend)
browser_closeclose a tab tsforge opened; your adopted tabs are only released
noteappend timestamped notes to notes/<topic>.md (append-only)

browser_read picks between an article view and the whole page on its own. It falls back to the whole page when the article extractor would drop most of the text, which is what happens with forum replies.

Research sessions are meant to run for hours, so a single model hiccup doesn’t end them:

  • Repetition loops. The retry is forced to make a tool call, at a higher temperature, and the repeated lines are removed from the history first. The loop budget counts only consecutive loops and starts over whenever a tool call succeeds. If three loops in a row get through, the context is compacted and tried once more before the session stops.
  • “Let me record it.” with no tool call. When there’s no gate, a reply that announces its next step without taking it gets a nudge to make the call. It is not treated as the final answer.
  • Compaction. The summary request is bounded. If it still fails, your requests are kept verbatim and the older tool output is dropped, so the context always shrinks.
  • No turn cap. Without a live gate a single message can run for days. Gated builds keep the 1000-turn backstop. TSFORGE_MAX_TURNS sets a cap anyway, or 0 for unlimited everywhere.
  • Saved as it goes. The session is saved every 40 turns, not only when a message finishes, so --continue picks up close to where a crash or reboot stopped it.
  • Data files. append adds records to a data file (.jsonl, CSV, logs) without an edit anchor. JSONL lines are checked, so a malformed record never gets written. Code and config files are refused.
  • No TypeScript rules on prose. The streaming TypeScript rules (like “no as cast”) stay off until the workspace has code.

For some sites tsforge knows a better way than reading rendered pages: it reads the site’s own structured data through your logged-in tab. Plugins are built in and reviewed like any other tsforge code. Reddit is the first.

They rely on one extra extension capability, page.fetch: a same-origin GET made from a tsforge tab, allowed only for hosts compiled into the extension. When you update tsforge, rebuild the extension and reload it in chrome://extensions. /browser shows outdated until the two versions match.

The bridge listens on 127.0.0.1:47823. Only the first tsforge process gets the port. A second session shows port 47823 in use and offers no browser tools. Set TSFORGE_BROWSER_PORT (and the same port in the extension options) to run one elsewhere.

Env varDefaultEffect
TSFORGE_BROWSERoffstart the bridge and offer the browser tools (=1)
TSFORGE_BROWSER_PORT47823bridge port (1024–65535)
TSFORGE_BROWSER_ALLOW_PRIVATEofflet the browser tools open private/loopback hosts (=1)

The browser tools are classified as network by the policy. They are allowed while planning (they can’t change your workspace) and denied in modes that deny network. note counts as a file edit, so it is withheld in plan mode.

→ Web access · Environment variables · Permissions & policy