• Home
  • News
  • Blog
  • Releases
  • LLM history
  • Compare LLMs
  • Library
  • About
⌘K
Sign in

A blog and notes on development. The easiest way to reach me is via the social links below.

Contacts
talalaev.misha@gmail.com
Documents
Personal data processing policyPersonal data processing consent

Claude Control Bar: Why I Created My Own Menu Bar for Claude Code

Sh0ny
Sh0ny
5 августа 2026
  1. Home
  2. Blog
  3. Claude Control Bar: Why I Created My Own Menu Bar for Claude Code
6 min read

In short

How I Came to Write My Plugin While Solving My Own Problems

I spend almost the entire day working in Claude Code, usually in several sessions at once. There’s a practical problem with this setup: the terminal is minimized, the window is covered by the editor, and the desktop app doesn’t show the status bar at all. Claude is doing something in there. Or he’s been waiting for a minute for me to give him a command. Or he’s finished with the context window and started to forget the beginning of the conversation. You can’t see anything from the outside. The second pain point is the MCP servers. A crashed server looks exactly like an unconfigured one: its tools silently disappear from the list, without a single error message. You only find out about it in the middle of a task, when the agent suddenly “forgets” how to do what it could do yesterday. And the third little thing that’s annoying: limits. The five-hour and weekly windows coexist in the command /usage — to find out how much time is left, you have to go and ask. I wanted a single, improved status bar—but not inside the terminal, rather above it: showing session status, MCP, and limits. There wasn’t a ready-made solution like that. Here’s what came of it: Claude Control Bar. At first, there were two apps Mika Cesanek’s claude-status-bar was already in my menu bar: the icon animates while Claude is working, a yellow dot appears when he’s waiting for permission, and there’s a running timer next to it. It’s a nice tool—I enjoyed using it. But it doesn’t show anything about MCP or limits, and that’s exactly what I needed to check most often. So, I first wrote a separate plugin for MCP—`claude-mcp-bar`. It showed all configured servers, indicated whether each had responded to a check, and provided toggles: one for the entire server and one for each tool individually. The toggles had a nice side effect: when a tool is turned off, it disappears entirely from the context; Claude Code doesn’t even load its description. So the toggle also clears the window of tools you aren’t using in this project anyway. Two adjacent icons split a single task in half. I forked the status-bar and moved the MCP layer from my plugin into it—the result was the Claude Control Bar. It has its own name and bundle ID, and it doesn’t interfere with its parent’s settings. From the first—sessions, animations, and the lifecycle; from the second—MCP, context measurement, and limits. What’s in the menu Sessions. Each row represents a project and branch, a live timer, a CLI or APP label, and the context window’s fill percentage. Clicking a row brings up the terminal for that session. The percentage took some work to implement. Claude Code only returns this value in statusLine, and the desktop app statusLine never runs—so for it, the figure is recalculated from the session transcript using the same formula that the CLI itself uses. Window sizes aren’t hardcoded but are parsed from the installed binary claude: a hardcoded table would become obsolete with every release. This doesn’t always help: the transcript might mention a model that isn’t in the binary. In my case, Claude Code 2.1.205 recognizes claude-opus-4-8, but the transcripts say claude-opus-5. Before the fix, a session with 154,000 tokens showed 77% of the window occupied when it should have been a mere 15%. Now, an unfamiliar name takes the widest window in its family and is marked with a tilde, and the size, once seen in a live statusLine, is remembered permanently. MCP. Servers are grouped by configuration location: global config, claude.ai connectors, plugins, project file .mcp.json. Each has a status, an “enabled/total” counter for tools, and a toggle switch; the list of tools opens in a submenu from the same line, and hovering over an item reveals its description and parameters. The line changed: lists what has changed since the last check, and a notification is sent if a server goes down—exactly the scenario this whole system was designed for. Health checks, by the way, are resource-intensive: claude mcp list it actually starts up every configured server and waits for a response; for me, this takes about half a minute. That’s why it runs when you click the toggle switch, every ten minutes via a timer, and when you open the menu if the image has been there for more than two minutes—but not every time you glance at the icon. Limits. The five-hour and weekly windows are shown as two mini-bars right in the menu bar; the menu itself displays percentages and reset times. The data is retrieved from the same Anthropic endpoint that queries /usageevery five minutes, using an OAuth token from Keychain; the token is read locally and is only sent to api.anthropic.com. The endpoint is undocumented—that’s just how all utilities in this niche operate—but for those who don’t like the gray area, the polling feature has a toggle in the options, and the section will honestly report that no data is available. Three Stories from the Development Process The most unpleasant discovery concerned the security of project servers. An early version would read .mcp.json directly from the repository and ran the commands listed there itself during the check. All it took was to clone someone else’s repository and open Claude Code in it—and that person’s command would have been executed during the next health check, bypassing all approvals. I patched the vulnerability in 0.5.0, and in 0.5.1 I fixed it properly: the application doesn’t run anything from the project config at all—it queries Claude Code itself (claude mcp list in the project folder) and accepts its response as-is. The decision of “what can be started” remains with your approval process. The second issue is about concurrent clicks. Each switch toggle is a separate process; two simultaneous clicks would read the same settings.json, and the second write overrode the first. In testing, one of the changes was lost in 43 out of 50 runs. Now the entire read-modify-write operation holds an exclusive file lock: 12 parallel toggles mean 12 changes survive, and this has been verified by a test that runs real processes, not mocks. The third issue is a minor one: the menu bar is a harsh environment. There’s room for about 772 pixels near the top bar, and any menu item that doesn’t fit isn’t truncated—it simply moves below the bar and disappears. It looks like an app bug, but it’s just macOS. For cases like this, there’s CONTROL_BAR_DUMP_MENU=1 — it displays the menu as text, so you don’t have to hunt for an item hidden off-screen. How to install Two ways. As a Claude Code plugin: /plugin marketplace add InfinityScripter/claude-control-bar, then /plugin install claude-control-bar. The app will be built on your Mac the next time you start a session (you’ll need Xcode Command Line Tools); Gatekeeper isn’t involved in the process, and updates come along with the plugin. The second method is via a DMG from the releases: it’s not notarized because the fork doesn’t have an Apple Developer ID, so you’ll need to allow the first launch by clicking “Open Anyway”—details are in the README. The code is open source under the MIT license. Special thanks to Miku Cesanek: without claude-status-bar, this fork wouldn’t exist. I built it to cover my three blind spots—status, MCP, and limits. If you have the same ones, feel free to grab it.

TechnologyEnvironmentalEducation
More AI-tool write-ups on the Telegram channel — short and to the point
Subscribe on Telegram

Comments

(0)
​