<?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: Jan van Dorth</title>
    <description>The latest articles on DEV Community by Jan van Dorth (@janvandorth).</description>
    <link>https://dev.to/janvandorth</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%2F3794459%2F6c8c7d19-c7bd-4f84-846c-9175e245efa2.png</url>
      <title>DEV Community: Jan van Dorth</title>
      <link>https://dev.to/janvandorth</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/janvandorth"/>
    <language>en</language>
    <item>
      <title>Testing Microservice Changes from Git Worktrees End to End Without the Terminal Tab Explosion</title>
      <dc:creator>Jan van Dorth</dc:creator>
      <pubDate>Sat, 28 Feb 2026 10:45:09 +0000</pubDate>
      <link>https://dev.to/janvandorth/testing-microservice-changes-from-git-worktrees-end-to-end-without-the-terminal-tab-explosion-e1f</link>
      <guid>https://dev.to/janvandorth/testing-microservice-changes-from-git-worktrees-end-to-end-without-the-terminal-tab-explosion-e1f</guid>
      <description>&lt;p&gt;TLDR: made a visual cli-tool called &lt;a href="https://www.npmjs.com/package/recomposable" rel="noopener noreferrer"&gt;Recomposable&lt;/a&gt; to tackle this issue.&lt;/p&gt;

&lt;p&gt;If you use Claude Code with git worktrees, you probably have multiple branches of the same repository checked out simultaneously. Claude works in one worktree, you review in another. This works well for single-service projects, but it breaks down when you run microservices.&lt;/p&gt;

&lt;p&gt;The problem: you need to verify that the changes Claude made to one service still work with the rest of your stack. This means rebuilding that one service from the worktree's code while keeping everything else on &lt;code&gt;main&lt;/code&gt;, and Docker Compose has no concept of worktrees, it only knows about files on disk, so you're on your own. I have solved this for myself with the cli-tool Recomposable, which I will discuss further down the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you have to do today
&lt;/h2&gt;

&lt;p&gt;Say Claude Code is working on your &lt;code&gt;auth-service&lt;/code&gt; in a worktree, and you want to test its changes against the rest of your stack. Here's the manual workflow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Find the worktree path.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude Code creates worktrees in &lt;code&gt;.claude/worktrees/&lt;/code&gt; with generated names, so you need to find it first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree list
&lt;span class="c"&gt;# /Users/you/project                   abc1234 [main]&lt;/span&gt;
&lt;span class="c"&gt;# /Users/you/project/.claude/worktrees/jan-abc123  def5678 [fix-oauth]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Build the service from the worktree.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need to combine the worktree path with the compose file path, specify the service, and build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; /Users/you/project/.claude/worktrees/jan-abc123/docker-compose.yml build auth-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Start it.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; /Users/you/project/.claude/worktrees/jan-abc123/docker-compose.yml up &lt;span class="nt"&gt;-d&lt;/span&gt; auth-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Verify.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open another tab, tail the logs, check the other services, maybe rebuild if it failed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Switch back.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you're done testing, repeat steps 2-3 but pointing back at the original compose file.&lt;/p&gt;

&lt;p&gt;Every step requires you to remember or paste the worktree path, and if you have multiple compose files you also need the correct file name. There's no overview of which services are running code from which branch - you just have to remember.&lt;/p&gt;

&lt;p&gt;You can script this with aliases or a Makefile target, but you still lack a way to see at a glance which service is running from which worktree, and every new worktree means updating your aliases.&lt;/p&gt;

