Talk to Omi from your terminal. Designed for humans and agents.
omi-cli is the command-line interface to the Omi developer
API. It exposes scoped, agent-friendly verbs for the four primary nouns Omi
maintains about you:
- memories — facts and learnings the system knows about you
- conversations — captured & processed audio/text exchanges
- action items — tasks and follow-ups
- goals — tracked progress metrics
It's intentionally small, scriptable, and JSON-first — everything you need to plug Omi into shell pipelines, CI jobs, agent harnesses, or just your own personal automation.
- PyPI: pypi.org/project/omi-cli
- Docs: docs.omi.me/doc/developer/cli/introduction
- Source: github.com/BasedHardware/omi/tree/main/sdks/python-cli
pipx install omi-cli # recommended — isolated install
# or
pip install omi-cliAfter install, the binary on your $PATH is named omi:
omi --version
omi --helpThe PyPI distribution name is
omi-cli(the bareomislot belongs to an unrelated package). The console command isomiregardless.
# 1. Log in. With no flags, omi-cli asks how you want to authenticate:
omi auth login
# → 1) Browser — sign in with Google or Apple (recommended for humans)
# → 2) API key — paste a developer key from app.omi.me (recommended for agents/CI)
# 2. Start using it:
omi memory list
omi conversation list --limit 5
omi action-item list --open
omi goal listPass --json to any command (as a global flag, before the verb) to get
machine-readable output, ready for jq, agent harnesses, or whatever else:
omi --json memory list | jq '.[] | {id, content}'Two auth methods, both fully wired:
| Method | Best for | How to use |
|---|---|---|
Dev API key (omi_dev_*) |
Agents, CI, headless, scoped permissions | omi auth login --api-key ... or env var |
| Firebase OAuth (Google/Apple) | Humans on a laptop | omi auth login --browser |
The browser flow opens your default browser for OAuth, captures the code on a localhost callback, and stores a Firebase ID token + refresh token. The ID token is auto-refreshed before each request when it's near expiry — you shouldn't need to think about it.
omi auth login # interactive picker (browser or key)
omi auth login --browser # force OAuth (default provider: google)
omi auth login --browser --provider apple
omi auth login --api-key K # force API-key path
omi auth login < key.txt # piped key, useful in CI
omi auth status # show profile + masked credential + expiry
omi auth whoami # round-trip to verify the credential works
omi auth refresh # force a Firebase refresh (no-op for API keys)
omi auth logout # wipe the credentialYou can also set OMI_API_KEY in the environment to bypass on-disk config
entirely — handy in containers and CI:
export OMI_API_KEY=omi_dev_...
omi memory listState lives at ~/.omi/config.toml (overridable via $OMI_CONFIG). The file
holds one or more named profiles, each with its own auth method and API base.
Switch between them with --profile:
omi config profile use work
omi auth login # logs in the active profile (work)
omi --profile personal memory listCommon config:
omi config show
omi config path
omi config set api_base https://api.staging.omi.me
omi config set local_api_url http://127.0.0.1:47778
omi config set local_token ...
omi config profile list
omi config profile delete old-account --yesomi local talks to a running Omi Desktop local API. Configure the active
profile once, or use env vars for ephemeral agent sessions:
omi local configure --url http://127.0.0.1:47778 --token ...
export OMI_LOCAL_API_URL=http://127.0.0.1:47778
export OMI_LOCAL_TOKEN=...Common local tools:
omi --json local status
omi --json local tools
omi --json local call search_screen_history --args-json '{"query":"pricing page","days":7}'
omi --json local search-screen "pricing page" --days 7 --app Safari
omi --json local screenshot 123 --output /tmp/omi-shot.jpg
omi --json local recap --days-ago 1
omi --json local sql "SELECT appName, COUNT(*) FROM screenshots GROUP BY appName"
omi --json local task search "taxes" --include-completedTask writes should only run after the user clearly asks for that change:
omi --json local task complete task_123
omi --json local task delete task_123 --yesThe full tree (run omi --help for the live version):
omi
├── auth
│ ├── login [--browser] [--api-key KEY]
│ ├── logout
│ ├── status
│ ├── whoami
│ └── refresh
├── config
│ ├── show
│ ├── path
│ ├── set <key> <value>
│ └── profile
│ ├── list
│ ├── use <name>
│ └── delete <name>
├── memory
│ ├── list [--limit N] [--offset N] [--categories ...]
│ ├── get <id>
│ ├── create <content> [--category ...] [--visibility ...] [--tag ...]
│ ├── update <id> [--content ...] [--category ...] [--visibility ...] [--tag ...]
│ └── delete <id> [-y]
├── conversation
│ ├── list [--limit N] [--start-date ...] [--end-date ...] [--include-transcript]
│ ├── get <id> [--include-transcript]
│ ├── create [--text ...] [--text-source ...] [...]
│ ├── from-segments <file.json> [--source ...]
│ ├── update <id> [--title ...] [--discarded/--no-discarded]
│ └── delete <id> [-y]
├── action-item
│ ├── list [--completed/--open] [--conversation-id ...] [...]
│ ├── get <id>
│ ├── create <description> [--due-at ...]
│ ├── update <id> [--description ...] [--completed/--open] [--due-at ...]
│ ├── complete <id>
│ └── delete <id> [-y]
├── local
│ ├── configure --url URL --token TOKEN
│ ├── status
│ ├── tools
│ ├── call <tool> [--args-json JSON]
│ ├── search-screen <query> [--days N] [--app NAME]
│ ├── screenshot <id> [--output PATH]
│ ├── recap [--days-ago N]
│ ├── sql <query>
│ └── task
│ ├── search <query> [--include-completed]
│ ├── complete <id>
│ └── delete <id> [-y]
└── goal
├── list [--limit N] [--include-inactive]
├── get <id>
├── create <title> --target N [--type ...] [--current N] [--unit ...]
├── update <id> [...]
├── progress <id> <value>
├── history <id> [--days N]
└── delete <id> [-y]
--json Emit JSON to stdout (machine-readable, agent-friendly).
--profile, -p NAME Use a specific profile.
--api-base URL Override the API base URL.
--verbose, -v Log HTTP traffic to stderr.
--no-color Disable colored output (also honors $NO_COLOR).
--version Print the version.
--help Show contextual help.
0 success
1 usage error (bad flags, missing args, validation)
2 auth error (no creds, expired token, insufficient scope)
3 server error (5xx, connection failure)
4 rate limited (429) — retry recommended
5 not found (404)
The CLI is built so an LLM can use it without a wrapper:
--jsonreturns valid JSON to stdout. Nothing else writes to stdout in JSON mode (errors go to stderr as{"error": "...", "detail": "..."}).- Stable exit codes (above) let an agent disambiguate retryable vs terminal errors.
- Rate-limit errors include a
Retry-Afterwindow in the message and surface the policy name (dev:conversations, etc.) so an agent can back off intelligently. OMI_API_KEYandOMI_API_BASEenv vars work without any priorauth login.OMI_LOCAL_API_URLandOMI_LOCAL_TOKENoverride profile-local Desktop API settings foromi local.
See examples/agent_quickstart.md for a worked
example.
The dev API enforces per-policy hourly limits:
| Policy | Limit |
|---|---|
dev:conversations |
25/hour |
dev:memories |
120/hour |
dev:memories_batch |
15/hour |
The CLI retries 429 automatically with exponential backoff and honors the
server's Retry-After hint where present. After all retries are exhausted you
get exit code 4 plus a message telling you how long to wait.
# Editable install with dev extras
pip install -e .[dev]
# Run the test suite
pytest -q
# Lint
black --check --line-length 120 --skip-string-normalization sdks/python-cli/
mypy omi_cli
# Build a wheel + sdist (no upload, no tag)
bash release.sh --build-onlyMIT — see LICENSE.