/deep-research
Conduct deep web research using the openbrowser-ai agent: decompose a query, investigate sub-questions across multiple sources, and produce a cited markdown report plus structured JSON under local_docs/research/. Trigger when the user asks to: research a topic, do a deep dive,
$ npx -y skills add billy-enrizky/openbrowser-ai --skill deep-research --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/deep-research
Context preview
The summary Claude sees to decide when to auto-load this skill.
Conduct deep web research using the openbrowser-ai agent: decompose a query, investigate sub-questions across multiple sources, and produce a cited markdown report plus structured JSON under local_docs/research/. Trigger when the user asks to: research a topic, do a deep dive,
SKILL.md
deep-research.SKILL.mdname: deep-research
description: |
Conduct deep web research using the openbrowser-ai agent: decompose a query, investigate sub-questions across multiple sources, and produce a cited markdown report plus structured JSON under local_docs/research/.
Trigger when the user asks to: research a topic, do a deep dive, investigate, gather evidence, compare options, write a literature review, build a briefing, or produce a cited report.
allowed-tools: Bash(openbrowser-ai:*) Bash(curl:*) Bash(uv:*) Bash(irm:*) Bash(mkdir:*) Bash(date:*) Read Write
Deep Research
Drive `openbrowser-ai` to investigate a topic across multiple web sources and produce a cited markdown report plus structured JSON. Two modes:
- **flat synthesis** (default) -- decompose query into 3-7 sub-questions, dispatch one parallel sub-agent per sub-question (each owns one tab), merge into one cited report.
- **drilldown** (auto-detected from prompt phrasing: "deep dive", "exhaustive", "recursive", "drilldown", "thorough") -- same as flat, plus a second wave of parallel sub-agents on findings flagged `needs_depth=true`. Hard cap depth=2, max 3 follow-up sub-agents per parent.
Output paths (relative to current project root):
- `local_docs/research/YYYY-MM-DD-<slug>.md`
- `local_docs/research/YYYY-MM-DD-<slug>.json`
**Architecture (mandatory):** the orchestrating Claude session (the one running this skill) MUST dispatch parallel sub-agents via `/dispatching-parallel-agents`, one sub-agent per sub-question. Each sub-agent owns exactly ONE tab. Sub-agents do not open additional tabs. The orchestrator merges per-agent findings into one report.
Why one tab per sub-agent and not `asyncio.gather` over tabs in a single `-c` call: a single Python coroutine driving N tabs through one daemon serializes navigation events at the CDP layer, contends for the LLM-extraction worker, and cannot make independent decisions about pagination or follow-up clicks per tab. Dispatching real Claude sub-agents (each with its own context window and its own browser tab) gives true parallelism, independent reasoning per tab, and isolates failures so one bad page doesn't poison the rest.
Hard rules:
- One sub-agent = one tab. Sub-agents must NOT call `navigate(url, new_tab=True)` to spawn additional tabs.
- All sub-agents share the same daemon (and so the same Chrome process). Tabs are isolated; navigation in one tab does not affect another.
- Each sub-agent writes its findings to its own JSON file under `local_docs/research/_partial/<slug>-NN.json`. The orchestrator reads and merges these.
- The orchestrator never drives tabs itself. It only plans, dispatches, merges, renders, verifies, cleans up.
If a first-wave sub-agent returns <2 findings, the orchestrator dispatches a Step 2b retry sub-agent with broader search strategy (alternative engines, query reformulation, lower thresholds). Still `-c`-only: the skill never calls `openbrowser-ai -p`.
Variables persist across `-c` calls in the daemon namespace.
**Session reuse:** Step 0 checks `openbrowser-ai daemon status`. If a daemon is already running (warm browser), the skill reuses it and operates in NEW tabs (never disturbs the user's existing tabs). If no daemon, the skill auto-starts one on first `-c` call.
Every factual claim in the report carries a footnote citation `[N]`. Verifier fails the run if uncited prose is found.
Setup
Verify install:
openbrowser-ai --help
Install if missing:
# macOS / Linux
curl -fsSL https://openbrowser.me/install.sh | sh
# Windows PowerShell
irm https://openbrowser.me/install.ps1 | iex
No LLM API key required. The skill drives the daemon via `openbrowser-ai -c` only, which executes raw CDP / JS through the daemon's Python namespace and never invokes a model. (The `-p` "prompt mode" of the CLI is a separate code path that loads `get_llm()` and requires an OpenAI / Anthropic / Google key per `cli.py:434-490`. This skill explicitly avoids `-p`.)
Set the headless env var so the daemon starts without a visible browser window (the default in `daemon/server.py` is already `headless: True`, but a user config file can override it; this env var wins over config):
export OPENBROWSER_HEADLESS=true
Prepare output dir at the project root (NOT user home):
mkdir -p local_docs/research
Workflow
Step 0 -- Session check
Enforce headless mode and detect whether a daemon is already running. If yes, reuse it (operate in NEW tabs only). If no, the next `-c` call auto-starts one.
`OPENBROWSER_HEADLESS=true` is set here so the daemon spawned by the first `-c` call inherits it, even if the user's config file sets `headless: false`. Already-running daemons are unaffected (their browser was opened at start time).
export OPENBROWSER_HEADLESS=true
if openbrowser-ai daemon status 2>&1 | grep -qi 'running\|listening\|pid'; then
echo "Reusing existing daemon -- will work in new tabs"
export DEEP_RESEARCH_REUSED=1
else
echo "No daemon running -- will start fresh headless session"
export DEEP_RESEARCH_REUSED=0
fiSnapshot existing tabs so cleanup leaves them untouched:
openbrowser-ai -c - <<'EOF'
state = await browser.get_browser_state_summary()
_preexisting_tab_ids = {t.target_id for t in state.tabs} if state.tabs else set()
print(f"Pre-existing tabs: {len(_preexisting_tab_ids)}")
EOFStep 1 -- Plan
Decompose the user query into sub-questions and pick the mode. Daemon namespace persists `_plan` across later `-c` calls.
openbrowser-ai -c - <<'EOF'
import json, re, datetime, os
QUERY = """<USER_QUERY>""" # paste exact user query here
# Daemon CWD often != shell CWD. Hard-code the absolute project root.
# Set this to the shell CWD at the start of the run; do NOT rely on os.getcwd().
PROJECT_ROOT = "<ABSOLUTE_PATH_TO_PROJECT_ROOT>" # e.g. /Users/foo/myproject
# Auto-detect mode
DRILL_RE = re.compile(r"\b(deep ?dive|exhaustive|recursive|drill ?down|thorough)\b
Read more
name: deep-research description: | Conduct deep web research using the openbrowser-ai agent: decompose a query, investigate sub-questions across multiple sources, and produce a cited markdown report plus structured JSON under local_docs/research/. Trigger when the user asks to: research a topic, do a deep dive, investigate, gather evidence, compare options, write a literature review, build a briefing, or produce a cited report. allowed-tools: Bash(openbrowser-ai:*) Bash(curl:*) Bash(uv:*) Bash(irm:*) Bash(mkdir:*) Bash(date:*) Read Write
Deep Research
Drive `openbrowser-ai` to investigate a topic across multiple web sources and produce a cited markdown report plus structured JSON. Two modes:
- **flat synthesis** (default) -- decompose query into 3-7 sub-questions, dispatch one parallel sub-agent per sub-question (each owns one tab), merge into one cited report.
- **drilldown** (auto-detected from prompt phrasing: "deep dive", "exhaustive", "recursive", "drilldown", "thorough") -- same as flat, plus a second wave of parallel sub-agents on findings flagged `needs_depth=true`. Hard cap depth=2, max 3 follow-up sub-agents per parent.
Output paths (relative to current project root):
- `local_docs/research/YYYY-MM-DD-<slug>.md`
- `local_docs/research/YYYY-MM-DD-<slug>.json`
**Architecture (mandatory):** the orchestrating Claude session (the one running this skill) MUST dispatch parallel sub-agents via `/dispatching-parallel-agents`, one sub-agent per sub-question. Each sub-agent owns exactly ONE tab. Sub-agents do not open additional tabs. The orchestrator merges per-agent findings into one report.
Why one tab per sub-agent and not `asyncio.gather` over tabs in a single `-c` call: a single Python coroutine driving N tabs through one daemon serializes navigation events at the CDP layer, contends for the LLM-extraction worker, and cannot make independent decisions about pagination or follow-up clicks per tab. Dispatching real Claude sub-agents (each with its own context window and its own browser tab) gives true parallelism, independent reasoning per tab, and isolates failures so one bad page doesn't poison the rest.
Hard rules:
- One sub-agent = one tab. Sub-agents must NOT call `navigate(url, new_tab=True)` to spawn additional tabs.
- All sub-agents share the same daemon (and so the same Chrome process). Tabs are isolated; navigation in one tab does not affect another.
- Each sub-agent writes its findings to its own JSON file under `local_docs/research/_partial/<slug>-NN.json`. The orchestrator reads and merges these.
- The orchestrator never drives tabs itself. It only plans, dispatches, merges, renders, verifies, cleans up.
If a first-wave sub-agent returns <2 findings, the orchestrator dispatches a Step 2b retry sub-agent with broader search strategy (alternative engines, query reformulation, lower thresholds). Still `-c`-only: the skill never calls `openbrowser-ai -p`.
Variables persist across `-c` calls in the daemon namespace.
**Session reuse:** Step 0 checks `openbrowser-ai daemon status`. If a daemon is already running (warm browser), the skill reuses it and operates in NEW tabs (never disturbs the user's existing tabs). If no daemon, the skill auto-starts one on first `-c` call.
Every factual claim in the report carries a footnote citation `[N]`. Verifier fails the run if uncited prose is found.
Setup
Verify install:
openbrowser-ai --help
Install if missing:
# macOS / Linux curl -fsSL https://openbrowser.me/install.sh | sh # Windows PowerShell irm https://openbrowser.me/install.ps1 | iex
No LLM API key required. The skill drives the daemon via `openbrowser-ai -c` only, which executes raw CDP / JS through the daemon's Python namespace and never invokes a model. (The `-p` "prompt mode" of the CLI is a separate code path that loads `get_llm()` and requires an OpenAI / Anthropic / Google key per `cli.py:434-490`. This skill explicitly avoids `-p`.)
Set the headless env var so the daemon starts without a visible browser window (the default in `daemon/server.py` is already `headless: True`, but a user config file can override it; this env var wins over config):
export OPENBROWSER_HEADLESS=true
Prepare output dir at the project root (NOT user home):
mkdir -p local_docs/research
Workflow
Step 0 -- Session check
Enforce headless mode and detect whether a daemon is already running. If yes, reuse it (operate in NEW tabs only). If no, the next `-c` call auto-starts one.
`OPENBROWSER_HEADLESS=true` is set here so the daemon spawned by the first `-c` call inherits it, even if the user's config file sets `headless: false`. Already-running daemons are unaffected (their browser was opened at start time).
export OPENBROWSER_HEADLESS=true
if openbrowser-ai daemon status 2>&1 | grep -qi 'running\|listening\|pid'; then
echo "Reusing existing daemon -- will work in new tabs"
export DEEP_RESEARCH_REUSED=1
else
echo "No daemon running -- will start fresh headless session"
export DEEP_RESEARCH_REUSED=0
fiSnapshot existing tabs so cleanup leaves them untouched:
openbrowser-ai -c - <<'EOF'
state = await browser.get_browser_state_summary()
_preexisting_tab_ids = {t.target_id for t in state.tabs} if state.tabs else set()
print(f"Pre-existing tabs: {len(_preexisting_tab_ids)}")
EOFStep 1 -- Plan
Decompose the user query into sub-questions and pick the mode. Daemon namespace persists `_plan` across later `-c` calls.
openbrowser-ai -c - <<'EOF' import json, re, datetime, os QUERY = """<USER_QUERY>""" # paste exact user query here # Daemon CWD often != shell CWD. Hard-code the absolute project root. # Set this to the shell CWD at the start of the run; do NOT rely on os.getcwd(). PROJECT_ROOT = "<ABSOLUTE_PATH_TO_PROJECT_ROOT>" # e.g. /Users/foo/myproject # Auto-detect mode DRILL_RE = re.compile(r"\b(deep ?dive|exhaustive|recursive|drill ?down|thorough)\b
OpenBrowser is a framework for intelligent browser automation. It combines direct CDP communication with a CodeAgent architecture, where the LLM writes Python code executed in a persistent namespace, to navigate, interact with, and extract information from web pages autonomously.
Repo: billy-enrizky/openbrowser-ai
Other skills on openbrowser-ai.
- /accessibility-audit
Audit web pages for accessibility issues, WCAG compliance, and screen reader compatibility. Trigger when the user asks to: check accessibility, run an a11y audit, test WCAG compliance, check screen reader support, audit ARIA attributes, verify keyboard navigation, find
Open skill - /e2e-testing
Test web applications end-to-end by simulating user interactions and verifying expected outcomes. Trigger when the user asks to: test a web app, verify a user flow, run end-to-end tests, QA a feature, check that a page works correctly, validate user journeys, or test a
Open skill - /file-download
Download files from websites, save PDFs, and read downloaded content. Trigger when the user asks to: download a file, save a PDF, export a document, fetch a file from a URL, grab a report, download and read a PDF, or save page content as a file.
Open skill - /form-filling
Fill out web forms, submit data, and handle login or registration flows. Trigger when the user asks to: fill a form, submit data on a website, log in to a site, register an account, complete a checkout, enter information into fields, or automate form submission.
Open skill - /page-analysis
Analyze web page content, structure, and layout to understand what a page contains and how it is organized. Trigger when the user asks to: analyze a page, understand page structure, inspect a website, summarize page content, examine page layout, review a web page, or describe
Open skill - /web-scraping
Extract structured data from websites, scrape page content, and collect information across multiple pages. Trigger when the user asks to: extract data from a website, scrape a page, collect information from URLs, pull content from web pages, gather data across multiple pages, or
Open skill

