The official CLI for the OpenAI REST API.
brew install openai/tools/openaiTo test or install the CLI locally, you need Go version 1.26 or later installed.
go install 'github.com/openai/openai-cli/cmd/openai@latest'Once you have run go install, the binary is placed in your Go bin directory:
- Default location:
$HOME/go/bin(or$GOPATH/binif GOPATH is set) - Check your path: Run
go env GOPATHto see the base directory
If commands aren't found after installation, add the Go bin directory to your PATH:
# Add to your shell profile (.zshrc, .bashrc, etc.)
export PATH="$PATH:$(go env GOPATH)/bin"After cloning the git repository for this project, you can use the
scripts/run script to run the tool locally:
./scripts/run args...The CLI follows a resource-based command structure:
openai [resource] <command> [flags...]Standard API endpoints require an API key:
export OPENAI_API_KEY="sk-..."
openai responses create \
--input "Say this is a test" \
--model gpt-5.5Admin endpoints require an admin API key:
export OPENAI_ADMIN_KEY="sk-admin-..."
openai admin:organization:usage completions \
--start-time 1735689600 \
--end-time 1735776000 \
--bucket-width 1dRun openai for a short starting guide. Help works without an API key or network connection:
openai help setup # Enter your API key safely
openai images generate --help # Example and common inputs
openai help --all images generate # Every image option and its details
openai help --all # Every command and global optionAdd --help (or -h) to any command for its short guide. Help changes only
what is displayed; command behavior, defaults, and output formats are unchanged.
Successful JSON responses print readable text by default, including in pipes.
Use --format json or --format jsonl in scripts that parse API data.
See reading command results for extraction, binary
output, and the scope of readable presentation.
openai images generate --prompt "A tiny orange robot" saves images to
~/Downloads/gpt-images/ and prints their paths, including in pipes. The CLI
uses gpt-image-2.5-sunburst when saving without an explicit model or legacy
response format. Use --model for another exact ID, --name for a filename,
or --output-dir for an existing directory. Existing files are kept.
--format json returns API data without saving or applying the CLI preset.
images edit and images create-variation also save new results while keeping
their source files. See image generation and saving
for commands and defaults.
Errors print actionable summaries to stderr by default. Use --format-error json
for original API error details, including unknown fields and SDK-reported stream
error events. For those events, extraction paths include the error envelope,
for example --transform-error error.code. Explicit --format
values json, jsonl, raw, and yaml also apply to errors unless overridden
by --format-error; an explicit --format-error auto or text restores summaries.
--transform-error extracts error data independently of successful output.
Malformed or empty error bodies receive a safe diagnostic; HTTP status is included
only when the SDK retains it. Summaries omit rejected values and request URLs;
explicit API error details can contain server-supplied sensitive data.
| Environment variable | Required | Default value |
|---|---|---|
OPENAI_API_KEY |
no | null |
OPENAI_ADMIN_KEY |
no | null |
OPENAI_ORG_ID |
no | null |
OPENAI_PROJECT_ID |
no | null |
OPENAI_WEBHOOK_SECRET |
no | null |
OPENAI_CUSTOM_HEADERS |
no | null |
OPENAI_MTLS_CLIENT_CERT_FILE |
no | null |
OPENAI_MTLS_CLIENT_KEY_FILE |
no | null |
OPENAI_UNTRUSTED_STDIN |
no | false |
--api-key(can also be set withOPENAI_API_KEYenv var)--admin-api-key(can also be set withOPENAI_ADMIN_KEYenv var)--organization(can also be set withOPENAI_ORG_IDenv var)--project(can also be set withOPENAI_PROJECT_IDenv var)--webhook-secret(can also be set withOPENAI_WEBHOOK_SECRETenv var)--mtls-client-cert-file(can also be set withOPENAI_MTLS_CLIENT_CERT_FILEenv var)--mtls-client-key-file(can also be set withOPENAI_MTLS_CLIENT_KEY_FILEenv var)--help- Show command line usage--debug- Enable debug logging. This includes HTTP request/response details and bodies; do not share debug logs if they may contain sensitive payloads.--version,-v- Show the CLI version--base-url- Use a custom API backend URL--header,-H- Add a literal request header asName: Value; repeat for multiple headers--format- Change the output format (auto,text,explore,json,jsonl,pretty,raw,yaml);autoselects readable text unless extracting data--format-error- Change the stderr error format (auto,text,explore,json,jsonl,pretty,raw,yaml);autoselects readable summaries unless extracting error data--transform- Transform the data output using GJSON syntax--transform-error- Transform the error output using GJSON syntax
Use --header or -H before or after a resource command:
openai --header 'X-Trace-ID: example-123' models list \
-H 'X-Client-Label: local,manual'Values are literal: commas and colons are preserved, and @ prefixes do not
read files. Surrounding spaces and tabs are trimmed from values. -H 'X-Example:'
sends an empty value. If a name is repeated, the last value wins regardless of
case, overriding default and endpoint-specific headers. Headers managed by the
HTTP transport, such as Host and Content-Length, retain the transport's
behavior. Supplied header values are hidden in help and redacted in debug logs.
For credential-bearing headers, have a secret manager or trusted launcher set
OPENAI_CUSTOM_HEADERS directly in the CLI's environment. This keeps credentials
out of command arguments and avoids typing literal secrets into shell history.
The variable accepts one Name: Value entry per line. For example, with
non-sensitive values:
export OPENAI_CUSTOM_HEADERS='X-Trace-ID: example-123
X-Client-Label: local,manual'
openai models list--header and endpoint-specific header flags override matching environment
entries. Environment header values are also redacted in debug logs. Use
OPENAI_API_KEY and OPENAI_ADMIN_KEY for standard API and admin authentication.
Mutual TLS is currently in beta. To opt in and activate a CA certificate for your organization or project, follow the OpenAI Mutual TLS Beta Program instructions.
To authenticate API-key requests with a mutual TLS client certificate, provide the client certificate and private key as separate PEM files. If certificate chain support is enabled for your organization, the certificate file must contain the leaf certificate first, followed by any intermediate certificates. Otherwise, use a client certificate signed directly by an activated CA certificate.
export OPENAI_MTLS_CLIENT_CERT_FILE=/run/secrets/openai/client-chain.pem
export OPENAI_MTLS_CLIENT_KEY_FILE=/run/secrets/openai/client.key
export OPENAI_BASE_URL=https://mtls.api.openai.com/v1
openai files listBoth mTLS files must be configured together. Keep the private key in a
permission-restricted file; do not put private-key contents directly in command
arguments or environment variables. The CLI does not automatically select an
mTLS endpoint, so configure OPENAI_BASE_URL or --base-url explicitly. HTTP
and SOCKS proxies remain supported, but HTTPS proxies are rejected to prevent
presenting the client certificate during the proxy's own TLS handshake.
To pass files to your API, you can use the @myfile.ext syntax:
openai <command> --arg @abe.jpgFiles can also be passed inside JSON or YAML blobs:
openai <command> --arg '{image: "@abe.jpg"}'
# Equivalent:
openai <command> <<YAML
arg:
image: "@abe.jpg"
YAMLWhen piping JSON or YAML from an untrusted source, enable untrusted-stdin mode:
untrusted-producer | OPENAI_UNTRUSTED_STDIN=1 openai <command> --file ./upload.txtIn this mode, values supplied through stdin are treated as literal data: @,
@file://, and @data:// references in request bodies, headers, and query
parameters do not read local files. File-upload parameters must be provided
explicitly as command-line flags. Explicit flags retain their normal file
behavior and take precedence over values supplied through stdin. Leave
OPENAI_UNTRUSTED_STDIN unset when using trusted heredocs or other trusted
piped input that intentionally references local files.
If you need to pass a string literal that begins with an @ sign, you can
escape the @ sign to avoid accidentally passing a file.
openai <command> --username '\@abe'For JSON endpoints, the CLI tool does filetype sniffing to determine whether the
file contents should be sent as a string literal (for plain text files) or as a
base64-encoded string literal (for binary files). If you need to explicitly send
the file as either plain text or base64-encoded data, you can use
@file://myfile.txt (for string encoding) or @data://myfile.dat (for
base64-encoding). Note that absolute paths will begin with @file:// or
@data://, followed by a third / (for example, @file:///tmp/file.txt).
openai <command> --arg @data://file.txtYou can link the CLI against a different version of the OpenAI Go SDK
for development purposes using the ./scripts/link script.
To link to a specific version from a repository (version can be a branch, git tag, or commit hash):
./scripts/link github.com/org/repo@versionTo link to a local copy of the SDK:
./scripts/link ../path/to/openai-goIf you run the link script without any arguments, it will default to ../openai-go.
Please share bug reports and feature requests through GitHub issues. Pull requests are limited to repository collaborators; we do not accept pull requests from non-collaborators. See CONTRIBUTING.md for the contribution policy and development guide. For security vulnerabilities, follow SECURITY.md.
Copyright 2026 OpenAI
This project is licensed under the Apache License 2.0.