CLI¶
The shield CLI is a thin HTTP client that talks to a running ShieldAdmin instance over HTTP. Install it separately if you only need the command-line tool:
First-time setup¶
1. Start your app with ShieldAdmin mounted¶
2. Configure the server URL¶
Drop a .shield file in your project root (commit it alongside your code so the whole team gets the right URL automatically):
Or set it manually:
3. Log in¶
Credentials are stored in ~/.shield/config.json with an expiry timestamp.
Route management¶
shield status # show all registered routes
shield status GET:/payments # inspect one route
shield enable GET:/payments # restore to ACTIVE
shield disable GET:/payments --reason "Use /v2/payments instead"
shield maintenance GET:/payments --reason "DB migration"
shield maintenance GET:/payments \
--reason "Planned migration" \
--start 2025-06-01T02:00Z \
--end 2025-06-01T04:00Z
shield schedule GET:/payments \
--start 2025-06-01T02:00Z \
--end 2025-06-01T04:00Z \
--reason "Planned migration"
shield disable GET:/payments --reason "hotfix" --until 2h
Sample shield status output
| Route | Status | Reason | Since |
|---|---|---|---|
| GET /payments | MAINTENANCE | DB migration | 2 hours ago |
| GET /debug | ENV_GATED | dev, staging only | startup |
| GET /health | ACTIVE |
Global maintenance¶
shield global enable --reason "Deploying v2"
# Exempt specific paths so they keep responding
shield global enable --reason "Deploying v2" --exempt /health --exempt GET:/status
# Block even @force_active routes
shield global enable --reason "Hard lockdown" --include-force-active
# Adjust exemptions while active
shield global exempt-add /monitoring/ping
shield global exempt-remove /monitoring/ping
shield global status # check current state
shield global disable # restore normal operation
Environment gating¶
Restrict a route to specific environments at runtime without redeploying.
shield env set /api/debug dev # allow only the "dev" environment
shield env set /api/internal dev staging # allow dev and staging
shield env clear /api/debug # remove the gate, restore to ACTIVE
Note
The engine's current_env is set at startup (ShieldEngine(current_env="prod")). Requests from an environment not in allowed_envs receive a 403 ENV_GATED response. shield env clear is equivalent to calling shield enable — it transitions the route back to ACTIVE.
Multi-service context¶
When the Shield Server manages multiple services, scope every command to the right service.
Option A — SHIELD_SERVICE env var (recommended)¶
export SHIELD_SERVICE=payments-service
shield status # only payments-service routes
shield disable GET:/payments --reason "hotfix"
shield enable GET:/payments
All route commands (status, enable, disable, maintenance, schedule) read SHIELD_SERVICE automatically. An explicit --service flag always overrides it.
Option B — --service flag per command¶
shield status --service payments-service
shield disable GET:/payments --service payments-service --reason "hotfix"
Discover active context and connected services¶
shield current-service # show which service SHIELD_SERVICE points to
shield services # list all services registered with the Shield Server
Sample shield services output
Rate limits¶
Manage rate limit policies and view blocked requests. Requires api-shield[rate-limit] on the server.
shield rl and shield rate-limits are aliases — use whichever you prefer.
shield rl list # show all registered policies
shield rl set GET:/public/posts 20/minute # set or update a policy
shield rl set GET:/search 5/minute --algorithm fixed_window --key global
shield rl reset GET:/public/posts # clear counters immediately
shield rl delete GET:/public/posts # remove persisted policy override
shield rl hits # blocked requests log, page 1
shield rl hits --page 2 # next page
shield rl hits --per-page 50 # 50 rows per page
# identical — shield rate-limits is the full name
shield rate-limits list
shield rate-limits set GET:/public/posts 20/minute
SDK clients receive policy changes in real time
When using Shield Server + ShieldSDK, rate limit policies set via shield rl set are broadcast over the SSE stream and applied to every connected SDK client immediately — no restart required.
Sample shield rl list output
| Route | Limit | Algorithm | Key Strategy |
|---|---|---|---|
| GET /public/posts | 10/minute | fixed_window | ip |
| GET /search | 5/minute | fixed_window | global |
| GET /users/me | 100/minute | fixed_window | user |
Audit log¶
shield log # page 1, 20 entries per page
shield log --route GET:/payments # filter by route
shield log --page 2 # next page
shield log --per-page 50 # 50 rows per page
Sample shield log output
| Timestamp | Route | Action | Actor | Platform | Status | Reason |
|---|---|---|---|---|---|---|
| 2025-06-01 02:00:01 | GET:/payments | maintenance | alice | cli | active > maintenance | DB migration |
| 2025-06-01 01:59:00 | GET:/debug | disable | system | system | active > disabled | |
| 2025-06-01 01:58:00 | GET:/payments | rl_policy_set | alice | cli | set |
Auth commands¶
shield login admin # prompts for password interactively
shield login admin --password "$SHIELD_PASS" # inline, useful in CI
shield config show # check current session and resolved URL
shield logout # revokes server-side token and clears local credentials
Config commands¶
shield config set-url http://prod.example.com/shield # override server URL
shield config show # show URL, source, session
Server URL discovery¶
The CLI resolves the server URL using this priority order (highest wins):
| Priority | Source | How to set |
|---|---|---|
| 1 | SHIELD_SERVER_URL environment variable |
export SHIELD_SERVER_URL=http://... |
| 2 | SHIELD_SERVER_URL in a .shield file (walked up from cwd) |
Add to project root |
| 3 | server_url in ~/.shield/config.json |
shield config set-url ... |
| 4 | Default | http://localhost:8000/shield |
Route key format¶
Routes are identified by a method-prefixed key. Use the same format in all CLI commands:
| Decorator | Route key |
|---|---|
@router.get("/payments") |
GET:/payments |
@router.post("/payments") |
POST:/payments |
@router.get("/api/v1/users") |
GET:/api/v1/users |
shield disable "GET:/payments" # method-specific
shield enable "/payments" # applies to all methods under /payments
Next step¶
Dive into the full Reference documentation →