Skip to content

Commit 4afa4ff

Browse files
vakovalskiiclaude
andcommitted
Add CLI output examples to test results, remove Drift traces
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent eec5dff commit 4afa4ff

4 files changed

Lines changed: 212 additions & 79 deletions

File tree

README.md

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,50 @@
11
## OpenAPI to CLI (ocli)
22

3-
`openapi-to-cli` (short `ocli`) is a TypeScript CLI concept that turns any HTTP API described by an OpenAPI/Swagger spec into a set of CLI commands.
3+
`openapi-to-cli` (short `ocli`) is a TypeScript CLI that turns any HTTP API described by an OpenAPI/Swagger spec into a set of CLI commands — at runtime, without code generation.
44

55
- **Input**: OpenAPI/Swagger spec (URL or file) plus API connection settings.
66
- **Output**: an executable `ocli` binary where each API operation is exposed as a dedicated subcommand.
77

8-
Unlike [openapi-to-mcp](https://github.com/EvilFreelancer/openapi-to-mcp), which starts an MCP server with tools, `ocli` provides a direct command line interface.
8+
Unlike [openapi-to-mcp](https://github.com/EvilFreelancer/openapi-to-mcp), which starts an MCP server with tools, `ocli` provides a direct command-line interface.
9+
10+
### Why convert OpenAPI spec to CLI?
11+
12+
The trend is clear: **CLI commands are cheaper and more native than MCP tools** for AI agents.
13+
14+
| Factor | MCP Tools | CLI Commands |
15+
|--------|-----------|--------------|
16+
| **Token cost** | Each tool call requires full JSON schema in context on every request | CLI commands are invoked by name with flags — minimal token overhead |
17+
| **Startup overhead** | MCP server must be running, connected via transport layer | Single process, instant execution, zero transport cost |
18+
| **Composability** | Tools are isolated in MCP server scope | CLI commands pipe, chain, and integrate with shell scripts natively |
19+
| **Agent compatibility** | Requires MCP-aware client (Claude, Cursor, etc.) | Any agent that can run shell commands — universal |
20+
| **Discoverability** | Agent must hold all tool schemas in context window | `--help` for quick lookup, `search --query` for BM25-ranked discovery |
21+
| **Multi-API** | One MCP server per API, each consuming context | Multiple profiles in one binary, switch with `ocli use <profile>` |
22+
| **Endpoint scoping** | All tools exposed at once, no per-session filtering | Per-profile `--include/--exclude-endpoints` — same API, different command sets for different roles |
23+
| **Debugging** | Opaque transport, hard to inspect | Plain HTTP requests, visible in terminal |
24+
25+
When an agent has access to 200+ API endpoints, loading all of them as MCP tools burns thousands of tokens per turn. With `ocli`, the agent calls `ocli search --query "upload files"` to discover relevant commands, then executes them directly. The context window stays clean.
26+
27+
**Bottom line**: if your agent talks to HTTP APIs, CLI is the most token-efficient and portable interface available today.
28+
29+
### Comparison with [openapi-cli-generator](https://github.com/danielgtaylor/openapi-cli-generator)
30+
31+
| Feature | ocli | openapi-cli-generator |
32+
|---------|:----:|:---------------------:|
33+
| Runtime interpretation (no codegen) |||
34+
| Zero-setup install (`npx`) |||
35+
| Multiple API profiles in one binary |||
36+
| Multiple endpoint sets per API |||
37+
| BM25 command search |||
38+
| Regex command search |||
39+
| Per-profile endpoint filtering |||
40+
| Spec caching with refresh |||
41+
| Add new API without recompile |||
42+
| Basic / Bearer auth |||
43+
| OAuth2 / Auth0 |||
44+
| Response JMESPath filtering |||
45+
| Syntax-highlighted output |||
46+
| Middleware / waiters |||
47+
| Active project || ❌ (deprecated) |
948

1049
### High level idea
1150

@@ -43,6 +82,22 @@ ocli use myapi
4382
ocli messages --limit 10
4483
```
4584

85+
### Command search
86+
87+
When the API surface is too large for `--help`, use the built-in search:
88+
89+
```bash
90+
# BM25 natural language search
91+
ocli search --query "upload files"
92+
ocli search -q "list messages" --limit 5
93+
94+
# Regex pattern matching
95+
ocli search --regex "admin.*get"
96+
ocli search -r "messages" -n 3
97+
```
98+
99+
The BM25 engine (ported from [picoclaw](https://github.com/sipeed/picoclaw)) ranks commands by relevance across name, method, path, description, and parameter names. This enables agents to discover the right endpoint without loading all command schemas into context.
100+
46101
### Installation and usage via npm and npx
47102

48103
To use `ocli` locally without installing it globally you can rely on `npx`:
@@ -97,7 +152,7 @@ api_bearer_token = MY_TOKEN
97152
openapi_spec_source = http://127.0.0.1:1111/openapi.json
98153
openapi_spec_cache = /home/user/.ocli/specs/default.json
99154
include_endpoints = get:/messages,get:/channels
100-
exclude_endpoints =
155+
exclude_endpoints =
101156

102157
[myapi]
103158
api_base_url = http://127.0.0.1:2222
@@ -106,7 +161,7 @@ api_bearer_token = MY_TOKEN
106161
openapi_spec_source = http://127.0.0.1:2222/openapi.json
107162
openapi_spec_cache = /home/user/.ocli/specs/myapi.json
108163
include_endpoints = get:/messages,get:/channels
109-
exclude_endpoints =
164+
exclude_endpoints =
110165
```
111166

112167
The local file `./.ocli/profiles.ini`, if present, fully overrides the global one when resolving profiles.
@@ -176,6 +231,8 @@ The `ocli` binary provides the following core commands:
176231
- `ocli profiles remove <profile>` - remove a profile;
177232
- `ocli use <profile>` - set the profile to use when `--profile` is not passed (writes profile name to `.ocli/current`).
178233
- `ocli commands` - list available commands generated from the current profile and its OpenAPI spec.
234+
- `ocli search --query <text>` - BM25-ranked search across commands by name, path, description.
235+
- `ocli search --regex <pattern>` - regex pattern search across commands.
179236
- `ocli --version` - print the CLI version baked at build time (derived from the latest git tag when available).
180237

181238
Help:
@@ -185,31 +242,26 @@ Help:
185242
- `ocli profiles -h|--help` - profile management help;
186243
- `ocli <tool-name> -h|--help` - description of a particular operation, list of options and their types (generated from OpenAPI).
187244

188-
### Architecture (concept)
245+
### Architecture
246+
247+
```
248+
src/
249+
├── cli.ts # Entry point, command routing, HTTP requests
250+
├── config.ts # .ocli directory resolution (local > global)
251+
├── openapi-loader.ts # OpenAPI spec download and caching
252+
├── openapi-to-commands.ts # OpenAPI → CLI command generation
253+
├── command-search.ts # BM25 + regex search over commands
254+
├── bm25.ts # BM25 ranking engine (ported from picoclaw)
255+
├── profile-store.ts # Profile persistence in INI format
256+
└── version.ts # Version constant (generated at build)
257+
```
189258

190-
The `openapi-to-cli` project mirrors parts of the `openapi-to-mcp` architecture but implements a CLI instead of an MCP server:
259+
The project mirrors parts of the `openapi-to-mcp` architecture but implements a CLI instead of an MCP server:
191260

192261
- `config` - reads profile configuration and cache paths (INI files, global and local `.ocli` lookup).
193262
- `profile-store` - works with `profiles.ini` (read, write, select profile, current profile).
194263
- `openapi-loader` - loads and caches the OpenAPI spec (URL or file) into `.ocli/specs/`.
195-
- `openapi-to-commands` - parses OpenAPI, applies include/exclude filters, generates command names and option schemas (based on `openapi-to-mcp/openapi-to-tools.ts` ideas).
264+
- `openapi-to-commands` - parses OpenAPI, applies include/exclude filters, generates command names and option schemas.
265+
- `command-search` - BM25 and regex search over generated commands for discovery on large API surfaces.
266+
- `bm25` - generic BM25 ranking engine with Robertson IDF smoothing and min-heap top-K extraction.
196267
- `cli` - entry point, argument parser, command registration, help output.
197-
198-
### Next implementation steps
199-
200-
This `openapi-to-cli` directory currently documents the concept and architecture of the future CLI project.
201-
202-
When moving to implementation, we will:
203-
204-
- add full CLI logic in `src/` (argument parsing, commands, profile handling, spec loading);
205-
- add tests for:
206-
- parsing and persisting `profiles.ini`;
207-
- caching and loading OpenAPI specs;
208-
- mapping OpenAPI operations to commands and options.
209-
210-
The project is intended to be published as an npm package so it can be invoked as:
211-
212-
```bash
213-
npx openapi-to-cli onboard ...
214-
ocli messages_get --profile myapi ...
215-
```

tests/results/box-api-yaml-results.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,43 @@
3636
## Summary
3737

3838
**13 tests | 13 passed | 0 failed | ~1s**
39+
40+
---
41+
42+
## CLI Output Examples (Box API, loaded from YAML)
43+
44+
### `ocli search --query "upload file" --limit 5`
45+
46+
```
47+
Found 5 command(s):
48+
49+
files_upload_sessions_post POST /files/upload_sessions Create upload session
50+
files_upload_sessions_id_put PUT /files/upload_sessions/{upload_session_id} Upload part of file
51+
files_upload_sessions_id_commit_post POST /files/upload_sessions/{upload_session_id}/commit Commit upload session
52+
files_content_post POST /files/content Upload a file
53+
files_id_content_post POST /files/{file_id}/content Upload a file version
54+
```
55+
56+
### `ocli search --query "create folder" --limit 5`
57+
58+
```
59+
Found 5 command(s):
60+
61+
folders_post POST /folders Create folder
62+
folders_id_get GET /folders/{folder_id} Get folder info
63+
folders_id_items GET /folders/{folder_id}/items List items in folder
64+
folders_id_copy_post POST /folders/{folder_id}/copy Copy folder
65+
folders_id_put PUT /folders/{folder_id} Update folder
66+
```
67+
68+
### `ocli search --regex "metadata" --limit 5`
69+
70+
```
71+
Found 5 command(s):
72+
73+
files_id_metadata GET /files/{file_id}/metadata List metadata on file
74+
files_id_metadata_scope_template_get GET /files/{file_id}/metadata/{scope}/{template_key} Get metadata instance on file
75+
files_id_metadata_scope_template_post POST /files/{file_id}/metadata/{scope}/{template_key} Create metadata instance on file
76+
files_id_metadata_scope_template_put PUT /files/{file_id}/metadata/{scope}/{template_key} Update metadata instance on file
77+
files_id_metadata_scope_template_delete DELETE /files/{file_id}/metadata/{scope}/{template_key} Remove metadata instance from file
78+
```

tests/results/drift-api-results.md

Lines changed: 0 additions & 53 deletions
This file was deleted.

tests/results/github-api-results.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,97 @@
3636
## Summary
3737

3838
**13 tests | 13 passed | 0 failed | ~1s**
39+
40+
---
41+
42+
## CLI Output Examples
43+
44+
### `ocli commands | wc -l`
45+
46+
```
47+
847
48+
```
49+
50+
### `ocli search --query "list repositories" --limit 5`
51+
52+
```
53+
Found 5 command(s):
54+
55+
repositories GET /repositories List public repositories
56+
installation_repositories GET /installation/repositories List repositories accessible to the app installation
57+
user_migrations_migration_id_repositories GET /user/migrations/{migration_id}/repositories List repositories for a user migration
58+
user_installations_installation_id_repositories GET /user/installations/{installation_id}/repositories List repositories accessible to the user access token
59+
orgs_org_migrations_migration_id_repositories GET /orgs/{org}/migrations/{migration_id}/repositories List repositories in an organization migration
60+
```
61+
62+
### `ocli search --query "pull request reviews" --limit 5`
63+
64+
```
65+
Found 5 command(s):
66+
67+
repos_owner_repo_pulls_pull_number_reviews_get GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews List reviews for a pull request
68+
repos_owner_repo_pulls_pull_number_reviews_post POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews Create a review for a pull request
69+
repos_owner_repo_pulls_pull_number_reviews_review_id_get GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} Get a review for a pull request
70+
repos_owner_repo_pulls_pull_number_reviews_review_id_put PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} Update a review for a pull request
71+
repos_owner_repo_pulls_pull_number_reviews_review_id_delete DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} Delete a pending review for a pull request
72+
```
73+
74+
### `ocli search --query "create issue" --limit 5`
75+
76+
```
77+
Found 5 command(s):
78+
79+
repos_owner_repo_issues_issue_number_comments_post POST /repos/{owner}/{repo}/issues/{issue_number}/comments Create an issue comment
80+
repos_owner_repo_issues_issue_number_reactions_post POST /repos/{owner}/{repo}/issues/{issue_number}/reactions Create reaction for an issue
81+
repos_owner_repo_issues_post POST /repos/{owner}/{repo}/issues Create an issue
82+
repos_owner_repo_issues_comments_comment_id_reactions_post POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions Create reaction for an issue comment
83+
repos_owner_repo_issues_issue_number_get GET /repos/{owner}/{repo}/issues/{issue_number} Get an issue
84+
```
85+
86+
### `ocli search --query "actions workflow" --limit 5`
87+
88+
```
89+
Found 5 command(s):
90+
91+
orgs_org_actions_permissions_workflow_get GET /orgs/{org}/actions/permissions/workflow Get default workflow permissions for an organization
92+
orgs_org_actions_permissions_workflow_put PUT /orgs/{org}/actions/permissions/workflow Set default workflow permissions for an organization
93+
repos_owner_repo_actions_permissions_workflow_get GET /repos/{owner}/{repo}/actions/permissions/workflow Get default workflow permissions for a repository
94+
repos_owner_repo_actions_permissions_workflow_put PUT /repos/{owner}/{repo}/actions/permissions/workflow Set default workflow permissions for a repository
95+
repos_owner_repo_actions_workflows_workflow_id_runs GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs List workflow runs for a workflow
96+
```
97+
98+
### `ocli search --regex "gist" --limit 5`
99+
100+
```
101+
Found 5 command(s):
102+
103+
gists_get GET /gists List gists for the authenticated user
104+
gists_post POST /gists Create a gist
105+
gists_public GET /gists/public List public gists
106+
gists_starred GET /gists/starred List starred gists
107+
gists_gist_id_get GET /gists/{gist_id} Get a gist
108+
```
109+
110+
### `ocli search --regex "repos.*pulls" --limit 5`
111+
112+
```
113+
Found 5 command(s):
114+
115+
repos_owner_repo_commits_commit_sha_pulls GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls List pull requests associated with a commit
116+
repos_owner_repo_pulls_get GET /repos/{owner}/{repo}/pulls List pull requests
117+
repos_owner_repo_pulls_post POST /repos/{owner}/{repo}/pulls Create a pull request
118+
repos_owner_repo_pulls_comments GET /repos/{owner}/{repo}/pulls/comments List review comments in a repository
119+
repos_owner_repo_pulls_comments_comment_id_get GET /repos/{owner}/{repo}/pulls/comments/{comment_id} Get a review comment for a pull request
120+
```
121+
122+
### `ocli repos_owner_repo_get -h`
123+
124+
```
125+
ocli repos_owner_repo_get
126+
127+
Get a repository
128+
129+
Опции:
130+
131+
-h, --help Показать помощь [булевый тип]
132+
```

0 commit comments

Comments
 (0)