Make the stash CLI drivable by agents (and CI / pipes), not just interactive humans — additively, so nothing changes for a person in a real terminal.
Motivation: npx stash init (and stash auth login) hung on an interactive region picker with no non-interactive escape hatch — the last blocker to scripting stash init (DATABASE_URL / proxy / handoff-target already had escape hatches).
Shipped in #569
--region <slug> / STASH_REGION on auth login + init — skip the region picker; a missing/unknown region in a non-TTY context exits with an actionable error instead of hanging.
stash auth login --json — newline-delimited device-code events. The first (authorization_required) carries the verification URL, so an agent can trigger auth and hand the browser step to a human — only a human completes it. --no-open suppresses the browser launch.
stash auth regions (+ --json → [{slug,label}]) — discover valid --region values up front instead of learning them from an error.
- Region resolution mirrors the
DATABASE_URL resolver (TTY && !CI gate); lives in a native-free module with unit + E2E coverage.
Follow-ups (not in this PR)
PR: #569
Make the
stashCLI drivable by agents (and CI / pipes), not just interactive humans — additively, so nothing changes for a person in a real terminal.Motivation:
npx stash init(andstash auth login) hung on an interactive region picker with no non-interactive escape hatch — the last blocker to scriptingstash init(DATABASE_URL / proxy / handoff-target already had escape hatches).Shipped in #569
--region <slug>/STASH_REGIONonauth login+init— skip the region picker; a missing/unknown region in a non-TTY context exits with an actionable error instead of hanging.stash auth login --json— newline-delimited device-code events. The first (authorization_required) carries the verification URL, so an agent can trigger auth and hand the browser step to a human — only a human completes it.--no-opensuppresses the browser launch.stash auth regions(+--json→[{slug,label}]) — discover valid--regionvalues up front instead of learning them from an error.DATABASE_URLresolver (TTY && !CIgate); lives in a native-free module with unit + E2E coverage.Follow-ups (not in this PR)
packages/cli/src/commands/auth/region.ts,// TODO: pull from the CTS API);@cipherstash/authtreats region as an opaque string andpackages/stack/packages/protectonly carry a single-valueCtsRegionstype. When a CTS region API exists, the CLI + SDK should both read from it.'stash': minor) — omitted from feat(cli): non-interactive / agent-friendly auth + region flags #569 because it lives outsidepackages/cli.PR: #569