<?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: Francesco Meli</title>
    <description>The latest articles on DEV Community by Francesco Meli (@pinkynrg).</description>
    <link>https://dev.to/pinkynrg</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%2F3422630%2Fb45e4dbd-c6b0-403d-be1c-9ccea4615e58.jpeg</url>
      <title>DEV Community: Francesco Meli</title>
      <link>https://dev.to/pinkynrg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pinkynrg"/>
    <language>en</language>
    <item>
      <title>crew: run just the services you're working on - wired to the rest</title>
      <dc:creator>Francesco Meli</dc:creator>
      <pubDate>Sun, 09 Aug 2026 09:42:43 +0000</pubDate>
      <link>https://dev.to/pinkynrg/crew-run-just-the-services-youre-working-on-wired-to-the-rest-1i51</link>
      <guid>https://dev.to/pinkynrg/crew-run-just-the-services-youre-working-on-wired-to-the-rest-1i51</guid>
      <description>&lt;p&gt;You have fifteen services. Today you're touching two.&lt;/p&gt;

&lt;p&gt;If your stack is more than a couple of services, you know this moment. You want to run &lt;code&gt;web&lt;/code&gt; and &lt;code&gt;api&lt;/code&gt; locally to work on a feature - but &lt;code&gt;api&lt;/code&gt; talks to &lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;billing&lt;/code&gt;, a queue, a search cluster, and three other internal services. So what are your options?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Run the whole thing in Docker Compose.&lt;/strong&gt; Now you're maintaining a &lt;code&gt;docker-compose.yml&lt;/code&gt; that mirrors production (and drifts from it), booting thirteen containers you don't care about, feeding a daemon and disk, and waiting on rebuilds - all to change two services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Point your two local services at staging by hand.&lt;/strong&gt; Edit env files, swap URLs to &lt;code&gt;localhost&lt;/code&gt; for the one peer you're running, remember to change them back. Every time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are chores. I wanted a third option, so I built &lt;strong&gt;&lt;a href="https://github.com/pinkynrg/crew" rel="noopener noreferrer"&gt;crew&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every service is a switch
&lt;/h2&gt;

&lt;p&gt;The whole idea fits in one line: &lt;strong&gt;on = local, off = remote.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flip a service &lt;strong&gt;on&lt;/strong&gt; → crew runs it natively and rewrites every peer that talks to it to point at your &lt;code&gt;localhost&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Leave it &lt;strong&gt;off&lt;/strong&gt; → it stays on its real deployed environment (qa / staging / prod), and its callers keep hitting the real host.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The "slice" you run locally is just &lt;em&gt;which switches are on&lt;/em&gt; - one service, or the whole stack, or anything in between. And flipping a switch flips the wiring &lt;strong&gt;for you&lt;/strong&gt;, read straight from the &lt;code&gt;.env&lt;/code&gt; files you already ship.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;crew start env=staging     web   [x] on  → http://localhost:3000
                           api   [x] on  → http://localhost:4000   (web now calls this)
                           auth  [ ] off → https://auth.staging.acme.dev
                           …     [ ] off → deployed staging
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's &lt;code&gt;crew start&lt;/code&gt; in practice - pick a connected slice from the dependency graph, run it, watch the labelled logs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ivhcio5wwj8k5tnmncj.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ivhcio5wwj8k5tnmncj.gif" alt="crew start" width="720" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How the wiring works
&lt;/h2&gt;

&lt;p&gt;crew doesn't ask you to declare a topology. It &lt;strong&gt;derives the dependency graph from your env files&lt;/strong&gt;: each project gets a &lt;code&gt;match&lt;/code&gt; (the host(s) it's deployed under, per env) and a &lt;code&gt;local&lt;/code&gt; (its localhost URL). When a URL in one project's env matches another project's &lt;code&gt;match&lt;/code&gt; host, that's an edge.&lt;/p&gt;

&lt;p&gt;At &lt;code&gt;crew start&lt;/code&gt;, for each service you switched &lt;strong&gt;on&lt;/strong&gt;, crew reads its env file, rewrites the URLs of any &lt;em&gt;other&lt;/em&gt; on-services to their &lt;code&gt;local&lt;/code&gt; value, writes the result to a throwaway file, and hands that path to your start command via &lt;code&gt;{envfile}&lt;/code&gt;. Services you left off keep their real URLs. Nothing in your repo is touched - the wired copy lives in &lt;code&gt;~/.config/crew/tmp/&lt;/code&gt; and is deleted on teardown.&lt;/p&gt;

&lt;p&gt;Because the env each service resolves to is derived from the graph (not a static setting), the same shared config serves multiple teams correctly - the frontend team and the SDK team each get the right remote env for the services they didn't run.&lt;/p&gt;

&lt;h2&gt;
  
  
  You don't hand-write the config
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;crew config&lt;/code&gt; is a visual editor: pick a project's folder and crew auto-fills the mechanical parts it can read from your &lt;code&gt;package.json&lt;/code&gt;, lockfiles and &lt;code&gt;.envs&lt;/code&gt; - type, runner, start command, env-file path. You fill in the URLs (local port + deployed host per env). Out comes one readable, committable &lt;code&gt;config.json&lt;/code&gt; with no secrets in 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn8q3trxykc7cs4wdd5l4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn8q3trxykc7cs4wdd5l4.gif" alt="crew config" width="720" height="518"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"web"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"web"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"frontend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dotenv -e {envfile} -- npm run dev"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".envs/{env}.env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"match"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"staging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"web.staging.acme.dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"web.acme.dev"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"local"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvicorn app:main --reload --env-file {envfile}"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".envs/{env}.env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"match"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"staging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api.staging.acme.dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api.acme.dev"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"local"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:4000"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The same slice, three ways
&lt;/h2&gt;

&lt;p&gt;The picked set is remembered, so the other two commands open exactly what you started:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it opens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;crew start env=staging&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the dev servers (streamed, per-project-colored logs; Ctrl-C tears the whole group down)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;crew workspace&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;one multi-root VS Code window with every picked repo side by side&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;crew claude&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;one Claude Code session over the set, history kept per group of repos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why not just Docker Compose?
&lt;/h2&gt;

&lt;p&gt;crew runs your slice natively and borrows the rest from their deployed envs - a different category from the usual tools:&lt;/p&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;&lt;strong&gt;crew&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;Compose&lt;/th&gt;
&lt;th&gt;Tilt&lt;/th&gt;
&lt;th&gt;mirrord&lt;/th&gt;
&lt;th&gt;overmind&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Runs your slice natively&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&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;Rest of stack = real remote&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&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;Wiring from&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.env&lt;/code&gt; files&lt;/td&gt;
&lt;td&gt;compose file&lt;/td&gt;
&lt;td&gt;k8s manifests&lt;/td&gt;
&lt;td&gt;cluster intercept&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infra required&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;daemon&lt;/td&gt;
&lt;td&gt;k8s&lt;/td&gt;
&lt;td&gt;k8s&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;crew sits between plain process-runners (overmind, foreman, mprocs) and remote-wiring tools (mirrord, Telepresence): the native-slice-plus-real-remote of the latter, without the cluster, daemon, or containers - just URL swaps in the env files you already have.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When Docker is the right call:&lt;/strong&gt; you need full-stack isolation, byte-for-byte prod/CI parity, or your services can't run natively. crew doesn't replace that. It replaces the daily loop of flipping a couple of services on and letting everything else stay remote.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You need shared remote environments to borrow from.&lt;/strong&gt; If you don't have a staging/qa the "off" services can run on, a full-stack tool fits better.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;crew doesn't proxy.&lt;/strong&gt; If staging is down, your off-services are unreachable - same as calling staging directly. Turn them on to run locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;POSIX only&lt;/strong&gt; (macOS + Linux) - teardown relies on process groups so reparented dev-server children actually die.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No task graph, no ordering, no caching.&lt;/strong&gt; crew fans out one task at a time; that's make/turbo/nx territory, on purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Zero dependencies, by design
&lt;/h2&gt;

&lt;p&gt;crew is one file of Node built-ins - no runtime dependencies, no build step, no bundler. The source &lt;em&gt;is&lt;/em&gt; what runs, and its own parallel process runner handles the fan-out and teardown. So it installs instantly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @pinkynrg/crew          &lt;span class="c"&gt;# or: npm i -g @pinkynrg/crew&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://pinkynrg.github.io/crew/" rel="noopener noreferrer"&gt;site&lt;/a&gt; has a live version of that on/off switchboard: flip services on and off and watch the URLs and wiring rewire as you go. Source, docs, and the full config reference are on &lt;a href="https://github.com/pinkynrg/crew" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I built crew for my own stack. If you've solved the run-a-slice-locally problem a different way, I'm curious which trade-offs you landed on.&lt;/p&gt;

</description>
      <category>devtools</category>
      <category>cli</category>
      <category>microservices</category>
      <category>node</category>
    </item>
    <item>
      <title>PR Reviews: The Silent Team Killer? Let's Talk About It 🔍</title>
      <dc:creator>Francesco Meli</dc:creator>
      <pubDate>Fri, 08 Aug 2025 21:00:12 +0000</pubDate>
      <link>https://dev.to/pinkynrg/pr-reviews-the-silent-team-killer-lets-talk-about-it-kon</link>
      <guid>https://dev.to/pinkynrg/pr-reviews-the-silent-team-killer-lets-talk-about-it-kon</guid>
      <description>&lt;p&gt;Hey dev community! 👋&lt;/p&gt;

&lt;p&gt;I've been thinking about something that's been bugging me (and probably you, too): &lt;strong&gt;PR reviews&lt;/strong&gt;. Not the technical part, I'm referring to the human aspect.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Daily Drama We All Know
&lt;/h2&gt;

&lt;p&gt;You know the drill:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PRs sitting for days while everyone assumes "someone else will review it"&lt;/li&gt;
&lt;li&gt;@channel's messages flooding Slack: "Can someone please review my urgent PR?"&lt;/li&gt;
&lt;li&gt;That one teammate who cranks out massive 500 line PRs that nobody wants to touch&lt;/li&gt;
&lt;li&gt;The guilt when you realize you've been the bottleneck on three different PRs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sound familiar? 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experiment: A Different Approach
&lt;/h2&gt;

&lt;p&gt;Instead of more pings and notifications, I built a simple bot that sends one daily summary to our team's Slack channel every morning. We split our week into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Monday, Wednesday, Friday:&lt;/strong&gt; Async PR reviews - everyone finds time to review on their own schedule&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tuesday, Thursday:&lt;/strong&gt; Sync PR reviews - we have a 1-hour meeting before lunch where PR owners demo their changes live, then a randomly assigned presenter shares their screen to walk through the code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The daily message looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PR Updates for our team
[repo-name] Feature: User authentication
Reviewable | Async | Author: @john | Presenter: @paul | Updated: 2025-08-05 | Files: 12

[repo-name] Fix: Critical bug in payment flow  
Ready to merge | Sync | Author: @sarah | Presenter: @mike | Files: 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what each part means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Async vs Sync:&lt;/strong&gt; The PR owner decides whether to demo changes to everyone (sync) or let people review individually (async)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Random Presenter:&lt;/strong&gt; For sync reviews, someone is randomly assigned to actively examine the code and ask questions - this ensures at least one person is deeply engaged with each PR&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PR States:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Reviewable&lt;/em&gt; = No conflicts, ready for team feedback&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Ready to merge&lt;/em&gt; = Has enough approvals, feedback for the owner&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Conflicting&lt;/em&gt; = Needs attention before review can happen&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Mergeable with conflicts&lt;/em&gt; = Approved but conflicts appeared after approval (someone else merged something)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;File Counts:&lt;/strong&gt; Shows total files changed, but separates out "noise" like tests and snapshots (configurable) so teams get a real sense of the change scope&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened Surprised Me
&lt;/h2&gt;

&lt;p&gt;Instead of faster reviews, something more interesting happened: we developed a ritual.&lt;/p&gt;

&lt;p&gt;The team started naturally checking this message every morning with coffee. &lt;strong&gt;People began budgeting&lt;/strong&gt; time for reviews instead of treating them as interruptions. Large PRs became less common because the daily visibility made everyone conscious of their PR sizes.&lt;/p&gt;

&lt;p&gt;It wasn't about speed; it was about sustainable habits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Questions I'm Wrestling With
&lt;/h2&gt;

&lt;p&gt;This got me thinking about PR reviews differently:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the real problem coordination, or something deeper?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are we treating symptoms (slow reviews) instead of causes (unclear priorities, poor slicing)?&lt;/li&gt;
&lt;li&gt;Do teams need better tools, or better practices?&lt;/li&gt;
&lt;li&gt;Is "faster" actually better, or do we need "more sustainable"?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What makes teams want to do reviews?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is it social accountability? Clear expectations? Reducing cognitive load?&lt;/li&gt;
&lt;li&gt;How do you balance thoroughness with timeliness?&lt;/li&gt;
&lt;li&gt;Does team culture matter more than tooling?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Help Me Understand Your World
&lt;/h2&gt;

&lt;p&gt;I'm curious about your team's experience:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🤔 Questions for you:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What's your biggest PR review frustration?&lt;/strong&gt; (Too slow? Too shallow? Wrong people reviewing?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How does your team currently coordinate reviews?&lt;/strong&gt; (GitHub assignments? Slack chaos? Formal rotation?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What would make you excited to review code daily?&lt;/strong&gt; (Better tooling? Different process? Team structure?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Have you found any approaches that work?&lt;/strong&gt; (Tools, practices, cultural changes?)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;I'm wondering if there's space for tools that focus on team habits rather than individual productivity. Something that helps teams develop sustainable review practices instead of just automating the mechanics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do you think?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this a real problem worth solving?&lt;/li&gt;
&lt;li&gt;Are there existing solutions that work well for your team?&lt;/li&gt;
&lt;li&gt;Would you pay for something that helped build better review habits vs. just faster reviews?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop your thoughts below! Curious to hear how other teams handle this challenge.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PS: If you've built or used tools that address PR review coordination, I'd love to hear about them. Always looking to learn from what's working (or not working) out there.&lt;/em&gt;&lt;/p&gt;

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