Correr en contenedores
Corre el colector en Docker, en sandboxes de desarrollo como Daytona, devcontainers o Codespaces, y en Kubernetes.
tallygraph collect lee el historial del agente dentro de $HOME. En un contenedor tiene que correr donde vive ese historial: en el mismo contenedor que el agente, o en otro con la carpeta del historial montada. No hace falta iniciar sesión: el token llega por una variable de entorno.
Requisitos
- Node.js 22.13 o más nuevo en la imagen. La imagen oficial
node:22-slimsirve. - Un token de escritura de la página de Conectores, pasado como
TALLYGRAPH_WRITE_TOKEN. - Salida HTTPS a
www.tallygraph.dev, o a la URL que pongas enTALLYGRAPH_ENDPOINT. - El historial del agente dentro del contenedor, en su ruta por defecto bajo
HOME(para Claude Code,~/.claude/projects). Todas las rutas están en Inicio rápido.
No uses tallygraph service install en un contenedor. Registra la tarea en launchd, systemd o Task Scheduler, y un contenedor normalmente no tiene ninguno. Usa collect --watch o una tarea programada.
Docker
Primero revisa qué encuentra
Monta el historial en solo lectura y haz una corrida en seco. Lee y valida, pero no manda nada. No necesita token.
docker run --rm -u node -e HOME=/home/node \ -v /ruta/a/.claude/projects:/home/node/.claude/projects:ro \ node:22-slim npx --yes tallygraph collect --dry-run
[tallygraph] discovered: claude (cost basis: estimate) [tallygraph] file: discover — 1 valid, 0 invalid, 0.4 KiB [tallygraph] dry-run: nothing sent, spool untouched
Arma una imagen del colector
Con el CLI instalado en la imagen no se descarga en cada arranque. La carpeta .tallygraph se crea con el usuario node para que un volumen montado ahí se pueda escribir.
FROM node:22-slim
ARG TALLYGRAPH_VERSION=0.5.0
RUN npm i -g tallygraph@${TALLYGRAPH_VERSION}
USER node
RUN mkdir -p /home/node/.tallygraph
ENTRYPOINT ["tallygraph"]
CMD ["collect"]docker build -t tallygraph-collector . export TALLYGRAPH_WRITE_TOKEN=tg_xxxxxxxx docker run --rm -e TALLYGRAPH_WRITE_TOKEN \ -v /ruta/a/.claude/projects:/home/node/.claude/projects:ro \ -v tallygraph-state:/home/node/.tallygraph \ tallygraph-collector collect
El volumen tallygraph-state guarda el spool entre corridas, así que lo que no se pudo mandar sale en la siguiente. Para dejarlo corriendo, pasa collect --watch en lugar de collect. Se detiene limpio con docker stop.
Sandboxes de desarrollo: Daytona, devcontainers, Codespaces
Aquí el agente corre dentro del sandbox, así que su historial ya está en el home del sandbox. Corre el colector ahí mismo.
- Instálalo en la imagen o en el script de setup con
npm i -g tallygraph, o llámalo connpx --yes tallygraph. - Pon
TALLYGRAPH_WRITE_TOKENcomo secreto o variable de entorno del sandbox. No lo subas al repo. - Para tareas cortas, corre
tallygraph collectal terminar la tarea. - Para sesiones largas, arranca
tallygraph collect --watch --interval 60en otra terminal o en segundo plano. - Si el sandbox puede reiniciar con el disco limpio, guarda el historial del agente y
TALLYGRAPH_STATE_DIRen un volumen persistente. Si no, el uso que no se mandó antes del reinicio se pierde junto con el historial.
npm i -g tallygraph tallygraph collect --dry-run # no manda nada tallygraph collect --watch --interval 60
Correr collect varias veces no duplica nada. La API descarta los eventos que ya tiene, por external_id.
Kubernetes
Sidecar en el pod del agente
Agrega el colector como segundo contenedor en el pod donde corre el agente. Los dos montan el mismo volumen en la ruta del historial. El colector lo monta en solo lectura y guarda su spool en otro volumen. Arma la imagen con el Dockerfile de arriba y súbela a tu registry. Primero crea el Secret:
kubectl create secret generic tallygraph --from-literal=write-token="$TALLYGRAPH_WRITE_TOKEN"
apiVersion: v1
kind: Pod
metadata:
name: agent
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
volumes:
- name: claude-history
emptyDir: {}
- name: tallygraph-state
emptyDir: {}
containers:
- name: agent
image: your-agent-image
env:
- name: HOME
value: /home/node
volumeMounts:
- name: claude-history
mountPath: /home/node/.claude/projects
- name: tallygraph
image: registry.example.com/tallygraph-collector
args: ["collect", "--watch", "--interval", "300"]
env:
- name: HOME
value: /home/node
- name: TALLYGRAPH_STATE_DIR
value: /var/lib/tallygraph
- name: TALLYGRAPH_WRITE_TOKEN
valueFrom:
secretKeyRef:
name: tallygraph
key: write-token
volumeMounts:
- name: claude-history
mountPath: /home/node/.claude/projects
readOnly: true
- name: tallygraph-state
mountPath: /var/lib/tallygraph- Cambia
/home/nodepor el HOME del agente. El colector busca en las rutas bajo su propioHOME, así que los dos tienen que coincidir con el montaje. - Para Codex, monta
~/.codex/sessionsde la misma forma. emptyDirdura lo que dura el pod. Usa un PersistentVolumeClaim para los dos volúmenes si el pod se reemplaza antes de que el colector alcance a mandar todo.- Si el agente corre como Job, no le pongas un sidecar que se queda corriendo, porque el Job nunca termina. Mejor corre
tallygraph collectal final del comando del agente.
CronJob
Solo si el historial está en un PersistentVolumeClaim que el job pueda montar. Un volumen ReadWriteOnce solo lo pueden montar pods en el mismo nodo que el agente.
apiVersion: batch/v1
kind: CronJob
metadata:
name: tallygraph-collect
spec:
schedule: "*/15 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
volumes:
- name: claude-history
persistentVolumeClaim:
claimName: agent-claude-history
readOnly: true
- name: tallygraph-state
persistentVolumeClaim:
claimName: tallygraph-state
containers:
- name: tallygraph
image: registry.example.com/tallygraph-collector
args: ["collect"]
env:
- name: HOME
value: /home/node
- name: TALLYGRAPH_STATE_DIR
value: /var/lib/tallygraph
- name: TALLYGRAPH_WRITE_TOKEN
valueFrom:
secretKeyRef:
name: tallygraph
key: write-token
volumeMounts:
- name: claude-history
mountPath: /home/node/.claude/projects
readOnly: true
- name: tallygraph-state
mountPath: /var/lib/tallygraphProblemas comunes
| Ves | Qué significa | Qué hacer |
|---|---|---|
no local sources found | Código de salida 2. No hay historial en las rutas por defecto bajo HOME: el volumen no está montado, está en otra ruta, o HOME apunta a otro lado. | Revisa HOME y la ruta del montaje, y corre collect --dry-run hasta que diga discovered. |
missing --token (or TALLYGRAPH_WRITE_TOKEN env) | El token no llegó al contenedor. | Revisa que la variable exista donde corres docker, o el nombre y la key del Secret en secretKeyRef. |
cannot open spool at … | Código de salida 3. El usuario del contenedor no puede escribir en la carpeta de estado. | Monta ahí un volumen con permiso de escritura. En Kubernetes, pon fsGroup. |
watch: tick N produced no events | Con --watch el proceso sigue vivo y reintenta en el siguiente ciclo. | Lo mismo que para no local sources found. |