Skip to content

Generate API commands from the OpenAPI spec - #29

Closed
dennis-chen-vanta wants to merge 4 commits into
dennis-chen-vanta/cli-command-structurefrom
dennis-chen-vanta/command-codegen
Closed

dennis-chen-vanta wants to merge 4 commits into
dennis-chen-vanta/cli-command-structurefrom
dennis-chen-vanta/command-codegen

Conversation

@dennis-chen-vanta

@dennis-chen-vanta dennis-chen-vanta commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #31.

Summary

Adds the generator for the API commands in src/commands/, so they're regenerated from api-spec.json instead of edited by hand.

scripts/codegen/ derives every command using the conventions in AGENTS.md, one module per stage:

Module Does
main.ts Runs the stages, writes the files, formats them with oxfmt
spec.ts Reads each API operation from the spec
naming.ts Places it in a group and names it (vendors list-findings)
options.ts Turns its parameters and body into flags
help.ts Describes the command, then applies help overrides
groups.ts Collects commands into groups
render.ts Renders one file per group, plus index.ts
words.ts Word helpers (pluralize, indefinite, change-case)
config.ts What the rules can't derive: top-level order, display names, action verbs, add/remove operations, 2 name overrides, and help text overrides
  • pnpm generate:commands regenerates src/commands/.
  • CI fails if the committed commands differ from the generator's output.
  • AGENTS.md says the commands are generated and where exceptions go.
  • The generator fails on duplicate command names and on help overrides that are stale or repeat the default.

Command changes

  • Each generated file gets a // Code generated by \pnpm generate:commands`. DO NOT EDIT.` header. The generator uses it to remove files for groups that no longer exist.
  • trust-centers download-resource-media passes parseAs: "blob", as fix csv file downloads #30 did for documents download-file-media. The generator adds it to every download, which keeps fix csv file downloads #30's fix when the files are regenerated.

No other lines in src/commands/ change, and --help for all 276 commands is identical to main.

Test plan

  • pnpm generate:commands leaves src/commands/ unchanged; pnpm format:check, pnpm typecheck, and pnpm test (21/21) pass.
  • Built main and this branch and compared --help for every command: identical.
  • End-to-end against the real API with the built binary: pending.

🤖 Generated with Claude Code

@semgrep2-openvanta

Copy link
Copy Markdown

Semgrep found 6 detect-non-literal-regexp findings:

🟡 Medium severity issue identified in your code:

RegExp() called with a word function argument, this might allow an attacker to cause a Regular Expression Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is recommended to use hardcoded regexes instead. If your regex is run on user-controlled input, consider performing input validation or use a regex checking/sanitization library such as https://www.npmjs.com/package/recheck to verify that the regex does not appear vulnerable to ReDoS.

View Dataflow Graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>scripts/codegen/generate-commands.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/OpenVanta/cli/blob/17b4866451a6c346bce42c8d5d32f49600520186/scripts/codegen/generate-commands.ts#L141 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 141] word</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/OpenVanta/cli/blob/17b4866451a6c346bce42c8d5d32f49600520186/scripts/codegen/generate-commands.ts#L141 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 141] word</a>"]

            v3["<a href=https://github.com/OpenVanta/cli/blob/17b4866451a6c346bce42c8d5d32f49600520186/scripts/codegen/generate-commands.ts#L152 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 152] singularize</a>"]

            v4["<a href=https://github.com/OpenVanta/cli/blob/17b4866451a6c346bce42c8d5d32f49600520186/scripts/codegen/generate-commands.ts#L152 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 152] words</a>"]

            v5["<a href=https://github.com/OpenVanta/cli/blob/17b4866451a6c346bce42c8d5d32f49600520186/scripts/codegen/generate-commands.ts#L489 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 489] singular</a>"]

            v6["<a href=https://github.com/OpenVanta/cli/blob/17b4866451a6c346bce42c8d5d32f49600520186/scripts/codegen/generate-commands.ts#L489 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 489] own</a>"]

            v7["<a href=https://github.com/OpenVanta/cli/blob/17b4866451a6c346bce42c8d5d32f49600520186/scripts/codegen/generate-commands.ts#L490 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 490] `</a>"]
        end
            v2 --> v3
            v3 --> v4
            v4 --> v5
            v5 --> v6
            v6 --> v7
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/OpenVanta/cli/blob/17b4866451a6c346bce42c8d5d32f49600520186/scripts/codegen/generate-commands.ts#L490 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 490] new RegExp(`-(to|from|for)-${own}$`)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink

Loading

@dennis-chen-vanta
dennis-chen-vanta force-pushed the dennis-chen-vanta/cli-command-structure branch from 680d6c8 to aebb6f2 Compare October 21, 2026 17:46
@dennis-chen-vanta
dennis-chen-vanta force-pushed the dennis-chen-vanta/command-codegen branch from 9172332 to 0a3dbec Compare October 21, 2026 17:46
dennis-chen-vanta and others added 4 commits October 21, 2026 19:11
Add scripts/codegen/generate-commands.ts, which derives every API command
in src/commands/ from api-spec.json using the conventions in AGENTS.md.
Exceptions to the rules and help text overrides live in
scripts/codegen/config.ts.

- `pnpm generate:commands` regenerates src/commands/
- CI fails if the generated commands are out of date
- Generated files are marked with a "Code generated" header; the
  generator removes generated files for groups that no longer exist

The generated output matches the previous commit apart from the header.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Semgrep flags `new RegExp` built from a path segment
(detect-non-literal-regexp). Compare the suffix as a string instead;
generated output is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Resolve every $ref once when the spec loads, instead of calling
  deref() wherever a schema is read
- Type the parts of the OpenAPI spec the generator reads; no `any`
- Keep groups in a map keyed by CLI path instead of a tree with a fake
  root node
- Clearer names (`placement`, `topGroup`, `valueSchema`)

Generated commands are byte-for-byte identical.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- `links` in config.ts lists operations that attach or detach an existing
  resource; the generator names them add/remove. The spec can't mark these
  itself, since its summaries also say "Add" for creates.
- GETs that return a file use `download`.
- `commandPlural` lets `uploads` read as `files` in list commands.
- Drops the overrides that shortened names repeating the group
  (`list-library`, `list-deactivated`, `add-document`, `add-test`).
- Removes mounts: every group is its path's first segment, so the
  generator no longer nests groups.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@dennis-chen-vanta
dennis-chen-vanta force-pushed the dennis-chen-vanta/command-codegen branch from 0a3dbec to 80902d0 Compare October 21, 2026 19:11
@dennis-chen-vanta
dennis-chen-vanta force-pushed the dennis-chen-vanta/cli-command-structure branch from aebb6f2 to 866696d Compare October 21, 2026 19:11
@dennis-chen-vanta

Copy link
Copy Markdown
Contributor Author

Superseded by #32, which is the same change restacked on #31 (oxfmt).

@dennis-chen-vanta
dennis-chen-vanta deleted the dennis-chen-vanta/command-codegen branch October 27, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant