feat(quickstart): interactive provider selection + API-key entry#18
Merged
Conversation
Adds 8 new BATS tests that pin the upcoming behavior: - 'synthetic'/'alibaba'/'all'/'synthetic,alibaba' positional args honor the selection. - Bare cmd_quickstart in non-TTY (BATS' run) falls back to 'all'. - Unknown arg returns nonzero with a helpful error. - 'synthetic' with only alibaba JSON present errors out. - Whitespace in comma-separated lists tolerated. Currently 21 existing + 4 new pass (the 4 spurious passes will start exercising real logic once dispatch is implemented in green phase). 4 new tests fail because dispatch and arg validation are not yet implemented.
cmd_quickstart now accepts an optional positional arg to select which catalog(s) to provision: llm-env quickstart # all available (CI-safe) llm-env quickstart all llm-env quickstart synthetic llm-env quickstart alibaba llm-env quickstart synthetic,alibaba # comma-separated, whitespace tolerated Unknown sources produce a clear error and non-zero exit. Selecting a source whose JSON file isn't present is also an error (not a silent no-op). New helper _qs_resolve_selection encapsulates the parse-validate-emit logic so it can later be reused by the interactive menu (Phase 2). The non-TTY default path is unchanged: when run with no arg, every available JSON is processed, matching today's behavior — confirmed by the existing 21 BATS tests which use BATS' run command (no TTY). 29/29 quickstart BATS tests pass; full unit/integration/system suites green.
Adds tests/integration/test_quickstart_interactive.bats with 25 tests
covering the five helpers needed by the interactive quickstart flow:
_qs_detect_shell_rc — bash/zsh/fish/csh/tcsh/other
_qs_key_already_set — env, rc-file, leading-whitespace, quoting
_qs_append_export_to_rc — single-quote escaping, $/`/\ metachars,
idempotent (no duplicate export lines),
missing-trailing-newline handling
_qs_prompt_api_key — empty/'s'/whitespace-only treated as skip
_qs_verify_key — mocked curl, success and failure paths
Plus one integration test through cmd_quickstart with stubbed
interactivity to confirm env-already-set short-circuits the prompt.
curl/wget calls mocked throughout — no network in tests, no API
quota consumed. Plan requirement: "Tests must use mocks/fakes for
all campaign operations" applied here as "no real provider calls".
Currently red — helpers don't exist yet (exit 127). Implementation
arrives in the next commit.
Wires up the user-facing funnel for v1.5: when running interactively,
cmd_quickstart now:
1. (already in last commit) Resolves which catalog(s) to provision.
2. For each selected source, processes the JSON as before, then:
3. Skips key entry entirely if LLM_<vendor>_API_KEY is already set
in env OR already exported in the user's shell rc.
4. Otherwise prints the signup URL with the embedded referral code,
pauses for the user to grab their key, then prompts for the key
(input hidden).
5. Empty/'s'/whitespace-only input = skip — no rc write.
6. Otherwise appends `export VAR='<key>'` to the user's shell rc
(~/.bashrc or ~/.zshrc, mirroring install.sh's detection).
7. Single-quote-escapes the key for safe embedding ($, `, \, '
all round-trip correctly).
8. Refuses to duplicate the export if a line for the same VAR
already exists.
9. Verifies the key by invoking cmd_test against
anth_<vendor>_kimi-k2.5; failures print a warning but never
abort quickstart (verification is informational).
Five new helpers do the work:
_qs_is_interactive TTY-detection wrapper (stubbable).
_qs_detect_shell_rc bash/zsh → ~/.{bash,bash_profile,z}rc;
fish/csh/tcsh/other → empty (fallback).
_qs_key_already_set env-var or rc-file export-line check.
_qs_prompt_api_key masked read with skip-on-empty.
_qs_append_export_to_rc idempotent, single-quote-escaped append.
_qs_verify_key cmd_test wrapper, always returns 0.
Non-TTY behavior preserved exactly — the existing 21 BATS tests and
the docker e2e test still pass without modification because BATS'
`run` doesn't allocate a TTY, so _qs_is_interactive returns false
and the entire interactive branch is skipped.
25/25 new interactive tests pass; 29/29 quickstart tests pass.
Adds 3 hostile-input cases to lock in graceful behavior: - append_export with rc path that's a directory → nonzero, no crash - append_export with rc path that's unwritable (chmod 000) → nonzero - append_export with a value containing an embedded newline → safely embedded inside the single-quoted form (newline preserved through source-and-read round-trip) 28/28 tests pass.
README "Quickstart" section now explains the menu prompt, the positional-arg shortcuts (synthetic/alibaba/all/comma-list), and that non-TTY invocation falls back to the all-providers default. docs/claude-code-quickstart.md collapses former Steps 2-5 (run quickstart, sign up, paste key, test) into a single Step 2 since quickstart now does signup-prompt-paste-verify in one flow. Subsequent steps renumbered (Step 3 = reload shell, Step 4 = set provider, Step 5 = run claude, Step 6 = switch models).
Cumulative adversarial review caught this: \`./llm-env quickstart synthetic\` from the CLI was silently ignoring the arg and provisioning all sources. The case-statement dispatcher at the bottom of llm-env was calling \`cmd_quickstart\` with no args where it should have shifted past the subcommand name and forwarded "$@". The BATS tests passed because they call \`cmd_quickstart\` directly, bypassing the dispatcher. Adding a regression guard test that invokes the script-as-binary so future bugs at the dispatcher boundary get caught. 30/30 quickstart BATS tests pass.
samestrin
added a commit
that referenced
this pull request
May 1, 2026
Interactive quickstart (PR #18) is the v1.6.0 headline feature. Backfills CHANGELOG with the user-visible additions and explicitly notes that non-TTY behavior is preserved exactly so CI and scripted installs are unaffected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
`llm-env quickstart` becomes the v1.5 funnel UX promised in `docs/claude-code-quickstart.md`. When run interactively, it now:
/.bashrc` or `/.zshrc`, and runs a verify call to confirm the key works.Non-interactive paths preserved exactly: `./llm-env quickstart` from CI/scripts (`! -t 0`) does what it always did — provision every available catalog, no prompts. Existing 21 BATS tests passed unmodified.
Adds positional-arg dispatch for scripted use:
Test plan
Adversarial coverage
Hostile inputs verified:
\` round-trip correctly through single-quote-escaped export lines