seatledger: what your coding-agent seats and tokens buy
Uso de tokens de Claude Code y Codex y costo equivalente a API por día, proyecto y modelo, desde tu propia máquina, más una marca cuando cambia la tarifa. Servidor MCP local y CLI; sin cuenta.
Documentación
seatledger
Lo que tus asientos y tokens de agente de codificación compraron, desde tu propia máquina — y cuándo cambió la tarifa.
npx seatledger
La imagen es la salida real de npx seatledger demo, que se ejecuta sobre historial sintético. Se regenera mediante pnpm screenshot y una prueba falla si se desvía de lo que imprime la CLI.
seatledger lee las transcripciones que Claude Code y Codex ya guardan en tu máquina y te dice:
- tokens y dólares equivalentes a API por día, carpeta de proyecto, modelo y cliente;
- qué tan rápido te acercas a los límites que estableciste y cuándo los alcanzarías a este ritmo;
- cuándo cambió la tarifa: el mismo trabajo de repente cuesta más tokens por solicitud, las lecturas de caché disminuyen porque las escrituras se movieron a una vida de caché más corta, más tokens por turno después de una actualización del cliente, o la ventana de 5 horas de Codex se llena más rápido por los mismos tokens — con la fecha y la versión del cliente donde comienza.
Ningún proveedor construirá esa última función: es una alarma sobre su propia tarifa. seatledger es MIT, no tiene telemetría ni dependencias de ejecución, y no necesita cuenta. No realiza llamadas de red a menos que crees o te unas a un registro de equipo — y entonces seatledger push envía solo agregados diarios, que seatledger push --dry-run imprime en su totalidad.
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
Cada comando acepta --json, --client claude-code|codex, --claude-dir, --codex-dir, --no-cache y --quiet. Sin npm: npx github:agentwares/seatledger ejecuta la misma CLI desde este repositorio (incluye su dist/ compilado).
Lo que lee
| Cliente | Dónde | Qué toma |
|---|---|---|
| Claude Code | ~/.claude/projects/**/*.jsonl (o $CLAUDE_CONFIG_DIR/projects, ~/.config/claude/projects) | el usage de cada respuesta (entrada, salida, lecturas de caché, escrituras de caché divididas en 5 minutos y 1 hora), modelo, version, requestId, marca de tiempo, carpeta de directorio de trabajo |
| Codex CLI | ~/.codex/sessions/** y archived_sessions/ (o $CODEX_HOME) | token_usage_record por respuesta (versiones más nuevas) o eventos token_count, el modelo del turno, cli_version, y las lecturas rate_limits que Codex escribe |
Verificado el 7 de octubre de 2026 contra transcripciones de Claude Code escritas por versiones hasta 2.1.286 (el registro de cambios estaba en 2.1.292) y lanzamientos de Codex escritos por 0.144–0.159, más el código fuente de Codex en rust-v0.160.1 (TokenUsage, TokenUsageRecord, RateLimitSnapshot). Cosas que los formatos hacen que un lector ingenuo entiende mal, y que seatledger maneja:
- Claude Code escribe una respuesta como varias líneas, y solo la última lleva el
output_tokensfinal. seatledger las fusiona pormessage.id:requestIdy conserva el conteo más grande. - La misma respuesta aparece en más de un archivo (transcripciones de subagentes, sesiones reanudadas y apartadas); las solicitudes se deduplican entre archivos.
- El
input_tokensde Codex ya incluye entrada en caché y escrita en caché. - Los campos desconocidos se ignoran y una línea cortada a mitad de escritura se omite, nunca es fatal.
No leído (aún): Gemini CLI no estaba instalado donde se construyó esto, por lo que su registro local no pudo verificarse contra archivos reales; el almacén local de Cursor es una base de datos SQLite no documentada y la copia revisada no contenía conteos de tokens por solicitud. Ninguno se adivina.
Equivalente a API, no tu factura
Los dólares son equivalentes a API: lo que los mismos tokens costarían a los precios de lista de la API del proveedor. En un asiento Pro, Max, Plus o Team pagas una tarifa fija; esto es lo que el uso de ese asiento habría costado en la API, que es el número para comparar asientos, planes y meses. Está etiquetado en todas partes donde aparece. Los precios provienen de una tabla fechada en el paquete, con sus fuentes:
- Anthropic, platform.claude.com/docs/en/about-claude/pricing, leído el 7 de octubre de 2026 — entrada base, escrituras de caché de 5 minutos y 1 hora, lecturas de caché, salida; modo rápido; 1.1x para inferencia solo en EE. UU.
- OpenAI, developers.openai.com/api/docs/pricing, leído el 7 de octubre de 2026 — entrada, entrada en caché, escrituras de caché, salida y precios de contexto largo por encima de 272K tokens de entrada.
Un modelo sin precio de lista (el codex-auto-review interno de Codex, por ejemplo) se cuenta en tokens y sus dólares se reportan como sin precio, nunca estimados.
El detector de cambios de tarifa
seatledger rates observa, por cliente y modelo, días completos con al menos 20 solicitudes:
| Métrica | Qué suele significar un paso en ella |
|---|---|
| tokens por solicitud | un prompt fijo más grande (prompt del sistema, herramientas, habilidades, definiciones de MCP) o contexto más grande |
| participación de lecturas de caché en tokens de prompt | la caché se lee menos, se escribe más |
| escrituras de caché por lectura de caché | lo mismo, como proporción |
| tokens por turno de usuario | más solicitudes por prompt: más llamadas a herramientas o subagentes |
| participación de escrituras de caché a 1 hora (CC) | registrado directamente: escrituras movidas entre las vidas de caché de 1 hora y 5 minutos |
| tokens por 1% de la ventana de 5 horas (Codex) | la lectura de cuota propia del proveedor contra los tokens gastados: asignación por token |
Un día D se marca cuando la mediana de D y hasta 6 días activos después difiere de la mediana de hasta 7 días activos antes en al menos 30% (10 puntos porcentuales para participaciones), al menos tres cuartos de los días en cada lado están en su propio lado del punto medio, y la diferencia es más de tres veces la dispersión día a día. Reporta la fecha, la versión del cliente en uso y si D fue el primer día en ella, los valores antes y después, y con qué es consistente el cambio — por ejemplo:
Desde el 30 de septiembre (Claude Code 2.1.230, el primer día en ella), las lecturas de caché por solicitud cayeron 37%, las escrituras de caché por solicitud subieron 6.8x … — la transcripción misma muestra escrituras moviéndose de la vida de caché de 1 hora a la de 5 minutos.
Ve solicitudes en tu máquina, no en los servidores del proveedor, por lo que nunca nombra una causa. Un cambio en tu propio trabajo (un repositorio nuevo, una tarea más grande, más subagentes) también mueve estos números, y cuando no coincide un cambio de versión del cliente, lo dice.
Límites
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
seatledger no incluye los límites de plan de ningún proveedor. No se publican como conteos de tokens, cambian sin aviso, y un número codificado estaría mal de una manera que no podrías ver. Establece los tuyos — la cifra de "ventana más ocupada en 30 días" es un buen comienzo si alcanzaste el límite entonces. Una ventana de 5 horas se abre con tu primera solicitud y dura cinco horas, como Claude Code y Codex describen las suyas; weekly son los últimos 7 días móviles. Codex también escribe sus propios porcentajes de 5 horas y semanales en disco; seatledger muestra los últimos tal como Codex los reportó.
Tu historial sobrevive a las transcripciones
Claude Code elimina transcripciones más antiguas que cleanupPeriodDays, 30 días por defecto (docs). seatledger conserva los conteos que ha tomado — nunca texto — en ~/.seatledger/cache-v1/, un archivo pequeño por transcripción, para que el registro y las líneas base de tarifa mantengan su historial después de que la transcripción desaparezca. También hace que las ejecuciones posteriores sean rápidas: solo se leen transcripciones nuevas o cambiadas. Elimina el directorio para olvidarlo, o pasa --no-cache.
El registro de equipo
El registro local responde "qué compró mi asiento". Un líder de equipo que paga por diez asientos quiere lo mismo para todos, conservado más tiempo del que una laptop lo conserva, y un correo cuando la tarifa cambia en la máquina de alguien. Ese es el registro de equipo alojado, operado por agentwares:
| Plan | Precio | Desarrolladores | Historial | Alertas | CSV |
|---|---|---|---|---|---|
| Gratis | $0 | 3 | 30 días | hallazgos en el panel | — |
| Equipo | $49/mes | 10 | 13 meses | correo y Slack | sí |
| Negocio | $149/mes | 50 | 13 meses | correo y Slack | sí |
Inicia uno desde la CLI
npx seatledger team create --name "Acme platform" # optional: --email <alert address> --as <your name>
Eso crea un equipo Gratis y guarda su clave de propietario en ~/.seatledger/team.json (legible solo por ti, nunca impresa), exactamente como team join guarda la clave de un desarrollador, para que npx seatledger push funcione en esta máquina de inmediato. Imprime el enlace de invitación para enviar a tus compañeros de equipo — cada uno ejecuta npx seatledger team join <link> --as <name> una vez, luego npx seatledger push (a mano, o desde un cron o un hook de fin de sesión) — y el panel, donde inicias sesión con GitHub y adjuntas el equipo con la clave de propietario para actualizar, invitar y revocar. --dry-run imprime exactamente lo que se enviaría y no envía nada. Crear un equipo acepta los términos.
O inicia sesión con GitHub en agentwares-agentcheck.vercel.app/seatledger, que crea el equipo en el navegador. Un agente puede crear un equipo gratuito sin humano: POST /api/seatledger/v1/teams {"accept_terms": true} devuelve una clave de propietario y un enlace de invitación.
La única línea al respecto
Después de seatledger, seatledger report y — cuando encontró un cambio de paso — seatledger rates, una terminal muestra una línea tenue apuntando a npx seatledger team create, como máximo una vez al día por máquina. Nunca aparece con --json, en salida de MCP, cuando la salida no es una terminal, o una vez que esta máquina está en un equipo. --quiet o SEATLEDGER_QUIET=1 la apaga para siempre. Es texto impreso en tu pantalla; el único estado es el día en que se mostró por última vez, en ~/.seatledger/hint.json, y no se envía nada.
Exactamente lo que push envía
Un documento JSON (seatledger.push/v1); seatledger push --dry-run lo imprime en su totalidad y no envía nada.
days— cada día local que cubre el envío, desde el primer día del que esta máquina tiene historial. Las filas del registro para esos días se convierten exactamente en las filas enviadas, por lo que enviar un día de nuevo lo reemplaza, nunca lo agrega.rows— uno por día × cliente × versión de cliente × modelo:requests,input_tokens,output_tokens,cache_read_tokens,cache_write_tokensyapi_equivalent_usd(nulo para un modelo sin precio de lista).findings— lo queseatledger ratesencontró en al menos los últimos 90 días, como números e ids: cliente, modelo, el día en que comienza, la versión del cliente y la anterior, si ese fue el primer día en ella, y por métrica las medianas antes y después. La oración que lees localmente se reconstruye por el servicio a partir de estos números; no se envía texto. Un hallazgo enviado de nuevo es el mismo hallazgo.
Nunca enviado: contenido de prompt, respuesta, herramienta o archivo; rutas de archivo; ids de sesión o solicitud; nombres de carpetas de tu proyecto — a menos que pases --project-names, que divide filas por nombre de carpeta de directorio de trabajo (letras, dígitos, ., _, -; cualquier otra cosa se convierte en -). Cada campo de texto que el servicio acepta es un id sin espacios y con un límite de longitud corto; un campo que podría llevar una oración se rechaza.
El primer push envía hasta 400 días (el plan conserva lo que conserva e indica qué días no almacenó); los pushes posteriores comienzan dos días antes del último. --since 30d o --since 2026-09-01 anula eso. La clave es tuya (el propietario puede revocarla); vive en ~/.seatledger/team.json, legible solo por ti, o en SEATLEDGER_KEY. El host del enlace de invitación es a donde van tus pushes; SEATLEDGER_URL lo anula.
Desde tu agente
MCP (npx -y seatledger mcp, stdio, solo lectura): seatledger_usage_summary y seatledger_rate_changes leen esta máquina y no hacen ninguna solicitud; seatledger_team_summary lee el registro del equipo que esta máquina creó o al que se unió, con su clave guardada (una solicitud HTTPS, no cambia nada). Esquemas de entrada estrictos, errores con code, cause, fix, retryable.
claude mcp add seatledger -- npx -y seatledger mcp
{ "mcpServers": { "seatledger": { "command": "npx", "args": ["-y", "seatledger", "mcp"] } } }
Lo que devuelva una herramienta va al proveedor de modelos de tu agente como cualquier otro resultado de herramienta, incluidos los nombres de carpetas del proyecto.
Plugin de Claude Code (y Copilot CLI, que lee el mismo archivo de marketplace): /plugin marketplace add agentwares/seatledger, luego /plugin install seatledger@seatledger. /seatledger:usage explica el registro y tus límites; /seatledger:rates explica cualquier cambio de paso.
Gemini CLI: gemini extensions install https://github.com/agentwares/seatledger, luego /seatledger:usage y /seatledger:rates.
Privacidad
- Lee
~/.claude/projectsy~/.codex/sessions(o los directorios a los que lo apuntes). - Conserva conteos, marcas de tiempo, IDs de solicitudes y sesiones, IDs de modelos, versiones de clientes, nombres de carpetas del directorio de trabajo y las rutas de las transcripciones que leyó. Nunca almacena ni imprime el contenido de prompts, respuestas, herramientas o archivos: la mayoría de las líneas de transcripción se omiten antes de analizarse, y los registros que conserva no tienen ningún campo que pueda contener texto.
- Escribe solo en
~/.seatledger(limits.json,cache-v1/,hint.json— el día en que se mostró por última vez la línea del equipo — yteam.jsonuna vez que crees o te unas a un equipo), o$SEATLEDGER_HOME. - No tiene dependencias en tiempo de ejecución. No realiza llamadas de red, excepto
seatledger team create(el nombre del equipo y la dirección de alerta que pases),seatledger team join,seatledger push,seatledger teamy la herramientaseatledger_team_summary, que hablan con el registro del equipo que creaste o al que te uniste y envían lo que se lista bajo Exactamente lo quepushenvía.
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));
Desarrollar
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 © contribuyentes de agentwares.