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.
Files changed (84) hide show
  1. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.claude/README.md +2 -2
  2. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.claude/commands/release.md +4 -4
  3. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.env.template +15 -7
  4. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.github/workflows/ci.yml +3 -1
  5. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.github/workflows/release.yml +2 -0
  6. gflow_cli-0.3.0a1/CHANGELOG.md +127 -0
  7. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/CLAUDE.md +14 -5
  8. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/CONTRIBUTING.md +13 -14
  9. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/DISCLAIMER.md +10 -10
  10. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/KNOWN_ISSUES.md +13 -19
  11. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/PKG-INFO +65 -51
  12. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/PLAN.md +41 -26
  13. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/README.md +64 -50
  14. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/ARCHITECTURE.md +9 -1
  15. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/AUTHENTICATION.md +25 -25
  16. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/CONFIGURATION.md +36 -30
  17. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/INDEX.md +1 -1
  18. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/SECURITY.md +7 -7
  19. gflow_cli-0.3.0a1/docs/USAGE.md +363 -0
  20. gflow_cli-0.3.0a1/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +319 -0
  21. gflow_cli-0.3.0a1/docs/superpowers/plans/2026-05-09-image-mvp.md +430 -0
  22. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +1 -1
  23. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/docs/superpowers/plans/2026-05-09-video-mvp.md +4 -4
  24. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/pyproject.toml +1 -1
  25. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/README.md +5 -3
  26. gflow_cli-0.3.0a1/samples/captured/06_batchGenerateImages.json +103 -0
  27. gflow_cli-0.3.0a1/samples/captured/07_batchGenerateImages_seeded.json +121 -0
  28. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/scripts/smoke_e2e.py +1 -1
  29. gflow_cli-0.3.0a1/scripts/smoke_image.py +147 -0
  30. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/skills/README.md +6 -5
  31. gflow_cli-0.3.0a1/skills/gflow-cli/SKILL.md +158 -0
  32. gflow_cli-0.3.0a1/src/flow_cli/__init__.py +3 -0
  33. gflow_cli-0.3.0a1/src/flow_cli/api/client.py +567 -0
  34. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/dto.py +96 -1
  35. gflow_cli-0.3.0a1/src/flow_cli/api/image.py +236 -0
  36. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/routes.py +27 -1
  37. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/auth.py +3 -3
  38. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/cli.py +2 -0
  39. gflow_cli-0.3.0a1/src/flow_cli/cli_image.py +559 -0
  40. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/config.py +1 -1
  41. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/paths.py +10 -10
  42. gflow_cli-0.3.0a1/tests/api/test_client.py +177 -0
  43. gflow_cli-0.3.0a1/tests/api/test_client_image.py +580 -0
  44. gflow_cli-0.3.0a1/tests/api/test_image.py +253 -0
  45. gflow_cli-0.3.0a1/tests/api/test_image_dto.py +122 -0
  46. gflow_cli-0.3.0a1/tests/api/test_routes.py +93 -0
  47. gflow_cli-0.3.0a1/tests/cli/__init__.py +0 -0
  48. gflow_cli-0.3.0a1/tests/cli/test_cli_image.py +459 -0
  49. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_config.py +2 -2
  50. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_paths.py +7 -7
  51. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_smoke.py +1 -1
  52. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/uv.lock +2 -2
  53. gflow_cli-0.2.0a1/CHANGELOG.md +0 -59
  54. gflow_cli-0.2.0a1/docs/USAGE.md +0 -262
  55. gflow_cli-0.2.0a1/skills/gflow-cli/SKILL.md +0 -156
  56. gflow_cli-0.2.0a1/src/flow_cli/__init__.py +0 -3
  57. gflow_cli-0.2.0a1/src/flow_cli/api/client.py +0 -246
  58. gflow_cli-0.2.0a1/tests/api/test_client.py +0 -44
  59. gflow_cli-0.2.0a1/tests/api/test_routes.py +0 -36
  60. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.gitattributes +0 -0
  61. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/.gitignore +0 -0
  62. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/LICENSE +0 -0
  63. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/01_upload_image.json +0 -0
  64. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  65. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  66. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/04_archive_workflow.json +0 -0
  67. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/samples/captured/05_createProject.json +0 -0
  68. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/__main__.py +0 -0
  69. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/__init__.py +0 -0
  70. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/recaptcha.py +0 -0
  71. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/api/video.py +0 -0
  72. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/cli_video.py +0 -0
  73. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/manifest.py +0 -0
  74. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/src/flow_cli/profile_store.py +0 -0
  75. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/__init__.py +0 -0
  76. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/__init__.py +0 -0
  77. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/test_client_generate_video.py +0 -0
  78. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/test_dto.py +0 -0
  79. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/test_recaptcha.py +0 -0
  80. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/api/test_video.py +0 -0
  81. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_auth.py +0 -0
  82. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_cli_video.py +0 -0
  83. {gflow_cli-0.2.0a1 → gflow_cli-0.3.0a1}/tests/test_manifest.py +0 -0
  84. {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/flow-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.
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/flow-cli/`:
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 flow-cli release — bump version, update CHANGELOG, tag, push.
2
+ description: Cut a new gflow-cli release — bump version, update CHANGELOG, tag, push.
3
3
  ---
4
4
 
5
- # `/release` — Cut a new flow-cli release
5
+ # `/release` — Cut a new gflow-cli release
6
6
 
7
- You are about to release a new version of `flow-cli`. Follow this sequence verbatim — every step matters.
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
- # flow-cli — example environment variables.
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: %USERPROFILE%/.flow-cli (Windows)
11
- # ~/.flow-cli (macOS / Linux)
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\flow-cli
27
- # macOS: ~/Downloads/flow-cli
28
- # Linux: $XDG_DOWNLOAD_DIR/flow-cli (falls back to ~/Downloads/flow-cli)
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.3+, requires Gemini API key)
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
@@ -10,7 +10,9 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
  strategy:
12
12
  matrix:
13
- python-version: ["3.11", "3.12"]
13
+ python-version: ["3.11", "3.12", "3.13"]
14
+ env:
15
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
14
16
  steps:
15
17
  - uses: actions/checkout@v4
16
18
 
@@ -15,6 +15,8 @@ jobs:
15
15
  environment:
16
16
  name: pypi
17
17
  url: https://pypi.org/p/gflow-cli
18
+ env:
19
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
18
20
  steps:
19
21
  - uses: actions/checkout@v4
20
22
  with:
@@ -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
- `flow-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.
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 1Foundation** (refactor scaffold into layered structure, wire `pydantic-settings`, `structlog`, command/query bus). See [PLAN § Phase 1](PLAN.md#phase-1--foundation-target-12-days). Subset already landed: profile-store + `gflow auth` UX (commit `d821f39`).
20
+ **Phase 3Image 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
- Layered Clean / Hexagonal see **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** for the full diagram and rationale.
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/flow-cli/profile_*` (Windows) or `~/.local/share/flow-cli/profile_*` (POSIX) via [`platformdirs`](https://github.com/platformdirs/platformdirs). Never store sessions in `/tmp`, `%TEMP%`, or anywhere the OS auto-reaps.
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 a Provider route | [PLAN.md § 4 Feature specs](PLAN.md#4-feature-specs) + existing stubs in `src/flow_cli/providers/flow.py` + capture data in `samples/captured_requests.json` |
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 flow-cli
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 flow-cli
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
- `flow-cli` is built test-first. Every change must include tests, and CI rejects PRs that lower coverage.
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/providers/`**: 90%+ (the meat — every captured route has a contract test)
52
- - **`src/flow_cli/auth.py`, `models.py`**: 80%+
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 Provider route
78
+ ## Adding a new API route
79
79
 
80
- 1. **Capture the live request** — add to `samples/captured_requests.json` (sanitise project IDs, asset UUIDs).
81
- 2. **Write the contract test first** — `tests/providers/test_flow_<route>.py`:
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 test_upload_image_returns_asset(mock_flow_provider):
84
- asset = await mock_flow_provider.upload_image(Path("tests/fixtures/sample.png"))
85
- assert asset.uuid
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/providers/flow.py` until green.
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
- `flow-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.
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 `flow-cli` that worked yesterday may break today.
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`. `flow-cli` plans to support that path as a `--provider official` option in v0.3+.
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 `flow-cli` you must:
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 `flow-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.
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 `flow-cli`**.
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 `flow-cli` to:
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 `flow-cli` cease or restrict any reverse-engineered surface, the maintainer will:
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
- `flow-cli` is provided **AS IS**, without warranty of any kind, express or implied. The maintainer:
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 `flow-cli`, you acknowledge that you have read and accept this disclaimer.
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 `flow-cli` raises `AuthExpiredError`.
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 `flow-cli` itself
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". `flow-cli`'s API-driven path bypasses this dialog entirely (the REST endpoint already implies acceptance).
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 flow-cli:** none needed.
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
- `flow-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.
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
- `flow-cli` never deletes from `$FLOW_CLI_OUTPUT_DIR`. Generated assets accumulate forever unless you clean them up.
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/flow-cli" -type f -mtime +30 -delete
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
- _(none yetfirst release pending)_
118
+ ### v0.1provider 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
- - `flow-cli` version (`gflow --version`)
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