specli 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,464 +1,355 @@
1
1
  # specli
2
2
 
3
- specli turns an OpenAPI spec into a non-interactive, “curl replacement” CLI.
3
+ Turn any OpenAPI spec into a CLI.
4
4
 
5
- It has two modes:
6
-
7
- - **exec**: run commands dynamically from a spec URL/path.
8
- - **compile**: bundle the spec into a standalone executable.
9
-
10
- The guiding constraints:
5
+ ## Install
11
6
 
12
- - Bun-first (no Node runtime needed).
13
- - Suitable for automation/agents (stable commands, machine output via `--json`).
14
- - Best-effort validation of inputs against the OpenAPI schema.
7
+ ```bash
8
+ npm install -g specli
9
+ ```
15
10
 
16
- ## Status / What Works Today
11
+ Or use directly with npx/bunx:
17
12
 
18
- It works well for a large chunk of “typical” OpenAPI 3.x REST specs:
13
+ ```bash
14
+ npx specli exec ./openapi.json __schema
15
+ bunx specli exec ./openapi.json __schema
16
+ ```
19
17
 
20
- - Multiple servers + server variables.
21
- - Path/query/header/cookie parameters.
22
- - Request bodies via `--data` / `--file`.
23
- - JSON request body parsing + schema validation.
24
- - Body field flags matching OpenAPI schema properties (including nested objects with dot notation).
25
- - Auth injection for common schemes (bearer/basic/apiKey).
26
- - A deterministic `__schema` output for introspection.
18
+ ## Commands
27
19
 
28
- It is not “universal OpenAPI support” yet. See “Limitations” for important gaps.
20
+ ### exec
29
21
 
30
- ## Install
22
+ Run commands dynamically from any OpenAPI spec URL or file path. Works with both Node.js and Bun.
31
23
 
32
24
  ```bash
33
- bun install
25
+ specli exec <spec> <resource> <action> [args...] [options]
34
26
  ```
35
27
 
36
- ## Quickstart
37
-
38
- Inspect what commands will be generated:
28
+ **Examples:**
39
29
 
40
30
  ```bash
41
- bunx specli exec ./fixtures/openapi.json __schema
42
- ```
31
+ # Inspect available commands
32
+ specli exec ./openapi.json __schema
43
33
 
44
- Machine-readable schema output:
34
+ # Machine-readable schema output
35
+ specli exec ./openapi.json __schema --json
45
36
 
46
- ```bash
47
- bunx specli exec ./fixtures/openapi.json __schema --json
48
- ```
37
+ # Minimal schema (best for large specs)
38
+ specli exec ./openapi.json __schema --json --min
49
39
 
50
- Minimal schema output (best for large specs):
40
+ # Run an operation
41
+ specli exec ./openapi.json users list
51
42
 
52
- ```bash
53
- bunx specli exec ./fixtures/openapi.json __schema --json --min
54
- ```
43
+ # Run with path parameters
44
+ specli exec ./openapi.json users get abc123
55
45
 
56
- Run a generated operation:
46
+ # Preview the curl command without executing
47
+ specli exec ./openapi.json users list --curl
57
48
 
58
- ```bash
59
- bunx specli exec ./fixtures/openapi.json contacts list --curl
49
+ # Dry run (show request details without executing)
50
+ specli exec ./openapi.json users list --dry-run
60
51
  ```
61
52
 
62
- ## Build a Standalone Executable
53
+ ### compile
63
54
 
64
- Use the `compile` command to create a standalone binary with the spec embedded:
55
+ Bundle an OpenAPI spec into a standalone executable. **Requires Bun.**
65
56
 
66
57
  ```bash
67
- # compile with auto-derived name (from spec title)
68
- bunx specli compile ./path/to/openapi.yaml
69
- # → ./dist/my-api (derived from info.title)
58
+ specli compile <spec> [options]
59
+ ```
70
60
 
71
- # compile with explicit name
72
- bunx specli compile ./path/to/openapi.yaml --name myapi
73
- # → ./dist/myapi
61
+ **Options:**
74
62
 
