Skip to main content

Onehouse CLI (oh)

A command-line tool for managing your Onehouse project — clusters, lakes, databases, tables, flows, jobs, catalogs, sources, transformations, validations, service principals, API tokens, and GENERIC_K8S data planes.

Installation

pip install onehouse-cli

The SDK dependency (onehouse-python-sdk[resources]) is installed automatically.

oh dataplane storage connect / rotate check the bucket with boto3, which comes in an optional extra:

pip install 'onehouse-cli[dataplane]'

AI agent integration

The package bundles two skills for AI coding agents:

  • onehouse-cli teaches them how to use oh.
  • onehouse-autosetup (/onehouse-autosetup in Claude Code) onboards a Onehouse data plane onto your own Kubernetes cluster and S3-compatible storage. It checks the cluster, labels nodes, connects storage without the agent ever seeing the secret key, sets up ZooKeeper, installs dp-connect and runs oh dataplane create. It asks before every change to the cluster, and never creates a cluster, bucket policy or access key.

Install both for your agent:

oh install agent-skill --claude    # ~/.claude/skills/onehouse-cli and onehouse-autosetup
oh install agent-skill --cursor    # ~/.cursor/skills/...
oh install agent-skill --codex     # ~/.agents/skills/...
oh install agent-skill --all       # all of the above
oh install agent-skill --all --dry-run

Re-run the command after pip install --upgrade onehouse-cli to refresh the skills. To read the onehouse-cli skill without installing it, run oh skill.

Setup

Configure credentials:

oh-configure

This prompts for your API credentials and saves them to ~/.onehouse/credentials. You can create multiple named profiles and set a default.

Fields collected:

  • Profile name
  • Account UID
  • Project UID
  • API Key / API Secret (blank if you use oh login)
  • Project Region (optional; blank means us-east-1. Generic Kubernetes projects don't use a region)
  • User ID
  • Request ID (link UID)
  • API Endpoint (default: https://api.onehouse.ai)
  • AI Gateway URL (optional; only oh ai-gateway reads it)

Credentials are stored in: ~/.onehouse/credentials

Alternatively, set environment variables:

export ONEHOUSE_API_KEY=...
export ONEHOUSE_API_SECRET=...
export ONEHOUSE_ACCOUNT_UID=...
export ONEHOUSE_PROJECT_UID=...
export ONEHOUSE_REGION=...          # optional; us-east-1 when unset
export ONEHOUSE_USER_UID=...
export ONEHOUSE_LINK_UID=...
export ONEHOUSE_PROFILE=myprofile   # select a profile from the credentials file

Sign in instead of an API key (oh login)

oh login     # opens your browser; commands then run as you
oh logout    # revokes the session and forgets it
  • Your organization must have OAuth sign-in for the API turned on. Ask your Onehouse contact.
  • The profile still needs Account UID, Project UID and Request ID (link UID). It does not need an API key, secret or User ID, and the region defaults to us-east-1: oh-configure accepts all of these blank.
  • While you are signed in, commands use your session instead of the profile's API key and secret. oh logout switches back.
  • The session renews itself for 30 days. The refresh token is kept in your OS keychain. A machine with no keychain, such as headless Linux, keeps it in ~/.onehouse/sessions/ with mode 0600. ONEHOUSE_SESSION_STORE=file forces the file.
  • A machine with no browser uses a service principal's API key, or oh login --port <n> over an SSH forward.
  • oh login signs in to the Onehouse API only, not to an AI Gateway; that is oh ai-gateway login.

AI Gateway: Claude Code and Codex with no pasted token

oh ai-gateway keeps an AI Gateway token fresh for the whole session. Set the gateway once with oh-configure (AI Gateway URL) or pass --gateway-url. Everything here needs the VPN or your own network.

As a person:

oh ai-gateway login                 # once; prints the one-time MCP setup for both clients
oh ai-gateway run -- claude         # every session
oh ai-gateway run -- codex -m <model alias>

As a service principal: use a profile with its API key and secret, skip login, and add the MCP entry oh ai-gateway login would print. In short:

claude mcp add-json --scope user oh-ai-gateway \
  '{"type":"http","url":"<gateway>/mcp","headersHelper":"oh ai-gateway token --format mcp-headers --gateway-url <gateway>"}'
oh ai-gateway run -- claude

For Codex 0.148.0 or later, add to ~/.codex/config.toml:

[mcp_servers.oh-ai-gateway]
url = "<gateway>/mcp"
http_headers_helper = "oh ai-gateway token --format mcp-headers --gateway-url <gateway>"
  • Model calls go through a local proxy that run starts on 127.0.0.1 and stops when the client exits. It sets a fresh X-Onehouse-Authorization on every request and retries once after a 401. The client gets the proxy's address and a per-run secret in its environment; nothing is copied by hand or written to disk.
  • MCP tools use the headersHelper (Claude Code) or http_headers_helper (Codex). The client runs it on every connection and again after a 401.
  • Codex runs http_headers_helper without your shell's ONEHOUSE_* variables. The helper oh ai-gateway login prints carries --profile and, as an env prefix (not on Windows), any ONEHOUSE_CREDENTIALS_FILE or ONEHOUSE_SESSION_STORE you set. Writing the entry by hand, do the same, and keep a service principal's key and secret in the profile rather than in ONEHOUSE_API_KEY and ONEHOUSE_API_SECRET.
  • Codex sends only /v1/responses, which the gateway passes to the provider as is, so -m must name a model alias served by an OpenAI model with the Responses API, such as gpt-5. An alias served by Anthropic returns 404, and gpt-4 fails: it rejects Codex's web_search_preview tool and its 8K context is too small.
  • Add the MCP entry at user scope: a project or local-scope headersHelper does not run until you accept the folder trust prompt.
  • oh ai-gateway proxy runs the proxy on its own for other clients and prints the two variables to set.
  • oh ai-gateway token prints a token, and --format mcp-headers prints the JSON a headers helper returns.
  • oh ai-gateway logout ends the sign-in; the profile's service principal, if any, applies again. Tokens already issued to a person stay valid until they expire, up to 7 days.
  • run warns when ANTHROPIC_API_KEY is set: it displaces your subscription, and the gateway forwards it upstream as your own key.

Global Options

oh [--profile NAME] [--timeout MINS] [--output table|json] COMMAND
Option Default Description
--profile / -p _default key in credentials file Credentials profile to use
--timeout / -t 10 Minutes to wait for async operations
--output / -o table Output format: table or json

Every SQL-backed command also accepts --show-sql to print the generated SQL statement without executing it.

With -o json, stdout carries only the JSON result; status lines such as OK ... go to stderr, so oh -o json ... | jq always parses.

onehouse-cli and onehouse-cli-configure are kept as aliases for backward compatibility.

Commands

Clusters

oh cluster show
oh cluster describe CLUSTER_NAME
oh cluster create CLUSTER_NAME --type SQL --max-ocu 10 --min-ocu 2
oh cluster alter  CLUSTER_NAME --state STOP
oh cluster alter  CLUSTER_NAME --max-ocu 20
oh cluster alter  CLUSTER_NAME --new-name NEW_NAME
oh cluster delete CLUSTER_NAME

Cluster types: Managed, SQL, Spark, Open_Engines, Notebook, LakeBase

Lakes

oh lake show
oh lake create LAKE_NAME --type MANAGED --bucket-path s3://my-bucket/ --default-services-cluster mycluster
oh lake alter  LAKE_NAME --default-services-cluster newcluster
oh lake delete LAKE_NAME [--cascade]
oh lake describe LAKE_NAME

Databases

oh database show   --lake LAKE_NAME
oh database create DB_NAME --lake LAKE_NAME
oh database delete DB_NAME --lake LAKE_NAME [--cascade]

Tables

oh table show --lake LAKE_NAME --database DB_NAME

Table Services

oh table service create    --lake L --database D --table T --service COMPACT --trigger-mode ON_DEMAND
oh table service alter     --lake L --database D --table T --service COMPACT --trigger-mode AUTOMATIC
oh table service describe  --lake L --database D --table T --service COMPACT
oh table service show      --lake L --database D --table T
oh table service show-runs --lake L --database D --table T --service COMPACT
oh table service run       --lake L --database D --table T --service COMPACT
oh table service pause     --lake L --database D --table T --service COMPACT
oh table service resume    --lake L --database D --table T --service COMPACT
oh table service cancel    --lake L --database D --table T --service CLUSTER   # only CLUSTER runs can be cancelled
oh table service alter-cluster --lake L --database D --table T --services-cluster newcluster
oh table service delete    --lake L --database D --table T --service CLUSTER
# Enable/disable a service, or configure AUTOSAVEPOINT / RESTORE (ALTER SERVICE IN TABLE)
oh table service configure --lake L --database D --table T --service COMPACT --disabled --trigger-mode AUTOMATIC
oh table service configure --lake L --database D --table T --service AUTOSAVEPOINT --enabled \
    --trigger-mode AUTOMATIC --options savepoint.frequency=daily \
    --options savepoint.frequency.hour=2 --options savepoint.frequency.minute=30

Services: CLUSTER, COMPACT, CLEAN, METASYNC
Run-only services (for run): CLUSTER, COMPACT, CLEAN, METASYNC, AUTOSAVEPOINT, RESTORE

Catalogs

oh catalog show
oh catalog describe CATALOG_NAME
oh catalog create   CATALOG_NAME --type GLUE   # --credential-type applies to DataHub catalogs only
oh catalog delete   CATALOG_NAME

Types: GLUE, HIVE, BIGQUERY, DATAHUB, ONETABLE, DATAPROC, UNITY, SNOWFLAKE, ONELAKE

Policies (access control synced with an external catalog)

oh policy show   --catalog CATALOG [--diff IMPORT|SYNC]
oh policy import --catalog CATALOG --changes-path URL
oh policy sync   --catalog CATALOG --changes-path URL
oh policy grant  --catalog CATALOG --changes-path URL
oh policy revoke --catalog CATALOG --changes-path URL
oh policy reset  [--yes]              # clears every policy for the project; asks first

Sources

oh source show
oh source describe SOURCE_NAME
oh source create   SOURCE_NAME --type S3 --credential-type CREDENTIAL_TYPE_ONEHOUSE [--if-not-exists]
oh source delete   SOURCE_NAME

Types: APACHE_KAFKA, MSK_KAFKA, CONFLUENT_KAFKA, S3, GCS, ONEHOUSE_TABLE, POSTGRES, MY_SQL

Flows

oh flow show
oh flow describe FLOW_NAME
oh flow create   FLOW_NAME \
    --source mysource --lake mylake --database mydb --table-name mytable \
    --write-mode IMMUTABLE --cluster mycluster \
    [--performance-profile BALANCED] \
    [--record-key-fields id] \
    [--partition-key-fields date:DATE_STRING] \
    [--partition-key "field=ts,type=DATE_STRING,input-format=yyyy-MM-dd HH:mm:ss"] \
    [--precombine-key-field ts] \
    [--min-sync-frequency-mins 5] \
    [--quarantine-enabled | --no-quarantine-enabled] \
    [--source-data-schema SUBJECT] \
    [--catalogs cat1] [--transformations tx1] [--validations val1]
oh flow alter  FLOW_NAME --state PAUSE          # or RESUME, CLEAN_AND_RESTART
oh flow alter  FLOW_NAME --cluster newcluster   # exactly one option at a time
oh flow delete FLOW_NAME
# Unnamed flows, or one flow writing to several tables: address it by its target table
oh flow alter    --in-table TABLE --lake LAKE --database DB --state PAUSE
oh flow describe --in-table TABLE --lake LAKE --database DB
oh flow delete   --in-table TABLE --lake LAKE --database DB

Partition key field format: FIELD:TYPE:INPUT_FORMAT:OUTPUT_FORMAT
Write modes: IMMUTABLE, MUTABLE
Performance profiles: BALANCED, FASTEST_READ, FASTEST_WRITE

Transformations

oh transformation show
oh transformation describe TX_NAME
oh transformation create   TX_NAME --type ROW_FILTERING [--options FILTER_SQL="col > 0"]
oh transformation delete   TX_NAME

Types: CONVERT_CDC, ROW_FILTERING, DERIVED_DATE, ADD_CURRENT_TIMESTAMP, USER_PROVIDED, DATA_MASKING, L_PARSE_JSON, FLATTEN_STRUCT, EXPLODE_ARRAY, VECTOR_EMBEDDING

Validations

oh validation show
oh validation describe VAL_NAME
oh validation create   VAL_NAME --type SCHEMA
oh validation delete   VAL_NAME

Types: SCHEMA, TIMESTAMP

Jobs

oh job show
oh job describe      JOB_NAME
oh job create        JOB_NAME --type JAR --cluster mycluster --parameters arg1 --parameters arg2 [--max-concurrent-runs N]
oh job create-and-run JOB_NAME --type PYTHON --cluster mycluster --parameters script.py
oh job alter         JOB_NAME --cluster newcluster     # or --parameters, or --max-concurrent-runs N (one at a time)
oh job run           JOB_NAME [--argument VALUE ...] [--idempotency-key KEY]
oh job cancel-run    JOB_RUN_UUID --job-name JOB_NAME
oh job describe-run  JOB_RUN_UUID --job-name JOB_NAME
oh job show-runs     JOB_NAME
oh job upload-jar    JAR_NAME --options s3.path=s3://my-bucket/path/file.jar   # or gcs.path=gs://...
oh job replace-jar   JAR_NAME --options s3.path=s3://my-bucket/path/file.jar
oh job show-jars
oh job describe-jar  JAR_NAME
oh job delete-jar    JAR_NAME

Job types: JAR, PYTHON

Service Principals

oh service-principal show
oh service-principal create SP_NAME
oh service-principal alter  SP_NAME --new-name NEW_NAME
oh service-principal delete SP_NAME

Groups

oh group show
oh group create GROUP_NAME
oh group alter  GROUP_NAME --new-name NEW_NAME
oh group delete GROUP_NAME

Grants and roles

Every command takes exactly one principal: --user EMAIL, --group NAME or --service-principal NAME.

oh grant  privilege lake.db.table --privilege SELECT [--privilege INSERT] --on table --group G
oh grant  privilege lake.db --privilege SELECT --on-all tables --in database --group G   # current and future tables; or --on-all databases --in lake
oh grant  role ADMIN my_project --on project --group G          # or --on account --service-principal S (grant only)
oh grant  member my_group --on group [--role manager] --user U  # group: users/SPs; --on service-principal: users/groups
oh grant  row-filter "region = 'US'" --table lake.db.table --group G
oh grant  column-mask ssn --table lake.db.table --mask-type mask-show-last-4 --group G   # or --custom EXPR
oh grant  column-access id amount --table lake.db.table --group G
oh grant  data-admin --user U
oh grant  show lake.db.table --on table
oh grant  show-roles my_project --principal-type group
oh revoke privilege|role|member|row-filter|column-mask|column-access|data-admin ...   # same flags; uses FROM

API Tokens

oh api-token create TOKEN_NAME --service-principal SP_NAME
oh api-token delete TOKEN_NAME --service-principal SP_NAME

OCU limit

oh ocu alter --limit 15

Data plane (GENERIC_K8S)

Onboard a customer-run Kubernetes cluster with S3-compatible storage. Every command takes --org ORG_ID, which overrides the profile's project_uid.

oh dataplane describe --org ORG_ID            # org, storage, settings, dp-connect and workflow state (no secrets)
oh dataplane storage connect --org ORG_ID     # check and register the bucket's key (see below)
oh dataplane storage status --org ORG_ID      # registered endpoint, region, key suffix, bucket name
oh dataplane storage rotate --org ORG_ID      # replace the key, same checks; the bucket must exist
oh dataplane validate-storage --org ORG_ID    # Onehouse validates the registered credentials
oh dataplane set --org ORG_ID --zookeeper-servers zk-0.zk:2181,zk-1.zk:2181 [--storage-class fast] [--options KEY=VALUE ...]
oh dataplane template --org ORG_ID --out values.yaml   # byok-dp-connect Helm values, written 0600
oh dataplane node-types --org ORG_ID
oh dataplane create --org ORG_ID [--wait]     # start provisioning; --wait polls until it finishes
oh dataplane status --org ORG_ID              # workflow id/status/failed task, dp-connect status
oh dataplane drop --org ORG_ID [--wait]       # tear down; runs immediately, no prompt

set changes only the settings it is given; the rest keep their current values. --storage-class '' means the cluster default. --options KEY=VALUE passes any other setting the server supports; a key given both as a flag and in --options is an error. -o json prints {settings, updated_keys}, and describe reports the same settings block (zookeeper_servers, storage_class_name).

template prints the chart reference, chart version, release name, namespace and file path, never the values (they hold credentials).

storage connect opens a form at http://127.0.0.1:<port>/<one-time-token>. The secret key is typed into the browser and held only in the oh process: it never reaches the terminal, shell history, disk or the command's output. Before registering, the CLI checks, in order:

  1. the endpoint is https:// with a DNS name (not an IP or loopback) that resolves;
  2. its TLS certificate is publicly trusted and matches the name (it reports the issuer and expiry);
  3. a signed ListBuckets succeeds (path-style; the region defaults to us-east-1 when left blank, and is corrected automatically if the store signs with another one);
  4. bucket onehouse-customer-bucket-<first 8 of the link UID>: reused if it exists and the key can reach it, created if it is missing and --bucket-mode create (the default for connect), and a hard stop on 403;
  5. a probe object can be put, read, listed and deleted.

A failed check re-renders the form with the error next to the field; fix it and resubmit. The form closes after a successful submit or after 10 minutes. If the key can see other buckets, the output warns and suggests a bucket-scoped policy.

Option Use
--no-browser / --port N Print the URL instead of opening it; pin the port for an SSH forward (ssh -L N:127.0.0.1:N)
--tty Prompt in the terminal; the secret is not echoed
--from-aws-profile NAME Read the key (and endpoint_url/region, if set) from that ~/.aws profile
--from-env Read ONEHOUSE_S3_ACCESS_KEY_ID / ONEHOUSE_S3_SECRET_ACCESS_KEY (CI only)
--endpoint / --region Prefill the form, or supply them for --from-env (also ONEHOUSE_S3_ENDPOINT / ONEHOUSE_S3_REGION)
--bucket-mode create|existing Create the bucket if missing, or require it to exist

-o json prints {endpoint, region, bucket, bucket_action, access_key_id_suffix, checks: [{name, ok, detail}], warnings}; the command exits 1 when a check fails.

Raw SQL

# Execute any SQL statement
oh sql exec --command "SHOW CLUSTERS"

# Fire-and-forget (returns request ID immediately, no polling)
oh sql exec --command "SHOW CLUSTERS" --async-mode

# Check status of a previous request
oh sql status REQUEST_ID

WITH options

Commands that accept extra configuration take --options KEY=VALUE (repeatable):

oh catalog create mycat --type HIVE \
    --credential-type CREDENTIAL_TYPE_ONEHOUSE \
    --options METASTORE_URI=thrift://host:9083 \
    --options DATABASE=default

Show SQL

Any command can print its generated SQL without making a network call:

oh cluster create mycluster --type SQL --show-sql
# CREATE CLUSTER `mycluster`
#   TYPE = 'SQL'

oh flow create myflow --source src --lake l --database d \
    --table-name t --write-mode IMMUTABLE --cluster c --show-sql

Examples

# Create a managed lake and database
oh lake create prod-lake --type MANAGED \
    --bucket-path s3://my-data-lake/ \
    --default-services-cluster services-cluster
oh database create analytics --lake prod-lake

# Create a Kafka flow
oh source create kafka-src --type APACHE_KAFKA \
    --credential-type CREDENTIAL_TYPE_ONEHOUSE \
    --options BOOTSTRAP_SERVERS=kafka:9092
oh flow create orders-flow \
    --source kafka-src --lake prod-lake \
    --database analytics --table-name orders \
    --write-mode MUTABLE --cluster ingest-cluster \
    --record-key-fields order_id

# Monitor a table's compaction service
oh table service show --lake prod-lake --database analytics --table orders
oh table service run  --lake prod-lake --database analytics --table orders --service COMPACT

# JSON output for scripting
oh --output json cluster show | jq '.'

Metadata

Release files for onehouse-cli 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for onehouse-cli 0.6.0
File Size Uploaded Provenance Actions
onehouse_cli-0.6.0.tar.gz 127.6 kB Without provenance Details for onehouse_cli-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for onehouse-cli 0.6.0
File Interpreter ABI Platform Actions
onehouse_cli-0.6.0-py3-none-any.whl Python 3 none any Details for onehouse_cli-0.6.0-py3-none-any.whl

Total release size: 273.3 kB

Release files / onehouse_cli-0.6.0.tar.gz

Download URL onehouse_cli-0.6.0.tar.gz
Size 127.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f5ae1e7fce7d2f9548207a3887b0c30c44aa54d40f225c95ad1d39b688e56efe
BLAKE2b-256 checksum
How to use checksums
bbcc56b3a5f11aa54e1d3ceb6bbae5804b96472eb306b92e778d2788aec3defa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Release files / onehouse_cli-0.6.0-py3-none-any.whl

Download URL onehouse_cli-0.6.0-py3-none-any.whl
Size 145.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a291185acb7bf8c9a360b4f914ece850d17820f3d3185e748d21daa81cce336e
BLAKE2b-256 checksum
How to use checksums
4611a587266b45c5ebf1cf7e21b1e2112197883175b2c77b7287890bd3c28fbc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Security for onehouse-cli 0.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page