<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexandre Machado</title>
    <description>The latest articles on DEV Community by Alexandre Machado (@alexandremachado).</description>
    <link>https://dev.to/alexandremachado</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F247120%2F629ce04f-1bba-459f-9e4b-32a573b28c10.jpg</url>
      <title>DEV Community: Alexandre Machado</title>
      <link>https://dev.to/alexandremachado</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexandremachado"/>
    <language>en</language>
    <item>
      <title>Fale com o Xerife!!</title>
      <dc:creator>Alexandre Machado</dc:creator>
      <pubDate>Sat, 10 Oct 2026 23:18:10 +0000</pubDate>
      <link>https://dev.to/warrenbrasil/fale-com-o-xerife-2jdb</link>
      <guid>https://dev.to/warrenbrasil/fale-com-o-xerife-2jdb</guid>
      <description>&lt;p&gt;Como esse papel ajuda a &lt;a href="https://warren.com.br/" rel="noopener noreferrer"&gt;Warren&lt;/a&gt; no onboarding, ownership e operação de incidentes emergenciais&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyb34l3x6eycz6c2ny02n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyb34l3x6eycz6c2ny02n.png" alt="Xerife Woody Pride" width="720" height="432"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Então, qual foi o problema que enxergávamos?&lt;/strong&gt;&lt;br&gt;
Com o aumento de times e demandas de produto, começamos a sentir nas retrospectivas a necessidade de endereçar algumas tarefas que não se encaixavam muito bem em nossas estruturas de times.&lt;/p&gt;

&lt;p&gt;Nesta época tínhamos somente times de produto organizados em um formato de squads e chapters e não tinhamos um time de “devops” definido.&lt;/p&gt;

&lt;p&gt;Também, as demandas de infraestrutura estavam crescendo.&lt;/p&gt;

&lt;p&gt;Além disso, precisávamos que novos integrantes dos times tivessem contato com nossos pipelines de deploy, entendessem nossa arquitetura de cloud e se sentissem mais seguros para operar, investigar e sugerir mudanças no processo de desenvolvimento, testes e entrega.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tá, mas de onde surgiu esse nome???&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk570g6nmda0nm74271jf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk570g6nmda0nm74271jf.png" alt="imagem do slack com um histórico" width="428" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inicialmente chamamos de devops da semana. Só que esse nome era um pouco restritivo para as responsabilidades que queríamos atribuir.&lt;/p&gt;

&lt;p&gt;E xerife tinha também um mindset de empoderamento e engajamento muito interessante para o propósito deste papel.&lt;/p&gt;

&lt;p&gt;Precisávamos de um nome que pudesse receber inúmeras atribuições conforme elas surgiam. Algo como um guardião final…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqqxv1bb0hn1kmd9c7w6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqqxv1bb0hn1kmd9c7w6.png" alt="Heimdall, guardião do portal do filme Thor" width="720" height="678"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A idéia então começou a ganhar adeptos e fazer sentido…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzelgelroeh829ogxr46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzelgelroeh829ogxr46.png" alt="imagem do slack com um histórico" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E foi em julho de 2019 que “oficializamos” para nosso canal interno de tecnologia nosso papel de xerife:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8w3ga0n3otv33f5egoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8w3ga0n3otv33f5egoa.png" alt="imagem do slack com um histórico" width="720" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De lá para cá, cada chapter delimitou as responsabilidades do xerife conforme suas necessidades…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chapter QA&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt;Matheus Angellos&lt;/u&gt;, QA Lead&lt;/strong&gt;: “Vejo que o papel de xerife tem diversos impactos extremamente positivos. O senso de ownership acho que é o maior deles, onde a pessoa tem que estar muito atenta a tudo que ocorre, sabendo que ela querendo ou não é a responsável por aquilo que está subindo, portanto a régua tem que estar sempre muito alta. Também é necessário muitas vezes a análise de quais problemas são de fato impeditivos, quais podem ser contornados futuramente, impactos de outros times que não somente o seu que também estão envolvidos naquele deploy. A necessidade também de ser um ponto de contato com outros xerifes e também todas as pessoas da Warren é algo que faz com que a pessoa saia da zona de conforto, pois sabemos que nem todos se sentem confortáveis com isso, mas é um baita aprendizado. Em relação a novas pessoas que vão chegando, vejo como super positiva essa primeira participação, com o devido suporte é claro, para que desde o princípio a pessoa pegue contexto do produto, das pessoas e dos fluxos da empresa como um todo.”&lt;/p&gt;

&lt;p&gt;Olha alguns itens de responsabilidade do xerife de qualidade:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Acompanhar instabilidades gerais&lt;/li&gt;
&lt;li&gt;Acompanhar o andamento do processo de deploy para STG na Sexta&lt;/li&gt;
&lt;li&gt;Validar o ambiente de STG segunda pela manhã e ir atrás dos xerifes das outras squads e da infra cloud (Oliveira — quase sempre ele) pra garantir que esteja tudo ok&lt;/li&gt;
&lt;li&gt;Acessar os ambientes de STG&lt;/li&gt;
&lt;li&gt;Acessar a intranet e conseguir fazer buscas e pesquisas tanto no cadastro como no geral&lt;/li&gt;
&lt;li&gt;Acompanhar os impedimentos que surgirem durante os testes e acessar os xerifes&lt;/li&gt;
&lt;li&gt;Fazer a liberação do deploy, comunicando nos canais #xerifes-and-qas e #dev-geral, para que seja transparente a todos&lt;/li&gt;
&lt;li&gt;Fazer o acompanhamento até o deploy virar para produção, o que pode ser feito até remotamente e após o deploy, em produção executar teste de fumaça, realizando login e navegando em uma conta real (pode ser a sua mesmo)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Chapter Android&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Onboarding&lt;/strong&gt;: “O xerife é o papel no chapter responsável por manter a ordem e os bons costumes do nosso pipeline. O principal objetivo é monitorar crashes, garantir que as branches estejam sempre syncadas e organizar nossos milestones semanais no github.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chapter iOS&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Onboarding&lt;/strong&gt;: “O xerife é o papel no chapter responsável por acompanhar o andamento dos deploys, fazer rollout do app para a loja e monitorar crashes e bugs. Cada um de nós fica 1 semana no cargo para garantir que tudo ocorra dentro da lei.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chapter Core&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt;Paulo Immig&lt;/u&gt;, Tech Lead&lt;/strong&gt;: A iniciativa do “xerifado” foi criada com o intuito de resolver um problema pontual que era dividir a carga de trabalho que acabava sobrecarregando algumas pessoas chave. No fim das contas o resultado acabou sendo ainda melhor do que essa “rotatividade” de carga de trabalho, acabou se tornando uma prática que acelera a absorção de conhecimento dos novos colaboradores da nossa arquitetura/infraestrutura como um todo, aumenta o ownership e abre espaço para que todos se destaquem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chapter API&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;u&gt;Raryson Rost&lt;/u&gt;, Tech Lead&lt;/strong&gt;: “Ser xerife é ser responsável por todos ambientes de tecnologia. Acredito que é a atividade que mais gera contexto e o sentimento de como a Warren funciona.&lt;/p&gt;

&lt;p&gt;Quando você é xerife você precisa resolver qualquer problema que aconteça com os ambientes. Independente de você ter ou não contexto daquela área.&lt;/p&gt;

&lt;p&gt;Isso garante com que o Xerife tenha que conhecer e se comunicar com outras pessoas que geralmente não são da sua stack. Assim o xerife acaba pegando mais contexto de outras áreas e do negócio inteiro.&lt;/p&gt;

&lt;p&gt;Também é legal o processo de subxerife que temos, que faz com que o xerife consiga contextualizar e apoiar outra pessoa que está começando nessa jornada. Assim facilitando o caminho e tornando mais divertido.&lt;/p&gt;

&lt;p&gt;Acredito que sem o processo de xerife não teríamos como crescer tão independente a nível de chapters. Pois uma chapter ficaria colidindo com outra ou uma pessoa ficaria muito ocupada para sempre.&lt;/p&gt;

&lt;p&gt;Com o xerife sendo rotacional e esse papel existindo conseguimos dar escala na manutenção de ambientes, contextualizar e ‘rampar’ novas pessoas no negócio e também começar a criar o sentimento de influência em pessoas que ajudam outros a serem xerife.”&lt;/p&gt;

&lt;p&gt;Acompanhe nossas novidades em &lt;a href="https://warren.com.br" rel="noopener noreferrer"&gt;https://warren.com.br&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ownership</category>
      <category>devops</category>
      <category>culture</category>
    </item>
    <item>
      <title>I Gave Claude Code a Voice on My Windows Laptop. The Slowest Part Is the Voice.</title>
      <dc:creator>Alexandre Machado</dc:creator>
      <pubDate>Sat, 10 Oct 2026 22:55:27 +0000</pubDate>
      <link>https://dev.to/alexandremachado/i-gave-claude-code-a-voice-on-my-windows-laptop-the-slowest-part-is-the-voice-10ma</link>
      <guid>https://dev.to/alexandremachado/i-gave-claude-code-a-voice-on-my-windows-laptop-the-slowest-part-is-the-voice-10ma</guid>
      <description>&lt;p&gt;At 18:59 on a Saturday I asked my laptop, in Portuguese, for a short summary of the most important tech news of the week. A voice I had cloned said "Um instante" ("one moment"). Claude Code ran a web search, and about 17 seconds after I stopped talking her answer started coming back as speech. Her pick was Google putting the first prototype satellite of Project Suncatcher in orbit.&lt;/p&gt;

&lt;p&gt;Nothing in that loop typed a word. Speech recognition, the voice and the audio pipeline all run on the laptop. The only thing that leaves the machine is the text Claude Code sends to its own API.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/-TGHosZcQTk" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The demo is in Portuguese, my first language. Turn on English captions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI disclosure:&lt;/strong&gt; most of the code in this project was written by coding agents (Claude Code, OpenAI Codex and Google Antigravity) under my direction. I drafted this article with Claude from the repo's commit history, design notes and logs, then edited it myself. Every number below comes from those logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Débora came from
&lt;/h2&gt;

&lt;p&gt;Débora started as a dictation tool. I forked &lt;a href="https://github.com/Goodsmileduck/npu-whisper" rel="noopener noreferrer"&gt;npu-whisper&lt;/a&gt;, a Windows app that runs Whisper on Intel's NPU, and turned it into something I use every day: press Ctrl+Space, talk, and the text lands at the cursor. I added NVIDIA support through faster-whisper, a device priority list with fallback (RTX, then NPU, then iGPU, then CPU) and a &lt;code&gt;uv tool install&lt;/code&gt; setup so it installs as one command instead of an afternoon of virtualenvs.&lt;/p&gt;

&lt;p&gt;The laptop matters for everything that follows: a Core Ultra 9 185H (with an NPU and an Arc iGPU) and an RTX 4070 Laptop GPU with 8 GB of VRAM.&lt;/p&gt;

&lt;p&gt;When I wrote about it on LinkedIn, I said the next step was connecting this voice layer to the AI agents I already use in the terminal. About 30 hours and 55 commits later, that step is done. These are the decisions that shaped it, and the place where it is still slow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 1: a local LLM was good enough to chat, and I still didn't use it
&lt;/h2&gt;

&lt;p&gt;The first version of voice chat ran a local model as the brain. Before replacing it, I benchmarked three on the Arc iGPU with OpenVINO GenAI, int4, same Portuguese conversations, three samples each:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;First token&lt;/th&gt;
&lt;th&gt;Tokens/s&lt;/th&gt;
&lt;th&gt;Followed the long persona prompt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-8B&lt;/td&gt;
&lt;td&gt;0.3 s&lt;/td&gt;
&lt;td&gt;~11&lt;/td&gt;
&lt;td&gt;Badly: misread my name, wrote dates as digits, used emoji&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3.5-9B&lt;/td&gt;
&lt;td&gt;2.1 s&lt;/td&gt;
&lt;td&gt;~6&lt;/td&gt;
&lt;td&gt;Yes, but about 4x slower to the first token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 E4B&lt;/td&gt;
&lt;td&gt;0.2 to 0.4 s&lt;/td&gt;
&lt;td&gt;~15&lt;/td&gt;
&lt;td&gt;Yes, every rule, and the only one that used feminine Portuguese forms on its own&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Gemma 4 E4B won clearly. It answered "Débora, que dia é hoje?" with the full date spelled out for the speech engine, and asked me to repeat myself when the transcription came out garbled. With Qwen3-8B, every rule I added to the prompt made the answers worse.&lt;/p&gt;

&lt;p&gt;I went with Claude Code anyway. A local 4B model can hold a pleasant conversation, but it can't open my repositories, check a container, read the app's own logs or search the web. Claude Code already has the tools, the project context and my instructions. So the split became: Débora owns the ears and the mouth (Whisper and the TTS), and a harness I didn't write owns the thinking. The local model is still in the code as a backend for when I want everything offline.&lt;/p&gt;

&lt;p&gt;The obvious cost is latency. A cold &lt;code&gt;claude -p&lt;/code&gt; call took 6.1 s for a short question. I measured the other CLIs the same way:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CLI&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Cold call&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claude -p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2.1.295&lt;/td&gt;
&lt;td&gt;6.1 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;codex exec&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.161.0&lt;/td&gt;
&lt;td&gt;6.1 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;copilot -s -p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.0.93&lt;/td&gt;
&lt;td&gt;7.9 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;agy -p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.3.2&lt;/td&gt;
&lt;td&gt;9.3 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Six seconds of silence after every sentence would kill a voice conversation. That led to the next decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 2: keep one Claude Code process alive
&lt;/h2&gt;

&lt;p&gt;Claude Code can run as a long-lived process that reads and writes JSON lines over stdio. This is roughly how Débora starts it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;--input-format&lt;/span&gt; stream-json &lt;span class="nt"&gt;--output-format&lt;/span&gt; stream-json &lt;span class="nt"&gt;--verbose&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include-partial-messages&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--session-id&lt;/span&gt; &amp;lt;uuid&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--permission-mode&lt;/span&gt; acceptEdits &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--permission-prompts&lt;/span&gt; host &lt;span class="nt"&gt;--permission-prompt-tool&lt;/span&gt; stdio &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--append-system-prompt-file&lt;/span&gt; &amp;lt;voice-rules.md&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each flag solves one voice problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--include-partial-messages&lt;/code&gt; streams text as it is generated, so the TTS can start on the first phrase instead of waiting for the full answer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--session-id&lt;/code&gt; and &lt;code&gt;--resume&lt;/code&gt; keep the same conversation across app restarts. I can also open that session in a normal terminal with &lt;code&gt;claude --resume &amp;lt;id&amp;gt;&lt;/code&gt; and see everything she did.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--permission-prompt-tool stdio&lt;/code&gt; turns every tool permission into a &lt;code&gt;control_request&lt;/code&gt; with &lt;code&gt;subtype: "can_use_tool"&lt;/code&gt; on stdout. Débora answers on stdin.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--append-system-prompt-file&lt;/code&gt; adds the voice-channel rules (short spoken answers, no markdown, numbers and dates written out, the date and language of the session) on top of whatever &lt;code&gt;CLAUDE.md&lt;/code&gt; the project already has.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The permission answer is small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;behavior&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;updatedInput&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;behavior&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deny&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Permissão negada pela Débora.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;control_response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subtype&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default is to deny, with an allowlist for read-only diagnostics. For the demo I had opened it up, which is why the log shows &lt;code&gt;Claude pede permissão: WebSearch&lt;/code&gt; followed by &lt;code&gt;permission allowed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before writing any of this into the app, I proved it with a throwaway script. Two turns in the same process kept a test word ("jabuticaba") in context. The first text delta took 3.8 s cold and 1.8 s warm. An interrupt sent as a &lt;code&gt;control_request&lt;/code&gt; with &lt;code&gt;subtype: "interrupt"&lt;/code&gt; ended the turn with &lt;code&gt;terminal_reason: "aborted_streaming"&lt;/code&gt;, and the process stayed alive. That last part matters, because people talk over a voice assistant all the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 3: send the raw transcription, mistakes included
&lt;/h2&gt;

&lt;p&gt;Whisper hears "dictation engine" in a Brazilian accent as "dictêixon engine". My first idea was to have a local LLM clean the transcription before it reached Claude. I tested it, and the cleanup made things worse. It fixed the obvious errors, then "corrected" the project-specific ones into something wrong ("dictêixon engine" became "Decision Engine"), and it added about a second.&lt;/p&gt;

&lt;p&gt;Claude Code understood all four raw test requests, because it had the repository open and could see &lt;code&gt;dictation_engine.py&lt;/code&gt; sitting right there. So Débora sends the raw text, and the system prompt says it came from speech recognition and may contain errors.&lt;/p&gt;

&lt;p&gt;The fix for recognition errors went to the other end of the pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude keeps a small voice memory at &lt;code&gt;~/.debora/harness/voice_memory.md&lt;/code&gt;, one line per correction: &lt;code&gt;- "what was heard" → correct term (optional context)&lt;/code&gt;. Only sessions started by Débora get this file in their prompt.&lt;/li&gt;
&lt;li&gt;The terms from that file, plus the project names found in the working folder (folder name, &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;), are passed to Whisper as hotwords, up to 40 terms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over time the recognizer picks up my project vocabulary, and fewer mistakes reach Claude in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 4: never lose what the user said
&lt;/h2&gt;

&lt;p&gt;The bug that annoyed me most in testing: I paused mid-sentence, Débora started answering, and the second half of what I said disappeared. The fix touched several parts of the pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whisper re-transcribes the growing segment about once a second while I'm still talking (in the demo, 11.9 s of speech transcribed in 0.2 s on the RTX, a real-time factor of 0.02). If the draft looks unfinished, like a trailing "and..." or an ellipsis, the VAD waits 2 s of silence instead of 0.8 s before cutting.&lt;/li&gt;
&lt;li&gt;Capture and transcription keep running while Claude thinks and while Débora speaks. Nothing gets muted.&lt;/li&gt;
&lt;li&gt;Replies go through a serial queue. Barge-in can interrupt the active turn, drain the rest of Claude's response and send the next utterance in order.&lt;/li&gt;
&lt;li&gt;An echo filter compares what the mic heard against the sentences Débora was actually playing (60% token overlap means echo), so on laptop speakers she doesn't answer herself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The numbers, from the demo log
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Turn 1: "Oi Débora, tudo bem?"&lt;/th&gt;
&lt;th&gt;Turn 2: tech news&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Final transcription after I stopped&lt;/td&gt;
&lt;td&gt;~0.2 s&lt;/td&gt;
&lt;td&gt;~0.2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude first token&lt;/td&gt;
&lt;td&gt;1.4 s&lt;/td&gt;
&lt;td&gt;17.2 s (ToolSearch + WebSearch)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First audio&lt;/td&gt;
&lt;td&gt;31.8 s&lt;/td&gt;
&lt;td&gt;~4.8 s ("Um instante")&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Whole reply spoken&lt;/td&gt;
&lt;td&gt;49.2 s&lt;/td&gt;
&lt;td&gt;still talking when the log excerpt ends, 52 s in&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Claude was fast on the first turn and audio was slow. The first sentence was queued at 2.3 s, but synthesis didn't start until 28 s. VRAM went from 1.3 GB to 5.0 GB in that window, so my reading is that the TTS server was still loading its model. The fix is to start it earlier and warm it up before the first turn.&lt;/p&gt;

