feat(cli): add hyperframes auth login --api-key, status, logout#1081
feat(cli): add hyperframes auth login --api-key, status, logout#1081jrusso1020 wants to merge 1 commit into
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
d75ab76 to
a72b6ac
Compare
|
Self-review pass — addressed 13 of 15 findings. Force-push includes all fixes squashed into the original commit. Fixed (critical/high):
Deferred (noted, will address in a follow-up):
Tests: 54 unit tests, all green. Lint/format/typecheck/fallow clean. |
a72b6ac to
5c81d96
Compare
5c81d96 to
da2c2ea
Compare
miguel-heygen
left a comment
There was a problem hiding this comment.
Really clean work — the module split (paths/store/resolver/client/errors) is well-layered and the test coverage is solid. A few things I noticed:
store.ts rename+chmod race — The write path does rename(tmp, path) then chmod(path, FILE_MODE). Between those two calls, the file briefly has whatever perms the renamed inode carried. Since you already chmod the tmp file before renaming, the post-rename chmod is only needed for the overwrite case where the destination had looser perms. You could drop the second chmod entirely and rely on the pre-rename one — rename atomically replaces the inode so the new file's permissions come from the tmp.
SOURCE_LABELS mismatch — status.ts hardcodes ~/.heygen/credentials.json in the label for file_json, but paths.ts defines CREDENTIAL_FILENAME = "credentials" (no .json extension). Users will see a misleading path in auth status output.
tryResolveCredential error check — Uses (err as { code?: string }).code === "NOT_CONFIGURED" instead of the isAuthError guard that's already imported nearby. Inconsistent and could match a non-AuthError with a .code property.
Rollback on fresh machine — If someone runs hyperframes auth login --api-key=bad_key on a fresh machine and the key fails verification, the rollback says "No previous credential to restore" and leaves the invalid key on disk. Deleting the file entirely seems like the better default here — you don't want a stale bad key sitting in the store.
Missing cli.mdx docs — CLAUDE.md checklist requires new commands to be documented in docs/packages/cli.mdx. Didn't see that in the diff.
None of these are blockers, solid PR overall.

What
Introduces the
hyperframes authcommand group + a shared credentialstore library that hyperframes-CLI and heygen-cli will both read from.
hyperframes auth login --api-keysaves a HeyGen API key to~/.heygen/credentials.json(stdin pipe or hidden-input prompt).hyperframes auth statusresolves the active credential (env vars→ file) and verifies it against
GET /v3/users/me, printingidentity + billing.
hyperframes auth logoutremoves the credential (--keep-api-keydrops only the OAuth block).
Internals (
packages/cli/src/auth/):paths.ts—~/.heygenlayout,HEYGEN_CONFIG_DIRoverride.store.ts— read/writecredentials.json(file 0600, dir 0700)with legacy single-line plaintext fallback so existing heygen-cli
users don't lose their session.
resolver.ts— chain:HEYGEN_API_KEY→HYPERFRAMES_API_KEY→file (unexpired OAuth wins over api_key).
client.ts— hand-written typed wrapper forGET /v3/users/me(intentionally not OpenAPI codegen — single endpoint).
errors.ts— typedAuthErrorwith discriminatingcode.Why
This is the foundation for
hyperframes cloud render. Splitting itout keeps the cloud-render PR small and lets users sign in today.
The plan originally called for a library-only PR followed by a
commands PR. The
fallowdead-code gate flagged the library-onlyshape as unused exports, so I bundled them — the library and its
first consumers ship together. PR 3 (OAuth PKCE) and PR 4
(heygen-cli read-side JSON support) follow.
How
api_key+oauthblocks. Both CLIs read it; the resolver picks the freshest valid
credential.
Authorization: Bearer ..., API key →x-api-key: ....HEYGEN_API_URLlets dev testing targetapi.dev.heygen.comwithout rebuilding.
authcommand lazy-loads its subverbs (same pattern aslambda).Test plan
vitest) for paths, store, resolver,client, and errors — 45 tests, all green.
bunx tsc --noEmit -p packages/cli/tsconfig.jsonclean.bunx oxlint+bunx oxfmt --checkclean.bunx fallow audit --base origin/main --fail-on-issues—zero new findings.
HEYGEN_API_URL=https://api.dev.heygen.com hyperframes auth login --api-keythen
hyperframes auth status.