seatledger: what your coding-agent seats and tokens buy
Uso de tokens do Claude Code e Codex e custo equivalente à API por dia, projeto e modelo, a partir da sua própria máquina, além de um sinalizador quando a tarifa muda. Servidor MCP local e CLI; sem conta.
Documentação
seatledger
O que os assentos e tokens do seu agente de codificação compraram, a partir da sua própria máquina — e quando a tarifa mudou.
npx seatledger
A imagem é a saída real de npx seatledger demo, que roda em histórico sintético. Ela é regenerada por pnpm screenshot e um teste falha se ela se desviar do que a CLI imprime.
O seatledger lê as transcrições que o Claude Code e o Codex já mantêm na sua máquina e informa:
- tokens e dólares equivalentes à API por dia, pasta de projeto, modelo e cliente;
- a velocidade com que você está queimando os limites que definiu e quando os alcançaria nesse ritmo;
- quando a tarifa mudou: o mesmo trabalho de repente custando mais tokens por requisição, leituras de cache caindo porque as gravações mudaram para uma vida útil de cache mais curta, mais tokens por turno após uma atualização do cliente, ou a janela de 5 horas do Codex enchendo mais rápido pelos mesmos tokens — com a data e a versão do cliente em que começa.
Nenhum fornecedor vai construir esse último item: é um alarme sobre a própria tarifa deles. O seatledger é MIT, não tem telemetria nem dependências em tempo de execução, e não precisa de conta. Ele não faz chamadas de rede a menos que você crie ou entre em um registro de equipe — e então seatledger push envia apenas agregados diários, que seatledger push --dry-run imprime por completo.
Comandos
npx seatledger # today and the last 7 days, your limits, vendor readings
npx seatledger report --since 30d --by project # --by day | project | model | client, --since 2026-09-01
npx seatledger rates # step changes over the last 90 days (--since, --client, --model)
npx seatledger limits set --window 5h --tokens 40M # or --usd 25; --window weekly; --client codex
npx seatledger limits # your limits, burn rate, projected time to each
npx seatledger mcp # read-only MCP server on stdio
npx seatledger demo # all of the above on synthetic history
# the team ledger (optional; the only commands that send anything)
npx seatledger team create --name "Acme platform" # a free team for up to 3; prints the invite link
npx seatledger team join <invite link> --as alice # your key goes to ~/.seatledger/team.json (0600)
npx seatledger push --dry-run # exactly what would be sent; sends nothing
npx seatledger push # this machine's daily aggregates to the team
npx seatledger team # the team's plan and your seat
Todo comando aceita --json, --client claude-code|codex, --claude-dir, --codex-dir, --no-cache e --quiet. Sem npm: npx github:agentwares/seatledger executa a mesma CLI a partir deste repositório (ele acompanha seu dist/ compilado).
O que ele lê
| Cliente | Onde | O que ele captura |
|---|---|---|
| Claude Code | ~/.claude/projects/**/*.jsonl (ou $CLAUDE_CONFIG_DIR/projects, ~/.config/claude/projects) | os usage de cada resposta (entrada, saída, leituras de cache, gravações de cache divididas em 5 minutos e 1 hora), modelo, version, requestId, carimbo de data/hora, pasta do diretório de trabalho |
| Codex CLI | ~/.codex/sessions/** e archived_sessions/ (ou $CODEX_HOME) | token_usage_record por resposta (versões mais novas) ou eventos token_count, o modelo do turno, cli_version e as leituras de rate_limits que o Codex grava |
Verificado em 7 de outubro de 2026 contra transcrições do Claude Code escritas por versões até 2.1.286 (o changelog estava em 2.1.292) e lançamentos do Codex escritos por 0.144–0.159, além do código-fonte do Codex em rust-v0.160.1 (TokenUsage, TokenUsageRecord, RateLimitSnapshot). Coisas que os formatos fazem e que um leitor ingênuo erra, e que o seatledger trata:
- O Claude Code grava uma resposta em várias linhas, e apenas a última carrega o
output_tokensfinal. O seatledger as mescla pormessage.id:requestIde mantém a maior contagem. - A mesma resposta aparece em mais de um arquivo (transcrições de subagentes, sessões retomadas e deixadas de lado); as requisições são deduplicadas entre arquivos.
- O
input_tokensdo Codex já inclui entrada em cache e entrada gravada em cache. - Campos desconhecidos são ignorados e uma linha cortada no meio da gravação é pulada, nunca fatal.
Não lido (ainda): o Gemini CLI não estava instalado onde isto foi construído, então seu registro local não pôde ser verificado contra arquivos reais; o armazenamento local do Cursor é um banco de dados SQLite não documentado e a cópia verificada não continha contagens de tokens por requisição. Nenhum dos dois é adivinhado.
Equivalente à API, não sua fatura
Os dólares são equivalentes à API: o que os mesmos tokens custariam nos preços de tabela da API do fornecedor. Em um assento Pro, Max, Plus ou Team você paga uma taxa fixa; isto é o que o uso desse assento teria custado na API, que é o número para comparar assentos, planos e meses. Está rotulado em todos os lugares em que aparece. Os preços vêm de uma tabela datada no pacote, com suas fontes:
- Anthropic, platform.claude.com/docs/en/about-claude/pricing, lido em 7 out 2026 — entrada base, gravações de cache de 5 minutos e 1 hora, leituras de cache, saída; modo rápido; 1,1x para inferência somente nos EUA.
- OpenAI, developers.openai.com/api/docs/pricing, lido em 7 out 2026 — entrada, entrada em cache, gravações de cache, saída e preços de contexto longo acima de 272K tokens de entrada.
Um modelo sem preço de tabela (o codex-auto-review interno do Codex, por exemplo) é contado em tokens e seus dólares são relatados como sem preço, nunca estimados.
O detector de mudança de tarifa
seatledger rates analisa, por cliente e modelo, dias completos com pelo menos 20 requisições:
| Métrica | O que um degrau nela geralmente significa |
|---|---|
| tokens por requisição | um prompt fixo maior (prompt do sistema, ferramentas, habilidades, definições de MCP) ou contexto maior |
| participação de leituras de cache nos tokens de prompt | o cache está sendo lido menos, gravado mais |
| gravações de cache por leitura de cache | o mesmo, como uma proporção |
| tokens por turno do usuário | mais requisições por prompt: mais chamadas de ferramenta ou subagentes |
| participação de gravações de cache em 1 hora (CC) | registrado diretamente: gravações movidas entre as vidas úteis de cache de 1 hora e 5 minutos |
| tokens por 1% da janela de 5 horas (Codex) | a leitura de cota do próprio fornecedor contra os tokens gastos: permissão por token |
Um dia D é sinalizado quando a mediana de D e até 6 dias ativos depois dele difere da mediana de até 7 dias ativos antes dele em pelo menos 30% (10 pontos percentuais para participações), pelo menos três quartos dos dias de cada lado ficam no seu próprio lado do ponto médio, e a diferença é mais de três vezes a dispersão dia a dia. Ele relata a data, a versão do cliente em uso e se D foi o primeiro dia nela, os valores antes e depois, e com o que a mudança é consistente — por exemplo:
De 30 set (Claude Code 2.1.230, o primeiro dia nela), leituras de cache por requisição caíram 37%, gravações de cache por requisição subiram 6,8x … — a própria transcrição mostra gravações movendo-se da vida útil de cache de 1 hora para a de 5 minutos.
Ele vê requisições na sua máquina, não nos servidores do fornecedor, então nunca nomeia uma causa. Uma mudança no seu próprio trabalho (um novo repositório, uma tarefa maior, mais subagentes) também move esses números, e quando nenhuma mudança de versão do cliente coincide, ele diz isso.
Limites
npx seatledger limits set --window 5h --tokens 40M
npx seatledger limits set --window weekly --usd 300 --client claude-code
npx seatledger limits clear --window 5h
O seatledger não inclui os limites de plano de nenhum fornecedor. Eles não são publicados como contagens de tokens, mudam sem aviso, e um número codificado estaria errado de uma forma que você não poderia ver. Defina os seus próprios — o número de "janela mais movimentada em 30 dias" é um bom começo se você atingiu o limite então. Uma janela de 5 horas abre na sua primeira requisição e dura cinco horas, do jeito que o Claude Code e o Codex descrevem as deles; weekly são os últimos 7 dias corridos. O Codex também grava suas próprias porcentagens de 5 horas e semanais em disco; o seatledger mostra as mais recentes como o Codex as relatou.
Seu histórico sobrevive às transcrições
O Claude Code exclui transcrições mais antigas que cleanupPeriodDays, 30 dias por padrão (docs). O seatledger mantém as contagens que coletou — nunca texto — em ~/.seatledger/cache-v1/, um arquivo pequeno por transcrição, para que o registro e as linhas de base de tarifa mantenham seu histórico depois que a transcrição sumir. Isso também torna execuções posteriores rápidas: apenas transcrições novas ou alteradas são lidas. Exclua o diretório para esquecê-lo, ou passe --no-cache.
O registro de equipe
O registro local responde "o que meu assento comprou". Um líder de equipe pagando por dez assentos quer o mesmo para todos, mantido por mais tempo do que um laptop mantém, e um e-mail quando a tarifa muda na máquina de qualquer pessoa. Esse é o registro de equipe hospedado, operado por agentwares:
| Plano | Preço | Desenvolvedores | Histórico | Alertas | CSV |
|---|---|---|---|---|---|
| Grátis | $0 | 3 | 30 dias | descobertas no painel | — |
| Equipe | $49/mês | 10 | 13 meses | e-mail e Slack | sim |
| Empresarial | $149/mês | 50 | 13 meses | e-mail e Slack | sim |
Inicie um pela CLI
npx seatledger team create --name "Acme platform" # optional: --email <alert address> --as <your name>
Isso cria uma equipe Grátis e salva a chave do proprietário em ~/.seatledger/team.json (legível apenas por você, nunca impressa), exatamente como team join salva a chave de um desenvolvedor, para que npx seatledger push funcione nesta máquina imediatamente. Ele imprime o link de convite para enviar aos seus colegas de equipe — cada um executa npx seatledger team join <link> --as <name> uma vez, depois npx seatledger push (manualmente, ou a partir de um cron ou um gancho de fim de sessão) — e o painel, onde você entra com GitHub e anexa a equipe com a chave do proprietário para atualizar, convidar e revogar. --dry-run imprime exatamente o que seria enviado e não envia nada. Criar uma equipe aceita os termos.
Ou entre com GitHub em agentwares-agentcheck.vercel.app/seatledger, que cria a equipe no navegador. Um agente pode criar uma equipe grátis sem humano: POST /api/seatledger/v1/teams {"accept_terms": true} retorna uma chave de proprietário e um link de convite.
A única linha sobre isso
Após seatledger, seatledger report e — quando encontrou uma mudança de degrau — seatledger rates, um terminal mostra uma linha apagada apontando para npx seatledger team create, no máximo uma vez por dia por máquina. Ela nunca aparece com --json, na saída do MCP, quando a saída não é um terminal, ou uma vez que esta máquina está em uma equipe. --quiet ou SEATLEDGER_QUIET=1 a desliga permanentemente. É texto impresso na sua tela; o único estado é o dia em que foi mostrada pela última vez, em ~/.seatledger/hint.json, e nada é enviado.
Exatamente o que push envia
Um documento JSON (seatledger.push/v1); seatledger push --dry-run o imprime por completo e não envia nada.
days— todos os dias locais que o envio cobre, desde o primeiro dia em que esta máquina tem histórico. As linhas do registro para esses dias tornam-se exatamente as linhas enviadas, então enviar um dia novamente o substitui, nunca adiciona a ele.rows— uma por dia × cliente × versão do cliente × modelo:requests,input_tokens,output_tokens,cache_read_tokens,cache_write_tokenseapi_equivalent_usd(nulo para um modelo sem preço de tabela).findings— o queseatledger ratesencontrou em pelo menos os últimos 90 dias, como números e ids: cliente, modelo, o dia em que começa, a versão do cliente e a anterior, se esse foi o primeiro dia nela, e por métrica as medianas antes e depois. A frase que você lê localmente é reconstruída pelo serviço a partir desses números; nenhum texto é enviado. Uma descoberta enviada novamente é a mesma descoberta.
Nunca enviado: conteúdo de prompt, resposta, ferramenta ou arquivo; caminhos de arquivo; ids de sessão ou requisição; nomes das suas pastas de projeto — a menos que você passe --project-names, que divide linhas por nome de pasta do diretório de trabalho (letras, dígitos, ., _, -; qualquer outra coisa vira -). Todo campo de texto que o serviço aceita é um id sem espaços e com um limite curto de comprimento; um campo que pudesse carregar uma frase é recusado.
O primeiro push envia até 400 dias (o plano mantém o que mantém e informa quais dias não foram
armazenados); pushes posteriores começam dois dias antes do último. --since 30d ou --since 2026-09-01
substituem isso. A chave é sua (o proprietário pode revogá-la); ela fica em
~/.seatledger/team.json, legível apenas por você, ou em SEATLEDGER_KEY. O host do link de convite é
para onde seus pushes vão; SEATLEDGER_URL o substitui.
Do seu agente
MCP (npx -y seatledger mcp, stdio, somente leitura): seatledger_usage_summary e
seatledger_rate_changes leem esta máquina e não fazem nenhuma solicitação; seatledger_team_summary lê o
registro da equipe que esta máquina criou ou entrou, com sua chave salva (uma solicitação HTTPS, não altera
nada). Esquemas
de entrada estritos, erros com code, cause, fix, retryable.
claude mcp add seatledger -- npx -y seatledger mcp
{ "mcpServers": { "seatledger": { "command": "npx", "args": ["-y", "seatledger", "mcp"] } } }
O que uma ferramenta retorna vai para o provedor de modelo do seu agente como qualquer outro resultado de ferramenta, incluindo nomes de pastas de projeto.
Plugin Claude Code (e Copilot CLI, que lê o mesmo arquivo de marketplace):
/plugin marketplace add agentwares/seatledger, depois /plugin install seatledger@seatledger.
/seatledger:usage explica o registro e seus limites; /seatledger:rates explica qualquer mudança
de etapa.
Gemini CLI: gemini extensions install https://github.com/agentwares/seatledger, depois
/seatledger:usage e /seatledger:rates.
Privacidade
- Lê
~/.claude/projectse~/.codex/sessions(ou os diretórios que você apontar). - Mantém contagens, carimbos de data/hora, IDs de solicitação e sessão, IDs de modelo, versões de cliente, nomes de pastas do diretório de trabalho e os caminhos das transcrições que leu. Nunca armazena ou imprime conteúdo de prompt, resposta, ferramenta ou arquivo: a maioria das linhas de transcrição é ignorada antes de ser analisada, e os registros que mantém não têm campo que possa conter texto.
- Escreve apenas em
~/.seatledger(limits.json,cache-v1/,hint.json— o dia em que a linha da equipe foi mostrada pela última vez — eteam.jsonquando você cria ou entra em uma equipe), ou$SEATLEDGER_HOME. - Não tem dependências em tempo de execução. Não faz chamadas de rede, exceto
seatledger team create(o nome da equipe e o endereço de alerta que você passa),seatledger team join,seatledger push,seatledger teame a ferramentaseatledger_team_summary, que falam com o registro da equipe que você criou ou entrou e enviam o que está listado em Exatamente o quepushenvia.
Como biblioteca
import { load, groupRows, dailySeries, rateReport } from "seatledger";
const { requests, quota } = await load();
const byModel = groupRows(requests, "model");
const { findings } = rateReport(dailySeries(requests, quota));
Desenvolver
pnpm install && pnpm test # the test script builds dist/ first
node dist/cli.js demo
pnpm screenshot # regenerate docs/screenshot.svg after changing the output
MIT © contribuidores do agentwares.