fix(sync-banner): name the runtimes we actually sync, not a hardcoded OpenClaw - #5010
Merged
Merged
Conversation
… OpenClaw
The first-install sync banner shipped the literal string "Syncing your
OpenClaw workspace" in banners.html. Nothing ever rewrote it, so the banner
asserted OpenClaw on every machine, including the majority that only run
Claude Code / Codex / Cursor and have never installed OpenClaw. A user
watching an unfamiliar product name scroll past during onboarding reasonably
reads it as "this thing is confused about my setup."
The banner now names what it is really syncing:
0 / unknown Syncing your AI agents
1 Syncing your Claude Code data
2 Syncing Claude Code and Cursor
3+ Syncing Claude Code, Cursor and 2 more
/api/sync-progress grows a `runtimes: [{id, label}]` list (added by the
dashboard, not the daemon, so no daemon release is needed) and
_cmSyncScopeTitle builds the title from it. The static default in the
template is now runtime-neutral, since it renders before detection lands.
Two things the implementation has to get right:
- Honesty. A runtime is only named when it has sessions ON DISK, the same
rule _detect_runtimes_for_heartbeat already applies. Presence alone is a
phantom: the Cursor IDE creates its state dir whether or not the agent was
ever run, and naming that would just be a different lie.
- Cost. Detection globs session dirs and measured ~3.3s on a busy machine,
and the banner polls every 15s. So it never runs inline: the handler
serves a 60s cache and a daemon thread refreshes it. The very first
request returns [] (neutral title) and the next poll has the names.
Detection merges three sources because no single one is complete: the OSS
adapter registry (OpenClaw/NemoClaw, with a direct-instantiation fallback
since registration happens at app creation), _detect_runtimes_lite (free,
always present), and _detect_family_runtimes (more accurate, but it imports
from clawmetry_pro so it returns nothing in OSS).
Verified: 8 guard tests, all 8 red against the pre-fix tree; endpoint
returns the real list on this machine; browser screenshot of the rendered
banner reading "Syncing OpenClaw, Claude Code and 2 more".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
✅ Drift Bot (ClawMetry): no drift detectedDrift Bot analyzed the changed files against this project's blueprints and requirements and found no drift. |
Contributor
Visual diffComparing 32 of 66 comparison(s) flagged (>1% pixel diff).
Folder: ec3403ba92c9. Full PNGs also attached as a workflow artefact. Generated by visual-diff bot. Pixel diffs >1% flagged; eyeball the table before merging. This check is non-blocking — fail = bot bug, not a code problem. |
vivekchand
added a commit
that referenced
this pull request
Aug 20, 2026
…5010) Ships the fix for the hardcoded "Syncing your OpenClaw workspace" banner title to PyPI and the fleet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
vivekchand
added a commit
that referenced
this pull request
Aug 21, 2026
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.
The bug
The first-install sync banner shipped a hardcoded string in
banners.html:Nothing ever rewrote it. So the banner asserted OpenClaw on every machine, including the majority that only run Claude Code / Codex / Cursor and have never installed OpenClaw. During onboarding, an unfamiliar product name scrolling past reads as "this thing is confused about my setup," which is the opposite of what a first-install banner is for.
The fix
The banner now names what it is actually syncing:
Syncing your AI agentsSyncing your Claude Code dataSyncing Claude Code and CursorSyncing Claude Code, Cursor and 2 more/api/sync-progressgrows aruntimes: [{id, label}]list and_cmSyncScopeTitlebuilds the title from it. The list is added by the dashboard, not the daemon, so this needs no daemon release to take effect. The template's static default is now runtime-neutral, because it renders before any detection has landed.Two things the implementation has to get right
Honesty. A runtime is only named when it has sessions on disk, the same rule
_detect_runtimes_for_heartbeatalready applies. Presence alone is a phantom: the Cursor IDE creates its state dir whether or not the agent was ever run, and naming that would just be a different lie in place of the old one.Cost. Detection globs session dirs and measured ~3.3s on a busy machine, while the banner polls every 15s. So it never runs inline: the handler serves a 60s cache and a daemon thread refreshes it. The first request returns
[](neutral title) and the next poll has the names. That was a deliberate trade, a generic-but-true title beats stalling the banner for three seconds.Detection merges three sources because no single one is complete:
_detect_runtimes_lite(free, always present)_detect_family_runtimes(more accurate, but it imports fromclawmetry_pro, so it returns nothing in OSS)Verification
tests/test_sync_banner_names_real_runtimes.py, covering the template copy, the JS fallback, the render wiring, both endpoint branches (200 and cold-install 404), the non-blocking contract, the 0-session phantom rule, and the thread-failure path.origin/mainand re-running.[openclaw, claude_code, codex, qwen_code].Syncing OpenClaw, Claude Code and 2 more.tests/test_sync_progress_sticky.py,test_adapters.py,test_adapter_registry_override.pystill green (25 passed).Note for reviewers
detect_config()has a latent bug this surfaced but does not fix: itsargs=Nonepath builds a bareargparse.Namespaceand thenAttributeErrors onargs.log_dir. The CLI always passes a full Namespace so it never fires in production. The test fixture works around it rather than widening this PR's scope.🤖 Generated with Claude Code