&lt;h2&gt;
  
  
  What recomposable does instead
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/janvandorth/recomposable" rel="noopener noreferrer"&gt;recomposable&lt;/a&gt; is a Docker Compose TUI I built for development workflows, and version 1.1.4 adds worktree switching as a first-class feature.&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;t&lt;/code&gt; on any service, and a picker shows all available git worktrees. Select one with &lt;code&gt;j&lt;/code&gt;/&lt;code&gt;k&lt;/code&gt; and &lt;code&gt;Enter&lt;/code&gt;, and the service is stopped, rebuilt from the target worktree's compose file, and started. That's it.&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%2F3t5syt51syd71n301oh7.gif" 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%2F3t5syt51syd71n301oh7.gif" alt=" " width="1920" height="1111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When services run from different branches, a &lt;code&gt;WORKTREE&lt;/code&gt; column appears automatically with non-main branches highlighted in yellow, so you see at a glance which service runs from which branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SERVICE              STATUS    BUILT     PORTS          WORKTREE
auth-service         running   2m ago    5001           fix-oauth
api-gateway          running   1h ago    8080           main
web-app              running   3d ago    3000           main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No paths to remember, no compose file flags, no switching terminals to check which branch a container was built from.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;When you press &lt;code&gt;t&lt;/code&gt;, recomposable runs &lt;code&gt;git worktree list --porcelain&lt;/code&gt; from the compose file's directory to discover all worktrees, and the picker shows each worktree's branch name and path.&lt;/p&gt;

&lt;p&gt;On selection, it maps the compose file path to the equivalent path in the target worktree. If your compose file is at &lt;code&gt;infra/docker-compose.yml&lt;/code&gt; relative to the git root, it looks for the same relative path in the target worktree and shows an error if the file doesn't exist or the service isn't defined in the target compose file.&lt;/p&gt;

&lt;p&gt;The override is stored per service, and all subsequent operations — rebuild, restart, logs, exec, watch, dependency-aware cascade rebuild — automatically use the overridden compose file. Switching back is the same action: press &lt;code&gt;t&lt;/code&gt; and select the original worktree.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Claude Code workflow
&lt;/h2&gt;

&lt;p&gt;This is the workflow I built the feature for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start &lt;code&gt;recomposable&lt;/code&gt; in your project directory, with your full stack running on &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open Claude Code and tell it to work on &lt;code&gt;auth-service&lt;/code&gt; in a worktree.&lt;/li&gt;
&lt;li&gt;Claude makes its changes, and you want to verify them end-to-end.&lt;/li&gt;
&lt;li&gt;In recomposable, navigate to &lt;code&gt;auth-service&lt;/code&gt;, press &lt;code&gt;t&lt;/code&gt;, and select the worktree Claude is working in.&lt;/li&gt;
&lt;li&gt;The service rebuilds from Claude's branch while the rest of the stack stays on &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check logs, run requests, and verify — if something is wrong, check the logs right there in the TUI.&lt;/li&gt;
&lt;li&gt;When done, press &lt;code&gt;t&lt;/code&gt; again and switch back to &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No terminal tabs, no path juggling, no guessing which branch is running.&lt;/p&gt;

&lt;p&gt;This scales to any number of services. Claude working on three services across two worktrees? Switch all three, and the &lt;code&gt;WORKTREE&lt;/code&gt; column shows you exactly what's running where.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future work
&lt;/h2&gt;