75
- # cross-compile (example: linux x64)
76
- bunx specli compile https://api.vercel.com/copper/_openapi.json --target bun-linux-x64 --outfile ./dist/copper-linux
63
+ | Option | Description |
64
+ |--------|-------------|
65
+ | `--name <name>` | Binary name (default: derived from spec title) |
66
+ | `--outfile <path>` | Output path (default: `./dist/<name>`) |
67
+ | `--target <target>` | Cross-compile target (e.g. `bun-linux-x64`) |
68
+ | `--minify` | Enable minification |
69
+ | `--bytecode` | Enable bytecode compilation |
70
+ | `--no-dotenv` | Disable .env autoload |
71
+ | `--no-bunfig` | Disable bunfig.toml autoload |
72
+ | `--server <url>` | Bake in a default server URL |
73
+ | `--server-var <k=v>` | Bake in server variables (repeatable) |
74
+ | `--auth <scheme>` | Bake in default auth scheme |
77
75
 
78
- # disable runtime config loading for deterministic behavior
79
- bunx specli compile ./path/to/openapi.yaml --no-dotenv --no-bunfig
76
+ **Examples:**
80
77
 
81
- # bake in defaults (these become default flags; runtime flags override)
82
- bunx specli compile https://api.vercel.com/copper/_openapi.json \
83
- --name copper \
84
- --server https://api.vercel.com \
85
- --auth VercelOidc
78
+ ```bash
79
+ # Compile with auto-derived name
80
+ specli compile ./openapi.yaml
81
+ # Creates: ./dist/my-api
82
+
83
+ # Compile with explicit name
84
+ specli compile ./openapi.yaml --name myapi
85
+ # Creates: ./dist/myapi
86
+
87
+ # Cross-compile for Linux
88
+ specli compile ./openapi.json --target bun-linux-x64 --outfile ./dist/myapi-linux
89
+
90
+ # Bake in defaults
91
+ specli compile https://api.example.com/openapi.json \
92
+ --name myapi \
93
+ --server https://api.example.com \
94
+ --auth BearerAuth
86
95
  ```
87
96
 
88
- The compiled binary is a root CLI - no `specli` prefix needed:
97
+ The compiled binary works standalone:
89
98
 
90
99
  ```bash
91
- ./dist/copper contacts list
92
- ./dist/copper users get abc123 --json
100
+ ./dist/myapi users list
101
+ ./dist/myapi users get abc123 --json
93
102
  ```
94
103
 
95
- Notes:
96
-
97
- - The spec is embedded at compile-time using a Bun macro.
98
- - If `--name` is not provided, it is derived from the OpenAPI `info.title` or URL hostname.
99
- - Runtime flags (e.g., `--server`) override baked-in defaults.
100
-
101
104
  ## CLI Shape
102
105
 
103
106
  specli generates commands of the form:
104
107
 
105
108
  ```
106
- specli <resource> <action> [...positionals] [options]
109
+ <resource> <action> [...positionals] [options]
107
110
  ```
108
111
 
109
- - `resource` comes from `tags[0]`, `operationId` prefix, or the first path segment (heuristics).
110
- - `action` is inferred from HTTP method + “has id in path”, or from `operationId` suffix.
111
- - Name collisions are disambiguated deterministically by suffixing the action name.
112
+ - **resource**: Derived from `tags[0]`, `operationId` prefix, or first path segment
113
+ - **action**: Inferred from HTTP method or `operationId` suffix
114
+ - Name collisions are disambiguated automatically
112
115
 
113
- Use `__schema` to see the planned mapping for your spec.
116
+ Use `__schema` to see the command mapping for any spec.
114
117
 
115
118
  ## Global Options
116
119
 
