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
12 changes: 11 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,17 @@ jobs:
fi

- name: Build DMG
run: ./scripts/build-dmg.sh "${{ steps.version.outputs.value }}"
env:
CODESIGN_P12_BASE64: ${{ secrets.CODESIGN_P12_BASE64 }}
CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }}
IS_TAG_RELEASE: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
run: |
# Releases must keep the same signing identity, or users lose Keychain trust on update.
if [[ "$IS_TAG_RELEASE" == "true" ]]; then
: "${CODESIGN_P12_BASE64:?Set the CODESIGN_P12_BASE64 repository secret}"
: "${CODESIGN_P12_PASSWORD:?Set the CODESIGN_P12_PASSWORD repository secret}"
fi
./scripts/build-dmg.sh "${{ steps.version.outputs.value }}"

- name: Upload workflow artifact
uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- `swift build`: compile a development build.
- `swift test`: run the XCTest suite before submitting changes.
- `swift run LLMits`: launch the menu-bar app locally (it has no Dock icon).
- `./scripts/build-dmg.sh 1.0.1`: create a universal `.app`, DMG, and SHA-256 file under `dist/`.
- `./scripts/build-dmg.sh 1.0.1`: create a universal `.app`, DMG, and SHA-256 file under `dist/`. Set `CODESIGN_P12_PATH` (or `CODESIGN_P12_BASE64`) and `CODESIGN_P12_PASSWORD` to sign with the stable release certificate; otherwise it is ad-hoc signed.

Use Xcode 16+ and macOS 14+. Local `swift run` builds are ad-hoc signed, so macOS may ask for Keychain access after rebuilding.

Expand Down
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ curl -fsSL https://raw.githubusercontent.com/aryan1306/LLMits/main/install.sh |
- Choose one to three connected providers for the menu bar; Claude and Codex are selected by default
- Pin providers from the popover and drag to reorder them in Settings; the popover shows every connected provider
- Used or remaining percentage display modes
- Claude PKCE, ChatGPT device-code, and Google browser sign-in flows
- Claude PKCE and ChatGPT device-code sign-in, plus read-only use of an existing `agy` CLI login
- Credentials stored in macOS Keychain
- Automatic token refresh, configurable polling, and refresh after wake
- Relative freshness labels, reset times, stale-data indicators, and manual refresh
Expand All @@ -51,7 +51,7 @@ curl -fsSL https://raw.githubusercontent.com/aryan1306/LLMits/main/install.sh |
| --- | --- | --- | --- |
| **Claude** | Pro, Max (5× and 20×), Team, and Enterprise, detected from your account | Browser sign-in, then paste the authorization code | Five-hour and weekly windows |
| **ChatGPT (Codex)** | ChatGPT plans that include Codex, labeled with the plan reported by the Codex usage endpoint (for example, Plus or Pro) | One-time device code in the browser | Five-hour and weekly windows, plus any additional limits the endpoint reports |
| **Antigravity** | Google accounts with Antigravity access, labeled with the tier reported by Google | Google browser sign-in, or an existing `agy` CLI login | Gemini and Claude & GPT pools, each with five-hour and, when reported, weekly windows |
| **Antigravity** | Google accounts with Antigravity access, labeled with the tier reported by `agy` | An existing `agy` CLI login | Gemini and Claude & GPT pools, each with five-hour and, when reported, weekly windows |

Each connection tracks one account per service. Provider usage endpoints are unofficial, so available windows and plan labels can change without notice.

Expand All @@ -75,14 +75,14 @@ LLMits runs as a menu-bar accessory without a Dock icon. Click its menu-bar item

- **Claude:** complete authorization in the browser, then paste the authorization code or full callback URL into LLMits.
- **ChatGPT:** enter the one-time code on the page opened by LLMits and wait for approval.
- **Antigravity:** complete Google sign-in in your browser when Antigravity.app is installed. The `agy` CLI alone cannot supply LLMits' browser OAuth callback; sign in with `agy` in Terminal to use its existing login instead. CLI connections read the full `/usage` quota report without copying or changing its credentials.
- **Antigravity:** sign in by running `agy` in Terminal first. LLMits runs `agy`'s read-only `/usage` report and never reads, copies, or changes its credentials. Set `ANTIGRAVITY_CLI_PATH` if `agy` is not in `~/.local/bin`, `/opt/homebrew/bin`, or `/usr/local/bin`.

Open **Settings → Connections** to disconnect a provider from LLMits. Disconnecting an `agy` connection does not sign out of the CLI. In **Settings → Menu Bar**, drag selected providers or use the arrow buttons to change their order.

After connecting, the menu bar shows the configured used or remaining percentage. Pin up to three connected providers in the popover, and drag their rows in Settings to set their order. Antigravity uses the Gemini pool by default; choose Claude & GPT in Settings if preferred. Each pool prefers its five-hour window and falls back to weekly when available. Open the popover for every connected provider's available quota windows, reset times, plan details, and refresh status.

> [!NOTE]
> Running with `swift run` produces an ad-hoc-signed development executable. macOS may ask for Keychain access again after a rebuild because the executable identity changes. Choose **Always Allow** for the current build, or use a consistently signed app bundle for stable Keychain trust.
> LLMits keeps Claude and ChatGPT credentials in a single Keychain item and reads it only when a connected provider refreshes, so launching with nothing connected never prompts. Running with `swift run` produces an ad-hoc-signed development executable, so macOS may ask for Keychain access again after a rebuild because the executable identity changes. Choose **Always Allow** for the current build, or use a consistently signed app bundle for stable Keychain trust.

## Install

Expand All @@ -103,7 +103,7 @@ curl -fsSL https://raw.githubusercontent.com/aryan1306/LLMits/main/install.sh |

You can also download `LLMits.dmg` from the [latest release](https://github.com/aryan1306/LLMits/releases/latest), open it, and drag LLMits into Applications.

Release builds are currently ad-hoc signed. On first launch, macOS may require you to right-click LLMits and choose **Open**. A future Developer ID-signed and notarized release will remove this extra confirmation.
Release builds are signed with a self-signed LLMits certificate, which keeps Keychain access approved across updates. The certificate is not issued by Apple, so on first launch macOS may require you to right-click LLMits and choose **Open**. A future Developer ID-signed and notarized release will remove this extra confirmation.

Packaged apps check GitHub for a newer published release at launch, every six hours, and after wake. When an update is available, the popover's refresh control becomes a small download icon. Click it for **Update and Relaunch**, **Refresh quotas**, or **Cancel**. To check right away, choose **Check Now** under **Settings → Updates**; manual checks are limited to one per minute and pause while GitHub's API rate limit is in effect. After confirmation, LLMits downloads and verifies the release, replaces the app in its current location, then relaunches. Updating requires write access to the app's containing folder. Development builds started with `swift run` do not self-update.

Expand All @@ -113,7 +113,7 @@ Packaged apps check GitHub for a newer published release at launch, every six ho
- `LLMitsCore` contains provider-neutral quota models, OAuth flows, endpoint adapters, persistence, formatting, and refresh policy.
- Claude usage comes from the OAuth usage endpoint and is enriched with profile data for the plan label.
- ChatGPT usage comes from the Codex usage endpoint associated with the authorized account.
- Antigravity usage comes from Google's Cloud Code quota summary, with model-level fallback when the summary is unavailable. The unofficial remote response may omit weekly windows.
- Antigravity usage comes from `agy`'s `/usage` report. The unofficial remote response may omit weekly windows.
- Quota values are clamped and normalized before display, with a five-hour window preferred in the menu bar and weekly usage used as a fallback.

See [Architecture](docs/ARCHITECTURE.md) and [Roadmap](docs/ROADMAP.md).
Expand All @@ -138,6 +138,14 @@ Create a universal app and DMG locally:
./scripts/build-dmg.sh 0.1.0
```

Without signing variables the app is ad-hoc signed. To sign with the release certificate, pass a PKCS#12 identity:

```sh
CODESIGN_P12_PATH=path/to/llmits-codesign.p12 CODESIGN_P12_PASSWORD=… ./scripts/build-dmg.sh 0.1.0
```

The script imports the identity into a temporary keychain, signs, and removes it. Tagged releases require the `CODESIGN_P12_BASE64` and `CODESIGN_P12_PASSWORD` repository secrets. Keep the certificate unchanged: a new certificate changes the app's identity and makes every user approve Keychain access again.

Artifacts are written to `dist/`. GitHub Actions runs CI on pushes and pull requests. A manual **Build DMG** workflow run uploads the DMG as a workflow artifact; pushing a tag such as `v0.1.0` also creates a GitHub Release with the DMG and SHA-256 checksum.

The test suite covers authorization primitives, credential storage, provider response parsing, quota calculations, persistence, diagnostics, refresh policy, and update detection. The live updater integration test is skipped by default. To run it against the latest GitHub release, build an older packaged version in a temporary directory and run:
Expand Down
110 changes: 0 additions & 110 deletions Sources/LLMitsApp/AntigravityAuthorization.swift

This file was deleted.

Loading