Skip to content

LOCAL: add a gamified TeamClaude leaderboard section to the sidebar - #67

Merged
kiwidream merged 5 commits into
swaplabs/mainfrom
kiwidream/tcl-sidebar
Oct 28, 2026
Merged

kiwidream merged 5 commits into
swaplabs/mainfrom
kiwidream/tcl-sidebar

Conversation

@kiwidream

@kiwidream kiwidream commented Oct 28, 2026 •

Copy link
Copy Markdown
Files Added Deleted Net
Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​123 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​123
Prod 11 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​857 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​857

ELI5

The bottom of the left sidebar gets a small trophy row that shows where you stand in the team's TeamClaude token use today: "#3 of 6 today · 42.3M tokens · 6.6M behind #2". Clicking it opens the full board. It updates about once a minute, and it appears only on machines that run TeamClaude.

What Changed

The section sits directly above the settings/help toolbar. It lives in src/renderer/src/components/sidebar/teamclaude-leaderboard/, and sidebar/index.tsx gets a 2-line insertion.

Data

  • Polls getTeamClaudeLeaderboard(target) every TEAMCLAUDE_LEADERBOARD_REFRESH_MS (60s) through the existing installWindowVisibilityTimeoutPoller.
  • Pauses while the window is hidden and refreshes when it becomes visible again.
  • The target comes from useActiveAccountOwner, the same owner the status bar uses.

States

  • A result of null (an older or upstream runtime) or not-configured hides the section, with no console noise.
  • unavailable is a muted one-line row with the reason in a tooltip.
  • A failed refresh keeps the last board and marks it stale; it never shows zeros.
  • A request sequence drops replies that arrive after a newer request or after unmount.

Compact row

  • Trophy, rank and token count, plus the gap to the neighbouring rank, or "ahead" for the leader.
  • Ranks 1–3 get medal tints from existing tokens: gold is status-warning, silver muted-foreground, bronze workspace-status-done.
  • A rank change shows an up or down indicator for 8s, with motion-reduce:animate-none.

Board

  • An inline Collapsible that opens upward. Columns: rank, person, fresh tokens, output tokens. Your row is highlighted.
  • Each row's tooltip lists the TeamClaude clients merged into that person and their raw total.
  • Shows "Updated N minutes ago", from fetchedAt.

Other

  • The expanded state persists in localStorage, like the other sidebar flags.
  • 19 en.json keys, required by the localization gates.

This PR also carries the shared commit 20990ec7a6: the snapshot types (src/shared/teamclaude-leaderboard-types.ts) and the renderer client seam, which returns null until the data-service PR implements it. Until that PR lands, the section stays hidden.

Why

The operator asked for a gamified "you are #2" leaderboard of one-day TeamClaude token use, in the sidebar just above settings/help. It updates live-ish, a person's several minidevs count as one score, it reads only existing endpoints, and it is fork-only.

Fresh tokens (input + output + cache writes) are the ranking metric because cache reads make up about 98% of the raw total. Raw totals would mostly rank context length rather than work.

Linked Issue

N/A: operator request in session. Follow-ups:

  • the data-service PR (to follow);
  • a mobile equivalent: there is no sidebar on mobile, and the closest surface is mobile/src/home/MobileHomeAccountUsageCards.tsx.

Visual Proof

The component fixture was captured with pnpm fixtures:shot 'sidebar/teamclaude-leaderboard/*' --theme both --scale 2 at 280px and 220px sidebar widths. It covers 10 states in light and dark themes: leader, leaderExpanded, midPack, midPackMinWidth, midPackRowTooltip, rankUp, rankDown, stale, notRanked and unavailable. The images are on minidev-alex1 and not attached here, because no image-upload tool is available on the VM. I can add them on request. A capture in the integrated app will follow once the data service lands.

At 220px only the compact row's gap text truncates ("6.6M behi…").

Testing

  • pnpm check:changed --maxWorkers=2 --base=refs/remotes/swaplabs/swaplabs/main passed 24/24 checks on 12 files, in the worker's run.

  • The guard test passes 2/2: an out-of-order target switch, and staleness on a read failure. With the sequence check removed, the out-of-order test fails as intended.

  • Coordinator re-run after opening: pending, posted as a comment when done.

  • I manually tested these changes locally (component fixtures; integrated-app check pending the service)

  • Automated tests added/updated, or explained why not below

AI Disclosure

Prepared by Claude Code (Claude Opus 5.5) at the operator's request.

Review

Opened at the operator's request to "open PRs asap and run tests after". The local review and a coordinator test run come after opening.

Agent skill upstream boundary

  • Not applicable: fork-only renderer UI; no agent skill.

Notes

  • Security: no secrets reach the renderer. The service, coming in a separate PR, returns only names, ranks and counts.
  • Cross-platform: renderer-only.
  • Remote and SSH: uses the existing runtime-client target. An older runtime returns null, which hides the section.
  • Mobile: follow-up.
  • Backward compatibility: hidden everywhere TeamClaude isn't configured.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason: fixture captures are listed above; image files available on request
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred): the worker's check:changed passed; the coordinator re-run and the full build follow

🤖 Generated with Claude Code


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

kiwidream and others added 2 commits October 27, 2026 16:34
…nt seam

Shared surface for the sidebar leaderboard: the snapshot the runtime host
serves from the coordinator's existing /teamclaude/status, and the renderer
client the sidebar calls. The client returns null until the service lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Polls getTeamClaudeLeaderboard from the focused workspace's account owner
(as the status bar does) while the window is visible, refreshing on
visibility and focus. A null or not-configured result hides the section.
The compact row shows rank, fresh tokens and the gap to the neighbour,
with medal tints for ranks 1-3 and a brief rank-move indicator; it expands
upward into the full board, whose state persists in localStorage. A
request sequence drops replies from a previous target or an unmounted
section, and a failed read marks the last board stale instead of
clearing it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-28T15:10:40.477403Z 4323c9f Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Resolve the en.json conflict by keeping both the leaderboard keys and the keys from sync #64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

<TooltipContent side="right" sideOffset={8} className="max-w-64">
{entry.clients.map((client) => (
<div key={client} className="break-all">
{client}
</div>

P1 Badge Use a HoverCard for the leaderboard row details

When the board is rendered, this tooltip contains a client list and additional usage statistics rather than a control label. AGENTS.md requires following docs/STYLEGUIDE.md, whose component rules explicitly reserve Tooltip for naming controls and require HoverCard for rich hover previews. Replace the row's Tooltip with the existing HoverCard primitive so this new surface follows the documented component contract.

AGENTS.md reference: AGENTS.md:L10-L10


<TooltipContent side="top" sideOffset={4} className="max-w-64 break-words">
{message}
</TooltipContent>

P1 Badge Display the unavailable reason inline

For an unavailable snapshot, the visible row only says “Leaderboard unavailable”; the actual failure reason is accessible only by hovering or focusing it. AGENTS.md mandates the style guide, which explicitly prohibits putting errors in tooltips and requires persistent errors that users need to read or act on to appear inline. Render message in the unavailable state itself rather than hiding it behind the already-labeled row.

AGENTS.md reference: AGENTS.md:L10-L10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…le reason inline

The style guide reserves Tooltip for naming controls and keeps errors users must read inline (Codex review on #67).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kiwidream

Copy link
Copy Markdown
Author

Both Codex findings on cf6f09a are addressed in b54be75:

  • HoverCard for row details: the board row's client list and raw total now use the HoverCard primitive instead of Tooltip. It still opens on focus for keyboard users. The fixture midPackRowTooltip is renamed midPackRowDetails.
  • Unavailable reason inline: the unavailable state now shows the failure reason inline under "Leaderboard unavailable", with no tooltip. The line is no longer focusable, since nothing is hidden behind it.

Re-captured both states with pnpm fixtures:shot. The head also includes the merge of swaplabs/main (847f919), which resolves an en.json conflict with sync #64, and the localization catalog checks pass.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: b54be756de

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

HoverCardContent owns its spacing and typography; the changed-code quality gate refused the p-3 and text-xs overrides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kiwidream

Copy link
Copy Markdown
Author

CI's changed-code quality gate refused p-3 and text-xs on <HoverCardContent>, because the primitive owns its spacing and typography. 4323c9f drops the overrides and uses the default variant. The local gate passes and the fixture is re-captured.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 4323c9f069

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@kiwidream
kiwidream merged commit 5332f1d into swaplabs/main Oct 28, 2026
42 checks passed
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