gflow-cli 0.2.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/.claude/README.md +58 -0
- gflow_cli-0.2.0a1/.claude/commands/release.md +86 -0
- gflow_cli-0.2.0a1/.env.template +59 -0
- gflow_cli-0.2.0a1/.gitattributes +63 -0
- gflow_cli-0.2.0a1/.github/workflows/ci.yml +33 -0
- gflow_cli-0.2.0a1/.github/workflows/release.yml +51 -0
- gflow_cli-0.2.0a1/.gitignore +53 -0
- gflow_cli-0.2.0a1/CHANGELOG.md +59 -0
- gflow_cli-0.2.0a1/CLAUDE.md +130 -0
- gflow_cli-0.2.0a1/CONTRIBUTING.md +113 -0
- gflow_cli-0.2.0a1/DISCLAIMER.md +72 -0
- gflow_cli-0.2.0a1/KNOWN_ISSUES.md +143 -0
- gflow_cli-0.2.0a1/LICENSE +21 -0
- gflow_cli-0.2.0a1/PKG-INFO +404 -0
- gflow_cli-0.2.0a1/PLAN.md +336 -0
- gflow_cli-0.2.0a1/README.md +351 -0
- gflow_cli-0.2.0a1/docs/ARCHITECTURE.md +242 -0
- gflow_cli-0.2.0a1/docs/AUTHENTICATION.md +251 -0
- gflow_cli-0.2.0a1/docs/CONFIGURATION.md +182 -0
- gflow_cli-0.2.0a1/docs/INDEX.md +36 -0
- gflow_cli-0.2.0a1/docs/SECURITY.md +125 -0
- gflow_cli-0.2.0a1/docs/USAGE.md +262 -0
- gflow_cli-0.2.0a1/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +387 -0
- gflow_cli-0.2.0a1/docs/superpowers/plans/2026-05-09-video-mvp.md +2006 -0
- gflow_cli-0.2.0a1/pyproject.toml +78 -0
- gflow_cli-0.2.0a1/samples/README.md +57 -0
- gflow_cli-0.2.0a1/samples/captured/01_upload_image.json +44 -0
- gflow_cli-0.2.0a1/samples/captured/02_batchAsyncGenerateVideoText.json +118 -0
- gflow_cli-0.2.0a1/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +72 -0
- gflow_cli-0.2.0a1/samples/captured/04_archive_workflow.json +32 -0
- gflow_cli-0.2.0a1/samples/captured/05_createProject.json +32 -0
- gflow_cli-0.2.0a1/scripts/smoke_e2e.py +78 -0
- gflow_cli-0.2.0a1/skills/README.md +27 -0
- gflow_cli-0.2.0a1/skills/gflow-cli/SKILL.md +156 -0
- gflow_cli-0.2.0a1/src/flow_cli/__init__.py +3 -0
- gflow_cli-0.2.0a1/src/flow_cli/__main__.py +6 -0
- gflow_cli-0.2.0a1/src/flow_cli/api/__init__.py +18 -0
- gflow_cli-0.2.0a1/src/flow_cli/api/client.py +246 -0
- gflow_cli-0.2.0a1/src/flow_cli/api/dto.py +137 -0
- gflow_cli-0.2.0a1/src/flow_cli/api/recaptcha.py +107 -0
- gflow_cli-0.2.0a1/src/flow_cli/api/routes.py +37 -0
- gflow_cli-0.2.0a1/src/flow_cli/api/video.py +112 -0
- gflow_cli-0.2.0a1/src/flow_cli/auth.py +87 -0
- gflow_cli-0.2.0a1/src/flow_cli/cli.py +184 -0
- gflow_cli-0.2.0a1/src/flow_cli/cli_video.py +322 -0
- gflow_cli-0.2.0a1/src/flow_cli/config.py +116 -0
- gflow_cli-0.2.0a1/src/flow_cli/manifest.py +58 -0
- gflow_cli-0.2.0a1/src/flow_cli/paths.py +82 -0
- gflow_cli-0.2.0a1/src/flow_cli/profile_store.py +226 -0
- gflow_cli-0.2.0a1/tests/__init__.py +0 -0
- gflow_cli-0.2.0a1/tests/api/__init__.py +0 -0
- gflow_cli-0.2.0a1/tests/api/test_client.py +44 -0
- gflow_cli-0.2.0a1/tests/api/test_client_generate_video.py +77 -0
- gflow_cli-0.2.0a1/tests/api/test_dto.py +91 -0
- gflow_cli-0.2.0a1/tests/api/test_recaptcha.py +58 -0
- gflow_cli-0.2.0a1/tests/api/test_routes.py +36 -0
- gflow_cli-0.2.0a1/tests/api/test_video.py +83 -0
- gflow_cli-0.2.0a1/tests/test_auth.py +52 -0
- gflow_cli-0.2.0a1/tests/test_cli_video.py +150 -0
- gflow_cli-0.2.0a1/tests/test_config.py +104 -0
- gflow_cli-0.2.0a1/tests/test_manifest.py +56 -0
- gflow_cli-0.2.0a1/tests/test_paths.py +51 -0
- gflow_cli-0.2.0a1/tests/test_profile_store.py +157 -0
- gflow_cli-0.2.0a1/tests/test_smoke.py +28 -0
- gflow_cli-0.2.0a1/uv.lock +732 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# `.claude/` — repo-local Claude Code surface
|
|
2
|
+
|
|
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
|
+
|
|
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.
|
|
6
|
+
|
|
7
|
+
## Layout
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
.claude/
|
|
11
|
+
├── README.md ← this file
|
|
12
|
+
└── commands/ ← repo-local slash commands
|
|
13
|
+
└── release.md ← `/release` — automates the version-bump + tag + push flow
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Optional additions when needed:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
.claude/
|
|
20
|
+
├── settings.json ← Claude Code settings (NOT committed if user-specific)
|
|
21
|
+
├── hooks/ ← repo-local PreToolUse / PostToolUse / Stop hooks
|
|
22
|
+
└── skills/ ← internal maintainer skills (not for end users)
|
|
23
|
+
└── <name>/SKILL.md
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Adding a slash command
|
|
27
|
+
|
|
28
|
+
Drop a Markdown file into `commands/`. Filename (without `.md`) becomes the command name. The first paragraph is the description Claude shows in `/help`. The rest is the prompt the agent executes.
|
|
29
|
+
|
|
30
|
+
Example: `commands/foo.md` → invoked as `/foo`.
|
|
31
|
+
|
|
32
|
+
## Adding an internal skill
|
|
33
|
+
|
|
34
|
+
Same shape as the published one in `skills/flow-cli/`:
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
---
|
|
38
|
+
name: my-skill
|
|
39
|
+
description: When to invoke this skill (1-2 sentences).
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
# Body of the skill — how to do the thing.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Drop into `.claude/skills/<name>/SKILL.md`.
|
|
46
|
+
|
|
47
|
+
## Settings
|
|
48
|
+
|
|
49
|
+
`settings.json` is intentionally not committed by default — permissions and tool allowlists are usually a per-developer preference. If we ever agree on a project-wide set (e.g. always allow `uv run pytest` without a prompt), commit it then.
|
|
50
|
+
|
|
51
|
+
## Hooks
|
|
52
|
+
|
|
53
|
+
Same caveat as settings — repo-local hooks override user hooks and can surprise contributors. Only commit a hook when there's a strong, project-wide reason (e.g. block commits that would expose secrets).
|
|
54
|
+
|
|
55
|
+
## See also
|
|
56
|
+
|
|
57
|
+
- [CLAUDE.md](../CLAUDE.md) — project memory hub for any AI agent.
|
|
58
|
+
- [docs/INDEX.md](../docs/INDEX.md) — full documentation index.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Cut a new flow-cli release — bump version, update CHANGELOG, tag, push.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# `/release` — Cut a new flow-cli release
|
|
6
|
+
|
|
7
|
+
You are about to release a new version of `flow-cli`. Follow this sequence verbatim — every step matters.
|
|
8
|
+
|
|
9
|
+
## Inputs
|
|
10
|
+
|
|
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.
|
|
14
|
+
|
|
15
|
+
## Sequence
|
|
16
|
+
|
|
17
|
+
1. **Verify clean working tree.**
|
|
18
|
+
```bash
|
|
19
|
+
git status --short
|
|
20
|
+
```
|
|
21
|
+
Must be empty. If not, abort and tell the user to commit/stash first.
|
|
22
|
+
|
|
23
|
+
2. **Verify on `main`, up-to-date with `origin/main`.**
|
|
24
|
+
```bash
|
|
25
|
+
git rev-parse --abbrev-ref HEAD # must be "main"
|
|
26
|
+
git fetch origin
|
|
27
|
+
git rev-list HEAD..origin/main # must be empty
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
3. **Run quality gates.** Reject if any fail.
|
|
31
|
+
```bash
|
|
32
|
+
uv run ruff check src tests
|
|
33
|
+
uv run ruff format --check src tests
|
|
34
|
+
uv run pyright src
|
|
35
|
+
uv run pytest -q --cov=flow_cli --cov-fail-under=80
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
4. **Bump version** in `pyproject.toml`:
|
|
39
|
+
```toml
|
|
40
|
+
[project]
|
|
41
|
+
version = "<NEW_VERSION>"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
5. **Update `CHANGELOG.md`:**
|
|
45
|
+
- Move all entries under `## [Unreleased]` to a new `## [<NEW_VERSION>] — YYYY-MM-DD` section.
|
|
46
|
+
- Leave `## [Unreleased]` empty.
|
|
47
|
+
- Update the link footer:
|
|
48
|
+
```
|
|
49
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v<NEW_VERSION>...HEAD
|
|
50
|
+
[<NEW_VERSION>]: https://github.com/ffroliva/gflow-cli/releases/tag/v<NEW_VERSION>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
6. **Commit the release prep.**
|
|
54
|
+
```bash
|
|
55
|
+
git add pyproject.toml CHANGELOG.md
|
|
56
|
+
git commit -m "release: v<NEW_VERSION>"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
7. **Tag.** Pre-release tags include `-rc*` / `-alpha*` / `-beta*`:
|
|
60
|
+
```bash
|
|
61
|
+
git tag -a v<NEW_VERSION> -m "v<NEW_VERSION>"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
8. **Push commit + tag.**
|
|
65
|
+
```bash
|
|
66
|
+
git push origin main
|
|
67
|
+
git push origin v<NEW_VERSION>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
9. **Report.** Tell the user:
|
|
71
|
+
- The pushed tag triggers `.github/workflows/release.yml`.
|
|
72
|
+
- Watch <https://github.com/ffroliva/gflow-cli/actions> for the release workflow.
|
|
73
|
+
- On success: PyPI publish + GitHub Release with auto-generated notes.
|
|
74
|
+
- On failure (most common: PyPI Trusted Publishing not yet configured), point them to <https://pypi.org/manage/account/publishing/>.
|
|
75
|
+
|
|
76
|
+
## Critical reminders
|
|
77
|
+
|
|
78
|
+
- **NEVER** add `Co-Authored-By: Claude` (or any AI co-author) to the release commit.
|
|
79
|
+
- **NEVER** force-push a release tag once it's been created on GitHub. If a release ships broken, bump to the next PATCH and ship a fix; never rewrite tag history.
|
|
80
|
+
- **NEVER** `--no-verify` your way past hooks. If a hook complains, fix the underlying issue.
|
|
81
|
+
- If quality gates fail at step 3, **STOP**. Do not proceed. Surface the failures to the user.
|
|
82
|
+
|
|
83
|
+
## See also
|
|
84
|
+
|
|
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
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# flow-cli — example environment variables.
|
|
2
|
+
# Copy to `.env` (in this repo or in $FLOW_CLI_HOME) and customise.
|
|
3
|
+
# All variables are OPTIONAL — defaults work out of the box for most users.
|
|
4
|
+
|
|
5
|
+
# -----------------------------------------------------------------------------
|
|
6
|
+
# Auth & profiles
|
|
7
|
+
# -----------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
# Root directory for Playwright persistent contexts (signed-in Google sessions).
|
|
10
|
+
# Default: %USERPROFILE%/.flow-cli (Windows)
|
|
11
|
+
# ~/.flow-cli (macOS / Linux)
|
|
12
|
+
# FLOW_CLI_HOME=
|
|
13
|
+
|
|
14
|
+
# Default profile name. Override per-call with `--profile <name>`.
|
|
15
|
+
FLOW_CLI_PROFILE=default
|
|
16
|
+
|
|
17
|
+
# -----------------------------------------------------------------------------
|
|
18
|
+
# Output paths
|
|
19
|
+
# -----------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
# Where downloaded assets land. Subfolders are created per kind/date:
|
|
22
|
+
# <output_dir>/images/<YYYY-MM-DD>/<job_id>_<index>.png
|
|
23
|
+
# <output_dir>/videos/<YYYY-MM-DD>/<job_id>.mp4
|
|
24
|
+
#
|
|
25
|
+
# 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)
|
|
29
|
+
# FLOW_CLI_OUTPUT_DIR=
|
|
30
|
+
|
|
31
|
+
# -----------------------------------------------------------------------------
|
|
32
|
+
# Provider selection
|
|
33
|
+
# -----------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
# Backend to use for generations.
|
|
36
|
+
# flow - reverse-engineered Flow REST API (default, requires Ultra/Pro)
|
|
37
|
+
# official - official Veo SDK (planned for v0.3+, requires Gemini API key)
|
|
38
|
+
FLOW_CLI_PROVIDER=flow
|
|
39
|
+
|
|
40
|
+
# Gemini API key — only required when FLOW_CLI_PROVIDER=official.
|
|
41
|
+
# Get one at https://aistudio.google.com/apikey
|
|
42
|
+
# FLOW_CLI_GEMINI_API_KEY=
|
|
43
|
+
|
|
44
|
+
# -----------------------------------------------------------------------------
|
|
45
|
+
# Runtime tuning
|
|
46
|
+
# -----------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
# Per-request HTTP timeout (seconds). Veo videos can take 60-180s each.
|
|
49
|
+
FLOW_CLI_TIMEOUT_SECONDS=600
|
|
50
|
+
|
|
51
|
+
# Logging level — DEBUG | INFO | WARNING | ERROR
|
|
52
|
+
FLOW_CLI_LOG_LEVEL=INFO
|
|
53
|
+
|
|
54
|
+
# Log format — auto | text | json
|
|
55
|
+
# auto = text on TTY, json when piped (default)
|
|
56
|
+
FLOW_CLI_LOG_FORMAT=auto
|
|
57
|
+
|
|
58
|
+
# Concurrency for batch operations (requires multiple profiles, v0.4+).
|
|
59
|
+
FLOW_CLI_CONCURRENCY=1
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Normalise line endings to LF in the repository (working tree gets LF too).
|
|
2
|
+
# Cross-platform contributors don't need to worry about CRLF/LF — the repo
|
|
3
|
+
# is the source of truth, and Git enforces LF on add/commit.
|
|
4
|
+
|
|
5
|
+
# Default: detect text vs binary, force LF on text.
|
|
6
|
+
* text=auto eol=lf
|
|
7
|
+
|
|
8
|
+
# Code
|
|
9
|
+
*.py text eol=lf
|
|
10
|
+
*.toml text eol=lf
|
|
11
|
+
*.json text eol=lf
|
|
12
|
+
*.yml text eol=lf
|
|
13
|
+
*.yaml text eol=lf
|
|
14
|
+
*.lock text eol=lf
|
|
15
|
+
*.txt text eol=lf
|
|
16
|
+
*.cfg text eol=lf
|
|
17
|
+
*.ini text eol=lf
|
|
18
|
+
|
|
19
|
+
# Docs / config
|
|
20
|
+
*.md text eol=lf
|
|
21
|
+
*.template text eol=lf
|
|
22
|
+
*.example text eol=lf
|
|
23
|
+
.gitignore text eol=lf
|
|
24
|
+
.gitattributes text eol=lf
|
|
25
|
+
LICENSE text eol=lf
|
|
26
|
+
|
|
27
|
+
# Shell scripts
|
|
28
|
+
*.sh text eol=lf
|
|
29
|
+
*.bash text eol=lf
|
|
30
|
+
|
|
31
|
+
# Windows scripts MUST stay CRLF or they break under PowerShell / cmd.exe
|
|
32
|
+
*.ps1 text eol=crlf
|
|
33
|
+
*.bat text eol=crlf
|
|
34
|
+
*.cmd text eol=crlf
|
|
35
|
+
|
|
36
|
+
# Binary — never touch
|
|
37
|
+
*.png binary
|
|
38
|
+
*.jpg binary
|
|
39
|
+
*.jpeg binary
|
|
40
|
+
*.gif binary
|
|
41
|
+
*.webp binary
|
|
42
|
+
*.ico binary
|
|
43
|
+
*.mp4 binary
|
|
44
|
+
*.mov binary
|
|
45
|
+
*.webm binary
|
|
46
|
+
*.mp3 binary
|
|
47
|
+
*.wav binary
|
|
48
|
+
*.flac binary
|
|
49
|
+
*.zip binary
|
|
50
|
+
*.tar binary
|
|
51
|
+
*.gz binary
|
|
52
|
+
*.bz2 binary
|
|
53
|
+
*.7z binary
|
|
54
|
+
*.pdf binary
|
|
55
|
+
*.woff binary
|
|
56
|
+
*.woff2 binary
|
|
57
|
+
*.ttf binary
|
|
58
|
+
*.otf binary
|
|
59
|
+
*.eot binary
|
|
60
|
+
*.so binary
|
|
61
|
+
*.dll binary
|
|
62
|
+
*.dylib binary
|
|
63
|
+
*.exe binary
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.11", "3.12"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v3
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
run: uv python install ${{ matrix.python-version }}
|
|
22
|
+
|
|
23
|
+
- name: Install deps
|
|
24
|
+
run: uv sync --extra dev
|
|
25
|
+
|
|
26
|
+
- name: Lint
|
|
27
|
+
run: uv run ruff check src tests
|
|
28
|
+
|
|
29
|
+
- name: Type check
|
|
30
|
+
run: uv run pyright src
|
|
31
|
+
|
|
32
|
+
- name: Test (smoke only)
|
|
33
|
+
run: uv run pytest -q
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write # for creating GitHub Releases
|
|
10
|
+
id-token: write # for PyPI Trusted Publishing (OIDC)
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build-and-publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
environment:
|
|
16
|
+
name: pypi
|
|
17
|
+
url: https://pypi.org/p/gflow-cli
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v3
|
|
25
|
+
|
|
26
|
+
- name: Set up Python
|
|
27
|
+
run: uv python install 3.12
|
|
28
|
+
|
|
29
|
+
- name: Verify tag matches pyproject version
|
|
30
|
+
run: |
|
|
31
|
+
TAG=${GITHUB_REF_NAME#v}
|
|
32
|
+
PROJ_VERSION=$(grep -E '^version = ' pyproject.toml | head -1 | cut -d'"' -f2)
|
|
33
|
+
if [ "$TAG" != "$PROJ_VERSION" ]; then
|
|
34
|
+
echo "::error::Tag ($TAG) does not match pyproject.toml version ($PROJ_VERSION)"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
- name: Build
|
|
39
|
+
run: uv build
|
|
40
|
+
|
|
41
|
+
- name: Publish to PyPI
|
|
42
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
43
|
+
# No api-token needed — uses OIDC Trusted Publishing.
|
|
44
|
+
# Configure once at https://pypi.org/manage/account/publishing/
|
|
45
|
+
|
|
46
|
+
- name: Create GitHub Release
|
|
47
|
+
uses: softprops/action-gh-release@v2
|
|
48
|
+
with:
|
|
49
|
+
generate_release_notes: true
|
|
50
|
+
files: dist/*
|
|
51
|
+
prerelease: ${{ contains(github.ref_name, '-') }}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
env/
|
|
12
|
+
|
|
13
|
+
# uv
|
|
14
|
+
.uv-cache/
|
|
15
|
+
|
|
16
|
+
# Test / coverage
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
.coverage.*
|
|
20
|
+
htmlcov/
|
|
21
|
+
.tox/
|
|
22
|
+
.mypy_cache/
|
|
23
|
+
.ruff_cache/
|
|
24
|
+
.pyright/
|
|
25
|
+
|
|
26
|
+
# Editors
|
|
27
|
+
.vscode/
|
|
28
|
+
.idea/
|
|
29
|
+
*.swp
|
|
30
|
+
.DS_Store
|
|
31
|
+
|
|
32
|
+
# Project-specific — secrets / session storage (NEVER commit)
|
|
33
|
+
auth/ # any project-local auth dir
|
|
34
|
+
profile_*/ # Chromium persistent contexts (any name)
|
|
35
|
+
*.cookies.json # exported cookie jars
|
|
36
|
+
storage_state.json # Playwright storage_state output
|
|
37
|
+
secrets.json # generic secrets file
|
|
38
|
+
.env # local env overrides (the .env.template IS committed)
|
|
39
|
+
.env.local
|
|
40
|
+
.env.*.local
|
|
41
|
+
|
|
42
|
+
# Generated outputs
|
|
43
|
+
out/
|
|
44
|
+
tmp/
|
|
45
|
+
*.mp4
|
|
46
|
+
*.png
|
|
47
|
+
!docs/**/*.png # docs images are OK
|
|
48
|
+
!tests/fixtures/**/*.png
|
|
49
|
+
samples/*.captured.json # sandbox-recorded API exchanges may contain PII
|
|
50
|
+
|
|
51
|
+
# Claude Code worktrees and lock files
|
|
52
|
+
.claude/worktrees/
|
|
53
|
+
.claude/scheduled_tasks.lock
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `flow-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.2.0a1] — 2026-05-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **`gflow video t2v`** — generate a video from a text prompt via Veo 3.1.
|
|
14
|
+
Flags: `--aspect 9:16|16:9|1:1`, `--seed`, `--output`, `--profile`, `--poll-interval`.
|
|
15
|
+
- **`gflow video i2v`** — generate a video from a start image + text prompt (Veo 3.1 I2V).
|
|
16
|
+
- **`gflow video batch`** — run a TSV manifest of video generations against one shared project.
|
|
17
|
+
- `flow_cli.api` package — low-level REST client (`FlowApiClient`) + value objects
|
|
18
|
+
(`GenerateVideoRequest`, `VideoOperation`, `VideoStatus`) for video generation.
|
|
19
|
+
- `flow_cli.api.recaptcha` — reCAPTCHA Enterprise token minting via Playwright `page.evaluate`.
|
|
20
|
+
`TokenMinter` caches the discovered site key per session; `mint(action)` is called immediately
|
|
21
|
+
before each generation request.
|
|
22
|
+
- `flow_cli.manifest` — TSV manifest parser for `gflow video batch`. Supports optional
|
|
23
|
+
`start_image`, `end_image`, `aspect`, `output_path` columns; skips `# `-prefixed comments.
|
|
24
|
+
- `FLOW_CLI_HEADLESS` env var (`bool`, default `true`). Set to `false` if reCAPTCHA refuses
|
|
25
|
+
to mint tokens in headless mode (Google bot detection fallback).
|
|
26
|
+
- `scripts/smoke_e2e.py` — one-shot live T2V smoke test; run after `gflow auth login` to
|
|
27
|
+
verify the full happy path (create project → generate_video → poll → download).
|
|
28
|
+
- **`CLAUDE.md`** at repo root — project memory hub for AI coding agents
|
|
29
|
+
(Claude Code reads natively; Cursor/Codex/Gemini/Aider can read as reference).
|
|
30
|
+
- **`.claude/`** directory — repo-local Claude Code surface for maintainers.
|
|
31
|
+
- `.claude/README.md` — what goes here, how to extend.
|
|
32
|
+
- `.claude/commands/release.md` — `/release` slash command that automates
|
|
33
|
+
version bump + CHANGELOG migration + tag + push, with quality gates.
|
|
34
|
+
- `flow_cli.profile_store` — profile inventory + default-profile persistence
|
|
35
|
+
in `$FLOW_CLI_HOME/config.toml`. Five-step resolution chain (CLI flag > env >
|
|
36
|
+
config > auto-select > raise) with named exceptions
|
|
37
|
+
(`NoProfilesError`, `NoDefaultProfileError`).
|
|
38
|
+
- New auth subcommands: bare `gflow auth`, `gflow auth list`, `gflow auth use <name>`,
|
|
39
|
+
`gflow auth logout [--profile NAME] [-y]`. First login auto-sets default profile.
|
|
40
|
+
- `KNOWN_ISSUES.md` at repo root — open/mitigated/resolved issues with workarounds.
|
|
41
|
+
- `docs/` tree (INDEX, AUTHENTICATION, CONFIGURATION, ARCHITECTURE, USAGE, SECURITY).
|
|
42
|
+
- `.env.template` documenting every supported env var.
|
|
43
|
+
- GitHub Actions CI: ruff, pyright, pytest on Python 3.11 and 3.12.
|
|
44
|
+
- GitHub Actions release workflow: tag-triggered PyPI publish via Trusted Publishing.
|
|
45
|
+
- MIT license, comprehensive README, [`DISCLAIMER.md`](DISCLAIMER.md), [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
46
|
+
- [`skills/flow-cli/SKILL.md`](skills/flow-cli/SKILL.md) — installable Claude Code Skill.
|
|
47
|
+
|
|
48
|
+
### Removed
|
|
49
|
+
- `flow_cli.providers.FlowProvider` and `flow_cli.models` — superseded by `flow_cli.api`.
|
|
50
|
+
- Legacy CLI stubs: `gflow upload`, `gflow generate`, `gflow status`, `gflow download`,
|
|
51
|
+
`gflow i2v`. Replaced by the wired `gflow video` subgroup.
|
|
52
|
+
|
|
53
|
+
## [0.1.0] — _unreleased_
|
|
54
|
+
|
|
55
|
+
First skeleton. Not functional end-to-end yet.
|
|
56
|
+
|
|
57
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.2.0a1...HEAD
|
|
58
|
+
[0.2.0a1]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.2.0a1
|
|
59
|
+
[0.1.0]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.1.0
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
> **Project memory hub for AI coding agents.** Claude Code reads this natively. Other agents (Cursor, Codex, Gemini CLI, Aider) should read this as a top-level reference.
|
|
4
|
+
|
|
5
|
+
## What this project is
|
|
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.
|
|
8
|
+
|
|
9
|
+
**Same pattern as `edge-tts`:** a community SDK over a private cloud API.
|
|
10
|
+
|
|
11
|
+
## On every session start
|
|
12
|
+
|
|
13
|
+
1. Read **[docs/INDEX.md](docs/INDEX.md)** — routing layer for all project docs.
|
|
14
|
+
2. Read **[PLAN.md](PLAN.md)** — current phase, next concrete tasks, ADRs.
|
|
15
|
+
3. Read **[KNOWN_ISSUES.md](KNOWN_ISSUES.md)** — open issues to avoid re-discovering.
|
|
16
|
+
4. Check **[CHANGELOG.md](CHANGELOG.md) `[Unreleased]`** — what's recently shipped.
|
|
17
|
+
|
|
18
|
+
## Active phase
|
|
19
|
+
|
|
20
|
+
**Phase 1 — Foundation** (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`).
|
|
21
|
+
|
|
22
|
+
## Architecture (skim)
|
|
23
|
+
|
|
24
|
+
Layered Clean / Hexagonal — see **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** for the full diagram and rationale.
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
interfaces/ → application/ → domain/ ← infrastructure/
|
|
28
|
+
CLI commands / pure FlowProvider,
|
|
29
|
+
queries / business Playwright,
|
|
30
|
+
handlers / logic filesystem
|
|
31
|
+
ports
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Dependency rule: **`domain/` depends on nothing**. `application/` depends on `domain/` + ports (Protocols). `infrastructure/` implements the ports. `interfaces/` wires it together.
|
|
35
|
+
|
|
36
|
+
## CRITICAL rules — invariant, never violate
|
|
37
|
+
|
|
38
|
+
- **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
|
+
- **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.
|
|
41
|
+
- **No `print()` in `src/`** — use `structlog` (or `logging` until structlog lands in Phase 1).
|
|
42
|
+
- **Domain layer is pure** — `src/flow_cli/domain/*` must not import `application/`, `infrastructure/`, or `interfaces/`. No I/O, no frameworks.
|
|
43
|
+
- **Frozen dataclasses for value objects.** Aggregates may have controlled mutation methods, but VOs (AspectRatio, Prompt, JobId, ...) are immutable.
|
|
44
|
+
- **Async all the way down.** Handlers and providers are `async def`. CLI is the only place that calls `asyncio.run(...)`.
|
|
45
|
+
- **TDD is non-negotiable.** Red → Green → Refactor → Commit. Coverage floor: **80% overall**, **90% on `domain/` and `application/`**. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
46
|
+
|
|
47
|
+
## Coding conventions
|
|
48
|
+
|
|
49
|
+
- **Python 3.11+**, strict typing (`pyright --strict` on `src/flow_cli/`), `from __future__ import annotations` at the top of every module.
|
|
50
|
+
- **`@dataclass(frozen=True)`** for value objects and DTOs. `Protocol` for ports.
|
|
51
|
+
- **`pathlib.Path`** everywhere — never raw strings for filesystem paths.
|
|
52
|
+
- **Click + Rich** for the CLI, **httpx + Playwright** for I/O, **pytest + pytest-bdd** for tests.
|
|
53
|
+
- **Conventional Commits** for messages (`feat:`, `fix:`, `docs:`, `test:`, `chore:`, `refactor:`, etc.). See examples in `git log`.
|
|
54
|
+
- **Short files, single responsibility.** ~200-400 lines typical, 800 max. Split into `package/<topic>.py` if growing.
|
|
55
|
+
|
|
56
|
+
## How to verify your work
|
|
57
|
+
|
|
58
|
+
Run all four BEFORE asking to commit:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv run ruff check src tests # lint
|
|
62
|
+
uv run ruff format --check src tests # formatting
|
|
63
|
+
uv run pyright src # types
|
|
64
|
+
uv run pytest -q --cov=flow_cli # tests + coverage
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
CI runs the same four on every push (see `.github/workflows/ci.yml`).
|
|
68
|
+
|
|
69
|
+
## Where to look
|
|
70
|
+
|
|
71
|
+
| I need to… | Read this |
|
|
72
|
+
|---|---|
|
|
73
|
+
| Understand the architecture | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) |
|
|
74
|
+
| 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` |
|
|
76
|
+
| Touch auth | [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md) |
|
|
77
|
+
| Add a config knob | [docs/CONFIGURATION.md](docs/CONFIGURATION.md) + `.env.template` + (later) `src/flow_cli/shared/config.py` |
|
|
78
|
+
| Write a test | [CONTRIBUTING.md § TDD](CONTRIBUTING.md#test-driven-development-mandatory) + existing patterns in `tests/` |
|
|
79
|
+
| Cut a release | [README § Releases](README.md#releases) — bump version in `pyproject.toml`, update CHANGELOG, `git tag vX.Y.Z`, push |
|
|
80
|
+
| Track a known issue | [KNOWN_ISSUES.md](KNOWN_ISSUES.md) |
|
|
81
|
+
| Understand security posture | [docs/SECURITY.md](docs/SECURITY.md) |
|
|
82
|
+
|
|
83
|
+
## Common tasks
|
|
84
|
+
|
|
85
|
+
### Run the CLI from source
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
uv sync
|
|
89
|
+
uv run gflow --help
|
|
90
|
+
uv run gflow auth # bare command — list profiles or login
|
|
91
|
+
uv run gflow auth login --profile experiments # named profile
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Add a new test (TDD)
|
|
95
|
+
|
|
96
|
+
1. Write the failing test in `tests/<area>/test_<thing>.py`.
|
|
97
|
+
2. `uv run pytest tests/<area>/test_<thing>.py` — verify it fails for the right reason.
|
|
98
|
+
3. Implement the minimum production code to pass.
|
|
99
|
+
4. Refactor.
|
|
100
|
+
5. `uv run pytest -q --cov=flow_cli` — verify nothing else broke and coverage didn't regress.
|
|
101
|
+
|
|
102
|
+
### Update a doc
|
|
103
|
+
|
|
104
|
+
1. Edit the file under `docs/`.
|
|
105
|
+
2. Add a row to `docs/INDEX.md` if it's a new file.
|
|
106
|
+
3. Update `CHANGELOG.md` `[Unreleased]` only if the change is user-visible.
|
|
107
|
+
|
|
108
|
+
## Things NOT to do
|
|
109
|
+
|
|
110
|
+
- Don't add a feature without a PLAN entry (or update PLAN if scope shifts).
|
|
111
|
+
- Don't `pip install` — always `uv add` so the lockfile stays in sync.
|
|
112
|
+
- Don't put new files in the repo root unless they're truly top-level (LICENSE, README, PLAN, CHANGELOG, etc.). Code goes in `src/`, tests in `tests/`, docs in `docs/`.
|
|
113
|
+
- Don't introduce a new dependency without listing the rationale in PLAN's Decision Log.
|
|
114
|
+
- Don't `--no-verify` your way past a hook. Fix the hook's complaint instead.
|
|
115
|
+
- Don't generate placeholder content (lorem ipsum, "todo: implement"). Either skip the file or write the real thing.
|
|
116
|
+
|
|
117
|
+
## Reasoning style for an agent
|
|
118
|
+
|
|
119
|
+
- **Verify before claiming done.** Run the quality gates and read the output. "Tests pass" without evidence is not acceptable.
|
|
120
|
+
- **Small, atomic commits.** Each commit message captures one logical change.
|
|
121
|
+
- **Question scope creep.** If the user asks for X and you're tempted to also fix Y, ask first.
|
|
122
|
+
- **Plan before implementing** for anything > 1 file or > 50 LoC. Write the plan into PLAN.md or a comment, then execute.
|
|
123
|
+
- **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).
|
|
124
|
+
|
|
125
|
+
## See also
|
|
126
|
+
|
|
127
|
+
- [README.md](README.md) — public-facing project overview
|
|
128
|
+
- [docs/INDEX.md](docs/INDEX.md) — full doc routing
|
|
129
|
+
- [PLAN.md](PLAN.md) — implementation roadmap with phases & ADRs
|
|
130
|
+
- [.claude/README.md](.claude/README.md) — what's in `.claude/` and how to extend it
|