Skip to content

Show the API's default in flag help - #60

Merged
giordano-lucas merged 1 commit into
mainfrom
fix/show-api-defaults-in-help
Aug 6, 2026
Merged

Show the API's default in flag help#60
giordano-lucas merged 1 commit into
mainfrom
fix/show-api-defaults-in-help

Conversation

@giordano-lucas

Copy link
Copy Markdown
Member

notte sessions start --help gives no hint that most of its flags are already on.

The OpenAPI spec declares defaults for ten SessionStart fields, but SchemaRef had no Default member, so the value was never unmarshalled. Field.Default was always nil, getDefaultValue's Default branch was dead code, every flag registered as a Go zero value, and cobra printed nothing.

The result reads backwards:

Flag Real default What help implied
--solve-captchas true off unless passed
--headless true off unless passed
--use-file-storage true off unless passed
--max-duration-minutes 15 unbounded
--idle-timeout-minutes 3 unbounded

The timeouts are the ones that bite silently — a session vanishing after 15 minutes is hard to explain when nothing says 15 anywhere.

After

--headless                 Whether to run the session in headless mode. (API default: true)
--solve-captchas           Whether to try to automatically solve captchas (API default: true)
--use-file-storage         Whether FileStorage should be attached to the session. (API default: true)
--max-duration-minutes int Maximum session lifetime in minutes ... (API default: 15)

The default goes in the description, not the registered value

That distinction is the whole point, and I got it wrong first.

Request builders send non-boolean fields on a zero-value check (if X != "", if X > 0). Registering the API default would make those checks always true, so every session start would transmit browser_type=chromium, max_duration_minutes=15, idle_timeout_minutes=3 — and the API could never change its own default again, because the client would always override it. That's the same failure #58 fixed, in reverse.

An intermediate version of this branch did exactly that. getDefaultValue is now pinned to zero values with a comment explaining why, so nobody "fixes" it later.

Booleans are already gated on cmd.Flags().Changed(), so nothing about what gets sent changes.

Verification

A session started with no flags is byte-identical to v0.0.30:

{"use_file_storage": true, "headless": true, "solve_captchas": true, "max_duration_minutes": 15}
  • go build, go vet, gofmt -l clean
  • go test ./internal/... — all 10 packages pass
  • make generate reproduces the committed output

Also picks up defaults on personas create and vaults create.

Note on use_file_storage

This started from a question about whether the recent API-side change making use_file_storage default to true was reaching the CLI. It is — the CLI omits the parameter when the flag isn't passed, so the server default applies, and a session started without flags reports use_file_storage: true. No CLI change was needed for the behaviour; only the help text was misleading.

Worth knowing the flag is now effectively an opt-out: --use-file-storage=false disables the session file store, after which notte page download fails with Cannot execute download_file because no storage object was provided. If that's undesirable, the flag could be dropped or renamed, but that's a separate call.

🤖 Generated with Claude Code

`notte sessions start --help` gave no hint that most of its flags are already
on. The OpenAPI spec declares defaults for ten SessionStart fields, but
SchemaRef had no Default member, so the value was never unmarshalled,
Field.Default was always nil, and getDefaultValue's Default branch was dead
code. Every flag registered as a Go zero value and cobra printed nothing.

The result read backwards. --solve-captchas, --headless and --use-file-storage
all default to true server-side, yet help implied they were off unless passed;
--max-duration-minutes silently caps sessions at 15 and --idle-timeout-minutes
at 3, which is the sort of thing users discover when a session disappears.

Now: parse `default` from the spec and report it in the help text.

  --headless               Whether to run the session in headless mode. (API default: true)
  --solve-captchas         ... (API default: true)
  --use-file-storage       ... (API default: true)
  --max-duration-minutes   ... (API default: 15)

The default is surfaced in the description, NOT as the registered flag value,
and that distinction is the point. Request builders send non-boolean fields on
a zero-value check (`if X != ""`, `if X > 0`), so registering the API default
would make those checks always true - every session start would transmit
browser_type=chromium, max_duration_minutes=15, idle_timeout_minutes=3, and the
API could never change its own default again because the client would always
override it. That is the same failure the --only-active work fixed, in reverse.
An intermediate version of this change did exactly that; getDefaultValue is now
pinned to zero values with a comment explaining why.

Booleans are already gated on cmd.Flags().Changed(), so nothing about what gets
sent changes here. Verified: a session started with no flags still reports
use_file_storage=true, headless=true, solve_captchas=true,
max_duration_minutes=15, identical to v0.0.30.

Also picks up defaults on personas create and vaults create.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown

Greptile Summary

The PR propagates OpenAPI defaults into generated Cobra help descriptions while deliberately retaining Go zero values for registered flags.

  • Adds default metadata to the generator’s schema model and field conversion.
  • Annotates generated agent, session, persona, and vault flag descriptions with API defaults.
  • Keeps request construction behavior unchanged by removing API defaults from flag registration.

Confidence Score: 4/5

The PR appears safe to merge functionally, with non-blocking cleanup needed for missing regression coverage and the unused compiled generator artifact.

The generated help changes preserve zero-valued flag registration and no current runtime failure was established, but the parser/code-generator behavior is untested and an unnecessary binary is tracked.

Files Needing Attention: scripts/gen-flags/codegen.go, scripts/gen-flags/parser.go, gen-flags

Important Files Changed

Filename Overview
scripts/gen-flags/parser.go Parses and propagates OpenAPI default values, but the new behavior has no targeted automated coverage.
scripts/gen-flags/codegen.go Appends API defaults to help while preserving zero-value registration; targeted tests should pin both behaviors.
internal/cmd/sessionstart_flags.gen.go Regenerated session help now accurately displays scalar API defaults without changing registered flag values.
gen-flags Adds an unused compiled generator artifact that should be removed from source control.

