gflow-cli 0.4.0a2__tar.gz → 0.6.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 (161) hide show
  1. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.claude/commands/release.md +21 -10
  2. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.gitattributes +4 -2
  3. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.github/workflows/ci.yml +8 -1
  4. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.github/workflows/release.yml +5 -1
  5. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.gitignore +7 -0
  6. gflow_cli-0.6.0a1/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +38 -0
  7. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/CHANGELOG.md +133 -3
  8. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/CLAUDE.md +63 -0
  9. gflow_cli-0.6.0a1/CONFIGURATION.md +68 -0
  10. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/PKG-INFO +44 -11
  11. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/README.md +43 -10
  12. gflow_cli-0.6.0a1/RELEASE.md +97 -0
  13. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/AUTHENTICATION.md +1 -1
  14. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/INDEX.md +2 -0
  15. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/SECURITY.md +1 -1
  16. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/USAGE.md +97 -4
  17. gflow_cli-0.6.0a1/docs/assets/example-run.gif +0 -0
  18. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +165 -0
  19. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +46 -0
  20. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +89 -0
  21. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +70 -0
  22. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +37 -0
  23. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +33 -0
  24. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +1919 -0
  25. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +70 -0
  26. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +36 -0
  27. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +66 -0
  28. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +70 -0
  29. gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +30 -0
  30. gflow_cli-0.6.0a1/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +497 -0
  31. gflow_cli-0.6.0a1/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +123 -0
  32. gflow_cli-0.6.0a1/examples/README.md +67 -0
  33. gflow_cli-0.6.0a1/examples/batch_from_config.py +99 -0
  34. gflow_cli-0.6.0a1/examples/multi_prompt_t2i.py +126 -0
  35. gflow_cli-0.6.0a1/examples/sample_config.json +18 -0
  36. gflow_cli-0.6.0a1/examples/sample_prompts.txt +4 -0
  37. gflow_cli-0.6.0a1/examples/single_image_t2i.py +135 -0
  38. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/pyproject.toml +5 -1
  39. gflow_cli-0.6.0a1/scripts/diag_capture_flow_traffic.py +125 -0
  40. gflow_cli-0.6.0a1/scripts/diag_recaptcha_mint.py +77 -0
  41. gflow_cli-0.6.0a1/scripts/record_demo.ps1 +226 -0
  42. gflow_cli-0.6.0a1/scripts/smoke_real_chrome_image.py +416 -0
  43. gflow_cli-0.6.0a1/scripts/smoke_worker_style.py +415 -0
  44. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/__init__.py +1 -1
  45. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/_cli_helpers.py +31 -0
  46. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/client.py +100 -57
  47. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/image.py +13 -3
  48. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/__init__.py +83 -0
  49. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/_common.py +94 -0
  50. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/_fingerprint.py +132 -0
  51. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/base.py +60 -0
  52. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/experimental/__init__.py +29 -0
  53. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/experimental/bearer.py +334 -0
  54. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +306 -0
  55. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/experimental/sapisidhash.py +297 -0
  56. gflow_cli-0.6.0a1/src/gflow_cli/api/transports/ui_automation.py +611 -0
  57. gflow_cli-0.6.0a1/src/gflow_cli/browser_manager.py +633 -0
  58. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/cli.py +2 -0
  59. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/cli_image.py +241 -37
  60. gflow_cli-0.6.0a1/src/gflow_cli/cli_run.py +351 -0
  61. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/cli_video.py +2 -1
  62. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/config.py +12 -0
  63. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/errors.py +49 -0
  64. gflow_cli-0.6.0a1/src/gflow_cli/image_batch.py +360 -0
  65. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tasks/lessons.md +79 -0
  66. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_client.py +134 -0
  67. gflow_cli-0.6.0a1/tests/api/test_client_image.py +809 -0
  68. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_image.py +19 -10
  69. gflow_cli-0.6.0a1/tests/api/transports/test_base.py +42 -0
  70. gflow_cli-0.6.0a1/tests/api/transports/test_bearer.py +444 -0
  71. gflow_cli-0.6.0a1/tests/api/transports/test_common.py +206 -0
  72. gflow_cli-0.6.0a1/tests/api/transports/test_evaluate_fetch.py +462 -0
  73. gflow_cli-0.6.0a1/tests/api/transports/test_factory.py +60 -0
  74. gflow_cli-0.6.0a1/tests/api/transports/test_fingerprint.py +119 -0
  75. gflow_cli-0.6.0a1/tests/api/transports/test_sapisidhash.py +389 -0
  76. gflow_cli-0.6.0a1/tests/api/transports/test_ui_automation.py +996 -0
  77. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/cli/test_cli_image.py +119 -0
  78. gflow_cli-0.6.0a1/tests/cli/test_cli_run.py +421 -0
  79. gflow_cli-0.6.0a1/tests/cli/test_t2i_multi_prompt.py +410 -0
  80. gflow_cli-0.6.0a1/tests/e2e/__init__.py +0 -0
  81. gflow_cli-0.6.0a1/tests/e2e/test_transports_e2e.py +313 -0
  82. gflow_cli-0.6.0a1/tests/features/__init__.py +0 -0
  83. gflow_cli-0.6.0a1/tests/features/image.feature +56 -0
  84. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/test_image_steps.py +115 -1
  85. gflow_cli-0.6.0a1/tests/smoke/__init__.py +0 -0
  86. gflow_cli-0.6.0a1/tests/smoke/test_real_flow.py +88 -0
  87. gflow_cli-0.6.0a1/tests/test_browser_manager.py +1541 -0
  88. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_errors.py +28 -0
  89. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_smoke.py +1 -1
  90. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/uv.lock +7 -1
  91. gflow_cli-0.4.0a2/tests/api/test_client_image.py +0 -799
  92. gflow_cli-0.4.0a2/tests/features/image.feature +0 -25
  93. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.claude/README.md +0 -0
  94. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.env.template +0 -0
  95. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/CONTRIBUTING.md +0 -0
  96. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/DISCLAIMER.md +0 -0
  97. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/KNOWN_ISSUES.md +0 -0
  98. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/LICENSE +0 -0
  99. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/PLAN.md +0 -0
  100. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/ARCHITECTURE.md +0 -0
  101. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/CONFIGURATION.md +0 -0
  102. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/USER_GUIDE.md +0 -0
  103. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
  104. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
  105. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
  106. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
  107. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
  108. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
  109. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
  110. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/README.md +0 -0
  111. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/01_upload_image.json +0 -0
  112. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  113. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  114. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/04_archive_workflow.json +0 -0
  115. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/05_createProject.json +0 -0
  116. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/06_batchGenerateImages.json +0 -0
  117. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  118. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/scripts/smoke_e2e.py +0 -0
  119. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/scripts/smoke_image.py +0 -0
  120. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/skills/README.md +0 -0
  121. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/skills/gflow-cli/SKILL.md +0 -0
  122. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/__main__.py +0 -0
  123. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/__init__.py +0 -0
  124. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/_retry.py +0 -0
  125. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/dto.py +0 -0
  126. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/recaptcha.py +0 -0
  127. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/routes.py +0 -0
  128. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/video.py +0 -0
  129. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/auth.py +0 -0
  130. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/manifest.py +0 -0
  131. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/observability.py +0 -0
  132. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/paths.py +0 -0
  133. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/profile_store.py +0 -0
  134. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/__init__.py +0 -0
  135. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/__init__.py +0 -0
  136. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_client_generate_video.py +0 -0
  137. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_concurrency.py +0 -0
  138. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_dto.py +0 -0
  139. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_image_dto.py +0 -0
  140. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_recaptcha.py +0 -0
  141. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_retry.py +0 -0
  142. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_routes.py +0 -0
  143. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_video.py +0 -0
  144. {gflow_cli-0.4.0a2/tests/cli → gflow_cli-0.6.0a1/tests/api/transports}/__init__.py +0 -0
  145. {gflow_cli-0.4.0a2/tests/features → gflow_cli-0.6.0a1/tests/cli}/__init__.py +0 -0
  146. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/cli/test_error_handling.py +0 -0
  147. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/cli/test_helpers.py +0 -0
  148. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/conftest.py +0 -0
  149. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/auth.feature +0 -0
  150. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/conftest.py +0 -0
  151. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/test_auth_steps.py +0 -0
  152. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/test_step_collision_guard.py +0 -0
  153. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/test_video_steps.py +0 -0
  154. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/video.feature +0 -0
  155. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_auth.py +0 -0
  156. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_cli_video.py +0 -0
  157. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_config.py +0 -0
  158. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_manifest.py +0 -0
  159. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_observability.py +0 -0
  160. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_paths.py +0 -0
  161. {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_profile_store.py +0 -0
@@ -9,8 +9,8 @@ You are about to release a new version of `gflow-cli`. Follow this sequence verb
9
9
  ## Inputs
10
10
 
11
11
  Ask the user (if not already provided):
12
- 1. **Version** — the new SemVer (e.g. `0.2.0`, `0.2.0a1`, `1.0.0-rc1`). If they don't know, look at the latest entry in `CHANGELOG.md` `[Unreleased]` and propose the next bump (PATCH for fixes only, MINOR for new features, MAJOR for breaks).
13
- 2. **Pre-release?** — `0.x.y` is alpha by definition. Only the user can say if a `0.x.y-rc1` should ship.
12
+ 1. **Version** — the new version (e.g. `0.4.0`, `0.4.0a3`, `1.0.0rc1`). Use PEP 440 prerelease suffixes (`aN`, `bN`, `rcN`) for Python package releases. If they don't know, look at the latest entry in `CHANGELOG.md` `[Unreleased]` and propose the next bump (PATCH for fixes only, MINOR for new features, MAJOR for breaks).
13
+ 2. **Pre-release?** — prerelease versions such as `0.4.0a3` should stay marked as GitHub prereleases. Only the user can say when a release line is ready for the stable tag, such as `0.4.0`.
14
14
 
15
15
  ## Sequence
16
16
 
@@ -41,7 +41,17 @@ Ask the user (if not already provided):
41
41
  version = "<NEW_VERSION>"
42
42
  ```
43
43
 
44
- 5. **Update `CHANGELOG.md`:**
44
+ 5. **Bump package version** in `src/gflow_cli/__init__.py`:
45
+ ```python
46
+ __version__ = "<NEW_VERSION>"
47
+ ```
48
+
49
+ 6. **Update version assertion tests** if present:
50
+ ```bash
51
+ rg -n "__version__|<OLD_VERSION>|version assertion" tests src pyproject.toml
52
+ ```
53
+
54
+ 7. **Update `CHANGELOG.md`:**
45
55
  - Move all entries under `## [Unreleased]` to a new `## [<NEW_VERSION>] — YYYY-MM-DD` section.
46
56
  - Leave `## [Unreleased]` empty.
47
57
  - Update the link footer:
@@ -50,24 +60,24 @@ Ask the user (if not already provided):
50
60
  [<NEW_VERSION>]: https://github.com/ffroliva/gflow-cli/releases/tag/v<NEW_VERSION>
51
61
  ```
52
62
 
53
- 6. **Commit the release prep.**
63
+ 8. **Commit the release prep.**
54
64
  ```bash
55
- git add pyproject.toml CHANGELOG.md
56
- git commit -m "release: v<NEW_VERSION>"
65
+ git add pyproject.toml src/gflow_cli/__init__.py CHANGELOG.md tests
66
+ git commit -m "chore(release): v<NEW_VERSION>"
57
67
  ```
58
68
 
59
- 7. **Tag.** Pre-release tags include `-rc*` / `-alpha*` / `-beta*`:
69
+ 9. **Tag.** PEP 440 prerelease tags include `aN` / `bN` / `rcN`:
60
70
  ```bash
61
71
  git tag -a v<NEW_VERSION> -m "v<NEW_VERSION>"
62
72
  ```
63
73
 
64
- 8. **Push commit + tag.**
74
+ 10. **Push commit + tag.**
65
75
  ```bash
66
76
  git push origin main
67
77
  git push origin v<NEW_VERSION>
68
78
  ```
69
79
 
70
- 9. **Report.** Tell the user:
80
+ 11. **Report.** Tell the user:
71
81
  - The pushed tag triggers `.github/workflows/release.yml`.
72
82
  - Watch <https://github.com/ffroliva/gflow-cli/actions> for the release workflow.
73
83
  - On success: PyPI publish + GitHub Release with auto-generated notes.
@@ -82,5 +92,6 @@ Ask the user (if not already provided):
82
92
 
83
93
  ## See also
84
94
 
85
- - [README § Releases](../../README.md#releases) — full release policy & cadence
95
+ - [RELEASE.md](../../RELEASE.md) — full release protocol, prerelease policy, and checklist
96
+ - [README § Releases](../../README.md#releases) — short release policy & cadence
86
97
  - [PLAN § Phase 5](../../PLAN.md#phase-5--public-alpha-release-on-pypi) — first-release exit criteria
@@ -28,8 +28,10 @@ LICENSE text eol=lf
28
28
  *.sh text eol=lf
29
29
  *.bash text eol=lf
30
30
 
31
- # Windows scripts MUST stay CRLF or they break under PowerShell / cmd.exe
32
- *.ps1 text eol=crlf
31
+ # PowerShell handles LF fine on both PS 5.1 and Core, so keep .ps1 as LF.
32
+ # cmd.exe has historical edge cases with multi-line batch files, so .bat/.cmd
33
+ # stay CRLF.
34
+ *.ps1 text eol=lf
33
35
  *.bat text eol=crlf
34
36
  *.cmd text eol=crlf
35
37
 
@@ -32,4 +32,11 @@ jobs:
32
32
  run: uv run pyright src
33
33
 
34
34
  - name: Test (smoke only)
35
- run: uv run pytest -q
35
+ # e2e tests (tests/e2e/) require a logged-in `denon82` Chromium profile
36
+ # and live Flow auth — never runnable in CI. They self-mark with
37
+ # `pytestmark = pytest.mark.e2e` (file-level) and are opt-in via
38
+ # `-m e2e` per their module docstring. `live` marker is reserved for
39
+ # `GFLOW_LIVE=1` tests that hit the real Flow API. Both are excluded
40
+ # from the default smoke run; `tests/smoke/test_real_flow.py` already
41
+ # self-skips via `pytest.mark.skipif(GFLOW_E2E != "1")`.
42
+ run: uv run pytest -q -m "not e2e and not live"
@@ -50,4 +50,8 @@ jobs:
50
50
  with:
51
51
  generate_release_notes: true
52
52
  files: dist/*
53
- prerelease: ${{ contains(github.ref_name, '-') }}
53
+ # Pre-release detection covers both conventions:
54
+ # - semver suffixes: v1.2.3-alpha1, v1.2.3-rc1, v1.2.3-beta1 (any '-' qualifies)
55
+ # - PEP 440 suffixes: v1.2.3a1, v1.2.3b1, v1.2.3rc1 (any 'a' / 'b' / 'rc')
56
+ # Stable tags like v1.2.3 contain none of these substrings.
57
+ prerelease: ${{ contains(github.ref_name, '-') || contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
@@ -48,6 +48,13 @@ tmp/
48
48
  !tests/fixtures/**/*.png
49
49
  samples/*.captured.json # sandbox-recorded API exchanges may contain PII
50
50
 
51
+ # Live Flow traffic captures — NEVER commit (contain real Bearer tokens / API keys).
52
+ # Diagnostic scripts MUST default-write here, NOT to samples/captured/.
53
+ # Sanitised reference samples (no secrets) can still live under samples/captured/.
54
+ tmp/captured/
55
+ samples/captured/flow_outgoing_*.jsonl
56
+ samples/captured/flow_outgoing_*.json
57
+
51
58
  # Claude Code worktrees and lock files
52
59
  .claude/worktrees/
53
60
  .claude/scheduled_tasks.lock
@@ -0,0 +1,38 @@
1
+ ---
2
+ created: 2026-05-11T11:34:56.295Z
3
+ title: Add project logo and docs site promotion plan
4
+ area: docs
5
+ files:
6
+ - README.md:18
7
+ - README.md:365
8
+ - RELEASE.md:1
9
+ - docs/INDEX.md:10
10
+ ---
11
+
12
+ ## Problem
13
+
14
+ The project is now public on GitHub and PyPI and has enough release/process
15
+ surface to benefit from a more polished presentation. The README was cleaned up
16
+ with working badges and a public `RELEASE.md`, but the next promotion step is
17
+ still undecided: whether to add a logo/social preview, whether to create a
18
+ GitHub Pages documentation site, and which static-docs stack to use.
19
+
20
+ Jekyll is available on GitHub Pages, but for this Python CLI project the better
21
+ default is likely MkDocs Material: it fits Markdown-heavy CLI docs, has search
22
+ and navigation, and can publish to GitHub Pages cleanly. This should wait until
23
+ after the current prerelease E2E validation, because the real launch gate is
24
+ runtime confidence, not site polish.
25
+
26
+ ## Solution
27
+
28
+ After E2E validation, decide a small promotion package:
29
+
30
+ 1. Add a simple project logo and GitHub social preview image.
31
+ 2. Keep README as the landing page and make the first screen clear for users.
32
+ 3. If docs navigation grows cramped, add a MkDocs Material site published to
33
+ GitHub Pages.
34
+ 4. Avoid Jekyll unless the goal shifts toward a blog-style marketing site.
35
+ 5. Add the star-history chart only after the repo has enough activity for the
36
+ graph to render as useful signal rather than empty axes.
37
+ 6. Keep `RELEASE.md`, README release policy, and `.claude/commands/release.md`
38
+ in sync when the release process changes.
@@ -7,6 +7,136 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.0a1] — 2026-05-14
11
+
12
+ > **Shell-friendly multi-prompt `t2i` + performance hardening.** This release
13
+ > promotes `gflow image t2i` to a variadic command that can consume multiple
14
+ > prompts from positional arguments, a line-delimited text file, or standard
15
+ > input. Core generation logic has been consolidated into a shared
16
+ > `image_batch` module, ensuring architectural consistency between shell runs
17
+ > and JSON-described batches. This version also ships critical resource
18
+ > cleanup fixes for SQLite connections and OOM protection for stdin streams.
19
+
20
+ ### Added
21
+
22
+ - **Variadic `gflow image t2i`** — now accepts multiple positional prompts.
23
+ Example: `gflow image t2i "prompt 1" "prompt 2"`.
24
+ - **`--prompts-file <PATH>` and `--stdin`** — read batches of prompts from
25
+ text files or pipes. All prompts in a batch share a single Flow session
26
+ and project, significantly reducing reCAPTCHA and project-init overhead.
27
+ - **Shared `image_batch` logic** (`src/gflow_cli/image_batch.py`) — unified
28
+ orchestration, validation, and rendering for all multi-prompt generation
29
+ surfaces.
30
+ - **Memory safety for stdin** — bounded read on standard input prevents
31
+ memory exhaustion when piping large or infinite streams.
32
+ - **`examples/multi_prompt_t2i.py` + `examples/sample_prompts.txt`** —
33
+ runnable template for the new shell-multi-prompt surface.
34
+
35
+ ### Fixed
36
+
37
+ - **Resource leaks in SQLite** — ensured all `sqlite3` connections are
38
+ properly closed via `try...finally` blocks, resolving resource exhaust
39
+ warnings and potential hangs in long-running processes.
40
+ - **Output directory partitioning** — `t2i` batches now correctly land in
41
+ date-partitioned folders (`images/YYYY-MM-DD/`) by default, aligning
42
+ with the core design spec.
43
+
44
+ ### Changed
45
+
46
+ - **CLI validation alignment** — `t2i` and `i2i` subcommands now use
47
+ authoritative domain constants for model, aspect, and count validation,
48
+ ensuring UI help text and defaults stay in perfect sync with the engine.
49
+
50
+ ## [0.5.0a1] — 2026-05-12
51
+
52
+ > **Pluggable image transport + JSON-described batch runs.** The image
53
+ > generation surface now ships a new default `ui_automation` transport —
54
+ > a Playwright-driven UI mimicry strategy validated end-to-end against
55
+ > real Flow on a Google AI Pro/Ultra profile. Three earlier HTTP
56
+ > transport strategies (`evaluate_fetch`, `bearer`, `sapisidhash`) move
57
+ > into a new `experimental/` subpackage; they remain importable for
58
+ > research but are hidden from the CLI by default. New top-level
59
+ > `gflow run --config <file>` command drives JSON-described sequential
60
+ > batches through one shared session.
61
+
62
+ ### Added
63
+
64
+ - **`UiAutomationTransport`** (`gflow_cli.api.transports.ui_automation`)
65
+ — new default transport. Drives the Flow editor on a logged-in
66
+ profile through a Playwright-managed persistent context (internal CDP
67
+ port; no externally-exposed debug port). Mirrors the validated
68
+ reference flow in `scripts/smoke_worker_style.py`.
69
+ - **`gflow run --config <file>`** — sequential JSON-described batch
70
+ command. Schema covers `profile`, `transport`, `output_dir`, and a
71
+ `prompts` list (1–50 entries) with per-prompt `text`,
72
+ `aspect_ratio`, `model`, `count`, and `output_filename`. Supports
73
+ `--continue-on-error` (default) and `--fail-fast` semantics; final
74
+ exit code is the max per-prompt exit code. ONE `FlowApiClient`
75
+ session wraps the whole loop so the browser/project persist across
76
+ prompts.
77
+ - **`examples/` directory** — three runnable scripts (`single_image_t2i.py`,
78
+ `batch_from_config.py`) + a copy-and-edit `sample_config.json` + an
79
+ index `examples/README.md`. All sanitised: no hardcoded profile
80
+ names, generic placeholder prompts, parameterised via `--profile` /
81
+ `$GFLOW_EXAMPLE_PROFILE`.
82
+ - **Opt-in real-Flow smoke test** at `tests/smoke/test_real_flow.py`,
83
+ gated by `GFLOW_E2E=1` + `GFLOW_E2E_PROFILE`. Runs the full
84
+ `UiAutomationTransport` flow against real Flow and asserts a
85
+ non-trivial PNG was written.
86
+ - **`EXPERIMENTAL_TRANSPORTS` constant** + **`transport_choices()`
87
+ helper** in `gflow_cli.api.transports`. The factory continues to
88
+ accept every registered key; the CLI `--transport` Choice list is
89
+ the gated surface (default = `ui_automation` only;
90
+ `GFLOW_CLI_EXPERIMENTAL_TRANSPORTS=1` expands to all four).
91
+ - **Download host allow-list** in `UiAutomationTransport._download`
92
+ (`googleusercontent.com`, `googleapis.com`, `google.com` suffix
93
+ match). `follow_redirects=False`. Prevents session cookies from
94
+ reaching a non-Google host through a malformed or compromised
95
+ `fifeUrl`.
96
+
97
+ ### Changed
98
+
99
+ - **Default `--transport` flag** flipped from `evaluate_fetch` to
100
+ `ui_automation` across `gflow image t2i`, `gflow image i2i`, and
101
+ `gflow image upload`. The change is transparent to existing scripts
102
+ unless they pinned `--transport evaluate_fetch` explicitly.
103
+ - **`evaluate_fetch` / `bearer` / `sapisidhash` strategies moved** to
104
+ `gflow_cli.api.transports.experimental.*`. Public registry keys
105
+ (the strings used by `make_transport()` and the
106
+ `GFLOW_CLI_TRANSPORT` env var) are unchanged. Import paths within
107
+ the package are the only user-visible delta.
108
+ - **Debug screenshots** captured by the strategy on `_enter_editor` /
109
+ `_send_prompt` failures are now **viewport-only**
110
+ (`full_page=False`) and emit a `WARNING` log line noting the file
111
+ may contain identifying information from the authenticated session.
112
+
113
+ ### Fixed
114
+
115
+ - Listener-attach race in `generate_images`. The earlier
116
+ `asyncio.create_task(_capture_batch_response(page))` scheduled the
117
+ listener registration AFTER the next event-loop tick; on a busy
118
+ loop the prompt click could fire before the listener attached,
119
+ causing the capture to time out. Refactored into a synchronous
120
+ `_attach_batch_response_listener(page)` + an `async
121
+ _await_captured(captured, ...)`. No more orphaned task on partial
122
+ failure.
123
+
124
+ ### Removed
125
+
126
+ - Dead `_extract_image_urls(response)` helper on
127
+ `UiAutomationTransport` and its five tests.
128
+ `generate_images` parses `body.media[]` directly through
129
+ `GeneratedImage.from_response_item`; the parallel helper was
130
+ unreachable.
131
+
132
+ ### Documentation
133
+
134
+ - `BrowserManager` module docstring updated to make explicit that the
135
+ module is retained for research / non-Flow use, not on the
136
+ v0.5.0a1 image-generation critical path. No behavior change.
137
+ - README "Project status" table updated with v0.5.0a1 row.
138
+ - `docs/USAGE.md` gains a `gflow run` section.
139
+
10
140
  ## [0.4.0a2] — 2026-05-11
11
141
 
12
142
  > **Documentation polish.** Same release surface as v0.4.0a1; this tag fixes
@@ -307,9 +437,9 @@ shell-script template that branches on these codes.
307
437
 
308
438
  First skeleton. Not functional end-to-end yet.
309
439
 
310
- [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.4.0a2...HEAD
311
- [0.4.0a2]: https://github.com/ffroliva/gflow-cli/compare/v0.4.0a1...v0.4.0a2
312
- [0.4.0a1]: https://github.com/ffroliva/gflow-cli/compare/v0.3.0a1...v0.4.0a1
440
+ [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a1...HEAD
441
+ [0.6.0a1]: https://github.com/ffroliva/gflow-cli/compare/v0.5.0a1...v0.6.0a1
442
+ [0.5.0a1]: https://github.com/ffroliva/gflow-cli/compare/v0.4.0a2...v0.5.0a1
313
443
  [0.3.0a1]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.3.0a1
314
444
  [0.2.0a1]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.2.0a1
315
445
  [0.1.0]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.1.0
@@ -142,3 +142,66 @@ uv run gflow auth login --profile experiments # named profile
142
142
  - [docs/INDEX.md](docs/INDEX.md) — full doc routing
143
143
  - [PLAN.md](PLAN.md) — implementation roadmap with phases & ADRs
144
144
  - [.claude/README.md](.claude/README.md) — what's in `.claude/` and how to extend it
145
+
146
+ # context-mode — MANDATORY routing rules
147
+
148
+ You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
149
+
150
+ ## BLOCKED commands — do NOT attempt these
151
+
152
+ ### curl / wget — BLOCKED
153
+ Any Bash command containing `curl` or `wget` is intercepted and replaced with an error message. Do NOT retry.
154
+ Instead use:
155
+ - `ctx_fetch_and_index(url, source)` to fetch and index web pages
156
+ - `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
157
+
158
+ ### Inline HTTP — BLOCKED
159
+ Any Bash command containing `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, or `http.request(` is intercepted and replaced with an error message. Do NOT retry with Bash.
160
+ Instead use:
161
+ - `ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
162
+
163
+ ### WebFetch — BLOCKED
164
+ WebFetch calls are denied entirely. The URL is extracted and you are told to use `ctx_fetch_and_index` instead.
165
+ Instead use:
166
+ - `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` to query the indexed content
167
+
168
+ ## REDIRECTED tools — use sandbox equivalents
169
+
170
+ ### Bash (>20 lines output)
171
+ Bash is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
172
+ For everything else, use:
173
+ - `ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
174
+ - `ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
175
+
176
+ ### Read (for analysis)
177
+ If you are reading a file to **Edit** it → Read is correct (Edit needs content in context).
178
+ If you are reading to **analyze, explore, or summarize** → use `ctx_execute_file(path, language, code)` instead. Only your printed summary enters context. The raw file content stays in the sandbox.
179
+
180
+ ### Grep (large results)
181
+ Grep results can flood context. Use `ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
182
+
183
+ ## Tool selection hierarchy
184
+
185
+ 1. **GATHER**: `ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
186
+ 2. **FOLLOW-UP**: `ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
187
+ 3. **PROCESSING**: `ctx_execute(language, code)` | `ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
188
+ 4. **WEB**: `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
189
+ 5. **INDEX**: `ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
190
+
191
+ ## Subagent routing
192
+
193
+ When spawning subagents (Agent/Task tool), the routing block is automatically injected into their prompt. Bash-type subagents are upgraded to general-purpose so they have access to MCP tools. You do NOT need to manually instruct subagents about context-mode.
194
+
195
+ ## Output constraints
196
+
197
+ - Keep responses under 500 words.
198
+ - Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
199
+ - When indexing content, use descriptive source labels so others can `ctx_search(source: "label")` later.
200
+
201
+ ## ctx commands
202
+
203
+ | Command | Action |
204
+ |---------|--------|
205
+ | `ctx stats` | Call the `ctx_stats` MCP tool and display the full output verbatim |
206
+ | `ctx doctor` | Call the `ctx_doctor` MCP tool, run the returned shell command, display as checklist |
207
+ | `ctx upgrade` | Call the `ctx_upgrade` MCP tool, run the returned shell command, display as checklist |
@@ -0,0 +1,68 @@
1
+ # gflow-cli Configuration Reference
2
+
3
+ ## Environment variables
4
+
5
+ | Env var | Default | Description |
6
+ |---|---|---|
7
+ | `GFLOW_CLI_HOME` | Platform data dir | Root directory for profiles and config. |
8
+ | `GFLOW_CLI_OUTPUT_DIR` | `~/Downloads/gflow-cli` | Where generated images and videos are saved. |
9
+ | `GFLOW_CLI_BROWSER` | `auto` | Browser mode. See **Browser mode** section below. |
10
+ | `CHROME_BINARY` | (autodetect) | Override Chrome binary path. Falls back to platform-standard locations. |
11
+ | `GFLOW_CLI_CONCURRENCY` | `4` | Maximum parallel API requests per batch. |
12
+ | `GFLOW_LIVE` | _(unset)_ | Set to `1` to enable live-API test markers (`@pytest.mark.live`). |
13
+
14
+ ---
15
+
16
+ ## Browser mode (D.2.3+)
17
+
18
+ | Env var | Default | Description |
19
+ |---|---|---|
20
+ | `GFLOW_CLI_BROWSER` | `auto` | `auto` attaches to running Chrome via CDP or spawns detached; `fresh` launches new Playwright Chromium per call (legacy); `cdp:<port>` attaches to explicit CDP endpoint. |
21
+ | `CHROME_BINARY` | (autodetect) | Override Chrome binary path. Falls back to platform-standard locations. |
22
+
23
+ ### When to use which
24
+
25
+ - **`auto`** (recommended): real Chrome fingerprint = highest reCAPTCHA risk score; persistent
26
+ across CLI invocations. First call spawns Chrome detached; subsequent calls attach via CDP.
27
+ - **`fresh`**: legacy single-shot Playwright Chromium. Use when you need a clean profile per call.
28
+ - **`cdp:<port>`**: connect to an already-running Chrome you spawned yourself
29
+ (e.g. with `--remote-debugging-port=9222`).
30
+
31
+ ### Chrome binary autodetection order
32
+
33
+ 1. `CHROME_BINARY` env var (checked first — always wins)
34
+ 2. `shutil.which("chrome")` / `shutil.which("google-chrome")` / `shutil.which("chromium")`
35
+ 3. Platform-standard paths:
36
+ - **Windows**: `C:\Program Files\Google\Chrome\Application\chrome.exe`,
37
+ `C:\Program Files (x86)\Google\Chrome\Application\chrome.exe`,
38
+ `%LOCALAPPDATA%\Google\Chrome\Application\chrome.exe`
39
+ - **macOS**: `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`
40
+ - **Linux**: `/usr/bin/google-chrome`, `/usr/bin/chromium`, `/usr/bin/chromium-browser`
41
+
42
+ If Chrome is not found, gflow-cli raises a `ConfigurationError` with an install hint.
43
+
44
+ ### CDP port range
45
+
46
+ By default gflow-cli uses CDP port `9222`. If that port is occupied by a non-gflow Chrome,
47
+ it probes `9222–9229` until a free port is found. The chosen port is persisted in
48
+ `<profile_dir>/.gflow-cdp.lock` so subsequent calls reuse the same port.
49
+
50
+ If all 8 ports are occupied, a `ConfigurationError` is raised.
51
+
52
+ ### Lockfile
53
+
54
+ `<profile_dir>/.gflow-cdp.lock` — JSON file containing `{pid, port, profile_name}`.
55
+ Written atomically (tmp + `os.link`, `O_CREAT|O_EXCL|O_NOFOLLOW`, mode `0o600`)
56
+ when Chrome is first spawned. Stale locks (PID no longer alive) are cleaned up
57
+ automatically on the next CLI invocation.
58
+
59
+ ### Security note — localhost CDP trust model
60
+
61
+ The Chrome DevTools Protocol endpoint (`http://localhost:<port>/json/version`)
62
+ is **not authenticated**. Any process on the same machine that can reach
63
+ `localhost:9222` can drive the browser. gflow-cli treats a port owner that
64
+ matches our lockfile as trusted; an unmanaged Chrome on the same port is
65
+ attached with a `attached_to_unmanaged_chrome=true` warning logged.
66
+
67
+ **Do not run gflow-cli on a shared multi-user machine** where untrusted users
68
+ have shell access. Use a dedicated user account or a VM per worker.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gflow-cli
3
- Version: 0.4.0a2
3
+ Version: 0.6.0a1
4
4
  Summary: Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal.
5
5
  Project-URL: Homepage, https://github.com/ffroliva/gflow-cli
6
6
  Project-URL: Issues, https://github.com/ffroliva/gflow-cli/issues
@@ -69,7 +69,7 @@ Description-Content-Type: text/markdown
69
69
 
70
70
  > ⚠️ **Not affiliated with Google.** Reverse-engineered from public Flow web traffic. Endpoints can change at any time. See full [DISCLAIMER](DISCLAIMER.md) before use.
71
71
 
72
- 📚 **Docs:** [INDEX](docs/INDEX.md) · [User Guide](docs/USER_GUIDE.md) · [Architecture](docs/ARCHITECTURE.md) · [Authentication](docs/AUTHENTICATION.md) · [Configuration](docs/CONFIGURATION.md) · [Usage](docs/USAGE.md) · [Security](docs/SECURITY.md) · [Known issues](KNOWN_ISSUES.md) · [Plan](PLAN.md) · [Changelog](CHANGELOG.md)
72
+ 📚 **Docs:** [INDEX](docs/INDEX.md) · [User Guide](docs/USER_GUIDE.md) · [Architecture](docs/ARCHITECTURE.md) · [Authentication](docs/AUTHENTICATION.md) · [Configuration](docs/CONFIGURATION.md) · [Usage](docs/USAGE.md) · [Security](docs/SECURITY.md) · [Known issues](KNOWN_ISSUES.md) · [Release protocol](RELEASE.md) · [Plan](PLAN.md) · [Changelog](CHANGELOG.md)
73
73
  🤖 **For AI agents:** [CLAUDE.md](CLAUDE.md) · [`.claude/`](.claude/README.md)
74
74
 
75
75
  ---
@@ -108,7 +108,7 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
108
108
 
109
109
  ## Project status
110
110
 
111
- **v0.4.0a2 — alpha.** Video (T2V/I2V/batch), image (T2I/I2I/upload), and **batch concurrency, typed errors, retry/backoff, and structured logging** are functional end-to-end against a live Google AI Ultra/Pro Flow account.
111
+ **v0.5.0a1 — alpha.** Video (T2V/I2V/batch), image (T2I/I2I/upload), the new **`gflow run` JSON-batch command**, and the **`ui_automation` default transport** are functional end-to-end against a live Google AI Pro/Ultra Flow account. Three earlier HTTP transport strategies (`evaluate_fetch` / `bearer` / `sapisidhash`) move to an `experimental/` subpackage in this release; the production path is `ui_automation`.
112
112
 
113
113
  | Milestone | Status |
114
114
  |---|---|
@@ -122,7 +122,36 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
122
122
  | Typed errors (RFC 9457 Problem Details) + per-class exit codes 3–7 | ✅ done (v0.4.0a2) |
123
123
  | Retry / backoff + reCAPTCHA re-mint inside the retry loop | ✅ done (v0.4.0a2) |
124
124
  | Structured logs (`structlog`, JSON on pipe) | ✅ done (v0.4.0a2) |
125
- | Provider abstraction for official Veo 3.1 API | planned (v0.5+) |
125
+ | Pluggable image transport + `ui_automation` default strategy | done (v0.5.0a1) |
126
+ | `gflow run --config <file>` sequential JSON batches | ✅ done (v0.5.0a1) |
127
+ | `examples/` directory with runnable single-image + batch scripts | ✅ done (v0.5.0a1) |
128
+ | Shell multi-prompt `gflow image t2i` (`PROMPT...`, `--prompts-file`, `--stdin`) | ✅ done (v0.6.0a1) |
129
+ | Provider abstraction for official Veo 3.1 API | ⏳ planned (v0.6+) |
130
+
131
+ ### What's new in v0.5.0a1
132
+
133
+ - `UiAutomationTransport` is now the default image-generation strategy — Playwright-driven UI mimicry against the Flow editor on a logged-in Pro/Ultra profile (no externally-exposed CDP debug port).
134
+ - New top-level `gflow run --config <file>` command for JSON-described sequential batches (1–50 prompts per file, `--continue-on-error` / `--fail-fast` modes). See [`docs/USAGE.md`](docs/USAGE.md#gflow-run) for the schema.
135
+ - Three runnable example scripts shipped under [`examples/`](examples/README.md) — copy and edit for your own pipelines.
136
+ - See the full [CHANGELOG](CHANGELOG.md#0501) for the security follow-ups (download host allow-list, viewport-only debug screenshots) and the listener-attach race fix.
137
+
138
+ ---
139
+
140
+ ## Demo
141
+
142
+ ![gflow image t2i — single 9:16 prompt, streaming structlog output, PNG on disk](docs/assets/example-run.gif)
143
+
144
+ *A single `gflow image t2i "..." --aspect 9:16 --model nano2 --out ...` call against a logged-in Pro/Ultra profile. The terminal shows the streaming `structlog` JSON for the run, the final `ls` of the written PNG, and nothing else — Chromium drives the Flow editor silently in the background because the persistent Playwright session is already warm, so this take is intentionally terminal-only.*
145
+
146
+ **Try it yourself** — this is the exact command the GIF runs:
147
+
148
+ ```bash
149
+ gflow image t2i "a quiet mountain lake at dawn, cinematic photography" --aspect 9:16 --model nano2 --out ./gflow-output/example-single
150
+ ```
151
+
152
+ One prompt, default model (`nano2` = Nano Banana 2), 9:16 portrait, written as `./gflow-output/example-single/<media_name>_0.png`. Wall time is typically 30–90s on a warm profile; the first call after a fresh `gflow auth login` is slower because Playwright spins up Chromium and navigates to the Flow editor. See [`docs/USAGE.md`](docs/USAGE.md) for the full `gflow image t2i` flag reference (`--model`, `--aspect`, `-n`, `--seed`, `--profile`, `--transport`).
153
+
154
+ To reproduce the recording yourself, see [`scripts/record_demo.ps1`](scripts/record_demo.ps1) (Windows, requires OBS + ffmpeg + gifski).
126
155
 
127
156
  ---
128
157
 
@@ -233,7 +262,9 @@ gflow auth login # one-time browser sign
233
262
  gflow auth status # show current session
234
263
 
235
264
  gflow image upload <path> # upload PNG/JPEG → asset UUID
236
- gflow image t2i "<prompt>" [--model] [--aspect] [-n] # text-to-image (1–4 per call)
265
+ gflow image t2i "<prompt>" [...] [--model] [--aspect] # text-to-image; repeat prompts for a warm batch
266
+ gflow image t2i --prompts-file prompts.txt # text-file multi-prompt batch
267
+ gflow image t2i --stdin # stdin multi-prompt batch
237
268
  gflow image i2i "<prompt>" --ref PATH_OR_UUID [...] # image-to-image (1–4 per call)
238
269
 
239
270
  gflow video t2v "<prompt>" -o out.mp4 # text-to-video (Veo 3.1)
@@ -376,17 +407,20 @@ Each `Provider` method has a corresponding test file under `tests/`. New routes
376
407
 
377
408
  1. Update [`CHANGELOG.md`](CHANGELOG.md) with the version's changes (Keep-a-Changelog format).
378
409
  2. Bump `version` in `pyproject.toml`.
379
- 3. Tag the commit:
410
+ 3. Bump `__version__` in `src/gflow_cli/__init__.py`.
411
+ 4. Tag the commit:
380
412
  ```bash
381
- git tag vX.Y.Z # or vX.Y.ZaN for an alpha
382
- git push origin vX.Y.Z
413
+ git tag v<version> # for example, v0.4.0 or v0.4.0a3
414
+ git push origin v<version>
383
415
  ```
384
- 4. The [`release.yml`](.github/workflows/release.yml) GitHub Action runs:
416
+ 5. The [`release.yml`](.github/workflows/release.yml) GitHub Action runs:
385
417
  - Builds the wheel + sdist with `uv build`
386
418
  - Publishes to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) — no API tokens stored
387
419
  - Creates a GitHub Release with the changelog excerpt + built artifacts attached
388
420
 
389
- Pre-release tags (`v*.*.*-rc*`, `v*.*.*-alpha*`, `v*.*.*-beta*`) auto-flag as pre-releases on GitHub. Install with `pip install --pre gflow-cli` or `uvx --from "gflow-cli==0.4.0a2" gflow`.
421
+ PEP 440 prerelease tags (`vX.Y.ZaN`, `vX.Y.ZbN`, `vX.Y.ZrcN`) and hyphenated prerelease tags (`vX.Y.Z-alphaN`, `vX.Y.Z-betaN`, `vX.Y.Z-rcN`) auto-flag as prereleases on GitHub. Stable tags such as `v0.4.0` become full GitHub Releases. See [RELEASE.md](RELEASE.md) for the checklist and the prerelease/full-release policy.
422
+
423
+ Install prereleases explicitly with `pip install --pre gflow-cli` or `uvx --from "gflow-cli==0.4.0a2" gflow`.
390
424
 
391
425
  ---
392
426
 
@@ -422,6 +456,5 @@ Note that the **Google service** this tool talks to has its own terms (Google La
422
456
  [![GitHub last commit](https://img.shields.io/github/last-commit/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli/commits/main)
423
457
  [![GitHub repo size](https://img.shields.io/github/repo-size/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli)
424
458
  [![PyPI downloads](https://img.shields.io/pypi/dm/gflow-cli.svg)](https://pypi.org/project/gflow-cli/)
425
- [![PyPI total downloads](https://img.shields.io/pypi/dt/gflow-cli.svg)](https://pypi.org/project/gflow-cli/)
426
459
 
427
460
  If `gflow-cli` saves you time, please ⭐ the repo — it's the cheapest way to support the project.