Un plugin de notas para quienes llevan sus sesiones de agente al límite
Antes del post, unas palabras sobre cómo se escribió
Este post lo escribió mayormente una IA. Quiero decirlo de entrada, porque cada vez veo más medios que prohíben de plano el contenido generado por IA, y me parece un error.
Soy ingeniero, no escritor. Escribir me cuesta esfuerzo de verdad. La mayoría de las veces lo hago igual porque lo disfruto y porque me obliga a pensar un tema a fondo, lo cual ya vale por sí solo. Me da claridad. Pero son unas cuantas horas que no siempre tengo.
Así que la decisión que tenía enfrente esta semana no era "buen post o post con IA". Era "post con IA o ningún post". Encontré algo genuinamente útil, casi por accidente, y lo he visto mencionado en exactamente un newsletter. En ningún otro lado. Si el precio de compartir eso es admitir que un modelo me ayudó a ordenar las frases, me parece bien.
La prohibición general trata "generado por IA" como sinónimo de "sin valor". A veces lo es. Se está publicando mucha basura para conseguir clics y no defiendo nada de eso. Pero el sinónimo es malo. Lo que importa es si hay algo real debajo: un hallazgo, un bug con el que chocaste de verdad, algo que construiste de verdad. Juzga eso. No hago esto por métricas de engagement. Lo hago porque creo que tres o cuatro personas que lean esto van a instalar esta cosa y se van a alegrar de haberlo hecho.
En fin. Vamos a la parte importante.
TL;DR
Quería dejarme notas dentro de una sesión de agente todo el tiempo. No había buena forma de hacerlo. Investigué las opciones, casi todas malas. Después apareció en un newsletter un IDE de agentes llamado bb y resultó ser la única herramienta donde podía construir yo mismo la función que faltaba. Veinte minutos, más o menos. El plugin está acá, con licencia MIT.
El problema real: notas que sobreviven, contexto que no
Si trabajas con agentes de código todo el día, ya conoces esta.
Le pones una tarea a Claude. La trabaja y la termina. La tarea queda genuinamente hecha.
Y entonces, en el mismo aliento, te cuenta de otras tres cosas. Una función que está mal pero quedaba fuera del alcance. Un valor de configuración que contradice la documentación. Un test que está saltado desde marzo. Todo real, todo relacionado con lo que acabas de hacer, y nada de eso es lo que pediste. Los buenos agentes sacan estas cosas a la luz. Claude saca muchísimas.
El problema es el momento. Ese instante ya es el más ocupado de todo el ciclo. El trabajo está en un worktree, así que todavía tengo que mirar qué cambió realmente, ejecutarlo, decidir si le creo y lograr que la rama se integre de vuelta en main. Esa es la obligación viva, y es la que tiene mi atención.
O sea que tres hallazgos genuinos llegan justo en el momento en que menos espacio tengo para ellos, y compiten con un merge por la misma porción de mi cabeza. Lo que pase con ellos a continuación tiene que pasar en más o menos un minuto, porque después ya estoy metido en el diff.
Durante mucho tiempo lo que pasaba a continuación era una app de tareas, o un archivo de pendientes en texto plano que abría en otra cosa. Viví en Warp un buen rato, después en Superset, siempre haciendo malabares con tres ventanas de terminal repartidas en por lo menos otros tantos proyectos.
Y mantenía esas listas. Una por proyecto, trabajadas meticulosamente, cada ítem atendido tarde o temprano. No se cayó nada.
Aun así era el sistema equivocado, por dos razones que me tomó un rato separar.
La primera es que escribir la nota me costaba la sesión. Capturar una idea significaba salir de lo que estaba haciendo, cambiar a otra aplicación, escribirla y volver. Digamos quince segundos. Quince segundos alcanzan de sobra. Esa es la ventana en la que todavía tengo en la cabeza la forma de lo que el agente acaba de hacer, y cada ida y vuelta le abre un agujerito. Haz eso seis veces en una tarde y la tarde se te va en recuperar el hilo. Mantener la lista nunca fue lo difícil. Lo difícil era la interrupción que exigía, cada maldita vez.
La segunda es peor, y es la que realmente impulsó esto. Una tarea en otra app no tiene forma de llevarse su contexto consigo. Escribía "revisar la lógica de reintentos en el sync handler" y medio día y 1 millón de tokens después lo releía y la frase era técnicamente clara y prácticamente inútil. ¿Por qué lo marqué? ¿Qué estaba haciendo Claude cuando salió? ¿Qué había en la salida que me hizo pensar que importaba? Eso estaba mil líneas más arriba, en un scrollback que había cerrado hacía rato.
Probé escribiendo notas más largas. Eso solo significaba resumir una sesión en la que todavía estaba parado en medio, y eso cuesta más de lo que vale la nota.
Así que la nota sobrevivía y su significado no. Terminaba reconstruyendo el razonamiento desde cero o, peor, ahí sentado recordando el contexto a medias y apoyándome casi siempre en Claude para que me llenara los huecos.
Lo que quería era chico y concreto: dejar una nota pegada al turno exacto donde salió la cosa, sin salir de la sesión para hacerlo, para que cuando vuelva, la conversación que la rodea vuelva con ella. No una nota sobre el contexto. Una nota que vive en el contexto.
En la práctica eso significa que la nota cuelga del mensaje donde Claude listó sus hallazgos. Que es el mensaje que ya contiene el razonamiento, los nombres de archivo y todo lo demás que si no estaría intentando comprimir en el título de una tarea en el peor momento posible.
Lo que miré primero
Pasé unos días en esto antes de construir nada, y resumo acá toda la búsqueda porque la forma de la respuesta es más útil que mi conclusión.
Al final todo dependía de una pregunta: ¿el agente tiene que seguir corriendo en una terminal?
Si la respuesta es sí, las opciones son flacas. iTerm2 es la única terminal que hace esto de verdad. Tiene una función de anotación real que ancla una nota a un rango de texto en tu scrollback, y como es una acción de interfaz gráfica y no una entrada de shell, funciona perfecto mientras Claude Code es dueño de la terminal. Es una respuesta legítima y lista para usar, y si quieres dejar de leer acá e irte a usarla, es un desenlace razonable. Warp, que era la que yo usaba entonces, tiene bookmarks que no llevan texto alguno, así que son marcadores de navegación y nada más. Su propia documentación dice que desaparecen cuando se cierra la sesión. kitty y WezTerm tienen marcadores de posición o hooks de scripting, pero no anotación. Ghostty no tiene ninguna de las dos. tmux no trae nada incorporado, pero es el mejor sustrato si quieres armarte algo con un popup y un panel lateral.
Las propias funciones de Claude Code te llevan parte del camino y ahí se frenan. Los hooks pueden imprimir marcadores en la transcripción, pero se disparan con los eventos de Claude, no cuando yo noto algo. # y /memory escriben en CLAUDE.md, que es memoria de largo plazo duradera, exactamente lo opuesto a lo que quería. Los comandos con barra necesitan el prompt, al que no puedo llegar en medio de un turno. Las transcripciones de sesión son JSONL en disco y puedes agregarles cosas por fuera, pero nada se renderiza en vivo. Y los distintos servidores MCP de scratchpad son almacenes laterales: la nota entra, pero no queda anclada a nada, con lo cual reproduce el mismo problema del que estaba tratando de escapar.
Una cosa que hay que evitar activamente. Si estás pensando "le inyecto el texto a la terminal en ejecución desde afuera", no lo hagas. Ese camino pasa por TIOCSTI, que tiene una historia tan larga de ser usado en ataques de escalada de privilegios que Linux lo desactivó por defecto en 6.2 y OpenBSD lo eliminó años antes. Escribir directo al dispositivo TTY es peor. Esos bytes aterrizan en medio de lo que el agente está dibujando en ese momento, y la pantalla se convierte en basura.
El resultado de todo eso fue una bifurcación. Cada una de esas limitaciones es una propiedad de las terminales, no de los agentes. La salida es un flujo de bytes hacia un TTY, un proceso en primer plano es dueño de la entrada, el scrollback se desborda y nada tiene un ID estable. No hay ningún objeto al que pegarle una nota, así que cada workaround es en realidad un intento de fingir uno.
Lo cual dejaba dos opciones honestas: usar iTerm2 y aceptar su modelo, o encontrar algo donde la sesión esté hecha de objetos direccionables en vez de bytes. Para lo segundo no tenía candidato. Y ahí tuve suerte.
El accidente
A mitad de esos días, bb apareció en Ben's Bites, uno de los newsletters de IA a los que estoy suscrito.
La mención era corta. Algo así como: es un IDE de agentes y es extremadamente personalizable. Con eso bastó, sobre todo por cuándo llegó. Ya estaba metido hasta el cuello en un problema donde "personalizable" era la respuesta entera que buscaba. Cualquier otra semana lo habría pasado de largo.
Quiero ser claro sobre cuánta suerte hubo acá. Están apareciendo herramientas de codificación agéntica, terminales, orquestadores y wrappers nuevos todas las semanas. Nadie puede evaluarlos todos. No encontré bb por diligencia. Me cayó en el escritorio la semana en que justo tenía un problema con su forma, y solo lo reconocí porque había pasado un par de días puliendo esa forma.
Por qué encajó
A bb lo archivan bajo "IDE", lo cual confunde, porque ahí no editas archivos. Orquesta: corre agentes de código (Claude Code, Codex, Cursor y cualquier cosa que hable ACP) dentro de hilos con nombre, cada uno con su propio git worktree, tiene licencia MIT y corre enteramente en tus propias máquinas usando las suscripciones que ya pagas.
Dos cosas de mi setup hicieron que esto pegara más fuerte de lo que quizás pegaría en otros.
El homelab. Corro trabajos en varias máquinas de mi red local. Una caja hace el trabajo de agente permanente, otra tiene la GPU, la Mac Mini es la máquina de todos los días. Coordinar eso solía ser un montón de sesiones SSH y mucho acordarse de cuál ventana era cuál. bb lo maneja como corresponde: cada máquina corre un demonio cliente real que se conecta de vuelta al servidor en mi máquina principal. Esa es una diferencia sustancial con SSH. El demonio sabe de proyectos, entornos y proveedores, así que puedo arrancar un hilo y decir "corre esto allá" y el worktree se crea en ese host con su propio entorno. Cada máquina además tiene un techo de permisos, así que mi caja de pruebas puede quedarse en acceso total mientras la laptop se mantiene cerrada, y nada de lo que haga en un hilo puede subir ese techo.
Los dos modos en que trabajo. De día soy ingeniero de IA, y ese trabajo todavía implica escribir mucho software. Fuera de horario soy lo que la gente empezó a llamar un builder, que básicamente significa que tengo demasiados proyectos abiertos a la vez. Los dos modos son "muchas sesiones de agente en paralelo, varias máquinas, fácil perder el hilo". bb está hecho exactamente para eso.
Las funciones que de verdad me mantienen en flow
Me salto el recorrido guiado y nombro las cuatro cosas que cambiaron cómo transcurre un día.
Tareas que se vuelven hilos. Puedo capturar una tarea en la app y convertirla en un hilo de agente corriendo con un clic. Suena a poca cosa. La brecha entre "noté algo" y "hay un agente trabajando en eso" es justo donde mis ideas se quedaban trabadas, y reducir esa brecha a un clic significa que el backlog vive donde ya estoy trabajando, en vez de en Vikunja o Jira esperando a que yo vuelva.
Bifurcar un hilo. Puedes bifurcar una sesión en cualquier punto de su historial. La bifurcación clona la sesión real del proveedor, no solo una transcripción, así que el agente recuerda de verdad todo hasta ese punto. Es el botón de "esperá, ¿y si lo hacíamos al revés?". Lo uso todo el tiempo. Claude Code te deja hacer lo mismo de forma nativa, pero no con la misma fluidez que bb.
Chat lateral. Puedes tener una conversación paralela corta fuera del hilo principal sin molestarlo. Claude nota un "gate" sin cerrar, o un subpunto de una especificación olvidado, en medio de la ejecución, o necesito consultar algo adyacente, y el contexto del hilo principal queda limpio.
Notas en los turnos. Esa es la que no existía. Así que la construí.
El plugin
La API de plugins de bb no es una API de plugins en el sentido habitual de "expusimos seis hooks". Un plugin es TypeScript que extiende el servidor directamente: su propia base de datos SQLite, endpoints HTTP y RPC, trabajos en segundo plano, ajustes que se renderizan en la interfaz, componentes React en la app y su propio subcomando bb que funciona igual que cualquiera de los incorporados. Casi todo lo que trae bb está construido así, y esa es la prueba real de que la API es honesta.
Todo el asunto me llevó quince, quizá veinte minutos.
Lo que hace: pasas el mouse por cualquier mensaje de un hilo, haces clic en "Add note" y se abre una pestaña de Notes en el panel lateral con un cuadro ya anclado a ese mensaje. Escribes, guardas con Cmd+Enter. Nunca sales de la sesión, que era la mitad del punto.
La otra mitad es lo que vuelve después. Las notas se listan en orden de línea de tiempo, así que leer el panel de arriba abajo recorre la sesión en orden. Cada una lleva un fragmento del mensaje al que está pegada, y la nota sigue sentada en su propia posición dentro de un hilo por el que puedo hacer scroll. Así que no tengo que resumir el contexto en el momento de capturarlo. Simplemente señalo y sigo, y el razonamiento sigue ahí cuando vuelvo, porque nunca separé la nota de la conversación que la produjo.
También hay un comando bb note add, así que un script o un hook pueden dejar una marca.
Lo que se niega a hacer
Las notas nunca llegan al modelo. Nunca se inyectan en el contexto, nunca se envían a un proveedor, nunca influyen en un turno. Son mías.
El valor de estas notas es que son mi comentario en vivo sobre lo que el agente está haciendo. En el segundo en que se convierten en entrada del modelo, dejan de ser observaciones y pasan a ser instrucciones, y pierdo el único lugar del flujo de trabajo donde estoy pensando yo solo.
Una excepción honesta: registrar el comando de CLI significa que un agente puede descubrir que existe la función de notas y escribir una. El contenido sigue sin volver nunca a él, pero escribir puede. En vez de esconder eso, las notas creadas así se etiquetan como "via bb note" en lugar de "You", para que siempre pueda distinguir cuáles escribí yo.
Aristas ásperas
Las notas se renderizan en un panel lateral y no en línea debajo del mensaje, que es lo que yo había esperado en un principio.
Solo puedes anotar mensajes de usuario y de asistente, no llamadas a herramientas ni su salida. La API lo tipa así. La CLI es la salida de emergencia cuando necesito una.
Y bb está en 0.38.0 y se mueve rápido. Todo lo que diga sobre su superficie de plugins tiene fecha de vencimiento. Tenlo en cuenta si vas a construir algo.
La parte que se generaliza
Normalmente, querer una función pequeña significa levantar un pedido y esperar, si es que llegas hasta ahí. Quizá se implementa, probablemente no, y en cualquier caso la decisión pertenece a alguien cuyas prioridades no son las tuyas. No es culpa de nadie. Es simplemente lo que pasa cuando un producto atiende a cien mil personas con cien mil flujos de trabajo distintos.
Ese trato solía ser inevitable, porque construir la función tú mismo costaba más que vivir sin ella. Esa es la parte que está cambiando. El costo de "constrúyelo y ya" bajó lo suficiente como para que, en una función genuinamente pequeña con beneficios desproporcionados, esperar sea ahora la opción cara.
Lo cual significa que se está volviendo una elección. Y la gente que siga esperando el pedido de función va a estar cada vez más eligiendo esperar.
Si quieres seguir sintiendo la adrenalina de llevar tus agentes al límite, consíguete herramientas que se ajusten a cómo trabajas.
Yo escribí el plugin Session Notes. No escribí bb y no tengo relación con el proyecto. bb tiene licencia MIT y es gratis, en getbb.app. El plugin también es MIT, en github.com/pablooliva/bb-ide-session-notes-plugin. Versiones al momento de escribir: bb 0.38.0, plugin SDK 0.4.6.