Fix All in Claude Code

Prompt To Fix All With AI
### Issue 1
scripts/gen-flags/codegen.go:164-175
**Default generation lacks regression tests**

The new schema-default parsing and help-generation behavior has no unit or integration coverage, so regressions can silently remove or misformat API defaults—or register them as client-side values—without a targeted test detecting the change.
- Add a comment if the PR does n... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))

### Issue 2
gen-flags:1
**Unused generator binary is tracked**

Generation runs `scripts/gen-flags` directly from source, so this compiled, platform-specific executable has no repository consumer and adds opaque binary churn that can become stale independently of the generator source.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "fix: show the API's default in flag help" | Re-trigger Greptile

@giordano-lucas
giordano-lucas merged commit 72cd188 into main Aug 6, 2026
4 checks passed
giordano-lucas added a commit that referenced this pull request Aug 6, 2026
* feat: add --headed, --no-solve-captchas and --no-file-storage

Three session-start options default to true server-side, which left their flags
shaped as opt-ins for something already on. Passing --headless or
--solve-captchas changed nothing, and turning either off meant the double
negative `--headless=false`. #60 made the defaults visible in help; this gives
each a positive way to opt out.

  notte sessions start --headed              # was --headless=false
  notte sessions start --no-solve-captchas   # was --solve-captchas=false
  notte sessions start --no-file-storage     # was --use-file-storage=false

Naming follows one rule: use the word the ecosystem already has, otherwise
prefix with --no-. Playwright exposes a visible browser as --headed and users
arrive from Playwright and Puppeteer, so that is what they will guess. The other
two have no comparable term and take the --no- prefix used by git, docker, npm
and curl.

--no- rather than --disable- specifically because Chromium's own flags are
--disable-* and this command forwards them verbatim through --chrome-args.
Distinct prefixes mean `--no-file-storage --chrome-args="--disable-gpu"` reads
unambiguously as one Notte flag and one browser flag.

The originals are deliberately NOT deprecated. Pinning a value explicitly is
legitimate defensive scripting: a caller who needs a headless session should not
have to trust that the server default stays true, which is exactly the failure
mode #58 and #60 dealt with. Deprecating would also print a warning on the most
common invocation in our own docs. Passing both spellings at once is an error
rather than letting precedence silently pick a winner.

Omitting the new flags sends nothing, so the server default still applies -
covered by a test, since sending an explicit value would re-freeze the default
into the client.

Verified against the API: --headed -> headless=false, --no-file-storage ->
use_file_storage=false, --no-solve-captchas -> solve_captchas=false, no flags ->
all three true, and `--headed --headless` is rejected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: validate session-start flag conflicts before stopping the current session

Review catch, and a real one. runSessionsStart prompts, stops the current
session and clears the local pointers before it builds the request, so the
conflict check I put next to the request build ran too late:

  notte sessions start --headed --headless

with an active session stopped that session, wiped current_session,
current_viewer_url and current_agent, and only then refused to start a new one.
The user ends up with neither.

Validation now hangs off PreRunE, which cobra runs before RunE and therefore
before any of that. applySessionStartOptOuts revalidates so the invariant does
not depend on the command wiring.

The pre-existing proxy check had exactly the same shape - it also ran after the
stop - so it is extracted into validateSessionStartProxyFlags and runs from the
same place. `--proxy --proxy-country=us` no longer costs the caller their
session either.

Verified against the API with a session active: both conflicts now error while
the original session stays `active`. Previously it would have been stopped.

The regression test asserts the ordering rather than just the error - that
sessionsStartCmd has a PreRunE at all, and that RunE does not run for an invalid
combination. Testing only for a returned error would pass even with the bug.

Also fixes the gofumpt failure from CI: the table literal in
sessionstart_optout_test.go now uses named fields. `gofmt` accepted it, which is
why it slipped through locally; golangci-lint runs gofumpt, which is stricter.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
giordano-lucas added a commit that referenced this pull request Aug 6, 2026
…lp (#62)

The README still described the pre-v0.0.31 flag surface. It showed
--solve-captchas and --use-file-storage as things you switch on, when all three
of those options default to true server-side, and it did not mention --headed,
--no-solve-captchas or --no-file-storage at all.

  --headed                    # was: --headless (a no-op against the default)
  --no-solve-captchas         # was: --solve-captchas
  --no-file-storage           # was: --use-file-storage

Also:

- document the session lifetime that #60 surfaced: 3 minutes idle, 15 minutes
  total. Neither default appeared in the README, and both are short enough that
  the next command fails with a bare "Session closed" without saying why
- drop --headless and --solve-captchas from examples that only passed them to
  get the default behaviour
- correct `notte page upload`. The README showed a positional
  `notte page upload <id> <file>`; it is a required --file flag, and the name
  refers to a file in the uploads store rather than a path on the caller's
  machine, so a local path fails with "Unable to get file: <path> for upload".
  The `notte files upload` step it needs first is now spelled out, as is the
  matching `notte files download --from session` for retrieving what
  `page download` produced

Separately, fixes a cosmetic bug I shipped in #61. Cobra's UnquoteUsage takes
the first backquoted span in a usage string as the flag's value placeholder, and
the --no-file-storage description had `notte page download` in backticks, so
v0.0.31 renders it as:

  --no-file-storage notte page download   Do not attach FileStorage...

as though the flag took an argument. Single quotes instead.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant