esops is your operations CLI for (self-managed) Elasticsearch and OpenSearch clusters. "es" (Elasticsearch, and its fork OpenSearch), "ops" for operations: because when the clusters need work, it’s time to go esops.
esops is a Go based binary for Site Reliability Engineering (SRE) and DevOps processes. These processes can be both day-to-day maintenance and large scale migration efforts on a long-term basis against both Elasticsearch and OpenSearch. Both product implementations have the same Command Line Interface (CLI) as the rest of its counterparts. The actual implementations only differ in implementation (i.e. ILM & ISM etc.) or through snapshot key differences and/or re-indexing dialect.
Showing the health of your cluster.
$ esops ops health -o wide
NAME STATUS DIALECT VERSION NODES DATA_NODES SHARDS PRIMARIES RELOC INIT UNASSIGNED PENDING ACTIVE%
esops-dev-es-mtls green elasticsearch 9.3.3 1 1 3 3 0 0 0 0 100.0Showing all the 'yellow' indices.
$ esops index list --health yellow --context local-os -o wide
NAME HEALTH STATUS PRI REP DOCS DELETED STORE PRI_STORE UUID CREATED
esops-stuck-replicas yellow open 1 3 1 0 4.2kb 4.2kb PFHUKha7RXmCOlj4kegBVQ 2026-05-07T08:20:57ZAnd many more.
The older the ES/OS cluster gets, the more often you will find yourself typing command lines using curl and jq to perform different operations like checking shard imbalance, explaining the allocation of requests, driving re-indexing, cleaning up snapshots, and swapping aliases. Rather than having a bunch of different command lines, esops is one binary that does all of the above.
- Adaptive, resumable reindexing (coming soon).
- Scriptable output in table, JSON, NDJSON, or YAML with stable schemas and standard exit codes.
- kubectl-style named contexts, with protection tiers (
none/prod). Destructive ops onprodrequire--i-know-this-is-prod; dry-runs and read-only commands are always allowed. - Secrets loaded securely via indirection (
${env:VAR},${file:...},${keyring:...}); inline plaintext secrets are refused and auth headers are redacted from logs. - Pipeline-friendly by design:
CI=trueauto-enables non-interactive mode and JSON logging. Stdout is pure data; stderr gets logs and progress. NDJSON streams large results without buffering. - One-command diagnostics:
esops ops diagbundles health, shards, hot threads, tasks, ILM/ISM, snapshots, etc. into a credential-free tarball: perfect for support tickets. - Single static binary,
CGO_ENABLED=0. No JVM, no Python runtime, no Docker. Drops into Alpine or scratch images without dragging a runtime along.
- Cluster Operations - Health, Shard Allocation Explanation, Shard Distribution, Hot Threads, Security Audit, Rebalance Helper, Redacted Diagnostic Bundle
- Migrating databases - Pre-flight Check, Mapping Plan One with Incompatibility Diffs, Task based Reindex With Resume + Auto Throttle, Doc Count And Sampled Checksum Verify, Atomic Alias-swap Cutover
- Manage your Indexes - List, Optimise, Rollover, Shrink, Open/Close, Aliases, Settings and Template ILM (ES) and ISM (OS) Policies
- Manage your Data Streams - List, Get, Stats, Recovery, Segments, Optimize, Rollover, Modify, Delete (Elasticsearch and OpenSearch)
- Manage your Snapshots - List, Create, Verify, Restore, Retention Prune
- Inspect Ingest Pipelines - List, Get (Elasticsearch and OpenSearch)
- Multiple Settings - Named contexts like kubectl's with per-context protection levels; Explicit acknowledgement is needed for destructive operations against prod context.
- Authentication - Basic, API key, bearer, mTLS, AWS SigV4
Pre-built binaries for Linux (amd64 and arm64), Darwin (amd64 and arm64) and Windows (amd64) are available on the release page. There are also .deb and .rpm packages. When a release is created, cosign signatures, SBOM, and SLSA provenance are generated.
Requires Go matching the floor in go.mod.
git clone https://github.com/esops-dev/esops-go
cd esops-go
make build
./bin/esops --helpDrop a config file at ~/.config/esops/config.yaml (see
config/esops.example.yaml for the full
schema):
current-context: prod-eu
defaults:
output: table
timeout: 30s
contexts:
prod-eu:
url: https://es-prod-eu.example.com:9200
protection: prod
username: esops
password: ${keyring:esops/prod-eu}
dev:
url: http://localhost:9200
protection: noneThen:
esops ops health
esops index list --health red
esops migrate plan --from idx-v1 --to idx-v2
esops migrate reindex --from idx-v1 --to idx-v2 --auto-throttle
esops migrate verify --source idx-v1 --target idx-v2
esops migrate cutover --alias idx --from idx-v1 --to idx-v2ops health · nodes · shards · allocation-explain · hot-threads
audit · rebalance · drain · uncordon · tasks · diag
settings · unblock · cache-clear
migrate plan · check · reindex · verify · cutover
index list · recovery · segments · optimize · rollover · shrink
open · close · aliases · settings · template
ilm (ES) · ism (OS)
datastream list · get · stats · recovery · segments · optimize
rollover · modify · delete
snapshot list · create · verify · restore · prune · register · deregister
pipeline list · get
config use-context · get-contexts · view · validate
See docs/ for per-command reference.
| Flag | Description |
|---|---|
--cacert PATH |
Custom CA bundle |
-c, --config PATH |
Config file (env: ESOPS_CONFIG) |
--context NAME |
Named cluster from config (alias: --cluster) |
--dry-run |
Where applicable |
--i-know-this-is-prod |
Required for destructive operations against a prod-protected context |
--insecure |
Skip TLS verification (last resort) |
--log-file PATH |
Append log lines to PATH instead of stderr (file created with mode 0600) |
--log-format FORMAT |
text | json |
--log-level LEVEL |
debug | info | warn | error |
--no-prompt |
Fail instead of prompting (CI-safe) |
-o, --output FORMAT |
table | json | ndjson | yaml | wide |
--timeout DURATION |
HTTP timeout (default 30s) |
--url URL |
Override: single cluster URL |
CI=true in the environment auto-enables --no-prompt and defaults --log-format=json.
esops config validate lints the config file without contacting any cluster. Intended for a pre-merge job so a typo doesn't roll out across a fleet:
esops --config esops.yaml config validate --strictDefault mode exits 0 on warnings, 2 on errors; --strict treats warnings as failures too. --output json emits a findings array for CI annotation tooling. Cluster-side checks ("does this config match reality") remain migrate check's job.
- docs/index.md — index management
- docs/datastream.md — data stream management
- docs/ops.md — cluster operations
- docs/snapshot.md — snapshot and repository inspection
- docs/pipeline.md — ingest pipeline inspection
- docs/transform.md — transform inspection
- docs/migrate.md — cross-cluster reindex pre-flight and planning
- docs/config.md — config schema, contexts, secrets
- docs/completion.md — shell completion
- docs/auth.md — Authentication
Found a vulnerability? See SECURITY.md. Please do not open public issues for security reports.
- No need for AI usage in the tool. Doesn't help this tool in any way;
- No OpenTelemetry tooling/metrics will be enabled in this tool. This is a standalone tool and is not connected to anything else;
- No usage of
--forceor anything else that could destroy the cluster or its data.
See CONTRIBUTING.md for development setup, testing against the local ES/OS dev clusters, and PR conventions.