AI Share Usage
Track how much of a shared Codex (ChatGPT) account each team member has used
this week, right in the VS Code status bar.
48% / 61%
The account is 61% through its weekly quota, and you have used 48% of your 1/N
share of it. Hover for a summary popup, click for a dashboard panel.
Language. The extension UI — status bar, tooltips, notifications,
dashboard and setup guide — follows the aiShareUsage.language setting
(auto, ko, en); auto picks Korean when VS Code's display language is
Korean and English otherwise. Command palette titles, the view name and the
settings descriptions follow VS Code's own display language instead, because
VS Code resolves them from package.nls.json before the extension starts.
How it works
Codex only reports the usage of the whole account, never per person. The
extension collects per-model token counts from your local OMO sessions,
discovered Senpi child sessions, Codex rollout logs, and Gajae Code sessions.
It uploads them to a Supabase project your team owns and fits per-model
weights against the movement of the account percentage. Those weights turn
each member's tokens back into a personal percentage. Tokens are additive, so
concurrent work by several members still adds up to the account total.
Requirements
- VS Code 1.96+ (or Cursor)
codex login completed on this machine
- A GitHub account (sign-in goes through GitHub OAuth)
- The one-line invite from your team admin — it carries the team server, so the
published extension needs no server coordinates from you
Getting started
Install the extension, then click the status bar item
AI Share Usage: Join with invite, or run AI Share Usage: Setup Guide from
the command palette. Members have three steps:
- Paste the invite your admin sent you (or click the invite link)
- Sign in with GitHub
- Open the dashboard
The invite is one line, ais1.<ref>.<key>.<group>, carrying the team server
address, its public key and the group code. There is nothing else to configure,
and it must stay inside the team channel: anyone holding it can join the group.
Admins do the rest, all of it inside the same guide: create the Supabase
project, supabase db push, the GitHub OAuth App, supabase config push, then
configure the server, create the group and copy the invite code or invite link
to send out. The guide also covers daily use, every setting, troubleshooting and
exactly which fields are sent to your server.
The weekly report
The dashboard's admin tab carries a Copy report button, for every member
rather than only the group's creator: it is a summary of your own group. One
click puts the whole quota window on the clipboard as Markdown — the range,
where the account opened and closed, every member with their tokens, quota,
API-equivalent cost and share of their own fair share, the models that did the
work, what the window is missing, the calibration the percentages rest on, and
where the current pace lands.
It keeps the marks the dashboard uses, and they mean the same thing in a chat
message: ≥ is a floor, ≈ is partly estimated, and — is withheld, so
nothing behind that figure could be priced and no percent is claimed. A
summary that dropped them would read as more certain than the page it came
from. ais report [--window last] [--format md|json] prints the same thing in
a terminal.
Collecting from a container
When VS Code runs on a host but omo or Codex run inside containers, their
sessions are written into the container's home. Bind-mount that home and name
it in aiShareUsage.extraHomes:
docker run -v $HOME/dev-box:/root -it my-image
{
// Absolute paths; ~ and $VAR are expanded.
"aiShareUsage.extraHomes": ["~/dev-box"],
// Or name one, for a machine label you choose:
// "aiShareUsage.extraHomes": [{ "path": "~/dev-box", "label": "box" }]
}
Each entry is read exactly like your own home — <home>/.omo/agent/sessions,
<home>/.codex/sessions, <home>/.gjc/agent/sessions for the sources you have
enabled, Senpi child sessions included. Usage found there is filed under the
machine <hostname>:<label>, where the label defaults to the directory's name,
so the container and its host stay separate rows in the per-machine breakdown.
A directory that is not there yet (or cannot be read) is simply not watched and
says so once in the output channel; it is picked up on a later refresh, without
a window reload. Adding or removing an entry needs no reload either.
Your Codex sign-in stays the one in your own home: an extra home's
.codex/auth.json is only ever compared with it, and a different account there
is logged as a warning while collection continues — what may be uploaded is
decided by the account-provenance rules, not by which directory a log sat in.
Finding those homes automatically
When the containers run on the same host as VS Code, the extension can ask
Docker where their homes are instead of you writing the paths down:
{
"aiShareUsage.discoverContainers": true,
// Empty means every running container; * matches any text.
"aiShareUsage.containerNamePatterns": ["dev-*", "ci"]
}
Every running container that matches is inspected, and each bind or volume
mount whose destination is a home (/root, /home/<user>) or one of the agent
directories (.omo, .codex, .gjc) becomes an extra home on its host-side
path, filed under the machine <hostname>:<container name>. A container that
stops loses its watchers on the next refresh and one that starts gains them,
without a window reload. An aiShareUsage.extraHomes entry you wrote yourself
always wins for the same path, label included, and your own home is never
collected twice.
Volume mounts resolve to /var/lib/docker/volumes/<name>/_data, which usually
only root can read. That is detected rather than hit: the home is skipped and
the output channel says which container and which path, so you can bind-mount
the home instead. No Docker socket, or a DOCKER_HOST that is not a local unix
socket, means the feature stays inactive and says so once.
The trust boundary. Being able to talk to /var/run/docker.sock is
root-equivalent on most hosts — whoever reaches it can start a privileged
container. That is why this is opt-in and off by default. What the extension
does with the socket is two read-only calls, GET /containers/json and
GET /containers/{id}/json; it never execs, never attaches, never creates, and
of the answer it reads only the container name, whether it is running, and the
mount table. Environment variables, labels and secrets are not read.
Development
npm install
npm run build
npm run lint
npm test
F5 runs the "Run Extension" launch configuration, which builds via the
npm: build task and opens an Extension Development Host.
Live Supabase check
npm test runs entirely against a mocked Supabase client. To exercise a real
project (rpcs, RLS, Realtime) end to end, point it at your project through the
environment and run:
set -a; . ./.env; set +a # SUPABASE_URL or SUPABASE_PROJECT_REF, see .env.example
npm run live-check
It reads the anon and service_role keys at runtime through
supabase projects api-keys (Supabase CLI login required; keys are never
written to disk or printed), creates throwaway users at @example.invalid,
runs one PASS/FAIL check per behaviour, deletes everything it created and exits
non-zero on any failure. Safe to rerun.
Releasing
npm run release # patch, or npm run release minor
scripts/release.mjs checks that the working tree is clean, runs
npm version <bump>, pushes the tag and creates the GitHub release. The
release workflow then builds the VSIX and publishes it to the VS Code
Marketplace and Open VSX. npm run package builds a VSIX locally.
License
MIT