Skip to main content
CoreSDK
Reference

CLI Reference

Complete reference for the CoreSDK CLI — sidecar management, policy testing, and config validation.

Available in Phase 1b. The sidecar binary ships with Phase 1b. Phase 1a (Rust crate only) users access the engine directly without a separate binary.

CLI Reference

The coresdk-sidecar binary is the standalone sidecar daemon. It embeds the Core Engine and exposes gRPC/HTTP locally. Install it:

cargo install coresdk-sidecar

Starting the sidecar

# Start with default config (reads coresdk.toml in the current directory)
coresdk-sidecar

# Start with explicit config file
coresdk-sidecar --config /etc/coresdk/coresdk.toml

# Start with environment variables only
CORESDK_SIDECAR_ADDR=[::1]:50051 \
CORESDK_TENANT_ID=acme-corp \
CORESDK_SERVICE_NAME=my-api \
coresdk-sidecar

Environment variables

The sidecar reads all configuration from CORESDK_* environment variables (which override coresdk.toml):

VariableDescription
CORESDK_SIDECAR_ADDRListen address for the gRPC endpoint (default: [::1]:50051)
CORESDK_TENANT_IDTenant ID for this deployment
CORESDK_SERVICE_NAMEOTel service.name resource attribute
CORESDK_FAIL_MODEopen (default) or closed
CORESDK_JWKS_URLHTTPS URL of the JWKS endpoint
CORESDK_POLICY_DIRDirectory of .rego policy files
CORESDK_LOG_LEVELtrace | debug | info | warn | error
OTEL_EXPORTER_OTLP_ENDPOINTOTLP gRPC endpoint for traces and metrics

See Environment Variables for the complete reference.


Policy commands

core policy test

Evaluate a policy directory against a JSON input or a directory of fixture files.

core policy test <policy-dir> [flags]

Single input:

core policy test ./policies --input '{
  "action": "orders:read",
  "user": { "role": "member", "tenant_id": "acme" },
  "resource": { "tenant": "acme", "id": "ord_1" }
}'
# → allow: true

Expect a deny and assert a reason:

core policy test ./policies \
  --input '{"action":"data:export","user":{"role":"member","tenant_id":"acme"},"resource":{"tenant":"acme"}}' \
  --expect deny \
  --expect-reason "enterprise plan required"
# → allow: false  ✓
# → deny_reasons: ["enterprise plan required"]  ✓

Fixture directory:

core policy test ./policies --fixtures ./tests/policy-fixtures/
# → 12 passed, 0 failed

CI mode (non-zero exit on any failure):

core policy test ./policies --fixtures ./tests/policy-fixtures/ --ci
FlagDescription
--input <json>JSON string to use as policy input
--input-file <path>Read input from a JSON file
--fixtures <dir>Run all *.input.json / *.expect.json pairs in a directory
--expect allow|denyAssert the expected decision (exit 1 if wrong)
--expect-reason <string>Assert a substring appears in deny_reasons
--ciExit non-zero on any failure; machine-readable output
--verbosePrint the full evaluated rule set

Fixture file format:

tests/policy-fixtures/member-read-own-tenant.input.json:

{
  "action": "orders:read",
  "user": { "role": "member", "tenant_id": "acme", "id": "usr_1" },
  "resource": { "tenant": "acme", "id": "ord_1" },
  "tenant": { "id": "acme", "plan": "starter" }
}

tests/policy-fixtures/member-read-own-tenant.expect.json:

{ "allow": true, "deny_reasons": [] }

core policy lint

Validate Rego syntax and check for common mistakes.

core policy lint ./policies
# → ✓ orders.rego
# → ✓ reports.rego
# → ✗ admin.rego:14 — undefined reference: input.user.roles (did you mean input.user.role?)
# → 1 error, 0 warnings
FlagDescription
--strictTreat warnings as errors
--format jsonMachine-readable output

core policy bench

Benchmark policy evaluation latency in-process.

core policy bench ./policies \
  --input ./tests/policy-fixtures/member-read-own-tenant.input.json \
  --iterations 10000
# → p50:  0.3 ms
# → p95:  0.6 ms
# → p99:  0.9 ms
# → p999: 2.1 ms

Fail CI if p99 exceeds a threshold:

core policy bench ./policies --p99-max-us 1000 --ci
FlagDescription
--iterations <n>Number of evaluations (default: 1000)
--warmup <n>Warmup iterations before measurement (default: 100)
--p99-max-us <n>Fail if p99 exceeds this microsecond threshold
--ciExit non-zero on threshold breach

core policy dry-run

Evaluate a policy against live traffic without enforcing decisions. Records outcomes to the audit log with simulated: true.

core policy dry-run ./policies \
  --sidecar http://localhost:7700 \
  --duration 5m
# → Shadowing live traffic for 5 minutes...
# → allow: 1,204  deny (simulated): 38  errors: 0
# → Top deny reasons:
#     "enterprise plan required"  (31)
#     "cross-tenant access"       (7)

Review the simulated denies in the audit log before switching to PolicyMode::Enforce.


core policy bundle

Package and sign a policy directory for air-gapped or manual delivery.

