This document outlines the architecture, design decisions, and implementation details for the grm CLI authentication flow.
Overview
Thegrm CLI (backend/go/cmd/cli/) aims to provide a single typed command to replace interactive shell scripts, enhancing developer experience. More importantly, it serves as an agent interface, allowing AI agents to authenticate once and use the stored API key for all subsequent operations without human intervention.
The MVP scope includes three core commands:
grm auth logingrm auth logoutgrm auth whoami
Problem Statement
The CLI must authenticate on behalf of developers and AI agents—including cases where no human is present after the initial login. Traditional authentication mechanisms fall short:- Username/password flags: Require typing credentials into the terminal, are incompatible with SSO/OAuth, and result in passwords stored at rest.
- Session cookies: Browser-scoped and cannot be portably persisted across CLI invocations.
- Short-lived access tokens: Require frequent re-authentication, breaking agent workflows where no human is present to approve the refresh.
Solution: OAuth 2.0 Device Flow with API Keys
To solve these issues, thegrm CLI uses the OAuth 2.0 Device Authorization Grant (RFC 8628) combined with long-lived API keys.
The Flow
- Request Device Code: The CLI requests a device code (
POST /api/auth/device/code). - User Approval: The CLI opens the browser to the admin panel’s
/devicepage. The user explicitly approves the request. - Poll for Token: The CLI polls (
POST /api/auth/device/token) until the user approves, receiving a short-lived access token. - Exchange for API Key: The CLI immediately exchanges the access token for a long-lived API key (
POST /api/auth/api-key/create). - Persistence: Only the API key is persisted locally (to
~/.config/grm/config.json). The access token is discarded.
By storing an API key, every subsequent CLI invocation can authenticate using the
x-api-key header with no expiry concerns. API keys can also be named and revoked independently per device.Implementation Details
The implementation spans three main subsystems across the monorepo:1. Bun Backend
The Bun backend leverages Better Auth with three required plugins:deviceAuthorization: Enables the OAuth 2.0 Device Flow.apiKey: Enables the generation of long-lived API keys.bearer: Allows the CLI to authenticate thePOST /api/auth/api-key/createrequest usingAuthorization: Bearer <access_token>.
2. SolidStart Admin Panel
A dedicated/device route serves as the user verification page.
- Requires an active session (redirects unauthenticated users to sign in).
- Shows the user code and explicit Approve and Deny buttons.
- Security Rule: The page does not auto-approve on mount to prevent a stolen
user_codelink from silently authorizing a device.
3. Go CLI Core
The CLI uses a thin abstraction layer over Cobra (pkg/cli/builder.go) to reduce boilerplate and declarative define commands (CommandDef, GroupDef).
Auth state is saved to ~/.config/grm/config.json with 0600 permissions (owner read/write only).
Per-Device Naming and Revocation
A single developer may use the CLI from multiple machines. To prevent orphaned keys and avoid accidentally revoking another machine’s key, the CLI performs a best-effort revocation on re-login:- Lists all API keys for the authenticated user.
- Filters for keys matching the current device’s hostname.
- Revokes only those matching keys before creating a fresh one.
Related Files
Architectural Decision Records
- ADR-0010: grm CLI uses OAuth 2.0 Device Flow with long-lived API key storage
- ADR-0011: Better Auth bearer plugin required for CLI API key creation
- ADR-0012: grm CLI names API keys per-device and revokes the old key on re-login
Specs and Plans
docs/superpowers/plans/2026-05-13-grm-cli-auth.mddocs/superpowers/specs/2026-05-13-grm-cli-auth-design.md
Summary
Thegrm CLI auth architecture provides a robust, agent-friendly authentication mechanism without compromising security. By leveraging the OAuth 2.0 Device Flow to bootstrap a long-lived, per-device API key, it balances developer convenience with the automated needs of AI agents.