Skip to content

refactor(cli): migrate local parsers to usage-rs - #2534

Closed
fengmk2 wants to merge 4 commits into
rfc/napi-clap-cli-argsfrom
refactor/usage-rs-cli-args
Closed

refactor(cli): migrate local parsers to usage-rs#2534
fengmk2 wants to merge 4 commits into
rfc/napi-clap-cli-argsfrom
refactor/usage-rs-cli-args

Conversation

@fengmk2

@fengmk2 fengmk2 commented Aug 23, 2026

Copy link
Copy Markdown
Member

The complete plan is in rfcs/usage-rs-local-cli.md. The Vite Task change is in vite-task#694.

This draft is stacked on #2523. It replaces all clap parsers in the local NAPI binary with usage-rs. The global vp binary continues to use clap.

Design

The command call graph stays the same:

Node.js local CLI
  -> raw argv
  -> NAPI parser
  -> usage-rs static typed parser
  -> typed NAPI result
  -> JavaScript or Rust command operation

The local dependency graph now has one parser framework:

vite-plus-cli NAPI binary
  +-> js_command_args -> usage-rs
  +-> local command router -> usage-rs
  +-> vp_pm_cli -> usage-rs
  +-> vt -> usage-rs
  +-> vt_workspace -> parser-neutral data
  +-> vp_cli_help -> usage-rs metadata

clap: no normal dependency path

Completion uses the selected local Vite+ package:

shell completion script
  -> global vp completion request
  +-> global-only clap_complete candidates
  +-> selected local Vite+ package
      -> Node.js completion entry
      -> NAPI completion request
      -> usage-rs completion engine
  -> merge and remove duplicate candidates
  -> usage-rs shell renderer
  -> shell

One typed Rust grammar supplies parsing, help, diagnostics, and completion data. The implementation keeps strict errors, aliases, negated flags, repeated-option rules, and -- forwarding.

Completion supports Bash, Zsh, Fish, Nu, and PowerShell. Dynamic completion includes task names, package names, package filters, and the vpr view.

Performance

The parser benchmarks ran on macOS ARM64 with Node.js 22.22.0.

Metric main / mri #2523 / clap This PR / usage-rs
Successful staged parse 1.20 µs 6.36 µs 1.007 µs
Unknown option Not comparable 4.42 µs 2.158 µs
Parse and build staged help Not available 21.572 µs 1.977 µs
Static staged completion Not available Not available 1.571 µs
vp --version 130.76 ms 130.38 ms 123.8 ms
vp staged --help 140.27 ms 132.42 ms 124.4 ms

The successful parser is 84% faster than clap. Full CLI latency does not improve measurably because Node.js startup controls the result.

Artifact size

Paired local release builds produced these macOS ARM64 NAPI sizes:

Format #2523 / clap This PR / usage-rs Change
Binary 41,869,648 B 41,774,816 B -94,832 B (-0.23%)
gzip -9 17,221,832 B 17,147,440 B -74,392 B (-0.43%)
Mach-O __text 19,438,000 B 19,207,460 B -230,540 B (-1.19%)

The JavaScript files do not change after #2523. The canonical Linux artifact totals are:

Distributed JavaScript main / mri #2523 / clap This PR / usage-rs
packages/cli/dist 1,685,719 B 1,666,423 B 1,666,423 B
packages/core/dist, without .node 4,097,460 B 4,097,460 B 4,097,460 B
Combined dist 5,783,179 B 5,763,883 B 5,763,883 B

The binary reduction is real but small. Binary size alone does not justify this migration. The main benefits are one grammar, completion support, and lower parser cost.

usage-rs is experimental. This draft pins an exact reviewed revision from the experiment fork. A dependency update must repeat the compatibility, performance, and size checks.

@fengmk2 fengmk2 self-assigned this Aug 23, 2026
@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

CLI artifact sizes (dab32fe)

Final release artifacts built by the canonical build-upstream and build-windows-cli actions.
The dist rows use the Linux build. The core total excludes .node files to match the release artifact.

Artifact Format Base PR Change
packages/cli/dist Directory total 1.59 MiB 1.59 MiB 0 B (0.00%)
packages/core/dist Directory total 3.91 MiB 3.91 MiB 0 B (0.00%)
Combined package dist Directory total 5.50 MiB 5.50 MiB 0 B (0.00%)
vp (Linux x64) Binary 10.74 MiB 10.77 MiB +24.00 KiB (+0.22%)
vp (Linux x64) gzip -9 4.65 MiB 4.66 MiB +11.75 KiB (+0.25%)
NAPI (Linux x64) Binary 32.39 MiB 32.17 MiB -224.06 KiB (-0.68%)
NAPI (Linux x64) gzip -9 12.76 MiB 12.69 MiB -71.86 KiB (-0.55%)
vp (macOS ARM64) Binary 8.03 MiB 8.05 MiB +16.11 KiB (+0.20%)
vp (macOS ARM64) gzip -9 4.06 MiB 4.07 MiB +11.89 KiB (+0.29%)
NAPI (macOS ARM64) Binary 39.93 MiB 39.84 MiB -92.66 KiB (-0.23%)
NAPI (macOS ARM64) gzip -9 17.05 MiB 16.95 MiB -95.55 KiB (-0.55%)
vp (Windows x64) Binary 8.64 MiB 8.66 MiB +23.50 KiB (+0.27%)
vp (Windows x64) gzip -9 3.77 MiB 3.78 MiB +8.08 KiB (+0.21%)
NAPI (Windows x64) Binary 27.20 MiB 26.92 MiB -283.00 KiB (-1.02%)
NAPI (Windows x64) gzip -9 10.82 MiB 10.74 MiB -81.98 KiB (-0.74%)
Trampoline (Windows x64) Binary 214.00 KiB 214.00 KiB 0 B (0.00%)
Trampoline (Windows x64) gzip -9 103.20 KiB 103.20 KiB -1 B (-0.00%)
Installer (Windows x64) Binary 4.50 MiB 4.50 MiB +512 B (+0.01%)
Installer (Windows x64) gzip -9 2.11 MiB 2.11 MiB +725 B (+0.03%)

@fengmk2 fengmk2 changed the title refactor(cli): parse JS command arguments with usage-rs refactor(cli): migrate local parsers to usage-rs Aug 23, 2026
@fengmk2

fengmk2 commented Aug 23, 2026

Copy link
Copy Markdown
Member Author

Closing this experiment for now. usage-rs makes little difference to the final NAPI binary size. Replacing clap requires a major refactor, so we will not consider this migration now.

@fengmk2 fengmk2 closed this Aug 23, 2026
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