perf(launch): no Cloud config request before the first window
cmux NEXT no longer waits on the network before it opens its window. At launch, the Cloud client-config is read from the validated cache, or from a known backend's built-in configuration when there is no cache. Before, every launch held applicationDidFinishLaunching, and with it the first window and the daemon connect, behind one GET /v1/client-config request. On NIGHTLY 4203360930601 that took 113–1532 ms per relaunch in the L5 relaunch check (cmuxterm-hq#7289). Production answers that request with a 404, which falls back to the built-in configuration anyway, so the wait bought nothing there.
- The launch read.
cmux cloud env get --cache-first(Resolver::client_config_cache_first) answers from the validated cache, else from a known deployment's built-in configuration, with no request. A custom (loopback) origin with no cache is still fetched, and fails closed as before. An unreadable or invalid cache falls through to the fetch. - The refresh. Once the first frame is up, the app runs the old fetch once (
CloudEnvironmentBootstrap.resolveAtLaunch'srefresh; ProcessRunner bounds it at 30 s). It writes the cache, so a backend's changed config applies at the next launch. A malformed or refused response still fails that fetch and is never cached. - Cost. A config the backend changed applies one launch later. That is what an offline launch already does with the cache today.
Numbers (L5 relaunch check, scripts/ci/relaunch_restore_check.py, NIGHTLY 4203360930601)
The main.run → did_finish_launching_start launch marks are the wait this removes:
| round | front | main.run → did_finish_launching_start | quit → usable |
|---|---|---|---|
| A1 | terminal | 1532 ms | 3042 ms |
| A2 | chat | 113 ms | 4041 ms |
| A3 | terminal | 825 ms | 2382 ms |
| B1 | terminal | 777 ms | 3228 ms |
| B2 | chat | 841 ms | 5645 ms |
| B3 | terminal | 1077 ms | 2834 ms |
curl https://cloud-api.cmux.dev/v1/client-config gives 404 in 0.20–1.34 s. The after number comes from the first nightly with this change, on the same check (cmuxterm-hq#7290's relaunch-restore job). I'll post it here and on cmuxterm-hq#7289. Chat-front rounds also have a separate first-paint gap, which is fixed apart from this.
Testing
cargo test -p cmux-cloud-environment: 18 passed. That includes the newcache_first_reads_the_cache_or_a_known_deployment_without_the_network, which checks:- a cache in front of a backend that never answers returns in under 1 s;
- a known backend with no cache takes its built-in config;
- a custom origin with no cache is fetched.
- Fleet app compile check at this head.
Changelog
Changed: cmux NEXT opens its window without waiting on a Cloud configuration request.
Agent session: agent session
🤖 Generated with Claude Code
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
cmux NEXT now opens its first window without waiting on a Cloud client-config request. Previously every launch held applicationDidFinishLaunching behind a GET /v1/client-config fetch that took 113–1532 ms; production answers with a 404 anyway, falling back to the built-in configuration.
cmux cloud env get --cache-firstreads from the validated cache, else a known backend's built-in configuration, with no network request; a custom origin with no cache still fetches and fails closed.- After the first frame, a single bounded fetch refreshes the cache, so a backend's changed config applies at the next launch; malformed or refused responses are never cached.
- The refresh runs in the launch-read task and is cancelled at quit, and each cache write is fenced by its fetch's start time so an older fetch never replaces a newer cache.