117
- Available on the root command:
118
-
119
- - `--spec <urlOrPath>`: OpenAPI URL or file path (only needed for compiled binaries to override embedded spec)
120
- - `--server <url>`: override server/base URL
121
- - `--server-var <name=value>`: server URL template variable (repeatable)
122
- - `--profile <name>`: profile name (config under `~/.config/specli`)
123
-
124
- Auth selection + credentials:
125
-
126
- - `--auth <scheme>`: pick an auth scheme by key
127
- - `--bearer-token <token>`: set `Authorization: Bearer <token>`
128
- - `--oauth-token <token>`: alias of `--bearer-token`
129
- - `--username <username>` / `--password <password>`: basic auth
130
- - `--api-key <key>`: value for apiKey auth
131
-
132
- Output mode:
133
-
134
- - `--json`: machine-readable output (never prints stack traces)
135
-
136
- ## Per-Operation Common Options
137
-
138
- Every generated operation command includes:
139
-
140
- - `--header <header>` (repeatable): extra headers; accepts `Name: Value` or `Name=Value`
141
- - `--accept <type>`: override `Accept` header
142
- - `--timeout <ms>`: request timeout in milliseconds
143
- - `--dry-run`: print the request that would be sent (no network call)
144
- - `--curl`: print an equivalent `curl` command (no network call)
145
-
146
- For operations with `requestBody`, it also includes:
147
-
148
- - `--data <data>`: inline request body
149
- - `--file <path>`: read request body from a file
150
- - `--content-type <type>`: override `Content-Type` (defaults from OpenAPI)
151
-
152
- ## Parameter Mapping
120
+ | Option | Description |
121
+ |--------|-------------|
122
+ | `--server <url>` | Override server/base URL |
123
+ | `--server-var <name=value>` | Server URL template variable (repeatable) |
124
+ | `--profile <name>` | Profile name |
125
+ | `--auth <scheme>` | Select auth scheme by key |
126
+ | `--bearer-token <token>` | Set `Authorization: Bearer <token>` |
127
+ | `--oauth-token <token>` | Alias for `--bearer-token` |
128
+ | `--username <user>` | Basic auth username |
129
+ | `--password <pass>` | Basic auth password |
130
+ | `--api-key <key>` | API key value |
131
+ | `--json` | Machine-readable output |
132
+
133
+ ## Per-Operation Options
134
+
135
+ Every operation command includes:
136
+
137
+ | Option | Description |
138
+ |--------|-------------|
139
+ | `--header <header>` | Extra headers (repeatable, `Name: Value` or `Name=Value`) |
140
+ | `--accept <type>` | Override `Accept` header |
141
+ | `--timeout <ms>` | Request timeout in milliseconds |
142
+ | `--dry-run` | Print request details without sending |
143
+ | `--curl` | Print equivalent curl command without sending |
144
+
145
+ For operations with request bodies:
146
+
147
+ | Option | Description |
148
+ |--------|-------------|
149
+ | `--data <data>` | Inline request body |
150
+ | `--file <path>` | Read request body from file |
151
+ | `--content-type <type>` | Override `Content-Type` |
152
+
153
+ ## Parameters
153
154
 
154
155
  ### Path Parameters
155
156
 
156
- OpenAPI parameters where `in: path` become positional arguments.
157
-
158
- - Order is derived from the path template: `/users/{id}/keys/{key_id}` becomes `<id> <key-id>`.
159
- - Values are URL-encoded when applied to the path.
160
-
161
- ### Query / Header / Cookie Parameters
162
-
163
- OpenAPI parameters where `in: query|header|cookie` become flags.
164
-
165
- Flag name rules:
166
-
167
- - `--${kebabCase(parameter.name)}`
168
- - Examples:
169
- - `limit` -> `--limit`
170
- - `X-Request-Id` -> `--x-request-id`
157
+ Path parameters become positional arguments in order:
171
158
 
172
- Required flags:
159
+ ```
160
+ /users/{id}/keys/{key_id} → <id> <key-id>
161
+ ```
173
162
 
174
- - If the spec says `required: true`, the CLI flag is marked required (Commander enforces this).
163
+ ### Query/Header/Cookie Parameters
175
164
 
176
- Type coercion:
165
+ These become kebab-case flags:
177
166
 
178
- - `string` -> string
179
- - `integer` -> `parseInt`
180
- - `number` -> `Number(...)`
181
- - `boolean` -> flag presence (no value)
182
- - `object` -> JSON object literal string, parsed via `JSON.parse`
183
- - `array` -> see below
167
+ ```
168
+ limit → --limit
169
+ X-Request-Id --x-request-id
170
+ ```
184
171
 
185
- ### Arrays (Improved UX)
172
+ Required parameters are enforced by the CLI.
186
173
 
187
- Array parameters are treated as repeatable flags and appended to the query string.
174
+ ### Arrays
188
175
 
189
- All of these become `?tag=a&tag=b`:
176
+ Array parameters are repeatable:
190
177
 
191
178
  ```bash
179
+ # All produce ?tag=a&tag=b
192
180
  specli ... --tag a --tag b
193
181
  specli ... --tag a,b
194
182
  specli ... --tag '["a","b"]'
195
183
  ```
196
184
 
197
- Implementation notes:
198
-
199
- - The query string is built with repeated keys (`URLSearchParams.append`).
200
- - Array item types are derived from `schema.items.type` when present (e.g. integer arrays validate and coerce correctly).
201
-
202
185
  ## Request Bodies
203
186
 
204
187
  ### Body Field Flags
205
188
 
206
- When an operation has a `requestBody` and the preferred schema is a JSON object, specli generates convenience flags that match the property names:
207
-
208
- - For `string|number|integer`: `--<prop> <value>`
209
- - For `boolean`: `--<prop>` (presence sets it to `true`)
210
- - For nested objects: `--<parent>.<child> <value>` (dot notation)
211
-
212
- Example (from `fixtures/openapi-body.json`):
189
+ For JSON request bodies, specli generates convenience flags matching schema properties:
213
190
 
214
191
  ```bash
215
- bunx specli exec ./fixtures/openapi-body.json contacts create --name "Ada" --curl
192
+ specli exec ./openapi.json contacts create --name "Ada" --email "ada@example.com"
216
193
  ```
217
194
 
218
- Produces a JSON body:
195
+ Produces:
219
196
 
220
197
  ```json
221
- {"name":"Ada"}
198
+ {"name":"Ada","email":"ada@example.com"}
222
199
  ```
223
200
 
224
- #### Nested Objects
225
-
226
- Nested object properties use dot notation. For a schema like:
227
-
228
- ```json
229
- {
230
- "type": "object",
231
- "properties": {
232
- "name": { "type": "string" },
233
- "address": {
234
- "type": "object",
235
- "properties": {
236
- "street": { "type": "string" },
237
- "city": { "type": "string" }
238
- }
239
- }
240
- }
241
- }
242
- ```
201
+ ### Nested Objects
243
202
 
244
- You can use:
203
+ Use dot notation for nested properties:
245
204
 
246
205
  ```bash
247
- mycli contacts create --name "Ada" --address.street "123 Main St" --address.city "NYC"
206
+ mycli contacts create --name "Ada" --address.city "NYC" --address.zip "10001"
248
207
  ```
249
208
 
250
- Which produces:
209
+ Produces:
251
210
 
252
211
  ```json
253
- {"name":"Ada","address":{"street":"123 Main St","city":"NYC"}}
212
+ {"name":"Ada","address":{"city":"NYC","zip":"10001"}}
254
213
  ```
255
214
 
256
- Notes / edge cases:
257
-
258
- - Body field flags are only supported for JSON bodies.
259
- - Required fields in the schema are checked with friendly error messages:
260
- - `Missing required body field 'name'. Provide --name.`
261
- - If a body field flag would conflict with an operation parameter flag or `--curl`, the operation parameter takes precedence.
262
- - Numeric coercion uses `Number(...)` / `parseInt(...)`.
263
-
264
215
  ## Servers
265
216
 
266
- specli resolves the request base URL in this order:
217
+ Server URL resolution order:
267
218
 
268
- 1. `--server <url>`
269
- 2. profile `server` (if `--profile` is set and the profile has a server)
270
- 3. the first `servers[0].url` in the OpenAPI spec
219
+ 1. `--server <url>` flag
220
+ 2. Profile `server` setting
221
+ 3. First `servers[0].url` in the spec
271
222
 
272
- If the chosen server URL has template variables (e.g. `https://{region}.api.example.com`):
223
+ For templated URLs (e.g. `https://{region}.api.example.com`):
273
224
 
274
- - Provide `--server-var region=us-east-1` (repeatable)
275
- - If the spec defines a default for that variable, it is used automatically
225
+ ```bash
226
+ specli ... --server-var region=us-east-1
227
+ ```
276
228
 
277
229
  ## Authentication
278
230
 
279
- ### Supported Scheme Kinds
280
-
281
- From `components.securitySchemes`, specli recognizes:
282
-
283
- - HTTP bearer (`type: http`, `scheme: bearer`)
284
- - HTTP basic (`type: http`, `scheme: basic`)
285
- - API key (`type: apiKey`, `in: header|query|cookie`)
286
- - OAuth2 (`type: oauth2`) (treated as bearer token injection)
287
- - OpenID Connect (`type: openIdConnect`) (treated as bearer token injection)
231
+ ### Supported Schemes
288
232
 
289
- ### Selecting an Auth Scheme
233
+ - HTTP Bearer (`type: http`, `scheme: bearer`)
234
+ - HTTP Basic (`type: http`, `scheme: basic`)
235
+ - API Key (`type: apiKey`, `in: header|query|cookie`)
236
+ - OAuth2 (`type: oauth2`) - treated as bearer token
237
+ - OpenID Connect (`type: openIdConnect`) - treated as bearer token
290
238
 
291
- Scheme selection happens in this order:
239
+ ### Scheme Selection
292
240
 
293
- 1. `--auth <scheme>` (explicit)
294
- 2. profile `authScheme` (only if that key exists in the current spec)
295
- 3. if the operation requires exactly one scheme, it is chosen
296
- 4. if the spec defines exactly one scheme total, it is chosen
297
-
298
- This “only if present in current spec” behavior prevents accidental auth leakage between different specs.
241
+ 1. `--auth <scheme>` flag (explicit)
242
+ 2. Profile `authScheme` setting
243
+ 3. If operation requires exactly one scheme, use it
244
+ 4. If spec defines exactly one scheme, use it
299
245
 
300
246
  ### Providing Credentials
301
247
 
302
- Bearer-like schemes (`http-bearer`, `oauth2`, `openIdConnect`):
303
-
304
- - `--bearer-token <token>` or `--oauth-token <token>`
305
- - or a profile token stored via `specli auth token ...`
306
-
307
- Basic auth:
308
-
309
- - `--username <username>` and `--password <password>`
310
-
311
- API key:
312
-
313
- - `--api-key <key>` (injected into the header/query/cookie location declared by the scheme)
314
-
315
- ## Profiles (Non-Interactive)
316
-
317
- Profiles are for automation.
318
-
319
- Config file:
248
+ ```bash
249
+ # Bearer/OAuth2/OIDC
250
+ specli ... --bearer-token <token>
320
251
 
321
- - Read preference: `~/.config/specli/profiles.json`, else `~/.config/specli/profiles.yaml` if present
322
- - Writes always go to: `~/.config/specli/profiles.json`
252
+ # Basic auth
253
+ specli ... --username <user> --password <pass>
323
254
 
324
- Secrets:
255
+ # API key
256
+ specli ... --api-key <key>
257
+ ```
325
258
 
326
- - Tokens are stored in Bun’s secrets store (`bun.secrets`) under a spec-scoped service name.
259
+ ## Profiles
327
260
 
328
- Commands:
261
+ Store configuration for automation:
329
262
 
330
263
  ```bash
264
+ # List profiles
331
265
  specli profile list
266
+
267
+ # Create/update profile
332
268
  specli profile set --name dev --server https://api.example.com --auth bearerAuth --default
269
+
270
+ # Switch default profile
333
271
  specli profile use --name dev
272
+
273
+ # Delete profile
334
274
  specli profile rm --name dev
335
275
 
276
+ # Manage tokens
336
277
  specli auth token --name dev --set "..."
337
278
  specli auth token --name dev --get
338
279
  specli auth token --name dev --delete
339
280
  ```
340
281
 
341
- ## Output Behavior
342
-
343
- ### Default (Human + Agent Readable)
282
+ Config location: `~/.config/specli/profiles.json`
344
283
 
