Skip to content

[STG-2511] feat: add browse skills show and agent-facing --help header#2335

Merged
shrey150 merged 3 commits into
mainfrom
shrey/cli-skills-show
Jul 9, 2026
Merged

[STG-2511] feat: add browse skills show and agent-facing --help header#2335
shrey150 merged 3 commits into
mainfrom
shrey/cli-skills-show

Conversation

@shrey150

@shrey150 shrey150 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Why

Agents run browse inside sandboxes/harnesses we don't control, so they can't rely on a copied SKILL.md or a docs URL staying in sync with the installed CLI version. Serving the skill straight from the binary means the guidance is always version-matched to whatever browse the agent actually has.

This converges with the shape competitors have already landed on:

  • agent-browser: agent-browser skills get core --full + a top-of---help "Start here (for AI agents)" header
  • Modal: modal skills show
  • browser-use: skill show

What changed

  • Added browse skills show (packages/cli/src/commands/skills/show.ts), following the existing skills topic command style (BrowseCommand base, single-line description, examples). It resolves and prints the bundled SKILL.md via the same bundledCliSkillPath() helper skills install already uses (exported from packages/cli/src/lib/skills/install.ts), so path resolution is shared and works in both src and dist layouts. Reads the file synchronously and calls this.error(...) with a clear message + non-zero exit if it's missing/unreadable.
  • Added a custom oclif Help class (packages/cli/src/help.ts) that prepends a short agent-facing block before oclif's auto-generated VERSION/USAGE/DESCRIPTION/TOPICS/COMMANDS sections on root help only (browse --help and bare browse). Wired via "helpClass": "./dist/help.js" in packages/cli/package.json's oclif config. Per-command --help views (e.g. browse open --help) are unaffected.
  • Added a patch changeset — browse is in the changesets ignore list by default, but per team convention it still gets patch changesets for release-impacting CLI changes.
  • Tests: new packages/cli/tests/skills-show.test.ts (happy path + resolution from a different cwd), plus updates to packages/cli/tests/cli-surface.test.ts for the new skills show command help, the agent header appearing before USAGE on root help, and its absence on command help.

E2E Test Matrix

Command / flow Observed output Confidence / sufficiency
node packages/cli/bin/run.js skills show | head -20 Prints bundled SKILL.md frontmatter: name: browse, description: Use the browse CLI for..., # Browse CLI heading Proves the command reads and prints the real bundled skill from the local build, not a mock
node packages/cli/bin/run.js skills show | wc -lc 369 17221 (369 lines, 17221 bytes) Confirms full file is printed, not truncated
node packages/cli/bin/run.js --help | head -25 Output opens with Start here (for AI agents): / browse skills show / rationale block, then Unified Browserbase CLI..., VERSION, USAGE, TOPICS (incl. skills) Confirms header renders before the auto-generated sections on --help
node packages/cli/bin/run.js | head -25 Same header block, same ordering, for bare browse with no args Confirms bare invocation (not just --help) also gets the header
node packages/cli/bin/run.js open --help | head -15 Standard command help (Open a URL in a browse driver session., USAGE, ARGUMENTS, FLAGS) with no agent header Confirms per-command help is unaffected
cd /tmp && node <worktree>/packages/cli/bin/run.js skills show | head -3 Same SKILL.md frontmatter, run from an unrelated cwd Confirms path resolution is relative to the module file, not process.cwd() — required for the dist-layout published package
pnpm test:cli (vitest) Test Files 24 passed (24), Tests 349 passed (349) Full existing CLI suite plus new/updated tests all green — no regressions
pnpm lint (prettier + eslint + tsc) All three steps pass with no output/errors Static checks clean

Linear

https://linear.app/browserbase/issue/STG-2511/add-browse-skills-show-agent-facing-help-header

🤖 Generated with Claude Code


Summary by cubic