&lt;p&gt;The second turn shows the real problem. Débora's voice is a clone made with Chatterbox Multilingual from a short reference recording, and on this GPU it synthesizes slower than real time. The chunks in that reply took between 1.1x and 1.4x their own audio length to generate (for example, 5.9 s of work for 5.1 s of speech). Every sentence waits for the previous one, so the gap grows over a long answer.&lt;/p&gt;

&lt;p&gt;Claude Code was not the bottleneck. With the process warm, its first token came in 1.4 s on a simple turn, and the web search turn spent its time on tools. What slows the conversation down is the voice: a voice-cloning TTS model sharing 8 GB of VRAM with Whisper on a laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who actually wrote the code
&lt;/h2&gt;

&lt;p&gt;Most of the 55 commits were written by agents. Claude Code coordinated: it broke the work down, wrote most of the harness and dispatched tasks. Codex picked up work in parallel through &lt;code&gt;codex exec&lt;/code&gt;, mostly because I had spare quota there, including the code and security reviews before merging. Antigravity got research questions and UI ideas, like how to show voice mode in both the tray icon and the overlay. Its first pass left some mess behind that Claude later cleaned up.&lt;/p&gt;

&lt;p&gt;My part was the one the agents couldn't do. I talked to her while testing, found bugs by ear ("your text gets cut off next to the mascot", "half of my sentence vanished when you interrupted me"), read the logs with them, and decided what stayed. Some of those decisions were about what not to build: no pre-cleanup LLM, no terminal UI for now, and no new Windows-only dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Débora runs her own headless Claude Code session. She can't drive a terminal you already have open.&lt;/li&gt;
&lt;li&gt;Claude answers in markdown. Only the speakable part goes to the TTS, and code and lists stay in the overlay and the log.&lt;/li&gt;
&lt;li&gt;It is Windows-only today, and the voice chat needs a GPU to be pleasant.&lt;/li&gt;
&lt;li&gt;The Whisper &lt;code&gt;language&lt;/code&gt; setting matters. If it's set to English, Portuguese speech gets translated before Claude sees it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The next piece is automatic hardware distribution. At startup Débora will probe the NPU, the iGPU and the RTX, then decide where Whisper, the TTS and a local model should each run, with a fallback for each component instead of one global device. The goal is to take the voice off the critical path. One option on this laptop is Whisper on the NPU, which would leave the whole RTX to the TTS.&lt;/p&gt;

&lt;p&gt;The code is MIT licensed: &lt;a href="https://github.com/alexandre-machado/debora-whisper" rel="noopener noreferrer"&gt;github.com/alexandre-machado/debora-whisper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One question, because I haven't solved it: has anyone gotten a local, voice-cloned TTS running faster than real time on 8 GB of VRAM? Which model, and what did it cost you in quality?&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>claude</category>
      <category>llm</category>
    </item>
    <item>
      <title>mARC – IRC-style AI agent team for Claude Code that runs its own repo</title>
      <dc:creator>Alexandre Machado</dc:creator>
      <pubDate>Mon, 06 Jul 2026 20:49:12 +0000</pubDate>
      <link>https://dev.to/alexandremachado/marc-irc-style-ai-agent-team-for-claude-code-that-runs-its-own-repo-22kk</link>
      <guid>https://dev.to/alexandremachado/marc-irc-style-ai-agent-team-for-claude-code-that-runs-its-own-repo-22kk</guid>
      <description>&lt;p&gt;I've spent the last months running my repos with an AI team instead of an AI assistant. Today I'm releasing the thing that made it work: mARC, an IRC-style agent team for Claude Code.&lt;/p&gt;

&lt;p&gt;The problem first. A single AI coding session is a brilliant engineer with no memory, no process, and no colleagues. It writes code fast and loses track faster. Decisions evaporate when the chat ends. Work happens that no board ever sees. And the same session that wrote the code is the one that reviews it, which means nobody reviews it. A smarter model doesn't fix any of this. Teams weren't invented because engineers were dumb. They were invented because shipping needs structure.&lt;/p&gt;

&lt;p&gt;So mARC gives the AI a team structure instead of a bigger brain. When you open the channel you talk to &lt;a class="mentioned-user" href="https://dev.to/techlead"&gt;@techlead&lt;/a&gt;, an operator that behaves like a tech lead, not like a code generator. Five specialists idle in the channel until pinged: an engineer, an SRE, a designer, a security reviewer, and a researcher. You say "users are getting pinged when we save issues, fix it". The tech lead writes the spec, opens a GitHub issue, puts it on the Project board, dispatches the engineer in the background, and keeps talking to you while the work runs.&lt;/p&gt;

&lt;p&gt;Four rules turn this into a team instead of a fan-out script.&lt;/p&gt;

&lt;p&gt;Specs before dispatch. A vague task produces a vague PR. The operator won't delegate anything that lacks a goal, acceptance criteria, affected files, and constraints. If something's missing it asks you first, because one question now is cheaper than a reverted PR later.&lt;/p&gt;

&lt;p&gt;The board is the source of truth, and it gets audited. Work lives in GitHub Issues and a Project board, not in the chat scrollback. Before dispatching anything, the operator checks the board against reality: merged PRs, deploys, CI. Boards lie. Merged PRs don't. Status actually means something here. Blocked means it needs you. Done means merged and validated.&lt;/p&gt;

&lt;p&gt;Nothing merges without a review the author can't skip. Every PR gets a security pass on its diff before merge. The reviewers are read-only by contract: the security agent and the researcher physically have no write tools. At one point we considered giving them a scoped write folder. The researcher went off, read OWASP's LLM guidance and GitHub's token-hardening docs, and came back recommending against its own write access. The idea died in review, where it belonged.&lt;/p&gt;

&lt;p&gt;The process itself is versioned. When something goes wrong, the lesson doesn't die in the chat. It lands in the playbook via PR and gets reviewed like any code. The team that made the mistake ships the rule that prevents it.&lt;/p&gt;

&lt;p&gt;Does this actually work? mARC runs its own repository, and every issue, PR, security review, and decision record of the team building the team is public. Including the embarrassing ones.&lt;/p&gt;

&lt;p&gt;My favorite: the team's own issue template was writing handles like @dev into GitHub issue bodies. Those are real GitHub accounts owned by real strangers, and they got mentioned on every issue we filed. One release even listed them as contributors. The team fixed the template, sanitized 14 historical issues, and added a CI gate so it can't happen again. Then the security review of that fix caught that the gate was case-sensitive, so @Dev would have slipped through. One grep flag. That's what a second pair of eyes is for.&lt;/p&gt;

&lt;p&gt;There's more in the record. A config migration where the security reviewer probed the new parser with hostile values and got two hardenings merged before the PR landed. A day when I dispatched two writing agents in parallel without isolating their worktrees and one clobbered the other's checkout. The recovery and the dispatch rule that came out of it are both public.&lt;/p&gt;

&lt;p&gt;To be clear about what this is not: it's not the demo where an agent writes a TODO app in one take. It's slower and noisier than that, on purpose. Specs before dispatch, review before merge, and a paper trail a human can audit six months later. The board isn't a visualization of what the AI did. It's the real board. I can grab any item on it and do it myself.&lt;/p&gt;

&lt;p&gt;Try it in two minutes. You need Claude Code and a GitHub repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add NexaDuo/mARC
/plugin install marc@nexaduo
/marc:tech-lead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No config, no signup. It discovers your repo at runtime: org, board, paths. If you want the binding to persist across sessions, &lt;code&gt;/marc:init&lt;/code&gt; scaffolds a team.toml, shows you every file before it writes anything, and writes nothing without your yes.&lt;/p&gt;

&lt;p&gt;The repo is the real landing page: &lt;a href="https://github.com/NexaDuo/mARC" rel="noopener noreferrer"&gt;github.com/NexaDuo/mARC&lt;/a&gt;. The whole history of an AI team running itself is in there, embarrassments included.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxfl7ix07ea9xswlehvd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxfl7ix07ea9xswlehvd4.png" alt="prompt on vscode" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>github</category>
    </item>
  </channel>
</rss>
