Skip to content

feat(login): send install context to the browser consent page (v1.56.0) - #195

Merged
paulkr merged 13 commits into
mainfrom
feat/cli-auth-install-context
Sep 10, 2026
Merged

paulkr merged 13 commits into
mainfrom
feat/cli-auth-install-context

Conversation

@paulkr

@paulkr paulkr commented Sep 9, 2026

Copy link
Copy Markdown
Member

Summary

Browser login now tells the consent page where this CLI is installed, and learns the key's name (and a cancel) back from it. Together with the backend (withoneai/pica-v2#750) and frontend (withoneai/core-ui#733) changes, the key minted by one login / one init --auth browser is named (e.g. CLI · Claude Code · acme) and tagged with scope, project path, machine, OS user, CLI version, and the harnesses using it, so the dashboard can show every install.

  • src/lib/install-context.ts (new): collects scope, project path (project scope only), hostname, OS and release, arch, OS user, the stable device id from ~/.one/device-id, CLI version, installed harnesses (agent registry plus ~/.gemini, ~/.openclaw, ~/.hermes, ~/.devin), and the launching agent from env markers (CLAUDECODE, CODEX_SANDBOX, GEMINI_CLI, CURSOR_AGENT, …). Best-effort: nothing here can fail a login.
  • src/lib/browser.ts: the auth URL carries the context as readable query params; ONE_APP_URL overrides the dashboard origin.
  • src/commands/login.ts: browserLogin({ scope }); the callback accepts name and error=cancelled (state is still verified first), so a browser Cancel ends the wait instead of the 5-minute timeout. The terminal note lists exactly what the page will record.
  • init, whoami, logout show the key name; it is stored as apiKeyName in config.
  • ONE_API_BASE env override for the API origin (mirrors ONE_APP_URL) for running against a local backend.
  • Docs: help text, one guide, skills/one/SKILL.md, README. Version 1.56.0 (minor).

Works against the current page too: the extra params are ignored and the flow behaves as before.

Review fixes (last two commits)

  • One saveCredentials() in lib/config.ts replaces the four hand-built config literals. They dropped the OpenAI key, memory settings, and telemetry opt-out on every re-login, and one login then re-read through resolveConfig() and wrote the project config's key over the new global one. Writes go to exactly the requested scope.
  • The whoami cache records the API base it was fetched from and is withheld when ONE_API_BASE points elsewhere, so a local backend's org and project ids never reach the hosted dashboard, or the reverse.
  • The device id follows the telemetry opt-out: nothing is sent or minted on disk under DO_NOT_TRACK, ONE_NO_TELEMETRY, CI, or telemetry: off. The terminal disclosure and the docs now list it.
  • CURSOR_TRACE_ID no longer counts as an agent launcher (Cursor exports it into every integrated terminal); CURSOR_AGENT still does.
  • Callback: a minted key wins over an error param, error=cancelled is matched exactly and other values surface as a failure with the reason, the key name is stripped of control characters and capped at 120, and EACCES retries like EADDRINUSE for Windows' reserved port ranges.
  • browserLogin uses the agent-aware note and spinner; in agent mode the auth URL goes to stderr so stdout stays one JSON document.
  • getApiBase() honours ONE_API_BASE from .onerc as the README already claimed; one config prefills the stored base rather than the env override and drops the minted key's name when a pasted key replaces it; one whoami shows the name only when the config's key is the one that authenticated; logout shows it without a cached account record; init summaries show it; "Browse all platforms" follows ONE_APP_URL.

Test plan

  • npm run typecheck, npm run build, and the new suites: src/lib/install-context.test.ts (13), src/lib/browser.test.ts (4), src/commands/login.test.ts (7), src/lib/config-api-base.test.ts (6), src/lib/config-credentials.test.ts (3). Full npm test: 528 of 534 pass.
  • Local end to end against the backend and frontend branches with ONE_HOME=/tmp/x ONE_APP_URL=http://localhost:4202 ONE_API_BASE=http://localhost:5005 node bin/cli.js init --auth browser --project: the key landed with name = CLI · Claude Code · cli and the full tag set; whoami shows the name; Cancel in the browser ends the command immediately.
  • npm test also reports six pre-existing resolveConfig failures on macOS (/var vs /private/var in the test's temp path); they fail on main too and are untouched here.

🤖 Generated with Claude Code

paulkr and others added 13 commits September 9, 2026 13:12
…n and install-context tags

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ontext tags

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nt page

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…RL override

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e and cancel on the callback

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n whoami and logout

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…mary

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ackend

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…llback server

- One saveCredentials() in lib/config.ts replaces four hand-built config
  literals (login, init --auth, update-key, fresh setup) that dropped the
  OpenAI key, memory settings and telemetry opt-out on every re-login, and
  writes only the requested scope, so a new global key is no longer
  clobbered by resolveConfig()'s project-first re-read.
- The whoami cache records the API base it came from and is withheld when
  ONE_API_BASE points elsewhere, in both directions.
- getApiBase() honours ONE_API_BASE from .onerc as the README already said.
- `one config` prefills the stored base, not the env override, and drops
  the consent-page key name when a pasted key replaces the minted one.
- `one whoami` shows the key name only when the config's key is the one
  that authenticated (not an ONE_SECRET or .onerc key); logout shows the
  name even without a cached account record; init summaries show it.
- Callback: a minted key wins over an error param, error=cancelled is
  matched exactly and other values surface as a failure with the reason,
  the key name is stripped of control characters and capped at 120, and
  EACCES retries like EADDRINUSE for Windows' reserved port ranges.
- browserLogin uses the agent-aware note and spinner, printing the auth
  URL to stderr in agent mode so stdout stays a single JSON document.
- "Browse all platforms" follows ONE_APP_URL like the rest of init.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…and drop Cursor's editor marker

- No device id is sent, or minted on disk, when telemetry is disabled
  (DO_NOT_TRACK, ONE_NO_TELEMETRY, CI, or telemetry: off); the terminal
  disclosure and the docs now list the device id.
- CURSOR_TRACE_ID is exported into every Cursor integrated terminal, so it
  no longer counts as an agent launcher; CURSOR_AGENT still does.
- A cliVersion() of "unknown" is omitted instead of sent.
- The user assertion tolerates os.userInfo() throwing in containers.
- README notes that ONE_APP_URL / ONE_API_BASE are per-process and never
  persisted, and to pair them with ONE_HOME for a local stack.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tale name, and scoping the write

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The design spec and implementation plan are working notes for building the
feature, not documentation the CLI ships or a contributor needs. The older
unified-memory plan goes with them, since docs/ held nothing else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@paulkr
paulkr merged commit d7bdfd3 into main Sep 10, 2026
7 checks passed
@paulkr
paulkr deleted the feat/cli-auth-install-context branch September 10, 2026 15:32
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