Add comprehensive README with command reference and robot mode docs
Covers: install, quick start, all 12 commands with full flag tables, robot mode activation (--robot, --json, env var, TTY auto-detect), JSON envelope schema, exit codes (0-16), configuration (auth profiles, aliases, network policy), and architecture overview (cache layout, index structure, SSRF protection model). Written for both human engineers and AI agents — structured enough for LLM consumption while remaining scannable for humans.
This commit is contained in:
342
README.md
Normal file
342
README.md
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
# swagger-cli
|
||||||
|
|
||||||
|
A fast, cache-first CLI for exploring OpenAPI specifications. Built for engineering teams and AI agents.
|
||||||
|
|
||||||
|
**Key properties:**
|
||||||
|
- Query latency: <50ms on cached specs (index-backed, no raw spec parsing)
|
||||||
|
- First query: <2s including fetch + index build
|
||||||
|
- Robot mode: 100% structured JSON output with versioned schema contract
|
||||||
|
- Exit codes: Consistent, actionable, concurrency-safe (14 error types, codes 2-16)
|
||||||
|
- Offline-capable: all queries work without network after initial fetch
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo install --path .
|
||||||
|
```
|
||||||
|
|
||||||
|
Requires Rust 2024 edition.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fetch and cache a spec
|
||||||
|
swagger-cli fetch https://petstore3.swagger.io/api/v3/openapi.json --alias petstore
|
||||||
|
|
||||||
|
# List endpoints
|
||||||
|
swagger-cli list petstore
|
||||||
|
|
||||||
|
# Search across the API
|
||||||
|
swagger-cli search petstore "pet"
|
||||||
|
|
||||||
|
# Show endpoint details
|
||||||
|
swagger-cli show petstore "/pet/{petId}" --method GET
|
||||||
|
|
||||||
|
# Browse schemas
|
||||||
|
swagger-cli schemas petstore
|
||||||
|
|
||||||
|
# Machine-readable output (for agents)
|
||||||
|
swagger-cli list petstore --robot
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### fetch
|
||||||
|
|
||||||
|
Download and cache an OpenAPI spec.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli fetch <URL> --alias <NAME> [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
`<URL>` accepts HTTP/HTTPS URLs, `file://` paths, relative paths, or `-` for stdin.
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--alias <NAME>` | Required. Must match `^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$` |
|
||||||
|
| `-H, --header <HEADER>` | Additional HTTP header (repeatable, format: `"Name: Value"`) |
|
||||||
|
| `--bearer <TOKEN>` | Bearer token for Authorization header |
|
||||||
|
| `--auth-profile <NAME>` | Auth profile name from config.toml |
|
||||||
|
| `--force` | Overwrite existing alias |
|
||||||
|
| `--timeout-ms <N>` | HTTP request timeout in milliseconds (default: 10000) |
|
||||||
|
| `--max-bytes <N>` | Maximum response size in bytes (default: 26214400 / ~25 MB) |
|
||||||
|
| `--retries <N>` | Retries on transient errors (default: 2) |
|
||||||
|
| `--allow-private-host <HOST>` | Bypass SSRF protection for this host (repeatable) |
|
||||||
|
| `--allow-insecure-http` | Permit plain HTTP |
|
||||||
|
| `--resolve-external-refs` | Fetch and inline external `$ref` entries |
|
||||||
|
| `--ref-allow-host <HOST>` | Allowed host for external ref fetching (repeatable, required with `--resolve-external-refs`) |
|
||||||
|
| `--ref-max-depth <N>` | Maximum chain depth for transitive external refs (default: 10) |
|
||||||
|
| `--ref-max-bytes <N>` | Maximum total bytes fetched for external refs (default: 10485760 / ~10 MB) |
|
||||||
|
|
||||||
|
### list
|
||||||
|
|
||||||
|
List endpoints from a cached spec.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli list [ALIAS] [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--all-aliases` | Query across every cached alias |
|
||||||
|
| `-m, --method <METHOD>` | Filter by HTTP method (case-insensitive) |
|
||||||
|
| `-t, --tag <TAG>` | Filter by tag |
|
||||||
|
| `-p, --path <PATTERN>` | Filter by path pattern (regex) |
|
||||||
|
| `--sort <FIELD>` | Sort order: path (default), method, or tag |
|
||||||
|
| `-n, --limit <N>` | Maximum results (default: 50) |
|
||||||
|
| `-a, --all` | Show all results (no limit) |
|
||||||
|
|
||||||
|
### show
|
||||||
|
|
||||||
|
Display details of a specific endpoint.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli show <ALIAS> <PATH> [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `-m, --method <METHOD>` | HTTP method to show. Required when path has multiple methods |
|
||||||
|
| `--expand-refs` | Expand `$ref` entries inline |
|
||||||
|
| `--max-depth <N>` | Maximum depth for ref expansion (default: 3) |
|
||||||
|
|
||||||
|
Output includes the full operation object: summary, description, tags, operationId, security, parameters (path/query/header/cookie), request body, and response schemas with status codes.
|
||||||
|
|
||||||
|
Circular references are detected and annotated with `{"$circular_ref": "..."}`.
|
||||||
|
|
||||||
|
### search
|
||||||
|
|
||||||
|
Full-text search across endpoints and schemas.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli search [ALIAS] <QUERY> [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
When using `--all-aliases`, the first positional argument is treated as the query.
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--all-aliases` | Search across every cached alias |
|
||||||
|
| `--case-sensitive` | Case-sensitive matching |
|
||||||
|
| `--exact` | Match query as exact phrase |
|
||||||
|
| `--in <FIELDS>` | Fields to search (comma-separated): all (default), paths, descriptions, schemas |
|
||||||
|
| `--limit <N>` | Maximum results (default: 20) |
|
||||||
|
|
||||||
|
Scoring is tokenized with field weights (path > summary > description) and term coverage boost, quantized to basis points for deterministic output.
|
||||||
|
|
||||||
|
### schemas
|
||||||
|
|
||||||
|
Browse component schemas.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli schemas <ALIAS> [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--name <PATTERN>` | Filter schema names by regex |
|
||||||
|
| `--list` | List schemas (default mode) |
|
||||||
|
| `--show <NAME>` | Show a specific schema by exact name |
|
||||||
|
| `--expand-refs` | Expand `$ref` entries inline (show mode only) |
|
||||||
|
| `--max-depth <N>` | Maximum depth for ref expansion (default: 3) |
|
||||||
|
|
||||||
|
### tags
|
||||||
|
|
||||||
|
List tags from a cached spec with endpoint counts.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli tags <ALIAS>
|
||||||
|
```
|
||||||
|
|
||||||
|
### aliases
|
||||||
|
|
||||||
|
Manage spec aliases.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli aliases [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--list` | List all aliases (default) |
|
||||||
|
| `--show <ALIAS>` | Full details (URL, version, size, stats) |
|
||||||
|
| `--rename <OLD> <NEW>` | Rename an alias |
|
||||||
|
| `--delete <ALIAS>` | Delete an alias and cached files |
|
||||||
|
| `--set-default <ALIAS>` | Set the default alias (used when ALIAS is omitted in other commands) |
|
||||||
|
|
||||||
|
### sync
|
||||||
|
|
||||||
|
Re-fetch and update cached specs.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli sync [ALIAS] [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--all` | Sync all cached specs |
|
||||||
|
| `--dry-run` | Check for changes without writing |
|
||||||
|
| `--force` | Re-fetch regardless of cache freshness |
|
||||||
|
| `--details` | Include per-item change lists in output (capped at 200 items) |
|
||||||
|
| `--auth <PROFILE>` | Auth profile name from config |
|
||||||
|
| `--jobs <N>` | Maximum concurrent sync jobs, `--all` only (default: 4) |
|
||||||
|
| `--per-host <N>` | Maximum concurrent requests per host, `--all` only (default: 2) |
|
||||||
|
| `--max-failures <N>` | Abort after N alias failures, `--all` only |
|
||||||
|
| `--resume` | Resume a previously interrupted `--all` sync |
|
||||||
|
| `--allow-private-host <HOST>` | Bypass SSRF protection for this host (repeatable) |
|
||||||
|
|
||||||
|
Uses ETag + Last-Modified for conditional fetches. Respects `Retry-After` headers with exponential backoff. Per-alias progress checkpoints enable resumable execution.
|
||||||
|
|
||||||
|
### diff
|
||||||
|
|
||||||
|
Compare two spec versions (structural diff).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli diff <LEFT> <RIGHT> [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--fail-on <LEVEL>` | Exit non-zero if changes at this level: `breaking` |
|
||||||
|
| `--details` | Include per-item change descriptions |
|
||||||
|
|
||||||
|
Output covers added/removed/modified endpoints and schemas with a summary and breaking-change flag. Useful as a CI gate for API contract changes.
|
||||||
|
|
||||||
|
### doctor
|
||||||
|
|
||||||
|
Check cache health and diagnose issues.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli doctor [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--fix` | Attempt auto-repair |
|
||||||
|
| `--alias <ALIAS>` | Check a specific alias only |
|
||||||
|
|
||||||
|
Checks: directory permissions, meta.json generation + index_hash validation, index pointer validity, stale caches (30+ days), index version compatibility, and torn/partial cache state.
|
||||||
|
|
||||||
|
Fix modes: (1) rebuild index from raw, (2) reconstruct meta from raw + index, (3) delete alias only as last resort.
|
||||||
|
|
||||||
|
### cache
|
||||||
|
|
||||||
|
Manage the spec cache.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swagger-cli cache [OPTIONS]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--stats` | Show cache statistics (default) |
|
||||||
|
| `--path` | Print the cache directory path |
|
||||||
|
| `--prune-stale` | Remove aliases older than the stale threshold |
|
||||||
|
| `--prune-threshold <DAYS>` | Days before an alias is stale (default: 90) |
|
||||||
|
| `--max-total-mb <N>` | LRU eviction until total size is under this limit |
|
||||||
|
| `--dry-run` | Preview without deleting |
|
||||||
|
|
||||||
|
## Global Options
|
||||||
|
|
||||||
|
Every command accepts these flags:
|
||||||
|
|
||||||
|
| Flag | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `--robot` | Structured JSON output (auto-detects non-TTY) |
|
||||||
|
| `--pretty` | Pretty-print JSON output |
|
||||||
|
| `--network <MODE>` | `auto` (default), `online-only`, or `offline` |
|
||||||
|
| `--config <PATH>` | Path to config file (or `SWAGGER_CLI_CONFIG` env var) |
|
||||||
|
|
||||||
|
## Robot Mode
|
||||||
|
|
||||||
|
All commands support `--robot` for structured JSON output. Success:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"data": { ... },
|
||||||
|
"meta": {
|
||||||
|
"schema_version": 1,
|
||||||
|
"tool_version": "0.1.0",
|
||||||
|
"command": "list",
|
||||||
|
"duration_ms": 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Errors emit JSON to stderr:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ok": false,
|
||||||
|
"error": {
|
||||||
|
"code": "ALIAS_NOT_FOUND",
|
||||||
|
"message": "Alias not found: myapi",
|
||||||
|
"suggestion": "Run 'swagger-cli aliases --list' to see available aliases."
|
||||||
|
},
|
||||||
|
"meta": { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exit Codes
|
||||||
|
|
||||||
|
| Code | Error | Suggestion |
|
||||||
|
|------|-------|------------|
|
||||||
|
| 0 | Success | |
|
||||||
|
| 2 | `USAGE_ERROR` | Run `swagger-cli --help` |
|
||||||
|
| 4 | `NETWORK_ERROR` | Check connectivity or use `--network offline` |
|
||||||
|
| 5 | `INVALID_SPEC` | Verify URL points to valid OpenAPI 3.x JSON/YAML |
|
||||||
|
| 6 | `ALIAS_EXISTS` | Use `--force` to overwrite |
|
||||||
|
| 7 | `AUTH_ERROR` | Check auth profile in config.toml |
|
||||||
|
| 8 | `ALIAS_NOT_FOUND` | Run `aliases --list` to see available |
|
||||||
|
| 9 | `CACHE_LOCKED` | Wait or check for stale locks |
|
||||||
|
| 10 | `CACHE_ERROR` | Run `doctor --fix` |
|
||||||
|
| 11 | `CONFIG_ERROR` | Check config file, run `doctor` |
|
||||||
|
| 12 | `IO_ERROR` | File system error |
|
||||||
|
| 13 | `JSON_ERROR` | Invalid JSON/YAML parsing |
|
||||||
|
| 14 | `CACHE_INTEGRITY` | Run `doctor --fix` or re-fetch |
|
||||||
|
| 15 | `OFFLINE_MODE` | Use `--network auto` or `online-only` |
|
||||||
|
| 16 | `POLICY_BLOCKED` | Use `--allow-private-host` or `--allow-insecure-http` |
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Config file location: `~/.config/swagger-cli/config.toml` (or set `SWAGGER_CLI_CONFIG`).
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[auth_profiles.corp_internal]
|
||||||
|
credential_source = "env:MY_API_TOKEN"
|
||||||
|
auth_type = "bearer"
|
||||||
|
|
||||||
|
[auth_profiles.api_key]
|
||||||
|
credential_source = "env:API_KEY"
|
||||||
|
auth_type = "api_key"
|
||||||
|
header = "X-API-Key"
|
||||||
|
```
|
||||||
|
|
||||||
|
`credential_source` supports `env:VAR_NAME` and `file:/path/to/token`.
|
||||||
|
|
||||||
|
## Cache Layout
|
||||||
|
|
||||||
|
Specs are stored per-alias under `~/.cache/swagger-cli/aliases/{alias}/`:
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `raw.source` | Original upstream bytes (YAML or JSON, lossless provenance) |
|
||||||
|
| `raw.json` | Canonical normalized JSON (all queries operate on this) |
|
||||||
|
| `index.json` | Precomputed query index (endpoints, schemas, tags, search data) |
|
||||||
|
| `meta.json` | Fetch metadata, written last as commit marker |
|
||||||
|
|
||||||
|
The four-file protocol provides crash consistency: `meta.json` is written last with a generation counter and content hash, so a torn write is always detectable by `doctor`.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- **SSRF protection**: Blocks loopback, private ranges, and multicast addresses by default. Override per-host with `--allow-private-host`.
|
||||||
|
- **DNS rebinding mitigation**: Validates resolved IP after redirects (5 redirect limit).
|
||||||
|
- **Auth redaction**: Tokens are never printed in output or logs.
|
||||||
|
- **Streaming byte limit**: `--max-bytes` prevents OOM on oversized or malicious specs.
|
||||||
|
- **Network policy**: `--network offline` guarantees zero outbound connections.
|
||||||
|
- **External refs are opt-in**: `--resolve-external-refs` must be explicitly set with an allowlist of permitted hosts.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
Reference in New Issue
Block a user