Skip to content

The bar (sill)

sill replaces the macOS menu bar with SketchyBar — a fully scriptable status bar tuned to the nebelung palette and wired to your tiling. When sill is on, the native menu bar is hidden so the bar is the single source of glanceable state.

Left — workspace pills. One pill per workspace in your app roster. A pill shows either its workspace letter or the app’s bar icon (e.g. :slack:), and the focused workspace is highlighted. The front app’s title sits alongside.

Right — the status cluster (on by default, each one hideable):

  • Clock and battery
  • Wi-Fi state
  • Weather — a compact pill that opens a full popover on click
  • Media — the currently-playing track, scrolling

Any of these five can be switched off individually — see Toggling bar items below.

The pills react live: switch workspaces and the highlight follows; tap the Caps-Lock leader and the whole bar flips into launcher letter-mode.

Click the weather pill and a popover blooms open with the full picture: location, condition, current and feels-like temperature, sunrise/sunset, wind, humidity, UV, an hourly strip, and a three-day forecast. It’s one of the bar’s nicer flourishes and a good demo of what SketchyBar can do.

Every right-side pill is a single boolean in nebelhaus.sill.items. The five core pills (clock, weather, media, battery, wifi) default on; the extras below default off. Set only the ones you want to change:

nebelhaus.sill.items = {
weather = false; # drop a default-on core pill
cpu = true; # add an off-by-default readout
caffeinate = true; # add the keep-awake controller
};

A pill set false is never created — its update script doesn’t even run.

Extra readouts — harmless anywhere, just off so the default bar stays quiet:

  • cpu — total CPU load, as a percentage pill.
  • memory — memory-pressure percentage pill.
  • volume — output volume / mute state.
  • calendar — your next timed event, with a click-popup of the next five. Pulls in ical-buddy automatically and reads Calendar, so macOS prompts for Calendar access on first run.
  • caffeinate — a coffee pill for preventing idle system sleep. Click it to choose 1, 2, 4, or 8 hours, enter a custom number of hours, keep the Mac awake until stopped, or allow sleep again; right-click stops immediately. While active, the pill shows the time remaining. The assertion is owned by launchd, not SketchyBar, so it survives a bar reload and resumes with the correct remaining time after a rebuild or login. It uses macOS’s built-in caffeinate—no package or permission prompt. The display can still turn off, and closing a MacBook lid still sleeps it.

The same keep-awake engine is available without the pill:

Terminal window
awake 3h
awake 90m
awake indefinitely
awake status
awake off

Personal extras — each targets one person’s hardware, service, or workflow:

  • agents — a paw pill tracking your agent-worktree panes: amber when one is waiting on you, click for the per-agent list, click a row to jump to its pane. Each row is marked with the client sitting in it (Claude Code, Codex, Opencode), painted in that pane’s state colour, and a row clears itself once its pane is gone — however the agent ended. Dormant until a client’s hooks fire, so it’s harmless if you don’t use agents. The same state also shows up inside the terminal: a count badge beside the zellij tab name of whichever tab holds agent panes — see Coding agents.

  • aiUsage (was claudeUsage, still accepted) — a gauge pill showing how much of your AI usage you’ve spent: a percentage for subscription limits (Claude Code, Codex), or the day’s dollars for token-billed Opencode. It follows whichever provider reported most recently, showing the higher of the 5-hour or weekly window and colouring to match (green under 50%, yellow past 50%, peach past 75%, red at 90%). Click it for every provider’s windows with their reset times.

    Where each row comes from matters, because one of them leaves the machine:

    • Claude Code rides its own statusline feed. Nothing is polled and no token is read, so the row appears once a Claude session first reports and greys out if none has in half an hour.
    • Opencode is read straight out of its local sqlite db. Also no network.
    • Codex is the exception. It keeps no usage data on disk at all — the desktop app holds threads server-side, and only the CLI and the VS Code extension ever wrote rate limits locally — so a disk-fed row silently freezes the day you switch to the GUI app. That row is polled from your ChatGPT account instead (limits are per account, so it counts GUI usage too), authenticated with the OAuth token already in ~/.codex/auth.json. The refresher renews that token when it nears expiry and rewrites the file in place, keeping a .bak. If you’ve never logged into Codex on this machine, no call is ever made — the presence of auth.json is the entire opt-in.

    Claude’s row is pushed by its statusline; the Codex and Opencode rows are pulled, and the pill pulls them itself every few minutes. That matters if you don’t use Claude: those two rows used to move only while a Claude statusline was rendering somewhere, so on a Codex or Opencode machine the pill would grey out and stay grey.

  • elgato — a pill that toggles an Elgato Key Light on your local network.

  • harvest — a Harvest time-tracking pill. It reads credentials from a file you provide at ~/.config/sketchybar/harvest_secrets.sh.

The hush (Do-Not-Disturb) pill is separate: it rides nebelhaus.hush.enable, not sill.items.

nebelhaus.sill.enable = false;

With sill disabled, the native macOS menu bar is shown again (the rice only hides it when sill is on). Tiling and the rest of the rice are unaffected.

sill is generated entirely from your config. On rebuild it writes ~/.config/sketchybar/ — the main sketchybarrc, a colors.sh exporting the nebelung palette as 0xAARRGGBB values, a workspaces.sh built from your app roster, and a plugins/ directory of small shell scripts (one per bar item). The palette and your roster are the single sources of truth, so the bar always matches the rest of the system.