<?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: João Henrique</title>
    <description>The latest articles on DEV Community by João Henrique (@fontnelle).</description>
    <link>https://dev.to/fontnelle</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4191297%2F5935b816-734d-465b-9b0c-be781a685171.png</url>
      <title>DEV Community: João Henrique</title>
      <link>https://dev.to/fontnelle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fontnelle"/>
    <language>en</language>
    <item>
      <title>The One Command I Run Before Formatting Any Machine</title>
      <dc:creator>João Henrique</dc:creator>
      <pubDate>Sun, 18 Oct 2026 01:09:24 +0000</pubDate>
      <link>https://dev.to/fontnelle/the-one-command-i-run-before-formatting-any-machine-3bh8</link>
      <guid>https://dev.to/fontnelle/the-one-command-i-run-before-formatting-any-machine-3bh8</guid>
      <description>&lt;p&gt;Before I format a laptop, switch machines or try a new Linux distro, I run one command.&lt;/p&gt;

&lt;p&gt;Then I stop worrying.&lt;/p&gt;

&lt;p&gt;It wasn't always like this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ritual I used to dread
&lt;/h2&gt;

&lt;p&gt;Every new machine meant the same ritual:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reinstall Homebrew and the dozens of packages I forgot I even had&lt;/li&gt;
&lt;li&gt;Hunt down the right versions of Node and Python&lt;/li&gt;
&lt;li&gt;Dig up my dotfiles from an old repo, a USB drive or a message I sent to myself&lt;/li&gt;
&lt;li&gt;Tweak my terminal until it finally felt like &lt;em&gt;mine&lt;/em&gt; again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of the day, I was &lt;em&gt;almost&lt;/em&gt; back to where I started.&lt;/p&gt;

&lt;p&gt;And a week later, I'd still find something missing.&lt;/p&gt;

&lt;p&gt;So I built the command I wish I'd had all along. It's called &lt;strong&gt;dudu&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet dudu
&lt;/h2&gt;

&lt;p&gt;dudu is an open source CLI that turns your entire dev environment into something you can back up and restore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One command&lt;/strong&gt; captures your setup.&lt;br&gt;
&lt;strong&gt;One command&lt;/strong&gt; brings it back on a new machine.&lt;/p&gt;

&lt;p&gt;No config repo to maintain. No install scripts to write. No "I'll document this later" that never happens.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fontnelle" rel="noopener noreferrer"&gt;
        fontnelle
      &lt;/a&gt; / &lt;a href="https://github.com/fontnelle/dudu" rel="noopener noreferrer"&gt;
        dudu
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🐣 New machine, same setup. Back up your packages, runtimes, dotfiles and terminal in one command, restore them in another. macOS and Linux.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
  &lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;dudu&lt;/h1&gt;