345
- - On success:
346
- - if response `content-type` includes `json`, prints pretty JSON
347
- - otherwise prints raw text
348
- - On non-2xx HTTP:
349
- - prints `HTTP <status>` and response body
350
- - exits with code 1
351
- - On CLI/validation errors:
352
- - prints `error: <message>`
353
- - exits with code 1
284
+ ## Output Modes
354
285
 
355
- ### `--json` (Machine Readable)
286
+ ### Default (Human Readable)
356
287
 
357
- - On success:
358
- - if response is JSON, prints the parsed JSON
359
- - otherwise prints the raw string
360
- - With `--status` and/or `--headers`, wraps output:
361
-
362
- ```json
363
- { "status": 200, "headers": { "content-type": "..." }, "body": ... }
364
- ```
288
+ - Success: Pretty JSON for JSON responses, raw text otherwise
289
+ - HTTP errors: `HTTP <status>` + response body, exit code 1
290
+ - CLI errors: `error: <message>`, exit code 1
365
291
 
366
- - On non-2xx HTTP:
292
+ ### --json (Machine Readable)
367
293
 
368
294
  ```json
369
- { "status": 404, "body": ..., "headers": { ... } }
370
- ```
295
+ // Success
296
+ {"status":200,"body":{...}}
371
297
 
372
- - On CLI/validation errors:
298
+ // HTTP error
299
+ {"status":404,"body":{...}}
373
300
 
374
- ```json
375
- { "error": "..." }
301
+ // CLI error
302
+ {"error":"..."}
376
303
  ```
377
304
 
378
- ### `--curl`
379
-
380
- Prints an equivalent curl invocation without sending the request.
381
-
382
- ### `--dry-run`
383
-
384
- Prints the method, URL, headers, and body that would be sent without sending the request.
385
-
386
- ## `__schema`
387
-
388
- `specli __schema` reports:
389
-
390
- - OpenAPI title/version
391
- - spec source + computed spec id + fingerprint
392
- - servers/auth schemes counts
393
- - list of normalized operations
394
- - planned command mapping
395
-
396
- Flags:
397
-
398
- - `--json`: JSON output
399
- - `--pretty`: pretty JSON
400
- - `--min`: minimal schema payload (commands + metadata only)
401
-
402
- ## Recommended Public Specs to Test
403
-
404
- A good “real world” smoke test matrix includes:
305
+ ### --curl
405
306
 
406
- 1. Vercel API (OpenAPI 3.x)
407
- - URL: `https://api.vercel.com/copper/_openapi.json`
408
- - Focus: real-world parameter naming collisions (e.g. `accept`), large-ish spec
307
+ Prints equivalent curl command without sending the request.
409
308
 
410
- 2. GitHub REST API (OpenAPI 3.1, very large)
411
- - URL (huge): `https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.json`
412
- - Focus: size, OAS 3.1, many endpoints, varied parameter shapes
309
+ ### --dry-run
413
310
 
414
- 3. DigitalOcean API (OpenAPI 3.0)
415
- - URL: `https://raw.githubusercontent.com/digitalocean/openapi/main/specification/DigitalOcean-public.v2.yaml`
416
- - Focus: big spec + deref cycles, request bodies, auth schemes
311
+ Prints method, URL, headers, and body without sending.
417
312
 
418
- 4. Stripe API (OpenAPI 3.x, very complex schemas)
419
- - URL: `https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml`
420
- - Focus: very heavy schema usage (`anyOf`, large components)
313
+ ## AI SDK Integration
421
314
 
422
- Smoke harness:
315
+ specli exports an AI SDK tool for use with LLM agents:
423
316
 
