Skip to content

cli: add custom chrome policy flags to browser and pool commands#180

Open
rgarcia wants to merge 1 commit into
mainfrom
hypeship/cli-chrome-policy
Open

cli: add custom chrome policy flags to browser and pool commands#180
rgarcia wants to merge 1 commit into
mainfrom
hypeship/cli-chrome-policy

Conversation

@rgarcia

@rgarcia rgarcia commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds CLI support for setting a custom Chrome enterprise policy (the API's chrome_policy field, already supported by the Go SDK) on three commands:

  • kernel browsers create
  • kernel browser-pools create
  • kernel browser-pools update

Each gains two mutually-exclusive flags:

  • --chrome-policy '<json>' — an inline JSON object
  • --chrome-policy-file <path> — read the object from a file (- reads stdin)

This mirrors the existing --payload / --payload-file and --data / --data-file conventions.

kernel browsers create --chrome-policy '{"BookmarkBarEnabled": false}'
kernel browsers create --chrome-policy-file policy.json
cat policy.json | kernel browser-pools update my-pool --chrome-policy-file -

Design notes

  • A shared parseChromePolicy helper parses into map[string]any, so non-object JSON (arrays, scalars, null) is rejected with a clear error before any request is sent.
  • chrome_policy uses omitzero, which only drops a nil map — a non-nil empty {} would serialize as "chrome_policy":{}. Assignment is therefore guarded by len > 0, so an empty object is treated as "unset".
  • On browser-pools update, an empty {} cannot clear an existing policy (omitzero strips it before it reaches the server). Rather than silently no-op, this surfaces a warning in human output (suppressed under -o json to keep stdout valid).
  • Kernel-managed policies (extensions, proxy, automation) are enforced server-side. The CLI forwards the object verbatim and surfaces the API's error, rather than duplicating a blocklist that would drift.

Scope

  • browsers update and invoke are intentionally excluded: their SDK params structs (BrowserUpdateParams, InvocationNewParams) carry no chrome_policy field, so there's nothing to wire until the SDK is regenerated.
  • The policy echoes back via --output json with no printer changes (response structs already carry the field).

Test plan

  • Unit tests for all three commands: inline policy applied, empty {} omitted (asserted at both the Go field and the serialized JSON), invalid JSON / null rejected, parser covers file + stdin + whitespace + missing-file, and the pool-lease conflict contract is locked (--chrome-policy stays out of the allowed-flag set).
  • make test (go vet + go test ./...) passes; gofmt clean.
  • E2E against a live environment via the built binary: inline/file/stdin create echo the policy; pool create + get persist it; pool update replaces it and an empty {} no-ops without clearing; invalid/null/mutual-exclusion exit non-zero before any API call; and the server correctly rejects ProxyMode / ExtensionInstallForcelist with the CLI surfacing the error.

Note (pre-existing, unrelated)

When a browser-config flag is combined with --pool-id/--pool-name, the existing conflict-confirmation prompt (pterm.DefaultInteractiveConfirm) does not treat EOF / non-TTY stdin as "no", so it blocks in a non-interactive pipeline. This predates this change and affects all config flags equally; flagging it as a possible follow-up.

🤖 Generated with Claude Code


Note

Low Risk
CLI-only wiring to an existing SDK/API field with client-side validation and tests; policy enforcement for kernel-managed keys remains server-side.

Overview
Adds --chrome-policy and --chrome-policy-file (mutually exclusive, - for stdin) so kernel browsers create and kernel browser-pools create / update can send the API’s chrome_policy field. A shared parseChromePolicy helper validates a JSON object before any request; only non-empty policies are attached (len > 0), so {} is not sent on the wire.

On browser-pools update, passing an empty {} does not clear an existing pool policy—the CLI warns in human output and stays silent with -o json. poolLeaseAllowedFlags is extracted so --chrome-policy is not treated as pool-lease-safe; combining it with --pool-id/--pool-name still triggers the existing config conflict warning. README and unit tests cover parsing, omission, warnings, and serialized JSON.

Reviewed by Cursor Bugbot for commit 0d964f8. Bugbot is set up for automated code reviews on this repo. Configure here.

Add --chrome-policy / --chrome-policy-file to `browsers create`,
`browser-pools create`, and `browser-pools update`, wiring the API's
chrome_policy field (already supported by the Go SDK) through the CLI.

The two flags are mutually exclusive; --chrome-policy takes an inline
JSON object and --chrome-policy-file reads one from a path ("-" = stdin),
matching the existing --payload/--payload-file convention. A shared
parseChromePolicy helper validates the input is a JSON object. Blocked
kernel-managed policies are enforced server-side, so the CLI forwards
verbatim and surfaces the API error rather than duplicating the rules.

An explicit empty object is dropped from the request (chrome_policy uses
omitzero, which only drops a nil map, so assignment is guarded by len>0);
on pool update an empty object cannot clear an existing policy, which is
surfaced with a warning in human output.
@rgarcia rgarcia marked this pull request as ready for review June 9, 2026 21:20
@rgarcia rgarcia requested a review from masnwilliams June 9, 2026 21:22
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