Saltar al contenido
claudemods

Agent Profiler: un profiler para Claude Code que muestra adónde va el tiempo

Adónde va el tiempo de una sesión de Claude Code: modelo, herramientas, subagentes, en vivo. Con exportación OTLP.

Permisos

  • Escribe archivosPuede crear o sobrescribir archivos en tu equipo ($.fs.write).
  • RedPuede hacer peticiones HTTP o comunicarse con servidores MCP ($.http.fetch / $.mcp.*).
  • Intercepta llamadas a herramientasVe cada llamada a herramienta que hace Claude (tool.call / tool.check) y podría bloquearla o modificarla.
  • Modifica la interfazDibuja en la interfaz de Claude Code: bandas, paneles, texto de estado, avisos (ui.render / $.ui.*).
  • Añade comandos/herramientasRegistra nuevos comandos de barra o herramientas invocables por ti o por Claude ($.command.register / $.tool.register).
probado con
v2.1.303
última prueba
requiere
Claude Code ≥ 2.1.287
superficies
estado, panel, aviso

Instalar dentro de Claude Code:

/plugin install agent-profiler --marketplace YeonwooSung/my-claude-code-mods
Todas las opciones de instalación ↓

¿Qué hace este mod?

Agent Profiler es un profiler para Claude Code creado por YeonwooSung, parte de la colección my-claude-code-mods. Responde a una pregunta: cuando una sesión se siente lenta, ¿adónde se fue el tiempo? Divide el tiempo de cada turno en espera del modelo, ejecución de herramientas, subagentes bloqueantes y sobrecarga del motor, y muestra el resultado en tres sitios.

  • Una línea de estado que se actualiza mientras Claude trabaja, por ejemplo model 100% · tools 0% · ▶ model claude-haiku-5-5 12.5s.
  • /profile, un informe de texto de toda la sesión, o /profile turn para el último turno. Enumera categorías de tiempo, tiempo hasta el primer token, tokens, herramientas lentas, lecturas repetidas de archivos, subagentes y una lista corta de hallazgos.
  • /profile-pane, un panel en vivo con las peticiones y herramientas en curso. /profile-export escribe la sesión como OTLP JSON.

El mod es prudente con lo que afirma. Nunca informa de un «tiempo de inferencia». Cada cifra lleva un grado: measured (entregada por Claude Code, como la duración de una herramienta), observed (medida por el mod en los límites de los eventos), reported (uso de tokens que informa la API) o inferred (un resto calculado). El README del autor requiere Claude Code 2.1.287 o posterior.

Demo

La grabación inicia Claude Code con el mod cargado en el pequeño proyecto de demostración y pide a Claude que lea README.md y describa el proyecto en una frase. Mientras corre el turno, la línea de estado sobre el pie cuenta en vivo: primero model 92% · tools 0%, luego model 100% con la petición en curso ▶ model claude-haiku-5-5 y sus segundos transcurridos. Al terminar el turno, el clip ejecuta /profile. El informe muestra 29,0 s de espera de la respuesta del modelo, 5 ms de herramientas, el tiempo hasta el primer token, 82,3k tokens de entrada, la única llamada a Read y el hallazgo de que esperar al modelo fue el 100 % del tiempo del agente.

Instalación

Usa cualquiera de los métodos del bloque de instalación; instalan directamente desde el marketplace del propio autor. Ese marketplace incluye muchos plugins, así que elige agent-profiler. La línea de estado y los comandos aparecen al iniciar la siguiente sesión.

$ install agent-profiler

Requiere Claude Code ≥ 2.1.287

Se instala desde el marketplace del autor: YeonwooSung/my-claude-code-mods

  1. 1.Una línea, dentro de Claude Code

    /plugin install agent-profiler --marketplace YeonwooSung/my-claude-code-mods

    Pégala en una sesión abierta (v2.1.275+). Claude Code te pedirá primero añadir el marketplace.

  2. 2.Desde tu shell

    claude plugin marketplace add YeonwooSung/my-claude-code-mods
    claude plugin install agent-profiler@my-claude-code-mods

    Después ejecuta /reload-plugins en cualquier sesión que ya esté abierta.

  3. 3.Pruébalo sin instalarlo

    git clone https://github.com/YeonwooSung/my-claude-code-mods
    claude --plugin-dir ./my-claude-code-mods/agent-profiler

    Carga el mod solo para una sesión. No se añade nada a tu configuración.

Cómo funciona

El módulo hooks/register.tsx guarda un objeto Profiler en memoria y lo alimenta en los límites de los eventos: turn.start y turn.complete, cada llamada al modelo mediante turn.step, cada herramienta mediante tool.call, y la duración de herramienta que da el propio Claude Code en classic.PostToolUse. El hook tool.call solo observa. Espera a la herramienta con await next(e) y devuelve la respuesta sin cambios, de hooks/register.tsx:

