Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 44 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,69 @@
# CodexBar
<h1 align="center">CodexBar</h1>

[![Build and Test](https://github.com/GordonBeeming/codex-bar/actions/workflows/build.yml/badge.svg)](https://github.com/GordonBeeming/codex-bar/actions/workflows/build.yml)
<p align="center">
Your Codex usage limits, in the macOS menu bar, in your timezone.
</p>

CodexBar puts your Codex plan limits in the macOS menu bar. It shows the current five-hour and weekly usage, reset times in your timezone, and whether you're ahead of a steady pace through each window.
<p align="center">
<a href="https://github.com/GordonBeeming/codex-bar/actions/workflows/build.yml"><img src="https://github.com/GordonBeeming/codex-bar/actions/workflows/build.yml/badge.svg" alt="Build status" /></a>
<a href="https://github.com/GordonBeeming/codex-bar/releases/latest"><img src="https://img.shields.io/github/v/release/GordonBeeming/codex-bar" alt="Latest release" /></a>
<img src="https://img.shields.io/badge/platform-macOS%2015%2B%20(Apple%20Silicon)-blue" alt="macOS 15+ Apple Silicon" />
</p>

It deliberately stops there: no cost tracking, charts, token copying, account switching, or provider abstraction.
---

Settings cover the parts that affect the small menu-bar experience:
CodexBar shows your Codex plan limits in the menu bar—the same session and weekly percentages reported by Codex, nothing more. The menu-bar item shows the highest usage percentage; the dropdown lists each limit with a progress bar, its reset time in your local timezone, and whether you're ahead of a steady pace through the window.

- Default or custom warning and critical colours
- A pace flame beside the menu-bar percentage
- Full-screen reactions for session resets, weekly resets, and crossing weekly pace
- Launch at login
That's the whole app. No cost tracking, charts, token copying, account switching, or provider abstraction.

## Requirements
## Install

- macOS 15 or later on Apple Silicon
- Codex CLI installed and signed in with ChatGPT
```sh
brew install --cask gordonbeeming/tap/codex-bar
open -a CodexBar
```

CodexBar starts `codex app-server` locally and reads its documented `account/read` and `account/rateLimits/read` responses. Codex owns authentication and token refresh; CodexBar never reads `~/.codex/auth.json`.
CodexBar needs macOS 15 or later on Apple Silicon, plus the [Codex CLI](https://developers.openai.com/codex/cli) installed and signed in with ChatGPT.

If Codex isn't on the app's inherited `PATH`, CodexBar also checks common Homebrew, fnm, Volta, nvm, and `~/.local/bin` locations. Set `CODEX_PATH` to an explicit executable path when needed.
The app launches at login by default. You can turn that off in Settings.

## Build and install
### From source

```sh
make test
make install
open ~/Applications/CodexBar.app
```

The installed app launches at login by default. You can turn that off in Settings.
`make install` builds a release binary and signs it with an available Apple Development identity, falling back to ad-hoc signing.

## Settings

Open **Settings…** from the dropdown:

- **Usage colours** — use the default 75% warning and 90% critical levels, or drag the two splitters to choose your own.
- **Pace flame** — show a flame beside the menu-bar percentage when usage is ahead of a steady pace through a window.
- **Celebrations** — choose full-screen reactions for session resets, weekly resets, and crossing the weekly pace line, or turn them off individually.
- **Launch at login** — on by default for an installed app.

## Development
## How it works

CodexBar starts `codex app-server` locally and reads its `account/read` and `account/rateLimits/read` responses once a minute, plus when the menu opens with stale data. Codex remains responsible for authentication and token refresh; CodexBar never reads `~/.codex/auth.json`.

The app guards against temporary usage regressions before updating the display or firing a reset celebration. A suspicious drop must persist across three readings, while a real window reset or a Codex plan change is accepted immediately. Plan changes also reseed the celebration baseline, so upgrading doesn't create a fake reset signal.

If Codex isn't on the app's inherited `PATH`, CodexBar checks common Homebrew, fnm, Volta, nvm, and `~/.local/bin` locations. Set `CODEX_PATH` to an explicit executable path if your installation lives somewhere else.

## Dev loop

```sh
make run
make run # Run directly from source
make test # Build and run the unit tests
```

`swift run` doesn't produce an app bundle, so launch-at-login controls only appear in the installed app.
The testable usage mapping, formatting, thresholds, celebration detection, and snapshot stabilization live in `CodexBarCore`. The app target is a small SwiftUI `MenuBarExtra` on top.

## Releasing

Publish a GitHub release tagged `vX.Y`. The release workflow builds and tests the app, signs it with the Developer ID certificate, notarizes and staples the bundle, uploads `CodexBar-X.Y.dmg`, then updates `gordonbeeming/homebrew-tap`.

The release job uses the `prod` environment with these secrets:
Publish a GitHub release tagged `vX.Y` and CI handles the rest: tests, Developer ID signing, notarization, stapling, DMG upload, and the signed Homebrew cask update.

- `DEVELOPER_ID_CERTIFICATE`
- `DEVELOPER_ID_PASSWORD`
- `APPLE_ID`
- `APPLE_TEAM_ID`
- `APPLE_APP_PASSWORD`
- `HOMEBREW_TAP_DEPLOY_KEY`
- `COMMIT_SIGNING_KEY`
For local setup, packaging details, CI secrets, and the full release process, see the [development and release guide](docs/development.md).
88 changes: 88 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Development and release guide

This document covers the contributor and maintainer details that don't need to sit in the consumer-focused README.

## Requirements

- macOS 15 or later on Apple Silicon
- Xcode with Swift 6.1 or later
- Codex CLI installed and signed in with ChatGPT for live usage data

## Build and test

Run the normal development checks with:

```sh
swift build --build-tests
swift test --parallel
```

The Makefile also provides a release build target and a standard test target:

```sh
make build # swift build -c release
make test # swift test
```

## Run and install

Run the executable directly from source with:

```sh
make run
```

`swift run` doesn't create an app bundle, so launch-at-login controls are only available in an installed build.

After any code change that affects the app, install and relaunch it:

```sh
make install
open ~/Applications/CodexBar.app
```

`make install` builds the release executable, creates `dist/CodexBar.app`, signs it with an available Apple Development identity or ad-hoc identity, stops the running installed copy, and copies the new bundle to `~/Applications`.

To create the signed bundle without installing it:

```sh
make bundle
```

You can override the bundle metadata and signing options when packaging:

```sh
make bundle VERSION=0.3 BUILD=42 CODESIGN_IDENTITY="Developer ID Application: YOUR_NAME (TEAM_ID)" CODESIGN_OPTS="--options runtime --timestamp"
```

## Project structure

- `Sources/CodexBarCore` contains the testable protocol models, usage mapping, formatting, severity thresholds, celebration detection, and snapshot stabilization.
- `Sources/CodexBar` contains the app-server client, settings, menu-bar UI, reactions, launch-at-login support, and icon rendering.
- `Tests/CodexBarCoreTests` covers the core behavior.
- `Packaging/Info.plist` and `Makefile` build the distributable app bundle.
- `.github/workflows/build.yml` runs CI and publishes releases.

## Release process

Releases use `vX.Y` tags. Publishing a GitHub release triggers the release job, which:

1. Builds and tests all targets.
2. Imports the Developer ID certificate into a temporary keychain.
3. Builds and signs `CodexBar.app` with the hardened runtime and timestamping.
4. Verifies the signature, submits the app for notarization, and staples the ticket.
5. Creates and uploads `CodexBar-X.Y.dmg`.
6. Updates `gordonbeeming/homebrew-tap` with the matching version and SHA-256 checksum.
7. Signs the Homebrew cask commit before pushing it through the repository-specific deploy key.

The `prod` GitHub environment provides these secrets:

- `DEVELOPER_ID_CERTIFICATE`
- `DEVELOPER_ID_PASSWORD`
- `APPLE_ID`
- `APPLE_TEAM_ID`
- `APPLE_APP_PASSWORD`
- `HOMEBREW_TAP_DEPLOY_KEY`
- `COMMIT_SIGNING_KEY`

The certificate secret contains the base64-encoded `.p12`. `COMMIT_SIGNING_KEY` must contain an OpenSSH-formatted private key because Git's SSH signing helper doesn't accept the PKCS#8 export produced by some password managers.
Loading