Native Shell
Native Shell:AI 生成的 UI,在你的应用中原生呈现,覆盖每个平台。iOS、Android、macOS、Windows 与 Linux 上的应用、GPUI 应用与网页在运行时加载已签名、沙箱隔离的 TSX 模块并绘制 th
AI 翻译
openobserve-cli lets coding agents (Claude Code and others) — and humans — explore an OpenObserve (O2) backend from the command line: discover streams, inspect their schema, and run SQL searches and time-bucketed histograms over logs, metrics and traces.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Query OpenObserve from your terminal — built for coding agents.
openobserve-cli lets coding agents (Claude Code and others) — and humans —
explore an OpenObserve (O2) backend from the command
line across all three pillars: discover streams and schema, run SQL searches,
histograms and a live tail -f over logs, query metrics with PromQL
(instant and range), and reassemble a distributed trace into a span
waterfall. It works with both self-hosted OpenObserve and OpenObserve
Cloud, returns agent-friendly JSON with structured errors, and ships a
companion Skill that teaches an agent how to use it.
📖 Documentation site: https://angelmsger.github.io/openobserve-cli/
$ openobserve-cli search run --stream default --where "level = 'ERROR'" --since 1h --limit 3
{
"sql": "SELECT * FROM \"default\" WHERE level = 'ERROR' ORDER BY _timestamp DESC",
"total": 1284, "returned": 3, "took_ms": 18, "scan_size_mb": 4.2,
"hits": [ { "_timestamp": 1718528391000000, "level": "ERROR", "log": "…" } ]
}
search run/histogram/tail), metrics via PromQL (metrics query /
query-range), traces via a dedicated span model (trace search lists
recent traces; trace get rebuilds one into a parent/child waterfall).search histogram shows volume per time bucket, and
trace search surfaces recent traces, so an agent sees the shape before
pulling raw rows or a full span tree.search tail follows a stream as ndjson
like tail -f; --sql @file / @- reads long queries from a file or stdin;
search run --all pages through every matching row (bounded by --max).--since 1h, --from/--to,
RFC3339, epochs, now-30m) are converted to the microsecond timestamps the API
needs; stream and column names come from discovery commands, never guesses.{items, next, has_more} list
envelope, --format json|table|ndjson, and --fields projection to spend
minimal context.category/code/hint/next_steps/retryable) and mapped to a stable exit
code, so a script or agent can branch and self-recover.stream list, a column from stream schema, an org from
org list..env file, a
YAML config file, or an interactive wizard; multiple named server contexts;
secrets stored in the OS keychain.openobserve Skill, embedded in the binary, that
guides coding agents through the CLI.Scope (v0.18): telemetry queries remain read-only. Alert and Dashboard management supports discovery, JSON backup/restore, create/update/delete and alert enable/disable. Every write supports
--dry-runand honors session read-only mode; deletion requires--yes. Functions/pipelines, users and ingestion remain planned.
SQL search run, search histogram and search tail default to --type logs.
For raw metric or trace records, pass the discovered --type metrics or
--type traces. Use PromQL for metric calculations and trace get for span
trees; trace get selects the traces namespace automatically.
openobserve-cli alert list
openobserve-cli dashboard list --title traffic
openobserve-cli dashboard get <id> --folder <folder-id> > dashboard.json
# Edit dashboard.json while retaining its hash, then preview and apply:
openobserve-cli dashboard update <id> --folder <folder-id> --file dashboard.json --dry-run
openobserve-cli dashboard update <id> --folder <folder-id> --file dashboard.json
Use the IDs and folders returned by the lists. A stale Dashboard backup is
rejected with a conflict; fetch the current definition and re-apply your edits.
Writes are allowed by default. Set OPENOBSERVE_CLI_READ_ONLY=1 to block them,
then use --allow-writes only for an intended mutation. Alert management needs
OpenObserve's ID-based v2 API. See the Alert guide,
Dashboard guide and
read-only mode.
npm install -g @angelmsger/openobserve-cli
npm downloads the prebuilt binary for your platform, verifies its SHA-256
checksum, and keeps upgrades one npm update -g @angelmsger/openobserve-cli
away.
go install github.com/angelmsger/openobserve-cli/cmd/openobserve-cli@latest # go 1.24+
make install # from a source checkout
Or download a prebuilt binary from the Releases page. The full installation guide covers every method, shell completion and the companion Skill.
The openobserve Skill is embedded in the binary; it teaches your coding agent
(Claude Code, Codex, Cursor, Agents (shared), Gemini CLI, GitHub Copilot, OpenCode, Continue, Windsurf, Grok Build, Pi, Kilo Code, and Roo Code) how to drive the CLI. skill install probes for
installed agents and installs into each one found:
openobserve-cli skill install # auto-detect; install for each agent found
openobserve-cli skill install --agent codex
openobserve-cli skill status # compare loaded, installed, embedded versions
openobserve-cli skill uninstall # remove it again
After upgrading the CLI, re-run skill install and reload the agent context.
source <(openobserve-cli completion bash) # bash, current shell
openobserve-cli completion zsh > "${fpath[1]}/_openobserve-cli" # zsh, persistent
fish and PowerShell are supported too — see openobserve-cli completion --help.
openobserve-cli config init --pretty # interactive TUI setup (recommended for humans)
openobserve-cli doctor # verify configuration and connectivity
openobserve-cli org list # discover organizations
openobserve-cli stream list # discover streams (the map)
openobserve-cli stream schema default # queryable columns + search settings
# logs: volume over time, then the rows behind a spike
openobserve-cli search histogram --stream default --since 6h --interval 5m
openobserve-cli search run --stream default --where "level = 'ERROR'" --since 1h --limit 20
# metrics: error rate over the last hour, one point per minute (PromQL)
openobserve-cli metrics query-range \
--query 'sum(rate(http_requests_total{status=~"5.."}[5m]))' --since 1h --step 1m
# traces: find a recent trace, then open its span waterfall
openobserve-cli trace search --stream default --since 1h --limit 20
openobserve-cli trace get <trace_id> --stream default --since 1h
Settings resolve in precedence order (highest first): CLI flags → environment
variables (OPENOBSERVE_*) → .env → ~/.angelmsger/openobserve/config.yaml →
defaults. Secrets are stored in the OS keychain. If Windows Credential Manager
is unavailable, the fallback is encrypted with per-user DPAPI; macOS/Linux
retain the 0600 fallback. Secrets are never written to the config file.
For headless / CI / agent use, configure entirely from the environment:
export OPENOBSERVE_URL=http://localhost:5080 # or https://api.openobserve.ai
export OPENOBSERVE_ORG=default
export [email protected]
export OPENOBSERVE_PASSWORD='Complexpass#123'
# …or a pre-generated token instead of email+password:
export OPENOBSERVE_TOKEN='<base64-or-Basic/Bearer value>'
When OpenObserve logs users in through an external identity provider, those users have no local password and cannot authenticate the CLI directly. Create a Service Account (IAM → Service Accounts), assign it a role, then use its email + token as the credentials above (the token goes in the password position). See the SSO / OAuth section of the getting-started reference for the full walkthrough.
Instances behind SSO cannot use a password or a generated token. Sign in through a real browser instead:
openobserve-cli auth login --browser
A browser window opens on your instance's login page; once you are signed in the CLI captures the session, verifies it with an authenticated request, and stores it in the OS keychain.
Requires a Chromium-family browser (Chrome, Chromium, Edge or Brave) and a
graphical session. Set OPENOBSERVE_BROWSER to choose a specific one. The
browser profile is remembered under ~/.angelmsger/openobserve/browser-profile
so you are not sent through SSO on every login; --fresh-profile opts out, and
auth logout removes it.
| Command | Purpose |
|---|---|
org list / org use | discover organizations; set the default one |
stream list | list streams with type and storage stats (the discovery map) |
stream schema | a stream's queryable columns and full-text-search settings |
stream get / stream stats | full stream detail; document count, time range, size |
search run | run a SQL query (auto-built from --stream/--where, or a full --sql; @file/@-; --all to page everything) |
search histogram | time-bucketed counts — volume over time before pulling rows |
search tail | follow a stream live, printing new rows as ndjson (Ctrl-C to stop) |
metrics query / query-range | evaluate a PromQL expression at an instant, or across a window at --step |
trace search / trace get | list recent traces; reassemble one trace into a span waterfall |
auth login / status / logout | store credentials, check identity, sign out |
config init / show / get-contexts / use-context / delete-context | setup, inspect, manage servers |
doctor | check configuration, credentials and connectivity |
skill install / uninstall | deploy or remove the embedded companion Skill |
version | print version and build information |
In the default JSON output, list commands return a {items, next, has_more}
envelope; --format ndjson instead streams the items themselves, one JSON object
per line (ideal for piping search run hits into jq). --fields a,b.c projects
output down to specific dot-paths.
For paginated NDJSON, stderr carries a separate
{"_notice":{"pagination":{"next":"20","has_more":true},"next_steps":["Pass next as --offset to retrieve the next page."]}}
record after the rows. Pass next as --offset; keep the same query and fixed
absolute --from and --to values across pages. Repeating --since moves
the time window and can duplicate or skip rows. Single-page SQL search verifies
an ambiguous full page with at most one extra single-row request, without a
full-count query. search run --all traverses one resolved window automatically
and retains its existing --max truncation notices. JSON search summaries are
unchanged.
Time ranges accept --since 15m|1h|24h|7d, or --from/--to as RFC3339, a date,
an epoch (seconds/millis/micros), or now-30m; the CLI converts to the
microsecond timestamps the search API requires. --since cannot be combined
with --from or --to, and --to requires --from (it defaults to now); a
conflicting window is a BAD_TIME_RANGE usage error.
A single config file can hold several OpenObserve servers as named contexts.
Most users need only one and never see the concept. When a config already
exists, re-running config init lists it and asks whether to edit a context,
add a new one, or replace everything; pass config init --context prod
to skip that prompt and target a context directly. Then:
openobserve-cli config get-contexts # list contexts, current marked
openobserve-cli config use-context prod # switch the current context
openobserve-cli --use-context prod stream list # override for one command
openobserve-cli config delete-context staging # remove a context and its unused secret
OPENOBSERVE_CONTEXT overrides the current context via the environment. New
context names are saved trimmed and in lower case; existing names keep their
spelling and match in any case.
Failures are JSON on stderr (stdout stays a clean data channel) and map to
stable exit codes: 0 success, 2 usage, 3 config, 4 auth, 5 permission,
6 not found, 7 rate limit, 8 network, 9 server, 10 parse, 11 conflict.
Each error carries next_steps naming the command to run next, and retryable
to guide back-off.
The HTTP client that powers the CLI is published as a standalone Go package, so a GUI or other tool can query OpenObserve directly — same normalized models and structured errors, without shelling out to the binary.
import (
"context"
"encoding/base64"
"net/http"
"os"
api "github.com/angelmsger/openobserve-cli/pkg/apiclient"
cerr "github.com/angelmsger/openobserve-cli/pkg/errors"
"github.com/angelmsger/openobserve-cli/pkg/transport"
)
// Authentication is a transport.Decorator you supply — it sets the
// Authorization header on every request. OpenObserve uses HTTP Basic
// (email + password); a pre-generated token works too.
func basic(email, password string) transport.Decorator {
header := "Basic " + base64.StdEncoding.EncodeToString([]byte(email+":"+password))
return func(r *http.Request) { r.Header.Set("Authorization", header) }
}
ctx := context.Background()
client, err := api.Build(api.BuildParams{
BaseURL: "https://o2.example.com:5080",
Org: "default",
AuthDecorator: basic(os.Getenv("OPENOBSERVE_EMAIL"), os.Getenv("OPENOBSERVE_PASSWORD")),
})
if err != nil { /* see error handling below */ }
streams, err := client.ListStreams(ctx, "default", "logs", true) // include schema
The example hand-rolls the decorator to keep dependencies minimal, but two more packages save you the work when you want the CLI's own behavior:
pkg/auth — the Credential model. It supports basic and token
Authorization headers plus browser-captured session envelopes (cookies with
an optional Authorization fallback), validates itself, and exposes
Credential.Decorator() to drop straight into BuildParams.AuthDecorator.pkg/config — the on-disk config-file model (named contexts +
current_context + shared defaults, with file IO). Import it to read or write
the same config.yaml the CLI uses, so a GUI and the CLI share one config.
Secrets are never stored there; passwords, tokens, and captured sessions live
in the OS keychain.Errors are *errors.CLIError with a stable Category and Code, so callers branch
on failure kinds instead of parsing strings:
if ce := cerr.AsCLIError(err); ce != nil {
// ce.Category, ce.Code, ce.Hint, ce.NextSteps, ce.HTTPStatus, ce.Retryable
}
These
pkg/...packages primarily back this CLI and its companion Skill; their exported surface is treated as a stable contract. Read the package doc comment (go doc ./pkg/apiclient) before changing it.
make build # compile to ./bin/openobserve-cli
make test # unit + httptest integration tests
make e2e # build + run against an in-repo mock OpenObserve server
make lint # gofmt + go vet
make docs # regenerate the CLI reference under docs/cli/
CONTRIBUTING.md covers the conventions and commands;
docs/technical-design.md the architecture, and
docs/releasing.md the release process. The docs/cli/
reference is generated from the cobra command tree by cmd/gen-docs, so it
always matches --help — run make docs after changing a command or flag, and
commit the result (CI fails if it drifts). See CHANGELOG.md for
the version history.
Part of a family of agent-facing CLIs — one skeleton, one set of conventions, all built for coding agents. Browse the full set at github.com/AngelMsger:
Released under the MIT License.
An installer can run openobserve-cli config set-context team --base-url <url> --auth-scheme basic --activate without credentials or network access. Members then run openobserve-cli auth guide and openobserve-cli auth login. See team distribution and personal login for environment-only presets, conflict handling, and version-specific credential pages.
To point a prepared team context at a login this machine already has for the
same service, whatever scheme it uses and preferring a password or token to a
browser session, run openobserve-cli --use-context team auth reuse --dry-run,
then omit --dry-run.
See existing-login reuse.