Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
79715e6
feat(cli): add MissingInput and MissingPrerequisite error variants
itzlambda May 15, 2026
c456b4f
feat(cli): add interactivity gate with ask_text/ask_select/ask_confirm
itzlambda May 15, 2026
83f1bc3
test(cli): cover interactivity gate behavior under non-interactive mode
itzlambda May 15, 2026
9626131
feat(cli): render MissingInput/MissingPrerequisite errors as JSON or …
itzlambda May 15, 2026
48c048b
feat(cli): hide spinners in non-interactive mode
itzlambda May 15, 2026
b50b755
feat(cli): ssh-keys add runs non-interactively with --file/--name/--f…
itzlambda May 15, 2026
13a1c36
test(cli): hang-smoke harness for non-interactive command execution
itzlambda May 15, 2026
e51e945
style(cli): move gate test module after public fns (clippy items_afte…
itzlambda May 15, 2026
111c293
fix lints
itzlambda May 15, 2026
a915dda
feat(cli): require explicit delete to replace registered ssh key
itzlambda May 15, 2026
1977c82
refactor(cli): polish non-interactive json error contract
itzlambda May 16, 2026
038c3f8
refactor(cli): drop choices from MissingInput error contract
itzlambda May 18, 2026
f4b154c
Merge branch 'main' into feat/non-interactive-cli-foundation
itzlambda May 18, 2026
38c2381
refactor(cli): simplify interactivity gate and drop redundant spinner…
itzlambda May 18, 2026
4717ec1
refactor(cli): drop OnceLock memoization from interactivity gate
itzlambda May 18, 2026
f657283
refactor(cli): add prompt parameter to interactive ask helpers
itzlambda May 18, 2026
dacbb0c
fix(cli): short-circuit OAuth auto-login in non-interactive mode
itzlambda May 18, 2026
d7b5577
docs(cli): changelog entry for non-interactive mode
itzlambda May 18, 2026
d93f76d
test(cli): restore prior BASILICA_NON_INTERACTIVE value in RAII guard
itzlambda May 18, 2026
950704d
fix(cli): treat empty BASILICA_NON_INTERACTIVE as unset and correct s…
itzlambda May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions crates/basilica-cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Non-interactive mode for agent and CI usage. Auto-detected when stdin
is not a TTY, or forced with `BASILICA_NON_INTERACTIVE=1`. In this
mode every interactive prompt surfaces a structured error instead of
blocking on stdin.
- Errors carry a `field` identifier and a `hint` naming the flag or
command to run. Rendered as single-line JSON on stderr when
`--json` is set, and as human-readable text otherwise.

### Changed
- OAuth auto-login is skipped in non-interactive mode: commands that
need authentication now exit with a `missing_prerequisite` error
pointing at `basilica login` (or `BASILICA_API_TOKEN`) instead of
starting a callback server that would block for 300s.
- `basilica ssh-keys add` no longer silently generates a new key under
`~/.ssh` in non-interactive mode when no local public keys are
present; pass `--file <path>` to an existing public key instead.

## [0.29.0] - 2026-05-04

### Added
Expand Down
2 changes: 2 additions & 0 deletions crates/basilica-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,5 @@ basilica-sdk = { path = "../basilica-sdk" }
basilica-validator = { path = "../basilica-validator", features = ["client", "cli"] }

[dev-dependencies]
serial_test = "3"
assert_cmd = "2"
13 changes: 13 additions & 0 deletions crates/basilica-cli/src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,19 @@ impl Args {
Err(err) => {
// Check if this is specifically a login_required error
if matches!(&err, CliError::Auth(_)) {
// In non-interactive mode, never start an OAuth flow — the
// callback server / device flow will block on user action
// (300s timeout). Surface a structured error instead.
if matches!(
crate::interactive::gate::current(),
crate::interactive::gate::Interactivity::NonInteractive
) {
return Err(CliError::MissingPrerequisite {
field: "authentication".into(),
hint: "Not authenticated. Run `basilica login` (or `basilica login --device-code` on headless hosts), or set BASILICA_API_TOKEN.".into(),
});
}

// Inform user we need to authenticate
println!("You need to authenticate to continue.");
println!();
Expand Down
Loading
Loading