Adds browse skills show to print the bundled SKILL.md for version-matched guidance, and adds an agent-facing header on root help pointing to it. Addresses STG-2511.

  • New Features

    • browse skills show prints the bundled skill via bundledCliSkillPath() and, on error, uses fail() (exit 1 with resultCode: "skill_show_missing").
    • Root help (browse --help and bare browse) prepends a short “Start here” header; per-command help is unchanged. Wired via helpClass in packages/cli/package.json.
    • Exported bundledCliSkillPath() so path resolution works in both src and dist.
  • Refactors

    • Use fs/promises.readFile for async skill file reads.

Written for commit 2a74053. Summary will update on new commits.

Review in cubic

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a74053

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.
Architecture diagram
sequenceDiagram
    participant Agent as AI Agent
    participant CLI as browse CLI (oclif)
    participant Help as BrowseHelp (custom Help class)
    participant CmdShow as SkillsShow command
    participant FS as Node.js File System
    participant BundledSkill as bundled SKILL.md

    Note over Agent,BundledSkill: Agent-Facing Root Help Flow (browse --help / browse)
    Agent->>CLI: browse --help (or bare browse)
    CLI->>Help: showRootHelp()
    Help->>Help: log AGENT_HEADER ("Start here (for AI agents):…")
    Help->>CLI: super.showRootHelp() – auto-generated VERSION, USAGE, TOPICS, COMMANDS
    CLI-->>Agent: Full help output with agent header prepended

    Note over Agent,BundledSkill: Per-Command Help Flow (unaffected)
    Agent->>CLI: browse open --help
    CLI->>CLI: default oclif command help
    CLI-->>Agent: Standard command help (no agent header)

    Note over Agent,BundledSkill: Skills Show Flow
    Agent->>CLI: browse skills show
    CLI->>CmdShow: run()
    CmdShow->>CmdShow: bundledCliSkillPath() → path to skills/browse/ directory
    CmdShow->>FS: join(path, "SKILL.md")
    FS-->>CmdShow: resolved absolute path to SKILL.md

    alt Success: SKILL.md exists and is readable
        CmdShow->>FS: readFileSync(skillMdPath, "utf8")
        FS-->>CmdShow: file contents (markdown string)
        CmdShow->>CmdShow: this.log(contents) – print to stdout
        CmdShow-->>CLI: exit code 0
        CLI-->>Agent: Full SKILL.md content printed
    else Error: SKILL.md missing or unreadable
        CmdShow->>FS: readFileSync(skillMdPath, "utf8")
        FS-->>CmdShow: error (ENOENT, EACCES, etc.)
        CmdShow->>CmdShow: this.error("Could not read…") – non-zero exit
        CmdShow-->>CLI: exit code non-zero (oclif handles formatted error display)
        CLI-->>Agent: Error message to stderr
    end

    Note over Agent,FS: Path Resolution (handles both src and dist layouts)
    CmdShow->>CmdShow: packageRoot() – based on __dirname of module file
    CmdShow->>FS: join(packageRoot(), "skills", "browse")
    FS-->>CmdShow: path → works from any process.cwd()
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/cli/tests/skills-show.test.ts
Comment thread packages/cli/tests/skills-show.test.ts Outdated
Use the project's fail() error convention (exit code 1) instead of
oclif's default this.error() (exit 2), make the different-cwd test
platform-agnostic via os.tmpdir(), and add a missing-SKILL.md
error-path test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread packages/cli/src/commands/skills/show.ts Outdated
shrey150 added a commit that referenced this pull request Jul 9, 2026
…idance (#2336)

## Summary

A 3-provider bare-loop smoke test (E2B/Modal/Vercel, real sandboxes,
local CLI build) surfaced two systematic gaps in the bundled `browse`
skill (`packages/cli/skills/browse/SKILL.md`):

1. **3/3 agents ignored the pre-wired `BROWSE_SESSION` env var** and
self-named sessions via `--session <name>` (one run orphaned a
Browserbase session as a result). The skill taught named `--session`
usage but never said "if `BROWSE_SESSION` is already set, every command
already targets that session — don't pass `--session` or invent a new
name." This defeats the sandbox-template env-steering pattern
(`BROWSERBASE_API_KEY` + `BROWSE_SESSION=<name>` → flagless remote
commands).
2. **2/3 agents tried `--local` first inside Chrome-less containers**,
hit "No Chrome or Chromium found", then recovered on retry. The skill
lacked explicit guidance that `--local` requires local Chrome/Chromium
and that containers/CI/sandboxes without Chrome should go straight to
`--remote`.

## What changed

Two minimal additions to `packages/cli/skills/browse/SKILL.md`, both in
the existing "Browser Target Selection" section (the section that
already teaches local/remote choice and named-session usage) — no
restructuring, no new sections:

```
`--local` requires Chrome or Chromium already installed on the machine. In containers, CI, and sandboxes with no browser installed, use `--remote` instead of `--local`. If `--local` fails with "No Chrome or Chromium found" and `BROWSERBASE_API_KEY` is set, switch to `--remote` — do not retry `--local`.
```

```
If `BROWSE_SESSION` is already set in the environment, every command already targets that session — do not pass `--session` or invent a new name. An explicit `--session <name>` always overrides `BROWSE_SESSION` for that command, so only pass it to deliberately target a different session.
```

Verified the precedence claim against the actual implementation before
writing the wording (not just trusting the smoke-test writeup):

- `packages/cli/src/lib/driver/flags.ts:73` — `export function
sessionName(value?: string): string { return value ??
process.env.BROWSE_SESSION ?? "default"; }`. An explicit `--session`
flag always wins over `BROWSE_SESSION`; when omitted, `BROWSE_SESSION`
becomes the effective session; with neither, it's `"default"`.
- `packages/cli/src/lib/driver/command-cli.ts:75` —
`runDriverCommandFromFlags` calls `sessionName(flags.session)` for every
driver command, so this precedence applies uniformly across `open`,
`snapshot`, `click`, `stop`, etc.
- `packages/cli/src/lib/driver/remote.ts:130` — exact no-Chrome error
string is `"No Chrome or Chromium found on this machine. Install one
(Linux: apt install chromium · macOS: brew install --cask google-chrome,
or Chromium with CHROME_PATH set), attach to a running browser with
--cdp <port>, or set BROWSERBASE_API_KEY to use a remote browser."`

## No changeset

This is a skill-text-only change (`SKILL.md`), same category as PR #2329
(skill-text-only fix, no changeset). The updated text ships with the
next `browse` release — a release is already queued by #2335's changeset
— and is consumed at runtime by the evals harness added in #2334.

## E2E Test Matrix

| Command / flow | Observed output | Confidence / sufficiency |
| --- | --- | --- |
| `pnpm install && pnpm turbo run build --filter=browse` (worktree,
local build) | `Tasks: 4 successful, 4 total` | Proves the local CLI
build succeeds with the change in place; no build regressions from a
docs-only edit. |
| Resolve `bundledCliSkillPath()` from the compiled
`dist/lib/skills/install.js` via `require.resolve` + manual path join
(no `skills show` command exists on `main` yet — it ships in PR #2335,
unmerged at time of this PR) | `resolved bundledCliSkillPath:
<worktree>/packages/cli/skills/browse` | Proves the exact file `browse
skills install` resolves to at runtime is the file this PR edits, not a
stale copy. |
| `grep -n "already set in the environment\|do not retry"
packages/cli/skills/browse/SKILL.md` | `76:If \`BROWSE_SESSION\` is
already set in the environment, every command already targets that
session...` `68:...If \`--local\` fails with "No Chrome or Chromium
found"...do not retry \`--local\`.` | Confirms the exact new lines are
present at the bundled path resolved above — the new guidance flows
through to the real command path. |
| `node bin/run.js skills install --help` | Prints usage for `browse
skills install` (no side effects triggered — did not run the real
install, which mutates the global `~/.agents/skills` pool via `npx
skills add --global`) | Confirms the command is wired and reachable;
deliberately did not execute the real install to avoid mutating local
global skill state outside this change's scope. |
| `pnpm test:cli` (vitest, worktree build) | `Test Files 23 passed (23)`
/ `Tests 344 passed (344)` | Full existing CLI test suite still green;
this change touches no runtime code. |
| `pnpm eslint .` | No output / exit 0 | Lint clean. |
| `pnpm format:check` (prettier) | `All matched files use Prettier code
style!` | Formatting clean, including the edited Markdown. |
| `tsc --noEmit -p tsconfig.json` | No output / exit 0 | Typecheck clean
(unaffected by a Markdown-only change, included for completeness). |

## Related

- Linear:
https://linear.app/browserbase/issue/STG-2513/browse-skill-document-browse-session-precedence-container-remote
- Evidence source: 3-provider (E2B/Modal/Vercel) bare-loop smoke test,
2026-07-09
- Text will be exercised by the evals harness landing in #2334
- Release vehicle: changeset already queued in #2335

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Clarifies the `browse` skill docs to prevent session misrouting and
container failures by documenting `BROWSE_SESSION` precedence and when
to use `--remote` instead of `--local`. Addresses Linear STG-2513.

- **Bug Fixes**
- Documented that if `BROWSE_SESSION` is set, commands target that
session; only pass `--session` to override (precedence: `--session` >
`BROWSE_SESSION` > `default`).
- Stated that `--local` requires Chrome/Chromium; in
containers/CI/sandboxes use `--remote`. If you see "No Chrome or
Chromium found," switch to `--remote` instead of retrying `--local`.

<sup>Written for commit 829ff7b.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2336?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@shrey150 shrey150 merged commit 19f9f5a into main Jul 9, 2026
36 checks passed
shrey150 added a commit that referenced this pull request Jul 9, 2026
… 22 (#2344)

## Why

Every stagehand release since 2026-07-09 18:52 UTC is broken. The
Release workflow's "Update npm for Trusted Publishing" step runs `npm
install -g npm@latest`; npm@12.0.0 was published 2026-07-08 21:06 UTC
and became `latest`, and it requires node `^22.22.2 || ^24.15.0 || >=26`
— the release job runs node 20, so the step dies with `EBADENGINE`
before versioning even starts.

- Last green Release: 2026-07-08 17:50 UTC
- First failure: 2026-07-09 18:52 UTC
([run](https://github.com/browserbase/stagehand/actions/runs/29043380120)
— `npm error notsup Required: {"node":"^22.22.2 || ^24.15.0 ||
>=26.0.0"} / Actual: {"npm":"10.8.2","node":"v20.20.2"}`)
- This currently blocks the browse release carrying `browse skills show`
(#2335) and the browse-skill guidance fixes (#2336), whose changeset is
pending on main.

## What

Pin the step to `npm@11` (currently 11.18.0): supports node >= 20.17
**and** Trusted Publishing/OIDC (needs npm >= 11.5.1) — the reason this
step exists, since node 20 bundles npm 10.8.2 which predates it. One
line + a comment stating the constraint.

The alternative (bump the job to node 22/24 and keep `@latest`) changes
the entire release build environment (SEA binaries, prebuilds) and isn't
hotfix material; it can be considered separately.

## Validation

| Command / flow | Observed output | Confidence / sufficiency |
| --- | --- | --- |
| Failure-log inspection of both failed Release runs | `EBADENGINE ...
npm@12.0.0 ... Required node ^22.22.2 \|\| ^24.15.0 \|\| >=26 / Actual
node v20.20.2`, exit 1 at the pinned step | Proves the failure mechanism
exactly at this line |
| `curl registry.npmjs.org/npm` → dist-tags + publish times | `latest =
12.0.0`, published 2026-07-08T21:06Z — inside the 07-08 17:50 → 07-09
18:52 breakage window | Proves `@latest` drift is the trigger; nothing
repo-side changed |
| npm 11.x engine range vs job node | npm 11.18.0 supports node >=
20.17; job runs 20.20.2 | Proves the pin resolves the engine conflict
while keeping Trusted Publishing (>= 11.5.1) |
| Real release exercise | Not possible pre-merge — the Release workflow
only runs from main. Merging this PR pushes to main, which itself
triggers Release with the pending browse changeset — that run is the
live verification | The one path that cannot be tested from a branch |

Linear: STG-2520

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Pin `npm` in the Release workflow to `11.18.0` to avoid `npm@12`
requiring Node >=22. Restores releases on Node 20 and keeps Trusted
Publishing (Linear: STG-2520).

<sup>Written for commit 90a6d71.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2344?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants