-
Notifications
You must be signed in to change notification settings - Fork 11.2k
Description
Summary
Gemini CLI's npm package ships ~44,835 files (unbundled dist/ + full node_modules/). On Windows, this causes severe cold-start latency (~1-2 minutes) due to Windows Defender's real-time protection minifilter scanning every file on first access. Subsequent launches are fast because Defender caches scan results — but the cache expires after a few hours, so the penalty recurs daily.
The esbuild bundling infrastructure already exists in the repo (npm run bundle → bundle/gemini.js), but the published npm package doesn't use it.
Evidence
File count comparison:
| Tool | Files on disk | Cold start (Windows) |
|---|---|---|
Gemini CLI (@google/gemini-cli) |
44,835 | ~60-120s |
| Claude Code | 1 (compiled Bun binary) | ~3s |
The "first launch of the day" pattern:
Cold starts are slow (~1-2 min), repeat launches within the same session are fast (~4-8s), and after a few hours of inactivity the slowness returns. This exactly matches Windows Defender's scan cache behaviour — results are cached per (file path, file hash) with a TTL of a few hours, after which every file is rescanned on next access.
Built-in profiling confirms the app code itself is fast:
Using GEMINI_DEBUG_LOG_FILE and the startup profiler, the entire cli_startup phase takes only ~3.8 seconds internally:
cli_startup: 3,825ms
initialize_app: 2,124ms
authenticate: 201ms
load_builtin_cmds: 215ms
discover_tools: 113ms
load_settings: 28ms
parse_arguments: 19ms
load_cli_config: 9ms
The ~1-2 minute gap is entirely before any application code runs — during Node.js module resolution and OS-level file scanning of the 44,835 files in node_modules/.
Workaround confirms the diagnosis:
Adding node.exe to Windows Defender's process exclusion list (Add-MpPreference -ExclusionProcess "node.exe") eliminates the cold-start penalty entirely.
The bundle infrastructure already exists
The repo already has esbuild bundling:
npm run bundleproducesbundle/gemini.js- The root
package.jsondeclares"bin": { "gemini": "bundle/gemini.js" }and"files": ["bundle"]
However, the published npm package (packages/cli) ships with "main": "dist/index.js" and full dependencies, resulting in the 44,835-file install. The bundling is currently only used for the npx execution path.
Proposed fix
Ship the esbuild bundle as the primary npm distribution:
- Replace
dist/+ dependencies with the pre-builtbundle/gemini.jsin the published package - Keep platform-specific native optional dependencies (node-pty, keytar) that can't be bundled
- This would reduce the on-disk file count from ~44,835 to a handful, eliminating the antivirus scan overhead on all platforms
This is essentially what Claude Code does — they ship zero npm dependencies by bundling everything into the package.
Environment
- Windows 11 Home (10.0.26200)
- Node.js 24.13.0 (via Volta)
- Gemini CLI 0.28.x (npm global install)
- Windows Defender real-time protection enabled (default)
Related issues
- Package installation is slow; suggest bundling dependencies to improve speed #5348 — "Package installation is slow; suggest bundling dependencies" (bot-closed, no action taken)
- Gemini CLI takes up to 39 seconds to load on Windows #11511 — "Takes up to 39 seconds to load on Windows" (contributor confirmed node_modules FS operations as root cause)
- Optimize Startup Performance #14429 — "Optimize Startup Performance" (open, assigned, but focused on micro-optimizations)
- Poor Startup time on Windows 11 #7828 — "Poor Startup time on Windows 11"