← Back to PRs

#16710: feat: fast-path --version, --help, and no-args to skip full module loading (~98% faster on Windows)

by xin-wen open 2026-02-15 01:43 View on GitHub →
size: S
## Problem On Windows+NTFS, even simple commands take 4-9s due to filesystem overhead resolving ~400 npm packages through the ESM module loader. ### Profiling breakdown (5.1s total wall time): | Component | Time | |-----------|------| | PowerShell shim | ~65ms | | Node.js startup | ~75ms | | **ESM module resolution (fs I/O)** | **~2900ms** | | JS compilation | ~670ms | | JS execution (CLI setup) | ~600ms | | GC + misc | ~400ms | Top CPU profile hitters: `internalModuleStat` (1137ms), `lstat` (434ms), `getPackageScopeConfig` (251ms). ## Solution Add fast-paths in `openclaw.mjs` that intercept before any heavy imports: - **--version / -V**: Reads version from `package.json` directly and exits. - **--help / -h / no args**: Uses a version+subcommand-keyed cache file at `~/.openclaw/.cache/help-VERSION[-SUBCMD].txt`. - First run: full load (generates cache transparently) - Subsequent runs: serves from cache (~85ms) - Cache auto-invalidates on version change (different filename) - Works for **both** top-level and subcommand help (e.g. `openclaw gateway --help`) ## Results | Command | Before | After (cached) | Speedup | |---------|--------|----------------|---------| | `openclaw --version` | ~4600ms | ~85ms | 98% | | `openclaw --help` | ~4600ms | ~83ms | 98% | | `openclaw` (no args) | ~4600ms | ~85ms | 98% | | `openclaw gateway --help` | ~9200ms | ~92ms | 99% | | `openclaw config --help` | ~9400ms | ~84ms | 99% | First run of each unique help page is normal speed (generating cache). Every subsequent run is ~85ms. ## Design - Cache key: `help-{version}[-{subcommands}].txt` — auto-invalidates on upgrade - Cache location: `~/.openclaw/.cache/` — easy to clear, doesn't pollute config - Stdout hook captures output transparently on cache miss — zero changes to existing CLI code - Only `--help`/`-h`/no-args triggers caching; normal command execution is unaffected <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR adds a fast-path in `openclaw.mjs` to intercept `--version`, `--help`, and no-args invocations before the heavy ESM module resolution, delivering a ~98% speedup on Windows+NTFS. The approach is sound — reading `package.json` directly for version and using a file-based help cache keyed by version + subcommand. However, the implementation has several issues that should be addressed before merging: - **Path traversal in cache key**: Subcommand tokens from argv are interpolated into the cache filename without sanitizing path separators (`/`, `\`), allowing `path.join` to resolve `..` segments and write files outside `~/.openclaw/.cache/`. - **Missing `-v` flag**: The downstream CLI (`src/cli/program/help.ts`, `src/cli/argv.ts`) recognizes `-v` as a version flag, but the fast-path only handles `-V` and `--version`, so `-v` users don't get the optimization. - **Error output gets cached**: The exit handler writes to cache regardless of exit code — if a help invocation fails with >100 chars of stdout output, that error text gets cached and served on subsequent runs. - **ANSI codes baked into cache**: Help output contains terminal color escape sequences which are cached verbatim. Cached output from a TTY run will show raw escape codes when piped, and vice versa. <h3>Confidence Score: 2/5</h3> - This PR has a path traversal vulnerability and functional inconsistencies that should be fixed before merging. - Score of 2 reflects the path traversal issue in cache key construction (allows writing files outside the intended cache directory), the missing `-v` flag creating behavioral inconsistency with the existing CLI, and the risk of caching error output. While the path traversal is mitigated by the fact that written content is only help text, it's still a security concern worth addressing. - `openclaw.mjs` — the only changed file; the cache key construction at line 11-12 and the exit handler at lines 47-53 both need fixes. <sub>Last reviewed commit: fd96b34</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs