Pitwall: an always-on-top note showing your Claude Code, Codex and Antigravity plan limits, cost, context windows and live agents. Native macOS and Windows, no dependencies, no telemetry.
C#
0
28 commits
updated Sep 18, 2026
See how much of your AI coding plan is left, and what every agent is doing, without leaving your editor.
Pitwall is a small always-on-top note for people who work with Claude Code, Codex and Antigravity. It shows your plan limits and when they reset, what the provider says you have spent, how full each agent's context window is, and a live tree of every running agent and sub-agent. It appears when you open one of those tools and goes away when you close the last one.
Native macOS app (Swift) and native Windows app (C#/WPF). No Electron, no Python, no third-party packages, no telemetry. MIT licensed.
Demo mode (--demo), so every state is on screen at once. Real accounts look the same.
claude, codex or agy session is a small ghost acting out its real state: working,
thinking, using a tool, waiting for you, rate limited, done. Sub-agents hang under the session that launched them.You need the CLIs you already use to be signed in (claude, codex login, agy). Pitwall has no login of its own: it
reads the sign-ins those tools created, read-only.
Download it. Get the installer for your computer from the
latest release: Pitwall-Setup-…-x64.exe for Windows (-arm64 for
Windows on ARM), Pitwall-….dmg for macOS 14 or newer. The builds are not code signed, so the first launch needs one
extra click: on Windows More info > Run anyway, on macOS System Settings > Privacy & Security > Open Anyway.
Or build it yourself, which takes about a minute and is how you avoid those warnings.
macOS (14 Sonoma or newer, with Xcode or xcode-select --install):
git clone https://github.com/Emip159/pitwall.git
cd pitwall/macos
./build-app.sh && cp -R build/Pitwall.app /Applications/
open /Applications/Pitwall.app
macOS asks whether Pitwall may read the Claude Code-credentials Keychain item, once per Claude sign-in. Choose Always Allow.
Windows (10 or 11, with the .NET 10 SDK: winget install Microsoft.DotNet.SDK.10):
git clone https://github.com/Emip159/pitwall.git
cd pitwall\windows
powershell -ExecutionPolicy Bypass -File .\build.ps1
.\publish\win-x64\Pitwall-Setup.exe
The Setup window installs for your user only (no administrator rights) and can start Pitwall when you sign in. The
-ExecutionPolicy Bypass applies to that one command: Windows refuses to run any script by default.
Then just work. Open claude, codex or agy in any terminal and the note appears on its own.
| You want to | Do this |
|---|---|
| Check your limits with no tool open | Click the ghost icon in the menu bar (macOS: Show Note) or the tray (Windows: left-click) |
| Put the note away for now | The ✕ in its corner. It comes back with the next tool you open |
| Move or resize it | Drag it, or drag any edge. It remembers where you put it |
| See an agent's task, model, context, tools and cost | Click its row |
| See plan details for an account | Click the card's name |
| Change theme, size, compact mode, accounts | Right-click the note, or open Settings from the icon |
| Try it without any account | Run it with --demo |
Is it safe to run? It reads the same local sign-ins your CLIs use and sends them only to the provider that issued them. The hosts are on a fixed allowlist, redirects are refused, nothing is written back, and there is no telemetry or update check. Security and privacy has the short version and SECURITY.md the whole boundary, including what it does not protect you from.
![]() Compact layout, six accounts | ![]() macOS, one column, an agent's details open |
![]() Light | ![]() Sticky note | ![]() Glass |
The rest of this page is reference. Everything above is enough to install and use Pitwall.
You are deep in a Claude Code session and you want to know, without breaking flow, whether you are about to hit your weekly limit. That is the whole idea. The note floats above your editor and answers it.
Plan limits and resets
~/.claude,
~/.claude-personal and ~/.claude-work.agy), the 5-hour and weekly limits for Gemini models and for Claude and GPT
models. Through the Gemini CLI, the Workspace / Code Assist quota.Cost
Live agents
Every running claude, codex or agy session appears as a small ghost that acts out its real state: working,
thinking, using a tool, needs you, done, rate limited, error, queued or idle. Claude Code sub-agents appear as a
tree under the session that launched them, with their task, model, context, tool calls and result on demand. A Pac-Man
on each card eats through your quota as you use it.
Context window
How full each agent's context is, taken from the tokens of its latest request. Claude Code does not record the window size, so the maximum is assumed per model and labelled as such. Codex reports its own.
| macOS | Windows | |
|---|---|---|
| To run | macOS 14 Sonoma or newer | Windows 10 or 11, x64 or ARM64 |
| To build | Xcode, or the command line tools (xcode-select --install) | .NET 10 SDK (winget install Microsoft.DotNet.SDK.10) |
| Dependencies | None | None |
Installers for both platforms are attached to every release, built by
GitHub Actions from the tagged commit, with SHA-256 checksums. Building it yourself takes about a minute. Either way the
Windows exe is self-contained, so the PC that runs it needs nothing installed. On macOS, git and the compiler come with the command
line tools. On Windows you need git (winget install Git.Git) only if you clone rather than download the ZIP from
GitHub.
A note on code signing. This project is not distributed with an Apple Developer ID or an Authenticode certificate, because those cost money and are tied to one person's identity. An app you build on your own machine runs normally. An app you copy to a different machine will be stopped by Gatekeeper or SmartScreen until you allow it. Both sections below explain how.
git clone https://github.com/Emip159/pitwall.git
cd pitwall/macos
UNIVERSAL=1 ./build-dmg.sh
That writes macos/build/Pitwall-<version>.dmg, which runs on both Apple Silicon and Intel. Open it and drag Pitwall
onto Applications, then launch it from Applications or Spotlight. The app has no Dock icon. Look for the small
ghost in the menu bar, with your highest usage percentage beside it. The note itself stays away until a tool is open:
see When the note appears.
Other build options:
| Command | Result |
|---|---|
./build-app.sh | build/Pitwall.app for this Mac's architecture only |
UNIVERSAL=1 ./build-app.sh | Universal app bundle, no DMG |
./build-dmg.sh | DMG for this Mac's architecture only |
SIGN_IDENTITY="-" ./build-app.sh | Force an ad-hoc signature, even if you have a certificate |
swift test | Run the unit tests |
Quick install without a DMG: ./build-app.sh && cp -R "build/Pitwall.app" /Applications/
build-app.sh signs automatically, picking the first identity it finds in this order:
SIGN_IDENTITY, if you set it.A stable certificate matters for one specific reason. macOS remembers a Keychain "Always Allow" grant per signing identity, and an ad-hoc signature changes on every rebuild, so macOS will ask again every time. This is also why you should only ever grant "Always Allow" to a build signed with a real certificate, as SECURITY.md explains.
To share a build with another Mac you need to notarize it, which requires a paid Apple Developer account and a Developer ID certificate. Store the credentials once, then build:
xcrun notarytool store-credentials my-profile
NOTARY_PROFILE=my-profile UNIVERSAL=1 ./build-dmg.sh
Without notarization, the other Mac can allow the app once in System Settings > Privacy & Security > Open Anyway,
or you can clear the quarantine flag: xattr -dr com.apple.quarantine "/Applications/Pitwall.app".
/Applications.Clone the repository to the PC, open PowerShell in the windows folder, and run:
.\build.ps1
If PowerShell refuses with "running scripts is disabled on this system", that is Windows' default execution policy,
not a problem with the script. Run it as powershell -ExecutionPolicy Bypass -File .uild.ps1 instead, which lifts
the policy for that one command only.
That produces two identical files in publish\win-x64\: Pitwall.exe and Pitwall-Setup.exe. Double-click the Setup
one. The app is its own installer. A small window lets you tick Start when I sign in to Windows and Launch now,
then it:
%LOCALAPPDATA%\Programs\Pitwall\. No administrator rights needed.claude,
codex or agy session is open, top right the first time. See When the note appears.Running the Setup exe again updates an existing installation. For scripted installs there is install.ps1:
powershell -ExecutionPolicy RemoteSigned -File .\install.ps1 -LaunchAtLogin
| Command | Result |
|---|---|
.\build.ps1 | Build only. Single self-contained file, about 150 MB (uncompressed on purpose: a compressed single file costs about 100 MB more memory while running) |
.\build.ps1 -Runtime win-arm64 | Build for ARM64 PCs |
.\build.ps1 -FrameworkDependent | Small exe, about 1 MB, needs the .NET 10 Desktop Runtime on the PC |
.\install.ps1 -Runtime win-arm64 | Install the ARM64 build |
.\install.ps1 -Uninstall | Remove the app, shortcut and login item, keeping settings |
.\install.ps1 -Uninstall -Purge | Also delete settings and saved keys |
dotnet run --project ParserTests | Parser checks. These also run on macOS and Linux |
After a git pull, delete the publish folder, or run .\build.ps1 again, before running .\install.ps1, so it does
not reinstall the old exe.
Building the Windows exe on a Mac. After brew install --cask dotnet-sdk:
cd windows
dotnet publish Pitwall/Pitwall.csproj -c Release -r win-x64 --self-contained true \
-p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=false \
-o publish/win-x64
Copy publish/win-x64 to the PC and run install.ps1 there. It sees the existing exe and skips the build.
SmartScreen. An exe built on the same PC runs normally. An exe you download or copy from elsewhere may show
"Windows protected your PC". Click More info, then Run anyway, or run
Unblock-File .\publish\win-x64\Pitwall.exe before installing.
Pitwall never asks for a password and has no login of its own. It only reads sign-ins that the official CLIs have already created, so log in with them first.
| Agent | Log in with | What the note then shows |
|---|---|---|
| Claude Pro / Max / Team | claude (Claude Code). For several accounts use separate config folders: CLAUDE_CONFIG_DIR=~/.claude-work claude | 5-hour session, weekly all-models, weekly per-model limits |
| ChatGPT Plus / Pro / Team | codex login (OpenAI Codex CLI) | 5-hour and weekly limits, plus any extra model limits |
| Gemini, personal Google account | agy, then log in (Google Antigravity CLI) | Gemini models 5h and weekly, Claude and GPT models 5h and weekly |
| Gemini, Workspace / Code Assist | gemini (Gemini CLI) | Per-model daily quota |
| Claude API | Paste an Admin API key in Settings | Cost today and this month, tokens today, top models |
Then click Rescan in Settings, or restart the app.
The Admin API key looks like sk-ant-admin01-..., and an organization admin creates it in the Console under
Settings > Admin keys. Ordinary sk-ant-api... keys and individual, non-organization accounts cannot read usage.
Each account gets a card in its agent's colours: Claude terracotta, ChatGPT green, Gemini blue to purple. A card with something that needs you gets an orange outline. Top to bottom:
124k / 1M tokens, 62%, with what is left, the
model, and whether the maximum is assumed or reported. It turns amber at the threshold in Settings, 80% by default.Every row names the project and spells out the status in words, so you never have to interpret the animation.
| Status | What you see | Where it comes from |
|---|---|---|
| Working | Ghost scoots around, bits of output fly off | Session busy, writing a reply |
| Thinking | Ghost floats, eyes wander, thought bubble | Waiting on the model |
| Running / Reading / Editing / Browsing | Ghost next to its tool: terminal, magnifier, pencil, globe, wrench | An unanswered tool call in the transcript |
| Delegating | Ghost hands a package to a small sub-agent ghost | An Agent or Task tool call |
| Needs you | Ghost looks at you, orange question mark pulses | Claude Code is waiting for your input or permission |
| Done | A quick jump with sparks, then a tick | A turn just finished without errors |
| Rate limited | Ghost stuck behind a striped barrier | A 429 from the API, or the plan window at 100% |
| Retrying | Ghost keeps going with spinning arrows | An API error mid-turn that Claude Code is retrying |
| Error | A short shake, dizzy eyes, red exclamation | The turn ended with an API error |
| Idle | Ghost dozes | Session open, nothing running |
| Queued | Ghost waits in a small queue | A sub-agent launched but not yet producing output |
Codex and Antigravity only report working and idle, plus Done, so their ghosts show only those states.
Sub-agents. Each Agent tool call that Claude Code runs as a separate agent gets its own row under its parent, read
from the subagents transcripts. It shows Queued until its first reply, then the same states as a session, then Done
and Idle once its turn ends. Finished sub-agents stay listed for 5 minutes, configurable in Settings, after which only
a count remains. Nested sub-agents nest.
Accessibility and performance. The note never takes keyboard focus, since it is an always-on-top tool window, so expand and collapse rows with the mouse. Rows still expose their name and status to screen readers. Animations are Core Animation layers, so an animating note uses almost no CPU, and they pause while the note is hidden or covered. Under macOS Reduce Motion, or with Animate agents and Pac-Man turned off, still poses replace them and each state is still distinguishable.
The note follows your tools, so it is only on screen while there is something to watch.
claude, codex or agy is running, the note stays away.
The menu bar or tray icon keeps showing your highest usage.agy and its card joins.To keep the note away for good, untick Show the note while a tool is open in Settings. Showing it from the icon turns that back on.
Right-click the note for the menu below. Right-click a specific card to also get a Hide item for that account.
| Item | What it does |
|---|---|
| Refresh Now | Fetch all accounts now |
| Hide account | Hide this account. Bring it back from Accounts |
| Accounts | Tick which accounts appear on the note |
| Size (macOS) / Reset size (Windows) | macOS: zoom presets. Windows: back to hugging the content |
| Theme | Dark, Glass (translucent), Light, Sticky note |
| Compact | One line per limit |
| Show Live Agents | Show or hide the live agents section |
| Lock Position & Size | Stops accidental dragging and hides the resize grip |
| Settings | Open Settings |
| Hide Note | Hide the note for now. It returns with the next tool, or from the menu bar or tray |
The icon shows the highest current-window usage across your accounts. On macOS it is a monochrome ghost with the percentage beside it, which follows light and dark mode. On Windows the ghost is filled with the severity colour and the percentage sits inside it.
The menu lists every account and limit, plus Show/Hide Note, Lock Position, Click-Through, Refresh Now, Settings and Quit. On Windows, left-click the tray icon to show or hide the note. With no tool open, showing it is a peek at every account (see When the note appears).
Click-through makes mouse clicks pass straight through the note to whatever is under it, turning it into a true overlay. Turn it off from the menu bar or tray icon.
Everything is read locally and read-only. Pitwall never writes to any CLI's files and never writes a token back.
| Account | Sign-in read from | Network request | Active sessions |
|---|---|---|---|
| Claude Code | macOS: Keychain Claude Code-credentials, plus -<hash> per extra config folder. Windows: %USERPROFILE%\.claude*\.credentials.json | GET https://api.anthropic.com/api/oauth/usage for windows, limits[] including the Fable limit, spend, and the weekly breakdown | <config>/sessions/<pid>.json gives busy or idle, and only if the process is still alive. The transcript at projects/<slug>/<sessionId>.jsonl, appended bytes only, gives model, tokens and context. <sessionId>/subagents/**/agent-*.jsonl gives the sub-agents |
| Codex (ChatGPT) | ~/.codex/auth.json | GET https://chatgpt.com/backend-api/wham/usage. If the token has expired, the last limits recorded in ~/.codex/sessions/**/rollout-*.jsonl are shown instead | ~/.codex/thread-writer-locks/*.lock. Working means a rollout was written in the last 20 seconds |
| Antigravity | macOS: Keychain item with account antigravity. Windows: Credential Manager entry gemini:antigravity. Fallback: ~/.gemini/antigravity-cli/antigravity-oauth-token | POST https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuotaSummary, on the backend and quota project that agy's own log/cli-*.log shows it using, since each backend keeps its own quota | Running agy processes. Working means a conversation file changed in the last 20 seconds. Model and workspace come from that launch's log |
| Gemini CLI | ~/.gemini/oauth_creds.json | POST .../v1internal:loadCodeAssist and :retrieveUserQuota | Chat logs written in the last 15 minutes |
| Claude API | The Admin key you pasted | GET https://api.anthropic.com/v1/organizations/cost_report and /usage_report/messages | Not applicable |
Timing. Session scanning is local and runs every 2 seconds. Usage is fetched on the refresh timer, when you click refresh, and when a session finishes working, at most once a minute per account.
Admin API costs are reported in cents and converted to dollars. "Today" means today in UTC, and the data lags by about 5 minutes.
Claude Code prices each session in its own transcript, and the note reads that figure rather than inventing one. Two things it is careful about:
total_cost_usd counts sub-agent requests alongside the top-level loop, while the token usage counts only the
top-level loop. So a sub-agent's cost is shown as a share of the session, never added on top of it.It is list-price arithmetic, not a bill. A session whose transcript carries no cost line says "Not reported for this session" rather than guessing.
The app icon is the same ghost the agents in the note are drawn from. swift macos/Tools/make-icons.swift redraws it
and writes both macos/Resources/AppIcon.icns and windows/Pitwall/Pitwall.ico using CoreGraphics only, no packages.
Both files are committed, so a normal build never runs it. Run it when the mark changes.
Pitwall reads the sign-ins of AI coding CLIs on your machine, which is a sensitive thing for a program to do. SECURITY.md is the full account, including how to report a vulnerability. The short version:
api.anthropic.com, chatgpt.com, oauth2.googleapis.com and
cloudcode-pa.googleapis.com, or the *-cloudcode-pa.googleapis.com backend your agy uses, and only for accounts
you have enabled. Redirects are refused, so a token cannot be forwarded to another host.agy or gemini.
No Google client credentials are stored in this repository.What it does not protect you from. Anything already running under your user account can read these tokens directly,
with or without this app. On Windows in particular, because this project is open source, the DPAPI entropy constant is
public, so secrets.json is protected against another Windows user but not against software running as you.
SECURITY.md spells out the whole boundary.
| Symptom | Fix |
|---|---|
"Sign-in expired. Run any claude command" | Claude Code's token expired while it was not in use. Run claude once. The note recovers on the next refresh. |
| "Keychain access was denied" (macOS) | Click refresh on the note and choose Always Allow. You can also fix it in Keychain Access, under the item's Access Control. |
| Keychain asks again after every rebuild | You are building with an ad-hoc signature. Build with an Apple Development or Developer ID certificate. |
| An account is missing | Log in with its CLI, then Settings > Rescan. Check it is ticked under Accounts. |
| Two cards show the same numbers | Two config folders are signed in to the same account. Hide one. |
| "From your last Codex session" | The Codex token expired, so the numbers come from Codex's local log. Run codex to refresh. |
| Gemini CLI: "no longer supported for Gemini Code Assist for individuals" | Google moved personal accounts to Antigravity. Log in with agy. |
| Antigravity: "Couldn't refresh the Antigravity sign-in" | The stored token expired and the OAuth client could not be read from your installed agy. Run agy once, then refresh. |
| Settings and sign-ins look reset after updating | The app used to be called Claude Usage Note, and its identity moved with the rename. It copies the old settings and stored keys across on first launch. If something did not come over, the old data is still there, since nothing is deleted. Please report it rather than re-entering keys. |
| Note disappeared | It leaves when no tool is open and returns with the next one. To see it now: menu bar or tray icon, then Show Note. If it is off-screen, delete the saved position: macOS defaults delete local.pitwall noteTopLeft, Windows remove NoteLeft and NoteTop from settings.json. Then restart. |
| Cannot click the note | Click-through is on. Turn it off from the menu bar or tray icon. |
| "Rate limited by the server" | Pick a longer refresh interval in Settings. |
| Context window: "Unavailable from provider" | Codex only reports it in sessions that logged a token_count with a window size. Antigravity and Gemini CLI never do. For Claude Code it appears once the transcript has an assistant reply. |
| Usage cost: "Not reported by ..." | Only Claude reports a cost in its usage response. Antigravity and Codex do not, and the note never estimates one. |
| Cost: "Not reported for this session" | Only Claude Code writes a per-session cost into its transcript, and only once the session has billed a request. That format is internal to Claude Code and changes between versions, so if a release stops writing that line the note says this rather than guessing. |
| A sub-agent's cost says "derived" | It shares a model with another agent in the session, so that model's reported cost was split by weighted tokens. An agent that is its model's only user shows Claude's own figure instead. |
| More than one keychain item matches (macOS) | Two generic passwords share the same service or account name. Pitwall refuses to guess which one is real. Remove the duplicate in Keychain Access. |
Neither dump command prints a secret.
macOS:
"/Applications/Pitwall.app/Contents/MacOS/Pitwall" --dump
"/Applications/Pitwall.app/Contents/MacOS/Pitwall" --dump --verbose # also prints response structure, field names only
"/Applications/Pitwall.app/Contents/MacOS/Pitwall" --demo # made-up accounts cycling through every state, reads and fetches nothing
Windows: crashes are logged to %APPDATA%\Pitwall\error.log.
& "$env:LOCALAPPDATA\Programs\Pitwall\Pitwall.exe" --dump
& "$env:LOCALAPPDATA\Programs\Pitwall\Pitwall.exe" --demo
Dump output does include folder and project names, so glance over it before pasting it into an issue.
macOS:
Turn off Launch at login in Settings.
Quit from the menu bar icon.
Run:
rm -rf "/Applications/Pitwall.app"
defaults delete local.pitwall
If you pasted an Admin key or token, delete the Pitwall items in Keychain Access.
Windows: Settings > Apps > Installed apps > Pitwall > Uninstall. It asks whether to keep your settings.
Alternatively, from the windows folder, run .\install.ps1 -Uninstall -Purge.
Issues and pull requests are welcome. A few things worth knowing first.
Repository layout
macos/ Swift package: menu bar item plus floating note
Sources/Pitwall/ App code
Tests/PitwallTests/ Unit tests, run with `swift test`
build-app.sh Build and sign the .app
build-dmg.sh Build the .app, then package a DMG
windows/ .NET 10 WPF app: tray icon plus floating note
Pitwall/ App code
ParserTests/ Parser checks that run on any OS
build.ps1 Build the exe and the self-installer
install.ps1 Scripted install and uninstall
docs/ Design notes and specs
SECURITY.md What the app touches, what it sends, how to report a vulnerability
Running the tests
cd macos && swift test # unit tests
cd windows && dotnet run --project ParserTests # parser checks, any OS
The Windows app itself also compiles on macOS and Linux, which is useful for checking a change before you get to a PC:
cd windows && dotnet build Pitwall/Pitwall.csproj
One parser check, sub id from path, fails when run on macOS or Linux and passes on Windows. It uses a Windows-style
path, and Path.GetFileNameWithoutExtension does not treat a backslash as a separator off Windows. This is expected.
Cutting a release
windows/Pitwall/Pitwall.csproj (<Version>) and macos/Resources/Info.plist
(CFBundleShortVersionString and CFBundleVersion), and commit.git tag v1.2.0 && git push origin v1.2.0..github/workflows/release.yml then tests and builds both apps, and publishes a GitHub Release with the DMG, the x64
and ARM64 Windows installers and their checksums. It refuses a tag that does not match the two version numbers. A tag
with a suffix, such as v1.2.0-rc1, becomes a pre-release. Versions follow MAJOR.MINOR.PATCH: a fix bumps the last
number, a feature the middle one.
Things to keep in mind
macos/PARITY.md records what
the last port involved.agy.MIT. Copyright (c) 2026 Emilian Popescu.
28 commits
C#
50.2%
Swift
48.9%
Pitwall: an always-on-top note showing your Claude Code, Codex and Antigravity plan limits, cost, context windows and live agents. Native macOS and Windows, no dependencies, no telemetry.
C#
0
28 commits
updated Sep 18, 2026
See how much of your AI coding plan is left, and what every agent is doing, without leaving your editor.
Pitwall is a small always-on-top note for people who work with Claude Code, Codex and Antigravity. It shows your plan limits and when they reset, what the provider says you have spent, how full each agent's context window is, and a live tree of every running agent and sub-agent. It appears when you open one of those tools and goes away when you close the last one.
Native macOS app (Swift) and native Windows app (C#/WPF). No Electron, no Python, no third-party packages, no telemetry. MIT licensed.
Demo mode (--demo), so every state is on screen at once. Real accounts look the same.
claude, codex or agy session is a small ghost acting out its real state: working,
thinking, using a tool, waiting for you, rate limited, done. Sub-agents hang under the session that launched them.You need the CLIs you already use to be signed in (claude, codex login, agy). Pitwall has no login of its own: it
reads the sign-ins those tools created, read-only.
Download it. Get the installer for your computer from the
latest release: Pitwall-Setup-…-x64.exe for Windows (-arm64 for
Windows on ARM), Pitwall-….dmg for macOS 14 or newer. The builds are not code signed, so the first launch needs one
extra click: on Windows More info > Run anyway, on macOS System Settings > Privacy & Security > Open Anyway.
Or build it yourself, which takes about a minute and is how you avoid those warnings.
macOS (14 Sonoma or newer, with Xcode or xcode-select --install):
git clone https://github.com/Emip159/pitwall.git
cd pitwall/macos
./build-app.sh && cp -R build/Pitwall.app /Applications/
open /Applications/Pitwall.app
macOS asks whether Pitwall may read the Claude Code-credentials Keychain item, once per Claude sign-in. Choose Always Allow.
Windows (10 or 11, with the .NET 10 SDK: winget install Microsoft.DotNet.SDK.10):
git clone https://github.com/Emip159/pitwall.git
cd pitwall\windows
powershell -ExecutionPolicy Bypass -File .\build.ps1
.\publish\win-x64\Pitwall-Setup.exe
The Setup window installs for your user only (no administrator rights) and can start Pitwall when you sign in. The
-ExecutionPolicy Bypass applies to that one command: Windows refuses to run any script by default.
Then just work. Open claude, codex or agy in any terminal and the note appears on its own.
| You want to | Do this |
|---|---|
| Check your limits with no tool open | Click the ghost icon in the menu bar (macOS: Show Note) or the tray (Windows: left-click) |
| Put the note away for now | The ✕ in its corner. It comes back with the next tool you open |
| Move or resize it | Drag it, or drag any edge. It remembers where you put it |
| See an agent's task, model, context, tools and cost | Click its row |
| See plan details for an account | Click the card's name |
| Change theme, size, compact mode, accounts | Right-click the note, or open Settings from the icon |
| Try it without any account | Run it with --demo |
Is it safe to run? It reads the same local sign-ins your CLIs use and sends them only to the provider that issued them. The hosts are on a fixed allowlist, redirects are refused, nothing is written back, and there is no telemetry or update check. Security and privacy has the short version and SECURITY.md the whole boundary, including what it does not protect you from.
![]() Compact layout, six accounts | ![]() macOS, one column, an agent's details open |
![]() Light | ![]() Sticky note | ![]() Glass |
The rest of this page is reference. Everything above is enough to install and use Pitwall.
You are deep in a Claude Code session and you want to know, without breaking flow, whether you are about to hit your weekly limit. That is the whole idea. The note floats above your editor and answers it.
Plan limits and resets
~/.claude,
~/.claude-personal and ~/.claude-work.agy), the 5-hour and weekly limits for Gemini models and for Claude and GPT
models. Through the Gemini CLI, the Workspace / Code Assist quota.Cost
Live agents
Every running claude, codex or agy session appears as a small ghost that acts out its real state: working,
thinking, using a tool, needs you, done, rate limited, error, queued or idle. Claude Code sub-agents appear as a
tree under the session that launched them, with their task, model, context, tool calls and result on demand. A Pac-Man
on each card eats through your quota as you use it.
Context window
How full each agent's context is, taken from the tokens of its latest request. Claude Code does not record the window size, so the maximum is assumed per model and labelled as such. Codex reports its own.
| macOS | Windows | |
|---|---|---|
| To run | macOS 14 Sonoma or newer | Windows 10 or 11, x64 or ARM64 |
| To build | Xcode, or the command line tools (xcode-select --install) | .NET 10 SDK (winget install Microsoft.DotNet.SDK.10) |
| Dependencies | None | None |
Installers for both platforms are attached to every release, built by
GitHub Actions from the tagged commit, with SHA-256 checksums. Building it yourself takes about a minute. Either way the
Windows exe is self-contained, so the PC that runs it needs nothing installed. On macOS, git and the compiler come with the command
line tools. On Windows you need git (winget install Git.Git) only if you clone rather than download the ZIP from
GitHub.
A note on code signing. This project is not distributed with an Apple Developer ID or an Authenticode certificate, because those cost money and are tied to one person's identity. An app you build on your own machine runs normally. An app you copy to a different machine will be stopped by Gatekeeper or SmartScreen until you allow it. Both sections below explain how.
git clone https://github.com/Emip159/pitwall.git
cd pitwall/macos
UNIVERSAL=1 ./build-dmg.sh
That writes macos/build/Pitwall-<version>.dmg, which runs on both Apple Silicon and Intel. Open it and drag Pitwall
onto Applications, then launch it from Applications or Spotlight. The app has no Dock icon. Look for the small
ghost in the menu bar, with your highest usage percentage beside it. The note itself stays away until a tool is open:
see When the note appears.
Other build options:
| Command | Result |
|---|---|
./build-app.sh | build/Pitwall.app for this Mac's architecture only |
UNIVERSAL=1 ./build-app.sh | Universal app bundle, no DMG |
./build-dmg.sh | DMG for this Mac's architecture only |
SIGN_IDENTITY="-" ./build-app.sh | Force an ad-hoc signature, even if you have a certificate |
swift test | Run the unit tests |
Quick install without a DMG: ./build-app.sh && cp -R "build/Pitwall.app" /Applications/
build-app.sh signs automatically, picking the first identity it finds in this order:
SIGN_IDENTITY, if you set it.A stable certificate matters for one specific reason. macOS remembers a Keychain "Always Allow" grant per signing identity, and an ad-hoc signature changes on every rebuild, so macOS will ask again every time. This is also why you should only ever grant "Always Allow" to a build signed with a real certificate, as SECURITY.md explains.
To share a build with another Mac you need to notarize it, which requires a paid Apple Developer account and a Developer ID certificate. Store the credentials once, then build:
xcrun notarytool store-credentials my-profile
NOTARY_PROFILE=my-profile UNIVERSAL=1 ./build-dmg.sh
Without notarization, the other Mac can allow the app once in System Settings > Privacy & Security > Open Anyway,
or you can clear the quarantine flag: xattr -dr com.apple.quarantine "/Applications/Pitwall.app".
/Applications.Clone the repository to the PC, open PowerShell in the windows folder, and run:
.\build.ps1
If PowerShell refuses with "running scripts is disabled on this system", that is Windows' default execution policy,
not a problem with the script. Run it as powershell -ExecutionPolicy Bypass -File .uild.ps1 instead, which lifts
the policy for that one command only.
That produces two identical files in publish\win-x64\: Pitwall.exe and Pitwall-Setup.exe. Double-click the Setup
one. The app is its own installer. A small window lets you tick Start when I sign in to Windows and Launch now,
then it:
%LOCALAPPDATA%\Programs\Pitwall\. No administrator rights needed.claude,
codex or agy session is open, top right the first time. See When the note appears.Running the Setup exe again updates an existing installation. For scripted installs there is install.ps1:
powershell -ExecutionPolicy RemoteSigned -File .\install.ps1 -LaunchAtLogin
| Command | Result |
|---|---|
.\build.ps1 | Build only. Single self-contained file, about 150 MB (uncompressed on purpose: a compressed single file costs about 100 MB more memory while running) |
.\build.ps1 -Runtime win-arm64 | Build for ARM64 PCs |
.\build.ps1 -FrameworkDependent | Small exe, about 1 MB, needs the .NET 10 Desktop Runtime on the PC |
.\install.ps1 -Runtime win-arm64 | Install the ARM64 build |
.\install.ps1 -Uninstall | Remove the app, shortcut and login item, keeping settings |
.\install.ps1 -Uninstall -Purge | Also delete settings and saved keys |
dotnet run --project ParserTests | Parser checks. These also run on macOS and Linux |
After a git pull, delete the publish folder, or run .\build.ps1 again, before running .\install.ps1, so it does
not reinstall the old exe.
Building the Windows exe on a Mac. After brew install --cask dotnet-sdk:
cd windows
dotnet publish Pitwall/Pitwall.csproj -c Release -r win-x64 --self-contained true \
-p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=false \
-o publish/win-x64
Copy publish/win-x64 to the PC and run install.ps1 there. It sees the existing exe and skips the build.
SmartScreen. An exe built on the same PC runs normally. An exe you download or copy from elsewhere may show
"Windows protected your PC". Click More info, then Run anyway, or run
Unblock-File .\publish\win-x64\Pitwall.exe before installing.
Pitwall never asks for a password and has no login of its own. It only reads sign-ins that the official CLIs have already created, so log in with them first.
| Agent | Log in with | What the note then shows |
|---|---|---|
| Claude Pro / Max / Team | claude (Claude Code). For several accounts use separate config folders: CLAUDE_CONFIG_DIR=~/.claude-work claude | 5-hour session, weekly all-models, weekly per-model limits |
| ChatGPT Plus / Pro / Team | codex login (OpenAI Codex CLI) | 5-hour and weekly limits, plus any extra model limits |
| Gemini, personal Google account | agy, then log in (Google Antigravity CLI) | Gemini models 5h and weekly, Claude and GPT models 5h and weekly |
| Gemini, Workspace / Code Assist | gemini (Gemini CLI) | Per-model daily quota |
| Claude API | Paste an Admin API key in Settings | Cost today and this month, tokens today, top models |
Then click Rescan in Settings, or restart the app.
The Admin API key looks like sk-ant-admin01-..., and an organization admin creates it in the Console under
Settings > Admin keys. Ordinary sk-ant-api... keys and individual, non-organization accounts cannot read usage.
Each account gets a card in its agent's colours: Claude terracotta, ChatGPT green, Gemini blue to purple. A card with something that needs you gets an orange outline. Top to bottom:
124k / 1M tokens, 62%, with what is left, the
model, and whether the maximum is assumed or reported. It turns amber at the threshold in Settings, 80% by default.Every row names the project and spells out the status in words, so you never have to interpret the animation.
| Status | What you see | Where it comes from |
|---|---|---|
| Working | Ghost scoots around, bits of output fly off | Session busy, writing a reply |
| Thinking | Ghost floats, eyes wander, thought bubble | Waiting on the model |
| Running / Reading / Editing / Browsing | Ghost next to its tool: terminal, magnifier, pencil, globe, wrench | An unanswered tool call in the transcript |
| Delegating | Ghost hands a package to a small sub-agent ghost | An Agent or Task tool call |
| Needs you | Ghost looks at you, orange question mark pulses | Claude Code is waiting for your input or permission |
| Done | A quick jump with sparks, then a tick | A turn just finished without errors |
| Rate limited | Ghost stuck behind a striped barrier | A 429 from the API, or the plan window at 100% |
| Retrying | Ghost keeps going with spinning arrows | An API error mid-turn that Claude Code is retrying |
| Error | A short shake, dizzy eyes, red exclamation | The turn ended with an API error |
| Idle | Ghost dozes | Session open, nothing running |
| Queued | Ghost waits in a small queue | A sub-agent launched but not yet producing output |
Codex and Antigravity only report working and idle, plus Done, so their ghosts show only those states.
Sub-agents. Each Agent tool call that Claude Code runs as a separate agent gets its own row under its parent, read
from the subagents transcripts. It shows Queued until its first reply, then the same states as a session, then Done
and Idle once its turn ends. Finished sub-agents stay listed for 5 minutes, configurable in Settings, after which only
a count remains. Nested sub-agents nest.
Accessibility and performance. The note never takes keyboard focus, since it is an always-on-top tool window, so expand and collapse rows with the mouse. Rows still expose their name and status to screen readers. Animations are Core Animation layers, so an animating note uses almost no CPU, and they pause while the note is hidden or covered. Under macOS Reduce Motion, or with Animate agents and Pac-Man turned off, still poses replace them and each state is still distinguishable.
The note follows your tools, so it is only on screen while there is something to watch.
claude, codex or agy is running, the note stays away.
The menu bar or tray icon keeps showing your highest usage.agy and its card joins.To keep the note away for good, untick Show the note while a tool is open in Settings. Showing it from the icon turns that back on.
Right-click the note for the menu below. Right-click a specific card to also get a Hide item for that account.
| Item | What it does |
|---|---|
| Refresh Now | Fetch all accounts now |
| Hide account | Hide this account. Bring it back from Accounts |
| Accounts | Tick which accounts appear on the note |
| Size (macOS) / Reset size (Windows) | macOS: zoom presets. Windows: back to hugging the content |
| Theme | Dark, Glass (translucent), Light, Sticky note |
| Compact | One line per limit |
| Show Live Agents | Show or hide the live agents section |
| Lock Position & Size | Stops accidental dragging and hides the resize grip |
| Settings | Open Settings |
| Hide Note | Hide the note for now. It returns with the next tool, or from the menu bar or tray |
The icon shows the highest current-window usage across your accounts. On macOS it is a monochrome ghost with the percentage beside it, which follows light and dark mode. On Windows the ghost is filled with the severity colour and the percentage sits inside it.
The menu lists every account and limit, plus Show/Hide Note, Lock Position, Click-Through, Refresh Now, Settings and Quit. On Windows, left-click the tray icon to show or hide the note. With no tool open, showing it is a peek at every account (see When the note appears).
Click-through makes mouse clicks pass straight through the note to whatever is under it, turning it into a true overlay. Turn it off from the menu bar or tray icon.
Everything is read locally and read-only. Pitwall never writes to any CLI's files and never writes a token back.
| Account | Sign-in read from | Network request | Active sessions |
|---|---|---|---|
| Claude Code | macOS: Keychain Claude Code-credentials, plus -<hash> per extra config folder. Windows: %USERPROFILE%\.claude*\.credentials.json | GET https://api.anthropic.com/api/oauth/usage for windows, limits[] including the Fable limit, spend, and the weekly breakdown | <config>/sessions/<pid>.json gives busy or idle, and only if the process is still alive. The transcript at projects/<slug>/<sessionId>.jsonl, appended bytes only, gives model, tokens and context. <sessionId>/subagents/**/agent-*.jsonl gives the sub-agents |
| Codex (ChatGPT) | ~/.codex/auth.json | GET https://chatgpt.com/backend-api/wham/usage. If the token has expired, the last limits recorded in ~/.codex/sessions/**/rollout-*.jsonl are shown instead | ~/.codex/thread-writer-locks/*.lock. Working means a rollout was written in the last 20 seconds |
| Antigravity | macOS: Keychain item with account antigravity. Windows: Credential Manager entry gemini:antigravity. Fallback: ~/.gemini/antigravity-cli/antigravity-oauth-token | POST https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuotaSummary, on the backend and quota project that agy's own log/cli-*.log shows it using, since each backend keeps its own quota | Running agy processes. Working means a conversation file changed in the last 20 seconds. Model and workspace come from that launch's log |
| Gemini CLI | ~/.gemini/oauth_creds.json | POST .../v1internal:loadCodeAssist and :retrieveUserQuota | Chat logs written in the last 15 minutes |
| Claude API | The Admin key you pasted | GET https://api.anthropic.com/v1/organizations/cost_report and /usage_report/messages | Not applicable |
Timing. Session scanning is local and runs every 2 seconds. Usage is fetched on the refresh timer, when you click refresh, and when a session finishes working, at most once a minute per account.
Admin API costs are reported in cents and converted to dollars. "Today" means today in UTC, and the data lags by about 5 minutes.
Claude Code prices each session in its own transcript, and the note reads that figure rather than inventing one. Two things it is careful about:
total_cost_usd counts sub-agent requests alongside the top-level loop, while the token usage counts only the
top-level loop. So a sub-agent's cost is shown as a share of the session, never added on top of it.It is list-price arithmetic, not a bill. A session whose transcript carries no cost line says "Not reported for this session" rather than guessing.
The app icon is the same ghost the agents in the note are drawn from. swift macos/Tools/make-icons.swift redraws it
and writes both macos/Resources/AppIcon.icns and windows/Pitwall/Pitwall.ico using CoreGraphics only, no packages.
Both files are committed, so a normal build never runs it. Run it when the mark changes.
Pitwall reads the sign-ins of AI coding CLIs on your machine, which is a sensitive thing for a program to do. SECURITY.md is the full account, including how to report a vulnerability. The short version:
api.anthropic.com, chatgpt.com, oauth2.googleapis.com and
cloudcode-pa.googleapis.com, or the *-cloudcode-pa.googleapis.com backend your agy uses, and only for accounts
you have enabled. Redirects are refused, so a token cannot be forwarded to another host.agy or gemini.
No Google client credentials are stored in this repository.What it does not protect you from. Anything already running under your user account can read these tokens directly,
with or without this app. On Windows in particular, because this project is open source, the DPAPI entropy constant is
public, so secrets.json is protected against another Windows user but not against software running as you.
SECURITY.md spells out the whole boundary.
| Symptom | Fix |
|---|---|
"Sign-in expired. Run any claude command" | Claude Code's token expired while it was not in use. Run claude once. The note recovers on the next refresh. |
| "Keychain access was denied" (macOS) | Click refresh on the note and choose Always Allow. You can also fix it in Keychain Access, under the item's Access Control. |
| Keychain asks again after every rebuild | You are building with an ad-hoc signature. Build with an Apple Development or Developer ID certificate. |
| An account is missing | Log in with its CLI, then Settings > Rescan. Check it is ticked under Accounts. |
| Two cards show the same numbers | Two config folders are signed in to the same account. Hide one. |
| "From your last Codex session" | The Codex token expired, so the numbers come from Codex's local log. Run codex to refresh. |
| Gemini CLI: "no longer supported for Gemini Code Assist for individuals" | Google moved personal accounts to Antigravity. Log in with agy. |
| Antigravity: "Couldn't refresh the Antigravity sign-in" | The stored token expired and the OAuth client could not be read from your installed agy. Run agy once, then refresh. |
| Settings and sign-ins look reset after updating | The app used to be called Claude Usage Note, and its identity moved with the rename. It copies the old settings and stored keys across on first launch. If something did not come over, the old data is still there, since nothing is deleted. Please report it rather than re-entering keys. |
| Note disappeared | It leaves when no tool is open and returns with the next one. To see it now: menu bar or tray icon, then Show Note. If it is off-screen, delete the saved position: macOS defaults delete local.pitwall noteTopLeft, Windows remove NoteLeft and NoteTop from settings.json. Then restart. |
| Cannot click the note | Click-through is on. Turn it off from the menu bar or tray icon. |
| "Rate limited by the server" | Pick a longer refresh interval in Settings. |
| Context window: "Unavailable from provider" | Codex only reports it in sessions that logged a token_count with a window size. Antigravity and Gemini CLI never do. For Claude Code it appears once the transcript has an assistant reply. |
| Usage cost: "Not reported by ..." | Only Claude reports a cost in its usage response. Antigravity and Codex do not, and the note never estimates one. |
| Cost: "Not reported for this session" | Only Claude Code writes a per-session cost into its transcript, and only once the session has billed a request. That format is internal to Claude Code and changes between versions, so if a release stops writing that line the note says this rather than guessing. |
| A sub-agent's cost says "derived" | It shares a model with another agent in the session, so that model's reported cost was split by weighted tokens. An agent that is its model's only user shows Claude's own figure instead. |
| More than one keychain item matches (macOS) | Two generic passwords share the same service or account name. Pitwall refuses to guess which one is real. Remove the duplicate in Keychain Access. |
Neither dump command prints a secret.
macOS:
"/Applications/Pitwall.app/Contents/MacOS/Pitwall" --dump
"/Applications/Pitwall.app/Contents/MacOS/Pitwall" --dump --verbose # also prints response structure, field names only
"/Applications/Pitwall.app/Contents/MacOS/Pitwall" --demo # made-up accounts cycling through every state, reads and fetches nothing
Windows: crashes are logged to %APPDATA%\Pitwall\error.log.
& "$env:LOCALAPPDATA\Programs\Pitwall\Pitwall.exe" --dump
& "$env:LOCALAPPDATA\Programs\Pitwall\Pitwall.exe" --demo
Dump output does include folder and project names, so glance over it before pasting it into an issue.
macOS:
Turn off Launch at login in Settings.
Quit from the menu bar icon.
Run:
rm -rf "/Applications/Pitwall.app"
defaults delete local.pitwall
If you pasted an Admin key or token, delete the Pitwall items in Keychain Access.
Windows: Settings > Apps > Installed apps > Pitwall > Uninstall. It asks whether to keep your settings.
Alternatively, from the windows folder, run .\install.ps1 -Uninstall -Purge.
Issues and pull requests are welcome. A few things worth knowing first.
Repository layout
macos/ Swift package: menu bar item plus floating note
Sources/Pitwall/ App code
Tests/PitwallTests/ Unit tests, run with `swift test`
build-app.sh Build and sign the .app
build-dmg.sh Build the .app, then package a DMG
windows/ .NET 10 WPF app: tray icon plus floating note
Pitwall/ App code
ParserTests/ Parser checks that run on any OS
build.ps1 Build the exe and the self-installer
install.ps1 Scripted install and uninstall
docs/ Design notes and specs
SECURITY.md What the app touches, what it sends, how to report a vulnerability
Running the tests
cd macos && swift test # unit tests
cd windows && dotnet run --project ParserTests # parser checks, any OS
The Windows app itself also compiles on macOS and Linux, which is useful for checking a change before you get to a PC:
cd windows && dotnet build Pitwall/Pitwall.csproj
One parser check, sub id from path, fails when run on macOS or Linux and passes on Windows. It uses a Windows-style
path, and Path.GetFileNameWithoutExtension does not treat a backslash as a separator off Windows. This is expected.
Cutting a release
windows/Pitwall/Pitwall.csproj (<Version>) and macos/Resources/Info.plist
(CFBundleShortVersionString and CFBundleVersion), and commit.git tag v1.2.0 && git push origin v1.2.0..github/workflows/release.yml then tests and builds both apps, and publishes a GitHub Release with the DMG, the x64
and ARM64 Windows installers and their checksums. It refuses a tag that does not match the two version numbers. A tag
with a suffix, such as v1.2.0-rc1, becomes a pre-release. Versions follow MAJOR.MINOR.PATCH: a fix bumps the last
number, a feature the middle one.
Things to keep in mind
macos/PARITY.md records what
the last port involved.agy.MIT. Copyright (c) 2026 Emilian Popescu.
28 commits
C#
50.2%
Swift
48.9%