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
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CODEX_SWITCH_CODEX_HOME=
CODEX_SWITCH_VAULT_ROOT=
CODEX_SWITCH_CODEX_BIN=
CODEX_SWITCH_SKIP_LAUNCH=
CODEX_SWITCH_QUOTA_TTL_MS=
CODEX_SWITCH_LOG_LEVEL=
CODEX_HOME=
OPENAI_API_KEY=
54 changes: 54 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: CI

on:
pull_request:
push:
branches:
- main

permissions:
contents: read

jobs:
validate:
name: Validate (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10.33.1

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Typecheck
run: pnpm typecheck

- name: Test
run: pnpm test

- name: Lint
run: pnpm lint

- name: Build
run: pnpm build

- name: Pack dry run
run: npm pack --dry-run
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dist/
out/
coverage/
.turbo/
output/
.DS_Store
*.log
*.sqlite
Expand All @@ -12,6 +13,6 @@ coverage/
*.tgz
.env
.env.*
!.env.example
.codex-switch/
packages/dashboard/.next/
plans/
12 changes: 7 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Changelog

## 0.1.0
## 1.0.7

- Added the pnpm workspace with shared, CLI, and dashboard packages
- Added vault-backed auth switching, TUI picker, log ingestion, and local dashboard flows
- Added standalone packaging, publish bins, and repo validation scripts
- Fixed session lock exclusivity, atomic auth replacement, watcher attribution, local day buckets, and add-page poll cancellation
- Added the pnpm workspace with shared and CLI packages.
- Added vault-backed auth switching, TUI picker, and CLI quota flows.
- Added deterministic `cs ls` quota bars for 5h and 7d limits.
- Removed the local browser UI package, browser launch command, browser dependencies, standalone UI packaging, stale screenshot artifacts, and unused session-history code.
- Added publish bins and repo validation scripts.
- Fixed session lock exclusivity and atomic auth replacement.
52 changes: 34 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# codex-switch

`codex-switch` keeps native Codex behavior intact while letting you switch between multiple OAuth accounts.
`codex-switch` keeps native Codex behavior intact while letting you switch between multiple OAuth accounts from the terminal.

It does not proxy API traffic and it does not split `~/.codex/` into per-account homes. Instead it snapshots each account's `auth.json` into a vault at `~/.codex-switch/accounts/` and swaps the active snapshot into `~/.codex/auth.json` before launching Codex.

## What ships

- `cs` / `codex-switch`: CLI wrapper for add, use, run, sync, remove, dashboard launch
- Next.js dashboard on localhost for list, switch, history, and add-account flow
- `cs` / `codex-switch`: CLI wrapper for add, use, run, sync, remove, current, and list
- bare `cs` TUI account picker
- local SQLite state at `~/.codex-switch/state.sqlite`
- read-only session ingestion plus on-demand quota probing with a 2-minute cache
- on-demand quota probing with a 2-minute cache
- terminal quota bars in `cs ls`

## Requirements

Expand Down Expand Up @@ -38,10 +39,22 @@ Use an account:
pnpm --filter @codex-switch/cli exec node dist/index.js use personal
```

Launch the dashboard:
List accounts and cached quota:

```bash
pnpm --filter @codex-switch/cli exec node dist/index.js dash
pnpm --filter @codex-switch/cli exec node dist/index.js ls
```

Force-refresh cached quota:

```bash
pnpm --filter @codex-switch/cli exec node dist/index.js ls --refresh
```

Machine-readable list output:

```bash
pnpm --filter @codex-switch/cli exec node dist/index.js ls --json
```

## Global install flow
Expand All @@ -52,15 +65,24 @@ After packaging, the intended user flow is:
npm i -g codex-switch
cs add --name personal
cs use personal
cs dash
cs ls --refresh
```

Force-refresh cached quota:
## Quota Display

```bash
pnpm --filter @codex-switch/cli exec node dist/index.js ls --refresh
`cs ls` prints a three-column quota table:

```text
╭───────────────────────────────┬──────────────────────────────┬──────────────────────────────────────╮
│ Account (1) │ 5h Limit │ Weekly Limit │
├───────────────────────────────┼──────────────────────────────┼──────────────────────────────────────┤
│ * personal │ [████████░░░░░░░░░░░░] 42% │ [█████████████████░░░] 84% │
│ (Pro / user@example.com) │ (resets 16:52) │ (resets 13:04 on 29 Apr) │
╰───────────────────────────────┴──────────────────────────────┴──────────────────────────────────────╯
```

The display uses a monochrome ink palette: bold for emphasis and dim text for secondary/used quota cells. Columns are auto-aligned by visible terminal width, ignoring ANSI style codes. Bars clamp to 0-100%; `█` means quota left and `░` means quota used/unavailable. Unknown quota renders as a fully shaded bar with `--`. Re-auth and stale states are shown in the account cell instead of fake quota.

## Recommended shell aliases

PowerShell:
Expand Down Expand Up @@ -92,16 +114,10 @@ alias codex='cs run'
## Troubleshooting

- `Could not locate the bindings file`:
Run `pnpm install` again after allowing native builds for `better-sqlite3` and `sharp`.
Run `pnpm install` again after allowing native builds for `better-sqlite3`.
- `No active account recorded`:
Add or use an account first.
- `Close the running Codex session first`:
Another `cs use` / `cs run` process still owns the runtime lock.
- No quota data yet:
Quota is now fetched on demand from ChatGPT when the dashboard or `cs ls --refresh` asks for it. If refresh fails, the UI shows the last cached value or a re-auth banner instead of parsing Codex logs.

## Developer utilities

```bash
pnpm inspect:codex-logs
```
Quota is fetched on demand from ChatGPT when `cs ls --refresh` asks for it. If refresh fails, the CLI shows the last cached value or a re-auth status.
29 changes: 10 additions & 19 deletions docs/code-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
## Monorepo Boundaries

- Keep shared filesystem paths, SQL schema, and cross-package types in `packages/shared`.
- Keep auth mutation, vault writes, swapping, lock handling, and process launching in `packages/cli`.
- Keep dashboard UI and local HTTP routes in `packages/dashboard`.
- Keep auth mutation, vault writes, swapping, lock handling, process launching, and CLI display in `packages/cli`.
- Do not reintroduce browser UI or local HTTP routes without a new plan.

## TypeScript and Module Rules

Expand All @@ -19,7 +19,6 @@
- `pnpm typecheck`
- `pnpm lint`
- `pnpm test`
- `pnpm inspect:codex-logs`

Run validation after code edits that affect runtime behavior.

Expand All @@ -28,18 +27,15 @@ Run validation after code edits that affect runtime behavior.
- Commands are registered in `packages/cli/src/index.ts`.
- Mutating commands should flow through the same swap/vault helpers rather than duplicate auth logic.
- Bare `cs` should remain a shortcut to the interactive picker.

## Dashboard Conventions

- App routes live under `packages/dashboard/app`.
- Read-only database access stays in `packages/dashboard/lib/db.ts`.
- Mutation routes should guard against cross-origin requests and call the CLI rather than reimplement auth changes inside the dashboard.
- Keep `cs ls --json` stable for scripts.
- Put deterministic terminal formatting in small helpers with focused tests.
- Use ASCII for quota bars so output is width-stable across terminals.

## SQLite Rules

- `state.sqlite` is the source of truth for dashboard reads.
- Writes go through the CLI-side DB helpers.
- Dashboard DB access must stay read-only with `query_only`.
- `state.sqlite` is the source of truth for local account and quota state.
- Writes go through CLI-side DB helpers.
- Read-only paths should open SQLite with readonly/query-only options when practical.

## File Safety Rules

Expand All @@ -59,20 +55,15 @@ Run validation after code edits that affect runtime behavior.
- `CODEX_SWITCH_VAULT_ROOT`
- `CODEX_SWITCH_CODEX_BIN`
- `CODEX_SWITCH_SKIP_LAUNCH`
- `CODEX_SWITCH_NO_OPEN`
- `CODEX_SWITCH_FORCE_DASH_BUILD`
- `CODEX_SWITCH_QUOTA_TTL_MS`
- `CODEX_SWITCH_POLL_DISABLED`
- `CODEX_SWITCH_LOG_LEVEL`
- `CS_CLI_ENTRY`
- `CS_NODE_BINARY`

## Generated Artifact Policy

- Publish bins from `bin/`.
- Build CLI and shared packages into `dist/`.
- Keep dashboard standalone output under `.next/standalone`.
- `prepack` must rebuild and copy dashboard static/public assets into the standalone tree.
- `prepack` must rebuild shared before CLI.
- Package files should not include removed UI artifacts.

## Documentation Sync Rules

Expand Down
16 changes: 5 additions & 11 deletions docs/codebase-summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,31 @@

## Repo Shape

- `packages/shared`: shared types, paths, SQL schema, SQL queries
- `packages/cli`: commander-based CLI, vault logic, swap flow, TUI, watcher
- `packages/dashboard`: Next.js app, local API routes, charts, add/history pages
- `packages/shared`: shared types, paths, SQL schema
- `packages/cli`: commander-based CLI, vault logic, swap flow, TUI, quota display
- `bin`: publish-time bin shims
- `scripts`: packaging helpers
- `plans`: brainstorm + implementation plan artifacts

## Package Summary

- `@codex-switch/shared`: exports path helpers for `~/.codex` and `~/.codex-switch`, plus SQLite schema and query strings.
- `@codex-switch/cli`: owns account add/use/run/sync/remove flows, session locking, atomic writes, and the dashboard launcher.
- `@codex-switch/dashboard`: reads the shared SQLite state read-only and exposes a local dashboard plus local mutation routes that shell out to the CLI.
- `@codex-switch/shared`: exports path helpers for `~/.codex` and `~/.codex-switch`, plus SQLite schema and shared runtime types.
- `@codex-switch/cli`: owns account add/use/run/sync/remove/current/list flows, session locking, atomic writes, quota cache/probe orchestration, and terminal quota formatting.

## Primary Commands

- `pnpm build`
- `pnpm typecheck`
- `pnpm lint`
- `pnpm test`
- `pnpm inspect:codex-logs`

## Key Data Stores

- `~/.codex/auth.json`: active live auth used by native Codex
- `~/.codex/history.jsonl`: session history source
- `~/.codex/logs_2.sqlite`: structured log source
- `~/.codex-switch/accounts/*.json`: vault snapshots
- `~/.codex-switch/state.sqlite`: account/session/quota state
- `~/.codex-switch/state.sqlite`: account and quota state

## Main Runtime Paths

- CLI entry: `packages/cli/dist/index.js`
- Dashboard standalone server: `packages/dashboard/.next/standalone/packages/dashboard/server.js`
- Publish bins: `bin/codex-switch.js`, `bin/cs.js`
28 changes: 28 additions & 0 deletions docs/design-guidelines.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Design Guidelines

## Terminal Account List

- Keep `cs ls` scan-friendly with three columns: account/type/email, 5h limit, weekly limit.
- Use terminal block bars: `█` for quota left and `░` for quota used/unavailable.
- Use rounded Unicode table borders for the default terminal table.
- Auto-align columns by visible width and ignore ANSI color codes during width calculation.
- Use a monochrome ink palette only: bold for emphasis, dim for secondary text and used/unavailable quota cells. Avoid colorful status or quota palettes.
- Clamp quota percentages to 0-100% and round to whole numbers.
- Render unknown quota as a fully shaded `░` bar with `--`.
- Show re-auth and stale states as text. Do not invent quota values.
- Keep `--json` output for machines; terminal formatting is for humans.

## Text And Status

- Active account marker is `*`.
- Account names should be bold in supported terminals, with plan/email on the next line.
- Quota cells should put the bar and percent on the first line, then reset text on the next line.
- Terminal output should omit low-value metadata such as source and last-used when there is no stale/error state.
- Stale and re-auth status text should render only when it requires user attention, inside the account column.
- Do not print auth payloads, tokens, or raw vault file content.

## Layout Rules

- Use a text table for quota bars so accounts can be scanned row-by-row.
- Keep each line short enough for typical terminals.
- Use deterministic formatting so tests can assert exact bar output.
26 changes: 12 additions & 14 deletions docs/development-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,43 @@

## Current Status Summary

Implementation is materially complete for the planned v1 surface. Local validation is green. Remaining work is mostly live-account acceptance, packaging confidence, and publish readiness.
The product scope is now CLI-only. Core account switching, TUI picker, and on-demand quota probing are implemented. The removed browser UI scope is superseded by terminal quota bars in `cs ls`.

## Phase Status

| Phase | Status | Notes |
| --- | --- | --- |
| 1. Monorepo Setup | Completed | Workspace, packages, build/lint/typecheck wiring are in place. |
| 2. Vault and Core CLI Swap | In Progress | Core flows are implemented; native live-account smoke is still manual. |
| 3. TUI Picker and Quota Capture | Completed | Picker is implemented and quota now comes from on-demand backend probing instead of log parsing. |
| 4. Dashboard Core | Completed | Home/API/switch flows exist with cache-backed quota gauges; live UI smoke remains open. |
| 5. History Charts and OAuth Add | In Progress | Charts and add flow exist; real interaction smoke remains open. |
| 6. Packaging and Distribution | In Progress | Build/prepack/tarball checks pass; install and publish readiness still need manual proof. |
| 3. TUI Picker and Quota Capture | Completed | Picker is implemented and quota comes from on-demand backend probing. |
| 4. Terminal Quota Visibility | Completed | `cs ls` shows deterministic 5h and 7d quota bars plus stale/reauth status. |
| 5. Removed Browser UI Scope | Completed | The local browser UI package and command were removed from current product scope. |
| 6. Packaging and Distribution | In Progress | CLI-only package and temp global install smoke pass on Windows; publish readiness still needs live-account and cross-platform proof. |

## Completed Scope

- CLI command surface and TUI picker
- vault snapshot storage and active auth swap
- local SQLite schema and query layer
- history ingestion helpers plus on-demand quota probing
- local dashboard home/history/add pages
- standalone dashboard packaging
- local SQLite schema and quota cache helpers
- on-demand quota probing
- terminal quota bars for account list output
- CLI/shared-only package build path

## Validation Still Pending

- live `codex login` / `cs add` smoke
- live `cs use` / `cs run` smoke against real accounts
- native Codex tool fidelity checks after switch
- repeated swap durability testing
- global install smoke on Windows and one non-Windows platform
- global install smoke on one non-Windows platform

## Immediate Backlog

1. Perform native end-to-end smoke with real Codex auth.
2. Validate packaged install from tarball on another platform.
3. Decide whether to suppress or isolate the Next NFT tracing warning.
4. Add broader dashboard/API integration tests if the project continues beyond v1.
3. Consider `cs quota [account]` only if `cs ls` lacks enough detail in real use.

## Risks and Dependencies

- The project depends on Codex’s auth snapshot shape and the undocumented ChatGPT quota endpoint remaining usable.
- Packaging confidence depends on standalone Next output continuing to tolerate local terminal spawn helpers.
- The project depends on Codex's auth snapshot shape and the undocumented ChatGPT quota endpoint remaining usable.
- Real publish should wait for live-account smoke, not just local unit/integration-style checks.
Loading
Loading