&lt;p&gt;The worktree feature covers the core workflow, but there are gaps worth addressing for teams that use this pattern heavily:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-detect worktree changes.&lt;/strong&gt; Currently you manually press &lt;code&gt;t&lt;/code&gt; to switch, but recomposable could watch for new worktrees appearing (e.g., Claude Code just created one) and prompt you to switch the affected service, removing the "go check if Claude is done, then switch" polling loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worktree-aware cascading rebuilds.&lt;/strong&gt; The dependency-aware rebuild (&lt;code&gt;d&lt;/code&gt;) already restarts transitive dependents, but if &lt;code&gt;auth-service&lt;/code&gt; is switched to a worktree and &lt;code&gt;api-gateway&lt;/code&gt; depends on it, the cascade doesn't switch &lt;code&gt;api-gateway&lt;/code&gt; too. For tightly coupled services that should be tested from the same branch, a "cascade switch" would reduce manual steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diff preview before switching.&lt;/strong&gt; Before rebuilding from a worktree, showing a summary of what changed (files modified, services affected) would help you decide whether the switch is worth the rebuild time, especially when Claude has been working for a while and you're not sure what exactly changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Branch status indicators.&lt;/strong&gt; Showing whether a worktree's branch is ahead/behind &lt;code&gt;main&lt;/code&gt;, or has uncommitted changes, would help you decide which worktree to test — a branch that's 30 commits ahead is a different risk profile than one that changed a single config file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-service worktree switch.&lt;/strong&gt; A single action to switch all services from one compose file to the same worktree, because when Claude works on changes that span multiple services in the same repo, switching them one by one is unnecessary friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g recomposable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to a directory with a &lt;code&gt;docker-compose.yml&lt;/code&gt;, create a &lt;code&gt;recomposable.json&lt;/code&gt; pointing to your compose files, and run &lt;code&gt;recomposable&lt;/code&gt;. The worktree feature works out of the box with any git repository that has multiple worktrees.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/janvandorth/recomposable" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://www.npmjs.com/package/recomposable" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Every Docker Compose TUI I Could Find (And Why I Built My Own)</title>
      <dc:creator>Jan van Dorth</dc:creator>
      <pubDate>Thu, 26 Feb 2026 14:50:20 +0000</pubDate>
      <link>https://dev.to/janvandorth/every-docker-compose-tui-i-could-find-and-why-i-built-my-own-2oo0</link>
      <guid>https://dev.to/janvandorth/every-docker-compose-tui-i-could-find-and-why-i-built-my-own-2oo0</guid>
      <description>&lt;p&gt;If you run more than a couple of containers locally, you know the hassle. Countless terminal tabs, just to be able to rebuild your services and inspect the logs.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/janvandorth/recomposable" rel="noopener noreferrer"&gt;recomposable&lt;/a&gt; to fix this for my own workflow. &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%2Fr17d3xrk8maujpxmdkk2.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%2Fr17d3xrk8maujpxmdkk2.png" alt=" " width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before building it, I searched for existing tools to see if one would fit my needs. Below is a feature comparison of every Docker TUI I could find which I deemed relevant for my development workflow.&lt;/p&gt;

&lt;p&gt;Here's what I found:&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tools
&lt;/h2&gt;

&lt;p&gt;See the table below for a quick comparison. The table is followed by a short summary of which features each package has or doesn't have. The comparison is biased, as Recomposable ticks almost all the boxes, but that's because i've made it to solve my own specific docker development hassles.&lt;/p&gt;

&lt;h2&gt;
  
  
  How They Compare
