gflow-cli 0.2.0a1__tar.gz → 0.3.0a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.claude/README.md +2 -2
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.claude/commands/release.md +4 -4
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.env.template +15 -7
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.github/workflows/ci.yml +3 -1
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.github/workflows/release.yml +2 -0
- gflow_cli-0.3.0a1/CHANGELOG.md +127 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/CLAUDE.md +14 -5
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/CONTRIBUTING.md +13 -14
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/DISCLAIMER.md +10 -10
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/KNOWN_ISSUES.md +13 -19
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/PKG-INFO +65 -51
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/PLAN.md +41 -26
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/README.md +64 -50
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/ARCHITECTURE.md +9 -1
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/AUTHENTICATION.md +25 -25
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/CONFIGURATION.md +36 -30
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/INDEX.md +1 -1
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/SECURITY.md +7 -7
- gflow_cli-0.3.0a1/docs/USAGE.md +363 -0
- gflow_cli-0.3.0a1/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +319 -0
- gflow_cli-0.3.0a1/docs/superpowers/plans/2026-05-09-image-mvp.md +430 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +1 -1
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/superpowers/plans/2026-05-09-video-mvp.md +4 -4
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/pyproject.toml +1 -1
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/README.md +5 -3
- gflow_cli-0.3.0a1/samples/captured/06_batchGenerateImages.json +103 -0
- gflow_cli-0.3.0a1/samples/captured/07_batchGenerateImages_seeded.json +121 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/scripts/smoke_e2e.py +1 -1
- gflow_cli-0.3.0a1/scripts/smoke_image.py +147 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/skills/README.md +6 -5
- gflow_cli-0.3.0a1/skills/gflow-cli/SKILL.md +158 -0
- gflow_cli-0.3.0a1/src/flow_cli/__init__.py +3 -0
- gflow_cli-0.3.0a1/src/flow_cli/api/client.py +567 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/dto.py +96 -1
- gflow_cli-0.3.0a1/src/flow_cli/api/image.py +236 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/routes.py +27 -1
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/auth.py +3 -3
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/cli.py +2 -0
- gflow_cli-0.3.0a1/src/flow_cli/cli_image.py +559 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/config.py +1 -1
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/paths.py +10 -10
- gflow_cli-0.3.0a1/tests/api/test_client.py +177 -0
- gflow_cli-0.3.0a1/tests/api/test_client_image.py +580 -0
- gflow_cli-0.3.0a1/tests/api/test_image.py +253 -0
- gflow_cli-0.3.0a1/tests/api/test_image_dto.py +122 -0
- gflow_cli-0.3.0a1/tests/api/test_routes.py +93 -0
- gflow_cli-0.3.0a1/tests/cli/__init__.py +0 -0
- gflow_cli-0.3.0a1/tests/cli/test_cli_image.py +459 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_config.py +2 -2
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_paths.py +7 -7
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_smoke.py +1 -1
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/uv.lock +2 -2
- gflow_cli-0.2.0a1/CHANGELOG.md +0 -59
- gflow_cli-0.2.0a1/docs/USAGE.md +0 -262
- gflow_cli-0.2.0a1/skills/gflow-cli/SKILL.md +0 -156
- gflow_cli-0.2.0a1/src/flow_cli/__init__.py +0 -3
- gflow_cli-0.2.0a1/src/flow_cli/api/client.py +0 -246
- gflow_cli-0.2.0a1/tests/api/test_client.py +0 -44
- gflow_cli-0.2.0a1/tests/api/test_routes.py +0 -36
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.gitattributes +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.gitignore +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/LICENSE +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/01_upload_image.json +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/04_archive_workflow.json +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/05_createProject.json +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/__main__.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/__init__.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/recaptcha.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/video.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/cli_video.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/manifest.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/profile_store.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/__init__.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/__init__.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/test_client_generate_video.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/test_dto.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/test_recaptcha.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/test_video.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_auth.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_cli_video.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_manifest.py +0 -0
- {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_profile_store.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This directory holds **internal maintainer workflows** that are bundled with the repo so any contributor running Claude Code in this checkout gets the same environment.
|
|
4
4
|
|
|
5
|
-
> Distinct from `skills/
|
|
5
|
+
> Distinct from `skills/gflow-cli/SKILL.md` at the repo root, which is the **published** Skill end users install into their own Claude Code to learn how to use `gflow` from agent contexts. `.claude/` is for *us*, the maintainers; `skills/` is for *them*, the users.
|
|
6
6
|
|
|
7
7
|
## Layout
|
|
8
8
|
|
|
@@ -31,7 +31,7 @@ Example: `commands/foo.md` → invoked as `/foo`.
|
|
|
31
31
|
|
|
32
32
|
## Adding an internal skill
|
|
33
33
|
|
|
34
|
-
Same shape as the published one in `skills/
|
|
34
|
+
Same shape as the published one in `skills/gflow-cli/`:
|
|
35
35
|
|
|
36
36
|
```markdown
|
|
37
37
|
---
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Cut a new
|
|
2
|
+
description: Cut a new gflow-cli release — bump version, update CHANGELOG, tag, push.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# `/release` — Cut a new
|
|
5
|
+
# `/release` — Cut a new gflow-cli release
|
|
6
6
|
|
|
7
|
-
You are about to release a new version of `
|
|
7
|
+
You are about to release a new version of `gflow-cli`. Follow this sequence verbatim — every step matters.
|
|
8
8
|
|
|
9
9
|
## Inputs
|
|
10
10
|
|
|
@@ -83,4 +83,4 @@ Ask the user (if not already provided):
|
|
|
83
83
|
## See also
|
|
84
84
|
|
|
85
85
|
- [README § Releases](../../README.md#releases) — full release policy & cadence
|
|
86
|
-
- [PLAN § Phase 5](../../PLAN.md#phase-5--public-alpha-release) — first-release exit criteria
|
|
86
|
+
- [PLAN § Phase 5](../../PLAN.md#phase-5--public-alpha-release-on-pypi) — first-release exit criteria
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# gflow-cli — example environment variables.
|
|
2
2
|
# Copy to `.env` (in this repo or in $FLOW_CLI_HOME) and customise.
|
|
3
3
|
# All variables are OPTIONAL — defaults work out of the box for most users.
|
|
4
4
|
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
|
|
9
9
|
# Root directory for Playwright persistent contexts (signed-in Google sessions).
|
|
10
|
-
# Default
|
|
11
|
-
#
|
|
10
|
+
# Default (via `platformdirs`):
|
|
11
|
+
# Windows: %LOCALAPPDATA%\gflow-cli (e.g. C:\Users\<you>\AppData\Local\gflow-cli)
|
|
12
|
+
# macOS: ~/Library/Application Support/gflow-cli
|
|
13
|
+
# Linux: $XDG_DATA_HOME/gflow-cli (typically ~/.local/share/gflow-cli)
|
|
12
14
|
# FLOW_CLI_HOME=
|
|
13
15
|
|
|
14
16
|
# Default profile name. Override per-call with `--profile <name>`.
|
|
@@ -23,9 +25,9 @@ FLOW_CLI_PROFILE=default
|
|
|
23
25
|
# <output_dir>/videos/<YYYY-MM-DD>/<job_id>.mp4
|
|
24
26
|
#
|
|
25
27
|
# Default (via `platformdirs`):
|
|
26
|
-
# Windows: %USERPROFILE%\Downloads\
|
|
27
|
-
# macOS: ~/Downloads/
|
|
28
|
-
# Linux: $XDG_DOWNLOAD_DIR/
|
|
28
|
+
# Windows: %USERPROFILE%\Downloads\gflow-cli
|
|
29
|
+
# macOS: ~/Downloads/gflow-cli
|
|
30
|
+
# Linux: $XDG_DOWNLOAD_DIR/gflow-cli (falls back to ~/Downloads/gflow-cli)
|
|
29
31
|
# FLOW_CLI_OUTPUT_DIR=
|
|
30
32
|
|
|
31
33
|
# -----------------------------------------------------------------------------
|
|
@@ -34,7 +36,7 @@ FLOW_CLI_PROFILE=default
|
|
|
34
36
|
|
|
35
37
|
# Backend to use for generations.
|
|
36
38
|
# flow - reverse-engineered Flow REST API (default, requires Ultra/Pro)
|
|
37
|
-
# official - official Veo SDK (planned for v0.
|
|
39
|
+
# official - official Veo SDK (planned for v0.5+, requires Gemini API key)
|
|
38
40
|
FLOW_CLI_PROVIDER=flow
|
|
39
41
|
|
|
40
42
|
# Gemini API key — only required when FLOW_CLI_PROVIDER=official.
|
|
@@ -57,3 +59,9 @@ FLOW_CLI_LOG_FORMAT=auto
|
|
|
57
59
|
|
|
58
60
|
# Concurrency for batch operations (requires multiple profiles, v0.4+).
|
|
59
61
|
FLOW_CLI_CONCURRENCY=1
|
|
62
|
+
|
|
63
|
+
# Run Playwright in headless mode for non-`auth login` commands (true|false).
|
|
64
|
+
# Default: true. Set to false if reCAPTCHA Enterprise refuses to mint tokens
|
|
65
|
+
# (Google's bot-detection sometimes refuses headless Chromium but accepts a
|
|
66
|
+
# visible window). The session is still reused from the persistent profile.
|
|
67
|
+
FLOW_CLI_HEADLESS=true
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `gflow-cli` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.3.0a1] — 2026-05-10
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **`gflow image upload PATH`** — upload a single local image (PNG/JPEG) into a
|
|
14
|
+
fresh Flow project and print the asset UUID + dimensions Flow inferred. The
|
|
15
|
+
UUID is reusable as a starting frame for `gflow image i2i --ref` and
|
|
16
|
+
`gflow video i2v`.
|
|
17
|
+
- **`gflow image t2i PROMPT`** — text-to-image generation (1–4 images per call)
|
|
18
|
+
via Google Flow's Imagen / Nano Banana models.
|
|
19
|
+
Flags: `--model {nano2|nano-pro|image4}`, `--aspect {9:16|16:9|1:1|4:3|3:4}`,
|
|
20
|
+
`-n/--count` (1–4), `--seed` (single-image only), `--out DIR`, `--profile`.
|
|
21
|
+
Files land date-partitioned under `$FLOW_CLI_OUTPUT_DIR/images/<YYYY-MM-DD>/`
|
|
22
|
+
by default; `--out DIR` writes flat as `<DIR>/<media_name>_<n>.png`.
|
|
23
|
+
- **`gflow image i2i PROMPT --ref PATH_OR_UUID`** — image-to-image generation
|
|
24
|
+
with one or more reference images. Each `--ref` is classified at the CLI
|
|
25
|
+
boundary: case-insensitive 8-4-4-4-12 hex UUIDs are passed through verbatim
|
|
26
|
+
(no upload), anything else is canonicalized (symlinks resolved at validation
|
|
27
|
+
time) and uploaded before use. `--ref` is repeatable; UUIDs and paths can mix
|
|
28
|
+
freely on the same call. Same flag set as `t2i` otherwise.
|
|
29
|
+
- **Multi-image fan-out** — `t2i` / `i2i` with `-n {2..4}` mint a single shared
|
|
30
|
+
`batch_id` and issue N parallel POSTs (one per shot, each with its own random
|
|
31
|
+
seed). Same-batch images share the prompt + refs; per-shot variation comes
|
|
32
|
+
from independent seeds.
|
|
33
|
+
- **Three image models** wired behind CLI aliases:
|
|
34
|
+
`nano2` → `NARWHAL` (Nano Banana 2; default, fast/balanced),
|
|
35
|
+
`nano-pro` → `GEM_PIX_2` (Nano Banana Pro; higher quality),
|
|
36
|
+
`image4` → `IMAGEN_3_5` (Imagen 4; photoreal-leaning).
|
|
37
|
+
- **Five aspect ratios** for image generation: `9:16`, `16:9`, `1:1`, `4:3`,
|
|
38
|
+
`3:4` (default `9:16`, matching the Flow web UI).
|
|
39
|
+
- `download_image()` on `FlowApiClient` — direct download of a generated
|
|
40
|
+
image's signed `fifeUrl` to disk. Streams to a temp file and atomically
|
|
41
|
+
renames on success; enforces an SSRF host allowlist (only Google-controlled
|
|
42
|
+
CDNs accepted).
|
|
43
|
+
- `scripts/smoke_image.py` — live single-image E2E smoke script (image
|
|
44
|
+
counterpart of `scripts/smoke_e2e.py` for video). Run after
|
|
45
|
+
`gflow auth login` to exercise the full happy path: project create →
|
|
46
|
+
`batchGenerateImages` → fifeUrl download.
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
- `FlowApiClient.upload_image` now validates **PNG/JPEG/WebP/GIF magic
|
|
50
|
+
bytes** and rejects files larger than **20 MB** before issuing the upload
|
|
51
|
+
request. Existing callers (`gflow video i2v`, `gflow video batch`) inherit
|
|
52
|
+
the stricter validation; previously-undocumented use of `upload_image` for
|
|
53
|
+
non-image payloads no longer works (was never officially supported).
|
|
54
|
+
- Project renamed `flow-cli` → `gflow-cli` across all docs and source. The
|
|
55
|
+
PyPI package and GitHub repo were already at the new name in v0.2.0a1;
|
|
56
|
+
this commit completes the in-source rename. Local clones may want to
|
|
57
|
+
rename their working directory to match `gh clone https://github.com/ffroliva/gflow-cli`
|
|
58
|
+
behavior.
|
|
59
|
+
|
|
60
|
+
### Security
|
|
61
|
+
- DEBUG-level body logs now redact reCAPTCHA Enterprise tokens and other
|
|
62
|
+
bearer-style fields before emission, eliminating a token-leak vector when
|
|
63
|
+
users share verbose logs while filing bug reports.
|
|
64
|
+
- `download_image()` enforces an **SSRF host allowlist** on the signed
|
|
65
|
+
`fifeUrl` returned by Flow — only Google-controlled image CDNs
|
|
66
|
+
(`*.googleusercontent.com`, etc.) are followed; any other host raises
|
|
67
|
+
before the GET is issued. Defends against a Flow-side bug or compromise
|
|
68
|
+
redirecting downloads to an attacker-controlled origin.
|
|
69
|
+
- `project_id` allowlist regex `^[A-Za-z0-9-]{1,128}$` on
|
|
70
|
+
`batch_generate_images_url` — closes percent-encoded slash (`%2F`),
|
|
71
|
+
Unicode-lookalike (U+FF0F / U+2215 / U+29F8), and CRLF/NUL injection
|
|
72
|
+
bypasses that the previous denylist guard let through.
|
|
73
|
+
|
|
74
|
+
### CI
|
|
75
|
+
- Test matrix now includes Python 3.13 alongside 3.11 and 3.12.
|
|
76
|
+
|
|
77
|
+
## [0.2.0a1] — 2026-05-09
|
|
78
|
+
|
|
79
|
+
### Added
|
|
80
|
+
- **`gflow video t2v`** — generate a video from a text prompt via Veo 3.1.
|
|
81
|
+
Flags: `--aspect 9:16|16:9|1:1`, `--seed`, `--output`, `--profile`, `--poll-interval`.
|
|
82
|
+
- **`gflow video i2v`** — generate a video from a start image + text prompt (Veo 3.1 I2V).
|
|
83
|
+
- **`gflow video batch`** — run a TSV manifest of video generations against one shared project.
|
|
84
|
+
- `flow_cli.api` package — low-level REST client (`FlowApiClient`) + value objects
|
|
85
|
+
(`GenerateVideoRequest`, `VideoOperation`, `VideoStatus`) for video generation.
|
|
86
|
+
- `flow_cli.api.recaptcha` — reCAPTCHA Enterprise token minting via Playwright `page.evaluate`.
|
|
87
|
+
`TokenMinter` caches the discovered site key per session; `mint(action)` is called immediately
|
|
88
|
+
before each generation request.
|
|
89
|
+
- `flow_cli.manifest` — TSV manifest parser for `gflow video batch`. Supports optional
|
|
90
|
+
`start_image`, `end_image`, `aspect`, `output_path` columns; skips `# `-prefixed comments.
|
|
91
|
+
- `FLOW_CLI_HEADLESS` env var (`bool`, default `true`). Set to `false` if reCAPTCHA refuses
|
|
92
|
+
to mint tokens in headless mode (Google bot detection fallback).
|
|
93
|
+
- `scripts/smoke_e2e.py` — one-shot live T2V smoke test; run after `gflow auth login` to
|
|
94
|
+
verify the full happy path (create project → generate_video → poll → download).
|
|
95
|
+
- **`CLAUDE.md`** at repo root — project memory hub for AI coding agents
|
|
96
|
+
(Claude Code reads natively; Cursor/Codex/Gemini/Aider can read as reference).
|
|
97
|
+
- **`.claude/`** directory — repo-local Claude Code surface for maintainers.
|
|
98
|
+
- `.claude/README.md` — what goes here, how to extend.
|
|
99
|
+
- `.claude/commands/release.md` — `/release` slash command that automates
|
|
100
|
+
version bump + CHANGELOG migration + tag + push, with quality gates.
|
|
101
|
+
- `flow_cli.profile_store` — profile inventory + default-profile persistence
|
|
102
|
+
in `$FLOW_CLI_HOME/config.toml`. Five-step resolution chain (CLI flag > env >
|
|
103
|
+
config > auto-select > raise) with named exceptions
|
|
104
|
+
(`NoProfilesError`, `NoDefaultProfileError`).
|
|
105
|
+
- New auth subcommands: bare `gflow auth`, `gflow auth list`, `gflow auth use <name>`,
|
|
106
|
+
`gflow auth logout [--profile NAME] [-y]`. First login auto-sets default profile.
|
|
107
|
+
- `KNOWN_ISSUES.md` at repo root — open/mitigated/resolved issues with workarounds.
|
|
108
|
+
- `docs/` tree (INDEX, AUTHENTICATION, CONFIGURATION, ARCHITECTURE, USAGE, SECURITY).
|
|
109
|
+
- `.env.template` documenting every supported env var.
|
|
110
|
+
- GitHub Actions CI: ruff, pyright, pytest on Python 3.11 and 3.12.
|
|
111
|
+
- GitHub Actions release workflow: tag-triggered PyPI publish via Trusted Publishing.
|
|
112
|
+
- MIT license, comprehensive README, [`DISCLAIMER.md`](DISCLAIMER.md), [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
113
|
+
- [`skills/gflow-cli/SKILL.md`](skills/gflow-cli/SKILL.md) — installable Claude Code Skill.
|
|
114
|
+
|
|
115
|
+
### Removed
|
|
116
|
+
- `flow_cli.providers.FlowProvider` and `flow_cli.models` — superseded by `flow_cli.api`.
|
|
117
|
+
- Legacy CLI stubs: `gflow upload`, `gflow generate`, `gflow status`, `gflow download`,
|
|
118
|
+
`gflow i2v`. Replaced by the wired `gflow video` subgroup.
|
|
119
|
+
|
|
120
|
+
## [0.1.0] — _unreleased_
|
|
121
|
+
|
|
122
|
+
First skeleton. Not functional end-to-end yet.
|
|
123
|
+
|
|
124
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.3.0a1...HEAD
|
|
125
|
+
[0.3.0a1]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.3.0a1
|
|
126
|
+
[0.2.0a1]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.2.0a1
|
|
127
|
+
[0.1.0]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.1.0
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## What this project is
|
|
6
6
|
|
|
7
|
-
`
|
|
7
|
+
`gflow-cli` is an unofficial Python CLI that drives [Google Flow](https://labs.google/fx/tools/flow) (Veo image-to-video, Imagen text-to-image) from the terminal by reverse-engineering Flow's private REST API at `aisandbox-pa.googleapis.com`. Built for Google AI Ultra/Pro subscribers who want to spend their Flow credits via batch automation rather than the web UI.
|
|
8
8
|
|
|
9
9
|
**Same pattern as `edge-tts`:** a community SDK over a private cloud API.
|
|
10
10
|
|
|
@@ -17,11 +17,18 @@
|
|
|
17
17
|
|
|
18
18
|
## Active phase
|
|
19
19
|
|
|
20
|
-
**Phase
|
|
20
|
+
**Phase 3 — Image MVP DONE (v0.3.0a1).** `gflow image upload/t2i/i2i` shipped.
|
|
21
|
+
Tag at `ccce4d5`. Next phase TBD (Phase 4 Hardening — concurrency pool,
|
|
22
|
+
retry/backoff, structlog, BDD).
|
|
21
23
|
|
|
22
24
|
## Architecture (skim)
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
> Note: the layered diagram below describes the **target** architecture
|
|
27
|
+
> (deferred per [PLAN.md ADR #2](PLAN.md#5-decision-log-adrs-in-miniature)).
|
|
28
|
+
> The current package layout is the simpler
|
|
29
|
+
> `src/flow_cli/{api/, cli.py, cli_image.py, cli_video.py, auth.py,
|
|
30
|
+
> config.py, paths.py, profile_store.py}`. See
|
|
31
|
+
> [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the full target shape.
|
|
25
32
|
|
|
26
33
|
```text
|
|
27
34
|
interfaces/ → application/ → domain/ ← infrastructure/
|
|
@@ -37,7 +44,7 @@ Dependency rule: **`domain/` depends on nothing**. `application/` depends on `do
|
|
|
37
44
|
|
|
38
45
|
- **Never commit secrets.** `.gitignore` excludes `auth/`, `profile_*/`, `*.cookies.json`, `storage_state.json`, `secrets.json`, `.env`, `.env.local`, `.env.*.local`. If you see one of these staged, abort and tell the user.
|
|
39
46
|
- **Never add `Co-Authored-By: Claude` (or any AI co-author) to commit messages.** Author attribution is the human user's only.
|
|
40
|
-
- **Sessions belong outside the repo.** Default location is `$LOCALAPPDATA/
|
|
47
|
+
- **Sessions belong outside the repo.** Default location is `$LOCALAPPDATA/gflow-cli/profile_*` (Windows) or `~/.local/share/gflow-cli/profile_*` (POSIX) via [`platformdirs`](https://github.com/platformdirs/platformdirs). Never store sessions in `/tmp`, `%TEMP%`, or anywhere the OS auto-reaps.
|
|
41
48
|
- **No `print()` in `src/`** — use `structlog` (or `logging` until structlog lands in Phase 1).
|
|
42
49
|
- **Domain layer is pure** — `src/flow_cli/domain/*` must not import `application/`, `infrastructure/`, or `interfaces/`. No I/O, no frameworks.
|
|
43
50
|
- **Frozen dataclasses for value objects.** Aggregates may have controlled mutation methods, but VOs (AspectRatio, Prompt, JobId, ...) are immutable.
|
|
@@ -72,7 +79,7 @@ CI runs the same four on every push (see `.github/workflows/ci.yml`).
|
|
|
72
79
|
|---|---|
|
|
73
80
|
| Understand the architecture | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) |
|
|
74
81
|
| Add a CLI command | [docs/USAGE.md](docs/USAGE.md) + existing patterns in `src/flow_cli/cli.py` |
|
|
75
|
-
| Add
|
|
82
|
+
| Add an API route | [PLAN.md § 4 Phase status](PLAN.md#4-phase-status) + existing client in `src/flow_cli/api/client.py` + capture data under `samples/captured/` |
|
|
76
83
|
| Touch auth | [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md) |
|
|
77
84
|
| Add a config knob | [docs/CONFIGURATION.md](docs/CONFIGURATION.md) + `.env.template` + (later) `src/flow_cli/shared/config.py` |
|
|
78
85
|
| Write a test | [CONTRIBUTING.md § TDD](CONTRIBUTING.md#test-driven-development-mandatory) + existing patterns in `tests/` |
|
|
@@ -121,6 +128,8 @@ uv run gflow auth login --profile experiments # named profile
|
|
|
121
128
|
- **Question scope creep.** If the user asks for X and you're tempted to also fix Y, ask first.
|
|
122
129
|
- **Plan before implementing** for anything > 1 file or > 50 LoC. Write the plan into PLAN.md or a comment, then execute.
|
|
123
130
|
- **Show your work.** When you change something non-obvious, leave a one-line comment with the WHY (not the WHAT — the diff already shows the what).
|
|
131
|
+
- **Fix bugs autonomously.** Given a bug report, reproduce it, trace the root cause, fix it, and verify — no hand-holding needed. Point at logs/errors/failing tests, then resolve them.
|
|
132
|
+
- **Learn from corrections.** After any user correction, append the pattern to `tasks/lessons.md` (create if absent) as a rule that prevents the same mistake. Review it at session start for relevant context.
|
|
124
133
|
|
|
125
134
|
## See also
|
|
126
135
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Contributing to
|
|
1
|
+
# Contributing to gflow-cli
|
|
2
2
|
|
|
3
3
|
Thanks for considering a contribution! Pre-1.0 the repo is private and managed by [@ffroliva](https://github.com/ffroliva), but the workflow described here is what'll be opened up to the community at the v0.2 alpha milestone.
|
|
4
4
|
|
|
@@ -6,14 +6,14 @@ Thanks for considering a contribution! Pre-1.0 the repo is private and managed b
|
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
git clone git@github.com:ffroliva/gflow-cli.git
|
|
9
|
-
cd
|
|
9
|
+
cd gflow-cli
|
|
10
10
|
uv sync --extra dev
|
|
11
11
|
uv run playwright install chromium
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
## Test-driven development (mandatory)
|
|
15
15
|
|
|
16
|
-
`
|
|
16
|
+
`gflow-cli` is built test-first. Every change must include tests, and CI rejects PRs that lower coverage.
|
|
17
17
|
|
|
18
18
|
The cycle:
|
|
19
19
|
|
|
@@ -47,9 +47,9 @@ CI runs `unit` + `integration` on every push. `live` tests run only on the maint
|
|
|
47
47
|
|
|
48
48
|
### Coverage targets
|
|
49
49
|
|
|
50
|
-
- **`src/flow_cli/cli.py`**: 70%+ (CLI plumbing — some Click branches are hard to unit-test)
|
|
51
|
-
- **`src/flow_cli/
|
|
52
|
-
- **`src/flow_cli/auth.py`, `
|
|
50
|
+
- **`src/flow_cli/cli.py`, `src/flow_cli/cli_image.py`, `src/flow_cli/cli_video.py`**: 70%+ (CLI plumbing — some Click branches are hard to unit-test)
|
|
51
|
+
- **`src/flow_cli/api/`**: 90%+ (the meat — every captured route has a contract test)
|
|
52
|
+
- **`src/flow_cli/auth.py`, `config.py`, `paths.py`, `profile_store.py`**: 80%+
|
|
53
53
|
- **Overall**: 80%+
|
|
54
54
|
|
|
55
55
|
`uv run pytest --cov=flow_cli --cov-fail-under=80` enforces the floor. Don't merge below it.
|
|
@@ -75,17 +75,16 @@ repos:
|
|
|
75
75
|
- id: ruff-format
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
## Adding a new
|
|
78
|
+
## Adding a new API route
|
|
79
79
|
|
|
80
|
-
1. **Capture the live request** — add
|
|
81
|
-
2. **Write the contract test first** — `tests/
|
|
80
|
+
1. **Capture the live request** — add a sanitised JSON sample under `samples/captured/` (numbered, e.g. `08_<route>.json`; scrub project IDs, asset UUIDs, bearer tokens, and reCAPTCHA tokens).
|
|
81
|
+
2. **Write the contract test first** — under `tests/api/`:
|
|
82
82
|
```python
|
|
83
|
-
async def
|
|
84
|
-
|
|
85
|
-
assert
|
|
86
|
-
assert asset.kind == "image"
|
|
83
|
+
async def test_new_route_returns_expected_dto(mock_client):
|
|
84
|
+
result = await mock_client.new_route(...)
|
|
85
|
+
assert result.some_field
|
|
87
86
|
```
|
|
88
|
-
3. **Implement** in `src/flow_cli/
|
|
87
|
+
3. **Implement** in `src/flow_cli/api/client.py` (and add helpers under `src/flow_cli/api/` as needed) until green.
|
|
89
88
|
4. **Add a `live` test** that runs the real flow end-to-end (skipped in CI by default).
|
|
90
89
|
5. **Update `CHANGELOG.md`** under `[Unreleased] → Added`.
|
|
91
90
|
6. **Document** the route in the README's Architecture section if it's a new capability.
|
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Not affiliated with Google
|
|
4
4
|
|
|
5
|
-
`
|
|
5
|
+
`gflow-cli` is an **independent, unofficial** project. It is **not affiliated with, endorsed by, sponsored by, or otherwise connected to Google LLC, Alphabet Inc., DeepMind, or any of their subsidiaries.** All trademarks (Google, Flow, Veo, Gemini, Imagen, AI Ultra, AI Pro) are the property of their respective owners. The use of these names here is purely descriptive — to identify the service this tool integrates with — and does not imply endorsement.
|
|
6
6
|
|
|
7
7
|
## Reverse-engineered surface
|
|
8
8
|
|
|
9
9
|
This tool calls Google's private REST API at `aisandbox-pa.googleapis.com`. That surface is:
|
|
10
10
|
|
|
11
11
|
- **Undocumented.** Google does not publish a contract for it.
|
|
12
|
-
- **Unstable.** Endpoints, request shapes, and response shapes may change without notice. A version of `
|
|
12
|
+
- **Unstable.** Endpoints, request shapes, and response shapes may change without notice. A version of `gflow-cli` that worked yesterday may break today.
|
|
13
13
|
- **Subject to access controls.** Google may rate-limit, throttle, restrict, or revoke access to this surface for any account at any time.
|
|
14
14
|
- **Not covered by any Google SLA.** When this surface goes down, you have no support recourse.
|
|
15
15
|
|
|
16
|
-
If you need a stable, supported, contractual API, use the [official Google Gen AI SDK](https://github.com/googleapis/python-genai) and the public Veo API on `generativelanguage.googleapis.com`. `
|
|
16
|
+
If you need a stable, supported, contractual API, use the [official Google Gen AI SDK](https://github.com/googleapis/python-genai) and the public Veo API on `generativelanguage.googleapis.com`. `gflow-cli` plans to support that path as a `--provider official` option in v0.3+.
|
|
17
17
|
|
|
18
18
|
## Account responsibility
|
|
19
19
|
|
|
20
|
-
To use `
|
|
20
|
+
To use `gflow-cli` you must:
|
|
21
21
|
|
|
22
22
|
1. **Own a valid Google account** with active access to [Google Flow](https://labs.google/fx/tools/flow) — typically an [AI Ultra or AI Pro](https://gemini.google/subscriptions/) subscription as of late 2025.
|
|
23
23
|
2. **Comply with Google's terms of service** for that account, including:
|
|
@@ -26,13 +26,13 @@ To use `flow-cli` you must:
|
|
|
26
26
|
- Any subscription-specific terms (Ultra, Pro, etc.)
|
|
27
27
|
- The [Google Labs Additional Terms](https://labs.google/terms) governing Flow
|
|
28
28
|
|
|
29
|
-
3. **Bear all costs.** Every generation made through `
|
|
29
|
+
3. **Bear all costs.** Every generation made through `gflow-cli` consumes credits from your Google account, exactly as if you had clicked "Generate" in the web UI. Neither the maintainer nor any contributor will be liable for unexpected billing.
|
|
30
30
|
|
|
31
|
-
4. **Use only your own credentials.** Sharing accounts, automating mass-account creation, or otherwise circumventing Google's per-account quotas is prohibited by Google's terms and is **not a supported use case for `
|
|
31
|
+
4. **Use only your own credentials.** Sharing accounts, automating mass-account creation, or otherwise circumventing Google's per-account quotas is prohibited by Google's terms and is **not a supported use case for `gflow-cli`**.
|
|
32
32
|
|
|
33
33
|
## Prohibited uses
|
|
34
34
|
|
|
35
|
-
The maintainer asks that you do **not** use `
|
|
35
|
+
The maintainer asks that you do **not** use `gflow-cli` to:
|
|
36
36
|
|
|
37
37
|
- Generate content that violates the [Generative AI Prohibited Use Policy](https://policies.google.com/terms/generative-ai/use-policy) (CSAM, harassment, IP infringement, etc.).
|
|
38
38
|
- Circumvent Google's billing, quota, or rate limits via account-rotation farms.
|
|
@@ -43,7 +43,7 @@ These uses can get **your** Google account banned, can put the maintainer in a d
|
|
|
43
43
|
|
|
44
44
|
## Takedown policy
|
|
45
45
|
|
|
46
|
-
If Google formally requests that `
|
|
46
|
+
If Google formally requests that `gflow-cli` cease or restrict any reverse-engineered surface, the maintainer will:
|
|
47
47
|
|
|
48
48
|
1. Acknowledge the request publicly within 7 days.
|
|
49
49
|
2. Comply by archiving / removing the affected code path.
|
|
@@ -53,13 +53,13 @@ If you are at Google and reading this: please open an issue at <https://github.c
|
|
|
53
53
|
|
|
54
54
|
## No warranty
|
|
55
55
|
|
|
56
|
-
`
|
|
56
|
+
`gflow-cli` is provided **AS IS**, without warranty of any kind, express or implied. The maintainer:
|
|
57
57
|
|
|
58
58
|
- Makes no guarantee that any version will work, today or tomorrow.
|
|
59
59
|
- Makes no guarantee about output quality, completeness, or fitness for any particular use.
|
|
60
60
|
- Will not be liable for lost credits, banned accounts, lost time, or any other damages arising from use of this tool.
|
|
61
61
|
|
|
62
|
-
See [LICENSE](LICENSE) for the full legal text. By installing or using `
|
|
62
|
+
See [LICENSE](LICENSE) for the full legal text. By installing or using `gflow-cli`, you acknowledge that you have read and accept this disclaimer.
|
|
63
63
|
|
|
64
64
|
## Reporting issues
|
|
65
65
|
|
|
@@ -24,7 +24,7 @@ Google's web session cookies aren't permanent. They expire when:
|
|
|
24
24
|
- You sign out from another device's session manager
|
|
25
25
|
- Google flags the session as suspicious (geo-jump, new device fingerprint)
|
|
26
26
|
|
|
27
|
-
When this happens, the next API call returns 401/403 and `
|
|
27
|
+
When this happens, the next API call returns 401/403 and `gflow-cli` raises `AuthExpiredError`.
|
|
28
28
|
|
|
29
29
|
**Workaround:**
|
|
30
30
|
```bash
|
|
@@ -59,23 +59,13 @@ gflow image batch ./batch-b.tsv --profile personal
|
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
|
-
### v0.1 — provider methods are stubs
|
|
63
|
-
|
|
64
|
-
- **Status:** Open · **Severity:** Critical (blocks usage) · **Resolution:** v0.2
|
|
65
|
-
|
|
66
|
-
The current published code is a **scaffold**. `upload_image`, `start_generation`, `get_job`, `download` all raise `NotImplementedError` until the route wiring lands in [PLAN](PLAN.md) Phases 2 and 3.
|
|
67
|
-
|
|
68
|
-
**Workaround:** none — wait for v0.2.
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
62
|
### Flow's first-upload terms-of-use dialog ("Aviso") blocks the worker (worker-only)
|
|
73
63
|
|
|
74
|
-
- **Status:** Open · **Severity:** Low · **Affects:** the legacy in-tree Compiled Growth worker, NOT `
|
|
64
|
+
- **Status:** Open · **Severity:** Low · **Affects:** the legacy in-tree Compiled Growth worker, NOT `gflow-cli` itself
|
|
75
65
|
|
|
76
|
-
Flow shows a one-time "Aviso" / "Notice" terms-of-use confirmation on the first image upload of a new account session. The legacy Playwright worker has to explicitly click "Concordo" / "Agree". `
|
|
66
|
+
Flow shows a one-time "Aviso" / "Notice" terms-of-use confirmation on the first image upload of a new account session. The legacy Playwright worker has to explicitly click "Concordo" / "Agree". `gflow-cli`'s API-driven path bypasses this dialog entirely (the REST endpoint already implies acceptance).
|
|
77
67
|
|
|
78
|
-
**Workaround in
|
|
68
|
+
**Workaround in gflow-cli:** none needed.
|
|
79
69
|
|
|
80
70
|
**Workaround in legacy worker:** see Compiled Growth's `flow_video.py` consent-dismiss block.
|
|
81
71
|
|
|
@@ -85,7 +75,7 @@ Flow shows a one-time "Aviso" / "Notice" terms-of-use confirmation on the first
|
|
|
85
75
|
|
|
86
76
|
- **Status:** Open · **Severity:** Low · **Roadmap:** v0.5
|
|
87
77
|
|
|
88
|
-
`
|
|
78
|
+
`gflow-cli` doesn't yet show how many Veo / Imagen credits remain on your Ultra/Pro subscription. You can check at <https://gemini.google/subscriptions/> in the meantime.
|
|
89
79
|
|
|
90
80
|
**Roadmap:** v0.5 will surface remaining quota via `gflow auth status` once we capture the relevant Google API.
|
|
91
81
|
|
|
@@ -107,12 +97,12 @@ Other ratios may be silently rejected or coerced server-side. We validate in the
|
|
|
107
97
|
|
|
108
98
|
- **Status:** Open · **Severity:** Low · **By design**
|
|
109
99
|
|
|
110
|
-
`
|
|
100
|
+
`gflow-cli` never deletes from `$FLOW_CLI_OUTPUT_DIR`. Generated assets accumulate forever unless you clean them up.
|
|
111
101
|
|
|
112
102
|
**Workaround:** schedule a cron / Task Scheduler job, e.g.:
|
|
113
103
|
```bash
|
|
114
104
|
# Delete files older than 30 days
|
|
115
|
-
find "$HOME/Downloads/
|
|
105
|
+
find "$HOME/Downloads/gflow-cli" -type f -mtime +30 -delete
|
|
116
106
|
```
|
|
117
107
|
|
|
118
108
|
---
|
|
@@ -125,7 +115,11 @@ _(none yet)_
|
|
|
125
115
|
|
|
126
116
|
## Resolved
|
|
127
117
|
|
|
128
|
-
|
|
118
|
+
### v0.1 — provider methods are stubs
|
|
119
|
+
|
|
120
|
+
- **Status:** Resolved · **Severity:** Critical (blocked usage) · **Fixed in:** v0.2.0a1
|
|
121
|
+
|
|
122
|
+
The v0.1 scaffold left `upload_image`, `start_generation`, `get_job`, `download` raising `NotImplementedError`. v0.2.0a1 wired the video routes (T2V/I2V/batch) on a new `flow_cli.api.client.FlowApiClient` and removed the legacy `providers/` + `models` modules. v0.3.0a1 added the image routes (`gflow image upload/t2i/i2i`) on the same client.
|
|
129
123
|
|
|
130
124
|
---
|
|
131
125
|
|
|
@@ -135,7 +129,7 @@ If you hit something not listed here:
|
|
|
135
129
|
|
|
136
130
|
1. Search existing issues at <https://github.com/ffroliva/gflow-cli/issues>.
|
|
137
131
|
2. If none match, open a new issue with:
|
|
138
|
-
- `
|
|
132
|
+
- `gflow-cli` version (`gflow --version`)
|
|
139
133
|
- Python version (`python --version`)
|
|
140
134
|
- OS + version
|
|
141
135
|
- Exact command that failed + full error output
|