Skip to content

fix(cli): reduce startup time by deferring Kilo module loading and telemetry work - #12682

Merged
marius-kilocode merged 3 commits into
mainfrom
improve-kilo-cli-startup-performance
Jul 30, 2026
Merged

fix(cli): reduce startup time by deferring Kilo module loading and telemetry work#12682
marius-kilocode merged 3 commits into
mainfrom
improve-kilo-cli-startup-performance

Conversation

@marius-kilocode

@marius-kilocode marius-kilocode commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Problem

Kilo CLI startup has grown slower than upstream OpenCode on the same machine (see #10242), and the gap is widest for short invocations. Profiling the startup path showed the extra time is Kilo-specific work that runs (or loads) before any command executes:

  • kilocode/cli/setup.ts was imported eagerly from src/index.ts and statically pulled in telemetry, the gateway, AppRuntime, config, auth, session-export, and the JSON migration (~800ms of module loading from source).
  • Kilo-added imports in shared command files (run, tui, serve, web, mcp, attach, providers) and the Kilo command modules (console, cloud, roll-call, profile, daemon, remote, config) re-eagerized heavy dependency chains that upstream opencode#30453 had already deferred behind lazy handlers.
  • Telemetry.updateIdentity blocked every bootstrap on a profile HTTP request (~150-200ms) even though the resolved email rarely changes.
  • Telemetry.shutdown blocked every process exit on a PostHog flush (~500ms from EU: TCP+TLS setup plus one round trip).

What changed

Lazy module loading, same pattern as upstream opencode#30453. Command modules keep light top levels (yargs definitions only) and dynamically import implementations inside their handlers. KiloCli.bootstrap/shutdown in kilocode/cli/setup.ts dynamically import telemetry, the gateway, AppRuntime, config, auth, session-export, and the migration instead of loading them at module evaluation. All shared-file changes stay behind kilocode_change markers, and upstream's own import structure is untouched so future merges are unaffected. profile.ts also no longer constructs the auth runtime at module load, and the daemon/console commands share one lazy resolve-and-warn network helper.

Telemetry identity cache. The email resolved from the auth token is cached in telemetry-profile.json under the telemetry data path, keyed by a SHA-256 hash of the token (never the raw token), written with 0600 permissions. Repeat invocations skip the profile request entirely; a token change refetches, and entries older than a week are used for the current run but refreshed in the background.

Background telemetry flush. After trackCliStart, a flush is scheduled on a 300ms unref'd timer. Commands that outlive it upload while they run, so the shutdown flush usually finds an empty queue or a warm connection (~550ms down to ~150ms). Commands that exit faster keep today's single bounded shutdown(2000) flush, so no events are lost and the unreachable-endpoint cap from #9788 still applies.

Measured impact

All numbers from the same machine (macOS arm64, EU network), A/B against main in the same session via bun dev source runs (n=25 unless noted).

End to end:

Command Before After Delta
kilo --version 1482ms 903ms -39%
kilo --help 2149ms 1674ms -22%
kilo daemon status ~2030ms ~1630ms ~-20%

Component level:

Component Before After Note
Startup module evaluation (--version CPU profile) 1919ms 860ms -55% in-process
kilocode/cli/setup.ts import cost 836ms 205ms heaviest single module
Telemetry.updateIdentity per bootstrap ~173ms ~1ms warm cache; unchanged on first run after login
Telemetry.shutdown (commands >= ~1s) ~550ms ~150ms flush overlaps with execution
Telemetry.shutdown (instant commands) ~500ms ~500ms unchanged by design, single bounded flush

The remaining gap to upstream for informational commands is the bootstrap/telemetry lifecycle itself, which #12659 skips independently; the two changes compose, and whichever lands second only needs a small rebase on the bootstrap() signature.

Closes #10242. Scope note: this PR addresses the Kilo-specific contributors the profiling identified (the issue's prioritization ask). The flag-gated startup profiler from the issue's acceptance criteria is intentionally not part of this change and should be tracked as follow-up tooling work.

Comment thread packages/kilo-telemetry/src/identity.ts Outdated
Comment thread packages/kilo-telemetry/src/identity.ts
Comment thread packages/opencode/src/kilocode/cli/cmd/daemon.ts Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/roll-call.ts Outdated
@kilo-code-bot

kilo-code-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

All four previously flagged suggestions have been addressed in the latest commit:

  • identity.ts: cache writes now use a temp-file + rename (atomic), with cleanup on failure.
  • identity.ts: the module comment was softened to accurately describe the best-effort, non-blocking background refresh.
  • daemon.ts: resolveNetworkOptions is now imported with import type, matching port-warning.ts.
  • roll-call.ts: the module-scope loader was renamed to loadDeps(), removing the name collision with the local load in handle().
Files Reviewed (3 files)
  • packages/kilo-telemetry/src/identity.ts
  • packages/opencode/src/kilocode/cli/cmd/daemon.ts
  • packages/opencode/src/kilocode/cli/cmd/roll-call.ts
Previous Review Summary (commit 9ab316e)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 9ab316e)

Status: 4 Issues Found | Recommendation: Merge (nice-to-haves only)

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 4
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-telemetry/src/identity.ts 88 Cache write is not atomic (no temp-file + rename); concurrent CLI invocations could interleave/corrupt the file
packages/kilo-telemetry/src/identity.ts 112 Background refresh of a stale cache entry is fire-and-forget with nothing keeping the process alive, so it may never complete for short-lived commands; the module comment overstates the guarantee
packages/opencode/src/kilocode/cli/cmd/daemon.ts 4 resolveNetworkOptions is now only used in a type position but still imported as a value; port-warning.ts already switched to import type for the same symbol
packages/opencode/src/kilocode/cli/cmd/roll-call.ts 15 New module-scope function load() collides in name with a pre-existing local const load in handle(); not a bug (correct shadowing) but confusing
Files Reviewed (21 files)
  • .changeset/cli-startup-lazy-loading.md
  • packages/kilo-telemetry/src/__tests__/identity.test.ts
  • packages/kilo-telemetry/src/client.ts
  • packages/kilo-telemetry/src/identity.ts - 2 issues
  • packages/kilo-telemetry/src/telemetry.ts
  • packages/opencode/src/cli/cmd/attach.ts
  • packages/opencode/src/cli/cmd/config.ts
  • packages/opencode/src/cli/cmd/mcp.ts
  • packages/opencode/src/cli/cmd/providers.ts
  • packages/opencode/src/cli/cmd/remote.ts
  • packages/opencode/src/cli/cmd/run.ts
  • packages/opencode/src/cli/cmd/serve.ts
  • packages/opencode/src/cli/cmd/tui.ts
  • packages/opencode/src/cli/cmd/web.ts
  • packages/opencode/src/kilocode/cli/cmd/cloud.ts
  • packages/opencode/src/kilocode/cli/cmd/console.ts
  • packages/opencode/src/kilocode/cli/cmd/daemon.ts - 1 issue
  • packages/opencode/src/kilocode/cli/cmd/profile.ts
  • packages/opencode/src/kilocode/cli/cmd/roll-call.ts - 1 issue
  • packages/opencode/src/kilocode/cli/port-warning.ts
  • packages/opencode/src/kilocode/cli/setup.ts

All kilocode_change markers on shared upstream files (attach.ts, config.ts, mcp.ts, providers.ts, remote.ts, run.ts, serve.ts, tui.ts, web.ts) correctly wrap the Kilo-specific lazy-import changes, and the refactors are surgical (no unnecessary upstream restructuring). Dynamic-import conversions in setup.ts and the Kilo-only command files are correctly awaited with no race conditions in startup/shutdown sequencing. Telemetry identity caching correctly hashes the token (SHA-256, never stored raw) and applies 0600 permissions. A changeset is present and user-facing-oriented. No CRITICAL or WARNING issues found; all findings above are low-severity suggestions.

Fix these issues in Kilo Cloud


Reviewed by claude-sonnet-5 · Input: 20 · Output: 3.7K · Cached: 395.9K

Review guidance: REVIEW.md from base branch main

@marius-kilocode
marius-kilocode merged commit 759139d into main Jul 30, 2026
31 checks passed
@marius-kilocode
marius-kilocode deleted the improve-kilo-cli-startup-performance branch July 30, 2026 11:24
unixcrh pushed a commit to unixcrh/kilocode that referenced this pull request Aug 1, 2026
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
…tup-performance

fix(cli): reduce startup time by deferring Kilo module loading and telemetry work
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.

Analyse and profile CLI startup speed

2 participants