Command-line tool for managing OpenHome voice AI abilities. Deploy, test, and manage abilities without leaving your terminal — and let AI agents do it for you.
Version: v0.1.40 Node: 18+ Platform: macOS (primary), Linux/Windows (config-file fallback for keychain)
Every command in this CLI works fully non-interactively. That means Claude Code, Claude agents, GitHub Actions, and any other automated context can deploy abilities, assign them to agents, and test them via openhome chat — no browser, no prompts, no human in the loop.
# Auth (one-time — or use env vars in CI, no disk writes needed)
export OPENHOME_API_KEY=<your_api_key>
export OPENHOME_JWT=<your_session_token>
# Deploy, assign, and chat-test an ability — all scriptable
openhome deploy ./my-ability.zip --name "weather-bot" --category skill --triggers "weather" --json
openhome assign --agent "My Agent" --capabilities weather-bot --json
openhome chat <agent_id>When called with no TTY (pipes, CI, agents), openhome with no arguments prints a machine-readable command reference and exits — so agents always get structured output.
All commands support --json for machine-readable output. All prompts can be bypassed with flags. Auth works via environment variables with no keychain access required.
| 🌐 Website | openhome.com |
| 📖 Docs | docs.openhome.com |
| 🤖 Dev Kit | dev.openhome.com — hardware waitlist, but you can build abilities today |
| 💬 Discord | discord.gg/gPpSCmuxWW |
| 🐦 X / Twitter | @openhome |
| 🐙 GitHub | github.com/openhome-dev |
| 📦 Community Abilities | openhome-dev/abilities |
Keep it private: Deploy directly with openhome deploy — your code stays local, only the zip goes to OpenHome.
Open-source it: Submit a PR to openhome-dev/abilities on the dev branch. See the contribution guide for the folder structure and checklist. Community abilities show up in the OpenHome ability library for anyone to use.
# Use directly without installing
npx openhome-cli
# Or install globally
npm install -g openhome-cli
openhome# 1. Log in with your API key
openhome login
# 2. Zip your ability folder, then deploy
cd path/to/my-ability && zip -r ../my-ability.zip . && cd ..
openhome deploy ./my-ability.zip
# 3. Assign to an agent
openhome assign
# 4. Chat to test it
openhome chatOr just run openhome with no arguments for the interactive menu.
All commands work non-interactively when the required flags are supplied.
Auth via environment variables (no disk writes, no keychain access):
export OPENHOME_API_KEY=<your_api_key>
export OPENHOME_JWT=<your_session_token>Typical agent/CI workflow:
# 0. Check auth state first — if jwt_status is expired/missing, stop and ask the human to run: openhome set-jwt
openhome whoami --json
# 1. Zip the ability (from parent directory)
zip -r my-skill.zip my-skill/
# 2. Deploy, list, assign, clean up
openhome deploy ./my-skill.zip --name "my-skill" --description "Does X" \
--category skill --triggers "activate" --json
openhome list --json
openhome assign --agent "My Agent" --capabilities <id_from_list> --json
openhome delete <id> --yes --jsonExit codes:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Error |
2 |
Auth error (expired JWT, invalid key) |
Opens an interactive menu. Use arrow keys to navigate, Enter to select. The menu loops after each command.
If you are not logged in, the CLI prompts for login before showing the menu.
Authenticate with your OpenHome API key.
- Prompts for your API key (masked input)
- Verifies the key against the OpenHome API
- Stores the key securely (macOS Keychain, or
~/.openhome/config.jsonfallback)
openhome login
# Non-interactive (skips all prompts)
openhome login --key <API_KEY> --jwt <SESSION_TOKEN>| Flag | What it does |
|---|---|
--key <api_key> |
API key (skips prompt) |
--jwt <token> |
Session token (skips browser setup step) |
Save a session token to unlock management commands (list, delete, assign, status).
# Guided flow — opens browser and walks you through copying the token
openhome set-jwt
# Direct — paste the token
openhome set-jwt eyJ...Guided flow: Opens app.openhome.com, then walks you through the browser console steps to copy your session token to clipboard.
The token is saved to macOS Keychain (or ~/.openhome/config.json fallback). You only need to do this once (until your session expires).
Validate and upload an ability zip to OpenHome.
You must zip your ability first. The CLI does not auto-zip directories. Run
zip -r my-ability.zip my-ability/from the parent directory before deploying.
# Deploy a zip from current directory (must already be zipped)
openhome deploy ./my-ability.zip
# Non-interactive
openhome deploy ./my-ability.zip \
--name "Weather Bot" \
--description "Checks the weather" \
--category skill \
--triggers "check weather,whats the weather"
# Attach to specific agent (use numeric agent ID from `openhome agents --json`)
openhome deploy ./my-ability.zip --personality <agent_id>| Flag | What it does |
|---|---|
--name <name> |
Ability name (skips prompt) |
--description <desc> |
Description (skips prompt) |
--category <cat> |
skill | brain_skill | background_daemon | local |
--triggers <words> |
Comma-separated trigger words (skips prompt) |
--personality <id> |
Override default agent for this deploy |
--timeout <seconds> |
Upload timeout (default: 120) |
--mock |
Use fake API responses for testing |
--json |
Machine-readable JSON output |
What happens on deploy:
- Validates the zip contents (blocks if errors)
- Asks for confirmation (skipped when non-interactive flags provided)
- Uploads to OpenHome
Note: There is no update/overwrite endpoint yet. Re-deploying with the same name will fail with a naming conflict. Delete the old version first with
openhome delete.
Run validation checks on an ability directory without deploying. Same checks deploy runs internally.
# Validate current directory
openhome validate
# Validate specific directory
openhome validate ./my-abilityPrints all errors (which would block deploy) and warnings (which would not).
| Flag | What it does |
|---|---|
--json |
Machine-readable JSON output |
List all your deployed abilities.
openhome list
openhome list --json
openhome list --mockShows a table with name, version, status, and last update date.
Status colors: green = active, yellow = processing, red = failed, gray = disabled.
| Flag | What it does |
|---|---|
--json |
Machine-readable JSON output |
--mock |
Use fake API client |
Delete a deployed ability.
# Interactive
openhome delete
# By name
openhome delete my-weather-bot
# Skip confirmation (useful for CI)
openhome delete my-weather-bot --yes| Flag | What it does |
|---|---|
--yes |
Skip confirmation prompt |
--json |
Machine-readable JSON output |
--mock |
Use fake API client |
Assign abilities to an agent.
# Interactive multiselect
openhome assign
# Non-interactive (IDs or names accepted)
openhome assign --agent "My Agent" --capabilities id1,id2| Flag | What it does |
|---|---|
--agent <id|name> |
Agent ID or name (skips prompt) |
--capabilities <ids> |
Comma-separated ability IDs or names (skips prompt) |
--json |
Machine-readable JSON output |
--mock |
Use fake API client |
View your agents and set a default for deploys.
openhome agents
openhome agents --jsonShows all agents with names and IDs. Optionally set or change your default agent (used by deploy when --personality is not specified).
| Flag | What it does |
|---|---|
--json |
Machine-readable JSON output |
--mock |
Use fake API client |
Edit an agent's name and system prompt in $EDITOR.
# Interactive
openhome agents edit
# Specific agent by name or numeric ID (use `openhome agents --json` to find IDs)
openhome agents edit <agent_id>Opens your $VISUAL or $EDITOR (falls back to nano) with the current prompt pre-loaded. Saves on exit.
Chat with an agent via WebSocket. Send text messages and trigger abilities with keywords.
openhome chat
openhome chat <agent_id>Commands inside chat: /quit, /exit, or /q to disconnect. Ctrl+C also works.
Note: Audio responses are not playable in the terminal. Text responses display normally.
Send a trigger phrase to fire an ability remotely.
openhome trigger "play aquaprime"
openhome trigger --agent <agent_id> "check weather"Show detailed info for one ability.
openhome status my-weather-bot
openhome status # reads name from local config.json
openhome status my-weather-bot --json| Flag | What it does |
|---|---|
--json |
Machine-readable JSON output |
--mock |
Use fake API client |
Stream live agent messages and logs.
openhome logs
openhome logs --agent pers_abc123Show auth status, default agent, and tracked abilities.
openhome whoami
openhome whoami --json # includes jwt_status: valid | expiring_soon | expired | missingEdit trigger words, description, or category in a local config.json.
openhome config
openhome config ./my-abilityStart the OpenHome MCP voice server for Claude Code integration.
openhome mcpLaunches the OpenHome voice server as an MCP (Model Context Protocol) server for use with Claude Code and other MCP-compatible tools.
Clear stored credentials and log out.
openhome logoutRemoves the API key from macOS Keychain and clears the default agent from config.
Deploy and validate both run these checks. Errors block deployment. Warnings do not.
Every ability must have:
main.py__init__.pyconfig.jsonREADME.md
Must contain:
unique_name— non-empty stringmatching_hotwords— array of strings
| What | Why |
|---|---|
Class extending MatchingCapability |
OpenHome ability base class |
call(self, ...) method |
Entry point OpenHome calls |
worker: AgentWorker = None |
Required field declaration |
capability_worker: CapabilityWorker = None |
Required field declaration |
resume_normal_flow() call |
Returns control to user after ability runs |
# {{register_capability}} comment |
Template marker used by OpenHome |
| Pattern | Use Instead |
|---|---|
print() |
self.worker.editor_logging_handler |
asyncio.sleep() |
self.worker.session_tasks.sleep() |
asyncio.create_task() |
self.worker.session_tasks.create() |
open() |
capability_worker file helpers |
exec() / eval() |
Not allowed |
pickle / dill / shelve / marshal |
Not allowed (security) |
assert |
Not allowed |
hashlib.md5() |
Not allowed |
| Import | Why |
|---|---|
redis |
Not available in sandbox |
from src.utils.db_handler |
Internal, not for abilities |
connection_manager |
Internal, not for abilities |
user_config |
Internal, not for abilities |
| Check | Message |
|---|---|
Hardcoded API keys (sk_..., key_...) |
Use capability_worker.get_single_key() instead |
| Multiple class definitions | Only one MatchingCapability class expected per ability |
| Variable | Purpose |
|---|---|
OPENHOME_API_KEY |
API key — takes precedence over stored credentials |
OPENHOME_JWT |
Session token — takes precedence over stored credentials |
OPENHOME_API_BASE |
Override API endpoint (enterprise / staging environments) |
OPENHOME_NO_UPDATE |
Set to 1 to disable the auto-update check |
~/.openhome/
config.json # Settings, fallback credentials
On macOS, API key and session token are stored in the system Keychain (service: openhome-cli). The config file is a fallback for non-macOS platforms or when Keychain is unavailable.
| Field | Purpose | Default |
|---|---|---|
api_base_url |
Override API endpoint | https://app.openhome.com |
default_personality_id |
Default agent for deploys | (none) |
api_key |
Fallback key storage (prefer Keychain) | (none) |
jwt |
Fallback session token (prefer Keychain) | (none) |
The CLI checks npm once per day for a newer version (result cached — no network call on every run).
- npx: new version re-executed transparently
- Global install: one-line notice printed, current version continues
- Set
OPENHOME_NO_UPDATE=1to disable (useful in CI)
- No local ability testing — Abilities run on the OpenHome platform. Use "Start Live Test" in the web editor.
- No ability editing — Edit locally, then re-deploy.
- No update/redeploy — Deploy creates a new entry; use
openhome deleteto remove the old one first. - No Windows Keychain — API key stored in plaintext config on non-macOS platforms.
| Command | Endpoint | Auth | Status |
|---|---|---|---|
login |
POST /api/sdk/verify_apikey/ |
API key | Live |
agents |
POST /api/sdk/get_personalities/ |
API key | Live |
chat |
WebSocket /websocket/voice-stream/ |
API key | Live |
deploy |
POST /api/capabilities/add-capability/ |
API key | Live |
list |
GET /api/capabilities/get-installed-capabilities/ |
JWT | Live |
delete |
POST /api/capabilities/delete-capability/ |
JWT | Live |
assign |
PUT /api/personalities/edit-personality/ |
JWT | Live |
Commands marked JWT require openhome set-jwt first.
-
openhome watch— Auto-deploy on file changes -
openhome update— Re-deploy/overwrite an existing ability (pending server-side update endpoint) - Cross-platform secure key storage (Windows Credential Manager, Linux Secret Service)
- Management commands without JWT (pending OpenHome API update)
npm install
npm run build # Build
npm run dev # Run without building
npm run lint # Type check
npm run test # Run tests| Term | Meaning |
|---|---|
| Ability | A Python plugin that adds a feature to an OpenHome agent |
| Agent | A voice AI personality that can have multiple abilities (called "personality" in the API) |
| Trigger words | Spoken phrases that activate an ability (called matching_hotwords in config.json) |
| Skill | An ability type that runs when the user triggers it |
| Brain Skill | An ability type that the agent triggers automatically |
| Background Daemon | An ability type that runs continuously from session start |
| CapabilityWorker | The runtime helper object for speaking, listening, file I/O, and secrets |
| AgentWorker | The runtime object for logging and session management |
MIT