<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Amith GC]]></title><description><![CDATA[Amith GC]]></description><link>https://amithgc.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 07 Nov 2026 09:52:40 GMT</lastBuildDate><atom:link href="https://amithgc.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Five terminals, four cd's, and which one was waiting? Why I built Quarters]]></title><description><![CDATA[If you use a terminal coding agent on more than one project, you probably know my old routine. A terminal window per project. cd into each one. Start…]]></description><link>https://amithgc.hashnode.dev/five-terminals-four-cd-s-and-which-one-was-waiting-why-i-built-quarters</link><guid isPermaLink="true">https://amithgc.hashnode.dev/five-terminals-four-cd-s-and-which-one-was-waiting-why-i-built-quarters</guid><category><![CDATA[AI]]></category><category><![CDATA[Open source software]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Amith GC]]></dc:creator><pubDate>Fri, 06 Nov 2026 00:48:39 GMT</pubDate><content:encoded><![CDATA[<p>If you use a terminal coding agent on more than one project, you probably know my old routine. A terminal window per project. <code>cd</code> into each one. Start <code>claude</code> (or <code>codex</code>, or <code>gemini</code>). Start the backend. Start the frontend. Then spend the next hour alt-tabbing to find out which agent finished and has been sitting there waiting for me.</p>
<p>I wanted something deliberately small: not another AI, not another IDE, just a home for the agents I already use. So I built <strong>Quarters</strong>, a free, open-source (MIT) Mac app where every project gets a room. This post is about the problem, the design choices, and a few things I learned building it in Go.</p>
<p>Repo: <a href="https://github.com/amithgc/quarters">https://github.com/amithgc/quarters</a></p>
<h2>The problem</h2>
<p>I work on several repos at once, and each one usually has an agent running plus a dev server or two. The agents are good at working on their own for a while, but then they stop and wait for me. With five terminal windows open, the hard part was never the typing. It was knowing which window needed me.</p>
<h2>What Quarters does</h2>
<p><strong>A room per project.</strong> Switch projects in a click (⌘P). Each room keeps its agent, its terminals and its git status.</p>
<p><strong>Who's waiting.</strong> When an agent is waiting for you, the project shows “◐ your turn”, and ⌘J jumps to the next one that needs you. There's a Dock badge and notifications too.</p>
<p><strong>Automations.</strong> Start the whole dev stack for a project with one action instead of three terminals.</p>
<p>There’s also a prompt queue and saved prompts, conversation search and resume, git worktrees, and a command palette (⇧⌘P).</p>
<h2>Bring your own agent</h2>
<p>Quarters has no AI of its own, no accounts, no cloud and no telemetry. It runs the agent you already have installed and signed in: Claude Code, Codex, Gemini CLI, Antigravity, OpenCode, GitHub Copilot CLI, Devin or Aider, chosen per project.</p>
<p>Claude Code gets the deepest integration, because it keeps local logs I can read: session stats, plan usage, per-project token usage with a 14-day chart, and past conversations. The other agents get the tabs, alerts, automations, worktrees, git and remote access.</p>
<h2>Working from my phone</h2>
<p>The feature I use most is remote access. I start something at my desk and approve it from the sofa. It's off until you start it, it listens only on the Mac, and you reach it through a tunnel you choose (Cloudflare, Tailscale) or your home Wi-Fi. Devices are paired with passkeys from the Mac, and each device can be full, type-only or watch-only. There are rate limits and growing lockouts.</p>
<p>I've tried to design it to be safe to expose, and the design and its limits are written up in <a href="https://github.com/amithgc/quarters/blob/main/SECURITY.md">SECURITY.md</a>. I'd genuinely welcome critique of it.</p>
<h2>Building it in Go</h2>
<p>Quarters is Go with Wails (Go plus the system WebView, not Electron) and xterm.js for the terminals. One event stream feeds both the Mac window and any browsers connected remotely.</p>
<p>The thing I spent the most time on was idle CPU. Early versions sat around 20% of one core. Now it's about 2% of one CPU core when idle, measured on my Mac with 14 projects. Most of the win came from two rules: only run git when something may actually have changed, and run no timers while the window is hidden.</p>
<h2>What it doesn't do</h2>
<p>It isn't a general-purpose terminal replacement, and it has no AI of its own. It's pre-1.0, so expect rough edges. Windows works as a browser client; the server runs on a Mac, Linux or WSL.</p>
<h2>Try it</h2>
<pre><code class="language-sh">brew install --cask amithgc/tap/quarters
</code></pre>
<p>There's also a headless Linux server you use from a browser (<code>brew install amithgc/tap/quarters-server</code>), or you can build from source. Everything is at <a href="https://github.com/amithgc/quarters">https://github.com/amithgc/quarters</a> and <a href="https://quarters.amithgc.com/">https://quarters.amithgc.com/</a>.</p>
<p>If it's useful, a star on GitHub helps other developers find it, and issues with what you'd like to see are very welcome. I'd also love to hear how you juggle multiple agents today.</p>
<p>Quarters is an independent project and isn't made by or affiliated with Anthropic, OpenAI, Google, GitHub or any of the agent makers.</p>
]]></content:encoded></item><item><title><![CDATA[How I built Quarters: a Go workspace for parallel CLI coding agents with passkey phone access]]></title><description><![CDATA[When you run one coding agent in a terminal tab, any terminal emulator works. When you run Claude Code, Codex, Gemini CLI, or Aider across ten repositories…]]></description><link>https://amithgc.hashnode.dev/how-i-built-quarters-a-go-workspace-for-parallel-cli-coding-agents-with-passkey-phone-access</link><guid isPermaLink="true">https://amithgc.hashnode.dev/how-i-built-quarters-a-go-workspace-for-parallel-cli-coding-agents-with-passkey-phone-access</guid><dc:creator><![CDATA[Amith GC]]></dc:creator><pubDate>Tue, 03 Nov 2026 18:46:59 GMT</pubDate><content:encoded><![CDATA[<p>When you run one coding agent in a terminal tab, any terminal emulator works. When you run Claude Code, Codex, Gemini CLI, or Aider across ten repositories at once—each with its own dev server, database port, and permission prompts—standard terminal tabs start to break down.</p>
<p>You end up cycling through tabs to find out which agent stopped five minutes ago to ask a question, or wondering how to undo a prompt that touched twelve files without wrecking your git index, or wishing you could approve a migration from the sofa on your phone.</p>
<p>I built <strong><a href="https://github.com/amithgc/quarters?utm_source=hashnode&amp;utm_medium=blog&amp;utm_campaign=e54_quarters_arch">Quarters</a></strong> (<a href="https://quarters.amithgc.com?utm_source=hashnode&amp;utm_medium=blog&amp;utm_campaign=e54_quarters_arch">quarters.amithgc.com</a>) to solve that workflow for myself. It is a native macOS app (plus a headless Linux server; Windows is supported as a browser client only) and is <strong>free and open source (MIT)</strong>.</p>
<blockquote>
<p><em>Independence note: Quarters is an independent open-source project. It is not made by, affiliated with, or endorsed by Anthropic, OpenAI, Google, GitHub, or the makers of the other agents it runs.</em></p>
</blockquote>
<p>Here is how the three core pieces work under the hood: PTY session multiplexing across desktop and mobile, zero-index-touch git checkpoints before every prompt, and passkey-paired remote access.</p>
<hr />
<h2>1. One PTY per session, shared across the Mac window and phone browsers</h2>
<p>Quarters is built with <a href="https://wails.io">Wails</a>: a Go backend driving a plain ES-module JavaScript frontend (no bundler) inside the system WebView, with <a href="https://xtermjs.org">xterm.js</a> rendering each terminal.</p>
<p>Each project gets its own "room" (<code>internal/projects</code>), and each tab inside a room—whether it is an agent (<code>claude</code>, <code>codex</code>, <code>gemini</code>, <code>aider</code>, <code>opencode</code>, <code>copilot</code>, <code>devin</code>, <code>amp</code>, <code>goose</code>, <code>qwen</code>, <code>agy</code>, or <code>agent</code>) or a shell—runs in a pseudo-terminal managed by Go (<code>internal/session</code>).</p>
<p>Because the Go backend owns the PTY stream:</p>
<ul>
<li><strong>Multi-window &amp; phone sync:</strong> The Mac window and any connected phone or laptop browser subscribe to the same live PTY session over a WebSocket. Whichever window you are actively typing in sets the terminal's dimensions.</li>
<li><strong>"Your turn" detection (<code>◐ waiting</code>):</strong> Quarters watches terminal activity and session logs so when an agent finishes a turn or pauses for input in a background project, the room gets marked and moves to the top of the <code>ACTIVE</code> list (sorted longest-waiting first, reachable from anywhere with <code>⌘J</code>).</li>
<li><strong>In-process subagents:</strong> When launching Claude Code, Quarters passes <code>--settings '{"teammateMode":"in-process"}'</code> (unless you set your own <code>--settings</code>) and strips inherited <code>TMUX</code> or <code>STY</code> environment variables. That keeps subagents inside the tab you can see on both your Mac and your phone instead of spawning invisible tmux panes.</li>
<li><strong>Low idle footprint:</strong> Git status checks and file watchers only run when filesystem events fire, and timers pause while the window is hidden. Measured on a Mac with 14 projects open, Quarters sits at roughly <strong>2% of one CPU core</strong> when idle in the background.</li>
</ul>
<hr />
<h2>2. Snapshotting every prompt without touching your git index (<code>refs/quarters/checkpoints/</code>)</h2>
<p>Every time you send a prompt to an agent, you want a clean "undo" button in case the agent goes down the wrong path—even if you had uncommitted work in your working tree before the prompt started.</p>
<p>Using <code>git stash</code> or commits on your current branch causes constant friction with your real staging area. Instead, Quarters snapshots the project before every prompt using a temporary git index:</p>
<ol>
<li>Quarters copies the current index state into a temporary <code>GIT_INDEX_FILE</code>.</li>
<li>It stages all non-ignored working-tree files into that temporary index and writes a tree object (<code>git write-tree</code>).</li>
<li>It creates a commit object stored under <code>refs/quarters/checkpoints/</code> (keeping the last 50 per project).</li>
</ol>
<p>Because these commits live under <code>refs/quarters/checkpoints/</code>:</p>
<ul>
<li>Your actual branch, <code>HEAD</code>, staging index, and stash are <strong>never touched</strong>.</li>
<li>A plain <code>git push</code> never uploads checkpoint commits to your remote.</li>
<li>Opening the <strong>Checkpoints</strong> panel shows the exact file-by-file diff since any prompt. Clicking <strong>Restore</strong> takes a fresh checkpoint first (so even a restore is reversible) and puts your files back where they were.</li>
</ul>
<p>Similarly, the built-in Git commit dialog refuses to stage or commit files that look like secrets (<code>.env</code>, <code>*.pem</code>, private keys)—stopping the commit and naming the blocked files before they ever reach history.</p>
<hr />
<h2>3. Remote access from a phone: passkeys, loopback listener, and origin checks</h2>
<p>Because a terminal tab runs with your user's privileges, anyone who can type into it can run commands as you. Remote access is <strong>designed to be safe to expose; read <a href="https://github.com/amithgc/quarters/blob/main/SECURITY.md">SECURITY.md</a></strong> for the full threat model and implementation details.</p>
<p>Key design choices in <code>internal/remote</code>:</p>
<ul>
<li><strong>Off until you start it:</strong> The HTTP/WebSocket server does not run until you explicitly start it (<code>⌥⌘R</code> or <em>Remote Access → Start server</em>). By default it binds only to <code>127.0.0.1</code> and expects to be reached through your own tunnel (such as Cloudflare Tunnel or Tailscale Funnel), so no router ports are opened.</li>
<li><strong>Paired from the Mac with WebAuthn passkeys:</strong> Clicking <em>Pair a device</em> on the Mac generates a QR code carrying a single-use token in the URL fragment (never logged, valid for 10 minutes, burned after 5 failed attempts). Signing in uses WebAuthn passkeys (<code>go-webauthn</code>) requiring device user verification (Face ID, Touch ID, or PIN) bound to your domain. If a passkey's signature counter ever moves backward—a sign of credential cloning—Quarters refuses it and alerts you on the Mac.</li>
<li><strong>In-memory SHA-256 session hashes &amp; strict allowlists:</strong> Sessions are random 256-bit tokens kept only in memory as SHA-256 hashes (restarting Quarters signs everyone out) with <code>__Host-</code> prefixed, <code>HttpOnly</code>, <code>Secure</code>, <code>SameSite=Strict</code> cookies. Every WebSocket message re-verifies the session, checks <code>Host</code> and <code>Origin</code> headers to block DNS rebinding and cross-site WebSocket hijacking, and passes through an explicit RPC allowlist (<code>remote_app.go</code>) that keeps device pairing and security settings Mac-only.</li>
<li><strong>Phone-friendly cards + full terminal:</strong> On a phone browser, you can read the conversation as clean message cards, approve or reject tool prompts with a tap, queue your next prompt while the agent works, or flip to the live xterm.js view.</li>
</ul>
<hr />
<h2>Try it or read the code</h2>
<p>Quarters is <strong>free and open source (MIT)</strong>:</p>
<ul>
<li><strong>GitHub repository:</strong> <a href="https://github.com/amithgc/quarters?utm_source=hashnode&amp;utm_medium=blog&amp;utm_campaign=e54_quarters_arch">https://github.com/amithgc/quarters</a></li>
<li><strong>Website &amp; tour:</strong> <a href="https://quarters.amithgc.com?utm_source=hashnode&amp;utm_medium=blog&amp;utm_campaign=e54_quarters_arch">https://quarters.amithgc.com</a></li>
<li><strong>Security architecture:</strong> <a href="https://github.com/amithgc/quarters/blob/main/SECURITY.md">SECURITY.md</a></li>
<li><strong>Homebrew (macOS):</strong><pre><code class="language-sh">brew install --cask amithgc/tap/quarters
</code></pre>
</li>
</ul>
<p>If you run multiple CLI agents across projects—or have solved terminal multiplexing and mobile approvals differently—I would love to hear what your setup looks like.</p>
]]></content:encoded></item><item><title><![CDATA[How I make sure none of my puzzles needs a guess]]></title><description><![CDATA[The small solver scripts behind Little Grids, my grid-puzzle app for iPhone, iPad and Mac]]></description><link>https://amithgc.hashnode.dev/how-i-make-sure-none-of-my-puzzles-needs-a-guess</link><guid isPermaLink="true">https://amithgc.hashnode.dev/how-i-make-sure-none-of-my-puzzles-needs-a-guess</guid><category><![CDATA[Game Development]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[iOS]]></category><category><![CDATA[puzzle]]></category><category><![CDATA[Indie Games]]></category><dc:creator><![CDATA[Amith GC]]></dc:creator><pubDate>Mon, 02 Nov 2026 12:50:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6ae886248831ba3a85b16257/70812484-5980-4933-b367-64a8b51b678d.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've always hated the moment in a Minesweeper game where you've done everything right and you still have to flip a coin. So when I started building Little Grids, a collection of 16 small grid puzzles, I set myself one rule: a logic board only ships if it can be finished by reasoning alone.</p>
<p>That rule turned out to be most of the work. Every game started life as a browser game, and each one has its own little generator and solver written as Node scripts. The boards in the app are exported straight from those scripts and never edited by hand. Here's how a few of the games are checked.</p>
<p><strong>Mines.</strong> Each board has a fixed opening. A solver starts from that opening and only makes moves it can prove are safe. If it ever gets stuck, the board is thrown away. So you never face a 50/50, and the board doesn't move mines around after your first tap to hide that.</p>
<p><strong>Nonogram.</strong> I drew 42 pictures by hand, in 5x5, 10x10 and 15x15. A picture is kept only if solving it one line at a time, with no guessing, finishes the whole thing. Some of my favourite drawings didn't survive that test, and I had to redraw them.</p>
<p><strong>Shikaku.</strong> The generator cuts the grid into rectangles first, then an exhaustive solver checks the clues. A board is kept only if there is exactly one answer.</p>
<p>Loop and Switch Off are solvable by construction. Loop scrambles a random spanning tree, and Switch Off starts from a board with every light off and applies random taps, so there is always a way back.</p>
<p>Word Snake lays each word as a path that turns, adds decoy starting letters, and then searches the finished grid to make sure every word is really there.</p>
<p>The app itself is written in Flutter, and the Dart game engines are tested against the web code: for each game, a script runs the web engine and solver and saves real solutions, and the Dart tests replay them move by move. If the two ever disagree, the test fails.</p>
<p>Why bother? Because a puzzle that needs a guess isn't really a puzzle. When you're stuck in Little Grids, there's always a reason you can find, and the hint (a ghost finger that shows the next move) is computed by the same solvers that checked the board.</p>
<p>Little Grids is free to download on iPhone, iPad and Mac, and every game has a free part with no time limit: <a href="https://apps.apple.com/app/id6816600512">https://apps.apple.com/app/id6816600512</a></p>
<p>This Sunday, 8 November, there's a Big Sunday board event in the app if you want to try it on something bigger.</p>
<p>I'd love to hear from other people who build puzzles: how do you check yours?</p>
<p>- Amith</p>
]]></content:encoded></item></channel></rss>