Three things changed this week for people who run AIHawk's browser from an assistant.
Claude Code and Codex take it as a plugin, Gemini CLI as an extension. Two lines for the first two, one for Gemini, and the setup skill comes along, so the assistant knows what to do when the browser engine is not there yet:
claude plugin marketplace add feder-cr/AIHawk
claude plugin install aihawk@feder-crcodex plugin marketplace add feder-cr/AIHawk
codex plugin add aihawk@feder-crgemini extensions install https://github.com/feder-cr/AIHawkThe engine downloads itself. Until 0.68 you ran uvx invisible-playwright fetch first, or the first browsing call sat there for minutes. Now the server starts the download the moment the client connects, and if you ask for a browser before it is done, browser_open answers with how far along it is and asks to be called again. No call waits on a transfer. uvx invisible-playwright fetch still exists, for watching the download in a terminal or redoing a failed one.
Gemini CLI installs this release from the archives attached below instead of cloning the repository. The wiki has a page per client: Claude Code, Codex, Gemini CLI, Claude Desktop, Cursor, Cline.
Two pages the README's commands were pointing at without a destination:
"Running AIHawk's browser from Codex" and "from Gemini CLI", in the shape of
the Claude Code one, listed in the guide and the index.
Gemini CLI installs the extension from the Latest release when it carries an
asset named for the platform, and clones the whole repository otherwise -
which is what it did on 2026-09-21, twelve megabytes of docs, tests and source
to deliver a manifest and a skill. Our releases carry two MCP bundles, so the
single-asset fallback never applies. scripts/pack_extension.py builds three
identical archives, one per platform name Gemini matches (darwin, linux,
win32), 22 KB each, listed against an allowed set before they ship, and the
bundle job attaches them beside the bundles. Measured with the packer; the
install from a release is measured at the first tag that carries them.
browser_open's first answer on a cold cache read "downloading now: 0 MB so
far", because the core says "downloading" before the first byte and before it
knows the size. That instant now reads as the download starting.
The test suite left two empty directories in TEMP per run, made at import
where no fixture teardown reaches; this machine had eighty-six. Removed at
exit, the throwaway cache last, after the guard has read it.
0.69.1, because engine.py changed.