diff --git a/.gitignore b/.gitignore
index db4c6d9..b186605 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
dist
-node_modules
\ No newline at end of file
+node_modules
+.DS_Store
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7e90152..98eaed6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
+- [2026-07-17] [the readme is the landing page: real captures only](https://github.com/RubricLab/tokenmaxx/commit/0db404df5a3d7ac4fa7fadcc8c4d7d1a74139ae4)
+- [2026-07-17] [drop the asset factory: fixture renders, remotion, brand generator](https://github.com/RubricLab/tokenmaxx/commit/3de71c1a13402ff8abb24bb111cdca42a25d5267)
- [2026-07-17] [routing becomes a plain tokenmaxx on/off in settings
The accounts title is quiet when on (just the auto policy) and shows '✗ off'
diff --git a/README.md b/README.md
index d290b4c..73ee4d4 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,16 @@
-
-
-
-
-
+
-
+
-**Juggle rate limits across all your Codex and Claude Code accounts — and see every token you burn.**
+**Juggle rate limits across all your Codex and Claude Code accounts. See every token you burn.**
-
macOS · [Bun](https://bun.sh) · [tokenmaxx.sh](https://tokenmaxx.sh) · a [Rubric Labs](https://rubriclabs.com) project
+
macOS · [Bun](https://bun.sh) · a [Rubric Labs](https://rubriclabs.com) project · not affiliated with OpenAI or Anthropic
-
+
-
-
-
-
-
+
@@ -29,95 +21,103 @@ bun add -g tokenmaxx
```
```bash
-tokenmaxx login codex # sign in (isolated; existing sessions untouched)
+tokenmaxx login codex # sign in; your existing sessions stay untouched
tokenmaxx login claude
-tokenmaxx install # route native codex & claude through tokenmaxx
+tokenmaxx install # route native codex & claude through tokenmaxx
-codex # use the clients as before — tokenmaxx injects the account
-claude
+codex # use your clients as before
+claude # tokenmaxx injects the account, per request
```
## What it does
-You have more than one Codex and Claude subscription, and you keep hitting the five-hour or
-weekly limit on whichever you're using. tokenmaxx runs a loopback proxy on `127.0.0.1:8459`
-that reads the **active account per request** and injects its credential — so switching takes
-effect on the very next request, even mid-turn, with the clients running unmodified.
-Credentials stay in the macOS Keychain; nothing but opaque references touches disk.
-
-Both providers report live rate-limit state on every response, and the proxy reads it as
-traffic streams by — so tokenmaxx always knows exactly how full the active account is, with
-zero extra requests. Anything speaking the Anthropic or OpenAI Responses API can point at
-`http://127.0.0.1:8459/anthropic` or `/openai` and get the same juggling — the proxy doesn't
-care which harness is on the other end.
-
-## Dashboard
-
-Run `tokenmaxx` for a live dashboard. **Accounts** shows every account and its rate-limit
-windows, colored by pressure; press space to expand one. **Analytics** is a combined
-token-throughput view (tokens/time across every account and both providers) with total
-tokens, the **≈ API-list-price value** you're extracting from your flat subscriptions, a
-per-model breakdown, and the input / output / cache-read / cache-write split. Tokens are
-metered by the proxy as responses stream by — every number is cross-checkable against the
-clients' own session logs — and it never buffers or delays them. **Settings** tunes
-auto-rotation, the switch threshold, and dwell per provider, applied live.
+You run a fleet of coding agents, and they burn through the five-hour or
+weekly limit on whichever subscription you're using:
-
-
-
-
-
+
+
+
+tokenmaxx runs a loopback proxy that reads the active account on every request
+and injects its credential, so a switch lands on the very next request, even
+mid-turn, with your clients running unmodified. Credentials stay in the macOS
+Keychain; nothing but opaque references touches disk.
+
+## The dashboard
+
+Run `tokenmaxx`. **Accounts** shows every account and its live rate-limit
+windows, colored by pressure, with plan tier and reset countdowns inline. Rows
+sort by pressure; the ● marks where traffic is going right now.
+
+
+
+
+
+**Analytics** is combined token throughput across all accounts and both
+providers, with the ≈ API-list-price value you're pulling from your flat
+subscriptions. Tokens are metered as responses stream by, never buffered, so
+every number is cross-checkable against your clients' own session logs. Press
+`m` for the full pricing breakdown per model.
+
+
+
+
+
+**Settings** holds the master on/off per provider, then auto-rotation, the
+switch threshold, and cooldown, applied live.
+
+
+
## Auto-rotation
-Turn it on and tokenmaxx moves off an account the moment its fullest window crosses your
-threshold, onto the one with the most headroom — mid-turn, on the next request. Pressure is
-read off every response, so a burst from a fleet of parallel agents can't outrun the switch;
-if an account still hits its hard limit mid-flight, the proxy rotates and retries that request
-on the next account before your client ever sees the 429. It's off by default; enabling it is
+Turn it on and tokenmaxx steps off an account the moment its fullest window
+crosses your threshold, onto the one with the most headroom. If an account
+still hits its hard limit mid-flight, the proxy rotates and retries that
+request before your client ever sees the 429. Off by default; enabling it is
your confirmation that your provider permits this use.
```bash
tokenmaxx auto both on --threshold 90 # or: codex | claude … off
```
-
-
-
-
-
-
-
+## How it works
+
+A single loopback proxy on `127.0.0.1:8459`, and the clients you already use.
+
+- **Account per request.** The proxy reads which account is active for each
+ request and injects its credential. Switching lands on the next request.
+- **Pressure read for free.** Both providers report rate-limit state on every
+ response; the proxy reads it as traffic streams by, so it always knows how
+ full the active account is, with zero extra requests.
+- **Harness-agnostic.** Anything speaking the Anthropic or OpenAI Responses API
+ can point at `/anthropic` or `/openai` and get the same juggling.
## Commands
-| Command | |
-|---|---|
-| `tokenmaxx` | Live dashboard |
-| `tokenmaxx login ` | Sign in (idempotent) |
-| `tokenmaxx install` · `uninstall` | Route native clients · restore config |
-| `tokenmaxx switch ` | Make an account active |
-| `tokenmaxx auto [--threshold N]` | Auto-rotation |
-| `tokenmaxx list` · `status` · `refresh` · `doctor` | Accounts · JSON · re-probe · checks |
+```text
+tokenmaxx live dashboard
+tokenmaxx login sign in; isolated, idempotent
+tokenmaxx install route native codex & claude
+tokenmaxx uninstall restore native config
+tokenmaxx switch make an account active
+tokenmaxx auto [--threshold N]
+tokenmaxx list | status | refresh | doctor
+```
Env: `TOKENMAXX_HOME`, `TOKENMAXX_PROXY_PORT`, `TOKENMAXX_THEME`.
## Not affiliated
-tokenmaxx is an independent [Rubric Labs](https://rubriclabs.com) project. It is **not** an
-official product of, affiliated with, or endorsed by OpenAI or Anthropic. Use only accounts
-you own, and only where the relevant terms permit account automation.
-
-## Credits
-
-Inspired by [`codex-account-switcher`](https://github.com/Sls0n/codex-account-switcher) by
-[Sls0n](https://github.com/Sls0n) — thanks for the spark.
+An independent [Rubric Labs](https://rubriclabs.com) project, not an official
+product of, affiliated with, or endorsed by OpenAI or Anthropic. Use only
+accounts you own, and only where the relevant terms permit account automation.
+Inspired by [codex-account-switcher](https://github.com/Sls0n/codex-account-switcher).
diff --git a/assets/.gitignore b/assets/.gitignore
deleted file mode 100644
index 6b86746..0000000
--- a/assets/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-# Intermediates — regenerated from assets.config.ts + the fixture seam.
-.tmp/
-tapes/
-
-# generated/ IS committed: the README embeds those images, so GitHub needs them
-# in the repo. Regenerate any time with `bun run assets`.
diff --git a/assets/README.md b/assets/README.md
deleted file mode 100644
index 97a3404..0000000
--- a/assets/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# tokenmaxx assets
-
-Every image and video in the docs is generated from source — no hand-editing.
-The real tokenmaxx TUI is rendered against **synthetic fixtures** with a **pinned
-clock**, so frames are deterministic and need no daemon, network, or real
-accounts.
-
-## How it works
-
-```
-src/tui/fixtures.ts fabricates schema-valid AnalyticsSnapshots (scenarios)
- │
- ▼
-tokenmaxx --fixture the real TUI renders that snapshot (hidden seam,
- │ pinned by TOKENMAXX_NOW / TOKENMAXX_THEME / TZ)
- ▼
-assets/assets.config.ts the shot list: scenario × view × theme × size
- │
- ▼
-assets/render.ts drives VHS to frame each shot (macOS window chrome)
- ▼
-assets/generated/*.png committed build products the README embeds
-```
-
-## Regenerate
-
-```bash
-bun run assets # all screenshots, dark + light
-bun run assets:screens accounts analytics # only matching shots
-```
-
-Requirements (macOS):
-
-```bash
-brew install vhs gifski
-brew install --cask font-jetbrains-mono-nerd-font # braille + block + symbol glyphs
-```
-
-## Iterating
-
-- **Change what a shot shows** → edit the scenario in `../src/tui/fixtures.ts`
- (or add a new one) and/or the shot's `keys`/`height` in `assets.config.ts`.
-- **Add a shot** → append to `SHOTS` in `assets.config.ts`, re-run.
-- **Preview one live** without rendering:
-
- ```bash
- TOKENMAXX_FIXTURE=oneHot TOKENMAXX_THEME=dark TZ=America/Los_Angeles \
- bun run src/index.ts # press ←/→, space, 1–5 to explore
- ```
-
-## Layout
-
-| Path | Role |
-|---|---|
-| `assets.config.ts` | shot list + render constants (source of truth) |
-| `render.ts` | VHS driver (screenshots) |
-| `generated/` | committed PNGs the README embeds + `manifest.json` |
-| `tapes/`, `.tmp/` | regenerated intermediates (gitignored) |
-
-Scenarios live in `../src/tui/fixtures.ts`: `cruising`, `oneHot`, `rotated`,
-`onboarding`.
diff --git a/assets/assets.config.ts b/assets/assets.config.ts
deleted file mode 100644
index 20add58..0000000
--- a/assets/assets.config.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-// The single source of truth for every generated screenshot. Each Shot renders
-// the real tokenmaxx TUI through the hidden fixture seam (src/tui/fixtures.ts) at a
-// pinned clock, then frames it with VHS (macOS window chrome + shadowless dark
-// backdrop). Edit this list — never the images — and re-run `bun run
-// assets:screens`.
-
-export type ThemeName = 'dark' | 'light'
-export const THEMES: readonly ThemeName[] = ['dark', 'light']
-
-// Rendering constants shared by every frame. JetBrainsMono Nerd Font is required
-// (brew install --cask font-jetbrains-mono-nerd-font) — it carries the braille,
-// block, and symbol glyphs the TUI draws. LetterSpacing 0 keeps text tight.
-export const FONT = 'JetBrainsMono Nerd Font'
-export const FONT_SIZE = 15
-export const WIDTH = 1200
-
-// The desktop the framed window sits on: near-black for dark, soft grey for
-// light, so the window edge always reads.
-export const MARGIN_FILL: Record = {
- dark: '#0b0d10',
- light: '#e6ebf2'
-}
-
-// Pins the header clock. FIXTURE_NOW (see src/tui/fixtures.ts) reads as a clean
-// 9:42 AM in Pacific, so every frame shows the same time.
-export const FIXTURE_TZ = 'America/Los_Angeles'
-
-export interface Shot {
- // Output basename: generated/-.png
- name: string
- // Fixture scenario from src/tui/fixtures.ts.
- scenario: string
- // Canvas height in pixels (width is fixed). Tune per view so the content fills
- // the frame without a tall empty gap.
- height: number
- // Keys sent after first paint to reach a view (e.g. ["Right"] → Analytics,
- // ["Space"] → expand the selected account). Each key waits for a repaint.
- keys?: string[]
- // false shows the "native routing is off" banner (onboarding).
- installed?: boolean
- // One-line caption for the docs manifest; not rendered into the frame.
- caption: string
-}
-
-export const SHOTS: readonly Shot[] = [
- {
- caption: 'Every account and its live rate-limit windows, at a glance.',
- height: 560,
- name: 'accounts',
- scenario: 'cruising'
- },
- {
- caption: 'The active Codex account is nearly out — auto-rotate is about to fire.',
- height: 560,
- name: 'hot',
- scenario: 'oneHot'
- },
- {
- caption: 'Press space: plan tier, per-window reset countdowns, account id.',
- height: 720,
- keys: ['Space'],
- name: 'expanded',
- scenario: 'cruising'
- },
- {
- caption: 'Combined token throughput across all accounts and both providers.',
- height: 720,
- keys: ['Tab'],
- name: 'analytics',
- scenario: 'cruising'
- },
- {
- caption: 'Total tokens and ≈ API value over the timeframe.',
- height: 720,
- keys: ['Tab', 'Right'],
- name: 'analytics-week',
- scenario: 'oneHot'
- },
- {
- caption: 'Auto-rotation, threshold, and dwell — tuned per provider, applied live.',
- height: 560,
- keys: ['Tab', 'Tab'],
- name: 'settings',
- scenario: 'cruising'
- },
- {
- caption: 'A fresh install: sign in, then route native codex & claude.',
- height: 470,
- installed: false,
- name: 'onboarding',
- scenario: 'onboarding'
- }
-]
diff --git a/assets/brand/logo-dark.svg b/assets/brand/logo-dark.svg
deleted file mode 100644
index 26a41b4..0000000
--- a/assets/brand/logo-dark.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
- tokenmaxx
- rate-limit control plane · Codex + Claude Code
-
-
-
-
-
-
diff --git a/assets/brand/logo-light.svg b/assets/brand/logo-light.svg
deleted file mode 100644
index f51d724..0000000
--- a/assets/brand/logo-light.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
- tokenmaxx
- rate-limit control plane · Codex + Claude Code
-
-
-
-
-
-
diff --git a/assets/brand/rubric-mark.svg b/assets/brand/rubric-mark.svg
deleted file mode 100644
index 5023d0b..0000000
--- a/assets/brand/rubric-mark.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/assets/flagship.ts b/assets/flagship.ts
deleted file mode 100644
index 0525e74..0000000
--- a/assets/flagship.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env bun
-// Renders the flagship composite (dark + light): the real tokenmaxx dashboard beside
-// mock Claude Code and Codex sessions, arranged in a tmux layout and framed by
-// VHS. The layout is built by flagship/build.sh; the sessions are the static
-// mock-claude.sh / mock-codex.sh (modelled on the real TUIs). Deterministic.
-//
-// bun run assets/flagship.ts
-
-import { spawnSync } from 'node:child_process'
-import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
-import { join } from 'node:path'
-import { FIXTURE_NOW } from '../src/tui/fixtures.ts'
-import { FONT, FONT_SIZE, MARGIN_FILL, THEMES, type ThemeName } from './assets.config.ts'
-
-const assetsDir = import.meta.dir
-const outDir = join(assetsDir, 'generated')
-const tapeDir = join(assetsDir, 'tapes')
-const tmpDir = join(assetsDir, '.tmp')
-for (const dir of [outDir, tapeDir, tmpDir]) {
- mkdirSync(dir, { recursive: true })
-}
-
-const vhs = existsSync('/opt/homebrew/bin/vhs') ? '/opt/homebrew/bin/vhs' : 'vhs'
-const buildScript = join(assetsDir, 'flagship', 'build.sh')
-
-// The whole terminal background must match the tokenmaxx theme, otherwise the mock
-// panes (which don't paint their own background) show VHS's default and their
-// theme-coloured text vanishes. Single-pane shots don't need this — tokenmaxx fills
-// the frame — but the flagship's mock panes do.
-const TERM_BG: Record = { dark: '#0b0d10', light: '#fbfcfe' }
-const TERM_FG: Record = { dark: '#e6e6e6', light: '#1c2430' }
-
-function tape(theme: ThemeName, png: string, gif: string): string {
- return [
- `Output "${gif}"`,
- `Set Theme '{ "background": "${TERM_BG[theme]}", "foreground": "${TERM_FG[theme]}" }'`,
- `Set FontFamily "${FONT}"`,
- `Set FontSize ${FONT_SIZE - 1}`,
- 'Set LetterSpacing 0',
- 'Set Width 1560',
- 'Set Height 860',
- 'Set Padding 22',
- 'Set Margin 46',
- `Set MarginFill "${MARGIN_FILL[theme]}"`,
- 'Set WindowBar Colorful',
- 'Set WindowBarSize 40',
- 'Set BorderRadius 12',
- 'Set TypingSpeed 1ms',
- `Env TOKENMAXX_NOW "${FIXTURE_NOW}"`,
- `Type "THEME=${theme} bash ${buildScript}"`,
- 'Enter',
- 'Sleep 9s',
- `Screenshot "${png}"`,
- ''
- ].join('\n')
-}
-
-let ok = 0
-const failed: string[] = []
-for (const theme of THEMES) {
- const base = `flagship-${theme}`
- const png = join(outDir, `${base}.png`)
- const gif = join(tmpDir, `${base}.gif`)
- const tapePath = join(tapeDir, `${base}.tape`)
- writeFileSync(tapePath, tape(theme, png, gif))
- spawnSync('rm', ['-f', png])
- let landed = false
- for (let attempt = 1; attempt <= 4 && !landed; attempt += 1) {
- spawnSync(vhs, [tapePath], { stdio: 'ignore' })
- // build.sh runs tmux inside VHS's own shell, but kill any stray session too.
- spawnSync('tmux', ['kill-session', '-t', 'fs'], { stdio: 'ignore' })
- landed = existsSync(png)
- if (!landed) {
- Bun.sleepSync(1500)
- }
- }
- if (landed) {
- ok += 1
- console.log(` ok ${base}.png`)
- } else {
- failed.push(base)
- console.log(` FAIL ${base}.png`)
- }
-}
-
-console.log(
- `\n${ok} rendered, ${failed.length} failed${failed.length ? `: ${failed.join(', ')}` : ''}`
-)
-process.exitCode = failed.length > 0 ? 1 : 0
diff --git a/assets/flagship/build.sh b/assets/flagship/build.sh
deleted file mode 100755
index 67f9946..0000000
--- a/assets/flagship/build.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-# Composes the flagship layout inside the current terminal and attaches:
-# left = the real tokenmaxx dashboard (fixture, no daemon)
-# right-top = a mock Claude Code session
-# right-bottom= a mock Codex session
-# All three panes are created before their commands run, so each renders at its
-# final size (the tokenmaxx fixture does not repaint on resize).
-set -u
-theme="${THEME:-dark}"
-now="${TOKENMAXX_NOW:-1784133720000}"
-dir="$(cd "$(dirname "$0")" && pwd)"
-repo="$(cd "$dir/../.." && pwd)"
-bun="$(command -v bun)"
-cols=$(tput cols)
-rows=$(tput lines)
-[ "$theme" = "light" ] && border="fg=#c7cedb" || border="fg=#2a3038"
-
-tmux kill-session -t fs 2>/dev/null || true
-tmux new-session -d -s fs -x "$cols" -y "$rows"
-tmux set -t fs status off \; set -t fs pane-border-style "$border" \; \
- set -t fs pane-active-border-style "$border"
-
-# Right column at 46% (tokenmaxx keeps the wider left), then split it in half.
-tmux split-window -h -t fs:0.0 -l 46%
-tmux split-window -v -t fs:0.1 -l 52%
-
-tmux send-keys -t fs:0.0 \
- "clear; TOKENMAXX_FIXTURE=oneHot TOKENMAXX_THEME=$theme TOKENMAXX_NOW=$now TZ=America/Los_Angeles $bun run $repo/src/index.ts" Enter
-tmux send-keys -t fs:0.1 "clear; THEME=$theme bash $dir/mock-claude.sh" Enter
-tmux send-keys -t fs:0.2 "clear; THEME=$theme bash $dir/mock-codex.sh" Enter
-tmux select-pane -t fs:0.0
-sleep 6
-tmux attach -t fs
diff --git a/assets/flagship/mock-claude.sh b/assets/flagship/mock-claude.sh
deleted file mode 100755
index 4e628f6..0000000
--- a/assets/flagship/mock-claude.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env bash
-# A believable, static Claude Code session for the flagship composite — modelled
-# on the real v2.1.210 TUI (rounded header, ❯ prompt, ● assistant marker, diff
-# summary, status line). Synthetic content; no real session. THEME=dark|light.
-set -u
-theme="${THEME:-dark}"
-if [ "$theme" = "light" ]; then
- fg=$'\e[38;2;28;36;48m'; dim=$'\e[38;2;90;100;114m'; faint=$'\e[38;2;170;178;189m'
-else
- fg=$'\e[38;2;230;230;230m'; dim=$'\e[38;2;139;147;161m'; faint=$'\e[38;2;75;81;92m'
-fi
-clay=$'\e[38;2;209;119;87m'; grn=$'\e[38;2;58;208;122m'; red=$'\e[38;2;235;90;104m'
-b=$'\e[1m'; r=$'\e[0m'
-printf '\e[2J\e[H'
-printf '\n'
-printf ' %s%sClaude Code%s %s~/code/rubrot · Opus 4.8 · Max 20×%s\n' "$b" "$clay" "$r" "$dim" "$r"
-printf '\n'
-printf ' %s❯%s %swire the inbox webhook to the bot runner%s\n' "$clay" "$r" "$fg" "$r"
-printf '\n'
-printf ' %s●%s %sAdded the webhook route and a replay guard.%s\n' "$clay" "$r" "$fg" "$r"
-printf ' %s⎿%s %ssrc/inbox/webhook.ts%s %s+34%s %s-2%s\n' "$faint" "$r" "$dim" "$r" "$grn" "$r" "$red" "$r"
-printf ' %ssrc/inbox/webhook.test.ts%s %s+51%s\n' "$dim" "$r" "$grn" "$r"
-printf '\n'
-printf ' %s●%s %sAll 128 tests pass. Deploy to metal?%s\n' "$clay" "$r" "$fg" "$r"
-printf '\n'
-printf ' %s──────────────────────────────────────────────%s\n' "$faint" "$r"
-printf ' %s❯%s %sdo it%s%s▏%s\n' "$clay" "$r" "$fg" "$r" "$dim" "$r"
-printf ' %s──────────────────────────────────────────────%s\n' "$faint" "$r"
-printf ' %s⏵⏵ accept edits · 2 files · esc to interrupt%s\n' "$dim" "$r"
-tput civis 2>/dev/null || true
-sleep 3600
diff --git a/assets/flagship/mock-codex.sh b/assets/flagship/mock-codex.sh
deleted file mode 100755
index 0d07c32..0000000
--- a/assets/flagship/mock-codex.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-# A believable, static Codex session for the flagship composite — modelled on the
-# real v0.144.1 TUI (>_ OpenAI Codex banner with model/directory/permissions, •
-# notices, › prompt, status line). Synthetic content. THEME=dark|light.
-set -u
-theme="${THEME:-dark}"
-if [ "$theme" = "light" ]; then
- fg=$'\e[38;2;28;36;48m'; dim=$'\e[38;2;90;100;114m'; faint=$'\e[38;2;170;178;189m'
-else
- fg=$'\e[38;2;230;230;230m'; dim=$'\e[38;2;139;147;161m'; faint=$'\e[38;2;75;81;92m'
-fi
-cyan=$'\e[38;2;120;196;196m'; grn=$'\e[38;2;58;208;122m'
-b=$'\e[1m'; r=$'\e[0m'
-printf '\e[2J\e[H'
-printf '\n'
-printf ' %s╭────────────────────────────────────────────╮%s\n' "$faint" "$r"
-printf ' %s│%s %s%s>_ OpenAI Codex%s %s(v0.144.1)%s %s│%s\n' "$faint" "$r" "$b" "$cyan" "$r" "$dim" "$r" "$faint" "$r"
-printf ' %s│%s %smodel:%s gpt-5.6-sol %s/model%s %s│%s\n' "$faint" "$r" "$dim" "$r" "$dim" "$r" "$faint" "$r"
-printf ' %s│%s %sdirectory:%s ~/code/rubrot %s│%s\n' "$faint" "$r" "$dim" "$r" "$faint" "$r"
-printf ' %s╰────────────────────────────────────────────╯%s\n' "$faint" "$r"
-printf '\n'
-printf ' %s› %sextract the selector into a pure function%s\n' "$cyan" "$fg" "$r"
-printf '\n'
-printf ' %s•%s %sExtracted selectRotation; added 7 cases.%s\n' "$cyan" "$r" "$fg" "$r"
-printf ' %s└%s %ssrc/selection.ts%s %s· 74 passing%s\n' "$faint" "$r" "$dim" "$r" "$grn" "$r"
-printf '\n'
-printf ' %s•%s %sThreshold check is now side-effect free.%s\n' "$cyan" "$r" "$fg" "$r"
-printf '\n'
-printf ' %s› %s%srun /review on my changes%s\n' "$cyan" "$r" "$dim" "$r"
-printf '\n'
-printf ' %sgpt-5.6-sol default · ~/code/rubrot%s\n' "$faint" "$r"
-tput civis 2>/dev/null || true
-sleep 3600
diff --git a/assets/generated/accounts-dark.png b/assets/generated/accounts-dark.png
deleted file mode 100644
index 8b0043c..0000000
Binary files a/assets/generated/accounts-dark.png and /dev/null differ
diff --git a/assets/generated/accounts-light.png b/assets/generated/accounts-light.png
deleted file mode 100644
index 6560f39..0000000
Binary files a/assets/generated/accounts-light.png and /dev/null differ
diff --git a/assets/generated/analytics-dark.png b/assets/generated/analytics-dark.png
deleted file mode 100644
index 4802011..0000000
Binary files a/assets/generated/analytics-dark.png and /dev/null differ
diff --git a/assets/generated/analytics-light.png b/assets/generated/analytics-light.png
deleted file mode 100644
index 39f5d99..0000000
Binary files a/assets/generated/analytics-light.png and /dev/null differ
diff --git a/assets/generated/analytics-week-dark.png b/assets/generated/analytics-week-dark.png
deleted file mode 100644
index a01a4f1..0000000
Binary files a/assets/generated/analytics-week-dark.png and /dev/null differ
diff --git a/assets/generated/analytics-week-light.png b/assets/generated/analytics-week-light.png
deleted file mode 100644
index 000fcaf..0000000
Binary files a/assets/generated/analytics-week-light.png and /dev/null differ
diff --git a/assets/generated/expanded-dark.png b/assets/generated/expanded-dark.png
deleted file mode 100644
index 3cafe90..0000000
Binary files a/assets/generated/expanded-dark.png and /dev/null differ
diff --git a/assets/generated/expanded-light.png b/assets/generated/expanded-light.png
deleted file mode 100644
index 8485191..0000000
Binary files a/assets/generated/expanded-light.png and /dev/null differ
diff --git a/assets/generated/flagship-dark.png b/assets/generated/flagship-dark.png
deleted file mode 100644
index 4bdde3f..0000000
Binary files a/assets/generated/flagship-dark.png and /dev/null differ
diff --git a/assets/generated/flagship-light.png b/assets/generated/flagship-light.png
deleted file mode 100644
index 202a430..0000000
Binary files a/assets/generated/flagship-light.png and /dev/null differ
diff --git a/assets/generated/hot-dark.png b/assets/generated/hot-dark.png
deleted file mode 100644
index 37c2206..0000000
Binary files a/assets/generated/hot-dark.png and /dev/null differ
diff --git a/assets/generated/hot-light.png b/assets/generated/hot-light.png
deleted file mode 100644
index 48c2f7f..0000000
Binary files a/assets/generated/hot-light.png and /dev/null differ
diff --git a/assets/generated/manifest.json b/assets/generated/manifest.json
deleted file mode 100644
index 2a0482d..0000000
--- a/assets/generated/manifest.json
+++ /dev/null
@@ -1,30 +0,0 @@
-[
- {
- "caption": "Every account and its live rate-limit windows, at a glance.",
- "name": "accounts"
- },
- {
- "caption": "The active Codex account is nearly out — auto-rotate is about to fire.",
- "name": "hot"
- },
- {
- "caption": "Press space: plan tier, per-window reset countdowns, account id.",
- "name": "expanded"
- },
- {
- "caption": "Combined token throughput across all accounts and both providers.",
- "name": "analytics"
- },
- {
- "caption": "Total tokens and ≈ API value over the timeframe.",
- "name": "analytics-week"
- },
- {
- "caption": "Auto-rotation, threshold, and dwell — tuned per provider, applied live.",
- "name": "settings"
- },
- {
- "caption": "A fresh install: sign in, then route native codex & claude.",
- "name": "onboarding"
- }
-]
diff --git a/assets/generated/onboarding-dark.png b/assets/generated/onboarding-dark.png
deleted file mode 100644
index 5aa4fd6..0000000
Binary files a/assets/generated/onboarding-dark.png and /dev/null differ
diff --git a/assets/generated/onboarding-light.png b/assets/generated/onboarding-light.png
deleted file mode 100644
index 6dab7ab..0000000
Binary files a/assets/generated/onboarding-light.png and /dev/null differ
diff --git a/assets/generated/settings-dark.png b/assets/generated/settings-dark.png
deleted file mode 100644
index 26bf913..0000000
Binary files a/assets/generated/settings-dark.png and /dev/null differ
diff --git a/assets/generated/settings-light.png b/assets/generated/settings-light.png
deleted file mode 100644
index 267bde4..0000000
Binary files a/assets/generated/settings-light.png and /dev/null differ
diff --git a/assets/generated/switch-dark.gif b/assets/generated/switch-dark.gif
deleted file mode 100644
index 770b9cb..0000000
Binary files a/assets/generated/switch-dark.gif and /dev/null differ
diff --git a/assets/generated/switch-light.gif b/assets/generated/switch-light.gif
deleted file mode 100644
index 225f5c0..0000000
Binary files a/assets/generated/switch-light.gif and /dev/null differ
diff --git a/assets/generated/timelapse-dark.gif b/assets/generated/timelapse-dark.gif
deleted file mode 100644
index 7f27da0..0000000
Binary files a/assets/generated/timelapse-dark.gif and /dev/null differ
diff --git a/assets/generated/timelapse-light.gif b/assets/generated/timelapse-light.gif
deleted file mode 100644
index 86cbdd6..0000000
Binary files a/assets/generated/timelapse-light.gif and /dev/null differ
diff --git a/assets/render.ts b/assets/render.ts
deleted file mode 100644
index 5861de5..0000000
--- a/assets/render.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env bun
-// Renders every Shot in assets.config.ts to a framed PNG (dark + light) by
-// driving the real tokenmaxx TUI through the fixture seam with VHS. Deterministic:
-// no daemon, no network, a pinned clock. Re-run any time; images are build
-// products under generated/.
-//
-// bun run assets/render.ts # all shots, both themes
-// bun run assets/render.ts accounts # only shots whose name matches an arg
-
-import { spawnSync } from 'node:child_process'
-import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
-import { join } from 'node:path'
-import { FIXTURE_NOW } from '../src/tui/fixtures.ts'
-import {
- FIXTURE_TZ,
- FONT,
- FONT_SIZE,
- MARGIN_FILL,
- SHOTS,
- type Shot,
- THEMES,
- type ThemeName,
- WIDTH
-} from './assets.config.ts'
-
-const assetsDir = import.meta.dir
-const repo = join(assetsDir, '..')
-const outDir = join(assetsDir, 'generated')
-const tapeDir = join(assetsDir, 'tapes')
-const tmpDir = join(assetsDir, '.tmp')
-for (const dir of [outDir, tapeDir, tmpDir]) {
- mkdirSync(dir, { recursive: true })
-}
-
-const bun = process.execPath
-const vhs = existsSync('/opt/homebrew/bin/vhs') ? '/opt/homebrew/bin/vhs' : 'vhs'
-const entry = join(repo, 'src/index.ts')
-
-function tape(shot: Shot, theme: ThemeName, pngPath: string, gifPath: string): string {
- const installed = shot.installed === false ? 'false' : 'true'
- const keyLines = (shot.keys ?? []).flatMap(key => [key, 'Sleep 900ms'])
- return [
- `Output "${gifPath}"`,
- `Set FontFamily "${FONT}"`,
- `Set FontSize ${FONT_SIZE}`,
- 'Set LetterSpacing 0',
- `Set Width ${WIDTH}`,
- `Set Height ${shot.height}`,
- 'Set Padding 24',
- 'Set Margin 50',
- `Set MarginFill "${MARGIN_FILL[theme]}"`,
- 'Set WindowBar Colorful',
- 'Set WindowBarSize 40',
- 'Set BorderRadius 12',
- 'Set TypingSpeed 1ms',
- `Env TOKENMAXX_FIXTURE "${shot.scenario}"`,
- `Env TOKENMAXX_THEME "${theme}"`,
- `Env TOKENMAXX_NOW "${FIXTURE_NOW}"`,
- `Env TOKENMAXX_INSTALLED "${installed}"`,
- `Env TZ "${FIXTURE_TZ}"`,
- `Type "${bun} run ${entry}"`,
- 'Enter',
- 'Sleep 6s',
- ...keyLines,
- `Screenshot "${pngPath}"`,
- ''
- ].join('\n')
-}
-
-const filter = process.argv.slice(2)
-const wanted = (shot: Shot) => filter.length === 0 || filter.some(f => shot.name.includes(f))
-
-let ok = 0
-const failed: string[] = []
-for (const theme of THEMES) {
- for (const shot of SHOTS) {
- if (!wanted(shot)) {
- continue
- }
- const base = `${shot.name}-${theme}`
- const png = join(outDir, `${base}.png`)
- const gif = join(tmpDir, `${base}.gif`)
- const tapePath = join(tapeDir, `${base}.tape`)
- writeFileSync(tapePath, tape(shot, theme, png, gif))
- rmSync(png, { force: true })
- // VHS is occasionally flaky when spawned in quick succession (its browser +
- // ttyd backend races); verify the frame landed and retry a few times, with a
- // short settle between attempts, before giving up.
- let landed = false
- for (let attempt = 1; attempt <= 4 && !landed; attempt += 1) {
- spawnSync(vhs, [tapePath], { stdio: 'ignore' })
- landed = existsSync(png)
- if (!landed) {
- Bun.sleepSync(1500)
- }
- }
- if (landed) {
- ok += 1
- console.log(` ok ${base}.png`)
- } else {
- failed.push(base)
- console.log(` FAIL ${base}.png`)
- }
- }
-}
-
-writeFileSync(
- join(outDir, 'manifest.json'),
- `${JSON.stringify(
- SHOTS.map(shot => ({ caption: shot.caption, name: shot.name })),
- null,
- 2
- )}\n`
-)
-
-console.log(
- `\n${ok} rendered, ${failed.length} failed${failed.length ? `: ${failed.join(', ')}` : ''}`
-)
-process.exitCode = failed.length > 0 ? 1 : 0
diff --git a/media/accounts.png b/media/accounts.png
new file mode 100644
index 0000000..9340b52
Binary files /dev/null and b/media/accounts.png differ
diff --git a/media/analytics.png b/media/analytics.png
new file mode 100644
index 0000000..3e9ee6c
Binary files /dev/null and b/media/analytics.png differ
diff --git a/media/fleet.gif b/media/fleet.gif
new file mode 100644
index 0000000..c39e899
Binary files /dev/null and b/media/fleet.gif differ
diff --git a/media/relay.gif b/media/relay.gif
new file mode 100644
index 0000000..99961c6
Binary files /dev/null and b/media/relay.gif differ
diff --git a/media/rubric-mark.svg b/media/rubric-mark.svg
new file mode 100644
index 0000000..0eb721f
--- /dev/null
+++ b/media/rubric-mark.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/media/settings.png b/media/settings.png
new file mode 100644
index 0000000..37d9777
Binary files /dev/null and b/media/settings.png differ
diff --git a/media/wordmark.png b/media/wordmark.png
new file mode 100644
index 0000000..176c04a
Binary files /dev/null and b/media/wordmark.png differ
diff --git a/package.json b/package.json
index 0897cd8..041d843 100644
--- a/package.json
+++ b/package.json
@@ -46,10 +46,6 @@
"url": "https://github.com/RubricLab/tokenmaxx.git"
},
"scripts": {
- "assets": "bun run assets:screens && bun run assets:flagship && bun run assets:site",
- "assets:flagship": "bun run assets/flagship.ts",
- "assets:screens": "bun run assets/render.ts",
- "assets:site": "mkdir -p site/img && cp assets/brand/wordmark-dark.png assets/brand/rubric-mark.svg assets/generated/flagship-dark.png assets/generated/accounts-dark.png assets/generated/analytics-dark.png assets/generated/metrics-dark.png assets/generated/settings-dark.png assets/generated/switch-dark.gif site/img/",
"bleed": "bun x npm-check-updates -u",
"build": "bun run clean && bun build ./src/index.ts --target bun --outdir dist --external '@opentui/*' && cp bin/launcher.cjs dist/launcher.cjs && chmod 755 dist/index.js dist/launcher.cjs",
"check": "bun run typecheck && bun x biome check . && bun test",
@@ -63,5 +59,5 @@
"post-commit": "bun x @rubriclab/package post-commit"
},
"type": "module",
- "version": "0.0.32"
+ "version": "0.0.34"
}
diff --git a/remotion/.gitignore b/remotion/.gitignore
deleted file mode 100644
index f9e6631..0000000
--- a/remotion/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules/
-out/
-package-lock.json
diff --git a/remotion/package.json b/remotion/package.json
deleted file mode 100644
index 5dfe51e..0000000
--- a/remotion/package.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "tokenmaxx-remotion",
- "private": true,
- "version": "0.0.0",
- "description": "Data-driven timelapse + switch-interaction videos for tokenmaxx docs",
- "scripts": {
- "render": "bun run render.ts",
- "studio": "remotion studio src/index.ts"
- },
- "dependencies": {
- "@remotion/cli": "4.0.286",
- "remotion": "4.0.286",
- "react": "19.0.0",
- "react-dom": "19.0.0"
- },
- "devDependencies": {
- "@types/react": "19.0.0"
- }
-}
diff --git a/remotion/render.ts b/remotion/render.ts
deleted file mode 100644
index c370063..0000000
--- a/remotion/render.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env node
-// Renders each composition in both themes to an mp4, then converts to a
-// high-quality gif (ffmpeg two-pass palette) into ../assets/generated/.
-//
-// cd remotion && node render.ts # (or: npm run render)
-
-const { spawnSync } = require("node:child_process");
-const { mkdirSync } = require("node:fs");
-const { join } = require("node:path");
-
-const here = __dirname;
-const outDir = join(here, "out");
-const gifDir = join(here, "..", "assets", "generated");
-mkdirSync(outDir, { recursive: true });
-mkdirSync(gifDir, { recursive: true });
-
-const ffmpeg = "/opt/homebrew/bin/ffmpeg";
-const GIF_WIDTH = 960;
-const GIF_FPS = 24;
-
-// [composition id, output gif basename]
-const comps = [
- ["UsageTimelapse", "timelapse"],
- ["SwitchRotation", "switch"],
-];
-const themes = ["dark", "light"];
-
-function run(cmd, args, cwd) {
- const r = spawnSync(cmd, args, { cwd: cwd || here, stdio: "inherit" });
- if (r.status !== 0) {
- throw new Error(`${cmd} exited ${r.status}`);
- }
-}
-
-for (const [id, base] of comps) {
- for (const theme of themes) {
- const mp4 = join(outDir, `${base}-${theme}.mp4`);
- console.log(`\n▶ ${id} (${theme}) → ${mp4}`);
- run("npx", [
- "remotion",
- "render",
- "src/index.ts",
- id,
- mp4,
- `--props={"themeName":"${theme}"}`,
- "--log=error",
- "--overwrite",
- ]);
-
- const gif = join(gifDir, `${base}-${theme}.gif`);
- const palette = join(outDir, `${base}-${theme}-palette.png`);
- const filters = `fps=${GIF_FPS},scale=${GIF_WIDTH}:-1:flags=lanczos`;
- console.log(` → gif ${gif}`);
- run(ffmpeg, ["-y", "-i", mp4, "-vf", `${filters},palettegen=stats_mode=diff`, palette]);
- run(ffmpeg, [
- "-y",
- "-i",
- mp4,
- "-i",
- palette,
- "-lavfi",
- `${filters}[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=3`,
- gif,
- ]);
- }
-}
-
-console.log("\n✓ videos + gifs written to assets/generated/");
diff --git a/remotion/src/Frame.tsx b/remotion/src/Frame.tsx
deleted file mode 100644
index 45c586b..0000000
--- a/remotion/src/Frame.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import type React from "react";
-import { AbsoluteFill } from "remotion";
-import { MONO, type Theme } from "./theme";
-
-const Dot: React.FC<{ color: string }> = ({ color }) => (
-
-);
-
-// A macOS-style window on a desktop surface, matching the screenshots' chrome so
-// the videos read as the same product.
-export const Frame: React.FC<{
- theme: Theme;
- title?: string;
- children: React.ReactNode;
-}> = ({ theme, title, children }) => (
-
-
-
-
-
-
- {title ? (
- {title}
- ) : null}
-
-
{children}
-
-
-);
-
-// The tokenmaxx wordmark, used as a small brand mark in the corner of each video.
-export const Wordmark: React.FC<{ theme: Theme; size?: number }> = ({ theme, size = 20 }) => (
-
- tokenmaxx
-
-);
diff --git a/remotion/src/Root.tsx b/remotion/src/Root.tsx
deleted file mode 100644
index 43883ba..0000000
--- a/remotion/src/Root.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Composition } from "remotion";
-import { SwitchRotation } from "./SwitchRotation";
-import { UsageTimelapse } from "./UsageTimelapse";
-
-// Both comps take a themeName prop so dark + light render from one definition
-// (see render.ts, which passes --props).
-export const RemotionRoot: React.FC = () => (
- <>
-
-
- >
-);
diff --git a/remotion/src/SwitchRotation.tsx b/remotion/src/SwitchRotation.tsx
deleted file mode 100644
index 05add1d..0000000
--- a/remotion/src/SwitchRotation.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion";
-import { Frame, Wordmark } from "./Frame";
-import { MONO, pressure, type Theme, type ThemeName, themes } from "./theme";
-
-const ROW_H = 68;
-const SWITCH = 102; // frame the rotation commits
-
-const Meter: React.FC<{ theme: Theme; percent: number; width: number }> = ({
- theme,
- percent,
- width,
-}) => {
- const color = pressure(theme, percent);
- return (
-
-
-
{Math.round(percent)}%
-
- );
-};
-
-const Row: React.FC<{
- theme: Theme;
- email: string;
- active: boolean;
- percent: number;
-}> = ({ theme, email, active, percent }) => (
-
-
- {active ? "●" : "○"}
-
-
- {email}
-
- 5h
-
-
-);
-
-export const SwitchRotation: React.FC<{ themeName: ThemeName }> = ({ themeName }) => {
- const theme = themes[themeName];
- const frame = useCurrentFrame();
- const { fps } = useVideoConfig();
-
- // dexter climbs to the limit, then rotation hands off to the cool standby.
- const dexterPct = interpolate(frame, [0, SWITCH], [72, 97], {
- extrapolateLeft: "clamp",
- extrapolateRight: "clamp",
- });
- const shipPct = 21;
- const switched = frame >= SWITCH;
-
- // The active highlight slides from row 0 to row 1 on the switch.
- const slide = spring({ frame: frame - SWITCH, fps, config: { damping: 16, mass: 0.7 } });
- const highlightTop = interpolate(slide, [0, 1], [0, ROW_H]);
-
- const rotating = interpolate(frame, [SWITCH - 8, SWITCH, SWITCH + 26, SWITCH + 40], [0, 1, 1, 0], {
- extrapolateLeft: "clamp",
- extrapolateRight: "clamp",
- });
- const done = interpolate(frame, [SWITCH + 26, SWITCH + 44], [0, 1], {
- extrapolateLeft: "clamp",
- extrapolateRight: "clamp",
- });
- const generation = switched ? 8 : 7;
-
- return (
-
-
-
-
OpenAI · Codex
-
- ⟳ auto-rotate 95% · gen {generation}
-
-
-
-
-
-
-
-
-
- ⟳ dexter@ hit 96% on its 5-hour window — rotating…
-
-
0 ? -28 : 0 }}>
- ✓ switched to ship@rubriclabs.com · the next request uses it, mid-turn · gen 8
-
-
-
-
- );
-};
diff --git a/remotion/src/UsageTimelapse.tsx b/remotion/src/UsageTimelapse.tsx
deleted file mode 100644
index 39198c8..0000000
--- a/remotion/src/UsageTimelapse.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import { interpolate, useCurrentFrame, useVideoConfig } from "remotion";
-import { Frame, Wordmark } from "./Frame";
-import { MONO, pressure, type ThemeName, themes } from "./theme";
-
-// A synthetic 5-hour-sawtooth-over-24h usage series — the same shape the TUI
-// charts, generated deterministically here so the video needs no runtime data.
-function series(n: number): number[] {
- const out: number[] = [];
- for (let i = 0; i < n; i += 1) {
- const t = i / (n - 1);
- const cyclePos = (t * 4.8) % 1; // ~4.8 five-hour cycles across the day
- const ramp = Math.min(1, cyclePos / 0.9);
- const peak = 62 + 30 * t; // the day trends busier
- const wobble = 3 * Math.sin(i * 1.7);
- out.push(Math.max(0, Math.min(100, peak * ramp + wobble)));
- }
- return out;
-}
-
-const N = 220;
-const DATA = series(N);
-
-const CHART = { w: 1040, h: 300, x: 0, y: 0 };
-
-function path(values: number[], upto: number): string {
- const pts = values.slice(0, Math.max(2, upto));
- return pts
- .map((v, i) => {
- const x = (i / (N - 1)) * CHART.w;
- const y = CHART.h - (v / 100) * CHART.h;
- return `${i === 0 ? "M" : "L"}${x.toFixed(1)},${y.toFixed(1)}`;
- })
- .join(" ");
-}
-
-const Pill: React.FC<{ label: string; active: boolean; theme: (typeof themes)[ThemeName] }> = ({
- label,
- active,
- theme,
-}) => (
-
- {label}
-
-);
-
-export const UsageTimelapse: React.FC<{ themeName: ThemeName }> = ({ themeName }) => {
- const theme = themes[themeName];
- const frame = useCurrentFrame();
- const { durationInFrames } = useVideoConfig();
-
- // Ease the reveal, hold full at the end.
- const reveal = interpolate(frame, [8, durationInFrames - 20], [0, 1], {
- extrapolateLeft: "clamp",
- extrapolateRight: "clamp",
- });
- const frontier = Math.max(1, Math.floor(reveal * (N - 1)));
- const now = DATA[frontier] ?? 0;
- const shown = DATA.slice(0, frontier + 1);
- const peak = Math.max(...shown);
- const avg = shown.reduce((s, v) => s + v, 0) / shown.length;
- const color = pressure(theme, now);
- const frontierX = (frontier / (N - 1)) * CHART.w;
- const frontierY = CHART.h - (now / 100) * CHART.h;
-
- return (
-
-
-
-
- Codex · dexter@rubriclabs.com ·{" "}
- Pro
-
-
- {["1h", "5h", "24h", "7d", "31d"].map((l) => (
-
- ))}
-
-
-
-
- 100
-
-
- 0
-
-
- usage over 24 hours
- {[0.25, 0.5, 0.75].map((g) => (
-
- ))}
-
-
-
-
-
-
- {shown.length > 2 ? (
- <>
-
-
-
-
- >
- ) : null}
-
-
-
-
-
- now
- {Math.round(now)}%
- · peak {Math.round(peak)}% · avg {Math.round(avg)}%
-
-
-
-
-
- );
-};
diff --git a/remotion/src/index.ts b/remotion/src/index.ts
deleted file mode 100644
index f31c790..0000000
--- a/remotion/src/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { registerRoot } from "remotion";
-import { RemotionRoot } from "./Root";
-
-registerRoot(RemotionRoot);
diff --git a/remotion/src/theme.ts b/remotion/src/theme.ts
deleted file mode 100644
index cc590e1..0000000
--- a/remotion/src/theme.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-// The tokenmaxx palette, mirrored from src/tui/format.ts so the videos read as the
-// same product as the screenshots.
-
-export interface Theme {
- fg: string;
- dim: string;
- faint: string;
- accent: string;
- bg: string;
- panel: string;
- selected: string;
- border: string;
- good: string;
- warn: string;
- bad: string;
- desktop: string; // the surface the window sits on
-}
-
-export const dark: Theme = {
- fg: "#e6e6e6",
- dim: "#8b93a1",
- faint: "#4b515c",
- accent: "#5ab0ff",
- bg: "#0b0d10",
- panel: "#0f1216",
- selected: "#1b2330",
- border: "#2a3038",
- good: "#3ad07a",
- warn: "#f0a83a",
- bad: "#ff5f6e",
- desktop: "#05070a",
-};
-
-export const light: Theme = {
- fg: "#1c2430",
- dim: "#5a6472",
- faint: "#aab2bd",
- accent: "#0b62d6",
- bg: "#fbfcfe",
- panel: "#f2f4f8",
- selected: "#e3e9f2",
- border: "#c7cedb",
- good: "#1f9d57",
- warn: "#b9770f",
- bad: "#d23b48",
- desktop: "#dfe4ec",
-};
-
-export const themes = { dark, light } as const;
-export type ThemeName = keyof typeof themes;
-
-// Usage-pressure colour, matching pressureColor() in the TUI.
-export function pressure(theme: Theme, percent: number): string {
- if (percent >= 85) {
- return theme.bad;
- }
- if (percent >= 60) {
- return theme.warn;
- }
- return theme.good;
-}
-
-export const MONO = "ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace";