@yoamigo/cli
v0.2.0
Published
YoAmigo CLI — keychain-backed local dev. `yoamigo login`, `yoamigo exec`, `yoamigo db`.
Downloads
24
Readme
@yoamigo/cli
Keychain-backed local-dev CLI for yoamigo customer apps. Fetches every
yoamigo-managed secret (Turso DB token, Better Auth secret, platform API
key) from yoamigo-api at spawn time and injects it into the child
process's environment in memory only. No .env file is ever written.
A stolen developer laptop contains nothing but a revocable, keychain-bound token whose only capability is "fetch env bundles for apps you own".
Install
npm i -g @yoamigo/cli # or pnpm add -g / yarn global addVerify: yoamigo --version.
Commands
yoamigo login
Opens a browser to Studio's /cli-login page, user signs in, a DevSessionToken
is minted server-side and handed back to the CLI via a short-lived device-code
poll. Token stored in:
- macOS Keychain
- Linux libsecret / Secret Service
- Windows Credential Vault
Non-interactive flavor (CI, integration-tests harness):
# 1. From an authenticated context, mint a bootstrap code:
# - Studio UI, or
# - tRPC `cli.mintBootstrapCode` (requires Supabase JWT)
# 2. Redeem it:
yoamigo login --bootstrap <code> --device-label "ci-runner"yoamigo exec -- <cmd> [args...]
Run any command with yoamigo-managed secrets injected — the dev server,
one-shot Prisma operations, scripts, anything that needs the same env
the customer app uses. Replaces the need for a local .env file.
# In the app directory (needs yoamigo.json with { "appId": "..." })
yoamigo exec -- pnpm dev
# One-shot ops:
yoamigo exec -- pnpm prisma db push
yoamigo exec -- pnpm prisma studio
yoamigo exec -- node scripts/seed.ts
# Override appId / env / port / account:
yoamigo exec --app app_abc --env PREVIEW --port 4000 -- pnpm devStdout/stderr is piped through a redactor that scrubs the known secret
values, so a stray console.log(process.env) in the customer app cannot
leak the Turso token / Better Auth secret / platform API key to terminal
scrollback.
Overriding env values: --override and --local-db
yoamigo exec accepts two flags for replacing values from the fetched
env bundle without ever editing it on disk:
--override KEY=VALUE— repeatable. Replaces (or introduces) any env var. Wins over--local-dbper-key.--local-db— convenience shortcut that resolvesDATABASE_URLandDATABASE_AUTH_TOKENfrom the worktree-local DB registered withyoamigo db init. Errors loudly if no entry is registered, so you cannot accidentally hit staging.
# Use the registered local SQLite DB:
yoamigo exec --local-db -- pnpm dev
yoamigo exec --local-db -- pnpm prisma studio
# Point at a one-off local DB without using the registry:
yoamigo exec \
--override DATABASE_URL=file:/tmp/scratch.db \
--override DATABASE_AUTH_TOKEN=anything \
-- pnpm dev
# Swap a single bundle value (e.g. point at a local Stripe listener):
yoamigo exec --override STRIPE_WEBHOOK_SECRET=whsec_local_xxx -- pnpm devA [yoamigo] banner prints to stderr listing exactly which keys were
overridden each run — there is no implicit per-cwd magic. Anything not
overridden falls through to the staging bundle.
yoamigo logout / yoamigo status
yoamigo status # verify current token and show account info
yoamigo logout # server-side revoke + delete from keychainyoamigo db ... — per-worktree local SQLite DBs
Customer apps default to a shared staging Turso DB, which means two git
worktrees of the same app step on each other when one of them edits the
schema. yoamigo db init creates an isolated SQLite file at
~/.yoamigo/local-dbs/<appId>__<hash>.db, runs prisma db push against
it, runs the configured prisma db seed, and registers the worktree.
To use the registered DB you opt in explicitly with --local-db on
yoamigo exec (see "Overriding env values" above) — the init step alone
never changes what staging-vs-local your app talks to.
yoamigo db init # create + push schema + seed for the current app
yoamigo db status # show registered DB info
yoamigo db path # print the DB file path
yoamigo db push # re-run prisma db push after editing schema
yoamigo db seed # re-run prisma db seed
yoamigo db reset # delete the file and re-init
yoamigo db rm # delete the file and unregister
yoamigo db list # all registered local DBs across worktrees
yoamigo db studio # open Prisma Studio against the local DB--cwd <path> is honored on every subcommand — yoamigo Studio uses it to
spawn a local DB automatically when a worktree is created. --json on
init and list emits a single JSON line for programmatic callers.
The locally-generated DATABASE_AUTH_TOKEN is purely cosmetic — libSQL
ignores auth tokens for file: URLs. Staging Turso credentials are never
written to disk and are not used when --local-db is set.
Project config
The CLI looks for yoamigo.json (or .yoamigo.json) starting in CWD and
walking up to the repo root. Minimum:
{ "appId": "app_..." }Optional:
{
"appId": "app_...",
"projectName": "todo-app"
}Library use (integration-tests)
The harness imports spawnDev directly instead of shelling out:
import { spawnDev } from '@yoamigo/cli/dev'
const child = await spawnDev({
cwd: appDir,
appId: 'app_...',
environment: 'PREVIEW',
port: 3165,
account: 'ci-runner', // optional keychain account override (defaults to userId)
})Re-exports available on @yoamigo/cli/dev:
spawnDev,SpawnDevResult,EnvironmentauthorizeBootstrap,authorizePoll,authorizeStart,fetchSelf,fetchEnvBundleflattenBundle,extractSecretValuessaveToken,loadToken,deleteToken,buildAccountNameresolveApiUrlDevEnvBundleResponse(type)
Keychain fallback
If keytar fails to load (headless Linux without libsecret), or you set
YOAMIGO_CLI_KEYCHAIN_BACKEND=file, tokens spill to
~/.yoamigo/credentials with 0600. Strictly less safe — avoid unless
the keychain is unavailable.
Environment variables
YOAMIGO_API_URL— overrides the saved api URL; e.g.https://api.yoamigo.comorhttp://localhost:3001.YOAMIGO_STUDIO_URL(server-side) — whereyoamigo loginpoints the browser for sign-in.YOAMIGO_CLI_KEYCHAIN_BACKEND=file— opt into file fallback.
Testing
Unit tests (env-bundle flattening, stdout redaction):
pnpm --filter @yoamigo/cli testEnd-to-end command tests live in apps/integration-tests. They spawn the
built yoamigo binary against a real yoamigo-api with a sandboxed HOME
and a file-backed keychain, covering login --bootstrap, status,
whoami, logout, dev, and exec:
pnpm --filter @yoamigo/cli build # dist/index.js must exist
pnpm --filter @yoamigo/integration-tests run:cliPrereqs: a scaffolded integration-test app (pnpm scaffold <name>) whose
appId the contract uses as its fixture, and the standard harness env
(YOAMIGO_API_URL, Agent Mail creds — see apps/integration-tests/README.md).
Security guarantees
- Tokens are never written to a file in the customer app directory.
~/.yoamigo/config.jsonholds no secrets — only the api URL and the current keychain account name.- The DevSessionToken can only call
GET /api/cli/env-bundle/:appId/:envfor apps the owner owns. It cannot call Turso, sign sessions, or authenticate any non-CLI endpoint. - Every env-bundle fetch writes an audit-log row
(
dev_session_token_audit_logs) server-side. - A single "Rotate all credentials" action in Studio invalidates Better-Auth secrets, Turso tokens, and platform API keys for the app within seconds. Revoke-device in Studio kills a specific DevSessionToken.
