Grok Bot Gets a Menu-Bar Skin Tool: CDP CSS Injection Keeps the Official .app Intact
Give Grok Bot on macOS a New Skin
I've been using the Grok Bot app recently, and it's pretty good. But the window is always black/white, a bit monotonous; and the subscription usage is tucked behind a secondary entry. One time an accidental loop task caused an overage.
Based on that, I built a skin tool: Grok Bot Skin .
Switch skins from the menu bar, preview and export/share in the skin studio, and keep the sidebar showing the current period's subscription used / remaining percentage.
Repo: https://github.com/Yellow5A5/Grok-Bot-Skin
Everything runs locally on the user's machine. It uses CDP to apply CSS overlay skins, does not modify the official Grok Bot.app, and does not upload conversations, accounts, or credentials.
Effects
Ink Night, Jade Grove (select Appearance Dark):
Leaf Warm, Avenger Neon (Leaf Warm uses Light, Avenger Neon uses Dark):
Straw Sea (Light):
Menu bar:
Skin studio:
You can also make your own package and export .grokskin.zip to share.
Installation
This machine needs:
- macOS 13+
- Node 22+
- Xcode Command Line Tools (used to compile the menu bar with
swiftcon first run) - Grok Bot already installed in
/Applications
The script won't install these. Once the environment is ready:
curl -fsSL https://raw.githubusercontent.com/Yellow5A5/Grok-Bot-Skin/main/scripts/install.sh | bash
It copies the tool to ~/Library/Application Support/grok-bot-skin/app, compiles the menu bar, opens Grok Bot, and applies the last-used skin. If you already have the repo directory, running ./scripts/install.sh does the same.
After installation, a palette appears in the menu bar. Click a skin name to switch; language can be switched between English and Chinese.
Technical principle
Grok Bot is a Developer ID-signed and notarized Electron app, and its package includes ElectronAsarIntegrity. Modifying the asar or resources inside /Applications/Grok Bot.app breaks the integrity check, and the next official update will also overwrite them. So this tool is a companion program that runs alongside, without touching that .app.
Skinning works in three steps.
1. Launch with a local debug port
The menu bar opens Grok Bot through the official app's own entry, only passing one extra argument:
--remote-debugging-port=19222
That is the Chrome DevTools Protocol (CDP) for Chromium/Electron. The port is bound to 127.0.0.1, not 0.0.0.0, so it is not reachable from the LAN. The tool finds the window via http://127.0.0.1:19222/json/list, then sends Runtime.evaluate over WebSocket.
If the app is opened from the official Dock and "follow" is enabled, and the current launch did not include the port, the menu bar will quit and reopen it with the port. If follow is off or the menu bar is not running, it is the original window with no skin.
2. Compile the skin into CSS and inject it into the current page
A skin is a folder: skin.json plus wallpaper/cover. Colors are written as tokens (foreground, window background, sidebar, chat surface, accent color) and compiled into an override CSS. The wallpaper is drawn on the window's real opaque layer .sand-shell, and the chat area stays transparent so the image shows through.
Injection inserts just one <style> and uses JSON.stringify to put the CSS into textContent; user strings are never concatenated into JS. Within the current session you can use Page.addScriptToEvaluateOnNewDocument to apply the same styles to newly opened pages. Once the process exits, the styles are gone; next time the menu bar launches with the port and injects again.
3. The menu bar is Swift, the work is done by local Node
The menu bar Extra (LSUIElement) only handles the menu and login item. Clicking a skin, opening the studio, or reading status all execute node bin/cli.mjs locally. The skin studio listens on http://127.0.0.1:4177/, also not exposed to the internet.
The last-used skin, language, and whether to show usage are written to:
~/Library/Application Support/grok-bot-skin/
Imported packs are also under packs/ there. The official Grok Bot data directory is not modified.
Subscription usage
The sidebar card reads interfaces that already exist in the Grok Bot window, for example window.desktop.main.getCursorUsageSummary, getCursorUsageBreakdown, getCursorWeeklyUsage, getCursorAuthStatus. When an interface only gives a subscription percentage, it shows the used/remaining amount for the current period.
These numbers are only drawn on the local sidebar and are not sent to any server.
Privacy
This tool has no account system, no remote backend, and no analytics/reporting.
| Data | Does it leave this Mac |
|---|---|
| Conversations, sidebar session names, input boxes | No. The tool does not read, store, or transmit them. |
| Grok / Cursor login state, cookies | No. It does not read the official data directory, and does not forward requests. |
| Subscription usage, tokens | Only read in the local renderer process and drawn on the sidebar. |
| Current skin, language, whether to show usage | Only written to the local Application Support/grok-bot-skin/ |
| Wallpapers and covers | Only appear as file:// in the local window |
The debug port listens only on 127.0.0.1. The skin studio listens only on 127.0.0.1. The repo and install script do not contain Grok Bot.app, and do not require putting the official app into git.
A .grokskin.zip from someone else can contain CSS. Only import packs you trust.
Notes
Welcome to try it, share a skin of your own, or see if there are pain points worth expanding: https://github.com/Yellow5A5/Grok-Bot-Skin