Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gflow",
"version": "0.71.1",
"version": "0.72.0",
"description": "Reusable development and operations workflows for gflow-cli",
"author": {
"name": "Flavio Oliva",
Expand Down
5 changes: 3 additions & 2 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,9 @@
# GFLOW_CLI_UI_MODE=auto

# Which Flow frontend gflow drives (#639). auto (default): flow.google.com is the
# default host for what it can serve today (video t2v, and video i2v from a local
# --initial-frame, with --project) on every
# default host for what it can serve today (video t2v; video i2v from a local
# --initial-frame; video r2v from local --ref files; image t2i; and image i2i from
# local files — all with --project) on every
# account; requests it cannot serve yet keep the labs driver on an unmoved
# account, and a moved account gets the migrated composer for everything ported.
# flow.google.com: force the migrated composer for everything.
Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ by construction, so Codex / Cursor / Aider / `agy` read exactly what Claude Code

## Project at a glance

- Unofficial Python CLI for [Google Flow](https://labs.google/fx/tools/flow) — drives Veo (image-to-video, text-to-video) and Imagen (text-to-image) generations from the terminal by reverse-engineering Flow's private REST API at `aisandbox-pa.googleapis.com` — and, for accounts Google has moved to `flow.google.com`, that frontend's `batchexecute` wire (text-to-video, image-to-video from a local `--initial-frame`, and reference-to-video from local `--ref` files, today; `GFLOW_CLI_FLOW_HOST`).
- Unofficial Python CLI for [Google Flow](https://labs.google/fx/tools/flow) — drives Veo (image-to-video, text-to-video) and Imagen (text-to-image) generations from the terminal by reverse-engineering Flow's private REST API at `aisandbox-pa.googleapis.com` — and, for accounts Google has moved to `flow.google.com`, that frontend's `batchexecute` wire (text-to-video, image-to-video from a local `--initial-frame`, reference-to-video from local `--ref` files, and text-to-image/local-file image-to-image, today; `GFLOW_CLI_FLOW_HOST`).
- Python 3.11+ · `uv`-managed · `hatchling` builds · Playwright Chromium transport · `pyright` strict · `ruff` · `pytest`.
- Single-package modular monolith. Top-level modules under `src/gflow_cli/`: `api/`, `auth/`, `data/`, `mcp/`, `services/`, `tools/`, `ui/`, `worker/`, `browser_manager.py`, `cli.py`, `_cli_helpers.py`, `diagnostics.py`, `json_output.py`, `media.py`, `profile_lease.py`, `redaction.py`, `storage.py`, `winsec.py`, `cli_project.py`, `cli_character.py`, `cli_credits.py`, `cli_data.py`, `cli_image.py`, `cli_instructions.py`, `cli_models.py`, `cli_movie.py`, `cli_run.py`, `cli_scene.py`, `cli_tools.py`, `cli_video.py`, `chain.py`, `chain_manifest.py`, `cli_doctor.py`, `cli_update.py`, `composition.py`, `config.py`, `errors.py`, `file_integrity.py`, `flow_selectors/`, `update_check.py`, `exceptions.py`, `image_batch.py`, `movie_manifest.py`, `observability.py`, `paths.py`, `profile_store.py`.
- Command surface: `gflow auth`, `gflow credits` (user/list — read-only Veo balance), `gflow image` (t2i/i2i/batch/upload/upscale), `gflow video` (t2v/i2v/r2v/chain/extend — `extend` continues an existing clip past Flow's 8s ceiling, server-seeded from the source so the join is continuous; no `batch` subcommand; the nonfunctional stub was removed, loop `gflow video t2v`/`i2v` from the shell for multi-clip runs), `gflow character` (create/list/show/rm/voices — reusable project-scoped Flow Character entities), `gflow scene` (create/show — Add Clip / Scenes, with `create --output` for credit-free server-side extended video), `gflow instructions` (persistent Agent-Mode brief cards — add/list/enable/disable/rm/apply/toggle-mode, credits-free, `--project` required), `gflow movie` (run/template — multi-scene manifest pipeline), `gflow tools` (list/show/run — prompt-rewriting tools, also `--tool` on generation commands), `gflow data` (catalog queries), `gflow doctor` (read-only pre-flight diagnostic, exit 33 = findings present), `gflow update` (self-update through the installer that put it here — uv tool / pipx / pip; `--check` only reports; source installs refused, exit 11; deliberately no MCP twin), `gflow project`, `gflow models`, `gflow run`, `gflow mcp` (run/setup — stdio MCP server), and `gflow serve` (Streamable HTTP at `/mcp`; `--transport sse` is deprecated).
- Works with any Google account that has Flow access. All generations bill against the user's own Google account.

## Headed-browser dependency (architectural reality)

gflow-cli currently drives Flow via a **real Chrome session managed by Playwright** — `ui_automation` transport. Google's auth + reCAPTCHA stack rejects Playwright's bundled Chromium and most headless approaches. This is the project's defining trade-off:
gflow-cli currently drives Flow via a **real Chrome session managed by Playwright** — `ui_automation` transport. Google's auth + reCAPTCHA stack rejects browsers that advertise automation, and most headless approaches. This is the project's defining trade-off:

- ✅ Works end-to-end against live Google accounts.
- ❌ Requires a saved Chrome profile, a display server for one-time login, and ~150 MB for Chromium.
Expand Down
87 changes: 86 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,90 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.72.0] — 2026-09-09

### Added

- **`gflow image t2i` and local-file `i2i` now run on migrated `flow.google.com`
accounts** ([#639](https://github.com/ffroliva/gflow-cli/issues/639)). The Angular
composer binds Image mode, Nano Banana 2 / Pro, the four aspect ratios measured on that
host (16:9, 4:3, 1:1, 9:16) and counts 1–4,
then observes the page-owned `ogiZ0b` `batchexecute` reply and returns the same
`GeneratedImage` contract as the labs driver. Local references reuse the measured
`maseQ` upload + mention path and are verified in the outgoing submit body before the
result is trusted. The migrated page owns reCAPTCHA minting, avoiding the root-grid
`RecaptchaError`; unsupported UUID/entity/instruction/Imagen-4 forms still fail before
submit rather than silently dropping options.

- **`gflow image batch` is refused on the migrated host instead of failing as selector
drift** ([#639](https://github.com/ffroliva/gflow-cli/issues/639)). The batch path
drives labs selectors only; it now raises `FlowHostMigratedError` (exit 36) before any
submit, rather than running those selectors against `flow.google.com` and reporting
exit 23 — which told the user to file a frontend-drift bug about a frontend that was
behaving correctly.

### Changed

- **`gflow auth login` closes the browser for you.** It drives your real Google Chrome
through Playwright, watches for the completed Flow sign-in, and closes the window itself —
the "now close Chrome" step is gone. Closing the window yourself still works and still
verifies; it is not an error. On a machine where Playwright cannot resolve a Chrome
channel, or where Google rejects the browser anyway, login falls back automatically to the
previous flow (Chrome as a plain subprocess, you close the window). **There is no new flag
and nothing to choose.**
([spike](docs/superpowers/spikes/2026-09-08-g12-blocks-webdriver-not-playwright.md))

### Fixed

- **The second image in one session no longer falls back to the labs reCAPTCHA mint**
([#673](https://github.com/ffroliva/gflow-cli/issues/673)). Every migrated image run
parks its page on `about:blank`, which routes as `labs` — so the page-owned-mint
capability, derived from `page.url`, answered `False` on the next call and sent it
back to minting on the pooled bootstrap page. The transport now latches the observed
host: `gflow image batch`, which runs every prompt through one `FlowApiClient`,
generated its first prompt and failed the rest with the exact `RecaptchaError` this
release exists to remove.
- **`--aspect 3:4` is refused on the migrated host rather than reported as selector
drift.** The composer's aspect radiogroup was enumerated there with four radios —
`crop_16_9`, `crop_landscape`, `crop_square`, `crop_9_16` — and no `crop_portrait`, so
a 3:4 request missed its selector and raised exit 23. It is now an unported form
(exit 36). The "all five aspect ratios" claim has been corrected to the four measured
wherever it appeared.
- **The exit-36 remediation no longer contradicts the error it accompanies.**
`FlowHostMigratedError._default_remediation` still described the migrated host as
driving only t2v and local-frame i2v, so an image refusal printed a `detail` saying
t2i/i2i are driven directly above a remediation saying they are not. Both it and the
class docstring now name the full ported matrix.
- **`gflow auth login --browser internal` launched a browser configuration measured as
rejected.** The bundled-Chromium path shipped with no anti-automation flags, which leaves
`navigator.webdriver` set. On 2026-09-08 a browser in that state — real Chrome with the
flags removed — was rejected at `/v3/signin/rejected` 17.5 s into the flow, while the same
browser *with* the flags signed in normally. Bundled Chromium was measured only in the
flagged configuration, so its unflagged rejection is inferred from the shared signal, not
observed directly. It now passes
`--disable-blink-features=AutomationControlled`, `ignore_default_args=["--enable-automation"]`
and `chromium_sandbox=True` — the last of which also removes Chrome's cosmetic *"You are
using an unsupported command-line flag"* banner — and signs in on the real OS window
instead of an emulated 1920×1080 viewport that pushed Google's sign-in form off-screen on
smaller or scaled displays.
- **Setting `CHROME_BINARY` no longer makes Playwright's `channel="chrome"` look resolvable
when it is not.** The availability check treated the variable as proof, passed, and then
failed at launch with *"Chromium distribution 'chrome' is not found"*. Playwright honours a
custom binary only via `executable_path=`, never via `channel=`, so the variable is now
ignored by that check (it still resolves a Chrome binary everywhere else).

### Security

- **`httpx2` / `httpcore2` bumped to 2.12.0, clearing five newly published CVEs**
([#766](https://github.com/ffroliva/gflow-cli/pull/766)). `httpcore2` CVE-2026-84381 and
`httpx2` CVE-2026-84378 / -84379 / -84380 / -84382, all against 2.9.1; both arrive
transitively through `mcp`. The advisories were published against an unchanged lockfile —
`Dependency audit (pip-audit)` went red on `develop` without any dependency change — so
this is not a regression introduced by a feature PR. `uvx pip-audit` on the exported
requirements now reports no known vulnerabilities. The bump also adds `httpx2-jsfetch`
1.0 to the lock, marked `sys_platform == 'emscripten'` (Pyodide/WASM only); it is never
installed on any platform gflow supports.

## [0.71.1] — 2026-09-08

### Fixed
Expand Down Expand Up @@ -4580,7 +4664,8 @@ shell-script template that branches on these codes.

First skeleton. Not functional end-to-end yet.

[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.71.1...HEAD
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.72.0...HEAD
[0.72.0]: https://github.com/ffroliva/gflow-cli/compare/v0.71.1...v0.72.0
[0.71.1]: https://github.com/ffroliva/gflow-cli/compare/v0.71.0...v0.71.1
[0.71.0]: https://github.com/ffroliva/gflow-cli/compare/v0.70.0...v0.71.0
[0.70.0]: https://github.com/ffroliva/gflow-cli/compare/v0.69.0...v0.70.0
Expand Down
Loading
Loading