core policy bundle \
  --dir ./policies \
  --sign-key /etc/coresdk/signing-key.pem \
  --output dist/policy-bundle.tar.gz

core policy bundle inspect dist/policy-bundle.tar.gz
# → Policies: 6   Signed: yes (ES256)   Created: 2026-03-19T12:00:00Z

Advanced CLI commands (Phase 2)

The following commands (core trace tail, core log tail, core config, core sidecar, core saml, core policy, core coverage) are Phase 2 features. They are not available in Phase 1b.


Observability commands

core trace tail (Phase 2)

Interactive terminal trace viewer. Streams live OTel spans from the sidecar and renders them as a tree with timeline waterfall, error path highlighting, and a variable inspector.

core trace tail --sidecar http://localhost:7700
┌─ POST /api/orders  [200]  142 ms  trace: 4bf92f3577b3
│  ├─ auth.verify_token          3 ms   ✓ user: usr_2xK9
│  ├─ policy.evaluate            1 ms   ✓ allow  rule: member-own-tenant
│  ├─ db.fetch_orders           89 ms   rows: 12
│  └─ response.serialize         2 ms

└─ POST /api/orders  [403]  8 ms  trace: 7ca13f4821e1  ← error path
   ├─ auth.verify_token          3 ms   ✓
   └─ policy.evaluate            1 ms   ✗ deny: "cross-tenant access"
         intent: "fetch orders for dashboard"
         deny_reasons: ["resource.tenant != user.tenant_id"]

Press Enter to expand a span, v to open the variable inspector for that span, q to quit.

FlagDescription
--sidecar <url>Sidecar address (default: http://localhost:7700)
--tenant <id>Filter to a specific tenant
--service <name>Filter by service.name OTel attribute
--trace-id <id>Jump directly to a specific trace
--errors-onlyShow only traces containing errors or denies
--since <duration>Show traces from the last N minutes (e.g. 5m, 1h)

core log tail

Stream structured CoreSDK logs with real-time filtering.

# All logs
core log tail

# Filter by tenant
core log tail --tenant acme

# Only denied policy decisions
core log tail --tenant acme --filter 'policy.result=denied'

# Follow a specific user's activity
core log tail --tenant acme --filter 'user_id=usr_2xK9'

# Correlate with a trace
core log tail --trace-id 4bf92f3577b34da6a3ce929d0e0e4736
FlagDescription
--tenant <id>Filter to a specific tenant
--filter <expr>Filter expression (field=value, AND/OR supported)
--trace-id <id>Show logs for a specific trace ID
--level <level>Minimum log level: error, warn, info, debug
--since <duration>Show logs from the last N (e.g. 10m, 1h)
--format jsonRaw JSON output (default: pretty-printed)

Config commands

core config validate

Validate a CoreSDK config file for syntax errors and unknown keys.

core config validate ./coresdk.yaml
# → ✓ Config valid (42 keys)
# → Warning: rate_limit.per_tenant.acme is not set; using default (1000 rpm)

core config diff

Show what changed between two config files or a config file and the live sidecar config.

core config diff ./coresdk.yaml --live http://localhost:7700
# → + rate_limit.default_rpm: 500 → 1000
# → ~ tenant_cache_ttl: 60 (unchanged)

Sidecar commands

core sidecar status

Show the current sidecar health, cache state, and control plane sync status.

core sidecar status
# → Status:         healthy
# → Partitioned:    false
# → Last sync:      2026-03-19T12:34:01Z (8s ago)
# → Cache valid:    true
# → Policies:       6 loaded
# → JWKS:           2 key sets cached
# → Uptime:         2d 4h 12m
# → Version:        1.4.0

When partitioned:

core sidecar status
# → Status:         degraded (partitioned)
# → Partitioned:    true  (since 2026-03-19T12:30:00Z — 4m 01s ago)
# → Cache valid:    true
# → Cache age:      241s

core sidecar restart

Gracefully drain in-flight requests, then restart the sidecar process.

core sidecar restart
# → Draining in-flight requests (timeout: 30s)...
# → Flushing OTel batch...
# → Restarting...
# → Sidecar healthy (v1.4.0)
FlagDescription
--drain-timeout <s>Max seconds to wait for in-flight requests (default: 30)
--forceSkip drain; restart immediately

core sidecar reload-policy

Load a new policy bundle without restarting the sidecar.

core sidecar reload-policy --bundle /etc/coresdk/policy-bundle.tar.gz
# → Verifying bundle signature...
# → Signature valid.
# → Loading 6 policies...
# → Policy bundle active. Previous bundle retired.

SAML commands

core saml metadata

Generate SP metadata XML for import into your IdP.

core saml metadata --output sp-metadata.xml

core saml test-assertion

Generate a signed test SAML assertion for local development (no real IdP needed).

core saml test-assertion \
  --email alice@example.com \
  --role member \
  --tenant acme \
  --output /tmp/test-assertion.xml

Global flags

FlagDescription
--sidecar <url>Sidecar address (default: http://localhost:7700)
--config <path>Path to CoreSDK config file
--log-level <level>CLI log level: error, warn, info, debug
--output jsonMachine-readable JSON output (most commands)
--versionPrint CLI version
--helpPrint command help

Next steps

On this page