Manage Alibaba Sentinel rules from your terminal. Built for AI-powered DevOps.
Sound familiar?
Sentinel Dashboard doesn't persist rules β they vanish on restart. Dashboard β Nacos two-way sync breaks in well-known ways (#1911 / #3419 / #2531 still open). No official CLI β every rule change is a Web UI click-through. No versioning, no diff, no audit, no rollback.
sentinel-cli fixes this. One command. Your AI reads, validates, and updates Sentinel rules in Nacos/Apollo directly β no more clicking through a Dashboard that doesn't even persist.
# AI reads your flow rules directly, in CI-friendly JSON
sentinel-cli rule list --app=order-service --type=flow -o json | jq '.[] | .resource'npm install -g @jianghe12/sentinel-cliNo Node.js? Grab a pre-built binary from Releases and drop it into your PATH.
Slow download in mainland China? The
postinstallscript pulls a platform binary from GitHub Releases. SetSENTINEL_CLI_DOWNLOAD_MIRRORto a reachable mirror prefix, e.g.SENTINEL_CLI_DOWNLOAD_MIRROR=https://ghproxy.com/ npm install -g @jianghe12/sentinel-cliEvery binary is cosign-signed and SHA-256 verified during install. Don't disable
SENTINEL_CLI_SKIP_VERIFYin production.
Verify it works:
sentinel-cli versionSave your Sentinel rule storage backend as a named context β you'll never have to type it again.
Nacos (most common):
SENTINEL_PASSWORD=nacos sentinel-cli ctx set dev \
--backend=nacos \
--server=http://127.0.0.1:8848 \
--username=nacos \
--env=dev
sentinel-cli ctx use devAnonymous Nacos: If your Nacos instance has authentication disabled, omit --username when creating the context (sentinel-cli ctx set ... --backend=nacos --server=...). The CLI will skip the login flow and use the config API directly.
Namespace note: Nacos may auto-create a missing namespace when writing configs through its OpenAPI. Double-check --namespace spelling before running rule import, rule delete --all, or rule rollback, especially in CI scripts.
Apollo (Ctrip's open-source config center):
SENTINEL_PASSWORD=<apollo-openapi-token> sentinel-cli ctx set apollo-prod \
--backend=apollo \
--server=http://apollo-portal:8070 \
--apollo-app-id=sentinel-rules \
--apollo-env=PRO \
--apollo-namespace=SENTINEL \
--apollo-operator=admin \
--env=prodApollo requires a JSON-type namespace created beforehand in Apollo Portal. See Apollo Backend for details.
Done. Every command from here uses this connection automatically.
Multiple environments (dev / staging / prod)? See Multi-Environment.
# List all rules
sentinel-cli rule list --app=order-service
# Read a specific rule type
sentinel-cli rule get --app=order-service --type=flow
# Create a single rule from a JSON file
sentinel-cli rule create --app=order-service --type=flow -f flow-rule.json
# Preview a write without changing the backend
sentinel-cli rule create --app=order-service --type=flow -f flow-rule.json --dry-run -o json
# Validate local rule files before importing (shallow + deep cross-rule checks)
sentinel-cli rule validate -f ./rules/order-service/ --deep
# GitOps workflow: export β edit β diff β import
sentinel-cli rule export --app=order-service --dir=./rules/order-service/
vim ./rules/order-service/flow.json
sentinel-cli rule diff --app=order-service -f ./rules/order-service/
sentinel-cli rule import --app=order-service -f ./rules/order-service/ \
--ticket=OPS-1234 --yes --allow-production-rule-overwrite
# Roll back from a backup (R3, requires explicit allow flag)
sentinel-cli rule rollback --app=order-service --backup=20260521T103045.123456789Z \
--ticket=OPS-1234 --yes --allow-production-rule-rollback
# Query the local audit log (SRE / compliance)
sentinel-cli audit query --since=24h --env=prod --type=rule.delete
# Diagnose backend connectivity
sentinel-cli doctor -o json
# Show what this binary supports (apiVersion, backends, features)
sentinel-cli capabilities -o jsonThat's it. You're productive.
sentinel-cli ships with a built-in AI Skill file. Install once, and your AI coding assistant will know every command on its own β no prompting required.
sentinel-cli install claude --skills # Claude Code
sentinel-cli install cursor --skills # Cursor
sentinel-cli install copilot --skills # GitHub Copilot
sentinel-cli install windsurf --skills # Windsurf
sentinel-cli install codex --skills # OpenAI Codex
sentinel-cli install cc-switch --skills # CC Switch
sentinel-cli install opencode --skills # OpenCode
sentinel-cli install aider --skills # Aider
# Or install to a custom path
sentinel-cli install /your/custom/path --skillsAfter that, just tell your AI:
"Check the flow rules for
order-servicein prod."
It will automatically run:
sentinel-cli --context=prod rule list --app=order-service --type=flow -o jsonAnd when you ask:
"Add a 100 QPS limit on
createOrderfor the dev environment."
The skill already knows to validate first, dry-run, then write with the right safety flags.
No extra setup. No server to start. Just a markdown file your AI reads.
AI Skill content is embedded in the binary. npm installs, direct GitHub Release binaries,
go install, and local builds can all runsentinel-cli install <agent> --skillswithout extra files.
Mark a context --protected and every write operation automatically escalates risk level. The CLI refuses to proceed until you supply the matching credentials.
| Risk | When | What's required |
|---|---|---|
| R0 | Read operations | Nothing |
| R1 | Writes in unprotected context | Interactive: nothing. --non-interactive: --yes |
| R2 | Writes in protected context | --ticket=<matches ticketPattern> + --yes |
| R3 | Destructive batch operations (in any context) OR any write in protected context | R2 + a specific --allow-production-* flag |
Why batch/destructive operations are always R3: rule import (whole-group replacement), rule delete --all, and rule rollback are "one-shot fatal" operations. A wrong context name in a script can wipe out production rules in seconds. Forcing the same authorization flow across all environments builds muscle memory that prevents accidents. Use --ticket=DEV-LOCAL (or any pattern matching your context's ticketPattern) in dev β the cost is one second, the benefit is that you never wipe prod by mistake.
sentinel-cli ctx set prod \
--backend=nacos \
--server=http://prod.nacos.internal:8848 \
--env=prod \
--protected \
--ticket-pattern='^OPS-[0-9]+$' \
--ticket-validator=/usr/local/bin/check-jira.sh \
--credential-backend=keychainThree R3 allow flags (one per destructive operation, no master switch):
--allow-production-rule-overwriteβ forrule import(whole-group replacement)--allow-production-rule-deleteβ forrule delete --all--allow-production-rule-rollbackβ forrule rollback
External --ticket-validator lets you wire in JIRA / your internal ticketing system. The validator reads a single-line JSON on stdin ({"ticket":"OPS-1234","context":"prod","operator":"alice"}) and returns exit code 0 = approved, non-zero = rejected (stderr is surfaced). Execution timeout is hard-coded at 10 seconds.
Every write triggers an automatic pre-write snapshot under ~/.sentinel-cli/backups/<context>/<timestamp>/, and every operation (success or failure) appends a JSON line to ~/.sentinel-cli/audit.log. Use sentinel-cli audit query to filter the log; never cat audit.log | jq because the log can grow large and the CLI streams + supports filters.
Full threat model and hardening checklist: SECURITY.md.
Flag conventions: Repeated single-value flags (e.g. --type=flow --type=degrade) follow cobra's default "last value wins" semantics β the second value overrides the first. To query multiple rule types, run the command once per type and combine results: for t in flow degrade; do sentinel-cli rule list --app=X --type=$t; done.
Rule Management
sentinel-cli rule list --app=<app> [--type=<flow|degrade|system|authority|param>]
sentinel-cli rule get --app=<app> --type=<type> [--resource=<resource>]
sentinel-cli rule create --app=<app> --type=<type> -f <rule.json>
sentinel-cli rule update --app=<app> --type=<type> -f <rule.json>
sentinel-cli rule delete --app=<app> --type=<type> --resource=<resource>
sentinel-cli rule delete --app=<app> --type=<type> --all \
--ticket=<ticket> --allow-production-rule-delete
sentinel-cli rule export --app=<app> --dir=<output-dir>
sentinel-cli rule import --app=<app> -f <input-dir> [--dry-run] \
--ticket=<ticket> --yes --allow-production-rule-overwrite
sentinel-cli rule diff --app=<app> -f <input-dir>
sentinel-cli rule validate -f <input-dir> [--deep] [--fail-on-warnings]
sentinel-cli rule rollback --app=<app> --backup=<timestamp> \
--ticket=<ticket> --yes --allow-production-rule-rollbackrule export produces five files (flow.json / degrade.json / system.json / authority.json / param.json) β one per Sentinel rule type. rule import is whole-group replacement: any rule of that type not in the file is removed.
rule validate --deep runs cross-rule conflict detection: duplicate keys per type, dangling refResource in flow strategy 1/2, mixed authority strategies, param resources without matching flow, multiple system rules, and grade mismatches between flow and degrade on the same resource. Exit code 12 on errors; warnings only fail when --fail-on-warnings is set.
Multi-Environment (ctx)
sentinel-cli ctx set <name> --backend=<nacos|apollo> --server=<url> [flags...]
sentinel-cli ctx use <name> # Switch active environment
sentinel-cli ctx list # Show all contexts
sentinel-cli ctx current # Show active context
sentinel-cli ctx remove <name> # Delete a contextOverride the active context per-command with --context=<name> β useful for cross-environment scripts without permanently switching:
sentinel-cli --context=prod rule list --app=order-service
sentinel-cli --context=staging rule diff --app=order-service -f ./rules/Context file lives at ~/.sentinel-cli/config.yaml with mode 0600. Passwords are never logged in plain text.
Audit Log Query
# Past 24 hours, all deletes in prod
sentinel-cli audit query --since=24h --env=prod --type=rule.delete
# Everything tied to a ticket (JSON output for SRE tools)
sentinel-cli audit query --ticket=OPS-1234 -o json
# All authorization-denied events (security audit)
sentinel-cli audit query --type=authorization.denied --status=failure --reverse
# Custom audit log path
sentinel-cli audit query --path=/var/log/sentinel-cli-audit.log --since=7dSupported filters: --since / --until (relative 24h/7d/30m or RFC3339), --operator, --context-filter, --env, --protected=true|false, --type, --ticket, --app, --rule-type, --resource, --status, --limit (default 100, 0 = unlimited), --reverse (newest first).
Output formats: table (default TTY), JSON (top-level apiVersion: sentinel-cli.io/audit/v1), plain (one JSONL event per line β pipes cleanly into jq -c).
The query streams the log; filtered scans with --limit are ~800Γ faster than full-table reads. See PERFORMANCE.md for baselines.
Credential Backends
ctx set supports three credential backends via --credential-backend:
| Backend | Use case | Storage |
|---|---|---|
plain-yaml |
Local dev | ~/.sentinel-cli/config.yaml (mode 0600) |
keychain (recommended) |
Workstation / laptop | OS keychain (macOS Keychain / Windows Credential Manager / Linux Secret Service via dbus) |
encrypted-file |
Linux containers / CI without keychain | ~/.sentinel-cli/credentials.enc β Argon2id KDF + AES-256-GCM. Master passphrase from SENTINEL_MASTER_PASSWORD env or interactive TTY prompt (never written to disk) |
# encrypted-file backend
export SENTINEL_MASTER_PASSWORD="my-pass-456"
export SENTINEL_PASSWORD="nacos"
sentinel-cli ctx set prod \
--backend=nacos \
--server=http://prod.nacos.internal:8848 \
--credential-backend=encrypted-fileMaster passphrase cannot be recovered β losing it means re-creating all encrypted contexts. This is intentional (see SECURITY.md).
Apollo Backend
Apollo needs a JSON-type namespace created beforehand in Apollo Portal. The OpenAPI token reuses the password field, so all three credential backends work (plain-yaml / keychain / encrypted-file).
SENTINEL_PASSWORD=<apollo-openapi-token> sentinel-cli ctx set apollo-prod \
--backend=apollo \
--server=http://apollo-portal:8070 \
--apollo-app-id=sentinel-rules \
--apollo-env=PRO \
--apollo-cluster=default \
--apollo-namespace=SENTINEL \
--apollo-operator=admin \
--env=prod
sentinel-cli --context=apollo-prod rule list --app=order-service --type=flow| Apollo field | Value | Note |
|---|---|---|
env |
from --apollo-env |
Apollo env code (DEV/FAT/UAT/PRO) |
appId |
from --apollo-app-id |
Apollo's app β not the same as Sentinel's --app |
cluster |
from --apollo-cluster (default default) |
|
namespace |
from --apollo-namespace (default SENTINEL) |
Must be JSON-type, created in Portal |
item.key |
{sentinel-app}-{rule-type}-rules |
E.g. order-service-flow-rules |
item.value |
rule JSON array as string |
Apollo writes are two-phase (PUT item β POST releases). If the publish phase fails, the item edit stays in Apollo's draft area β fix and republish manually via Portal. Apollo has no native CAS; the CLI uses dataChangeLastModifiedTime as an optimistic-lock approximation (non-atomic window between GET and PUT).
Diagnostics (doctor)
sentinel-cli doctor # Probe backend reachability
sentinel-cli doctor -o json # Structured output for CI / scriptsReports context name, backend type, server URL, namespace, env, protected flag, and a live reachability check (HTTP GET against the backend's health endpoint).
Capabilities
sentinel-cli capabilities -o jsonReturns supported apiVersion values (sentinel-cli.io/context/v1, sentinel-cli.io/audit/v1), supported backends (nacos / apollo), ruleTypes (5), outputFormats (3), and features (dry-run / backup / audit / shallow-validate / deep-validate / rollback / encrypted-credstore / ticket-validator / audit-query). AI/MCP/CI consumers should call this before submitting any manifest or write to confirm schema compatibility.
Global Flags
| Flag | Short | Description |
|---|---|---|
--server |
Backend URL (overrides context) | |
--username |
Username (overrides context) | |
--password |
Password (hidden; prefer SENTINEL_PASSWORD env) |
|
--namespace |
-n |
Namespace (overrides context) |
--output |
-o |
table / json / plain |
--plain-header |
Include headers in plain output | |
--timeout |
Request timeout, e.g. 10s, 1m (default 30s) |
|
--dry-run |
Preview writes without contacting backend | |
--backup |
Backup current state before writing | |
--no-backup |
Explicitly skip backup | |
--non-interactive |
Fail instead of prompting when authorization is missing | |
--ticket |
Change ticket required for R2/R3 writes | |
--operator |
Operator identity (default $USER@$HOSTNAME) |
|
--reason |
Change reason | |
--strict-no-change |
Exit 13 when planned operation has no changes | |
--yes |
Confirm an authorized write | |
--allow-production-rule-overwrite |
R3: rule import whole-group overwrite |
|
--allow-production-rule-delete |
R3: rule delete --all or protected delete |
|
--allow-production-rule-rollback |
R3: rule rollback |
|
--debug |
Print HTTP request summary to stderr | |
--trace |
Print full HTTP trace to stderr | |
--concurrency |
Max parallelism for batch operations (default 8) | |
--context |
Temporarily override the active context | |
--config |
Temporarily override the config file path |
Environment variables recognized:
| Variable | Purpose |
|---|---|
SENTINEL_SERVER / SENTINEL_USERNAME / SENTINEL_PASSWORD / SENTINEL_NAMESPACE |
Connection defaults |
SENTINEL_MASTER_PASSWORD |
Master passphrase for encrypted-file credential backend |
SENTINEL_CLI_DOWNLOAD_MIRROR |
Mirror prefix for npm postinstall binary download |
SENTINEL_CLI_SKIP_VERIFY |
1 to skip SHA-256 verification (NOT recommended) |
SENTINEL_TEST_URL |
Used by //go:build integration tests |
Machine-readable JSON envelopes on every output:
sentinel-cli rule list --app=order-service -o json | jq '.[] | .resource'
sentinel-cli capabilities -o json | jq '.features'
sentinel-cli audit query --since=24h -o json | jq '.events[] | select(.status=="failure")'Every -o json response carries an apiVersion field. Today there are two:
sentinel-cli.io/context/v1β config / capabilities schemasentinel-cli.io/audit/v1β audit query schema
Within a major version, only additive changes happen. Breaking changes bump the version. AI/CI consumers should call capabilities -o json first to confirm compatibility.
Errors go to stderr. stdout is always clean.
Structured exit codes:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Any error (use error code in stderr JSON to distinguish) |
13 |
NO_CHANGE_REQUIRED (only when --strict-no-change is set) |
Error codes inside the stderr JSON: USAGE_ERROR, LOCAL_IO_ERROR, BACKEND_UNREACHABLE, BACKEND_ERROR, AUTHORIZATION_REQUIRED, VALIDATION_FAILED, NO_CHANGE_REQUIRED, UNSUPPORTED_PROTOCOL, NOT_IMPLEMENTED, CREDENTIAL_STORE_ERROR, CREDENTIAL_STORE_MISSING.
| Doc | What's in it |
|---|---|
| PRD.md | Full design β interfaces, safety model, milestones, key decisions |
| SECURITY.md | Threat model, hardening checklist, vulnerability reporting |
| PERFORMANCE.md | Baselines β rule validate / audit query / decode on 10k+ rules |
| CICD.md | GitOps templates: GitHub Actions / GitLab CI / Jenkinsfile |
| CHANGELOG.md | Per-version additions and fixes |
Integration tests start a real Nacos and run only with the integration build tag:
docker compose -f docker-compose.integration.yml up -d
docker compose -f docker-compose.integration.yml ps # wait for healthy
SENTINEL_TEST_URL=http://127.0.0.1:8848 \
go test -tags=integration -count=1 -v ./test/integration/...
docker compose -f docker-compose.integration.yml down -vgo test ./... without the tag stays fast (integration suite skipped).
If you also manage Nacos configurations (not just Sentinel rules), check out nacos-cli β same architecture, same safety model, same UX. Independent codebases, but learning one means you already know the other.
MIT Β© JiangHe12