aperture_cli/
cli.rs

1use clap::{Parser, Subcommand};
2use std::path::PathBuf;
3
4#[derive(Parser, Debug)]
5#[command(
6    author,
7    version,
8    about = "Aperture: Dynamic CLI generator for OpenAPI specifications",
9    long_about = "Aperture dynamically generates commands from OpenAPI 3.x specifications.\n\
10                  It serves as a bridge between autonomous AI agents and APIs by consuming\n\
11                  OpenAPI specs and creating a rich command-line interface with built-in\n\
12                  security, caching, and agent-friendly features.\n\n\
13                  Examples:\n  \
14                  aperture config add myapi api-spec.yaml\n  \
15                  aperture api myapi users get-user --id 123\n  \
16                  aperture config list\n\n\
17                  Agent-friendly features:\n  \
18                  aperture api myapi --describe-json    # Get capability manifest\n  \
19                  aperture --json-errors api myapi ...  # Structured error output\n  \
20                  aperture api myapi --dry-run ...      # Show request without executing"
21)]
22pub struct Cli {
23    /// Output a JSON manifest of all available commands and parameters
24    #[arg(long, global = true, help = "Output capability manifest as JSON")]
25    pub describe_json: bool,
26
27    /// Output all errors as structured JSON to stderr
28    #[arg(long, global = true, help = "Output errors in JSON format")]
29    pub json_errors: bool,
30
31    /// Show the HTTP request that would be made without executing it
32    #[arg(long, global = true, help = "Show request details without executing")]
33    pub dry_run: bool,
34
35    /// Set the Idempotency-Key header for safe retries
36    #[arg(
37        long,
38        global = true,
39        value_name = "KEY",
40        help = "Set idempotency key header"
41    )]
42    pub idempotency_key: Option<String>,
43
44    #[command(subcommand)]
45    pub command: Commands,
46}
47
48#[derive(Subcommand, Debug)]
49pub enum Commands {
50    /// Manage API specifications (add, list, remove, edit)
51    #[command(long_about = "Manage your collection of OpenAPI specifications.\n\n\
52                      Add specifications to make their operations available as commands,\n\
53                      list currently registered specs, remove unused ones, or edit\n\
54                      existing specifications in your default editor.")]
55    Config {
56        #[command(subcommand)]
57        command: ConfigCommands,
58    },
59    /// Execute API operations for a specific context
60    #[command(
61        long_about = "Execute operations from a registered API specification.\n\n\
62                      The context refers to the name you gave when adding the spec.\n\
63                      Commands are dynamically generated based on the OpenAPI specification,\n\
64                      organized by tags (e.g., 'users', 'posts', 'orders').\n\n\
65                      Examples:\n  \
66                      aperture api myapi users get-user --id 123\n  \
67                      aperture api myapi posts create-post --body '{\"title\":\"Hello\"}'\n  \
68                      aperture api myapi --help  # See available operations"
69    )]
70    Api {
71        /// Name of the API specification context
72        context: String,
73        /// Remaining arguments will be parsed dynamically based on the `OpenAPI` spec
74        #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
75        args: Vec<String>,
76    },
77}
78
79#[derive(Subcommand, Debug)]
80pub enum ConfigCommands {
81    /// Add a new API specification from a file
82    #[command(
83        long_about = "Add an OpenAPI 3.x specification to your configuration.\n\n\
84                      This validates the specification, extracts operations, and creates\n\
85                      a cached representation for fast command generation. The spec name\n\
86                      becomes the context for executing API operations.\n\n\
87                      Supported formats: YAML (.yaml, .yml)\n\
88                      Supported auth: API Key, Bearer Token\n\n\
89                      Example:\n  \
90                      aperture config add myapi ./openapi.yaml"
91    )]
92    Add {
93        /// Name to identify this API specification (used as context in 'aperture api')
94        name: String,
95        /// Path to the `OpenAPI` 3.x specification file (YAML format)
96        file: PathBuf,
97        /// Overwrite existing specification if it already exists
98        #[arg(long, help = "Replace the specification if it already exists")]
99        force: bool,
100    },
101    /// List all registered API specifications
102    #[command(
103        long_about = "Display all currently registered API specifications.\n\n\
104                      Shows the names you can use as contexts with 'aperture api'.\n\
105                      Use this to see what APIs are available for command generation."
106    )]
107    List {},
108    /// Remove an API specification from configuration
109    #[command(
110        long_about = "Remove a registered API specification and its cached data.\n\n\
111                      This removes both the original specification file and the\n\
112                      generated cache, making the API operations unavailable.\n\
113                      Use 'aperture config list' to see available specifications."
114    )]
115    Remove {
116        /// Name of the API specification to remove
117        name: String,
118    },
119    /// Edit an API specification in your default editor
120    #[command(
121        long_about = "Open an API specification in your default text editor.\n\n\
122                      Uses the $EDITOR environment variable to determine which editor\n\
123                      to use. After editing, you may need to re-add the specification\n\
124                      to update the cached representation.\n\n\
125                      Example:\n  \
126                      export EDITOR=vim\n  \
127                      aperture config edit myapi"
128    )]
129    Edit {
130        /// Name of the API specification to edit
131        name: String,
132    },
133    /// Set base URL for an API specification
134    #[command(long_about = "Set the base URL for an API specification.\n\n\
135                      This overrides the base URL from the OpenAPI spec and the\n\
136                      APERTURE_BASE_URL environment variable. You can set a general\n\
137                      override or environment-specific URLs.\n\n\
138                      Examples:\n  \
139                      aperture config set-url myapi https://api.example.com\n  \
140                      aperture config set-url myapi --env staging https://staging.example.com\n  \
141                      aperture config set-url myapi --env prod https://prod.example.com")]
142    SetUrl {
143        /// Name of the API specification
144        name: String,
145        /// The base URL to set
146        url: String,
147        /// Set URL for a specific environment (e.g., dev, staging, prod)
148        #[arg(long, value_name = "ENV", help = "Set URL for specific environment")]
149        env: Option<String>,
150    },
151    /// Get base URL configuration for an API specification
152    #[command(
153        long_about = "Display the base URL configuration for an API specification.\n\n\
154                      Shows the configured base URL override and any environment-specific\n\
155                      URLs. Also displays what URL would be used based on current\n\
156                      environment settings.\n\n\
157                      Example:\n  \
158                      aperture config get-url myapi"
159    )]
160    GetUrl {
161        /// Name of the API specification
162        name: String,
163    },
164    /// List all configured base URLs
165    #[command(
166        long_about = "Display all configured base URLs across all API specifications.\n\n\
167                      Shows general overrides and environment-specific configurations\n\
168                      for each registered API. Useful for reviewing your URL settings\n\
169                      at a glance."
170    )]
171    ListUrls {},
172}