<?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: Guilherme Yamakawa de Oliveira</title>
    <description>The latest articles on DEV Community by Guilherme Yamakawa de Oliveira (@guilherme44).</description>
    <link>https://dev.to/guilherme44</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F30816%2F90a4981b-417b-4d41-ac2c-4be6e1433b90.jpg</url>
      <title>DEV Community: Guilherme Yamakawa de Oliveira</title>
      <link>https://dev.to/guilherme44</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guilherme44"/>
    <language>en</language>
    <item>
      <title>[PT-BR] McLovin: o roteador de links multiplataforma</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Fri, 15 May 2026 18:37:44 +0000</pubDate>
      <link>https://dev.to/guilherme44/pt-br-mclovin-o-roteador-de-links-multiplataforma-488o</link>
      <guid>https://dev.to/guilherme44/pt-br-mclovin-o-roteador-de-links-multiplataforma-488o</guid>
      <description>&lt;p&gt;&lt;a href="https://guilherme44.com/blog/the-link-routing-gap/" rel="noopener noreferrer"&gt;Semana passada escrevi&lt;/a&gt; que roteamento de links é a feature que SO e browser fingem não existir, e fechei dizendo que essa era de IA podia trazer um roteador multiplataforma decente, e que eu seria o divulgador número um. O multiplataforma ainda não saiu, mas a parte do Linux saiu. Lanço hoje o &lt;a href="https://mclovin.org" rel="noopener noreferrer"&gt;McLovin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Igual no &lt;a href="https://pt.wikipedia.org/wiki/Superbad" rel="noopener noreferrer"&gt;Superbad&lt;/a&gt;, o McLovin se dá bem com o Sistema Operacional (Oficial Slater) e os browsers (Oficial Michaels). Amigo dos dois, ele direciona cada link pro lugar certo.&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%2F2xeanpe7w8u33qdkb1h7.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%2F2xeanpe7w8u33qdkb1h7.png" alt="Menu principal do McLovin com browsers detectados e badge de update" width="800" height="632"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Menu principal da GUI&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Por que o McLovin existe?
&lt;/h2&gt;

&lt;p&gt;No Mac eu usava o &lt;a href="https://github.com/johnste/finicky" rel="noopener noreferrer"&gt;Finicky&lt;/a&gt;. Migrei pro Linux com o &lt;a href="https://omarchy.org" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; faz quase um ano e fui procurar equivalente. O &lt;a href="https://github.com/sonnyp/Junction" rel="noopener noreferrer"&gt;Junction&lt;/a&gt; só pergunta a cada link, o &lt;a href="https://github.com/BachoSeven/mimi" rel="noopener noreferrer"&gt;mimi&lt;/a&gt; não tem regras de roteamento. Sobrava o caminho do "monta o teu", e eu montei. Funcionou muito bem, fiz uma TUI que combinava com o Omarchy. Aí pensei: isso aqui deveria existir em todo SO por padrão, igual a regra que cada SO tem pra escolher qual app abre PDF. Então decidi fazer o McLovin do jeito certo: um roteador multiplataforma, configurável por qualquer pessoa, com picker de browser quando precisar e regras pra mandar cada link pro lugar certo.&lt;/p&gt;

&lt;p&gt;No iOS e no Android, esse problema também existe, mas fica pra depois.&lt;/p&gt;
&lt;h2&gt;
  
  
  O que é
&lt;/h2&gt;

&lt;p&gt;O McLovin se registra como o handler default do sistema pra &lt;code&gt;http&lt;/code&gt; e &lt;code&gt;https&lt;/code&gt;. Quando você clica em qualquer link, no Slack, no terminal, ou em qualquer outro app, o SO entrega a URL pro McLovin. Ele lê o &lt;code&gt;rules.toml&lt;/code&gt;, decide pra onde mandar, despacha o app ou browser certo, e some.&lt;/p&gt;

&lt;p&gt;Se nenhuma regra bater, abre um picker no estilo &lt;a href="https://github.com/abenz1267/walker" rel="noopener noreferrer"&gt;Walker&lt;/a&gt; pra você escolher entre os browsers detectados. Dois frontends compartilham o mesmo core em Rust: uma CLI pra automação e keybinds, e uma GUI (&lt;code&gt;mclovin settings&lt;/code&gt;) pra mouse e teclado.&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%2Fi4niftjcdj3c3es1l6aw.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%2Fi4niftjcdj3c3es1l6aw.png" alt="Picker do McLovin com browsers detectados" width="800" height="503"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Picker quando nenhuma regra bate&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  As regras
&lt;/h2&gt;

&lt;p&gt;As regras vivem no &lt;code&gt;~/.config/mclovin/rules.toml&lt;/code&gt;. São três tipos: substring, regex com reescrita, e Lua pra regras dinâmicas. Um exemplo curto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;fallback_browser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"brave"&lt;/span&gt;

&lt;span class="nn"&gt;[[handler]]&lt;/span&gt;
&lt;span class="py"&gt;match&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"github.com/empresa"&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chrome --profile-directory='Profile 1' {url}"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"GitHub do trabalho no Chrome do trabalho"&lt;/span&gt;

&lt;span class="nn"&gt;[[handler]]&lt;/span&gt;
&lt;span class="py"&gt;match_regex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'^https?://open\.spotify\.com/(\w+)/([^?#/]+)'&lt;/span&gt;
&lt;span class="py"&gt;rewrite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"spotify --uri=spotify:{1}:{2}"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Spotify aberto direto no app desktop"&lt;/span&gt;

&lt;span class="nn"&gt;[[handler]]&lt;/span&gt;
&lt;span class="py"&gt;match_lua&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ctx.url.host:find('work') and ctx.now.hour &amp;lt; 18"&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chrome --profile-directory='Profile 1' {url}"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Links de trabalho dentro do horário comercial"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;fallback_browser&lt;/code&gt; cobre o que não bate em nenhuma regra. O Lua roda num ambiente isolado (sem &lt;code&gt;os.execute&lt;/code&gt;, sem &lt;code&gt;loadfile&lt;/code&gt;) e recebe o contexto da URL, a hora atual, e o app que originou o clique. Receitas prontas pra colar saem com &lt;code&gt;mclovin examples&lt;/code&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%2Ftsynds2bnkwdkfokjhii.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%2Ftsynds2bnkwdkfokjhii.png" alt="Lista de regras configuradas no McLovin" width="800" height="632"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Lista de regras na GUI&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Status
&lt;/h2&gt;

&lt;p&gt;A versão alpha pra Linux já está funcionando. macOS e Windows vêm em breve. Pra qualquer problema, abra uma issue no &lt;a href="https://github.com/guilhermeyo/mclovin-release/issues" rel="noopener noreferrer"&gt;GitHub do mclovin-release&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onde ver
&lt;/h2&gt;

&lt;p&gt;O manual de instalação, configuração e exemplos de regras está no site oficial:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mclovin.org" rel="noopener noreferrer"&gt;mclovin.org&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalizando
&lt;/h2&gt;

&lt;p&gt;No post passado escrevi "eu, além de usar, seria o divulgador número um" de um roteador multiplataforma decente. Estou divulgando o meu. Falta o multiplataforma, mas no Linux já está entregue.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente em &lt;a href="https://guilherme44.com/blog/launching-mclovin/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mclovin</category>
      <category>linux</category>
      <category>browsers</category>
      <category>productivity</category>
    </item>
    <item>
      <title>McLovin: the cross-platform link router</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Fri, 15 May 2026 18:37:40 +0000</pubDate>
      <link>https://dev.to/guilherme44/mclovin-the-cross-platform-link-router-19ho</link>
      <guid>https://dev.to/guilherme44/mclovin-the-cross-platform-link-router-19ho</guid>
      <description>&lt;p&gt;&lt;a href="https://guilherme44.com/en/blog/the-link-routing-gap/" rel="noopener noreferrer"&gt;Last week I wrote&lt;/a&gt; that link routing is the feature OSes and browsers pretend isn't there, and closed by saying this AI era could bring a cross-platform router, and that I'd be the number one promoter. The cross-platform piece didn't ship yet, but the Linux piece did. Today I'm launching &lt;a href="https://mclovin.org" rel="noopener noreferrer"&gt;McLovin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just like in &lt;a href="https://www.imdb.com/title/tt0829482/" rel="noopener noreferrer"&gt;Superbad&lt;/a&gt;, McLovin gets along with the Operating System (Officer Slater) and the browsers (Officer Michaels). Friends with both, he steers each link to the right place.&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%2F4icmavjuyqq109j043mx.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%2F4icmavjuyqq109j043mx.png" alt="McLovin settings main menu with detected browsers and an update badge" width="800" height="632"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Main menu of the GUI&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why does McLovin exist?
&lt;/h2&gt;

&lt;p&gt;On Mac I used &lt;a href="https://github.com/johnste/finicky" rel="noopener noreferrer"&gt;Finicky&lt;/a&gt;. I switched to Linux with &lt;a href="https://omarchy.org" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; almost a year ago and went looking for an equivalent. &lt;a href="https://github.com/sonnyp/Junction" rel="noopener noreferrer"&gt;Junction&lt;/a&gt; only asks every time, &lt;a href="https://github.com/BachoSeven/mimi" rel="noopener noreferrer"&gt;mimi&lt;/a&gt; doesn't carry routing rules. The remaining path was "build your own", and I did. It worked well, with a TUI that paired nicely with Omarchy. Then I thought: this should be a built-in feature on every OS, the same way each OS has a rule for which app opens PDFs. So I decided to do McLovin the right way: a cross-platform router, configurable by anyone, with a browser picker when nothing matches and rules to send every link to the right place.&lt;/p&gt;

&lt;p&gt;iOS and Android have the same problem, but that's for later.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;McLovin registers as the system's default handler for &lt;code&gt;http&lt;/code&gt; and &lt;code&gt;https&lt;/code&gt;. When you click any link, in Slack, in your terminal, or in any other app, the OS hands the URL to McLovin. It reads &lt;code&gt;rules.toml&lt;/code&gt;, decides where to send it, dispatches the right app or browser, and gets out of the way.&lt;/p&gt;

&lt;p&gt;If no rule matches, a &lt;a href="https://github.com/abenz1267/walker" rel="noopener noreferrer"&gt;Walker&lt;/a&gt;-style picker shows the detected browsers and lets you pick one. Two frontends share one Rust core: a CLI for automation and keybinds, and a GUI (&lt;code&gt;mclovin settings&lt;/code&gt;) for mouse and keyboard.&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%2Fxuyyvd5l0kpcjwoafpsb.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%2Fxuyyvd5l0kpcjwoafpsb.png" alt="McLovin picker listing detected browsers" width="800" height="503"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Picker shown when no rule matches&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The rules
&lt;/h2&gt;

&lt;p&gt;Rules live in &lt;code&gt;~/.config/mclovin/rules.toml&lt;/code&gt;. Three kinds: substring, regex with rewrite, and Lua for dynamic rules. A short example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;fallback_browser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"brave"&lt;/span&gt;

&lt;span class="nn"&gt;[[handler]]&lt;/span&gt;
&lt;span class="py"&gt;match&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"github.com/work-org"&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chrome --profile-directory='Profile 1' {url}"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Work GitHub in the work Chrome profile"&lt;/span&gt;

&lt;span class="nn"&gt;[[handler]]&lt;/span&gt;
&lt;span class="py"&gt;match_regex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'^https?://open\.spotify\.com/(\w+)/([^?#/]+)'&lt;/span&gt;
&lt;span class="py"&gt;rewrite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"spotify --uri=spotify:{1}:{2}"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Spotify links opened in the desktop app"&lt;/span&gt;

&lt;span class="nn"&gt;[[handler]]&lt;/span&gt;
&lt;span class="py"&gt;match_lua&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ctx.url.host:find('work') and ctx.now.hour &amp;lt; 18"&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chrome --profile-directory='Profile 1' {url}"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Work links during business hours"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fallback_browser&lt;/code&gt; covers anything that doesn't match. Lua runs in a sandboxed environment (no &lt;code&gt;os.execute&lt;/code&gt;, no &lt;code&gt;loadfile&lt;/code&gt;) and receives the URL context, the current time, and the app that triggered the click. Ready-made recipes come from &lt;code&gt;mclovin examples&lt;/code&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%2Fxg93hiaiikk3mb7g3ekx.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%2Fxg93hiaiikk3mb7g3ekx.png" alt="List of rules configured in McLovin" width="800" height="632"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Rules list in the GUI&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Status
&lt;/h2&gt;

&lt;p&gt;The Linux alpha is working today. macOS and Windows are coming soon. Run into a problem? Open an issue on the &lt;a href="https://github.com/guilhermeyo/mclovin-release/issues" rel="noopener noreferrer"&gt;mclovin-release GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to look
&lt;/h2&gt;

&lt;p&gt;The full install guide, configuration manual, and rule examples live on the official site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mclovin.org" rel="noopener noreferrer"&gt;mclovin.org&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;In the previous post I wrote "I'd be the number one promoter" of a decent cross-platform router. I'm promoting mine. The cross-platform part isn't there yet, but Linux is.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://guilherme44.com/en/blog/launching-mclovin/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mclovin</category>
      <category>linux</category>
      <category>browsers</category>
      <category>productivity</category>
    </item>
    <item>
      <title>[PT-BR] Pela terceira vez, o Google enfia coisa no seu PC sem perguntar</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Fri, 08 May 2026 18:31:44 +0000</pubDate>
      <link>https://dev.to/guilherme44/pt-br-pela-terceira-vez-o-google-enfia-coisa-no-seu-pc-sem-perguntar-3pdf</link>
      <guid>https://dev.to/guilherme44/pt-br-pela-terceira-vez-o-google-enfia-coisa-no-seu-pc-sem-perguntar-3pdf</guid>
      <description>&lt;p&gt;Se você usa o Chrome, tem 4GB de modelo de IA na sua máquina que você nunca pediu. E não é a primeira vez que o Google faz isso, é a terceira. O pesquisador &lt;a href="https://www.thatprivacyguy.com/" rel="noopener noreferrer"&gt;Alexander Hanff&lt;/a&gt; &lt;a href="https://www.thatprivacyguy.com/blog/chrome-silent-nano-install/" rel="noopener noreferrer"&gt;publicou o relatório&lt;/a&gt; em 4 de maio de 2026. O arquivo se chama &lt;code&gt;weights.bin&lt;/code&gt;, fica em &lt;code&gt;OptGuideOnDeviceModel&lt;/code&gt; dentro do diretório do Chrome, e é o Gemini Nano. Sem aviso, sem checkbox. Se você descobrir e apagar, o Chrome baixa de novo no próximo restart.&lt;/p&gt;

&lt;p&gt;A primeira reação aqui foi de déjà vu, não de surpresa. Em dezembro de 2020 o &lt;a href="https://x.com/lorenb/status/1337832978253230081" rel="noopener noreferrer"&gt;Loren Brichter&lt;/a&gt; (@lorenb no X, o cara do "pull to refresh" e do &lt;a href="https://en.wikipedia.org/wiki/Tweetie" rel="noopener noreferrer"&gt;Tweetie&lt;/a&gt;, cliente que o Twitter comprou em 2010 pra virar o app oficial do iPhone) publicou o &lt;a href="https://chromeisbad.com/" rel="noopener noreferrer"&gt;chromeisbad.com&lt;/a&gt;, um site de uma página explicando como o Keystone, o updater do Google Chrome no Mac, ficava rodando em background deixando o sistema lento mesmo com o Chrome fechado. A reclamação dele veio onze anos depois da &lt;a href="https://www.wired.com/2009/02/why-googles-sof/" rel="noopener noreferrer"&gt;Wired publicar "Google Software Update Tool is evil"&lt;/a&gt; sobre o mesmo Keystone, quando ele apareceu enfiado no Google Earth coletando dados de hardware e baixando coisas em background sem avisar. O remédio que o Brichter indicou foi escrever instruções pra desinstalar Chrome e Keystone na mão, e recomendar Safari, Brave, Vivaldi, Opera no lugar.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que o Hanff descobriu
&lt;/h2&gt;

&lt;p&gt;A descoberta dele é mais detalhada que a do Brichter em 2020. O Hanff cruzou logs de filesystem do macOS (&lt;code&gt;.fseventsd&lt;/code&gt;), o &lt;code&gt;Local State&lt;/code&gt; do Chrome, feature flags e logs do GoogleUpdater pra montar uma cadeia de evidências de quatro pontas. No perfil de teste dele, o &lt;code&gt;weights.bin&lt;/code&gt; apareceu em 24 de abril de 2026 às 16:38:54 e levou 14 minutos e 28 segundos pra terminar de baixar. Silenciosamente. Cada perfil de Chrome roda esse processo de novo.&lt;/p&gt;

&lt;p&gt;A versão afetada é a Chrome 147 e seguintes. O modelo serve pra features como "Help me write" (composição de texto), detecção local de scam e APIs que sites podem chamar (&lt;code&gt;Summarizer API&lt;/code&gt;, &lt;code&gt;Translator API&lt;/code&gt;, &lt;code&gt;Prompt API&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  A parte que dá raiva
&lt;/h2&gt;

&lt;p&gt;Aquele botão chamativo de "AI Mode" que apareceu no omnibox do Chrome, que parece ser a feature visível de IA do browser, não usa o modelo local. As consultas digitadas ali vão pra cloud do Google. Ou seja: o usuário paga 4GB de download e 4GB de espaço em disco por um modelo que não roda quando ele clica no botão de IA do browser. O custo fica com o usuário, o uso fica com o Google.&lt;/p&gt;

&lt;h2&gt;
  
  
  Em escala
&lt;/h2&gt;

&lt;p&gt;Hanff fez as contas: 0,24 kWh por dispositivo pra baixar e instalar, 0,06 kg de CO2e por dispositivo. Em 1 bilhão de instalações, são 240 GWh e 60 mil toneladas de CO2e, equivalente à emissão anual de cerca de 13 mil carros europeus. E com a União Europeia em cima do GDPR, da ePrivacy Directive (o Artigo 5(3) proíbe armazenar dados no dispositivo do usuário sem consentimento prévio) e da CSRD (a diretiva europeia de reporte de sustentabilidade), a chance de virar caso jurídico é alta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como tirar isso da sua máquina
&lt;/h2&gt;

&lt;p&gt;O Google adicionou em fevereiro de 2026 a opção pra desabilitar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chrome Settings &amp;gt; System &amp;gt; "Turn On-device AI on or off"&lt;/strong&gt;, se a opção já apareceu pra você.&lt;/li&gt;
&lt;li&gt;Caminho alternativo: digite &lt;code&gt;chrome://flags&lt;/code&gt; na barra de endereço, busque por "optimization guide on device" e marque como "Disabled". Reinicie o Chrome.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lembrando que apagar o &lt;code&gt;weights.bin&lt;/code&gt; na unha não basta. Sem desabilitar a flag, o Chrome baixa de novo.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que faço no meu dia a dia
&lt;/h2&gt;

&lt;p&gt;Não uso o Chrome como browser principal há tempos. &lt;a href="https://guilherme44.com/blog/the-link-routing-gap/" rel="noopener noreferrer"&gt;Escrevi semana passada sobre roteamento de links&lt;/a&gt;, e no setup que descrevo lá os browsers que abrem cada link são Chromium-based ou Firefox-based (Brave, Vivaldi, Edge, Opera, Helium), não o Chrome do Google em si. Os mesmos nomes, que o Brichter recomendou em 2020, continuam servindo bem em 2026.&lt;/p&gt;

&lt;p&gt;A regra que adotei é simples. Não dá pra confiar num programa que decide instalar 4GB de IA, ou um daemon updater em background, sem te perguntar. O que tá em jogo não é só espaço em disco, é o controle sobre o que o seu computador faz quando você não tá olhando.&lt;/p&gt;

&lt;h2&gt;
  
  
  E lá vamos nós pela terceira vez
&lt;/h2&gt;

&lt;p&gt;Em 2009 a Wired publicou que o Keystone era evil quando o Google enfiou ele junto com o Google Earth. Em 2020 o Brichter publicou o chromeisbad porque o mesmo Keystone tava dentro do Chrome. Agora em 2026 o Hanff mostrou que são 4GB de IA, instalados do mesmo jeito. Entre essas datas o Google só ficou maior, e a forma de empurrar coisa no PC dos outros sem perguntar não mudou.&lt;/p&gt;

&lt;p&gt;Eu uso o Brave, e recomendo usar qualquer outro browser, menos o Google Chrome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fontes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.thatprivacyguy.com/blog/chrome-silent-nano-install/" rel="noopener noreferrer"&gt;Alexander Hanff, That Privacy Guy! (4 maio 2026)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chromeisbad.com/" rel="noopener noreferrer"&gt;Loren Brichter, chromeisbad.com (dez 2020)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomshardware.com/tech-industry/cyber-security/google-chrome-silently-downloads-4gb-ai-model-to-your-device-without-permission-report-claims-researcher-says-practice-may-violate-eu-law-waste-thousands-of-kilowatts-of-energy" rel="noopener noreferrer"&gt;Tom's Hardware: Chrome silently downloads 4GB AI model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.androidauthority.com/google-chrome-weights-bin-ai-model-download-explained-3664043/" rel="noopener noreferrer"&gt;Android Authority: explicação técnica do weights.bin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.malwarebytes.com/blog/news/2026/05/google-chromes-silent-4gb-ai-download-problem" rel="noopener noreferrer"&gt;Malwarebytes: Chrome's silent 4GB AI download problem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente em &lt;a href="https://guilherme44.com/blog/chrome-silently-installed-ai/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>chrome</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>For the third time, Google sneaks something onto your PC without asking</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Fri, 08 May 2026 18:31:41 +0000</pubDate>
      <link>https://dev.to/guilherme44/for-the-third-time-google-sneaks-something-onto-your-pc-without-asking-gge</link>
      <guid>https://dev.to/guilherme44/for-the-third-time-google-sneaks-something-onto-your-pc-without-asking-gge</guid>
      <description>&lt;p&gt;If you use Chrome, there are 4GB of an AI model sitting on your machine that you never asked for. And it is not the first time Google does this, it is the third. Privacy researcher &lt;a href="https://www.thatprivacyguy.com/" rel="noopener noreferrer"&gt;Alexander Hanff&lt;/a&gt; &lt;a href="https://www.thatprivacyguy.com/blog/chrome-silent-nano-install/" rel="noopener noreferrer"&gt;published the report&lt;/a&gt; on May 4, 2026. The file is called &lt;code&gt;weights.bin&lt;/code&gt;, lives in &lt;code&gt;OptGuideOnDeviceModel&lt;/code&gt; inside the Chrome user data directory, and it is the Gemini Nano model. No prompt, no checkbox. Find it and delete it, and Chrome re-downloads it on the next restart.&lt;/p&gt;

&lt;p&gt;The first reaction here was déjà vu, not surprise. In December 2020, &lt;a href="https://x.com/lorenb/status/1337832978253230081" rel="noopener noreferrer"&gt;Loren Brichter&lt;/a&gt; (@lorenb on X, the guy behind "pull to refresh" and &lt;a href="https://en.wikipedia.org/wiki/Tweetie" rel="noopener noreferrer"&gt;Tweetie&lt;/a&gt;, the client Twitter bought in 2010 to become its official iPhone app) published &lt;a href="https://chromeisbad.com/" rel="noopener noreferrer"&gt;chromeisbad.com&lt;/a&gt;, a one-page site explaining how Keystone, Google Chrome's updater on Mac, kept running in the background, dragging the system down even when Chrome was closed. His complaint came eleven years after &lt;a href="https://www.wired.com/2009/02/why-googles-sof/" rel="noopener noreferrer"&gt;Wired published "Google Software Update Tool is evil"&lt;/a&gt; about the same Keystone, when it showed up bundled with Google Earth, gathering hardware data and downloading things in the background without warning. Brichter's prescription was a manual uninstall guide for Chrome and Keystone, plus a list of replacements: Safari, Brave, Vivaldi, Opera.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Hanff found
&lt;/h2&gt;

&lt;p&gt;His discovery is more detailed than Brichter's was in 2020. Hanff cross-referenced macOS filesystem logs (&lt;code&gt;.fseventsd&lt;/code&gt;), Chrome's &lt;code&gt;Local State&lt;/code&gt;, feature flags, and GoogleUpdater logs to build a four-way evidence chain. On his test profile, &lt;code&gt;weights.bin&lt;/code&gt; appeared on April 24, 2026 at 16:38:54 and took 14 minutes and 28 seconds to finish downloading. Silently. Each Chrome profile runs the process again.&lt;/p&gt;

&lt;p&gt;The affected version is Chrome 147 onward. The model powers features like "Help me write" (text composition), local scam detection, and APIs that sites can call (&lt;code&gt;Summarizer API&lt;/code&gt;, &lt;code&gt;Translator API&lt;/code&gt;, &lt;code&gt;Prompt API&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The frustrating part
&lt;/h2&gt;

&lt;p&gt;That bright "AI Mode" pill that showed up in Chrome's omnibox, the visible AI feature of the browser, does not use the local model. Queries typed there are sent to Google's cloud. So the user pays 4GB of download and 4GB of disk for a model that does not run when they click the most prominent AI button on the browser. The cost lives with the user, the use lives with Google.&lt;/p&gt;

&lt;h2&gt;
  
  
  At scale
&lt;/h2&gt;

&lt;p&gt;Hanff did the math: 0.24 kWh per device for the download and install, 0.06 kg of CO2e per device. At 1 billion installs, that is 240 GWh and 60,000 tonnes of CO2e, equivalent to the annual emissions of about 13,000 European cars. And with the European Union watching closely on GDPR, the ePrivacy Directive (Article 5(3) prohibits storing data on a user's device without prior consent), and the Corporate Sustainability Reporting Directive, the chance of this turning into a legal case is high.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to remove it
&lt;/h2&gt;

&lt;p&gt;Google added an opt-out in February 2026:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chrome Settings &amp;gt; System &amp;gt; "Turn On-device AI on or off"&lt;/strong&gt;, if the option is showing up for you yet.&lt;/li&gt;
&lt;li&gt;Alternative path: type &lt;code&gt;chrome://flags&lt;/code&gt; in the address bar, search for "optimization guide on device", and set it to "Disabled". Restart Chrome.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that deleting &lt;code&gt;weights.bin&lt;/code&gt; by hand is not enough. Without disabling the flag, Chrome downloads it again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do in my daily setup
&lt;/h2&gt;

&lt;p&gt;I have not been using Chrome as my main browser for a long time. &lt;a href="https://guilherme44.com/blog/the-link-routing-gap/" rel="noopener noreferrer"&gt;I wrote last week about link routing&lt;/a&gt;, and in the setup I describe there the browsers that open each link are Chromium-based or Firefox-based (Brave, Vivaldi, Edge, Opera, Helium), not Google's own Chrome. The same names, recommended by Brichter back in 2020, still serve well in 2026.&lt;/p&gt;

&lt;p&gt;The rule I keep is simple. You cannot trust a program that decides to install 4GB of AI weights, or a background updater daemon, without asking you. What is at stake is not just disk space, it is control over what your computer does when you are not looking.&lt;/p&gt;

&lt;h2&gt;
  
  
  And here we go for the third time
&lt;/h2&gt;

&lt;p&gt;In 2009 Wired called Keystone evil when Google bundled it inside Google Earth. In 2020 Brichter published chromeisbad because the same Keystone was now sitting inside Chrome. Now in 2026 Hanff showed that 4GB of AI weights are being pushed the same way. Between those dates Google only got bigger, and the way it pushes things onto other people's machines without asking has not changed.&lt;/p&gt;

&lt;p&gt;I use Brave, and my recommendation is any browser, just not Google Chrome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.thatprivacyguy.com/blog/chrome-silent-nano-install/" rel="noopener noreferrer"&gt;Alexander Hanff, That Privacy Guy! (May 4, 2026)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chromeisbad.com/" rel="noopener noreferrer"&gt;Loren Brichter, chromeisbad.com (Dec 2020)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomshardware.com/tech-industry/cyber-security/google-chrome-silently-downloads-4gb-ai-model-to-your-device-without-permission-report-claims-researcher-says-practice-may-violate-eu-law-waste-thousands-of-kilowatts-of-energy" rel="noopener noreferrer"&gt;Tom's Hardware: Chrome silently downloads 4GB AI model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.androidauthority.com/google-chrome-weights-bin-ai-model-download-explained-3664043/" rel="noopener noreferrer"&gt;Android Authority: technical breakdown of weights.bin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.malwarebytes.com/blog/news/2026/05/google-chromes-silent-4gb-ai-download-problem" rel="noopener noreferrer"&gt;Malwarebytes: Chrome's silent 4GB AI download problem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://guilherme44.com/en/blog/chrome-silently-installed-ai/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>chrome</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Awesome!!</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Tue, 05 May 2026 02:22:44 +0000</pubDate>
      <link>https://dev.to/guilherme44/awesome-4ehg</link>
      <guid>https://dev.to/guilherme44/awesome-4ehg</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/aoligama/a-live-activity-isnt-a-notification-2k9o" class="crayons-story__hidden-navigation-link"&gt;A Live Activity isn't a notification&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/aoligama" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F1453761%2F78200e0f-c511-4bb3-bae3-712f13bfa74c.jpeg" alt="aoligama profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/aoligama" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Amanda Gama
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Amanda Gama
                
              
              &lt;div id="story-author-preview-content-3611931" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/aoligama" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F1453761%2F78200e0f-c511-4bb3-bae3-712f13bfa74c.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Amanda Gama&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/aoligama/a-live-activity-isnt-a-notification-2k9o" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 5&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/aoligama/a-live-activity-isnt-a-notification-2k9o" id="article-link-3611931"&gt;
          A Live Activity isn't a notification
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ios"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ios&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mobile"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mobile&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/aoligama/a-live-activity-isnt-a-notification-2k9o" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/aoligama/a-live-activity-isnt-a-notification-2k9o#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>[PT-BR] Roteamento de links: a feature que SO e browser fingem não existir</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Sun, 03 May 2026 21:57:23 +0000</pubDate>
      <link>https://dev.to/guilherme44/pt-br-roteamento-de-links-a-feature-que-so-e-browser-fingem-nao-existir-5hn7</link>
      <guid>https://dev.to/guilherme44/pt-br-roteamento-de-links-a-feature-que-so-e-browser-fingem-nao-existir-5hn7</guid>
      <description>&lt;p&gt;&lt;a href="https://guilherme44.com/blog/omarchy-from-day-one/" rel="noopener noreferrer"&gt;Migrei do Mac pro Linux com Omarchy&lt;/a&gt; faz quase um ano. Quase tudo voltou ao lugar. Tem uma coisa que continua incomodando, e percebi que o problema é maior do que parecia. Existe uma funcionalidade simples que Sistema Operacional nenhum entrega e browser nenhum entrega: regra pra decidir qual browser ou app abre cada link clicado.&lt;/p&gt;

&lt;p&gt;No Mac eu usava o &lt;a href="https://github.com/johnste/finicky" rel="noopener noreferrer"&gt;Finicky&lt;/a&gt; pra isso. Pra quem nunca viu: ele deixa você criar regras que decidem qual browser abre cada link. Você coloca o Finicky como browser padrão do sistema, e ele aplica suas regras a cada link clicado em qualquer app, escolhendo o browser certo. As regras são pequenos scripts em JavaScript, simples ou mais elaborados conforme a necessidade. Dá até pra reescrever a URL antes de abrir, tipo forçar HTTPS, remover parâmetros de rastreamento, ou converter num link interno que abre o app desktop diretamente. Se nenhuma regra bater, ele cai num browser de reserva que você define.&lt;/p&gt;

&lt;p&gt;Na prática, é assim. Link de &lt;code&gt;github.com/empresa&lt;/code&gt; abre no browser do trabalho, &lt;code&gt;github.com/pessoal&lt;/code&gt; no browser pessoal. &lt;code&gt;meet.google.com&lt;/code&gt; cai logado no perfil certo. Vídeo de YouTube volta sempre pro browser principal. Qualquer link que não bater em nenhuma regra cai no de reserva, no meu caso o browser pessoal. Trabalho e vida pessoal separados sem ter que copiar URL e colar na outra janela.&lt;/p&gt;

&lt;p&gt;E tem o caso dos apps que vêm com versão desktop e usam um endereço próprio que abre eles direto. Spotify, WhatsApp, Slack, Discord, Zoom, cada um tem um endereço interno tipo &lt;code&gt;spotify:&lt;/code&gt;, &lt;code&gt;whatsapp:&lt;/code&gt;, &lt;code&gt;slack:&lt;/code&gt;, que o sistema entende como "esse link é desse app, abre aqui". Quando alguém compartilha um link público (&lt;code&gt;open.spotify.com/track/...&lt;/code&gt;, &lt;code&gt;wa.me/&amp;lt;numero&amp;gt;&lt;/code&gt;, &lt;code&gt;chat.whatsapp.com/&amp;lt;convite&amp;gt;&lt;/code&gt;), o ideal é abrir direto no app desktop, não numa aba de browser que vai pedir login e perguntar "abrir no app?" toda vez. No Finicky você escreve uma regra que reconhece o link público e reescreve pro endereço interno do app (&lt;code&gt;open.spotify.com/track/abc&lt;/code&gt; vira &lt;code&gt;spotify:track:abc&lt;/code&gt;, &lt;code&gt;wa.me/5511...&lt;/code&gt; vira &lt;code&gt;whatsapp://send?phone=...&lt;/code&gt;), e o sistema entrega direto pro app. Aba intermediária zero.&lt;/p&gt;

&lt;p&gt;Solução simples, efeito grande. É aí que tá o estranho.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que existe no Linux
&lt;/h2&gt;

&lt;p&gt;Procurei equivalente e o que mais aparece é o &lt;a href="https://github.com/sonnyp/Junction" rel="noopener noreferrer"&gt;Junction&lt;/a&gt;: bonito, ativo, bem mantido. Mas ele só &lt;em&gt;pergunta&lt;/em&gt; qual browser usar a cada link. Não tem regras, não decide sozinho. Tem pedido aberto na comunidade pra ele lembrar de uma escolha padrão e só perguntar quando você segurar Alt, mas ninguém pegou pra implementar. Junction só pergunta, não roteia.&lt;/p&gt;

&lt;p&gt;O &lt;a href="https://github.com/BachoSeven/mimi" rel="noopener noreferrer"&gt;mimi&lt;/a&gt; é uma alternativa mais decente ao mecanismo padrão do Linux que abre links (&lt;code&gt;xdg-open&lt;/code&gt;), mas também não traz regras de roteamento prontas.&lt;/p&gt;

&lt;p&gt;Fora isso, sobra o caminho velho: criar um atalho próprio na pasta de apps do usuário (&lt;code&gt;~/.local/share/applications/&lt;/code&gt;), marcar esse atalho como o programa que vai abrir os links do sistema, e escrever um pequeno script que faz o roteamento na mão. Funciona, mas é peça caseira que cada um tem que manter por conta própria, sem comunidade no meio.&lt;/p&gt;

&lt;p&gt;O mais perto que tem hoje de Finicky no Linux é "monta o teu".&lt;/p&gt;

&lt;h2&gt;
  
  
  E no Mac?
&lt;/h2&gt;

&lt;p&gt;No Mac a paisagem é viva. Finicky tá em desenvolvimento ativo, lançou v4.2.2 em outubro de 2025 com editor visual de regras. Tem &lt;a href="https://sindresorhus.com/velja" rel="noopener noreferrer"&gt;Velja&lt;/a&gt;, &lt;a href="https://www.choosyosx.com/" rel="noopener noreferrer"&gt;Choosy&lt;/a&gt;, &lt;a href="https://www.defaulttamer.app/" rel="noopener noreferrer"&gt;Default Tamer&lt;/a&gt;, &lt;a href="https://github.com/fluffypony/yojam" rel="noopener noreferrer"&gt;Yojam&lt;/a&gt;. Mercado inteiro de ferramenta de terceiro tapando o mesmo buraco.&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%2F7add8stkab85432n1vft.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%2F7add8stkab85432n1vft.png" alt="Editor de regras do Finicky" width="800" height="588"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Editor visual de regras do &lt;a href="https://github.com/johnste/finicky" rel="noopener noreferrer"&gt;Finicky&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;E mesmo no Mac essa cena tem casualty. O &lt;a href="https://github.com/will-stone/browserosaurus" rel="noopener noreferrer"&gt;Browserosaurus&lt;/a&gt;, outro favorito da galera, foi arquivado em 2 de agosto de 2025. Mantenedor cansou, sem sucessor oficial. Comunidade tem fork, ninguém é o canônico.&lt;/p&gt;

&lt;p&gt;É o que costuma acontecer com ferramenta de terceiro que vive pra cobrir o que SO e browser deixam aberto.&lt;/p&gt;

&lt;h2&gt;
  
  
  E no Windows?
&lt;/h2&gt;

&lt;p&gt;No Windows a história é a mesma. Você define um único browser pra abrir todos os links do sistema, ponto. Não tem como dizer "esse site abre aqui, esse outro abre lá".&lt;/p&gt;

&lt;p&gt;A novidade recente é que o Edge ganhou em 2025 uma opção pra quem tem conta corporativa Microsoft (Entra ID, antiga Azure AD): link externo cai automaticamente no profile de trabalho do Edge. É só uma opção global. Você escolhe um profile e acabou. Sem regra por URL, sem distinção de qual app abriu o link.&lt;/p&gt;

&lt;p&gt;Fora do Edge, a cena de terceiro no Windows é até maior do que no Linux. O &lt;a href="https://github.com/U-C-S/Hurl" rel="noopener noreferrer"&gt;Hurl&lt;/a&gt; (ativo) e o &lt;a href="https://github.com/mortenn/BrowserPicker" rel="noopener noreferrer"&gt;BrowserPicker&lt;/a&gt; do mortenn (na Microsoft Store) lideram. O &lt;a href="https://github.com/nref/BrowseRouter" rel="noopener noreferrer"&gt;BrowseRouter&lt;/a&gt; é um fork ativo do &lt;a href="https://github.com/DanTup/BrowserSelector" rel="noopener noreferrer"&gt;BrowserSelector original&lt;/a&gt;, que foi arquivado em 2022. Tem também o &lt;a href="https://switchbar.com/" rel="noopener noreferrer"&gt;Switchbar&lt;/a&gt;, comercial e que roda no Mac e no Windows.&lt;/p&gt;

&lt;p&gt;Mesmo padrão de sempre. Terceiro tampa o que SO e browser não tampam, e quando o terceiro arquiva (oi, BrowserSelector) a comunidade aparece com fork, ninguém vira o canônico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que nenhum Sistema Operacional entrega
&lt;/h2&gt;

&lt;p&gt;O modelo que existe nos SOs hoje é o mesmo em todo lugar. macOS, Windows, Linux. Pra cada tipo de link, você escolhe um único app que vai abrir e pronto. Link de site (&lt;code&gt;https&lt;/code&gt;)? Um browser. Email (&lt;code&gt;mailto&lt;/code&gt;)? Um cliente de email. Música (&lt;code&gt;spotify&lt;/code&gt;)? Um app. Não dá pra dizer "esse link específico vai pra outro app", nem "esse link veio do Slack, então abre em outro lugar". Cada SO chama esse mecanismo de um nome diferente (xdg-mime no Linux, LaunchServices no Mac, registry no Windows), mas a limitação é a mesma.&lt;/p&gt;

&lt;p&gt;Linux teria espaço pra ir além já que esse mecanismo é convenção, não imposição, mas ninguém moveu. macOS e Windows nunca abriram uma forma oficial pra você definir regras de roteamento de link. Trinta anos de SO desktop, e a ideia de "esse link tem que abrir aqui, esse outro tem que abrir lá" continua fora do escopo do sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que browser nenhum entrega
&lt;/h2&gt;

&lt;p&gt;Chrome tem um seletor pra escolher qual perfil do &lt;em&gt;próprio Chrome&lt;/em&gt; abre o link. Firefox tem "containers" (uma forma de isolar abas em compartimentos separados), e com extensão (Containerise, Auto Containers) dá pra rotear por padrão de URL, mas tudo isso só funciona dentro do Firefox. Nenhum browser quer mandar tráfego pra outro browser. Cada um quer ser o browser padrão do sistema.&lt;/p&gt;

&lt;p&gt;Faz sentido pelo incentivo. Mandar link pra outro browser primeiro reduz a métrica que importa pra cada empresa, que é link aberto no produto deles. Pelo lado da segurança também tem desculpa: um único browser padrão de confiança é mais simples de auditar do que um esquema que decide pra onde mandar com base em regrinha de URL. Nada disso explica o tamanho do silêncio dos SOs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enquanto isso
&lt;/h2&gt;

&lt;p&gt;Faz mais de dez anos que esse problema é o mesmo. SO e browser fingem que rotear link não é responsabilidade deles, e toda vez que aparece terceiro pra resolver, ele vira projeto solo até o mantenedor cansar. Aí volta todo mundo pra estaca zero (oi, Browserosaurus).&lt;/p&gt;

&lt;p&gt;Separar link clicado por regra é tarefa básica de quem trabalha com mais de um contexto no mesmo computador. Devia estar na base do sistema, no mesmo nível de "qual app abre PDF". Faz dez anos esperando.&lt;/p&gt;

&lt;p&gt;Seria muito bom essa era de IA finalmente trazer um multiplataforma decente para todos. Mac, Windows e Linux na mesma ferramenta. Eu, além de usar, seria o divulgador número um. Mercado pra ele a gente sabe que tem.&lt;/p&gt;




&lt;p&gt;Fontes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/johnste/finicky" rel="noopener noreferrer"&gt;Finicky&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sonnyp/Junction" rel="noopener noreferrer"&gt;Junction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/BachoSeven/mimi" rel="noopener noreferrer"&gt;mimi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/will-stone/browserosaurus" rel="noopener noreferrer"&gt;Browserosaurus (arquivado)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sindresorhus.com/velja" rel="noopener noreferrer"&gt;Velja&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.choosyosx.com/" rel="noopener noreferrer"&gt;Choosy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/U-C-S/Hurl" rel="noopener noreferrer"&gt;Hurl (Windows)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mortenn/BrowserPicker" rel="noopener noreferrer"&gt;BrowserPicker (Windows)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://switchbar.com/" rel="noopener noreferrer"&gt;Switchbar (Mac + Windows)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/title/XDG_MIME_Applications" rel="noopener noreferrer"&gt;XDG MIME Applications (ArchWiki)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://larsee.com/blog/2023/04/select-browser-dialog-in-linux/" rel="noopener noreferrer"&gt;Selecting the browser when opening links in Linux (larsee.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente em &lt;a href="https://guilherme44.com/blog/the-link-routing-gap/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>browsers</category>
      <category>productivity</category>
      <category>macos</category>
    </item>
    <item>
      <title>Link routing: the feature OSes and browsers pretend isn't there</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Sun, 03 May 2026 21:57:19 +0000</pubDate>
      <link>https://dev.to/guilherme44/link-routing-the-feature-oses-and-browsers-pretend-isnt-there-2n4d</link>
      <guid>https://dev.to/guilherme44/link-routing-the-feature-oses-and-browsers-pretend-isnt-there-2n4d</guid>
      <description>&lt;p&gt;&lt;a href="https://guilherme44.com/en/blog/omarchy-from-day-one/" rel="noopener noreferrer"&gt;I switched from Mac to Linux with Omarchy&lt;/a&gt; almost a year ago. Most things slid back into place. There's one thing still bothering me, and turns out it's not just a Linux problem. There's a simple feature no OS ships and no browser ships: rules for deciding which browser or app opens each link you click.&lt;/p&gt;

&lt;p&gt;On Mac I used &lt;a href="https://github.com/johnste/finicky" rel="noopener noreferrer"&gt;Finicky&lt;/a&gt; for this. For anyone who never saw it: it lets you write rules that decide which browser opens each link. You set Finicky as the system's default browser, and it applies your rules to every link clicked in any app, picking the right one. Rules are short scripts in JavaScript, simple or as elaborate as you need. It can even rewrite the URL before opening it: force HTTPS, strip tracking parameters, or convert it into an internal link that opens the desktop app directly. If no rule matches, it falls through to a backup browser you define.&lt;/p&gt;

&lt;p&gt;In practice, it looks like this. A &lt;code&gt;github.com/work-org&lt;/code&gt; link opens in the work browser, &lt;code&gt;github.com/personal&lt;/code&gt; in the personal one. &lt;code&gt;meet.google.com&lt;/code&gt; lands logged into the right profile. YouTube videos always come back to the main browser. Anything that matches no rule falls through to the backup, in my case the personal browser. Work and personal life kept apart without copy-pasting URLs into another window.&lt;/p&gt;

&lt;p&gt;There's also the case of apps that ship a desktop client and use their own private address to open it directly. Spotify, WhatsApp, Slack, Discord, Zoom, each has an internal address like &lt;code&gt;spotify:&lt;/code&gt;, &lt;code&gt;whatsapp:&lt;/code&gt;, &lt;code&gt;slack:&lt;/code&gt;, which the system reads as "this link belongs to that app, open it there". When someone shares a public link (&lt;code&gt;open.spotify.com/track/...&lt;/code&gt;, &lt;code&gt;wa.me/&amp;lt;phone&amp;gt;&lt;/code&gt;, &lt;code&gt;chat.whatsapp.com/&amp;lt;invite&amp;gt;&lt;/code&gt;), the right move is to open it straight in the desktop app, not in a browser tab that asks for login and prompts "open in app?" every single time. With Finicky you write a rule that matches the public link and rewrites it to the app's internal address (&lt;code&gt;open.spotify.com/track/abc&lt;/code&gt; becomes &lt;code&gt;spotify:track:abc&lt;/code&gt;, &lt;code&gt;wa.me/15551234567&lt;/code&gt; becomes &lt;code&gt;whatsapp://send?phone=...&lt;/code&gt;), and the system hands it straight to the app. No intermediate tab.&lt;/p&gt;

&lt;p&gt;Simple solution, big payoff. That's the strange part.&lt;/p&gt;

&lt;h2&gt;
  
  
  What exists on Linux
&lt;/h2&gt;

&lt;p&gt;Searched for an equivalent and the most common answer is &lt;a href="https://github.com/sonnyp/Junction" rel="noopener noreferrer"&gt;Junction&lt;/a&gt;: pretty, active, well maintained. But it only &lt;em&gt;asks&lt;/em&gt; which browser to use on every link. No rules, no auto-routing. There's a community request asking it to remember a default choice and only ask when you hold Alt, but nobody has picked it up. Junction only asks, it doesn't route.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/BachoSeven/mimi" rel="noopener noreferrer"&gt;mimi&lt;/a&gt; is a more decent replacement for the Linux mechanism that opens links (&lt;code&gt;xdg-open&lt;/code&gt;), still without ready-made routing rules.&lt;/p&gt;

&lt;p&gt;What's left is the old path: drop a custom shortcut file in the user's apps folder (&lt;code&gt;~/.local/share/applications/&lt;/code&gt;), mark that shortcut as the program that opens the system's links, and write a small script that does the routing by hand. It works, but it's a homebrew piece each user has to maintain on their own, with no community in the middle.&lt;/p&gt;

&lt;p&gt;The closest thing to Finicky on Linux today is "build your own".&lt;/p&gt;

&lt;h2&gt;
  
  
  And on Mac?
&lt;/h2&gt;

&lt;p&gt;The Mac landscape is alive. Finicky is actively developed, with v4.2.2 out in October 2025 bringing a visual rules editor. There's &lt;a href="https://sindresorhus.com/velja" rel="noopener noreferrer"&gt;Velja&lt;/a&gt;, &lt;a href="https://www.choosyosx.com/" rel="noopener noreferrer"&gt;Choosy&lt;/a&gt;, &lt;a href="https://www.defaulttamer.app/" rel="noopener noreferrer"&gt;Default Tamer&lt;/a&gt;, &lt;a href="https://github.com/fluffypony/yojam" rel="noopener noreferrer"&gt;Yojam&lt;/a&gt;. A whole third-party market plugging the same gap.&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%2F7add8stkab85432n1vft.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%2F7add8stkab85432n1vft.png" alt="Finicky rules editor" width="800" height="588"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;&lt;a href="https://github.com/johnste/finicky" rel="noopener noreferrer"&gt;Finicky&lt;/a&gt;'s visual rules editor&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Even there it has casualties. &lt;a href="https://github.com/will-stone/browserosaurus" rel="noopener noreferrer"&gt;Browserosaurus&lt;/a&gt;, another community favorite, was archived on August 2, 2025. Maintainer burned out, no official successor. Community has forks, none is canonical.&lt;/p&gt;

&lt;p&gt;That's what tends to happen to any third-party tool plugging a gap that neither the OS nor the browser wants to plug.&lt;/p&gt;

&lt;h2&gt;
  
  
  And on Windows?
&lt;/h2&gt;

&lt;p&gt;On Windows, same story. You set one browser to handle every link in the system, period. No way to say "this site opens here, that other one opens there".&lt;/p&gt;

&lt;p&gt;The recent twist is that in 2025 Edge added a toggle for users on a Microsoft corporate account (Entra ID, formerly Azure AD): external links automatically land in Edge's work profile. It's just a global toggle. You pick a profile and that's it. No URL rules, no awareness of which app opened the link.&lt;/p&gt;

&lt;p&gt;Outside Edge, the third-party scene on Windows is actually bigger than on Linux. &lt;a href="https://github.com/U-C-S/Hurl" rel="noopener noreferrer"&gt;Hurl&lt;/a&gt; (active) and mortenn's &lt;a href="https://github.com/mortenn/BrowserPicker" rel="noopener noreferrer"&gt;BrowserPicker&lt;/a&gt; (on the Microsoft Store) lead the pack. &lt;a href="https://github.com/nref/BrowseRouter" rel="noopener noreferrer"&gt;BrowseRouter&lt;/a&gt; is an active fork of the &lt;a href="https://github.com/DanTup/BrowserSelector" rel="noopener noreferrer"&gt;original BrowserSelector&lt;/a&gt;, which was archived in 2022. There's also &lt;a href="https://switchbar.com/" rel="noopener noreferrer"&gt;Switchbar&lt;/a&gt;, commercial and running on both Mac and Windows.&lt;/p&gt;

&lt;p&gt;Same old pattern. Third-party plugs what OS and browser won't, and when the third-party gets archived (hi, BrowserSelector) the community spins up forks, none becoming the canonical one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why no OS ships this
&lt;/h2&gt;

&lt;p&gt;The model across operating systems is the same everywhere. macOS, Windows, Linux. For each kind of link, you pick one app that opens it, end of story. A web link (&lt;code&gt;https&lt;/code&gt;)? One browser. Email (&lt;code&gt;mailto&lt;/code&gt;)? One mail client. Music (&lt;code&gt;spotify&lt;/code&gt;)? One app. No way to say "this specific link goes to a different app", or "this link came from Slack so open it somewhere else". Each OS calls this mechanism by a different name (xdg-mime on Linux, LaunchServices on macOS, the registry on Windows), but the limit is the same.&lt;/p&gt;

&lt;p&gt;Linux has room to go further since this mechanism is convention, not enforcement, but nobody has moved. macOS and Windows never opened a public API for routing links by rule. Thirty years of desktop OS, and the idea of "this link belongs here, that other link belongs there" still sits outside the system's scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why no browser ships this
&lt;/h2&gt;

&lt;p&gt;Chrome has a selector for picking which profile of &lt;em&gt;Chrome itself&lt;/em&gt; opens the link. Firefox has "containers" (a way to isolate tabs into separate compartments), and with extensions (Containerise, Auto Containers) you can route by URL pattern, but all of that only works inside Firefox. No browser wants to hand traffic over to another browser. Each one wants to be the system's default browser.&lt;/p&gt;

&lt;p&gt;The incentive math is clear. Sending links to a different browser first reduces the metric that matters for each company, links opened in their own product. The security argument is also there: one trusted default browser is easier to audit than a system that decides where to send things based on URL-matching rules. None of that explains the size of the silence on the OS side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meanwhile
&lt;/h2&gt;

&lt;p&gt;This problem has been the same for over ten years. OSes and browsers act like routing a link isn't their responsibility, and every time a third-party tool steps up to fix it, it ends up a solo project until the maintainer burns out. Then everyone goes back to square one (hi, Browserosaurus).&lt;/p&gt;

&lt;p&gt;Splitting clicked links by rule is a basic task for anyone juggling more than one context on the same machine. It belongs in the base of the system, at the same level as "which app opens PDFs". Been ten years waiting.&lt;/p&gt;

&lt;p&gt;It would be great for this AI era to finally bring a decent cross-platform one for everyone. Mac, Windows and Linux in the same tool. Beyond just using it, I'd be its number-one evangelist. The market is there, we all know that.&lt;/p&gt;




&lt;p&gt;Sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/johnste/finicky" rel="noopener noreferrer"&gt;Finicky&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sonnyp/Junction" rel="noopener noreferrer"&gt;Junction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/BachoSeven/mimi" rel="noopener noreferrer"&gt;mimi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/will-stone/browserosaurus" rel="noopener noreferrer"&gt;Browserosaurus (archived)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sindresorhus.com/velja" rel="noopener noreferrer"&gt;Velja&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.choosyosx.com/" rel="noopener noreferrer"&gt;Choosy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/U-C-S/Hurl" rel="noopener noreferrer"&gt;Hurl (Windows)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mortenn/BrowserPicker" rel="noopener noreferrer"&gt;BrowserPicker (Windows)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://switchbar.com/" rel="noopener noreferrer"&gt;Switchbar (Mac + Windows)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/title/XDG_MIME_Applications" rel="noopener noreferrer"&gt;XDG MIME Applications (ArchWiki)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://larsee.com/blog/2023/04/select-browser-dialog-in-linux/" rel="noopener noreferrer"&gt;Selecting the browser when opening links in Linux (larsee.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://guilherme44.com/en/blog/the-link-routing-gap/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>browsers</category>
      <category>productivity</category>
      <category>macos</category>
    </item>
    <item>
      <title>[PT-BR] Por que troquei meu "Opinionated Linux" autoral (DIY) pelo Omarchy</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Sat, 02 May 2026 12:23:32 +0000</pubDate>
      <link>https://dev.to/guilherme44/pt-br-por-que-troquei-meu-opinionated-linux-autoral-diy-pelo-omarchy-5bab</link>
      <guid>https://dev.to/guilherme44/pt-br-por-que-troquei-meu-opinionated-linux-autoral-diy-pelo-omarchy-5bab</guid>
      <description>&lt;p&gt;Tô usando o &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; como setup principal desde 26 de junho de 2025, dia em que o DHH lançou a primeira versão. Antes tinha meu "Opinionated Linux" autoral (DIY), o &lt;a href="https://github.com/guilhermeyo/mclovin-ARCHived" rel="noopener noreferrer"&gt;mclovin-ARCHived&lt;/a&gt;: um installer Arch + &lt;a href="https://i3wm.org/" rel="noopener noreferrer"&gt;i3wm&lt;/a&gt; com tudo configurado do meu jeito. Era controle total sobre o SO: eu decidindo o que entra, mantendo cada peça (i3wm, &lt;a href="https://github.com/polybar/polybar" rel="noopener noreferrer"&gt;polybar&lt;/a&gt;, &lt;a href="https://github.com/yshui/picom" rel="noopener noreferrer"&gt;picom&lt;/a&gt;, &lt;a href="https://sw.kovidgoyal.net/kitty/" rel="noopener noreferrer"&gt;kitty&lt;/a&gt;, dotfiles) atualizada e fazendo elas conversarem entre si pra o SO inteiro funcionar. Servia bem, mas era custoso de manter atualizado: sempre desbravando algum TUI novo pra resolver um probleminha, e trocar de CPU ou notebook era ver compatibilidade de tudo e ajustar pra cada máquina.&lt;/p&gt;

&lt;p&gt;O &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; resolveu isso entregando o mesmo tipo de setup, só que com uma comunidade inteira por trás, trabalhando e discutindo melhorias toda semana. Aprendo algo novo o tempo todo.&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%2Fwommzbv5sh5f1dsbxqc2.jpg" 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%2Fwommzbv5sh5f1dsbxqc2.jpg" alt="Omarchy rodando com o tema Osaka Jade" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Tema: &lt;a href="https://omarchythemes.com/themes/osaka-jade" rel="noopener noreferrer"&gt;Osaka Jade&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que o Omarchy
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; é uma distro Arch opinativa criada pelo &lt;a href="https://dhh.dk/" rel="noopener noreferrer"&gt;David Heinemeier Hansson (DHH)&lt;/a&gt;, criador do &lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;Rails&lt;/a&gt;, do &lt;a href="https://basecamp.com/" rel="noopener noreferrer"&gt;Basecamp&lt;/a&gt; e do &lt;a href="https://www.hey.com/" rel="noopener noreferrer"&gt;Hey&lt;/a&gt;. Por baixo é &lt;a href="https://archlinux.org/" rel="noopener noreferrer"&gt;Arch Linux&lt;/a&gt; + &lt;a href="https://hyprland.org/" rel="noopener noreferrer"&gt;Hyprland&lt;/a&gt;, mas vem com tudo pré-configurado: lock screen, menu bar, bluetooth, temas, atalhos. Nada de instalar pacote por pacote.&lt;/p&gt;

&lt;p&gt;O que me convenceu: Hyprland puro é bonito mas cru. Sozinho ele te deixa configurando coisas básicas por semanas. O &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; escolhe defaults bons e te entrega um sistema pronto pra trabalhar poucos minutos depois do boot.&lt;/p&gt;

&lt;p&gt;É irmão do &lt;a href="https://github.com/basecamp/omakub" rel="noopener noreferrer"&gt;Omakub&lt;/a&gt;, versão Ubuntu da mesma ideia. Quem quer Linux com curva mais suave vai pro Omakub, quem quer Arch sem perder dois dias configurando vai pro &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Temas
&lt;/h2&gt;

&lt;p&gt;Um dos pontos fortes do &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; é a comunidade de temas. O &lt;a href="https://omarchythemes.com/" rel="noopener noreferrer"&gt;omarchythemes.com&lt;/a&gt; reúne dezenas de temas prontos pra instalar com um comando, e a paleta inteira muda junta: terminal, editor, status bar, lock screen, wallpaper. E a troca é instantânea. Um atalho, dois segundos, todo o sistema já tá com o novo visual. Impressionante toda vez. A hero shot lá em cima tá com o Osaka Jade. Abaixo, um dia a dia com o Rose of Dune.&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%2Fndqdnzj5o5a3nth62y6i.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%2Fndqdnzj5o5a3nth62y6i.png" alt="Omarchy num workflow tiled com tema Rose of Dune" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Tema: &lt;a href="https://omarchythemes.com/themes/roseofdune" rel="noopener noreferrer"&gt;Rose of Dune&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  De onde vim
&lt;/h2&gt;

&lt;p&gt;Voltei pro Linux saindo de um MacBook M1 com 16GB de RAM. Vários fatores pesaram: o Docker estourava a memória e no Mac RAM é soldada, não dá pra subir, precisa comprar um novo (e configurar com mais memória vira coisa burocrática e cara); pra ter um tiling window manager precisava desabilitar parte da proteção do sistema (o SIP) pra forçar o &lt;a href="https://github.com/koekeishiya/yabai" rel="noopener noreferrer"&gt;Yabai&lt;/a&gt; (tiling WM pra Mac), e qualquer update do macOS quebrava algo; e queria saber o que tava rodando na máquina, já que Mac, Windows e até Ubuntu vêm cheios de coisa que você não pediu, mandando telemetria sem transparência. Até o Chrome no macOS instala um daemon silencioso chamado Keystone por trás (vale ler o &lt;a href="https://chromeisbad.com/" rel="noopener noreferrer"&gt;chromeisbad.com&lt;/a&gt;). Trocar pra Arch era o caminho natural.&lt;/p&gt;

&lt;p&gt;Construí o &lt;a href="https://github.com/guilhermeyo/mclovin-ARCHived" rel="noopener noreferrer"&gt;mclovin-ARCHived&lt;/a&gt; pra automatizar a instalação do meu setup Arch + i3wm + polybar + &lt;a href="https://neovim.io/" rel="noopener noreferrer"&gt;neovim&lt;/a&gt; + dotfiles. O nome era referência ao McLovin do filme Superbad, era basicamente meu "script superbad".&lt;/p&gt;

&lt;p&gt;A referência inicial foi o &lt;a href="https://github.com/basecamp/omakub" rel="noopener noreferrer"&gt;Omakub&lt;/a&gt; do DHH, que mostrou o padrão "rodar um script e ter tudo pronto". Não fui pro Omakub direto porque anos atrás já tinha usado muito Ubuntu e não curtia o estilo do &lt;a href="https://www.gnome.org/" rel="noopener noreferrer"&gt;GNOME&lt;/a&gt;, queria algo mais personalizável e tiling. Mas a ideia ficou.&lt;/p&gt;

&lt;p&gt;Outras inspirações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.ml4w.com/" rel="noopener noreferrer"&gt;ML4W&lt;/a&gt;, outro projeto de automação de Arch que cheguei perto de adotar&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/@typecraft_dev" rel="noopener noreferrer"&gt;typecraft_dev&lt;/a&gt; no YouTube, com tutoriais de Hyprland, i3wm, Neovim e Arch&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://caffeine.wiki/x220.html" rel="noopener noreferrer"&gt;caffeine.wiki/x220&lt;/a&gt;, onde o Rodrigo Franco (caffo) personalizou o Arch + &lt;a href="https://dwm.suckless.org/" rel="noopener noreferrer"&gt;dwm&lt;/a&gt; num Thinkpad X220 pra ter uma máquina barata, durável e discreta pra trabalhar em qualquer canto (cafezinho de bairro suspeito incluso)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O installer fazia o trabalho. Mas era trabalho de manter sozinho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que migrei
&lt;/h2&gt;

&lt;p&gt;Ter installer próprio é divertido até o dia que você precisa fazer o display manager funcionar com a webcam nova. Ou descobrir que aquele &lt;a href="https://aur.archlinux.org/" rel="noopener noreferrer"&gt;AUR&lt;/a&gt; helper que você escolheu três anos atrás virou abandonware. Ou ver que o tema do polybar quebrou porque a fonte mudou de nome num update.&lt;/p&gt;

&lt;p&gt;Tudo isso é resolvível. Mas resolvível por uma pessoa só não escala bem.&lt;/p&gt;

&lt;p&gt;Como uso Ruby on Rails, sempre acompanhei o trabalho do DHH. O Rails é o que ele chama de &lt;a href="https://dhh.dk/2012/rails-is-omakase.html" rel="noopener noreferrer"&gt;omakase&lt;/a&gt; (em japonês, "deixa comigo, eu escolho"): você usa os defaults bons que vieram com a caixa, sem ficar configurando cada peça. &lt;a href="https://github.com/basecamp/omakub" rel="noopener noreferrer"&gt;Omakub&lt;/a&gt; levou a mesma ideia pro Ubuntu, e em junho de 2025 saiu o &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;, omakase pra Arch + Hyprland. Continuação natural. Entrei no dia 1.&lt;/p&gt;

&lt;p&gt;Acompanhar cada release desde o início faz parte da graça. O sistema fica mais redondo a cada versão, e a vista de perto da evolução compensa uns perrengues no caminho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando faz sentido pra você
&lt;/h2&gt;

&lt;p&gt;Antes da checklist prática: o &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; faz sentido se você é curioso pra entender como Linux funciona na prática. Vai acompanhar o projeto, atualizar, eventualmente quebrar o SO e ter que formatar pra arrumar. Não é caminho pra qualquer um. Mas é assim que se ganha conhecimento real de como o sistema funciona, em vez de só usar de longe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; é ótimo se você:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quer Arch + tiling WM mas não quer gastar dias configurando&lt;/li&gt;
&lt;li&gt;Curte a pegada omakase: defaults opinativos, convenção sobre configuração&lt;/li&gt;
&lt;li&gt;Tá disposto a aprender Hyprland (ele tem suas pegadinhas)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sobre hardware: roda bem até em máquinas antigas. Vários Macs com Intel que estavam parados em gaveta voltaram pra ativa rodando &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;. Alguns hardwares ficam mais difíceis de configurar, mas a comunidade no &lt;a href="https://discord.gg/tXFUdasqhY" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; e no &lt;a href="https://github.com/basecamp/omarchy" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; do projeto geralmente já passou pelo problema e ajuda a resolver.&lt;/p&gt;

&lt;p&gt;Não é pra você se quiser configurar cada bit do sistema na mão (nesse caso, Arch puro é o caminho), ou se prefere &lt;a href="https://kde.org/" rel="noopener noreferrer"&gt;KDE&lt;/a&gt;/GNOME (&lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; é Hyprland-only por design).&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalizando
&lt;/h2&gt;

&lt;p&gt;Manter um installer próprio de Linux foi uma fase boa, aprendi muito. Mas chegar no &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; é poder usar a mesma filosofia sem ser o único responsável por mantê-la.&lt;/p&gt;

&lt;p&gt;Formato o computador e em poucos minutos tenho tudo configurado de novo. Mac não funciona bem assim, Windows muito menos.&lt;/p&gt;

&lt;p&gt;E nem tudo é escrito em pedra. Ainda quero montar um "Opinionated Script" pro macOS com keybindings e tiling window manager parecidos com o do &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;, já que preciso do macOS pra usar Xcode e publicar pra iOS. Faz sentido deixar a máquina configurada na mesma pegada, sem ter que viver dentro dela. Com IA hoje, montar um script desse é tranquilo.&lt;/p&gt;

&lt;p&gt;Pra quem quer Arch produtivo no dia a dia sem virar o mantenedor solo, &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; é a melhor pedida.&lt;/p&gt;




&lt;p&gt;Fontes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://world.hey.com/dhh/omarchy-is-out-4666dd31" rel="noopener noreferrer"&gt;DHH: Omarchy is out&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/basecamp/omakub" rel="noopener noreferrer"&gt;Omakub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ml4w.com/" rel="noopener noreferrer"&gt;ML4W&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/guilhermeyo/mclovin-ARCHived" rel="noopener noreferrer"&gt;mclovin-ARCHived&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@typecraft_dev" rel="noopener noreferrer"&gt;typecraft_dev no YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://caffeine.wiki/x220.html" rel="noopener noreferrer"&gt;Arch on Thinkpad X220 (caffeine.wiki)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente em &lt;a href="https://guilherme44.com/blog/omarchy-from-day-one/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>omarchy</category>
      <category>archlinux</category>
      <category>hyprland</category>
      <category>linux</category>
    </item>
    <item>
      <title>Why I traded my custom "Opinionated Linux" for Omarchy</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Sat, 02 May 2026 12:23:28 +0000</pubDate>
      <link>https://dev.to/guilherme44/why-i-traded-my-custom-opinionated-linux-for-omarchy-5i</link>
      <guid>https://dev.to/guilherme44/why-i-traded-my-custom-opinionated-linux-for-omarchy-5i</guid>
      <description>&lt;p&gt;I've been using &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; as my main setup since June 26, 2025, the day DHH released the first version. Before that I had my own custom Opinionated Linux, &lt;a href="https://github.com/guilhermeyo/mclovin-ARCHived" rel="noopener noreferrer"&gt;mclovin-ARCHived&lt;/a&gt;: an Arch + &lt;a href="https://i3wm.org/" rel="noopener noreferrer"&gt;i3wm&lt;/a&gt; installer set up exactly the way I liked. It was total control over the OS: me deciding what goes in, keeping every piece (i3wm, &lt;a href="https://github.com/polybar/polybar" rel="noopener noreferrer"&gt;polybar&lt;/a&gt;, &lt;a href="https://github.com/yshui/picom" rel="noopener noreferrer"&gt;picom&lt;/a&gt;, &lt;a href="https://sw.kovidgoyal.net/kitty/" rel="noopener noreferrer"&gt;kitty&lt;/a&gt;, dotfiles) up to date and making sure they all talked to each other for the whole OS to keep working. It did the job, but it was costly to keep up to date: always digging into some new TUI to solve a small issue, and changing CPU or laptop meant checking compatibility for everything and tweaking for each machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; solved that by delivering the same kind of setup, but with a whole community behind it, working and discussing improvements every week. I learn something new all the time.&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%2Fwommzbv5sh5f1dsbxqc2.jpg" 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%2Fwommzbv5sh5f1dsbxqc2.jpg" alt="Omarchy running the Osaka Jade theme" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Theme: &lt;a href="https://omarchythemes.com/themes/osaka-jade" rel="noopener noreferrer"&gt;Osaka Jade&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Omarchy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; is an opinionated Arch distro created by &lt;a href="https://dhh.dk/" rel="noopener noreferrer"&gt;David Heinemeier Hansson (DHH)&lt;/a&gt;, creator of &lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;Rails&lt;/a&gt;, &lt;a href="https://basecamp.com/" rel="noopener noreferrer"&gt;Basecamp&lt;/a&gt; and &lt;a href="https://www.hey.com/" rel="noopener noreferrer"&gt;Hey&lt;/a&gt;. Under the hood it's &lt;a href="https://archlinux.org/" rel="noopener noreferrer"&gt;Arch Linux&lt;/a&gt; + &lt;a href="https://hyprland.org/" rel="noopener noreferrer"&gt;Hyprland&lt;/a&gt;, but it ships with everything pre-configured: lock screen, menu bar, bluetooth, themes, keybindings. No installing packages one by one.&lt;/p&gt;

&lt;p&gt;What sold me on it: bare Hyprland is beautiful but raw. On its own, it leaves you configuring basics for weeks. &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; picks good defaults and hands you a system that's ready to work a few minutes after boot.&lt;/p&gt;

&lt;p&gt;It's the sister project to &lt;a href="https://github.com/basecamp/omakub" rel="noopener noreferrer"&gt;Omakub&lt;/a&gt;, the Ubuntu version of the same idea. People who want Linux with a softer learning curve go for Omakub; people who want Arch without losing two days configuring it go for &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Themes
&lt;/h2&gt;

&lt;p&gt;One of &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;'s strong points is the theme community. &lt;a href="https://omarchythemes.com/" rel="noopener noreferrer"&gt;omarchythemes.com&lt;/a&gt; collects dozens of themes ready to install with a single command, and the whole palette switches together: terminal, editor, status bar, lock screen, wallpaper. And the switch is instant. A keybind, two seconds, the whole system already on the new look. Impressive every time. The hero shot up top is the Osaka Jade theme. Below, a day-to-day setup with the Rose of Dune.&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%2Fndqdnzj5o5a3nth62y6i.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%2Fndqdnzj5o5a3nth62y6i.png" alt="Omarchy in a tiled workflow with the Rose of Dune theme" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;Theme: &lt;a href="https://omarchythemes.com/themes/roseofdune" rel="noopener noreferrer"&gt;Rose of Dune&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I came from
&lt;/h2&gt;

&lt;p&gt;Came back to Linux from a MacBook M1 with 16GB of RAM. A few things piled up: Docker would eat through memory and RAM on a Mac is soldered, you can't upgrade, you have to buy a new one (and speccing one with more memory gets bureaucratic and expensive); for a tiling window manager I had to disable part of the system's security (SIP) to force &lt;a href="https://github.com/koekeishiya/yabai" rel="noopener noreferrer"&gt;Yabai&lt;/a&gt; (tiling WM for Mac), and any macOS update would break something; and I wanted to know what was actually running on the machine, since Mac, Windows and even Ubuntu come packed with stuff you never asked for, shipping telemetry without much transparency. Even Chrome on macOS installs a silent daemon called Keystone in the background (worth reading &lt;a href="https://chromeisbad.com/" rel="noopener noreferrer"&gt;chromeisbad.com&lt;/a&gt;). Switching to Arch was the natural move.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/guilhermeyo/mclovin-ARCHived" rel="noopener noreferrer"&gt;mclovin-ARCHived&lt;/a&gt; to automate the install of my Arch + i3wm + polybar + &lt;a href="https://neovim.io/" rel="noopener noreferrer"&gt;neovim&lt;/a&gt; + dotfiles setup. The name was a reference to McLovin from the movie Superbad, it was basically my own "superbad script".&lt;/p&gt;

&lt;p&gt;The initial reference was &lt;a href="https://github.com/basecamp/omakub" rel="noopener noreferrer"&gt;Omakub&lt;/a&gt; by DHH, which showed me the "run a script and have everything ready" pattern. I didn't go for Omakub directly because I'd used Ubuntu a lot years ago and wasn't into the &lt;a href="https://www.gnome.org/" rel="noopener noreferrer"&gt;GNOME&lt;/a&gt; style, I wanted something more customizable and tiling. But the idea stuck.&lt;/p&gt;

&lt;p&gt;Other inspirations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.ml4w.com/" rel="noopener noreferrer"&gt;ML4W&lt;/a&gt;, another Arch automation project I came close to adopting&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/@typecraft_dev" rel="noopener noreferrer"&gt;typecraft_dev&lt;/a&gt; on YouTube, with tutorials on Hyprland, i3wm, Neovim and Arch&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://caffeine.wiki/x220.html" rel="noopener noreferrer"&gt;caffeine.wiki/x220&lt;/a&gt;, where Rodrigo Franco (caffo) tuned Arch + &lt;a href="https://dwm.suckless.org/" rel="noopener noreferrer"&gt;dwm&lt;/a&gt; on a Thinkpad X220 for a cheap, durable and low-profile machine he could use anywhere (sketchy coffee shops included)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The installer did the job. But it was solo work to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I switched
&lt;/h2&gt;

&lt;p&gt;Having your own installer is fun until the day you need to make the display manager work with a new webcam. Or you find out the &lt;a href="https://aur.archlinux.org/" rel="noopener noreferrer"&gt;AUR&lt;/a&gt; helper you picked three years ago is now abandonware. Or the polybar theme breaks because the font got renamed in some update.&lt;/p&gt;

&lt;p&gt;All solvable. But solvable by one person doesn't scale well.&lt;/p&gt;

&lt;p&gt;Since I work with Ruby on Rails, I've been following DHH's work for years. Rails is what he calls &lt;a href="https://dhh.dk/2012/rails-is-omakase.html" rel="noopener noreferrer"&gt;omakase&lt;/a&gt; (Japanese for "I'll leave it to you"): you take the good defaults that came in the box, instead of configuring every piece. &lt;a href="https://github.com/basecamp/omakub" rel="noopener noreferrer"&gt;Omakub&lt;/a&gt; took the same idea to Ubuntu, and in June 2025 came &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;, omakase for Arch + Hyprland. Natural continuation. I jumped in on day 1.&lt;/p&gt;

&lt;p&gt;Following every release from the start is part of the appeal. The system gets more polished with each version, and the up-close view of the evolution makes up for any rough patches along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  When it makes sense for you
&lt;/h2&gt;

&lt;p&gt;Before the practical checklist: &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; makes sense if you're curious about how Linux actually works under the hood. You'll follow the project, update, eventually break the OS and have to format to fix it. Not a path for everyone. But that's how you end up with real knowledge of how the system works, instead of just using it from a distance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; is great if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Want Arch + tiling WM but don't want to spend days configuring&lt;/li&gt;
&lt;li&gt;Are into the omakase approach: opinionated defaults, convention over configuration&lt;/li&gt;
&lt;li&gt;Are willing to learn Hyprland (it has its quirks)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;About hardware: it runs well even on older machines. Several old Intel Macs that had been sitting in drawers are back in action running &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;. Some hardware takes more work to configure, but the community on the project's &lt;a href="https://discord.gg/tXFUdasqhY" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; and &lt;a href="https://github.com/basecamp/omarchy" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; has usually been there before and helps you sort it out.&lt;/p&gt;

&lt;p&gt;Not for you if you want to configure every bit of the system by hand (in which case bare Arch is the path), or if you prefer &lt;a href="https://kde.org/" rel="noopener noreferrer"&gt;KDE&lt;/a&gt;/GNOME (&lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; is Hyprland-only by design).&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Keeping my own Linux installer was a good phase, taught me a lot. But landing on &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; means I get to use the same philosophy without being the only one responsible for maintaining it.&lt;/p&gt;

&lt;p&gt;I can wipe the machine and have everything configured again in a few minutes. Macs don't work that way, Windows even less.&lt;/p&gt;

&lt;p&gt;And nothing's set in stone. I still want to build an "Opinionated Script" for macOS with keybindings and a tiling window manager similar to &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;, since I need macOS to use Xcode and ship apps to iOS. Makes sense to have the machine set up in the same vibe without having to live inside it. With AI these days, putting a script like that together is straightforward.&lt;/p&gt;

&lt;p&gt;If you want productive Arch in your day to day without being the solo maintainer, &lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt; is the way.&lt;/p&gt;




&lt;p&gt;Sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://omarchy.org/" rel="noopener noreferrer"&gt;Omarchy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://world.hey.com/dhh/omarchy-is-out-4666dd31" rel="noopener noreferrer"&gt;DHH: Omarchy is out&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/basecamp/omakub" rel="noopener noreferrer"&gt;Omakub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ml4w.com/" rel="noopener noreferrer"&gt;ML4W&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/guilhermeyo/mclovin-ARCHived" rel="noopener noreferrer"&gt;mclovin-ARCHived&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@typecraft_dev" rel="noopener noreferrer"&gt;typecraft_dev on YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://caffeine.wiki/x220.html" rel="noopener noreferrer"&gt;Arch on Thinkpad X220 (caffeine.wiki)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://guilherme44.com/en/blog/omarchy-from-day-one/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>omarchy</category>
      <category>archlinux</category>
      <category>hyprland</category>
      <category>linux</category>
    </item>
    <item>
      <title>Using MinIO with Rails</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Fri, 01 May 2026 03:27:57 +0000</pubDate>
      <link>https://dev.to/guilherme44/using-minio-with-rails-5044</link>
      <guid>https://dev.to/guilherme44/using-minio-with-rails-5044</guid>
      <description>&lt;p&gt;I'm on a project where the file upload setup uses Active Storage with Amazon S3. But there's no configuration for me to download files from S3 and use them in development.&lt;/p&gt;

&lt;p&gt;When I looked at &lt;code&gt;config/storage.yml&lt;/code&gt; I saw the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;local&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Disk&lt;/span&gt;
  &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= Rails.root.join("storage") %&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I figured it would be simple, just bring everything inside the S3 Bucket into the app's &lt;code&gt;app/storage&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;I downloaded the AWS CLI and set it up with my credentials.&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%2F8entetcwj3t4g75pkcea.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%2F8entetcwj3t4g75pkcea.png" alt="Configuration AWS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I synced the S3 files into my &lt;code&gt;app/storage&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;aws s3 &lt;span class="nb"&gt;sync &lt;/span&gt;s3://bucket-name ~/Projects/selected-project/storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Started the app and it didn't work 🙄.&lt;/p&gt;

&lt;p&gt;In ActiveStorage, when the configured service is Disk, after the blob generates the key, the file is saved inside two folders and then the blob key.&lt;/p&gt;

&lt;p&gt;I checked the file path in the console and it returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; user &lt;span class="o"&gt;=&lt;/span&gt; User.first
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ActiveStorage::Blob.service.send&lt;span class="o"&gt;(&lt;/span&gt;:path_for, u.avatar.key&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"storage/jt/Y7/jtY7656jGPvfPMUUA8kX6Vb4"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I noticed those folders were the first 4 characters of the key.&lt;/p&gt;

&lt;p&gt;I thought of a few solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Write a script to generate those subfolders and place the files in them.&lt;br&gt;&lt;br&gt;&lt;br&gt;
I didn't go with this. It might not work, and since I don't have experience with scripts that change the filesystem, I figured it would take too long.&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check how Active Storage generates &lt;code&gt;path_for&lt;/code&gt; and tell it to generate directly without those subfolders.&lt;br&gt;&lt;br&gt;&lt;br&gt;
I searched and didn't find anywhere I could do that.&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duplicate the bucket inside S3 and use it for development.&lt;br&gt;&lt;br&gt;&lt;br&gt;
Didn't like the idea, I'd have to pay for storing 2 buckets.&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;a href="https://min.io/" rel="noopener noreferrer"&gt;MinIO&lt;/a&gt;.&lt;br&gt;&lt;br&gt;&lt;br&gt;
This was the option I figured was fastest and had the best cost-benefit.&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For those who don't know, MinIO is an Open Source project written in &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;Go&lt;/a&gt;, designed from the start to be the standard for object storage in private cloud. It's a cloud-native object server with concurrent, scalable and lightweight performance (&lt;a href="https://min.io/product/overview" rel="noopener noreferrer"&gt;more info&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I need to set up &lt;a href="https://min.io/" rel="noopener noreferrer"&gt;MinIO&lt;/a&gt; like S3, since the app needs to think it's talking to S3. I downloaded &lt;a href="https://min.io/" rel="noopener noreferrer"&gt;MinIO&lt;/a&gt; from their site and set up the environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MINIO_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"minio_storage_development"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MINIO_SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"minio_storage_development"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MINIO_REGION_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's configured through environment variables. You can check all the settings in the docs. (&lt;a href="https://docs.min.io/" rel="noopener noreferrer"&gt;MinIO docs&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Now just start it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;minio server ~/minio_storage

Endpoint:  http://xxx.xxx.xxx.xxx:9000  http://xxx.xxx.xxx.xxx:9000  http://127.0.0.1:9000
AccessKey: minio_storage_development
SecretKey: minio_storage_development
Region:    us-east-1

Browser Access:
  http://xxx.xxx.xxx.xxx:9000  http://xxx.xxx.xxx.xxx:9000  http://127.0.0.1:9000

Command-line Access: https://docs.min.io/docs/minio-client-quickstart-guide
  &lt;span class="nv"&gt;$ &lt;/span&gt;mc config host add myminio http://100.100.101.162:9000 minio_storage_development minio_storage_development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: I hid my IP with &lt;code&gt;xxx.xxx.xxx.xxx&lt;/code&gt; because it's static and I don't want it exposed to the web.&lt;/p&gt;

&lt;p&gt;There you go, a &lt;a href="https://min.io/" rel="noopener noreferrer"&gt;MinIO&lt;/a&gt; server running on your machine.&lt;/p&gt;

&lt;p&gt;I accessed it through my browser at &lt;code&gt;http://127.0.0.1:9000/&lt;/code&gt; using the Access Key and Secret Key, and created a Bucket called &lt;code&gt;rails_app_bucket&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the Rails settings at &lt;code&gt;config/storage.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;local&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;S3&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:9000&lt;/span&gt;
  &lt;span class="na"&gt;access_key_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;minio_storage_development&lt;/span&gt;
  &lt;span class="na"&gt;secret_access_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;minio_storage_development&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;
  &lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rails_app_bucket&lt;/span&gt;
  &lt;span class="na"&gt;force_path_style&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I moved all the files I had downloaded from the S3 bucket into the &lt;a href="https://min.io/" rel="noopener noreferrer"&gt;MinIO&lt;/a&gt; bucket folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; ~/Projects/selected-project/storage/&lt;span class="k"&gt;*&lt;/span&gt; ~/minio_storage/rails_app_bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To sync files from S3 I now use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;aws s3 &lt;span class="nb"&gt;sync &lt;/span&gt;s3://bucket-name ~/minio_storage/rails_app_bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also added &lt;a href="https://min.io/" rel="noopener noreferrer"&gt;MinIO&lt;/a&gt; to my &lt;code&gt;Procfile.development&lt;/code&gt; so the server starts whenever I run the app through foreman:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# Procfile.development
&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;: &lt;span class="n"&gt;bin&lt;/span&gt;/&lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;
&lt;span class="n"&gt;webpacker&lt;/span&gt;: &lt;span class="n"&gt;bin&lt;/span&gt;/&lt;span class="n"&gt;webpack&lt;/span&gt;-&lt;span class="n"&gt;dev&lt;/span&gt;-&lt;span class="n"&gt;server&lt;/span&gt;
&lt;span class="n"&gt;redis&lt;/span&gt;: &lt;span class="n"&gt;redis&lt;/span&gt;-&lt;span class="n"&gt;server&lt;/span&gt;
&lt;span class="n"&gt;sidekiq&lt;/span&gt;: &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;sidekiq&lt;/span&gt;
&lt;span class="n"&gt;minio&lt;/span&gt;: &lt;span class="n"&gt;minio&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; ~/&lt;span class="n"&gt;minio_storage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;It became really simple to sync the files and not get any 404 errors when running the app, or that Rails error saying the file doesn't exist.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://guilherme44.com/en/blog/using-minio-with-rails/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>minio</category>
      <category>s3</category>
    </item>
    <item>
      <title>[PT-BR] Slash commands: chega de commits sem sentido</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Fri, 01 May 2026 03:27:22 +0000</pubDate>
      <link>https://dev.to/guilherme44/pt-br-slash-commands-chega-de-commits-sem-sentido-1ooa</link>
      <guid>https://dev.to/guilherme44/pt-br-slash-commands-chega-de-commits-sem-sentido-1ooa</guid>
      <description>&lt;p&gt;Uma das coisas que mais uso desde que comecei com o Claude Code são os slash commands. E um que acho que todo dev hoje precisa ter é o &lt;code&gt;/commit&lt;/code&gt;. Ele acabou com um hábito que vários devs sofrem, até os mais experientes. O &lt;code&gt;/commit&lt;/code&gt; deixa a régua explícita, e o time todo passa a escrever commits do mesmo jeito.&lt;/p&gt;

&lt;p&gt;Sempre me importei com mensagens de commit. Mesmo dev que se importa acaba deixando um &lt;code&gt;"fixes"&lt;/code&gt; ou um &lt;code&gt;"update"&lt;/code&gt; genérico escapar numa sexta cansada ou no meio de um refactor gigante. É assim que um repo acaba com uma camada de ruído que ninguém decifra três meses depois.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é um slash command
&lt;/h2&gt;

&lt;p&gt;Slash commands não são exclusivos do Claude Code. OpenCode, Codex CLI, Aider e Continue deixam você criar seus próprios comandos de algum jeito. O formato e o gatilho mudam, mas a ideia é a mesma: um atalho curto roda um prompt mais longo que você escreveu uma vez.&lt;/p&gt;

&lt;p&gt;Vou mostrar com Claude Code, que é o que uso no dia a dia. A configuração se traduz bem pros outros.&lt;/p&gt;

&lt;p&gt;No Claude Code, um slash command é só um arquivo markdown. Você joga ele em &lt;code&gt;~/.claude/commands/&amp;lt;nome&amp;gt;.md&lt;/code&gt; (global) ou &lt;code&gt;.claude/commands/&amp;lt;nome&amp;gt;.md&lt;/code&gt; (por projeto), e pronto: &lt;code&gt;/&amp;lt;nome&amp;gt;&lt;/code&gt; vira atalho. O frontmatter tem um &lt;code&gt;description&lt;/code&gt;, e o corpo é o prompt que o agente lê quando você chama.&lt;/p&gt;

&lt;p&gt;É isso. Sem DSL, sem SDK, sem manifesto de plugin. Arquivo markdown entra, slash command sai.&lt;/p&gt;

&lt;h2&gt;
  
  
  O problema do commit
&lt;/h2&gt;

&lt;p&gt;Mesmo com um agente bom no loop, um simples &lt;code&gt;"commita minhas mudanças"&lt;/code&gt; te entrega algo passável, mas não excelente. O agente escolhe um tipo qualquer, escreve uma mensagem que serve e empilha mudanças sem relação no mesmo commit. Melhor do que sem agente nenhum. Mas dá pra melhorar.&lt;/p&gt;

&lt;p&gt;O que eu queria era algo que lesse minhas mudanças, agrupasse por domínio, escrevesse uma mensagem decente seguindo o &lt;a href="https://www.conventionalcommits.org/pt-br/v1.0.0/" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt; pra cada grupo, e pulasse os arquivos que não devem ser commitados.&lt;/p&gt;

&lt;h2&gt;
  
  
  /commit
&lt;/h2&gt;

&lt;p&gt;Aqui vai o slash command que montei pra manter os commits limpos e consistentes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analyze&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;changes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;commit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;logical&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;groups."&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Commit&lt;/span&gt;

&lt;span class="gu"&gt;## Step 1: Survey changes&lt;/span&gt;

Run &lt;span class="sb"&gt;`bin/commit-survey`&lt;/span&gt; to get the file lists and classification.

Read diffs of key files if you need more context on the changes.

&lt;span class="gu"&gt;## Step 2: Group the changes&lt;/span&gt;

Use the &lt;span class="sb"&gt;`--- classified ---`&lt;/span&gt; output as a starting point, then refine into logical commits.

Grouping strategy:
&lt;span class="p"&gt;-&lt;/span&gt; By domain/feature: e.g., all auth changes together
&lt;span class="p"&gt;-&lt;/span&gt; By layer: e.g., model tests, controller tests
&lt;span class="p"&gt;-&lt;/span&gt; By type: e.g., all config changes, all dependency updates

Files in &lt;span class="sb"&gt;`[skip]`&lt;/span&gt; should NOT be committed. If unsure about a file, skip it.

&lt;span class="gu"&gt;## Step 3: Commit each group&lt;/span&gt;

For each group, combine stage + commit in one call:

git add &lt;span class="nt"&gt;&amp;lt;specific&lt;/span&gt; &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &amp;amp;&amp;amp; git commit -m "&lt;span class="nt"&gt;&amp;lt;message&amp;gt;&lt;/span&gt;"

Order commits from most independent to most dependent:
&lt;span class="p"&gt;-&lt;/span&gt; Config/tooling changes first
&lt;span class="p"&gt;-&lt;/span&gt; Then source code changes
&lt;span class="p"&gt;-&lt;/span&gt; Then test changes
&lt;span class="p"&gt;-&lt;/span&gt; Generated files last
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esses três passos são o motor inteiro.&lt;/p&gt;

&lt;h2&gt;
  
  
  bin/commit-survey
&lt;/h2&gt;

&lt;p&gt;O Step 1 chama um script. É o que faz o resto funcionar.&lt;/p&gt;

&lt;p&gt;Eu poderia pedir pro agente rodar &lt;code&gt;git status&lt;/code&gt;, &lt;code&gt;git diff&lt;/code&gt;, parsear a saída e classificar os arquivos na cabeça dele. Funcionaria na maioria das vezes. Mas aí cada execução gasta tokens na mesma lógica de parsing, e a saída fica do jeito que o Claude tiver inspirado naquele dia.&lt;/p&gt;

&lt;p&gt;Um script Ruby curto te dá:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uma invocação previsível&lt;/li&gt;
&lt;li&gt;Menos tokens (sem saída de &lt;code&gt;git status&lt;/code&gt; pra digerir, só o resultado classificado)&lt;/li&gt;
&lt;li&gt;Buckets que batem com o jeito que você pensa no seu código&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;São ~22 linhas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;SKIP_PATTERNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%w[.env credentials master.key tasks.md notes.txt scratch .claude/]&lt;/span&gt;

&lt;span class="no"&gt;BUCKETS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"skip"&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;SKIP_PATTERNS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pat&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"test"&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"db"&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"db/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"config"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"config/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Gemfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;".rubocop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Procfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Rakefile"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"docs"&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"docs/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"README"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;".md"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"app"&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`git status --porcelain`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;chomp: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;grouped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;BUCKETS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_h&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;grouped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;BUCKETS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="no"&gt;BUCKETS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_key&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grouped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;"(none)"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;skip&lt;/code&gt; vem primeiro pra que segredos e notas nunca acabem staged. O resto é um buffet que você ajusta por projeto. Uma app Phoenix teria &lt;code&gt;lib/&lt;/code&gt;, &lt;code&gt;priv/repo/migrations/&lt;/code&gt;, &lt;code&gt;assets/&lt;/code&gt;. Uma app Next.js teria &lt;code&gt;pages/&lt;/code&gt;, &lt;code&gt;app/&lt;/code&gt;, &lt;code&gt;public/&lt;/code&gt;, &lt;code&gt;prisma/&lt;/code&gt;. Mesma ideia, paths diferentes.&lt;/p&gt;

&lt;p&gt;Roda num repo sujo e sai isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;--- unstaged ---
&lt;/span&gt; M config.toml
 M templates/index.html
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;--- untracked ---
&lt;/span&gt;&lt;span class="p"&gt;content/blog/_index.md
content/blog/post.md
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;--- classified ---
&lt;/span&gt;[skip]   (none)
[test]   (none)
[db]     (none)
[config] config.toml
[docs]   content/blog/_index.md, content/blog/post.md
[app]    templates/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O agente olha aquilo e escreve uns três commits: &lt;code&gt;chore(config): bump zola version&lt;/code&gt;, &lt;code&gt;feat(templates): add language toggle&lt;/code&gt;, &lt;code&gt;feat(blog): bootstrap section&lt;/code&gt;. Três mensagens focadas em vez de uma pra cobrir tudo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Na prática
&lt;/h2&gt;

&lt;p&gt;Eu digito &lt;code&gt;/commit&lt;/code&gt; e o Claude:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Roda &lt;code&gt;bin/commit-survey&lt;/code&gt; e lê a saída&lt;/li&gt;
&lt;li&gt;Lê diffs dos arquivos que precisar pra ter mais contexto&lt;/li&gt;
&lt;li&gt;Stage + commit de cada grupo com mensagem &lt;a href="https://www.conventionalcommits.org/pt-br/v1.0.0/" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Pula &lt;code&gt;.env&lt;/code&gt; e qualquer segredo silenciosamente&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A coisa toda leva 30 segundos, e cada commit sai limpo e bem escopado.&lt;/p&gt;

&lt;p&gt;Exemplo real desse próprio blog. Survey antes do run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[skip]   (none)
[test]   (none)
[db]     (none)
[config] config.toml
[docs]   content/blog/slash-commands-no-more-bad-commits.md, content/blog/slash-commands-no-more-bad-commits.pt-br.md
[app]    sass/_predefined.scss, sass/style.scss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que o &lt;code&gt;/commit&lt;/code&gt; produziu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(blog): add slash commands post in EN and pt-br
chore(config): drop syntax theme, switch to monochrome code blocks
style(sass): apply osaka jade palette and bump body font
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Três commits, cada um com escopo claro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Faça o seu
&lt;/h2&gt;

&lt;p&gt;O jeito mais simples de começar é copiar esse e ir ajustando. Joga o arquivo em &lt;code&gt;~/.claude/commands/commit.md&lt;/code&gt; se quiser global, ou em &lt;code&gt;.claude/commands/commit.md&lt;/code&gt; por projeto. Ajusta os patterns dos buckets pro teu stack. Pronto.&lt;/p&gt;

&lt;p&gt;Dá pra fazer a mesma coisa pra qualquer coisa que você faz toda hora: &lt;code&gt;/changelog&lt;/code&gt;, &lt;code&gt;/release&lt;/code&gt;, &lt;code&gt;/pr-draft&lt;/code&gt;, &lt;code&gt;/deploy&lt;/code&gt;. Cada um é um arquivo markdown com os passos que você teria que digitar no chat toda vez.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalizando
&lt;/h2&gt;

&lt;p&gt;A configuração é pequena, mas a diferença aparece em todo commit. Um slash command customizado mais um script pequeno já é suficiente pra fazer a IA pegar o trabalho rotineiro pra si.&lt;/p&gt;

&lt;p&gt;Chega de commits &lt;code&gt;"update"&lt;/code&gt;. Cada commit reflete a régua que você escreveu no arquivo markdown.&lt;/p&gt;




&lt;p&gt;Fontes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.conventionalcommits.org/pt-br/v1.0.0/" rel="noopener noreferrer"&gt;Conventional Commits 1.0.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.claude.com/en/docs/claude-code/slash-commands" rel="noopener noreferrer"&gt;Documentação dos slash commands do Claude Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opencode.ai/" rel="noopener noreferrer"&gt;OpenCode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openai/codex" rel="noopener noreferrer"&gt;OpenAI Codex CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aider.chat/" rel="noopener noreferrer"&gt;Aider&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://continue.dev/" rel="noopener noreferrer"&gt;Continue&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente em &lt;a href="https://guilherme44.com/blog/slash-commands-no-more-bad-commits/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>opencode</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Sending SMS with Ruby and Twilio</title>
      <dc:creator>Guilherme Yamakawa de Oliveira</dc:creator>
      <pubDate>Fri, 01 May 2026 03:27:11 +0000</pubDate>
      <link>https://dev.to/guilherme44/sending-sms-with-ruby-and-twilio-3n50</link>
      <guid>https://dev.to/guilherme44/sending-sms-with-ruby-and-twilio-3n50</guid>
      <description>&lt;p&gt;I had never built an app that needed to send SMS, but our last project at the firm required it. I talked to a friend about it and he told me about &lt;a href="http://twilio.com" rel="noopener noreferrer"&gt;Twilio&lt;/a&gt;. I did some quick research and found the docs really complete and easy to follow.&lt;/p&gt;

&lt;p&gt;For those who don't know &lt;a href="http://twilio.com" rel="noopener noreferrer"&gt;Twilio&lt;/a&gt;, it's a platform that lets you integrate voice, text messages, video, notifications and other things into your app through an API. Integrations are available in Ruby, Java, .NET, Node.js, PHP, and others.&lt;/p&gt;

&lt;p&gt;I'll show how easy it is to send SMS from the Ruby console. Soon I plan to do a screencast on how to implement this in a Ruby on Rails app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Twilio account
&lt;/h3&gt;

&lt;p&gt;Create a Twilio account and access the &lt;a href="http://twilio.com/console" rel="noopener noreferrer"&gt;Twilio Console&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Sign up: &lt;a href="https://www.twilio.com/try-twilio" rel="noopener noreferrer"&gt;https://www.twilio.com/try-twilio&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Console: &lt;a href="http://twilio.com/console" rel="noopener noreferrer"&gt;http://twilio.com/console&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you create the account you get a Trial for running tests:&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%2Fijumb18ggvdmldl0g21v.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%2Fijumb18ggvdmldl0g21v.png" alt="Twilio credentials"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;a href="https://www.twilio.com/console/phone-numbers/verified" rel="noopener noreferrer"&gt;register a verified number&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://www.twilio.com/console/phone-numbers/verified" rel="noopener noreferrer"&gt;https://www.twilio.com/console/phone-numbers/verified&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Note:&lt;/strong&gt; Verified numbers are required to send SMS in TRIAL mode.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Send the SMS
&lt;/h3&gt;

&lt;p&gt;Install the Twilio gem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;twilio-ruby &lt;span class="nt"&gt;-v&lt;/span&gt; 5.21.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open a Ruby console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight irb"&gt;&lt;code&gt;&lt;span class="go"&gt;irb
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the console we import the &lt;code&gt;twilio-ruby&lt;/code&gt; gem, set up the variables and send a message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'twilio-ruby'&lt;/span&gt;

&lt;span class="c1"&gt;# Get your SID and Auth Token from twilio.com/console&lt;/span&gt;
&lt;span class="c1"&gt;# DANGER! This is insecure.&lt;/span&gt;
&lt;span class="n"&gt;account_sid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'&lt;/span&gt;
&lt;span class="n"&gt;auth_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your_auth_token'&lt;/span&gt;
&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your_number'&lt;/span&gt; &lt;span class="c1"&gt;# Number you rented from twilio&lt;/span&gt;
&lt;span class="vi"&gt;@client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Twilio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;REST&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account_sid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;from: &lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# +15017122661&lt;/span&gt;
  &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="s1"&gt;'My first message sent with ruby.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s1"&gt;'+5544999801281'&lt;/span&gt; &lt;span class="c1"&gt;# +5544998761234&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind this is insecure. It's important to keep credentials like the SID and Auth Token stored in a way that prevents unauthorized access. Since this is just a test example, I used them straight in the console.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;As you can see, it's pretty easy to send SMS with Ruby.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twilio.com" rel="noopener noreferrer"&gt;Twilio&lt;/a&gt; offers many other services and you can check the pricing for all of them at &lt;a href="https://www.twilio.com/pricing" rel="noopener noreferrer"&gt;https://www.twilio.com/pricing&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://guilherme44.com/en/blog/sending-sms-with-ruby-and-twilio/" rel="noopener noreferrer"&gt;guilherme44.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>twilio</category>
      <category>sms</category>
    </item>
  </channel>
</rss>
