<?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>Forem: Nawa Manusitthipol</title>
    <description>The latest articles on Forem by Nawa Manusitthipol (@nawaman).</description>
    <link>https://forem.com/nawaman</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%2F2335852%2Ffbf132af-702e-4776-bbef-067c281cef02.png</url>
      <title>Forem: Nawa Manusitthipol</title>
      <link>https://forem.com/nawaman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nawaman"/>
    <language>en</language>
    <item>
      <title>Introducing CodingBooth: Reproducible Dev Environments, One Command Away</title>
      <dc:creator>Nawa Manusitthipol</dc:creator>
      <pubDate>Thu, 14 May 2026 14:03:44 +0000</pubDate>
      <link>https://forem.com/nawaman/introducing-codingbooth-reproducible-dev-environments-one-command-away-1jo2</link>
      <guid>https://forem.com/nawaman/introducing-codingbooth-reproducible-dev-environments-one-command-away-1jo2</guid>
      <description>&lt;p&gt;Production is containerized. CI is containerized. The dev loop — where we actually spend our hours — usually isn't. &lt;a href="https://codingbooth.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;CodingBooth&lt;/strong&gt;&lt;/a&gt; is the missing piece.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three pains
&lt;/h2&gt;

&lt;p&gt;If you hop between projects, you've probably collected all three:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Project residue.&lt;/strong&gt; Every project installs &lt;em&gt;something&lt;/em&gt; — a JDK, a Go toolchain, a DB client, an SDK. After a few months the host is a graveyard of half-configured runtimes, and two unrelated projects end up fighting over a broken global.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legacy projects punish you.&lt;/strong&gt; The bigger and older the project, the harder it is to set up &lt;em&gt;the same way&lt;/em&gt; as the rest of the team. The onboarding doc is stale, the setup script worked on someone's 2019 laptop, and the "just works" build tool version isn't published anywhere obvious.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-assisted drift.&lt;/strong&gt; Coding assistants happily suggest &lt;code&gt;brew install this&lt;/code&gt; or &lt;code&gt;go install that@latest&lt;/code&gt; while solving something small. Unless someone is watching closely, those land on your host permanently. A year of pair-programming with an assistant later, the environment has mutated in ways nobody documented.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All three add up to the same thing: development becomes &lt;strong&gt;less repeatable&lt;/strong&gt; — and the breakage is subtle enough that it doesn't surface until someone else tries to run your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter CodingBooth
&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;booth&lt;/em&gt; is an isolated, reproducible dev environment, declared in the repo, brought up with a single command, and torn down without residue.&lt;/p&gt;

&lt;p&gt;The model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drop a &lt;code&gt;.booth/&lt;/code&gt; folder into your project. Declare the environment there (a &lt;code&gt;Boothfile&lt;/code&gt;, or a plain &lt;code&gt;Dockerfile&lt;/code&gt; if you'd rather).&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;./booth&lt;/code&gt;. A container starts with your host UID/GID mapped through, your project mounted in, and your chosen front-end open.&lt;/li&gt;
&lt;li&gt;Edit, build, test inside the booth. Files you create are owned by &lt;strong&gt;you&lt;/strong&gt; on the host — no &lt;code&gt;chown&lt;/code&gt; dance, no root-owned artifacts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Installing CodingBooth itself is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://codingbooth.io/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same booth for you and your teammate. Same image, same tools, same versions. Host stays clean.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not just a terminal
&lt;/h2&gt;

&lt;p&gt;The thing that surprises people first time they see this: they assume "booth = browser terminal." That's one variant. There are several, and they all share the same underlying environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;base&lt;/strong&gt; / &lt;strong&gt;terminal&lt;/strong&gt; — minimal shell, in-browser or in your host terminal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;notebook&lt;/strong&gt; — Jupyter Lab with multi-language kernels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;codeserver&lt;/strong&gt; — full browser-based VS Code, extensions and all&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;desktop-xfce&lt;/strong&gt; / &lt;strong&gt;desktop-kde&lt;/strong&gt; — a complete Linux desktop in your browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open today's project in browser VS Code, re-open tomorrow as a notebook when you want to plot something, switch to a full desktop when you need a GUI tool — same toolchain underneath the whole time.&lt;/p&gt;

&lt;h2&gt;
  
  
  This blog runs in a booth
&lt;/h2&gt;

&lt;p&gt;The entire &lt;code&gt;.booth/Boothfile&lt;/code&gt; for this Svelte + Firebase blog is two lines:&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="c"&gt;# .booth/Boothfile&lt;/span&gt;
&lt;span class="c"&gt;# syntax=codingbooth/boothfile:1&lt;/span&gt;
&lt;span class="c"&gt;# Configured by: booth config --no-tui --overwrite --variant codeserver --port 13579 --expose 5173 --select firebase+credential/claude-code+auto-accept+credential+settings-cache&lt;/span&gt;

setup claude-code
setup firebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Two &lt;code&gt;setup&lt;/code&gt; lines and the whole dev environment is declared. Each line maps to a curated install script — no &lt;code&gt;FROM&lt;/code&gt; wrangling, no &lt;code&gt;ARG&lt;/code&gt; ceremony. The &lt;code&gt;# Configured by:&lt;/code&gt; comment is the exact &lt;code&gt;booth config&lt;/code&gt; invocation that produced the file, so anyone can regenerate it from scratch.&lt;/p&gt;

&lt;p&gt;Runtime concerns (variant, port mappings, credential mounts) live in a small &lt;code&gt;config.toml&lt;/code&gt; next to it.&lt;/p&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;booth example list
booth example try snake-zig my-snake
&lt;span class="nb"&gt;cd &lt;/span&gt;my-snake
booth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The snake example builds with &lt;strong&gt;Zig&lt;/strong&gt; — a toolchain you almost certainly don't have on your host. Inside the booth you edit, compile, and the resulting binary lands on the host side ready to run. Nothing installed. Nothing to clean up. That's the whole pitch in miniature.&lt;/p&gt;

&lt;h2&gt;
  
  
  More
&lt;/h2&gt;

&lt;p&gt;There's a longer write-up — the Config TUI (130+ templates), who benefits most, more on each pain — over on the full post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website&lt;/strong&gt;: &lt;a href="https://codingbooth.io/" rel="noopener noreferrer"&gt;codingbooth.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/NawaMan/CodingBooth" rel="noopener noreferrer"&gt;github.com/NawaMan/CodingBooth&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blog&lt;/strong&gt;: &lt;a href="https://nawaman.net/blog/2026-05-14#CodingBooth" rel="noopener noreferrer"&gt;nawaman.net/blog/2026-05-14#CodingBooth&lt;/a&gt; (same with this)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A booth per project. A clean host. A repo that brings its own environment.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
