Aperture is a command-line interface (CLI) that dynamically generates commands from OpenAPI 3.x specifications. It's designed to provide a secure, reliable, and introspectable "tool-use" endpoint for autonomous AI agents and automated systems.
- OpenAPI-Native: Directly consumes standard OpenAPI 3.x documents as the single source of truth
- Dynamic & Performant: Generates commands at runtime from pre-validated, cached API specifications
- Agent-First Design: Optimized for programmatic use with structured I/O, JSON output modes, and actionable errors
- Secure & Robust: Enforces strict separation of configuration from secrets using environment variables
- Spec Validation: Validates OpenAPI specs during registration with clear error messages for unsupported features
- Parameter References: Full support for OpenAPI parameter references ($ref) for DRY specifications
- Server Variables: Support for OpenAPI server URL templates with validation and defaults
- Batch Processing: Execute multiple operations concurrently with rate limiting and error handling
- Response Caching: Intelligent caching with TTL support for improved performance
- Advanced Output: Multiple output formats (JSON, YAML, table) with JQ-based filtering
- Flag-Based Syntax: Consistent --flagsyntax for all parameters (with legacy positional support)
Aperture follows a two-phase approach:
- Setup Phase (aperture config add): Parses, validates, and caches OpenAPI specifications
- Runtime Phase (aperture <context> <command>): Loads cached specs for fast command generation and execution
~/.config/aperture/
├── specs/           # Original OpenAPI specification files
├── .cache/          # Pre-processed binary cache files
└── config.toml      # Global configuration (optional)
Authentication is handled through custom x-aperture-secret extensions in OpenAPI specs that map security schemes to environment variables.
- API Key (header, query, or cookie)
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      x-aperture-secret:
        source: env
        name: API_KEY- HTTP Bearer Token
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      x-aperture-secret:
        source: env
        name: API_TOKEN- HTTP Basic Authentication
components:
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      x-aperture-secret:
        source: env
        name: BASIC_CREDENTIALS # Format: username:password (will be base64 encoded automatically)- Custom HTTP Schemes (Token, DSN, ApiKey, proprietary schemes)
components:
  securitySchemes:
    # Common alternative to Bearer
    tokenAuth:
      type: http
      scheme: Token
      x-aperture-secret:
        source: env
        name: API_TOKEN
    # Sentry-style DSN authentication
    dsnAuth:
      type: http
      scheme: DSN
      x-aperture-secret:
        source: env
        name: SENTRY_DSN
    # Any custom scheme name
    customAuth:
      type: http
      scheme: X-CompanyAuth-V2
      x-aperture-secret:
        source: env
        name: COMPANY_TOKENAll custom HTTP schemes are treated as bearer-like tokens and formatted as: Authorization: <scheme> <token>
The following authentication types require complex flows and are not supported:
- OAuth2 (all flows)
- OpenID Connect
- HTTP Negotiate (Kerberos/NTLM)
- HTTP OAuth scheme
Starting from v0.1.4, Aperture handles APIs with unsupported features gracefully:
- Non-Strict Mode (Default): APIs containing unsupported authentication schemes or content types are accepted
- Only endpoints that require unsupported features are skipped
- Endpoints with multiple authentication options (where at least one is supported) remain available
- Clear warnings show which endpoints are skipped and why
 
- Strict Mode: Use the --strictflag withaperture config addto reject specs with any unsupported features
This allows you to use most endpoints of an API even if some require unsupported authentication methods or content types:
# Default behavior - accepts spec, skips unsupported endpoints with warnings
aperture config add my-api ./openapi.yml
# Strict mode - rejects spec if any unsupported features found
aperture config add --strict my-api ./openapi.ymlStarting from v0.1.4, Aperture supports dynamic authentication configuration without modifying OpenAPI specifications. This allows you to:
- Use unmodified third-party OpenAPI specs - No need to fork and add x-aperture-secretextensions
- Easy credential management - Configure authentication through simple CLI commands
- Environment flexibility - Use different credentials per environment without spec changes
- Credential rotation - Update environment variables without editing specifications
Configure secrets with CLI commands:
# Direct configuration
aperture config set-secret myapi bearerAuth --env API_TOKEN
aperture config set-secret myapi apiKey --env MY_API_KEY
# Interactive configuration (guided setup)
aperture config set-secret myapi --interactive
# List configured secrets
aperture config list-secrets myapiPriority system:
- Config-based secrets (set via CLI commands) take highest priority
- x-aperture-secret extensions (in OpenAPI specs) used as fallback
- Clear error messages when neither is available
This feature maintains complete backward compatibility - existing x-aperture-secret extensions continue to work exactly as before, but can now be overridden by config-based settings.
Aperture fully supports OpenAPI parameter references, allowing you to define reusable parameters:
components:
  parameters:
    userId:
      name: userId
      in: path
      required: true
      schema:
        type: string
