chromeflow v0.9.5: distribution-sprint retro fixes — 16 changes
Anti-bot detection, closed-shadow piercing, hidden-element ranking, and the
ergonomics gaps the May 13 retro hit hardest. Scope ruthlessly trimmed —
rejected magic helpers (submit_form_or_highlight, fill_form_steps,
oauth_device_flow, chromeflow_doctor) in favour of flags on existing tools.
Submit / click detection:
- click_element(expect_submit=true): broad anti-bot detector. Watches 4s for
URL change / role=alert / data-sonner-toast / .toast / aria-live / modal /
[role=dialog] appearance. Returns success=false with "submit silently
rejected" when no signal — replaces the Reddit/X/GitHub-device-flow guesswork. - click_element hidden-element refusal now surfaces the next visible candidate
in the error message so callers can retry without rebuilding nth math. - findClickable ranks visible candidates above hidden — a 0×0 flair-dropdown
match no longer claims nth=1 over the actually-visible submit button. - No-until SPA-pushState window bumped 600ms → 1500ms so React-router
navigations land in after_url instead of being missed.
Closed shadow DOM:
- shadow.ts introduces getShadowRoot() using chrome.dom.openOrClosedShadowRoot
(content-script-only API previously unused by the codebase). click_element,
fill_input (textHint mode), find_text, list_frames, wait_for(selector),
wait_for(text), and the background.ts wait_for_selector all transparently
pierce CLOSED roots now. Removes the deepFind-in-execute_script ceremony
for Reddit faceplate-* / r-post-form-submit-button and similar.
Discovery / hidden-element fixes:
- find_text isClickable walks ancestors for [hidden] / display:none /
visibility:hidden / aria-hidden=true; hidden flair-dropdown items no
longer report clickable=true. - list_frames now uses queryAllDeep so iframes nested inside shadow hosts
(e.g. Reddit chat composer) are discoverable. - get_form_fields response now includes captcha (reCAPTCHA / Turnstile /
hCaptcha + sitekey) and oauth_indicators ("Continue with X" button text)
so the agent knows upfront when synthetic submits will silently fail.
Network / disk ergonomics:
- fetch_url default max_bytes 2MB → 100,000 (≈25K tokens, the MCP transport
ceiling) — replaces the "result exceeds maximum allowed tokens" overflow. - fetch_url(to_file="/path") writes the FULL response body to disk and
returns metadata-only — clean alternative to pagination for large payloads. - take_screenshot default behaviour is now "auto-file when >500KB base64":
large screenshots no longer blow the agent context. inline="always" /
"never" override.
Tab management:
- close_tab(query?) and close_other_tabs(keep_query?): trivial chrome.tabs
.remove wrappers. End-of-sprint cleanup without rebuilding the matcher. - inspect_request_headers(new_tab=true) (default) opens a background tab for
the CDP attach so the user's active tab keeps form / scroll state.
Reactivity / discoverability:
- wait_for_click captures the actual click target (tag, text, selector, x/y)
and returns it — handoffs that diverge from the highlight are now visible. - wait_for(change_in=…, max_chars=N) (default 1000) — chat-style mutations
no longer dump 5KB of context. - fill_input selector-mode error responses now append the workaround pattern
(click_element + type_text / execute_script with React-aware setter) so a
silent rejection doesn't require docs round-trips. - execute_script description spells out MAIN-world execution + the CSP
fallback to fetch_url.
Docs:
- CLAUDE.md HARD RULE 4: anti-bot submit ceiling on social/auth platforms.
- CLAUDE.md privileged-context section updated for to_file / 100K default.
- CLAUDE.md tabs section adds close_tab / close_other_tabs guidance.
- CLAUDE.md complex-forms section flags captcha + OAuth surfacing.
- CLAUDE.md mirrored to both Claude (skills/) and Codex (skills-codex/)
SKILL.md files.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com