Skip to content

feat(cli): add close to shut tabs Browser Hand opened - #32

Open
autohub-claude[bot] wants to merge 2 commits into
mainfrom
agent/kernel-worker/d5f29f3b
Open

autohub-claude[bot] wants to merge 2 commits into
mainfrom
agent/kernel-worker/d5f29f3b

Conversation

@autohub-claude

@autohub-claude autohub-claude Bot commented Nov 4, 2026

Copy link
Copy Markdown

Summary

Adds browser-hand close, a user-facing way to close a tab through the existing Target.closeTarget path. By default it only closes tabs Browser Hand opened, never one the user already had open.

Closes #31

Changes

  • CLI (cli-js/src/cli.js, cli-js/src/tool.js): new close operation. It needs an explicit selector (--page-name, --query, --target-*, or --group-title) and never falls back to the active tab. A selector that matches several tabs is refused unless --all is passed. A lone --group-title closes the whole Browser Hand tab group. Returns { closed, targetId, url, title }.
  • Safety default: only tabs Browser Hand opened are closed. A tab the user had open is refused, or skipped and listed under skipped for --all / --group-title. --include-user-tabs is the explicit override and sends force: true on Target.closeTarget.
  • Relay (relay/src/relay.ts): stamps browserHandOwned on Target.getTargets entries (created by the relay and not adopted from an existing page), and honors force on Target.closeTarget for the override. Playwright never sends force, so its behavior is unchanged.
  • Extension (extension/services/TabManager.ts, extension/utils/types.ts): stamps groupTitle on listed targets so --group-title can find a session's tabs.
  • Honest result: closed is only true once the tab has left Chrome's live list, because the relay answers a close of an adopted tab with success without closing it. closed: false carries an error and the CLI exits 1.
  • Docs: README "Drive a tab", skills/browser-hand/SKILL.md, skills/browser-hand/references/extension-cli.md.
  • Tests: cli-js/test/close-tab.test.js (selection, ambiguity, ownership, fail-closed, result shape) and extension/__tests__/TabManager.test.ts (group titles).

Test plan

  • cd cli-js && node --test "test/*.test.js": 183 pass, 0 fail
  • cd extension && npm test: 56 pass, 0 fail
  • npm run build:relay: clean
  • npm run doctor and a live Chrome open then close round trip: not run in this branch's finalizer pass. Needs a rebuilt relay and a reloaded unpacked extension, so a reviewer with a live profile should run it before merge.
  • Upstream path: not applicable, daemon/ and cli/ are untouched