paths:
  /users/{userId}:
    get:
      parameters:
        - $ref: "#/components/parameters/userId"cargo install aperture-cligit clone https://github.com/kioku/aperture.git
cd aperture
cargo install --path .Aperture supports optional features that can be enabled during compilation:
Aperture provides JSON filtering capabilities through the --jq flag:
Basic Filtering (Default) Without any special features, Aperture supports basic field access:
# Simple field extraction
aperture api my-api get-user --id 123 --jq '.name'
aperture api my-api get-data --jq '.results.items'
# Nested field access
aperture api my-api get-user --id 123 --jq '.address.city'OpenAPI 3.1 Support
The openapi31 feature enables parsing of OpenAPI 3.1 specifications:
# Build with OpenAPI 3.1 support
cargo build --release --features openapi31Without this feature, only OpenAPI 3.0.x specifications are supported. When a 3.1 spec is detected without the feature enabled, a helpful error message will guide you to rebuild with the feature.
Advanced Filtering
The jq feature flag enables advanced JSON filtering using a pure Rust JQ implementation (jaq v2.x):
# Build with full JQ support
cargo build --release --features jqSupported without jq feature (basic filtering):
- Basic field access: .field,.nested.field
- Array index access: .items[0]
Requires jq feature (advanced filtering):
- Array operations: .[],.[0:5],.items[0].name
- Nested field extraction: .metadata.role
- Complex filters and transformations
- Standard JQ syntax support
# Register an API specification
aperture config add my-api ./openapi.yml
# Register with strict validation (rejects specs with any unsupported features)
aperture config add --strict my-api ./openapi.yml
# List available APIs
aperture config list
# Configure authentication secrets (v0.1.4)
aperture config set-secret my-api bearerAuth --env API_TOKEN
aperture config set-secret my-api --interactive  # Guided configuration
aperture config list-secrets my-api
# Execute API commands (dynamically generated from spec)
aperture api my-api users list
aperture api my-api users create --name "John Doe" --email "john@example.com"
aperture api my-api users get-user-by-id --id 123Aperture provides flexible base URL configuration for different environments:
# Set a custom base URL for an API (overrides spec and environment variables)
aperture config set-url my-api https://api.example.com
# Configure environment-specific URLs
aperture config set-url my-api --env staging https://staging.example.com
aperture config set-url my-api --env prod https://prod.example.com
# View current URL configuration
aperture config get-url my-api
# List all configured URLs across APIs
aperture config list-urls
# Use environment-specific URL
APERTURE_ENV=staging aperture api my-api users listURL Resolution Priority:
- Explicit test parameter (for testing)
- Per-API configuration (with environment support)
- APERTURE_BASE_URLenvironment variable (global override)
- OpenAPI spec server URL (default)
- Fallback URL (https://api.example.com)
Starting from v0.1.4, Aperture supports OpenAPI server URL templates with variables:
# For APIs with templated server URLs like https://{region}.api.example.com/{version}
# Provide template variables using --server-var
aperture api my-api users list --server-var region=us --server-var version=v2
# Variables with enum constraints are validated
aperture api my-api users list --server-var region=invalid  # Error if 'invalid' not in enum
# Variables with defaults can be overridden
aperture api my-api users list --server-var env=staging  # Overrides default 'production'OpenAPI Specification Example:
servers:
  - url: https://{region}.api.example.com/{version}
    variables:
      region:
        default: us
        enum: [us, eu, asia]
        description: API region
      version:
        default: v1
        description: API versionFeatures:
- Validation: Enum values are validated, invalid values are rejected
- Defaults: Variables with defaults are optional, others are required
- URL Encoding: Variable values are automatically URL-encoded
- Error Messages: Clear guidance when variables are missing or invalid
# Get JSON description of all available commands
aperture api my-api --describe-json
# Output errors as structured JSON
aperture api my-api --json-errors users list
# Preview request without execution
aperture api my-api --dry-run users create --name "Test"
# Add idempotency key for safe retries
aperture api my-api --idempotency-key "unique-key" users create --name "Test"
# Get specific user with flag-based syntax
aperture api my-api --dry-run users get-user-by-id --id 123Aperture supports multiple output formats and data filtering:
# Output as formatted table
aperture api my-api users list --format table
# Output as YAML
aperture api my-api users list --format yaml
# Extract specific fields with JQ filtering (basic - works without feature)
aperture api my-api users get-user --id 123 --jq '.name'
aperture api my-api users get-user --id 123 --jq '.email'
# Nested field access (works without feature)
aperture api my-api get-data --jq '.data.items[0].name'
# Advanced JQ transformations (requires --features jq)
aperture api my-api get-data --jq '.items[0].name'
aperture api my-api users list --jq '.[].email'
# JQ filtering with --describe-json
aperture api my-api --describe-json --jq '.api.info.title'
aperture api my-api --describe-json --jq '.commands.users'For high-volume automation, Aperture supports batch processing with concurrency controls:
# Execute multiple operations from a batch file
aperture --batch-file operations.json --batch-concurrency 10
# Rate limiting for batch operations
aperture --batch-file operations.json --batch-rate-limit 50
# Analyze batch results with JQ filtering (requires --json-errors)
# Basic field access (works without jq feature):
aperture api my-api --batch-file operations.json --json-errors --jq '.batch_execution_summary.total_operations'
aperture api my-api --batch-file operations.json --json-errors --jq '.batch_execution_summary.failed_operations'
# Advanced filters (require --features jq):
aperture api my-api --batch-file operations.json --json-errors --jq '.batch_execution_summary.successful_operations'Example batch file (JSON):
{
  "operations": [
    {
      "id": "get-user-1",
      "args": ["users", "get-user-by-id", "--id", "123"]
    },
    {
      "id": "get-user-2",
      "args": ["users", "get-user-by-id", "--id", "456"]
    }
  ]
}Improve performance with intelligent response caching:
# Enable caching with default TTL (300 seconds)
aperture api my-api --cache users list
# Custom cache TTL
aperture api my-api --cache --cache-ttl 600 users list
# Disable caching
aperture api my-api --no-cache users list
# Manage cache
aperture config cache-stats my-api
aperture config clear-cache my-apiAperture now uses flag-based syntax by default for all parameters:
# Default flag-based syntax (recommended)
aperture api my-api users get-user-by-id --id 123
# Legacy positional syntax (backwards compatibility)
aperture api my-api --positional-args users get-user-by-id 123Aperture follows standard CLI conventions for exit codes:
- 0: Success - all operations completed successfully
- 1: Failure - one or more operations failed, including:
- API request failures (4xx, 5xx errors)
- Network connection errors
- Authentication failures
- Batch operations with any failed requests
 
For batch operations, Aperture exits with code 1 if ANY operation fails, making it easy to detect failures in CI/CD pipelines:
# Check batch success/failure
aperture --batch-file ops.json --json-errors
if [ $? -eq 0 ]; then
    echo "All operations succeeded"
else
    echo "Some operations failed"
fi
# Continue despite failures
aperture --batch-file ops.json --json-errors || trueThis project is built with Rust and follows Test-Driven Development practices.
- Rust (latest stable version)
- Cargo
# Build the project
cargo build
# Run all tests
cargo test
# Run tests for specific module
cargo test config_manager
# Format code
cargo fmt
# Check formatting and linting
cargo fmt --check
cargo clippy -- -D warnings
# Run with debug output
RUST_LOG=debug cargo run -- config listThe project uses comprehensive testing strategies:
- Unit Tests: Fast, isolated tests without external dependencies
- Integration Tests: End-to-end CLI testing using assert_cmdandwiremock
- HTTP Mocking: API interaction testing using wiremock
# Run unit tests only (fastest)
cargo test --no-default-features
# Run all tests including integration
cargo test --features integration
# Run specific test file
cargo test --features integration --test integration_tests
# Using cargo-nextest (recommended for better parallelization)
cargo install cargo-nextest --locked
cargo nextest run --profile fast        # Fast local development
cargo nextest run --profile default     # Standard configuration
cargo nextest run --profile ci          # CI optimized
# Or use the provided script
./scripts/test-fast.shSee ADR-007 for test performance optimizations and metrics.
Experimental: This project is in an experimental phase. While core functionality is implemented and tested, the API and features may change as we iterate based on usage and feedback. See docs/architecture.md for the complete software design specification.
Licensed under the MIT License. See LICENSE for details.