@genietheai/genie-cli
v0.3.0
Published
First-party command-line client for Personal Genie
Readme
GenUI CLI
genie is a first-party terminal client for Personal Genie. It authenticates as an ordinary Supabase user, calls the same production Edge Functions as the iOS app, and keeps refresh sessions in macOS Keychain. It never needs a service-role key, direct database access, or client-side memory retrieval.
Install and run
Node.js 22 or newer and macOS are required.
npm install --global @genietheai/genie-cli
genie helpTo update later:
npm install --global @genietheai/genie-cli@latestFor development from a repository checkout:
npm install
npm run dev -- auth statusThe built-in production profile points at GenUI's production Supabase project and uses the same browser-safe public anon key as the iOS app. No user token is committed. Configure local or staging with environment variables or the non-secret config file shown by genie config show:
export GENIE_LOCAL_SUPABASE_URL=http://127.0.0.1:54321
export GENIE_LOCAL_SUPABASE_PUBLISHABLE_KEY='<local public key>'
export GENIE_LOCAL_CALLBACK_PORT=45454
genie config set-profile localGENIE_SUPABASE_URL, GENIE_SUPABASE_PUBLISHABLE_KEY, GENIE_CALLBACK_PORT, and GENIE_PROFILE override the selected profile. Access and refresh tokens are never written to this config or environment by the CLI.
Apple and Supabase prerequisites
Phone-linked accounts can sign in without an Apple browser session:
genie auth login --phoneEnter your number with its country code, then the SMS code in the hidden terminal
prompt. The CLI never accepts the code as a command-line argument or writes it to
configuration. Phone login signs into existing accounts only; create an account
or attach a number to your existing Apple account in the Genie app first.
Existing Keychain sessions keep working. genie auth login retains its Apple
browser behavior for compatibility; genie auth login --apple is an explicit
alias. Both login methods use the same project-scoped session storage and user ID.
Phone login requires Supabase Phone Auth and a working SMS provider.
Browser login uses Supabase Sign in with Apple through PKCE and a callback bound only to 127.0.0.1. The expected production callback is http://127.0.0.1:45454/auth/callback; it must be in the Supabase Auth redirect allow-list.
Apple web OAuth is separate from the existing native iOS capability. Production needs:
- Apple Services ID
com.Genie.GenUIApp.web, associated with primary App IDcom.Genie.GenUIApp. - Website domain
ogkuxjxnnifmntnodlyv.supabase.co. - Apple/Supabase return URL
https://ogkuxjxnnifmntnodlyv.supabase.co/auth/v1/callback. - Apple Team ID, Key ID, and securely stored
.p8signing key. - A generated Apple OAuth client secret configured in the Supabase Apple provider.
- The Services ID first in Supabase's Apple client-ID list, followed by the native App ID.
Apple web OAuth secrets expire and must be regenerated at least every six months. Put the rotation on a recurring operational calendar; missing it breaks CLI/web login while native iOS login can continue working, which is a particularly annoying split-brain failure. See the current Supabase Apple login guide.
Login:
genie auth login
genie auth whoami --json
genie auth logoutThe callback server accepts only GET /auth/callback, closes after success/error/timeout, exchanges the PKCE code with Supabase, verifies the resulting user, and stores only the rotating refresh token under a project-scoped Keychain item. To verify CLI and iOS resolve to the same account, compare genie auth whoami --json's user_id with the authenticated Supabase user ID shown by the iOS debug/account surface—not the Apple relay email.
Commands
genie chat
genie chat ask "What should I watch tonight?" --show-tools
genie chat ask "What should I watch tonight?" --jsonl
genie chat list
genie chat messages <conversation-id>
genie chat run <run-id> --json # Read your Personal Genie run status and tool diagnostics
genie chat submit "Who is John Mayer?" --json # Persist a Personal Genie request; inspect the returned run ID with chat run. Add --new for a fresh conversation or --images to enable image search.
genie lab baseline --json # Read the deployed Workbench instruction sections
genie lab experiment "Who is John Mayer?" --conversation <id> --file variant.json # Read-only tools, empty test history, no saved messages or memories. Add --memory to read authorized personal context.
genie chat export <conversation-id> --format json
genie chat export <conversation-id> --format markdown --output chat.md
genie chat export <conversation-id> --format fixture --output fixture.json
genie memory list --visibility private
genie memory get <memory-id>
genie memory visibility <memory-id> public
genie memory archive <memory-id>
genie memory delete <memory-id> --yes
genie memory export --format json
genie bio show --public
genie bio show --personal
genie bio refresh --personal --wait
genie bio sources --public
genie lab session
genie lab capabilities
genie lab chat ask "test prompt" --trace --jsonl
genie lab trace <trace-id>
genie lab fixture prompt --kind direct --scenario "Two friends planning a trip"
genie lab fixture validate fixture.jsonHuman-readable output is the default. On a capable interactive terminal, Genie uses a restrained cyan/blue eclipse orb for sign-in, chat entry, thinking, and Bio refreshes, plus semantic color for status and recovery. Animation runs at a bounded frame rate and restores the cursor after completion, errors, and signals. Set NO_COLOR=1 to disable color or GENIE_ANIMATION=0 to keep color with static presentation.
--json applies to request/response commands; chat streams use --jsonl. JSON, JSONL, quiet mode, redirected output, pipes, NO_COLOR, and limited terminals never receive cursor-control sequences or animation. Content and final data stay on stdout; progress and diagnostics stay on stderr. Ctrl-C cancels the local stream cleanly, though the production durable generation may still finish and persist server-side.
Normal chat calls chat-get-or-create-agent-conversation and then sends directly to genie-shared-stream with the current production Personal Genie V4 contract. That Edge Function persists both sides, owns retrieval, and runs the normal tool loop. The CLI does not pre-send through another endpoint, retrieve memory itself, inject hidden context, or execute tools locally.
Chat exports and synthetic fixtures
genie chat export follows the existing stable message cursor until the authenticated conversation is complete, then orders messages chronologically. JSON exports include visible message fields and active participant identities but omit raw message metadata. Markdown provides a readable transcript. Fixture exports anonymize participants, label every human as synthetic, convert historical turns to delivery: fixture, and force the existing evaluation contract to local/staging with production disabled.
Use --output <path> to create a mode-0600 file. Existing files are not overwritten unless --force is explicit. Without --output, content goes to stdout for piping.
genie lab fixture prompt emits a model-ready prompt containing a schema-valid draft for personal, direct, or group conversations. genie lab fixture validate uses the repository's canonical bundled memory-evaluation validator locally; it does not bootstrap Lab authority or call Supabase. Generated fixtures remain review-required files and are never inserted into real production chat history by these commands.
Security and authority
- Only the public project key and an ordinary user's JWT are sent to Edge Functions.
- JWTs, authorization headers, provider secrets, and token-shaped values are redacted from errors and structured output.
- Mutation request IDs are client-generated. Memory edits use server-side ownership checks, an expected-update compare-and-swap, embedding regeneration, semantic classification and identity-key recomputation, an audit event, and database-owned Bio invalidation. Revised content resets to private; publish it again explicitly so the new text passes current policy.
- Permanent deletion requires an exact ID and interactive confirmation, or
--yesin non-interactive use. - Chat export excludes raw metadata, authorization material, hidden prompts, and privileged trace evidence. Fixture conversion anonymizes real participant identifiers.
- Generated Bio documents are derived caches. Edit source memories, then refresh; there is no direct Bio markdown CRUD.
- Ordinary
genie chat --traceis rejected. Passive traces are available only undergenie labafter the server issues observer authority and a Lab session. The CLI cannot manufacture operator roles, sessions, grants, or sanitized evidence.
Known runtime limits
- Apple login cannot complete until the external Apple Services ID/client secret and Supabase loopback allow-list are configured.
- The repository includes the memory get and owner Personal Bio Edge Function contracts plus their migration, but they do not exist in production until the normal reviewed deployment flow applies them. This package does not deploy or migrate anything itself.
- Real authenticated production E2E is intentionally opt-in because visibility changes, archive, and delete affect the signed-in user's actual data.
Publishing
The npm package is public and MIT licensed. Source remains in the GenUI backend repository; the published tarball contains only the standalone executable bundle, this README, the license, and package metadata.
Manual releases can be published by an npm owner of the genietheai organization:
cd genie-cli
npm publish --access publicFuture releases use the genie-cli-v<version> tag workflow after publish-genie-cli.yml is configured as the package's npm trusted publisher. The workflow needs no long-lived npm token. Version the package, commit it, and push the matching tag only after the release commit is on main.
Shared message policy experiments
prepare --runtimes current,decisions:current,decisions:gemini-3.6-flash runs each Personal Genie instruction variant under every listed runtime: Current Genie, or Genie+Decisions on the current model or a pinned Gemini model (gemini-3.6-flash, gemini-3.8-flash). Variant names carry the runtime, and results report the model that actually ran. The backend must have Genie+Decisions enabled, and GEMINI_API_KEY set for Gemini runtimes.
genie workbench message-policy checks backend support and exports the current shared policy. prepare --agent UUID --message-policies policies.json compares policy wording against a pinned saved Genie. messages --file results.json --format json|html preserves actual text and rich blocks for review; review --id BATCH_UUID --job JOB_UUID --verdict pass|fail --notes-file notes.txt saves the assessment.
See the policy benchmark workflow for fixed context, bounded autonomous iteration, deployment and reporting limits.
Memory extraction benchmarks
genie workbench extraction-template exports fixed conversation tests; extraction-policy exports the deployed extractor instruction as an editable, versioned JSON file. prepare-extraction --file transcripts.json --variant candidate-policy.json --repetitions 3 --out run.json compares that candidate with the current instruction through the real extractor. Existing run/watch/review/export commands and the Workbench UI use the same backend queue. No user memories are created.
See the extraction benchmark workflow for setup, test cases, review and deployment requirements.
Builder evaluation preparation
genie builder-eval setup prepares an isolated local evaluation workspace; builder-eval validate checks it without running a campaign. Use the repository build and see the setup guide for account isolation, frozen fixtures, readiness checks, and current campaign limitations.
Builder session commands (initialize, start, status, answer, resume,
finalize, discard, cleanup) use the same isolated workspace. start reserves
one creation, answer --file resumes the existing task, and finalize verifies the
saved receipt against inventory and exports the saved package. Cleanup requires
that exact campaign-owned ID, receipt, exported package and a review report.
Never remove a stale .session-lock until the prior process has been inspected.
See the Folkways evaluation fixtures
for the bounded CLI-driven behavioral runner and its evidence limits.