Notes for reviewers

  • Needs a relay restart and extension reload after upgrading. Ownership is tracked in the relay's memory. A relay that predates this change reports no browserHandOwned field, and close fails closed with a clear error instead of guessing.
  • Ownership is lost on a relay restart. Tabs opened before the restart then read as user tabs and are refused without --include-user-tabs. This errs toward not closing.
  • Adopted tabs. When open adopts an already-open tab on the same URL, that tab counts as a user tab. This holds even for a --page-name bound to it.
  • Last tab. Closing the last tab of the last window can quit Chrome and drop the relay socket. The CLI reports that case rather than claiming success.
  • Focus policy: no change. close never focuses a tab or window.
  • Branched from main, not from the PR feat: target the connected browser, not Chrome by default (#29) #30 branch.

Implementation harness: Claude Code (claude-sonnet-5-5) via the AutoHub kernel worker. GitHub identity: autohub-claude GitHub App.

🤖 Generated with Claude Code

`browser-hand close` closes a tab through the existing Target.closeTarget
path. It needs an explicit selector (--page-name, --query, --target-*, or
--group-title) and never falls back to the active tab. A selector that
matches several tabs is refused unless --all is passed; a lone
--group-title closes the whole Browser Hand tab group.

Safety default: only tabs Browser Hand opened are closed. The relay now
stamps `browserHandOwned` on Target.getTargets entries (created by the
relay and not adopted from an existing page), and the extension stamps
`groupTitle`. A tab the user had open is refused, or skipped and listed
under `skipped` for --all / --group-title, unless --include-user-tabs is
given. A relay that predates ownership tracking fails closed.

The result is { closed, targetId, url, title }. `closed` is only true once
the tab has left Chrome's live list, because the relay answers a close of
an adopted tab with success without closing it. Multi-tab closes return a
`tabs` list plus `skipped`.

Closes #31

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@autohub-claude
autohub-claude Bot requested a review from jack-arturo as a code owner November 4, 2026 02:41
@autohub-claude autohub-claude Bot added babysit:active Babysit agent is actively working this PR babysit:waiting-codex 👀 Codex reviewing current head and removed babysit:active Babysit agent is actively working this PR labels Nov 4, 2026
@jack-arturo

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-04T02:48:24.033408Z dc457ee Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dc457ee61b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cli-js/src/tool.js Resolved
@autohub-claude autohub-claude Bot added babysit:active Babysit agent is actively working this PR and removed babysit:waiting-codex 👀 Codex reviewing current head labels Nov 4, 2026
`close` selected tabs through the http(s)-only inventory filter, but the
extension also lists about:blank and file:// pages. A Browser Hand tab that
had not navigated yet was refused by `--target-id`, and `--group-title` on
a mixed group dropped those tabs before ownership was checked. They were
neither closed nor listed under `skipped`, and `closed` still came back true.

planCloseTargets now selects from every controllable page target.
tabs, snapshot and click keep their http(s)-only filtering.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@autohub-claude autohub-claude Bot added babysit:waiting-ci Babysit waiting for CI checks on current head and removed babysit:active Babysit agent is actively working this PR labels Nov 4, 2026
@autohub-claude

autohub-claude Bot commented Nov 4, 2026

Copy link
Copy Markdown
Author

Babysit stopped — ci. The code and the review loop have converged, but CI cannot go green on this branch for a reason this PR does not cause.

What fails. Daemon (TypeScript + Tests) (ubuntu-latest) dies at pnpm exec playwright install chromium with Playwright does not support chromium on ubuntu26.04-x64. GitHub's ubuntu-latest image has rolled to Ubuntu 26.04. tsc --noEmit passed, and the daemon vitest step was skipped, so the daemon tests did not run on this head. The Windows daemon job shows cancelled, not passed: the matrix's default fail-fast cancels it when the Ubuntu job dies. Re-running reproduces it (same failure on dc457ee and 1d06543).

Why it is unrelated. No file under daemon/ or .github/ is touched here, and main was green on this same base commit (419786a, 2026-10-22), before the image rolled.

Where the fix already is. #30 changes .github/workflows/ci.yml to pin the matrix to ubuntu-24.04 with fail-fast: false, and its daemon check passes. I did not copy that hunk into this PR: it is outside #32's scope, and this branch was deliberately cut from main rather than #30. Note that #30 is a feature PR, not a dedicated tracker for this CI problem.

Passing at 1d06543: Format Checks, Build Daemon Bundles, CLI (Rust) on Ubuntu and Windows. Run locally: cli-js 187/187, extension 56/56, npm run build:relay clean.

Review state. Codex reviewed dc457ee and raised one P2 (close ignored about:blank and file:// tabs). It is fixed in 1d06543, with the thread replied to and resolved, and 0 threads are open. Codex posted nothing on 1d06543 within the 10-minute grace window. That is an auto-review skip, not a Codex pass. The PR is mergeable and not a draft, and Closes #31 is linked.

Decision for a human: land the ubuntu-24.04 pin first (merge #30, or split that hunk into its own PR), then update this branch and re-run CI. The agent did not merge anything.

Verified head: 1d06543cd1a51f90b73dbbf8f0b07abc3dbfd46c.

Agent: Claude Code (claude-sonnet-5-5) via the AutoHub kernel worker; GitHub identity: autohub-claude GitHub App.

@autohub-claude autohub-claude Bot added babysit:blocked Babysit stopped; unresolved blocker needs human and removed babysit:waiting-ci Babysit waiting for CI checks on current head labels Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

babysit:blocked Babysit stopped; unresolved blocker needs human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CLI close-tab command

1 participant