Rust CLI for the StepSecurity API. Built from a vendored OpenAPI spec, designed for LLM-driven workflows, with a local audit trail intended to be mined for meta-action patterns.
Status: usable. Auth (env / keyring / config), spec-aware operation dispatch, and the audit trail are all wired. Curated CLI verbs are follow-on work; today every operation is reachable via
sidestep api <operationId>.
- Spec-driven.
sidestep-apiis generated fromspec/stepsecurity-v1.yaml. Update the spec, regenerate, ship. - SDK-backed. The same SDK that powers the CLI will power a future MCP server. Auth, retries, pagination, audit, and redaction live in one place.
- Agent-first. JSON output for non-TTY, predictable verb shape, stable operation IDs, structured audit trail.
- Audit as feature. Every API call emits a JSONL line locally; a future tooling pass can mine those traces to propose meta-actions that compose multiple primitive calls.
sidestep is published as a single Homebrew formula. CI updates it on
every push to main (alpha versions like alpha-20260430-…); when the
first stable tag is cut, the same formula switches to the stable
version. No separate -a channel — kos's pattern.
brew tap arcavenae/tap # one-time
brew install arcavenae/tap/sidestepbrew update
brew upgrade arcavenae/tap/sidestepbrew uninstall arcavenae/tap/sidestep
brew untap arcavenae/tap # optional, removes the tapgit clone https://github.com/ArcavenAE/sidestep.git
cd sidestep
cargo build --release
./target/release/sidestep --versionmacOS arm64 only for now. Other platforms can build from source.
Recommended path — store your StepSecurity API token in the macOS Keychain once, and let sidestep find it on every call:
# Interactively (token never appears in argv or shell history):
echo "$YOUR_TOKEN" | sidestep auth login --stdin
# Or from a .env-style file:
( . ~/path/to/.env && printf '%s' "$STEP_SECURITY_API_KEY" ) | sidestep auth login --stdin
# Verify (prints source + length, never the token itself):
sidestep auth statusIf you'd rather use an environment variable, SIDESTEP_API_TOKEN takes
precedence over the keychain:
export SIDESTEP_API_TOKEN="<bearer-token>"
sidestep auth statusA config file at ~/.config/sidestep/config.toml (override path with
SIDESTEP_CONFIG) is the third fallback:
[auth]
token = "<bearer-token>"Resolution order is env → keychain → config file → error. A missing config file is silent; a malformed config file fails fast with a TOML parser diagnostic so a typo doesn't quietly fall through.
After sidestep auth status reports authenticated, confirm the wiring
end-to-end with a few read-only commands. Replace your-org with your
GitHub organization name as it appears in StepSecurity.
# 1. Discover what operations are available.
sidestep ops list | head
sidestep ops list --filter detection
# 2. Inspect one operation's path, params, and which are required.
sidestep ops show getRunsDetails
# 3. Make a real read-only call. --param values are JSON-parsed first,
# so `limit=1` becomes the integer 1, not the string "1".
sidestep api getRunsDetails --param owner=your-org --param limit=1You should see a JSON response with workflow runs and security data. If
you get HTTP 401, double-check the token; if you get HTTP 404,
double-check the org name.
Every API call writes an audit line under ~/.sidestep/audit/ (macOS) or
~/.local/state/sidestep/audit/ (Linux). The line records
operation.id, path/query params, response shape hash, status, duration,
and where the token was resolved from — never the token itself.
sidestep --version
sidestep --help
sidestep auth login --token <v> # store in keychain
sidestep auth login --stdin # read token from stdin
sidestep auth status # report source + length
sidestep auth logout # remove from keychain
sidestep ops list [--filter <substring>] # list operationIds
sidestep ops show <operationId> # path, params, body shape
sidestep api <operationId> \ # invoke any spec operation
[--param key=value ...]
[--body '<json>']
[--no-audit]The sidestep api command reaches every operation in the StepSecurity
OpenAPI spec. Curated verbs (sidestep runs list, detections suppress,
etc.) are follow-on work; for now any operation is one --param away.
just build # cargo build --workspace
just test # cargo test --workspace --all-targets
just check # fmt + clippy + cargo-deny
just sync-spec # cargo xtask sync-spec — refresh vendored OpenAPI
just regen # cargo xtask regen — rebuild sidestep-apiSee CLAUDE.md and charter.md for design context, and docs/audit-trail-format.md for the audit-trail JSONL schema.
MIT — see LICENSE.