Skip to content

Commit ca00312

Browse files
committed
tokenmaxx
0 parents  commit ca00312

78 files changed

Lines changed: 7713 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ci.yml‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
check:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: oven-sh/setup-bun@v2
14+
with:
15+
bun-version: latest
16+
- run: bun install --frozen-lockfile
17+
- run: bun run check
18+
- run: bun run build

‎.github/workflows/release.yml‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Release
2+
3+
# On every commit to main, release-please maintains a "Release PR" that bumps the
4+
# version and updates the changelog from conventional commits (feat:/fix:/…).
5+
# Merge that PR to cut a release; this same run then publishes to npm via Trusted
6+
# Publishing (OIDC — short-lived token, no NPM_TOKEN, automatic provenance).
7+
# While pre-launch, releases are 0.0.0-alpha.N and publish under the `alpha` tag.
8+
9+
on:
10+
push:
11+
branches: [main]
12+
workflow_dispatch:
13+
14+
permissions:
15+
contents: write
16+
pull-requests: write
17+
id-token: write
18+
19+
jobs:
20+
release:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: googleapis/release-please-action@v4
24+
id: release
25+
26+
- if: ${{ steps.release.outputs.release_created }}
27+
uses: actions/checkout@v4
28+
- if: ${{ steps.release.outputs.release_created }}
29+
uses: oven-sh/setup-bun@v2
30+
with:
31+
bun-version: latest
32+
- if: ${{ steps.release.outputs.release_created }}
33+
uses: actions/setup-node@v4
34+
with:
35+
node-version: 22
36+
registry-url: https://registry.npmjs.org
37+
# Trusted publishing needs npm >= 11.5.1; node 22 ships an older one.
38+
- if: ${{ steps.release.outputs.release_created }}
39+
run: npm install -g npm@latest
40+
- if: ${{ steps.release.outputs.release_created }}
41+
run: bun install --frozen-lockfile
42+
- if: ${{ steps.release.outputs.release_created }}
43+
run: bun run build
44+
- if: ${{ steps.release.outputs.release_created }}
45+
run: npm publish --tag alpha

‎.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist
2+
node_modules

‎.release-please-manifest.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "0.0.0-alpha.0"
3+
}

‎LICENSE‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
go nuts