on('tool.call', async ($, e, next) => {
  anonymous += 1
  const id = e.tool_use_id ?? `anonymous-${anonymous}`
  const tool = String(e.tool)
  safe(() => profiler.toolStart(Date.now(), { id, tool, agentId: e.agentId, input: summarizeInput(tool, e as unknown as Record<string, unknown>) }))
  paint($)
  try {
    const answer = await next(e)
    safe(() => profiler.toolEnd(Date.now(), id, toolOutcome(answer)))
    return answer
  } // ...
}).catch(($, e, next) => next(e))

Cada paso de registro pasa por safe(), de modo que un error del profiler se descarta en lugar de romper la sesión. La línea de estado se redibuja como máximo dos veces por segundo. Tras cada turno, el mod escribe los spans recién terminados en <outputDir>/<sessionId>/<loadId>-<seq>.otlp.json, y al cerrar la sesión escribe el resto más un span raíz de la sesión. Los nombres de los spans siguen las convenciones GenAI (chat <model>, execute_tool <tool>, invoke_agent <type>). Los ids de span y de traza son deterministas, así que enviar dos veces la misma sesión da los mismos spans. La memoria está limitada a 20.000 peticiones y llamadas a herramientas; pasado ese límite se descartan los turnos terminados más antiguos.

Personalízalo

Hay tres opciones en el menú de ajustes de /plugin o en pluginConfigs:

Opción Valor por defecto Significado
otlpEndpoint vacío URL base de un colector OTLP/HTTP como http://localhost:4318. Vacío significa solo archivos.
outputDir ~/.claude/agent-profiler Dónde se escriben los archivos de traza, una carpeta por sesión.
exportCommandText false Incluye en las exportaciones los prompts de los turnos, las líneas de comando de Bash y los patrones de búsqueda, ocultando los secretos evidentes.

Para ver una traza en Jaeger, ejecuta el examples/jaeger/docker-compose.yml del repositorio, configura otlpEndpoint como http://localhost:4318 y abre http://localhost:16686. Grafana Tempo acepta el mismo endpoint OTLP/HTTP.

Permisos y seguridad

Antes de ejecutarlo leímos los archivos que el plugin puede ejecutar: .claude-plugin/plugin.json, hooks/hooks.json, y hooks/register.tsx y el archivo compose de Jaeger completos. De los once módulos de hooks/core/ leímos completos export.ts, otlp.ts, redact.ts y el resumidor de entradas de profiler.ts, y buscamos en todos llamadas de red, procesos, archivos, eval, import() y entorno (los únicos resultados están en register.tsx). Los archivos de prueba los listamos, no los leímos. No hay package.json, script de instalación, binario, código empaquetado o minificado, eval ni import() dinámico. El código de hooks/ no tiene caracteres de ancho cero ni ocultos; los únicos caracteres no ASCII son símbolos visibles de estado e informe como █, ░, · y ⏱. El mod no inyecta texto en los prompts ni en los resultados de las herramientas.

Hallazgos destacables:

  • Escribe archivos, activado por defecto. Llama a $.fs.write tras cada turno y al cerrar la sesión, en ~/.claude/agent-profiler/<sessionId>/ salvo que configures outputDir. Es la carpeta propia del plugin, no settings.json ni un archivo del shell, pero se escribe sin preguntar. Los archivos contienen tiempos, cantidades de tokens, nombres de modelos, nombres de herramientas, rutas de archivos de Read/Edit/Write y una categoría por cada comando de Bash (como test o build). Las rutas de archivos se exportan siempre. Los prompts, los comandos de Bash y los patrones de búsqueda solo con exportCommandText.
  • Red solo si lo eliges. $.http.fetch se llama únicamente cuando otlpEndpoint no está vacío, y solo envía por POST el mismo JSON de traza a <endpoint>/v1/traces. El host es el que escribas. Si apuntas a un colector remoto, las rutas de archivos y, con exportCommandText, los comandos ocultados salen de tu equipo. El README advierte de que la ocultación es de mejor esfuerzo.
  • Lee una variable de entorno, HOME, para expandir ~ en outputDir.
  • Intercepta llamadas a herramientas sin cambiarlas. tool.call y tool.check se observan y se pasan sin cambios, ambos con protección .catch. No se deniega ni se reescribe nada. claude plugin validate también enumera los hooks classic.* como hooks de control sin .catch; son observadores que devuelven next(e). Según validate, los hooks classic.* no se ejecutan cuando una organización administra Claude Code, así que allí el informe puede quedar incompleto.
  • Sin procesos, sin daemons, sin llamadas al modelo. No ejecuta comandos ni mantiene ningún servicio en segundo plano. Los únicos temporizadores son relojes dentro de la sesión.
  • Servicio externo opcional. Jaeger o Tempo solo hacen falta para explorar las trazas. El archivo compose descarga jaegertracing/all-in-one:latest y el mod nunca lo ejecuta.
  • Licencia. Apache-2.0 (el LICENSE de la raíz del repositorio).

