Skip to content

Add btop-style agent activity sidebar example - #15393

Merged
teamleaderleo merged 10 commits into
mainfrom
examples/btop-agent-sidebar
Sep 28, 2026
Merged

teamleaderleo merged 10 commits into
mainfrom
examples/btop-agent-sidebar

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Adds Examples/CustomSidebars/btop-agents.js, a custom sidebar in the spirit of btop: each workspace gets a braille sparkline (U+2800 to U+28FF) of how busy its agents have been over the last six minutes, a state glyph, and a small progress meter, under a figlet-style header that graphs busy workspaces over twelve minutes. Relates to RFCs #15244 and #15245.

What each row shows:

  • A state glyph for the most urgent agent: braille spinner while working, amber ◆ when waiting for input, green ● when its turn is done, ○ when ended, · with no agent. A ×2 count appears when several agents are working.
  • The title, unread count and PR number. The PR number is colored by state and opens the PR on click.
  • The sparkline: each column is 15 seconds and its height is the share of that time an agent was working. Dot rows are layered in a ZStack so the graph runs green to orange with height, with a dotted floor where nothing happened.
  • The workspace's progress as a 6-cell meter with a percentage, or, without progress, the state and how long it has held (input 2m, run 14m, idle 5m).

Click a row to select the workspace, drag to reorder (drops map back to the full order when filtered), right-click to open the PR or mark read. The ALL/BUSY chip hides workspaces with no working or waiting agent and no unread notifications. Colors are system tokens (cyan, green, orange, tertiary, ...) plus gray washes, so it follows light and dark.

History is kept in the sidebar: each clock tick samples every workspace into 15-second buckets (48 kept per workspace, pruned when a workspace closes). Graphs start empty when the sidebar loads, except that sessions already working backfill from their sinceEpoch.

Install:

mkdir -p ~/.config/cmux/sidebars
cp Examples/CustomSidebars/btop-agents.js ~/.config/cmux/sidebars/
cmux sidebar validate btop-agents
cmux sidebar select btop-agents   # or: cmux sidebar open btop-agents

The README and docs/custom-sidebars.md example lists mention it, and CustomSidebarValidationTests.downloadableCustomSidebarExamplesValidate now expects it (19 examples).

Validation

  • Ran the file against the real SidebarRuntime.js prelude in Node with stub host bridges, a four-workspace fixture (claude/codex agents cycling working, idle and needs_input; a workspace with progress: "" and pr: ""), and 300 simulated clock ticks. It mounted without errors (143 scene nodes), a BUSY tap filtered to the busy rows, a row tap dispatched workspace.select, and a drop dispatched workspace.reorder. Also mounted with no data keys at all (shows "no workspaces"). Text dump of the scene after 300 ticks, braille layers merged:

    ┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐    20:31:40
    ├─┤│ ┬├┤ │││ │ └─┐    ⠋ 2 run
    ┴ ┴└─┘└─┘┘└┘ ┴ └─┘    ◆ 1 input
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡀⡀⠀⢀⡀⠀⢠⠀⠀⣀
    ⣤⣤⣤⣤⣤⣤⣤⣿⣿⣿⣿⣿⣿⣿⣿⣿⣼⣿⣷⣶⣿⣿⣶⣿
    12m busy workspaces, peak 3    now
    ALL BUSY    2/4 busy
    ▌ ⠋ cmux    ●2 #5812
      ⣿⣿⣿⣷⣀⣿⣷⣀⣿⣷⣀⣿    ■■■■ ■■ 64%
      ◆ review queue    #5801
      ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿    input 30s
      · research spike
      ⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀
      ● docs
      ⣀⣸⣄⣄⣰⣀⣄⣄⣰⣀⣄⣄    idle 20s
    
  • python3 scripts/verify-local.py: 16/16 static checks passed.

  • Not run locally: the CmuxSwiftRenderUI Swift test (CustomSidebarValidationTests), which validates every example through JavaScriptCore; CI runs it. No app build, so there is no screenshot yet; how the braille glyphs and layered ZStack look in the real sidebar is unverified until a dev build loads it.

Changelog

none

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Adds btop-agents.js, a btop-style agent activity sidebar, plus a regression test suite guarding its memory and rendering bounds. Each workspace shows a braille sparkline of agent busy-ness over the last six minutes, a state glyph, progress meter, unread count, and PR number, under a header that graphs busy workspaces over twelve minutes.

  • Click a row to select the workspace; drag to reorder; right-click to open the PR or mark read. The ALL/BUSY chip hides quiet workspaces, keeping the selected row visible.
  • History is sampled per clock tick into 15-second buckets inside the sidebar, so graphs start empty on load and backfill for already-working agents.
  • History is bounded with LRU eviction and stays capped across wall-clock jumps and filter changes; the per-tick snapshot never rescans the full workspace list.
  • Uses only system color tokens so it adapts to light and dark themes; heat ramps run green to orange to red because system yellow braille dots washed out on light sidebars.
  • Updates Examples/CustomSidebars/README.md, docs/custom-sidebars.md, the validation test (now 19 examples), and adds tests/test_btop_agents_sidebar.py to the preflight CI guards.

Install with cp Examples/CustomSidebars/btop-agents.js ~/.config/cmux/sidebars/ then cmux sidebar select btop-agents.

Written for commit 18140bd. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added a btop-style sidebar that displays workspace activity, status, progress, unread counts, and pull requests, with activity graphs and busy-workspace filtering. Select or reorder workspaces, open pull requests, and mark workspaces as read.
    • Added installation instructions and listed the sidebar among the downloadable examples.

btop-agents.js lists every workspace with a braille sparkline of recent
agent activity, a state glyph, a small progress meter, unread count and PR
number, under a figlet header with a graph of busy workspaces. History is
sampled per clock tick into per-workspace buckets inside the sidebar.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 28, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 82ef0f13-a9e7-4a69-b388-407f6d1479f8

📥 Commits

Reviewing files that changed from the base of the PR and between eb2331c and 18140bd.

📒 Files selected for processing (7)
  • .github/workflows/ci-guards.yml
  • Examples/CustomSidebars/README.md
  • Examples/CustomSidebars/btop-agents.js
  • Packages/macOS/CmuxSwiftRenderUI/Tests/CmuxSwiftRenderUITests/CustomSidebarValidationTests.swift
  • docs/custom-sidebars.md
  • tests/test-execution.toml
  • tests/test_btop_agents_sidebar.py

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

Adds a btop-style custom sidebar that displays workspace activity, status, progress, unread counts, and pull requests. It maintains bounded activity histories, caps and filters workspace rows, and supports workspace selection, reordering, opening pull requests, and marking workspaces as read.

Changes

Agent activity sidebar

Layer / File(s) Summary
Activity graphs and bounded history
Examples/CustomSidebars/btop-agents.js
Defines graph settings and state colors, renders braille graphs, and maintains bounded per-workspace activity history.
Workspace selection and snapshots
Examples/CustomSidebars/btop-agents.js, tests/test_btop_agents_sidebar.py, tests/test-execution.toml, .github/workflows/ci-guards.yml
Builds workspace row data, caps and filters displayed workspaces, and creates clock-based snapshots. Tests cover snapshot selection, history bounds, filtering, and eviction. Registers and runs the tests.
Sidebar display and example listing
Examples/CustomSidebars/btop-agents.js, Examples/CustomSidebars/README.md, docs/custom-sidebars.md, Packages/macOS/CmuxSwiftRenderUI/Tests/CmuxSwiftRenderUITests/CustomSidebarValidationTests.swift
Renders activity graphs, workspace rows, filters, and row actions. Adds the example to the README, downloadable examples, and sidebar validation expectations.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant SidebarClock
  participant Snapshot
  participant WorkspaceSelection
  participant ActivityHistory
  participant SidebarRows
  participant SidebarDisplay
  SidebarClock->>Snapshot: provide clock value
  Snapshot->>WorkspaceSelection: get capped workspace selection
  Snapshot->>ActivityHistory: sample workspace activity
  Snapshot->>SidebarRows: provide row data and aggregate history
  SidebarRows->>SidebarDisplay: render workspace rows and activity graphs
Loading

Merge Risk: ⚪ Minimal · up to 18140

The reported lone-row reorder problem cannot be triggered through the sidebar control. No merge-blocking issue remains after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 18140

The example uses existing workspace controls and keeps its activity history bounded. Its PR link opens a host-provided URL without restricting the URL scheme in the inspected path; the effect is limited to users who install the example and click the link. No exploit or broader exposure is established.

Retained concerns

  • Low · security · inferred: The new example passes a host-provided PR URL to the external URL-opening action on a user click, without a scheme restriction in the inspected example or action path. Whether an attacker can influence that URL, or an upstream control constrains it, remains unestablished.
Security review details

Security Blast Radius

  • inferred — The added URL action is available through the installed example and requires a user click. The inspected flow does not establish an automatic, cross-workspace, or remotely invoked URL-opening path.

Security Findings and Attack Paths

  • inferred — If an untrusted source can supply a non-web PR URL to the host snapshot, clicking its label could pass that URL to the operating system's handler. URL provenance and an attacker-controlled route were not established, so this is not a verified exploit.

Trust Boundaries and Controls

  • observed — Workspace actions are sent through the existing host command bridge using workspace IDs and fixed action names; the example does not directly own workspace state. URL opening uses a separate host action whose inspected final dispatch checks URL parseability, not scheme.

Resilience and Maintainability Implications

  • inferred — Clock-gated cleanup and sampling only visible rows can make the activity display temporarily stale or incomplete, but the inspected history limits contain retained state. No security decision was found to depend on that display.

Hardening Proposals

  • proposed — Confirm PR URL provenance and apply an appropriate web-URL policy before passing PR links to the external opener, particularly if PR metadata can originate outside the local host.

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Full Internationalization ❌ Error The new downloadable Examples/CustomSidebars/btop-agents.js adds user-facing sidebar text without a locale-specific source. It renders inline English labels such as run, input, `busy workspaces,… Add locale-aware string lookup support for interpreted JavaScript sidebars, route every new user-facing label and status string through that lookup, and add translated entries for all supported macOS locales (en, de, fr, ar, es, `…
Docstring Coverage ⚠️ Warning Docstring coverage is 23.81% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 21 functions across 3 files. (4 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: adding a btop-style agent activity sidebar example.
Description check ✅ Passed The description explains the sidebar behavior, installation, validation performed, known verification limits, and changelog status. It uses a Validation section instead of the template's Testing headi…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Cloud Persistent Session And Early Input ✅ Passed The pull request adds a custom JavaScript sidebar, documentation, validation tests, and CI registration. The new sidebar only calls workspace.select, workspace.reorder, and workspace.action; it …
Cmux Swift Actor Isolation ✅ Passed The pull request introduces no production Swift changes. Its only Swift change is in Packages/macOS/CmuxSwiftRenderUI/Tests/CmuxSwiftRenderUITests/CustomSidebarValidationTests.swift, where the test …
Cmux Swift Blocking Runtime ✅ Passed PASS: The pull request changes only one Swift file, Packages/macOS/CmuxSwiftRenderUI/Tests/CmuxSwiftRenderUITests/CustomSidebarValidationTests.swift. The diff only updates expected example names and…
Cmux Browser Automation Off-Main ✅ Passed The pull request does not change browser socket automation. The rule-scoped files Sources/TerminalController.swift and `Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Wire/ControlCommand…
Cmux Expensive Synchronous Load ✅ Passed The pull request changes no production Swift code. Its only Swift diff updates expected custom-sidebar names and the valid-example count in CustomSidebarValidationTests.swift; it does not add or mov…
Cmux Cache Substitution Correctness ✅ Passed PASS. The changed code adds only an in-memory sidebar activity history and a computed workspace selection for rendering. The history is a transient, non-persisted UI graph, which the rule allows. `wor…
Cmux No Hacky Sleeps ✅ Passed The changed runtime example introduces no sleep, setTimeout, setInterval, timer, polling, or fixed backoff. It updates history from the existing reactive data.clock()?.epoch signal and uses bo…
Cmux Algorithmic Complexity ✅ Passed PASS. The new production code uses a linear full-workspace selection pass and caps rendered rows and retained histories at MAX_ROWS = 40 and KEEP = 48 in `Examples/CustomSidebars/btop-agents.js:13…
Cmux Swift Concurrency ✅ Passed PASS. The only changed Swift file is the validation test, and its diff only adds the btop-agents name and changes the expected valid count from 18 to 19. It introduces no Dispatch, Combine, completi…
Cmux Swift @Concurrent ✅ Passed The PR changes one Swift file only to add btop-agents to the expected example names and increase the valid count from 18 to 19. It adds no async, nonisolated, or @concurrent code and does not …
Cmux Swift Package Boundaries ✅ Passed PASS. The pull request changes only one Swift file: CustomSidebarValidationTests.swift, and the change only updates the expected example name list and count. It introduces no production Swift code, …
Cmux Swiftpm Lockfiles ✅ Passed PASS — The PR changes one CI workflow step and a Swift test expectation, plus sidebar/docs/test files. It does not change any Package.swift, Package.resolved, .gitignore, Xcode project package r…
Cmux Swift Logging ✅ Passed The only Swift change is in Packages/macOS/CmuxSwiftRenderUI/Tests/CmuxSwiftRenderUITests/CustomSidebarValidationTests.swift, a test target. It only adds the btop-agents expected name and changes …
Cmux User-Facing Error Privacy ✅ Passed The changed sidebar reaches users through the cmux custom-sidebar UI, but it adds no user-facing error or recovery message. Its visible copy is limited to generic workspace status, empty-state text, P…
Cmux Swiftui State Layout ✅ Passed The pull request does not introduce SwiftUI implementation changes. Its only Swift change updates expected sidebar names and the valid count in CustomSidebarValidationTests.swift. The new sidebar is…
Cmux Architecture Rethink ✅ Passed PASS. The pull request introduces no Swift architecture change. The only Swift diff updates the custom-sidebar validation fixture from 18 to 19 names and adds btop-agents to the expected list. It ad…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR does not add or materially change a standalone cmux-owned window. Its only Swift change updates expected sidebar example names and the valid-count assertion in a test-only fixture. No NSWindow,…
Cmux Source Artifacts ✅ Passed All seven changed paths are intentional source, documentation, configuration, or test-system files. The new Examples/CustomSidebars/btop-agents.js is a documented product example, and `tests/test_bt…
Cmux No Test Or Debug Seam In Production Source ✅ Passed The pull request changes no Swift file under a production **/Sources/** path. Its only Swift change is `Packages/macOS/CmuxSwiftRenderUI/Tests/CmuxSwiftRenderUITests/CustomSidebarValidationTests.swi…
Full details: Docstring Coverage

Explanation

Docstring coverage is 23.81% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 21 functions across 3 files. (4 skipped: 4 unsupported.)

Full details: Cmux Full Internationalization

Explanation

The new downloadable Examples/CustomSidebars/btop-agents.js adds user-facing sidebar text without a locale-specific source. It renders inline English labels such as run, input, busy workspaces, peak, ALL, BUSY, Open PR, No PR, Mark Read, all quiet, and no workspaces (for example, lines 305, 310, 319, 378-397). The example is intended for installation, not a test or debug path. Examples/CustomSidebars/README.md also states that interpreted sidebars have no localization catalog, and the JS runtime passes raw Text and Button strings directly to native SwiftUI rendering. No translated entries or locale-specific runtime source were added.

Resolution

Add locale-aware string lookup support for interpreted JavaScript sidebars, route every new user-facing label and status string through that lookup, and add translated entries for all supported macOS locales (en, de, fr, ar, es, zh-Hant, zh-Hans, ko, ja) in Packages/macOS/CmuxSwiftRenderUI/Sources/CmuxSwiftRenderUI/Resources/Localizable.xcstrings. Alternatively, remove the user-facing prose from this downloadable example until that localization path exists.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review: I checked btop-agents.js against the JS sidebar runtime (SidebarRuntime.js, the scene node renderer and the color tokens), then loaded the file into that runtime under Node with stubbed host hooks and fed it data.

  • Braille bits are right. Dot rows bottom to top map to 0x40/0x04/0x02/0x01 on the left and 0x80/0x20/0x10/0x08 on the right. Each layer string sets only its own dot row, the floor layer draws only where a column is empty on the bottom line, and every layer has the same character count, so the ZStack lines up. The header puts the upper four heat colors on the top line.
  • History stays bounded. After 3,600 simulated ticks, no workspace holds more than 48 buckets. When the list went from 60 workspaces to 10, the 50 closed ones were dropped from history on the next tick. Backfill starts at the oldest column the window can show.
  • Reorder with BUSY on or with the 40-row cap is correct. I ran 13,626 drags across random filtered lists, and every workspace.reorder index put the row in the same visible position after the move. The command's index means the position after the move, which is what move() computes.
  • The validator's placeholder values are handled: pr: "", progress: "", color: "" and a string clock render an empty row instead of throwing. Unknown agent statuses fall back to the "none" state, and progress values above 1 are clamped.
  • It uses no timers. The spinner and sampling come from the clock data key, and sampling runs once per epoch second even when the workspaces key updates in the same second.
  • Cost per clock tick: about 2 ms for 10 workspaces and about 9 ms for 60 in Node. Most of that time was in the stub host and JSON. Only rows whose values changed produce updates, and the host skips props whose value didn't change.
  • The test's list of 19 names matches the 19 .js/.swift files in Examples/CustomSidebars. The new README and docs text has no em dashes and no internal names.

Fixed: nothing. I didn't find a correctness defect, so the head is still 4b86dd3.

Left:

  • In light mode, system yellow braille dots (the third dot row of each row graph and the middle band of the header) are faint on a white sidebar. Swapping the heat colors is a design call, so I didn't change them.
  • STATE.working.glyph is an empty string. It's never shown because working rows always use the spinner, but readers copying the file may find it confusing.
  • With more than 40 workspaces, ALL mode drops the extra rows silently. Only the "n/m busy" count shows that more exist.
  • The context menu shows a "No PR" item that does nothing when a workspace has no PR.

System yellow braille dots were faint on a white sidebar; the heat ramps
now go green to orange to red.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Follow-up on the review: the graph heat ramps no longer use yellow, which was faint on light sidebars (0e9f8c3). The other three notes stay as they are for now.

@cursor

cursor Bot commented Sep 28, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Repair head 18140bd135deb211f93c891e2ed1adce685e6323 is updated onto current main.

Evidence:

  • btop regressions: 5/5 pass
  • JavaScript syntax, registry (346 tests), guard workflow structure/wiring, and diff checks: pass
  • runtime harness with 1,000 workspaces: 20 clock ticks caused zero full-list selection recomputations
  • exact-head independent review: clean
  • exact-head autoreview: clean
  • no local cmux app build was run

Squash auto-merge is armed.

— Mochi

@teamleaderleo
teamleaderleo enabled auto-merge (squash) September 28, 2026 19:00
@teamleaderleo
teamleaderleo merged commit 03a30c0 into main Sep 28, 2026
71 checks passed
@teamleaderleo
teamleaderleo deleted the examples/btop-agent-sidebar branch September 28, 2026 19:21
@github-actions

Copy link
Copy Markdown
Contributor

Merge receipt for 18140bd135: every check was green at merge (20 verified; 19 skipped by policy). Full suite runs on main after merge.

github-actions Bot added a commit that referenced this pull request Sep 28, 2026
github-actions Bot added a commit that referenced this pull request Sep 28, 2026
github-actions Bot added a commit that referenced this pull request Sep 28, 2026
github-actions Bot added a commit that referenced this pull request Sep 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Dogfood tours of 18140bd1

sidebar-and-chrome-tour at 18140bd1, on its merge 84509753 that CI built: passed (run)

sidebar-and-chrome-tour at 18140bd1

Key frames of sidebar-and-chrome-tour at 18140bd 04-three-workspaces 10-split-right 15-command-palette 24-settings

Tours are picked by the paths globs in dogfood/scenarios/*.json; a Dogfood-tours: a, b line in the description picks them instead (none turns this off). Look at every frame before merging: a green tour only means no step failed.

github-actions Bot added a commit that referenced this pull request Sep 28, 2026
github-actions Bot added a commit that referenced this pull request Sep 28, 2026
rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 28, 2026
fc799b6 Merge project.pbxproj by union of added entries instead of by line (manaflow-ai#15419)
881de65 ci: reject masked Swift Testing failures (manaflow-ai#15425)
5410299 dogfood: make modifier-clicks-tour click on its own URL (manaflow-ai#15421)
03a30c0 Add btop-style agent activity sidebar example (manaflow-ai#15393)

# Conflicts:
#	.github/workflows/ci-guards.yml
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.

1 participant