&lt;/div&gt;
  &lt;p&gt;&lt;b&gt;Back up your whole dev setup in one command and put it back on a new machine in another. Packages, runtimes, dotfiles and terminal, on macOS and Linux.&lt;/b&gt;&lt;/p&gt;
  &lt;p&gt;English · &lt;a href="https://github.com/fontnelle/dudu/README.pt-BR.md" rel="noopener noreferrer"&gt;Português&lt;/a&gt; · &lt;a href="https://github.com/fontnelle/dudu/README.es.md" rel="noopener noreferrer"&gt;Español&lt;/a&gt;&lt;/p&gt;
  &lt;a href="https://github.com/fontnelle/dudu/stargazers" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/483ce06f44694dbec30c618493cd91278820893a5d218fe8036a28b9d7266cce/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f666f6e746e656c6c652f647564753f7374796c653d666c61742d737175617265" alt="Stars"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/fontnelle/dudu/releases" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c6926adad25b40a66464cdbe5fa7882026031dcf20cf677e0f80c25089e80f24/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f666f6e746e656c6c652f647564753f6c6162656c3d76657273696f6e267374796c653d666c61742d737175617265" alt="Version"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/fontnelle/dudu/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/942e017bf0672002dd32a857c95d66f28c5900ab541838c6c664442516309c8a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e7376673f7374796c653d666c61742d737175617265" alt="License"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/fontnelle/dudu/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/bfb82582ae033e4d8db282701dffd7b4445e61967862967d5f32dea5e8f11ef1/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f666f6e746e656c6c652f647564752f63692e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265" alt="Tests"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/fontnelle/dudu#quick-start" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/26199aeef0b030748d10910bb02121f271872c8fb80bfaf5e770a6f21b7ff36b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d6d61634f532532302537432532304c696e75782d6c69676874677265793f7374796c653d666c61742d737175617265" alt="Platform"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/fontnelle/dudu/./docs/img/backup.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ffontnelle%2Fdudu%2FHEAD%2F.%2Fdocs%2Fimg%2Fbackup.svg" alt="dudu backup: 9 tools collected, encrypted and saved to a local folder, iCloud Drive and Apple Notes" width="790"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Everything you installed from the terminal&lt;/strong&gt;: Homebrew, apt/dnf/pacman, Node versions, global npm/pnpm/yarn/bun packages, pyenv/pipx/uv, gems, cargo, go tools, VS Code and Cursor extensions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your terminal, as it was&lt;/strong&gt;: zsh, Oh My Zsh and plugins, Powerlevel10k/Starship, Terminal.app and iTerm2 profiles, Ghostty, Kitty, WezTerm, Nerd Fonts, git and SSH config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saved where you already are&lt;/strong&gt;: a local folder, iCloud Drive, Google Drive and Apple Notes, several at once&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets stay home&lt;/strong&gt;: tokens in your dotfiles are masked, key files are never copied, and &lt;code&gt;dudu secrets&lt;/code&gt; moves keys out of your &lt;code&gt;.zshrc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted if you want&lt;/strong&gt;: AES-256 with a password kept in your Keychain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe to restore&lt;/strong&gt;: a backup is treated as…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fontnelle/dudu" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;
  
  
  Try it in 30 seconds
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;fontnelle/tap/dudu

dudu backup              &lt;span class="c"&gt;# save everything to your destinations&lt;/span&gt;
dudu restore &lt;span class="nt"&gt;--dry-run&lt;/span&gt;   &lt;span class="c"&gt;# on the new machine: see what will happen&lt;/span&gt;
dudu restore             &lt;span class="c"&gt;# reinstall everything&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;No Homebrew yet? There's an install script too, and it verifies the release checksums before installing.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it captures
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Packages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Homebrew (formulae, casks, Mac App Store), apt, dnf, pacman, flatpak, snap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Runtimes and global tools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Node versions via nvm, fnm or volta, global npm/pnpm/yarn/bun packages, pyenv, pipx, uv, gems, cargo, go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dotfiles and configs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;zsh, bash, fish, Oh My Zsh plugins, Powerlevel10k, Starship, tmux, vim, nvim, git and SSH config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Terminal and editors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Terminal.app, iTerm2, Ghostty, Kitty, WezTerm, Alacritty, Nerd Fonts, VS Code and Cursor extensions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Your secrets never leave your machine
&lt;/h2&gt;

&lt;p&gt;This was the part I cared about most. Dotfiles are full of things that should never end up in a backup.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tokens get masked.&lt;/strong&gt; API keys, &lt;code&gt;ghp_…&lt;/code&gt;, &lt;code&gt;sk-…&lt;/code&gt;, &lt;code&gt;npm_…&lt;/code&gt;, AWS keys and JWTs become &lt;code&gt;&amp;lt;redacted-by-dudu&amp;gt;&lt;/code&gt; in the backup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key files are never copied.&lt;/strong&gt; &lt;code&gt;~/.ssh/id_*&lt;/code&gt;, &lt;code&gt;~/.aws/credentials&lt;/code&gt;, &lt;code&gt;~/.kube/config&lt;/code&gt; and friends stay home.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional encryption.&lt;/strong&gt; AES-256 with a password stored in your Keychain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restores are paranoid.&lt;/strong&gt; A backup is treated as untrusted: checksums are verified, package names are validated, and no file is overwritten without keeping a &lt;code&gt;.dudu-bak&lt;/code&gt; copy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Saved where you already are
&lt;/h2&gt;