&lt;/h2&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;lazydocker&lt;/th&gt;
&lt;th&gt;DockTUI&lt;/th&gt;
&lt;th&gt;oxker&lt;/th&gt;
&lt;th&gt;Cruise&lt;/th&gt;
&lt;th&gt;DockMate&lt;/th&gt;
&lt;th&gt;DockedUp&lt;/th&gt;
&lt;th&gt;Pocker&lt;/th&gt;
&lt;th&gt;dry&lt;/th&gt;
&lt;th&gt;ctop&lt;/th&gt;
&lt;th&gt;dcv&lt;/th&gt;
&lt;th&gt;recomposable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compose-first&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rebuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;No-cache rebuild toggle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dep-aware rebuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compose Watch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Log pattern scanning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Log search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Clipboard&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Keyword filter&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (&lt;code&gt;/&lt;/code&gt;, &lt;code&gt;n&lt;/code&gt;/&lt;code&gt;N&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CPU/Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ASCII graphs&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (color thresholds)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port display&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vim keybindings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Full (&lt;code&gt;j&lt;/code&gt;/&lt;code&gt;k&lt;/code&gt;/&lt;code&gt;gg&lt;/code&gt;/&lt;code&gt;G&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container exec&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (in-TUI)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Image/volume mgmt&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Images&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zero dependencies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single binary&lt;/td&gt;
&lt;td&gt;Docker container&lt;/td&gt;
&lt;td&gt;Single binary&lt;/td&gt;
&lt;td&gt;Single binary&lt;/td&gt;
&lt;td&gt;Single binary&lt;/td&gt;
&lt;td&gt;pip&lt;/td&gt;
&lt;td&gt;pipx&lt;/td&gt;
&lt;td&gt;Single binary&lt;/td&gt;
&lt;td&gt;Single binary&lt;/td&gt;
&lt;td&gt;Single binary&lt;/td&gt;
&lt;td&gt;Node.js (already on your machine)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  lazydocker
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/jesseduffield/lazydocker" rel="noopener noreferrer"&gt;github.com/jesseduffield/lazydocker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;40k+ GitHub stars. Written in Go. It's a general-purpose Docker manager: containers, images, volumes, networks. Has live logs, ASCII metric graphs, exec into containers, bulk commands. Docker Compose is supported but it's not the focus.&lt;/p&gt;

&lt;h3&gt;
  
  
  DockTUI
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/dialmaster/DockTUI" rel="noopener noreferrer"&gt;github.com/dialmaster/DockTUI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Actually built for Docker Compose specifically. Real-time CPU/memory dashboard, grouped by compose stacks. Interesting choice: it runs as a Docker container itself. Clipboard integration for copying log snippets. The downside is that it can't monitor remote daemons.&lt;/p&gt;

&lt;h3&gt;
  
  
  oxker
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/mrjackwills/oxker" rel="noopener noreferrer"&gt;github.com/mrjackwills/oxker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rust + ratatui. Clean single-screen layout showing containers, logs, CPU, memory, and ports all at once. Customizable keymaps and color schemes. Sortable columns. About 900 stars. Doesn't try to do too much, but does it quite good.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cruise
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/NucleoFusion/cruise" rel="noopener noreferrer"&gt;github.com/NucleoFusion/cruise&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go + Bubbletea. Containers, images, volumes, networks, logs, from one screen. Looks good too.&lt;/p&gt;

&lt;h3&gt;
  
  
  DockMate
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/shubh-io/DockMate" rel="noopener noreferrer"&gt;github.com/shubh-io/DockMate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Calls itself "htop for Docker". Go-based, zero-config. Single-keystroke actions: &lt;code&gt;s&lt;/code&gt; to start, &lt;code&gt;x&lt;/code&gt; to stop, &lt;code&gt;r&lt;/code&gt; to restart, &lt;code&gt;d&lt;/code&gt; to remove. Also supports Podman. Has compose lifecycle management.&lt;/p&gt;

&lt;h3&gt;
  
  
  DockedUp
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/anilrajrimal1/dockedup" rel="noopener noreferrer"&gt;github.com/anilrajrimal1/dockedup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Focused on monitoring. Auto-groups containers by docker-compose project. Color-coded status, health, CPU, and memory. Hotkeys for logs, restarts, shell access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pocker
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/pommee/Pocker" rel="noopener noreferrer"&gt;github.com/pommee/Pocker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python + Textual. View containers and images, manage status, browse logs/env/stats. Has log keyword filtering. Install via &lt;code&gt;pipx&lt;/code&gt;. If your stack is Python-heavy you might prefer this.&lt;/p&gt;

&lt;h3&gt;
  
  
  dry
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/moncho/dry" rel="noopener noreferrer"&gt;github.com/moncho/dry&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the older tools in this space. Go-based. Covers Docker and Docker Swarm. Gives you inspect, history, logs, and the usual start/stop/remove. More of a Docker CLI replacement with a visual layer on top than a monitoring dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  ctop
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/bcicen/ctop" rel="noopener noreferrer"&gt;github.com/bcicen/ctop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Does one thing: real-time container resource metrics. Think &lt;code&gt;top&lt;/code&gt; but for containers. CPU, memory, network, I/O. No compose awareness, log viewing nor container management. Good for when you just need a quick glance at resource usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  dcv
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/tokuhirom/dcv" rel="noopener noreferrer"&gt;github.com/tokuhirom/dcv&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Minimal TUI viewer for docker-compose. Rust-based. Lightweight by design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Recomposable Fits
&lt;/h2&gt;

&lt;p&gt;Most of these tools are general Docker managers that happen to support compose. They're built for people who manage Docker infrastructure.&lt;/p&gt;

&lt;p&gt;Recomposable is built for the developer workflow: you have one or more &lt;code&gt;docker-compose.yml&lt;/code&gt; files, and you spend your day rebuilding services, restarting them and checking logs for errors. You occasionally look for port numbers and want to make sure your services don't take up too much CPU and memory. If this sounds recognizable, Recomposable will help you out.&lt;/p&gt;

&lt;p&gt;Things it does that no package in the list does:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rebuild with no-cache toggle.&lt;/strong&gt; Press &lt;code&gt;b&lt;/code&gt; to rebuild. Press &lt;code&gt;n&lt;/code&gt; to toggle &lt;code&gt;--no-cache --force-recreate&lt;/code&gt; on and off. Other tools only support restart. When your Dockerfile changes or a dependency breaks, restart doesn't help you. You need a clean rebuild.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency-aware rebuild.&lt;/strong&gt; Press &lt;code&gt;d&lt;/code&gt; to rebuild a service and automatically restart everything that depends on it, in topological order. No more manually restarting five services because you changed a shared library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Compose Watch integration.&lt;/strong&gt; Press &lt;code&gt;w&lt;/code&gt; to toggle &lt;code&gt;docker compose watch&lt;/code&gt; per service. Watch output streams to the bottom log panel. The service list shows a cyan &lt;code&gt;W&lt;/code&gt; indicator next to watched services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log pattern scanning.&lt;/strong&gt; It continuously scans logs across all your services and counts matches for configurable patterns (warnings, errors, whatever you care about). You see the counts right in the service list without opening any log view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full log view with search.&lt;/strong&gt; Scrollable, full-screen, with &lt;code&gt;/&lt;/code&gt; to search, &lt;code&gt;n&lt;/code&gt;/&lt;code&gt;N&lt;/code&gt; to jump between matches, and live auto-scroll when you're at the bottom.&lt;br&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%2F45qv7jefjb3ve16fcz13.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%2F45qv7jefjb3ve16fcz13.png" alt=" " width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In-TUI container exec.&lt;/strong&gt; Press &lt;code&gt;e&lt;/code&gt; to open an inline exec panel in the bottom of the list view, or &lt;code&gt;x&lt;/code&gt; for a full-screen command runner. &lt;code&gt;cd&lt;/code&gt; works and the working directory is tracked across commands. Type commands, see output, navigate history with Up/Down. No need to leave the TUI or open another terminal.&lt;br&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%2F9x5ankrqdhuyyhtiw4me.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%2F9x5ankrqdhuyyhtiw4me.png" alt=" " width="800" height="628"&gt;&lt;/a&gt;&lt;br&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%2Fdit0vqvigmd5tn25tp40.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%2Fdit0vqvigmd5tn25tp40.png" alt=" " width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What it for now doesn't do: manage images, volumes, networks, Swarm and Podman support. You can find the current issues in the repo. If you want to contribute by building this or any other feature, just submit a PR! Thanks in advance :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; recomposable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;cd&lt;/code&gt; into a directory with a &lt;code&gt;docker-compose.yml&lt;/code&gt; and run &lt;code&gt;recomposable&lt;/code&gt;. Done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/janvandorth/recomposable" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://www.npmjs.com/package/recomposable" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>showdev</category>
      <category>tooling</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