‎README.md‎

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<div align="center">
2+
3+
<picture>
4+
<source media="(prefers-color-scheme: dark)" srcset="assets/brand/logo-dark.svg">
5+
<source media="(prefers-color-scheme: light)" srcset="assets/brand/logo-light.svg">
6+
<img alt="tokenmaxx" src="assets/brand/logo-dark.svg" width="440">
7+
</picture>
8+
9+
<br/><br/>
10+
11+
**Juggle rate limits across all your Codex and Claude Code accounts — and see every token you burn.**
12+
13+
<sub>macOS · [Bun](https://bun.sh) · [tokenmaxx.sh](https://tokenmaxx.sh) · a [Rubric Labs](https://rubriclabs.com) project</sub>
14+
15+
<br/>
16+
17+
<picture>
18+
<source media="(prefers-color-scheme: dark)" srcset="assets/generated/flagship-dark.png">
19+
<source media="(prefers-color-scheme: light)" srcset="assets/generated/flagship-light.png">
20+
<img alt="tokenmaxx beside live Claude Code and Codex sessions" src="assets/generated/flagship-dark.png">
21+
</picture>
22+
23+
</div>
24+
25+
## Install
26+
27+
```bash
28+
bun add -g tokenmaxx@alpha # pre-launch — drop @alpha at the first stable release
29+
```
30+
31+
```bash
32+
tokenmaxx login codex # sign in (isolated; existing sessions untouched)
33+
tokenmaxx login claude
34+
tokenmaxx install # route native codex & claude through tokenmaxx
35+
36+
codex # use the clients as before — tokenmaxx injects the account
37+
claude
38+
```
39+
40+
## What it does
41+
42+
You have more than one Codex and Claude subscription, and you keep hitting the five-hour or
43+
weekly limit on whichever you're using. tokenmaxx runs a loopback proxy on `127.0.0.1:8459`
44+
that reads the **active account per request** and injects its credential — so switching takes
45+
effect on the very next request, even mid-turn, with the clients running unmodified.
46+
Credentials stay in the macOS Keychain; nothing but opaque references touches disk.
47+
48+
## Dashboard
49+
50+
Run `tokenmaxx` for a live dashboard. **Accounts** shows every account and its rate-limit
51+
windows, colored by pressure; press space to expand one. **Tab** switches to **Analytics** —
52+
a combined token-throughput view (tokens/time across every account and both providers) with
53+
total tokens, peak tok/hr, and the **≈ API-list-price value** you're extracting from your flat
54+
subscriptions. Tokens are metered by the proxy as responses stream by; it never buffers or
55+
delays them.
56+
57+
<div align="center">
58+
<picture>
59+
<source media="(prefers-color-scheme: dark)" srcset="assets/generated/timelapse-dark.gif">
60+
<source media="(prefers-color-scheme: light)" srcset="assets/generated/timelapse-light.gif">
61+
<img alt="token throughput charting live" src="assets/generated/timelapse-dark.gif" width="820">
62+
</picture>
63+
</div>
64+
65+
## Auto-rotation
66+
67+
Turn it on and tokenmaxx moves off an account the moment its fullest window crosses your
68+
threshold, onto the one with the most headroom — mid-turn, on the next request. It's off by
69+
default; enabling it is your confirmation that your provider permits this use.
70+
71+
```bash
72+
tokenmaxx auto both on --threshold 95 # or: codex | claude … off
73+
```
74+
75+
<div align="center">
76+
<picture>
77+
<source media="(prefers-color-scheme: dark)" srcset="assets/generated/switch-dark.gif">
78+
<source media="(prefers-color-scheme: light)" srcset="assets/generated/switch-light.gif">
79+
<img alt="an at-limit account rotating to a fresh one" src="assets/generated/switch-dark.gif" width="740">
80+
</picture>
81+
</div>
82+
83+
## Commands
84+
85+
| Command | |
86+
|---|---|
87+
| `tokenmaxx` | Live dashboard |
88+
| `tokenmaxx login <codex\|claude>` | Sign in (idempotent) |
89+
| `tokenmaxx install` · `uninstall` | Route native clients · restore config |
90+
| `tokenmaxx switch <codex\|claude> <email>` | Make an account active |
91+
| `tokenmaxx auto <codex\|claude\|both> <on\|off> [--threshold N]` | Auto-rotation |
92+
| `tokenmaxx list` · `status` · `refresh` · `doctor` | Accounts · JSON · re-probe · checks |
93+
94+
Env: `TOKENMAXX_HOME`, `TOKENMAXX_PROXY_PORT`, `TOKENMAXX_THEME`.
95+
96+
## Not affiliated
97+
98+
tokenmaxx is an independent [Rubric Labs](https://rubriclabs.com) project. It is **not** an
99+
official product of, affiliated with, or endorsed by OpenAI or Anthropic. Use only accounts
100+
you own, and only where the relevant terms permit account automation.
101+
102+
## Credits
103+
104+
Inspired by [`codex-account-switcher`](https://github.com/Sls0n/codex-account-switcher) by
105+
[Sls0n](https://github.com/Sls0n) — thanks for the spark.
106+
107+
<div align="center">
108+
<br/>
109+
<a href="https://rubriclabs.com"><img alt="Rubric Labs" src="assets/brand/rubric-mark.png" width="52"></a>
110+
<br/>
111+
<sub>Built by <a href="https://rubriclabs.com">Rubric Labs</a> · <a href="./LICENSE">go nuts</a></sub>
112+
</div>

‎assets/.gitignore‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Intermediates — regenerated from assets.config.ts + the fixture seam.
2+
.tmp/
3+
tapes/
4+
5+
# generated/ IS committed: the README embeds those images, so GitHub needs them
6+
# in the repo. Regenerate any time with `bun run assets`.

‎assets/README.md‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# tokenmaxx assets
2+
3+
Every image and video in the docs is generated from source — no hand-editing.
4+
The real tokenmaxx TUI is rendered against **synthetic fixtures** with a **pinned
5+
clock**, so frames are deterministic and need no daemon, network, or real
6+
accounts.
7+
8+
## How it works
9+
10+
```
11+
src/tui/fixtures.ts fabricates schema-valid AnalyticsSnapshots (scenarios)
12+
│
13+
▼
14+
tokenmaxx --fixture <name> the real TUI renders that snapshot (hidden seam,
15+
│ pinned by TOKENMAXX_NOW / TOKENMAXX_THEME / TZ)
16+
▼
17+
assets/assets.config.ts the shot list: scenario × view × theme × size
18+
│
19+
▼
20+
assets/render.ts drives VHS to frame each shot (macOS window chrome)
21+
▼
22+
assets/generated/*.png committed build products the README embeds
23+
```
24+
25+
## Regenerate
26+
27+
```bash
28+
bun run assets # all screenshots, dark + light
29+
bun run assets:screens accounts analytics # only matching shots
30+
```
31+
32+
Requirements (macOS):
33+
34+
```bash
35+
brew install vhs gifski
36+
brew install --cask font-jetbrains-mono-nerd-font # braille + block + symbol glyphs
37+
```
38+
39+
## Iterating
40+
41+
- **Change what a shot shows** → edit the scenario in `../src/tui/fixtures.ts`
42+
(or add a new one) and/or the shot's `keys`/`height` in `assets.config.ts`.
43+
- **Add a shot** → append to `SHOTS` in `assets.config.ts`, re-run.
44+
- **Preview one live** without rendering:
45+
46+
```bash
47+
TOKENMAXX_FIXTURE=oneHot TOKENMAXX_THEME=dark TZ=America/Los_Angeles \
48+
bun run src/index.ts # press ←/→, space, 1–5 to explore
49+
```
50+
51+
## Layout
52+
53+
| Path | Role |
54+
|---|---|
55+
| `assets.config.ts` | shot list + render constants (source of truth) |
56+
| `render.ts` | VHS driver (screenshots) |
57+
| `generated/` | committed PNGs the README embeds + `manifest.json` |
58+
| `tapes/`, `.tmp/` | regenerated intermediates (gitignored) |
59+
60+
Scenarios live in `../src/tui/fixtures.ts`: `cruising`, `oneHot`, `rotated`,
61+
`onboarding`.

‎assets/assets.config.ts‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// The single source of truth for every generated screenshot. Each Shot renders
2+
// the real tokenmaxx TUI through the hidden fixture seam (src/tui/fixtures.ts) at a
3+
// pinned clock, then frames it with VHS (macOS window chrome + shadowless dark
4+
// backdrop). Edit this list — never the images — and re-run `bun run
5+
// assets:screens`.
6+
7+
export type ThemeName = "dark" | "light";
8+
export const THEMES: readonly ThemeName[] = ["dark", "light"];
9+
10+
// Rendering constants shared by every frame. JetBrainsMono Nerd Font is required
11+
// (brew install --cask font-jetbrains-mono-nerd-font) — it carries the braille,
12+
// block, and symbol glyphs the TUI draws. LetterSpacing 0 keeps text tight.
13+
export const FONT = "JetBrainsMono Nerd Font";
14+
export const FONT_SIZE = 15;
15+
export const WIDTH = 1200;
16+
17+
// The desktop the framed window sits on: near-black for dark, soft grey for
18+
// light, so the window edge always reads.
19+
export const MARGIN_FILL: Record<ThemeName, string> = {
20+
dark: "#0b0d10",
21+
light: "#e6ebf2",
22+
};
23+
24+
// Pins the header clock. FIXTURE_NOW (see src/tui/fixtures.ts) reads as a clean
25+
// 9:42 AM in Pacific, so every frame shows the same time.
26+
export const FIXTURE_TZ = "America/Los_Angeles";
27+
28+
export interface Shot {
29+
// Output basename: generated/<name>-<theme>.png
30+
name: string;
31+
// Fixture scenario from src/tui/fixtures.ts.
32+
scenario: string;
33+
// Canvas height in pixels (width is fixed). Tune per view so the content fills
34+
// the frame without a tall empty gap.
35+
height: number;
36+
// Keys sent after first paint to reach a view (e.g. ["Right"] → Analytics,
37+
// ["Space"] → expand the selected account). Each key waits for a repaint.
38+
keys?: string[];
39+
// false shows the "native routing is off" banner (onboarding).
40+
installed?: boolean;
41+
// One-line caption for the docs manifest; not rendered into the frame.
42+
caption: string;
43+
}
44+
45+
export const SHOTS: readonly Shot[] = [
46+
{
47+
name: "accounts",
48+
scenario: "cruising",
49+
height: 560,
50+
caption: "Every account and its live rate-limit windows, at a glance.",
51+
},
52+
{
53+
name: "hot",
54+
scenario: "oneHot",
55+
height: 560,
56+
caption: "The active Codex account is nearly out — auto-rotate is about to fire.",
57+
},
58+
{
59+
name: "expanded",
60+
scenario: "cruising",
61+
height: 720,
62+
keys: ["Space"],
63+
caption: "Press space: plan tier, per-window reset countdowns, account id.",
64+
},
65+
{
66+
name: "analytics",
67+
scenario: "cruising",
68+
height: 720,
69+
keys: ["Tab"],
70+
caption: "Combined token throughput across all accounts and both providers.",
71+
},
72+
{
73+
name: "analytics-week",
74+
scenario: "oneHot",
75+
height: 720,
76+
keys: ["Tab", "Right"],
77+
caption: "Total tokens and ≈ API value over the timeframe.",
78+
},
79+
{
80+
name: "onboarding",
81+
scenario: "onboarding",
82+
height: 470,
83+
installed: false,
84+
caption: "A fresh install: sign in, then route native codex & claude.",
85+
},
86+
];

‎assets/brand/logo-dark.svg‎

Lines changed: 14 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)