enhancement: 3x faster CLI invocation, unify boolean/env parsing, streamline CLI startup paths#1195
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR significantly improves CLI startup performance (3x faster on low-end hardware) through lazy loading, optimized routing, and centralized parsing. The changes also standardize environment variable and boolean parsing across the entire codebase.
Changes:
- Introduced centralized boolean/env parsing utilities (
parseBooleanValue(),isTruthyEnvValue()) replacing dozens of ad-hoc string comparisons - Implemented lazy subcommand registration and fast-path routing for common read-only commands (health, status, sessions, memory status)
- Added config caching (200ms default TTL) and deferred shell environment loading to reduce repeated I/O
- Extracted config validation/migration logic into a dedicated
config-guardmodule used explicitly by commands instead of global pre-action hooks - Made logger initialization lazy to avoid circular import issues and early initialization overhead
Reviewed changes
Copilot reviewed 58 out of 58 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
boolean.ts, boolean.test.ts |
New centralized boolean parsing utility with comprehensive test coverage |
env.ts, env.test.ts |
Added isTruthyEnvValue() helper for consistent env flag checks |
cli-timing.ts |
New structured CLI timing instrumentation for performance monitoring |
argv.ts, argv.test.ts |
New argv parsing helpers for command path extraction and flag detection |
route.ts |
Fast-path routing for read-only commands bypassing full program initialization |
register.subclis.ts, register.subclis.test.ts |
Major refactor to lazy subcommand registration with explicit argv parsing |
config-guard.ts |
Centralized config validation/migration extracted from pre-action hooks |
preaction.ts |
Removed config migration logic (moved to config-guard) |
context.ts |
Deferred plugin loading to avoid eager initialization |
plugin-registry.ts, channel-options.ts |
Extracted helpers for explicit control over plugin/channel loading |
register.agent.ts, register.status-health-sessions.ts, message/helpers.ts |
Added explicit config guards to commands |
memory-cli.ts, memory-cli.test.ts |
Extracted runMemoryStatus() for reuse in routing |
io.ts |
Added 200ms config caching and deferred shell env fallback support |
shell-env.ts, path-env.ts |
Standardized env checks using isTruthyEnvValue() |
entry.ts |
Added CLAWDBOT_NO_RESPAWN support and standardized env checks |
console.ts |
Made logger initialization lazy to avoid circular dependencies |
globals.ts, various CLI files |
Switched to direct subsystem logger imports avoiding barrel resolution |
| 50+ files across gateway, agents, memory, browser, hooks | Replaced ad-hoc env/boolean string comparisons with isTruthyEnvValue() and parseBooleanValue() |
frontmatter.ts (hooks & skills), browser-cli-state.ts, routes/utils.ts |
Reused parseBooleanValue() for consistent boolean handling |
| All live test files | Standardized test gating using isTruthyEnvValue() |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Contributor
|
Gustavo, ohh love this - yeah perf was bothering me too, just didn't expect it'd be as simple as this! Thanks! |
Add shared parseBooleanValue()/isTruthyEnvValue() and apply across CLI, gateway, memory, and live-test flags for consistent env handling. Introduce route-first fast paths, lazy subcommand registration, and deferred plugin loading to reduce CLI startup overhead. Centralize config validation via ensureConfigReady() and add config caching/deferred shell env fallback for fewer IO passes. Harden logger initialization/imports and add focused tests for argv, boolean parsing, frontmatter, and CLI subcommands.
Deleted the unused import of hasHelpOrVersion from argv.js to clean up the code.
Leftover functions I was using the benchmark and time CLI calls
Contributor
|
Landed via temp rebase onto main. Thanks @gumadeiras! |
lovewanwan
pushed a commit
to lovewanwan/openclaw
that referenced
this pull request
Apr 28, 2026
lovewanwan
pushed a commit
to lovewanwan/openclaw
that referenced
this pull request
Apr 28, 2026
enhancement: 3x faster CLI invocation, unify boolean/env parsing, streamline CLI startup paths
github-actions Bot
pushed a commit
to Desicool/openclaw
that referenced
this pull request
May 9, 2026
github-actions Bot
pushed a commit
to Desicool/openclaw
that referenced
this pull request
May 9, 2026
enhancement: 3x faster CLI invocation, unify boolean/env parsing, streamline CLI startup paths
22 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I noticed the
clawdbotinvocation getting slower over the last couple of weeks, especially in weak hardware. Can add up quickly if repeatedly running commandsA few example benchmarks running on a cheap VPS 2 core / 2GB:
Summary
Per-file Changes
boolean.tsparseBooleanValue()boolean.test.tsenv.tsisTruthyEnvValue()env.test.tsshell-env.tsisTruthyEnvValue(); added deferral flag helperpath-env.tsisTruthyEnvValue()cli-timing.tsio.tsentry.tsCLAWDBOT_NO_RESPAWNhandling; standardized env checksargv.tsargv.test.tshelpers.ts(CLI)resolveActionArgs()register.subclis.tsregister.subclis.test.tsbuild-program.tscontext.tschannel-options.tsplugin-registry.tsconfig-guard.tspreaction.tsregister.agent.tsagent/agentscommandsregister.status-health-sessions.tshelpers.ts(message actions)route.tsmemory-cli.tsrunMemoryStatus()and added config guardmemory-cli.test.tsbrowser-cli-state.tsparseBooleanValue()for on/off parsingutils.tsparseBooleanValue()for query/body boolean parsingutils.test.tstoBoolean()frontmatter.ts(flags)parseBooleanValue()for frontmatter flagsfrontmatter.test.ts(skills)frontmatter.ts(hooks)parseBooleanValue()for hook enablementfrontmatter.test.ts(hooks)server.tsisTruthyEnvValue()doctor-update.tsisTruthyEnvValue()health.tsisTruthyEnvValue()server-startup.tsisTruthyEnvValue()server-reload-handlers.tsisTruthyEnvValue()server-browser.tsisTruthyEnvValue()bonjour.tsisTruthyEnvValue()cli-runner.tsisTruthyEnvValue()pi-embedded-subscribe.raw-stream.tsisTruthyEnvValue()accounts.tsisTruthyEnvValue()batch-gemini.tsisTruthyEnvValue()embeddings-gemini.tsisTruthyEnvValue()console.tslogging.tsglobals.tsgetLogger()constants.tscli-credentials.tsanthropic.setup-token.live.test.tsisTruthyEnvValue()google-gemini-switch.live.test.tsminimax.live.test.tsmodels.profiles.live.test.tspi-embedded-runner-extraparams.live.test.tszai.live.test.tspw-session.browserless.live.test.tsgateway-cli-backend.live.test.tsgateway-models.profiles.live.test.tsaudio.live.test.tsOverall Improvements
parseBooleanValue()andisTruthyEnvValue()config-guardinstead of implicit pre-action hooksReasoning
Tests
pnpm vitest run boolean.test.ts env.test.ts frontmatter.test.ts frontmatter.test.ts utils.test.ts argv.test.ts register.subclis.test.ts embeddings.test.ts globals.test.ts gmail-setup-utils.test.ts memory-cli.test.tspnpm vitest run argv.test.ts register.subclis.test.tspnpm lint && pnpm build && pnpm testAI Assisted: GPT-5.2 Codex
To hopefully give some intuition and to make sure I validated routes correctly:
CLI entrypoints:
runCli().Routing diagrams (current):
Why faster: avoids building Commander program + importing all subcommands.
Why faster: only loads the chosen subcommand instead of importing all.
What’s new/different/faster:
NEW: Fast-path routing for read-only commands in route.ts.
Faster because it bypasses Commander setup and lazy imports entirely.
NEW: Lazy subcommand registration in register.subclis.ts.
Faster because only the invoked subcommand’s module tree is loaded.
NEW: Deferred plugin registry loading via channel-options.ts and plugin-registry.ts.
Faster because plugin discovery is avoided unless explicitly needed.
NEW: Config caching in io.ts.
Faster because repeated config reads in short-lived runs reuse cached content.
Summary flow (combined):