&lt;p&gt;Pick one or more destinations, and each backup goes to all of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A local folder&lt;/li&gt;
&lt;li&gt;iCloud Drive&lt;/li&gt;
&lt;li&gt;Google Drive (or any rclone remote on Linux)&lt;/li&gt;
&lt;li&gt;Apple Notes, with a readable summary of your setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want it on autopilot? &lt;code&gt;dudu schedule on&lt;/code&gt; runs a backup every day.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But I already use chezmoi or mackup"
&lt;/h2&gt;

&lt;p&gt;They're great tools, and dudu doesn't try to replace everything they do. The difference is scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.chezmoi.io" rel="noopener noreferrer"&gt;chezmoi&lt;/a&gt;&lt;/strong&gt; is excellent for dotfiles, with per-machine templates and password manager integration. But it doesn't install packages or runtimes on its own. You write and maintain those scripts yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/lra/mackup" rel="noopener noreferrer"&gt;mackup&lt;/a&gt;&lt;/strong&gt; syncs app settings through a cloud folder. It doesn't reinstall packages or language versions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brewfile (&lt;code&gt;brew bundle&lt;/code&gt;)&lt;/strong&gt; reinstalls Homebrew packages, and dudu actually builds on it. But on its own it doesn't cover dotfiles, runtimes or your terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;dudu&lt;/th&gt;
&lt;th&gt;chezmoi&lt;/th&gt;
&lt;th&gt;mackup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dotfiles&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Packages&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Via scripts&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtimes (Node, Python...)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Via scripts&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminal settings&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secret masking&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Via password manager&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One-command backup and restore&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interface in Portuguese and Spanish&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;dudu's bet is simple: &lt;strong&gt;one flow for the whole setup.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for developers who don't think in English
&lt;/h2&gt;

&lt;p&gt;Here's something most CLI tools ignore: millions of developers don't use English as their first language.&lt;/p&gt;

&lt;p&gt;dudu speaks &lt;strong&gt;English, Portuguese and Spanish&lt;/strong&gt;, and picks the right one automatically from your system. No flags, no config. You just run it, and it talks to you in your language.&lt;/p&gt;

&lt;p&gt;This wasn't an afterthought. It was a design decision from day one, because a tool that feels foreign is a tool people stop using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pure bash, zero dependencies
&lt;/h2&gt;

&lt;p&gt;dudu is written in pure bash and runs on the bash 3.2 that ships with macOS. Nothing to install first, no runtime to manage. The test suite runs on macOS, Ubuntu, Fedora and Arch.&lt;/p&gt;

&lt;h2&gt;
  
  
  When dudu saves your day
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New laptop:&lt;/strong&gt; go from unboxing to coding without the ritual&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fresh install:&lt;/strong&gt; formatted your machine? Bring everything back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second machine:&lt;/strong&gt; keep your work and personal setups in sync&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distro hopping:&lt;/strong&gt; try a new Linux distro without losing your environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;p&gt;dudu currently runs on &lt;strong&gt;macOS and Linux&lt;/strong&gt;. Windows isn't supported yet.&lt;/p&gt;

&lt;p&gt;It's a young project, and I'd rather tell you that upfront than have you find out the hard way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Help me shape what comes next
&lt;/h2&gt;

&lt;p&gt;I'd love your input on two questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What do you &lt;strong&gt;always&lt;/strong&gt; have to reinstall or reconfigure on a new machine that dudu should capture?&lt;/li&gt;
&lt;li&gt;Which tool is missing from the list above? Each one is a single file, so new collectors are easy to add, and contributions are welcome.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Drop your answer in the comments. I read every one.&lt;/p&gt;

&lt;p&gt;And if dudu looks useful to you, a ⭐ on &lt;a href="https://github.com/fontnelle/dudu" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; goes a long way. My next goal is getting dudu into the official Homebrew repository, which requires a minimum number of stars, forks and watchers.&lt;/p&gt;

&lt;p&gt;Your next setup should be a command, not a chore.&lt;/p&gt;

</description>
      <category>backup</category>
      <category>opensource</category>
      <category>linux</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
