{"id":729,"date":"2026-09-18T18:34:09","date_gmt":"2026-09-18T21:34:09","guid":{"rendered":"https:\/\/yellowkode.com\/blog\/skillsync-txcript-sessoes-agentes-ia-formato-portatil\/"},"modified":"2026-09-18T18:34:09","modified_gmt":"2026-09-18T21:34:09","slug":"skillsync-txcript-sessoes-agentes-ia-formato-portatil","status":"publish","type":"post","link":"https:\/\/yellowkode.com\/blog\/skillsync-txcript-sessoes-agentes-ia-formato-portatil\/","title":{"rendered":"Skillsync e txcript: como sess\u00f5es de agentes de IA viram formato port\u00e1til entre Claude Code, Codex e Cursor"},"content":{"rendered":"<p>Se voc\u00ea j\u00e1 usou mais de um agente de codifica\u00e7\u00e3o, provavelmente descobriu que cada um guarda a conversa de um jeito, num lugar diferente, e que trocar de agente no meio do trabalho significa recome\u00e7ar. Skillsync ataca essa dor com um conversor de formato de sess\u00e3o, e a parte t\u00e9cnica que faz isso funcionar \u00e9 open source.<\/p>\n<h2>O que foi lan\u00e7ado, quem lan\u00e7ou e quando<\/h2>\n<p>No dia 17 de novembro de 2026 (ontem, na thread do Hacker News), Nars Ganeshkumar e Nishant Joshi anunciaram no Launch HN o Skillsync, batch W26 da Y Combinator. A proposta \u00e9 resumida na p\u00e1gina oficial: tornar sess\u00f5es de IA port\u00e1veis entre agentes e times, local first, sem lock in e sem precisar re-explicar contexto. Por baixo do app desktop existe um motor separado, aberto: o <a href=\"https:\/\/github.com\/skillsynchq\/txcript\" target=\"_blank\" rel=\"noopener\">txcript<\/a>, uma crate Rust que tamb\u00e9m \u00e9 publicada como pacote npm e CLI.<\/p>\n<h2>Como o txcript converte uma sess\u00e3o entre agentes<\/h2>\n<h3>O problema real: cada harness inventou o pr\u00f3prio formato<\/h3>\n<p>Antes de entender a solu\u00e7\u00e3o, vale ver o tamanho da bagun\u00e7a. Claude Code, por exemplo, grava cada sess\u00e3o como um arquivo JSONL na sua m\u00e1quina. A documenta\u00e7\u00e3o oficial confirma: o SDK escreve os transcripts em arquivos JSONL sob ~\/.claude\/projects\/ no filesystem local. Cada linha desse arquivo \u00e9 um evento: uma linha JSON por vez, onde cada linha \u00e9 um evento na conversa, uma mensagem enviada, uma resposta do Claude ou uma chamada de ferramenta e seu resultado.<\/p>\n<p>A escolha de JSONL n\u00e3o \u00e9 est\u00e9tica. O arquivo \u00e9 append only e escrito uma linha por vez conforme a sess\u00e3o faz stream. Essa \u00e9 a raz\u00e3o inteira dele ser JSONL e n\u00e3o um grande array JSON: d\u00e1 para fazer flush da linha no instante em que ela existe sem reescrever o arquivo, e um crash no meio da sess\u00e3o ainda deixa voc\u00ea com um arquivo v\u00e1lido at\u00e9 a \u00faltima linha completa.<\/p>\n<p>Codex tamb\u00e9m usa JSONL, mas com esquema pr\u00f3prio. Cursor tem outro. Antigravity, OpenCode, Amp, Grok, Hermes, cada um cravou sua estrutura. E a Anthropic \u00e9 expl\u00edcita sobre o risco de voc\u00ea tratar isso como API est\u00e1vel: o transcript padr\u00e3o pode ser armazenado localmente como JSONL, mas seu formato de entrada \u00e9 explicitamente interno e pode mudar entre releases. N\u00e3o construa um parser em cima de rela\u00e7\u00f5es ou tipos de registro n\u00e3o documentados.<\/p>\n<p>Ou seja: os formatos existem, est\u00e3o no disco, mas ningu\u00e9m prometeu compatibilidade nem estabilidade. \u00c9 esse p\u00e2ntano que o txcript aceita atravessar.<\/p>\n<h3>A ideia central: um modelo can\u00f4nico no meio<\/h3>\n<p>Pense no que o ffmpeg faz com v\u00eddeo. Voc\u00ea tem MP4, MOV, MKV, WebM, cada um com codec e container pr\u00f3prios. O ffmpeg n\u00e3o escreve um conversor espec\u00edfico de MP4 para MOV, outro de MP4 para MKV, outro de MOV para WebM. Se fizesse assim, cada formato novo exigiria N conversores. Em vez disso, tudo passa por uma representa\u00e7\u00e3o intermedi\u00e1ria de frames e streams, e cada formato s\u00f3 precisa saber ler e escrever essa representa\u00e7\u00e3o. A analogia se paga aqui porque a mec\u00e2nica \u00e9 a mesma. Ela quebra se voc\u00ea levar longe demais: sess\u00f5es de agente carregam sem\u00e2ntica (quem \u00e9 usu\u00e1rio, quem \u00e9 assistente, qual bloco \u00e9 reasoning, qual \u00e9 tool call) que v\u00eddeo n\u00e3o tem.<\/p>\n<p>O txcript faz exatamente esse hub central. A documenta\u00e7\u00e3o da crate explica em uma linha: a crate mapeia cada formato atrav\u00e9s de Transcript&lt;Common&gt; e converte com convert::&lt;A, B&gt;: A -> Common -> B. Stores preservam o shape nativo em disco. Common preserva sem\u00e2ntica de conversa que d\u00e1 para retomar, n\u00e3o identidade byte a byte.<\/p>\n<p>Traduzindo o passo a passo:<\/p>\n<ul>\n<li><strong>Store<\/strong>: sabe onde no disco cada harness guarda os arquivos e como ler e escrever no formato nativo, byte a byte.<\/li>\n<li><strong>Codec<\/strong>: sabe como transformar o texto nativo daquele harness num objeto <code>Transcript&lt;Common&gt;<\/code>, e vice versa.<\/li>\n<li><strong>Common<\/strong>: o modelo can\u00f4nico. Tem common::Message, common::Block, common::Tool e afins.<\/li>\n<\/ul>\n<p>Para converter uma sess\u00e3o de Claude Code para Codex, o fluxo \u00e9: l\u00ea o JSONL do Claude com o Store do Claude, roda o Codec do Claude para produzir um Transcript&lt;Common&gt;, roda o Codec do Codex no sentido inverso para gerar o JSONL do Codex, escreve com o Store do Codex. A garantia declarada \u00e9 bem espec\u00edfica: round trips byte losless: carregar e salvar uma sess\u00e3o no pr\u00f3prio formato reproduz ela exatamente. Entre harnesses diferentes a promessa \u00e9 outra e mais honesta: a convers\u00e3o cross harness preserva mensagens, reasoning, tool calls, tool results, imagens, metadata e usage onde dispon\u00edvel.<\/p>\n<p>Note o &#8220;onde dispon\u00edvel&#8221;. Se o alvo n\u00e3o tem lugar para guardar tokens de reasoning, aquilo se perde na tradu\u00e7\u00e3o, e \u00e9 por isso que o commom n\u00e3o promete identidade byte a byte entre formatos diferentes.<\/p>\n<h3>O modelo hub e a matem\u00e1tica de N para 1<\/h3>\n<p>Hoje o txcript declara 16 harnesses, um modelo: cada formato converte atrav\u00e9s de Transcript&lt;Common&gt;, ent\u00e3o adicionar um harness conecta ele a todos os outros. A lista atual inclui, entre outros, Claude Code, Claude Chat, Cowork, Codex, OpenCode, pi, Campfire, Cursor, Grok, Hermes, Amp e Antigravity.<\/p>\n<p>Para quem quer plugar um agente que o txcript nunca ouviu falar, existe uma porta de sa\u00edda documentada: agentes que o txcript nunca ouviu falar emitem o Simple interchange JSON documentado, um arquivo ou stream entregue ao txcript diretamente, e seus transcripts continuam em qualquer harness suportado. Isso importa porque significa que voc\u00ea n\u00e3o depende do time do Skillsync escrever um adapter para o seu agente propriet\u00e1rio: se ele sabe emitir o Simple JSON, entra na rede.<\/p>\n<h2>O que isso significa na pr\u00e1tica<\/h2>\n<p>O caso concreto que a documenta\u00e7\u00e3o do pr\u00f3prio txcript coloca na cara \u00e9 o que mais d\u00f3i no dia a dia: come\u00e7ar uma sess\u00e3o no Claude Code, bater no limite de uso ou numa parede, e continuar no Codex com a conversa, o reasoning e o hist\u00f3rico de tool calls inteiros.<\/p>\n<p>Instala\u00e7\u00e3o, para quem quer testar em Rust:<\/p>\n<pre><code>cargo install --git https:\/\/github.com\/skillsynchq\/txcript txcript-cli<\/code><\/pre>\n<p>E o uso pelo pacote npm, direto do README:<\/p>\n<pre><code>import { convert, toCommon, fromCommon, harnesses } from \"txcript\";\nimport { readFileSync, writeFileSync } from \"node:fs\";\n\nconst input = readFileSync(\"rollout.jsonl\", \"utf8\");\n\/\/ native -> native (ex.: Codex -> Claude Code)\n<\/code><\/pre>\n<p>Para o app Skillsync existe tamb\u00e9m um servidor MCP: txcript mcp exp\u00f5e as ferramentas read only list_sessions, search_sessions e read_session, para que agentes possam minerar sess\u00f5es passadas como contexto. Ou seja, um agente rodando no seu editor consegue buscar dentro do seu pr\u00f3prio hist\u00f3rico de conversas com outros agentes.<\/p>\n<p>Eu venho puxando essa linha de perto porque nos livros que escrevi, entre eles a s\u00e9rie IA na Pr\u00e1tica, o tema recorrente \u00e9 justamente que contexto \u00e9 a camada onde a maior parte das falhas de agente acontece. Ter o transcript inteiro port\u00e1vel muda o que d\u00e1 para fazer com contexto passado: em vez de resumir e perder detalhe, voc\u00ea mant\u00e9m a trilha completa e decide na hora da retomada o que puxar.<\/p>\n<h2>Onde quebra<\/h2>\n<p>Alguns pontos que a leitura da documenta\u00e7\u00e3o e da thread deixam claros:<\/p>\n<ul>\n<li><strong>Sem\u00e2ntica portada n\u00e3o \u00e9 comportamento portado.<\/strong> Mesmo com toda a conversa migrada, o agente receptor pode reagir diferente. Um dos comentaristas na thread perguntou sobre degrada\u00e7\u00e3o. Um dos fundadores respondeu que Skillsync age como conversor universal, movendo a sess\u00e3o inteira incluindo mensagens, reasoning e tool calls, mas notou em outra resposta que sess\u00f5es longas \u00e0s vezes fazem o agente receptor decidir compactar. O transcript existe e \u00e9 acess\u00edvel, mas a janela efetiva do modelo destino manda.<\/li>\n<li><strong>Formato interno pode mudar sem aviso.<\/strong> Isso \u00e9 da Anthropic, n\u00e3o do txcript: o formato de entrada do JSONL \u00e9 explicitamente interno e pode mudar entre releases. N\u00e3o construa um parser em cima de rela\u00e7\u00f5es ou tipos de registro n\u00e3o documentados. Quem depende disso em produ\u00e7\u00e3o precisa aceitar risco de manuten\u00e7\u00e3o. O txcript minimiza porque documenta cada formato com proveni\u00eancia: todo formato on disk de cada harness est\u00e1 descrito em docs\/formats\/, com proveni\u00eancia para cada afirma\u00e7\u00e3o (docs oficiais, permalinks de fonte ou notas de engenharia reversa).<\/li>\n<li><strong>Sess\u00f5es arquivadas do Codex n\u00e3o aparecem sozinhas.<\/strong> Um usu\u00e1rio reportou na thread e o pr\u00f3prio fundador confirmou que ia adicionar suporte. O PR j\u00e1 foi mergeado, mas \u00e9 o tipo de canto que aparece.<\/li>\n<li><strong>Common n\u00e3o \u00e9 identidade byte a byte.<\/strong> Vale repetir porque \u00e9 o trade off central: Common preserva sem\u00e2ntica de conversa que d\u00e1 para retomar, n\u00e3o identidade byte a byte. Se o seu caso de uso for auditoria forense do transcript original, use o Store nativo, n\u00e3o o Common.<\/li>\n<li><strong>Subagentes viajam junto?<\/strong> A depender do harness, n\u00e3o \u00e9 trivial. No Claude Code, por exemplo, se a sess\u00e3o spawnou subagentes, voc\u00ea tamb\u00e9m recebe um diret\u00f3rio irm\u00e3o nomeado com o UUID da sess\u00e3o, com um arquivo por subagente dentro. Pegar s\u00f3 o .jsonl top level significa ter a thread principal com o trabalho dos subagentes faltando. Vale checar caso a caso o que o Store do txcript coleta.<\/li>\n<\/ul>\n<p>Do lado do produto, no StartAtende, meu agente de suporte no WhatsApp, o que importa n\u00e3o \u00e9 s\u00f3 transportar a conversa entre modelos, \u00e9 decidir o que da conversa vira decis\u00e3o de produto. Portabilidade de transcript \u00e9 insumo para isso, n\u00e3o substituto: ter os bytes n\u00e3o significa ter o que fazer com eles.<\/p>\n<h2>O que ainda n\u00e3o d\u00e1 para afirmar<\/h2>\n<p>N\u00e3o testei o Skillsync ponta a ponta em cima de uma sess\u00e3o de dezenas de MB para medir qualidade real de retomada num agente de destino diferente, ent\u00e3o n\u00e3o vou falar de lat\u00eancia ou de fidelidade percebida. Tamb\u00e9m n\u00e3o sei qu\u00e3o frequentemente Claude Code e Codex v\u00e3o mudar o formato interno nos pr\u00f3ximos meses, e o quanto isso vai gerar churn de manuten\u00e7\u00e3o no txcript. A promessa de &#8220;16 harnesses&#8221; \u00e9 do reposit\u00f3rio, mas a profundidade da cobertura varia por adapter, e a \u00fanica forma honesta de saber \u00e9 abrir os arquivos em <code>docs\/formats\/<\/code> do formato que interessa a voc\u00ea e conferir.<\/p>\n<p>Tamb\u00e9m h\u00e1 um ponto de neg\u00f3cio que a documenta\u00e7\u00e3o n\u00e3o resolve: o Skillsync app tem workspaces de time onde a sess\u00e3o sai do disco. A regra declarada \u00e9 que tudo roda na sua m\u00e1quina, ent\u00e3o seu contexto continua seu, exceto o que voc\u00ea explicitamente compartilha. Qual \u00e9 a pol\u00edtica de reten\u00e7\u00e3o nesse compartilhamento, criptografia em repouso, quem no time consegue ler o qu\u00ea, isso \u00e9 conversa para o SLA e n\u00e3o para um post de blog.<\/p>\n<h2>Como testar isso voc\u00ea mesmo<\/h2>\n<p>Um caminho pequeno para experimentar em uma tarde:<\/p>\n<ol>\n<li>Localize uma sess\u00e3o sua do Claude Code em <code>~\/.claude\/projects\/&lt;projeto&gt;\/&lt;session-id&gt;.jsonl<\/code>. Abra no editor e olhe as primeiras linhas para entender o shape.<\/li>\n<li>Instale o txcript pelo cargo: <code>cargo install --git https:\/\/github.com\/skillsynchq\/txcript txcript-cli<\/code>.<\/li>\n<li>Rode <code>txcript view &lt;session-id&gt;<\/code> para ver o transcript renderizado como texto leg\u00edvel. Isso j\u00e1 valida que o Store e o Codec do Claude Code est\u00e3o lendo seu arquivo.<\/li>\n<li>Fa\u00e7a uma convers\u00e3o para o formato do Codex e escreva o resultado. Abra o Codex, rode <code>codex resume<\/code> (ou equivalente da sua vers\u00e3o) e veja se a conversa aparece.<\/li>\n<li>Pegue uma sess\u00e3o que envolveu tool calls (edi\u00e7\u00f5es de arquivo, execu\u00e7\u00e3o de shell). Compare o que o Codex &#8220;lembra&#8221; dela contra o que estava no original. \u00c9 a\u00ed que d\u00e1 para calibrar quanto de fidelidade a convers\u00e3o preserva no seu caso.<\/li>\n<\/ol>\n<p>Se o seu agente n\u00e3o \u00e9 suportado, olhe a spec do Simple interchange JSON e escreva um exporter m\u00ednimo. \u00c9 a rota mais r\u00e1pida para plugar algo custom sem esperar um adapter oficial.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Como o Skillsync usa o motor open source txcript para converter sess\u00f5es entre Claude Code, Codex e Cursor sem perder mensagens, reasoning e tool calls.<\/p>\n","protected":false},"author":2,"featured_media":728,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-729","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts\/729","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/comments?post=729"}],"version-history":[{"count":0,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts\/729\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/media\/728"}],"wp:attachment":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/media?parent=729"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/categories?post=729"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/tags?post=729"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}