Skip to content

Agentic auth improvements: lazy login, --json consistency, and pc target fixes#83

Merged
austin-denoble merged 7 commits intomainfrom
adenoble/fix-target-and-json-flag
Apr 6, 2026
Merged

Agentic auth improvements: lazy login, --json consistency, and pc target fixes#83
austin-denoble merged 7 commits intomainfrom
adenoble/fix-target-and-json-flag

Conversation

@austin-denoble
Copy link
Copy Markdown
Collaborator

@austin-denoble austin-denoble commented Apr 2, 2026

Problem

After previous changes to daemonize the login flow and improve overall I/O, there were still some rough edges when working with the CLI through an agent. Lack of consistent --json flag representation was still an issue for a few flags, primarily around not supporting a shorthand option. The pc target command also needed changes to better support "headless", or agentic operation effectively. In-client documentation around the specifics of some of these operations also need to be improved to better guide users and agents when authenticating.

Solution

This PR improves the CLI's behavior in agentic/non-TTY contexts (Claude Code, Cursor, other AI coding agents). It builds on the daemon-backed login flow from #82

-j shorthand added to login commands

pc login and pc auth login were missing the -j shorthand for --json, inconsistent with every other command. Fixed.

Lazy auth completion

Added login.EnsureAuthenticated, called from a PersistentPreRun hook on the root command. After a successful browser login, the next command run — any command — automatically detects the completed session, reloads credentials, and initializes the target org/project context. A second pc login --json call is no longer required before running other commands.

Commands that don't require authentication are explicitly exempted: pc login, pc logout, pc auth login/logout/configure/clear/status/_daemon, pc auth local-keys/list, pc target (which handles its own auth after local-state early returns), pc version, and all pc config subcommands.

pc target fixes

  • TTY auto-detectionpc target now detects non-TTY stdout and enables JSON mode automatically, consistent with pc login.
  • No-flags JSON modepc target --json with no targeting flags now returns the current target context as JSON (equivalent to --show --json) instead of an error. This early return is correctly placed before auth and API calls, so it works for API-key users and requires no credentials.
  • --show and --clear unblocked — These are local-state-only operations; they now return before the auth gate and before any API calls.
  • Re-auth URL stays on stderr — When pc target triggers an org-switch re-auth, the auth URL is printed to stderr only. Stdout remains a single JSON document, keeping output compatible with jq . and other single-document parsers.
  • Missing return after exit.Error — Added return guards after all exit.Error calls in target and root pre-run, preventing fall-through when the exit handler is mocked in tests.

applyAuthContext / RunPostAuthSetup refactor

Extracted the org/project state-setting logic from RunPostAuthSetup into a new applyAuthContext helper that returns the user's email. This eliminates a redundant oauth.Token + ParseClaimsUnverified call that RunPostAuthSetup was making immediately after applyAuthContext had already fetched the same data. applyAuthContext now also always writes state.TargetProj (clearing it when the org has no projects), preventing stale project data from a previous session from appearing in the authenticated JSON response.

Root pre-run JSON error output

EnsureAuthenticated errors in the root PersistentPreRun now check both TTY state and the command's own --json/-j flag, so auth errors are machine-readable when a caller explicitly requests JSON even in a TTY context.

Deduplication

Extracted printTargetContextJSON() in target.go, replacing three identical blocks that each read state.GetTargetContext(), masked the API key, and printed JSON.

Documentation

Updated pc login, pc auth login, and pc target help text to document the interactive vs. agentic flows, the two-call pending/authenticated pattern, session resumability, and the lazy context initialization behavior. Also fixed a typo in pc target's example (-project--project).

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update
  • Infrastructure change (CI configs, etc)
  • Non-code change (docs, etc)
  • None of the above: (explain here)

Test Plan

Interactive login (TTY)

  • pc login opens a browser and completes auth, sets target org/project, prints success message
  • pc auth login same as above

Agentic login (non-TTY / --json)

  • pc login --json returns {"status":"pending","url":"...","session_id":"..."} and exits immediately
  • -j shorthand works identically on both pc login and pc auth login
  • Second pc login --json after completing browser auth returns {"status":"authenticated",...} with org/project populated
  • Running any other command (e.g. pc index list --json) after browser auth — without a second pc login call — succeeds and sets target context automatically
  • Piping output (pc login | cat) triggers non-TTY path automatically without needing --json

Lazy auth / EnsureAuthenticated

  • After pc login --json + browser auth, pc index list --json works without a second login call
  • pc auth status works with no credentials (not blocked by auth gate)
  • pc auth local-keys list works with no credentials (not blocked by auth gate)
  • pc version works with no credentials
  • All pc config subcommands work with no credentials

pc target

  • pc target --show works with no credentials
  • pc target --clear works with no credentials
  • pc target --json (no flags) returns current target context as JSON, works with no credentials
  • pc target --json --org "name" sets org and returns updated context as JSON
  • pc target --json --org "name" --project "name" sets both and returns updated context
  • pc target in a TTY launches interactive selector as before
  • pc target in a non-TTY (or with --json) without targeting flags returns current context rather than erroring

Auth errors

  • Running a command requiring auth with no credentials returns {"error":"..."} to stdout when stdout is non-TTY
  • Running a command requiring auth with no credentials and --json flag returns {"error":"..."} to stdout even in a TTY
  • "authentication in progress" error includes the auth URL when daemon is still running

Note

Medium Risk
Adds a global authentication pre-check for most commands and changes login/target behavior in non-TTY JSON mode, which could affect automation and command execution paths if the skip list or auth detection is incorrect.

Overview
Adds a root-level auth gate for most commands. pc now runs login.EnsureAuthenticated() in PersistentPreRun, with a curated skip list for commands that manage credentials/local state, and auto-detects JSON mode (non-TTY stdout or --json/-j) to format auth errors appropriately.

Improves non-interactive/agentic UX. login and auth login gain -j shorthand and updated help/examples; target now auto-enables JSON mode in non-TTY contexts, supports pc target --json as an auth-free “show current context” path, and centralizes JSON context printing.

Refactors and extends post-auth setup. Login utilities split context initialization into applyAuthContext(), ensure target project state is cleared when no projects exist, keep stdout clean during wait-mode by printing auth URLs to stderr, and introduce EnsureAuthenticated() to lazily complete pending daemon sessions and auto-initialize org/project context after successful browser auth.

Reviewed by Cursor Bugbot for commit ddb7ecd. Bugbot is set up for automated code reviews on this repo. Configure here.

…, same as login, when pc target needs to authenticate the URL is output to stdout properly, add shorthand --json flag for needed commands
…show/--clear are now not blocked by auth state
…e sure auth local-keys is not blocked by auth logic, remove duplicated output
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

@austin-denoble austin-denoble changed the title Fix target TTY detection, add shorthand --json | -j flag Agentic auth improvements: lazy login, --json consistency, and pc target fixes Apr 6, 2026
@austin-denoble austin-denoble merged commit 01e7566 into main Apr 6, 2026
8 checks passed
@austin-denoble austin-denoble deleted the adenoble/fix-target-and-json-flag branch April 6, 2026 03:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant