feat(auth): browser-assisted CLI login + profiles + auth/team commands#84
Open
LanusseMorais wants to merge 4 commits into
Open
feat(auth): browser-assisted CLI login + profiles + auth/team commands#84LanusseMorais wants to merge 4 commits into
LanusseMorais wants to merge 4 commits into
Conversation
Collaborator
Author
|
@greptile review please |
…sist legacy migration, don't overwrite default profile on login, reset poll backoff + fail-fast on approved-without-key, honor LATITUDESH_TOKEN in auth status, env api-version for --with-token, stderr warnings, filepath.Dir)
Collaborator
Author
|
@greptile review |
leandroh
approved these changes
Jun 9, 2026
…e run hooks for robust root PreRunE
Collaborator
Author
|
@greptile review please |
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
Adds a browser-assisted login flow to
lsh, so users no longer need to manually copy an API token from the dashboard. Adds multi-team support via profiles, plus commands to inspect and switch the active context.New commands
lsh loginlsh login --with-token <T>/user/profileand stores it under a profile.lsh auth statuslsh auth logout [--profile X | --all]browser.lsh profile use <name>lsh profile listNew global flag and env vars
--profile <name>LATITUDESH_TOKENLSH_PROFILELSH_PROJECT--projectflag (skips the interactive prompt).Interactive project picker
Commands that take
--project(e.g.lsh servers list,lsh servers create) now prompt interactively when the flag is missing and stdin is a TTY:For list commands, picking All projects (or passing
--all-projects) lists across every project.In non-interactive contexts the command fails with an actionable message:
Config file
The config at
~/.config/lsh/config.jsonnow supports multiple profiles. Existing single-token configs are migrated automatically on first run.Before:
{ "Authorization": "ak_xxx", "API-Version": "2023-06-01" }After (auto-migrated as profile
default):{ "default_profile": "acme", "profiles": { "acme": { "authorization": "ak_xxx", "team_id": "...", "team_name": "Acme", "team_slug": "acme", "email": "you@example.com", "source": "with-token", "api_version": "2023-06-01" } } }Permissions:
0700directory,0600file.Backward compatibility
lsh login <token>(positional) still works but prints a deprecation warning.--project=<id>etc.) unchanged.Breaking change
lsh servers listandlsh virtual-networks listno longer silently list across all projects when--projectis missing. Behaviour now:Existing scripts can opt back into the old behaviour with
--all-projects,--project=<id>, orLSH_PROJECT=<id>.Notes
cli/get_servers_operation.go,cli/get_virtual_networks_operation.go) gained a manually-added--all-projectsflag. Lines are tagged// MANUAL — keep when regeneratingto survive future swagger regenerations.How to test
go build -o ./lsh-dev .1. Token login (covers most of the flow without needing the browser page)
Expected:
auth statusshowsEmail,Team,Source: with-token.profile listshows the profile with a*marker.profilesmap with the team slug as key.2. Switch between profiles
Run
login --with-tokentwice with tokens from different teams (or pass--profile=<name>to override the auto-naming).3. Logout
Logout on a profile with
source: browserrevokes the API key remotely (you can verify under Settings → API Keys); logout on a--with-tokenprofile only clears it locally.4. Project picker
After logging in, run a command that needs a project:
Expected: an interactive picker listing projects + an All projects entry. Selecting a project filters results; selecting All projects lists everything.
Other invocations to test:
5. Browser-assisted login
Requires the matching dashboard page deployed (the page lives in a separate repo and is being shipped in parallel — you'll see the URL the CLI prints).
Expected: prints the URL + a
user_code; opens the browser if available; polls until you approve. After approval, prints✅ Logged in as .... If the browser cannot be opened (SSH session, no DISPLAY, piped stdin), the CLI prints the URL and waits — you open it from another machine.6. Config migration
Manually drop a legacy config and verify it gets migrated:
Expected: a
defaultprofile materialized from the legacy field,source: with-token. Subsequent runs are no-ops.Greptile Summary
This PR adds browser-assisted login via a polling CLI-session flow, multi-team profile support, interactive project picker, and
auth/profilesubcommand groups. Existing single-token configs are auto-migrated on first load and the change is backward-compatible for scripted callers via--all-projects,LSH_PROJECT, andLATITUDESH_TOKEN.cli/auth_login_browser.go): creates a server-side CLI session, polls until approved or timed-out, and persists the resulting API key as a named profile.internal/config/): newFile/Profiletypes replace the flat token map;migrateLegacyIntosilently upgrades old configs on firstLoad, now with a best-effortSaveto persist the migration to disk.cli/project_flag.go,internal/prompt/project.go):PersistentPreRunEresolves--projectfor every command that needs one — env var → explicit flag → interactive prompt → error — and the "All projects" path leaves--projectunset so the generated commands fall back to their original no-filter behavior.Confidence Score: 5/5
The PR is safe to merge. The auth, config, and polling logic is sound, previously-flagged issues have been addressed, and the change ships good test coverage for both the config package and the authclient.
The migration, polling, and profile-persistence paths all have dedicated tests and handle edge cases (empty profiles, concurrent legacy+new config, approved-without-key). The remaining observations are cosmetic output issues that do not affect correctness.
No files require special attention.
cli/auth_login_browser.gohas a minor UX inconsistency in the headless message and an edge case in the poll loop for unexpected status values, but neither affects the correctness of the login flow.Sequence Diagram
sequenceDiagram participant User participant CLI as lsh participant API as Latitude API participant Browser User->>CLI: lsh login CLI->>API: POST /auth/cli_sessions API-->>CLI: id, secret, user_code, authorize_url CLI->>User: Print URL and user_code CLI->>Browser: Open authorize_url if not headless loop Poll every 2s up to 5m30s CLI->>API: GET /auth/cli_sessions/id with X-CLI-Secret alt status pending API-->>CLI: status pending else status approved API-->>CLI: status approved, api_key, team, user CLI->>CLI: Save profile to config.json CLI->>User: Logged in as email on team else 404 within 15s grace API-->>CLI: 404 not yet propagated else 410 or 401 API-->>CLI: Terminal error CLI->>User: Error message end end note over User,CLI: Token login path User->>CLI: lsh login --with-token TOKEN CLI->>API: GET /user/profile with token API-->>CLI: email CLI->>API: GET /team with token API-->>CLI: team id, name, slug CLI->>CLI: Save profile to config.json CLI->>User: Logged in confirmation note over User,CLI: Logout path User->>CLI: lsh auth logout CLI->>CLI: Load config, resolve profile opt source is browser CLI->>API: DELETE /auth/api_keys/key_id end CLI->>CLI: RemoveProfile, Save config CLI->>User: Removed profilePrompt To Fix All With AI
Reviews (3): Last reviewed commit: "fix(auth): send API-Version header on au..." | Re-trigger Greptile