424
- - Run the built-in smoke script:
317
+ ```typescript
318
+ import { specli } from "specli/ai/tools";
319
+ import { generateText } from "ai";
425
320
 
426
- ```bash
427
- bun run smoke:specs
428
- ```
429
-
430
- Or run ad-hoc smoke tests:
431
-
432
- ```bash
433
- bunx specli exec <URL> __schema --json --min > /dev/null
434
- bunx specli exec <URL> <some-resource> <some-action> --curl
321
+ const result = await generateText({
322
+ model: yourModel,
323
+ tools: {
324
+ api: specli({
325
+ spec: "https://api.example.com/openapi.json",
326
+ bearerToken: process.env.API_TOKEN,
327
+ }),
328
+ },
329
+ prompt: "List all users",
330
+ });
435
331
  ```
436
332
 
437
- Note: Kubernetes publishes a Swagger 2.0 document (`swagger.json`) which is not OpenAPI 3.x. specli currently expects `openapi: "3.x"` and will reject Swagger 2.0 specs.
438
-
439
- ## Limitations (Important)
333
+ The tool supports three commands:
334
+ - `list` - Show available resources and actions
335
+ - `help` - Get details about a specific action
336
+ - `exec` - Execute an API call
440
337
 
441
- specli is intentionally v1-simple; common gaps for real-world specs:
338
+ ## Limitations
442
339
 
443
- - OpenAPI 3.x only (Swagger 2.0 not supported).
444
- - Parameter serialization is simplified:
445
- - arrays are always encoded as repeated keys (`?tag=a&tag=b`)
446
- - does not implement OpenAPI `style` / `explode` / deepObject / etc.
447
- - Array item types are not tracked yet (arrays treated as string arrays for coercion).
448
- - Request body convenience flags only support “simple object with scalar properties”.
449
- - Multipart, binary uploads, and file/form modeling are not implemented.
450
- - `Content-Type`/`Accept` negotiation is basic (string includes checks for `json`).
451
- - OAuth2 flows are not implemented (token acquisition is out of scope); oauth2 is treated as bearer token injection.
340
+ - OpenAPI 3.x only (Swagger 2.0 not supported)
341
+ - Array serialization uses repeated keys only (`?tag=a&tag=b`)
342
+ - OpenAPI `style`/`explode`/deepObject not implemented
343
+ - Body field flags only support JSON with scalar/nested object properties
344
+ - Multipart and binary uploads not implemented
345
+ - OAuth2 token acquisition not implemented (use `--bearer-token` with pre-acquired tokens)
452
346
 
453
347
  ## Development
454
348
 
455
- Scripts:
456
-
457
- - `bun run lint` (Biome CI)
458
- - `bun run typecheck` (tsgo)
459
- - `bun test`
460
-
461
- Repo entry points:
462
-
463
- - `cli.ts`: main CLI entry with `exec` and `compile` subcommands
464
- - `src/compiled.ts`: entry point for compiled binaries (embedded spec via Bun macro)
349
+ ```bash
350
+ bun install
351
+ bun run build
352
+ bun test
353
+ bun run lint
354
+ bun run typecheck
355
+ ```
package/bin/cli.sh CHANGED
@@ -1,7 +1,17 @@
1
1
  #!/usr/bin/env sh
2
2
  set -eu
3
3
 
4
- SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
4
+ # Resolve symlinks to find the actual script location
5
+ SCRIPT="$0"
6
+ while [ -L "$SCRIPT" ]; do
7
+ SCRIPT_DIR=$(cd -P "$(dirname "$SCRIPT")" && pwd)
8
+ SCRIPT=$(readlink "$SCRIPT")
9
+ case "$SCRIPT" in
10
+ /*) ;;
11
+ *) SCRIPT="$SCRIPT_DIR/$SCRIPT" ;;
12
+ esac
13
+ done
14
+ SCRIPT_DIR=$(cd -P "$(dirname "$SCRIPT")" && pwd)
5
15
  CLI_JS="$SCRIPT_DIR/../dist/cli.js"
6
16
 
7
17
  is_compile=0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specli",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "type": "module",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -15,7 +15,8 @@
15
15
  },
16
16
  "files": [
17
17
  "bin",
18
- "dist"
18
+ "dist",
19
+ "README.md"
19
20
  ],
20
21
  "scripts": {
21
22
  "build": "tsc",
@@ -44,5 +45,9 @@
44
45
  "peerDependencies": {
45
46
  "ai": "^6.0.0",
46
47
  "zod": "^4.0.0"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/AndrewBarba/specli.git"
47
52
  }
48
53
  }
package/dist/weather DELETED
Binary file