claude plugin validate no informó de errores ni de advertencias, solo de las notas anteriores. Las 67 pruebas del autor en 11 archivos pasaron todas con claude plugin test en Claude Code 2.1.303.

Escribe archivos
Puede crear o sobrescribir archivos en tu equipo ($.fs.write).
Red
Puede hacer peticiones HTTP o comunicarse con servidores MCP ($.http.fetch / $.mcp.*).
Intercepta llamadas a herramientas
Ve cada llamada a herramienta que hace Claude (tool.call / tool.check) y podría bloquearla o modificarla.
Modifica la interfaz
Dibuja en la interfaz de Claude Code: bandas, paneles, texto de estado, avisos (ui.render / $.ui.*).
Añade comandos/herramientas
Registra nuevos comandos de barra o herramientas invocables por ti o por Claude ($.command.register / $.tool.register).

Compatibilidad y solución de problemas

Comprobado con Claude Code 2.1.303 en macOS: validate, las pruebas del autor y la grabación de la demo. El README indica que la prueba de extremo a extremo del propio autor se hizo en 2.1.280 y que las formas de los eventos siguen las declaraciones de tipos de 2.1.292. El panel y la línea de estado se dibujan en el terminal y en la pestaña Code de la app de escritorio, pero no en el panel de chat de VS Code ni en claude -p; el texto de /profile funciona en todas partes.

  • No aparece la línea de estado ni los comandos. Comprueba que claude --version sea 2.1.287 o posterior y ejecuta /reload-plugins tras instalar en una sesión ya abierta.
  • No hay archivos de traza. No se escribe nada hasta que se conoce el id de la sesión. Un fallo de escritura aparece una vez como toast; comprueba que outputDir admita escritura.
  • Las cifras se reinician tras una recarga en caliente. El estado en memoria empieza de cero, pero los lotes ya escritos siguen en disco bajo el id de carga anterior.
  • Archivos modificados mediante Bash. El detector de lecturas repetidas no los ve.
  • El tiempo dentro del servidor del modelo (cola, prefill, decodificación) no puede desglosarse con ninguna herramienta del lado del cliente; el tiempo hasta el primer token lo agrupa.

Preguntas frecuentes

¿Agent Profiler envía mis datos a algún sitio?
No por defecto. Escribe archivos de traza en una carpeta de tu equipo. Solo hace una petición de red si configuras la opción otlpEndpoint, y entonces envía cada lote de trazas por POST a esa URL más /v1/traces. No se envía nada al autor.
¿Dónde se escriben los archivos de traza?
En ~/.claude/agent-profiler/<sessionId>/ salvo que configures outputDir. Se escribe un archivo después de cada turno terminado y otra vez al cerrar la sesión. Contienen tiempos, cantidades de tokens, nombres de herramientas y rutas de archivos.
¿Se exportan mis prompts y comandos de Bash?
No, salvo que actives exportCommandText. Con la opción desactivada, los prompts, las líneas de comando de Bash y los patrones de búsqueda quedan fuera de los archivos y de los POST, y solo se conserva una categoría de comando como test o build. Activada, se exportan tras ocultar los secretos lo mejor posible.
¿Mide cuánto calcula el modelo?
No, y el README lo dice. Mide cuánto esperó el cliente, por ejemplo el tiempo hasta el primer token, que mezcla red, cola y prefill. Cada cifra lleva la etiqueta observed, measured, reported o inferred.
¿Necesito Jaeger u otro servicio?
No. /profile y la línea de estado funcionan solos. Jaeger o Grafana Tempo solo hacen falta si quieres explorar en una interfaz las trazas OTLP exportadas. El repositorio incluye un pequeño archivo docker-compose de Jaeger para eso.
Agent Radar funcionando en Claude CodeDestacado

Agent Radar

Una línea en vivo sobre el prompt por subagente en ejecución: tiempo, herramientas y acción actual, más un panel /radar.

  • sobre el prompt
  • panel
  • aviso
  • Intercepta llamadas a herramientas
  • Lee tus prompts
  • Modifica la interfaz
  • Añade comandos/herramientas

probado con v2.1.291

Cache Clock funcionando en Claude CodeDestacado

Cache Clock

Una línea de caché de prompt bajo la barra de estado: tiempo restante, aciertos y tokens que se recachean en frío.

  • estado
  • Lee archivos
  • Escribe archivos
  • Ejecuta comandos
  • Añade comandos/herramientas

probado con v2.1.296

Contador de llamadas a herramientas funcionando en Claude CodeDestacado

Contador de llamadas a herramientas

Cuenta las llamadas a herramientas por turno y sesión, muestra el total junto al spinner y añade /tally con un desglose.

  • spinner
  • transcripción
  • estado
  • Intercepta llamadas a herramientas
  • Modifica la interfaz
  • Añade comandos/herramientas

probado con v2.1.310

Más en Temporizadores, tareas y standups, Barra de estado y barra del prompt, Paneles y dashboards.