Skip to content
CLEPSOdocs

Docs / Architecture

Architecture

A native macOS menu bar app (Swift 6, SwiftUI) that reads what Claude Code already reports about itself, on your Mac. It works fully without an account; signing in is optional and uploads daily counts only (see Privacy).

On this page

A reading's path

Six layers, bottom to top. Point at a step to light its layer.

  1. 01
    Claude Code · Status lineRuns your status line command on every refresh and hands it a JSON description of the session.
  2. 02
    Helper · statusline.sh · clepso-statuslinePasses the input to your own status line unchanged, keeps only allowlisted fields, sends them on.
  3. 03
    Ingest · Socket · IngestorLocal socket, peer checks and a rate limit; each frame becomes readings with source and freshness.
  4. 04
    Store · SQLite · UsageEngineOne transaction per frame: insert the reading, work out each limit's state, keep the history.
  5. 05
    Show · Menu bar · DashboardRenders snapshots it is handed and never computes a state itself.
  6. 06
    Sync · Optional, if you sign inUploads daily counts once an hour; the only module allowed to use the network.

Processes

ProcessRole
Clepso.appThe menu bar app. Listens on a local socket, keeps readings in a local database, works out each limit's state and shows it. If you sign in, it uploads daily counts once an hour.
clepso-statuslineA small signed helper inside the app that Claude Code runs on every status refresh. It passes the input to your own status line unchanged, keeps only allowlisted fields and sends them to the app. It links no networking at all.
hook.sh (optional)Installed only when you turn on agents per task. Claude Code runs it in the background on four events; it runs the helper in hook mode, which sends counts only and always exits silently, so it can never block or change what Claude Code does.
statusline.shThe installed command. Runs the helper if the app is there, otherwise your original status line, so removing the app never breaks Claude Code.

Data flow on the Mac

Claude Code ──stdin JSON──► statusline.sh ──exec──► clepso-statusline
                                                      │  allowlist (ShimProtocol)        │ raw bytes
                                                      ├──► frame ──► run/agent.sock       ▼
                                                      │                              /bin/sh -c <original command>
                                                      └──◄ stdout + exit status ◄─────────┘
                                                                     │
                                                                     ▼ (verbatim to Claude Code)

Clepso.app
  IngestSocket (actor) ──AsyncStream<ShimFrame>──► Ingestor (actor)
      │ accept, peer checks, rate limit, decode        │ parse, HMAC session id, Observation
      ▼                                                ▼
  connector_health                          Store (actor, one transaction per frame)
                                              insert observation
                                              reduce (UsageEngine) ──► pool_snapshots, events
                                              Scheduler.candidates(events) ──► notification_receipts
                                                      │                              │
                                   ValueObservation   ▼                              ▼
                                   OverviewSnapshot ──► @MainActor view models   NotificationDispatcher ──► UNUserNotificationCenter
                                                          MenuBarExtra popover · provider detail · provenance inspector · settings

Modules

ModuleResponsibility
DomainValues that carry where they came from and how fresh they are, so a missing number can never show as 0%.
ShimProtocol · StatusLineShimThe frame format and the allowlist; the helper's logic.
ClaudeCodeAdapterSocket ingest, mapping frames to readings, the settings and hooks installers, the statistics-file reader.
UsageEnginePure rules: limit states, windows, freshness, the pace estimate.
StorageSQLite (GRDB): one writer, a ledger of readings, migrations with a backup first, retention.
SyncOptional sign-in by email link and the hourly upload of daily counts. The only module that may use the network, and only the app imports it.
DesignSystemTokens, themes (Phosphor dark and light), pixel glyphs and components, accessibility formatting.
ClepsoAppThe app: menu bar panel, Dashboard (Home, Limits, Session, Stats, Goals, Account, Settings), onboarding, diagnostics.
SubscriptionCatalogPlan names, never used to infer usage.

Principles

Local first

Everything works on your Mac without an account. Network code lives only in Sync, used only after you sign in.

Allowlist at the source

The helper drops everything not on the allowlist before sending, so the app cannot receive what it must not keep.

Absent is not zero

A limit the source did not report is shown in words with an empty outlined bar, never as 0%.

Reversible

Installing into Claude Code backs up your settings; uninstalling and delete-all restore them byte for byte.

Quality gates

One command, make ci, runs every gate and must pass before each increment is committed. The list below is read from scripts/ci.sh.

GateWhat it checks
Toolchain pinnedThe expected Swift version.
Strict build (warnings=errors)Warnings are errors; Swift 6 strict concurrency.
TestsThe full suite (Swift Testing).
Helper links no networkingThe helper binary links no networking frameworks.
Release build has no debug code
Networking only in SyncNetworking APIs appear only in the Sync module, and only the app imports it.
Clock injectedLogic reads time through an injected clock, so tests control it.
Design tokens onlyViews use theme tokens and pixel glyphs, never literal colours, sizes or system symbols.
Motion through tokens
Keyboard reachable
Redaction auditLogs and exports contain no fields outside the allowlist.
Secret scanNo credentials in the repository.
No committed accounts project
Email templates
App bundleSignature, embedded helper, entitlements, URL scheme.
Relevant source files
  • scripts/ci.sh
  • docs/ARCHITECTURE.md