Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CCrab

A native macOS desktop companion for Claude Code — a pixel crab that lives on your desktop, reacts to what your agent sessions are doing, and keeps your usage limits one glance away in the menu bar.

Written in Swift against AppKit and Core Animation. No Electron, no WebView.

Why native

Measured on an M-series Mac, idle and while playing a 60-frame sprite loop:

CPU Memory
Resting (vector idle) 0.0% 42.7 MB
One sprite animation playing 0.0% 43.2 MB
After cycling five states 0.0% 86.9 MB

CPU stays at zero regardless of what is on screen. Memory is the real cost: each 302×300 sprite is ~360 KB per frame over 45–90 frames, so a decoded animation is ~15 MB. AnimationCache keeps at most three and evicts the rest, which is what bounds that last row — and the cache is purged entirely whenever the renderer parks.

The zero-CPU figure is not an accident of measurement — it falls out of three decisions:

  1. Every animation is a Core Animation animation. Sprite playback is a CAKeyframeAnimation over contents with discrete timing. The render server owns the timeline, so this process gets no per-frame wakeups: no timer, no CADisplayLink, no draw loop.
  2. The resting crab is vector, not bitmap. The source sprites are pure axis-aligned rects on a pixel grid, so VectorSprite parses them straight into CALayers. Breathing, blinking and cursor-following are layer transforms. No GIF decode, no texture memory, crisp at any size.
  3. Invisible means stopped. When the panel is occluded, the display sleeps, the screen locks, or the crab falls asleep, animations are removed and the decode cache is purged — not merely paused.

Everything upstream of the renderer is event-driven too. State arrives over a loopback HTTP endpoint from Claude Code's hooks; nothing polls.

Install

Requires macOS 14+ and a Swift 6 toolchain (Xcode 16+).

./Scripts/fetch-assets.sh && ./Scripts/build-app.sh && open dist/CCrab.app

On first launch CCrab offers to connect itself to Claude Code. That writes hook entries into ~/.claude/settings.json; see Connecting for exactly what it touches.

What it does

On your desktop. A borderless, non-activating floating panel — clicking the crab never steals focus from your terminal. Drag it anywhere; it remembers. Right-click for settings. Poke it a few times and it will get progressively less amused.

In your menu bar. A live glyph for the current state, your 5-hour usage percentage inline, and a menu with:

  • 5-hour and weekly usage bars with reset countdowns, colour-coded past 60% / 85%
  • every live session — project, model, current state — click to open its folder
  • recent projects, read from the ~/.claude/projects directory Claude Code already maintains
  • connect / disconnect the Claude Code hooks
  • show/hide the crab

Reactions. 49 clips wired to the state machine. Beyond the plain state map, selection is context-aware:

Signal Result
Bash / BashOutput debugger pose
Write / Edit hard hat
WebSearch / WebFetch thinking
Workflow wizard
2 live sessions headphones
3+ live sessions building
1 subagent headphones groove
2+ subagents three-ball juggling
Permission prompt alert pose + sound
PreCompact sweeping
90s quiet sleeping, and the renderer parks

The resting pose also rotates every couple of minutes through reading, dozing, coffee and others, so the crab never looks frozen.

Connecting

Connect edits ~/.claude/settings.json. It is written to be safe on a config you already care about:

  • a timestamped backup is copied to ~/.ccrab/backups/ before any change
  • existing hook entries for other tools are preserved; ours are appended
  • an existing statusLine is chained, never replaced — CCrab's shim runs first, forwards the payload, then executes your original command and passes its stdout through untouched
  • Disconnect removes only entries tagged as ours and restores the statusline it wrapped

The shim (~/.ccrab/bin/ccrab-hook.py) is deliberately defensive: every failure path exits 0 with empty output, and if CCrab is not running it is a ~15 ms no-op. It refuses to post to a port whose recorded owner pid is dead, so a stale ~/.ccrab/runtime.json can never redirect your hook traffic somewhere else.

Usage numbers come from Claude Code's statusline payload (rate_limits), which carries the Pro/Max window percentages directly. No extra API calls are made and no token is ever read.

Architecture

Claude Code hook  ──POST /state──▶  HookServer (127.0.0.1:45820)
                                        │
                                        ▼
                                  SessionRegistry  ── derives one state from N sessions
                                        │
                          ┌─────────────┴─────────────┐
                          ▼                           ▼
                    CrabRenderer                StatusItemController
              vector idle · GIF states           glyph · quota · sessions
                          ▲
                    PowerGovernor  ── occlusion · display sleep · lock · battery
Path Role
State/ state model, event mapping, multi-session derivation
Bridge/ loopback HTTP endpoint, ~/.ccrab/runtime.json
Render/ SVG rect parser, GIF decoder, clip catalog, renderer
Window/ non-activating panel, drag/poke handling
Integration/ settings.json installer, Claude app watcher, recent projects
Energy/ when the crab is allowed to animate
Debug/ --audit and --dump offline render checks

Diagnostics

./.build/debug/CCrab --audit

Lists every clip and whether its assets resolve.

./.build/debug/CCrab --dump clawd-typing /tmp/out.png

Renders a clip through the live code path and writes a PNG — no screen-capture permission needed.

Artwork

The sprites are not part of this repository and are not redistributable.

Clawd is Anthropic's character. The pixel art is fan-made by the clawd-on-desk project and is published All Rights Reserved, explicitly non-commercial. Scripts/fetch-assets.sh downloads it from upstream into your working copy for personal use; .gitignore keeps it out of the repo, and no build containing it should be distributed.

Anthropic enforces the Clawd trademark — the Clawdbot project was required to rename to Moltbot in January 2026. If CCrab is ever to be released rather than run locally, it needs its own original character. The renderer is asset-agnostic by design: an alternative sprite set is a directory swap, not a refactor.

License

Source code: MIT. Artwork: not covered — see above.

About

Native macOS desktop companion for Claude Code — a pixel crab that reacts to your agent sessions. Swift, AppKit, 0% idle CPU.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages