feat(cli): structured error for non-interactive workspace selection#68
Conversation
At the workspace-selection step, a non-interactive caller (no TTY or --json, with >=2 workspaces) now gets WORKSPACE_SELECTION_REQUIRED listing the workspaces under context.workspaces, instead of a plain "requires a real terminal" string. The caller re-runs with `alien workspaces set <name>`. The interactive arrow-key menu is unchanged. Also remove `alien login --json`: structured workspace data comes from `alien workspaces ls --json`, so a JSON mode on login is redundant.
Greptile SummaryThis PR replaces the opaque "requires a real terminal" string error in
Confidence Score: 5/5The change is a tightly scoped error-type upgrade with no mutations to auth logic and no new async paths; safe to merge. All changed paths are narrow: the new structured error is only returned when multiple workspaces exist and the caller is non-interactive, the single-workspace fast path is untouched, and the removal of --json from alien login is intentional and self-consistent. The test directly exercises the context.workspaces payload. No auth state is modified before the error is returned. No files require special attention.
|
| Filename | Overview |
|---|---|
| crates/alien-cli/src/commands/platform/login.rs | Removes the --json flag and LoginOutput struct from alien login; simplifies login_task to always emit human-readable output and forwards json_mode=false to prompt_workspace. |
| crates/alien-cli/src/commands/platform/workspace.rs | Replaces the generic require_prompt ConfigurationError with a structured WorkspaceSelectionRequired error when InteractionMode::current detects machine mode; drops can_prompt import since it is now called internally by InteractionMode::current. |
| crates/alien-cli/src/error.rs | Adds WorkspaceSelectionRequired error variant carrying Vec workspaces and a unit test that asserts the variant serializes context.workspaces correctly via AlienErrorData. |
| crates/alien-cli/src/lib.rs | Updates wants_json_output to return false for Login commands (destructuring the now-fieldless LoginArgs with _); consistent with the removal of the --json flag. |
| crates/alien-cli/src/ui.rs | Renames the test module from tests to command_event_tests to avoid a name collision, no functional change. |
Sequence Diagram
sequenceDiagram
participant Agent
participant CLI as alien CLI
participant Auth as force_login
participant API as Platform API
participant Browser
Note over Agent,Browser: New non-interactive workspace-selection flow
Agent->>CLI: alien login (no TTY)
CLI->>Auth: force_login()
Auth->>Browser: open OAuth URL
Browser-->>Auth: token callback
Auth-->>CLI: AuthHttp
CLI->>API: list_workspaces()
API-->>CLI: ["ws-a", "ws-b", "ws-c"]
Note over CLI: workspaces.len() > 1 AND is_machine() == true
CLI-->>Agent: WORKSPACE_SELECTION_REQUIRED context.workspaces: ["ws-a","ws-b","ws-c"]
Agent->>CLI: alien workspaces set ws-a
CLI->>API: validate_workspace_name("ws-a")
API-->>CLI: ok
CLI->>CLI: save_workspace("ws-a")
CLI-->>Agent: workspace saved
Note over Agent,Browser: Single-workspace or interactive flow (unchanged)
Agent->>CLI: alien login (single workspace)
CLI->>Auth: force_login()
Auth-->>CLI: AuthHttp
CLI->>API: list_workspaces()
API-->>CLI: ["ws-a"]
Note over CLI: workspaces.len() == 1 - auto-select
CLI->>CLI: save_workspace("ws-a")
CLI-->>Agent: human-readable success output
Reviews (1): Last reviewed commit: "feat(cli): structured error for non-inte..." | Re-trigger Greptile
Summary
When something automated runs
alien login— an agent like Claude, a script, anything without a real terminal — it can't use the arrow-key menu to pick a workspace. Before, it hit a dead end ("needs a real terminal"). Now it gets the actual list of workspaces back, so it can pick one with a follow-up command.What an agent sees when it runs
alien login:WORKSPACE_SELECTION_REQUIREDwith the names undercontext.workspaces. ← the new bitalien workspaces set <name>.So instead of a dead-end string, you get back something a machine can act on. I also removed
alien login --json— an agent can get the same list fromalien workspaces ls --json, so login didn't need its own JSON mode.How I tested it
On a local stack, logged in fresh, on an account with 3 workspaces:
alien login, finished in the browser — it ended onWORKSPACE_SELECTION_REQUIREDwith the 3 names and a hint pointing atalien workspaces ls/set.alien workspaces ls --jsongave the list,alien workspaces set <name>saved it,alien workspaces currentconfirmed it.alien login --jsonnow says "unexpected argument".cargo test -p alien-cli --features platformis green, including a test that checks the names actually land incontext.workspaces.