Skip to content

feat(cli): add 'qr' command for transferring API token to mobile apps#545

Open
eugenn wants to merge 1 commit into
junhoyeo:mainfrom
eugenn:feature/qr-login
Open

feat(cli): add 'qr' command for transferring API token to mobile apps#545
eugenn wants to merge 1 commit into
junhoyeo:mainfrom
eugenn:feature/qr-login

Conversation

@eugenn
Copy link
Copy Markdown

@eugenn eugenn commented May 13, 2026

Summary

Adds a new tokscale qr subcommand that renders the locally saved API token (from ~/.config/tokscale/credentials.json) as a QR code directly in the terminal. The QR payload is a JSON blob containing both the token and the username, so a companion app can authenticate and identify the user from a single scan.

Why

Tokscale is desktop-first today, but the account/leaderboard is a natural fit for a companion mobile app (on-the-go leaderboard, weekly summary push notifications, badge sharing, etc.). Mobile apps need a frictionless way to log in — typing a 50+ char tt_xxx token on a phone keyboard, or running the browser device-code flow a second time on mobile, is exactly the kind of paper-cut that kills a companion-app funnel.

Today's options are all unergonomic:

  • Browser device flow on mobile — works, but the user has to open the leaderboard, copy a code, switch apps. High enough friction that most users will give up.
  • Manual pastett_ tokens are 50+ characters; mobile keyboards make this miserable and error-prone.
  • Email / messenger / cloud notes — leaks the bearer token through extra surface area.

A QR code displayed by the already-trusted CLI is the de-facto standard for this exact problem (Discord, Signal, WhatsApp Web, GitHub CLI device flow all do variants of it):

  1. User runs tokscale qr on the machine where they already authenticated via tokscale login.
  2. Mobile app scans the QR with its built-in camera, parses the JSON payload, and is logged in.
  3. No retyping, no second browser round-trip, no token sent over email/Slack.

JSON (not bare token, not URL) was chosen for the payload so mobile apps can also display the username next to the avatar before activating the session — i.e. show a Sign in as @eugenn? confirmation step, which is a meaningful safety check when the QR may have been displayed on a screen the user no longer fully controls.

What changed

  • New tokscale qr subcommand wired in crates/tokscale-cli/src/main.rs (added to the Commands enum and routed to auth::show_qr).
  • New auth::show_qr() in crates/tokscale-cli/src/auth.rs:
    • Reads saved credentials via the existing load_credentials() helper. If the user isn't logged in, prints the same hint that whoami uses and exits cleanly (no crash, no error).
    • Builds a JSON payload {"token":"tt_xxx","username":"<name>"} and feeds it to qrcode::QrCode::new.
    • Renders the QR with unicode::Dense1x2 (two modules per terminal row → compact, square-aspect output). Colors are inverted so the QR is visible on a typical dark terminal background.
    • Prints Token: and User: plaintext below the QR for fallback / debugging.
  • Dependency: qrcode = "0.14" added under crates/tokscale-cli/Cargo.toml. Default features only; no FFI; MIT/Apache-2.0 dual-licensed.
  • README: documents the command in the existing Social section, with a note about the JSON payload shape.

No server-side, frontend, or shared-protocol changes. The mobile-app contract is just "scan, parse JSON, use token as bearer" — exactly the auth the CLI itself uses against /api/auth/token.

Usage

$ tokscale qr

  Tokscale - API Token QR Code

  Scan to get your API token:

  █████████████████████████████████████████████
  █████████████████████████████████████████████
  ████ ▄▄▄▄▄ ██▀ ▄▀██▄▀▀▀▀▀▀▄▀▄█▀▀▄█ ▄▄▄▄▄ ████
  ...
  █████████████████████████████████████████████

  Token: tt_5be17ed8c9b94...
  User:  eugenn

Decoded QR contents:

{"token":"tt_5be17ed8c9b94...","username":"eugenn"}

Validation

  • cargo build -p tokscale-cli (debug + release) — clean, no new warnings.
  • Manual: ran tokscale qr against a real credentials file. QR scans cleanly with iOS Camera and yields the expected JSON payload. The "not logged in" branch was exercised by temporarily moving credentials.json out of the way — prints the same hint as whoami, exits 0.
  • No existing code paths touched — login, logout, whoami, submit etc. are byte-for-byte unchanged.

Risk

  • New, opt-in subcommand. Users who never run tokscale qr are entirely unaffected.
  • The QR encodes the same bearer token that already lives in ~/.config/tokscale/credentials.json — no new secret material is created or exposed by this PR. The QR is only ever rendered to the user's own terminal output; there is no networking and no file write.
  • One new direct dependency (qrcode 0.14): pure Rust, no FFI, ~1.5k LOC, widely used.

Follow-ups (not in this PR)

  • Mobile app side: parse the JSON payload and call the existing /api/auth/token validator before persisting the token, mirroring login_with_token in auth.rs.
  • Optional: also accept tokscale://login?token=...&username=... once mobile apps register a URL scheme, so iOS/Android can deep-link straight from the system camera without an in-app QR reader.

Summary by cubic

Adds a tokscale qr command that displays your saved API token and username as a QR code in the terminal. This enables quick mobile sign-in by scanning one code.

  • New Features

    • New CLI subcommand tokscale qr.
    • Reads saved credentials; if not logged in, prints the same hint as whoami and exits.
    • QR payload is JSON: {"token":"tt_xxx","username":"..."}.
    • Renders with Unicode Dense1x2 and inverted colors for dark terminals.
    • Prints Token and User below the QR for fallback; wired via auth::show_qr() and Commands::Qr; README updated.
  • Dependencies

    • Add qrcode 0.14 to tokscale-cli (pure Rust).

Written for commit f4a15ae. Summary will update on new commits.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
tokscale Ignored Ignored Preview May 13, 2026 0:10am

Request Review

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 5 files

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