<?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[WIO]]></title><description><![CDATA[WIO]]></description><link>https://xwiox.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 30 Oct 2026 17:44:56 GMT</lastBuildDate><atom:link href="https://xwiox.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[All your coding agents in one Mac window, and the one that needs you is amber]]></title><description><![CDATA[One of your agents stopped to ask whether it could deploy, sometime in the last hour. You know one of them did. You don't know which. The shape is always…]]></description><link>https://xwiox.hashnode.dev/all-your-coding-agents-in-one-mac-window-and-the-one-that-needs-you-is-amber</link><guid isPermaLink="true">https://xwiox.hashnode.dev/all-your-coding-agents-in-one-mac-window-and-the-one-that-needs-you-is-amber</guid><category><![CDATA[AI]]></category><category><![CDATA[macOS]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[terminal]]></category><dc:creator><![CDATA[WIO]]></dc:creator><pubDate>Wed, 28 Oct 2026 08:27:54 GMT</pubDate><content:encoded><![CDATA[<p>One of your agents stopped to ask whether it could deploy, sometime in the last hour. You know one of them did. You don't know which.</p>
<p>The shape is always the same: Claude Code on the Mac, Codex on a build box, something else on a server you log into twice a week. Every one of them stops before it deploys, deletes or installs, and waits for a yes. The yes takes two seconds. Working out who is waiting, and where, is what ate my evenings.</p>
<p>The obvious discipline is a tmux session per machine, one terminal per project, and a habit of tailing the right scrollback. That holds until the third machine, and then you are the router. You alt-tab, you read a wall of output to see whether the agent is stuck or just quiet, you SSH in to check.</p>
<p>None of that is a complaint about Herdr. Herdr already knows which agent is working, waiting, done or idle, and it keeps them all alive whether or not anyone is looking. What I wanted was narrower: one Mac window with every agent in it, on every machine, and two keys to the one that needs me.</p>
<p>So I built Shepi for Herdr. It is a native Mac client for Herdr: every agent in a real terminal, on this Mac or your servers, with the one that needs you in amber.</p>
<p>It does not replace Herdr. Herdr keeps running your agents and Shepi is a window onto it. Quit Shepi and nothing stops; open it again and every space, tab and agent you already had is exactly where you left it.</p>
<h2>Amber means exactly one thing</h2>
<p>When an agent stops to ask, it turns amber in three places at once: the sidebar, its pane header and the status line. A card shows the command it wants to run, when the agent says so. A banner reaches you even with the sidebar folded away with ⇧⌘1, and you hear Herdr's own sound, at the moments Herdr would play it, from every machine.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6addfd528133d70a819385b1/3bddc3de-b9b7-45c2-95d2-5681b076e478.png" alt="The Shepi window: in the sidebar the agent &quot;ship usage chart&quot; is amber with &quot;needs you&quot;; a card under it reads &quot;Wants to run bunx wrangler deploy --env staging&quot; with a Review button; a banner at the top right says &quot;web-dashboard needs you&quot;." style="display:block;margin:0 auto" />

<p>Then it is the prefix and <code>a</code>. <code>⌃B a</code> lands you on the next agent that needs you, whichever machine it is on. Review on the card does the same thing with the mouse.</p>
<p>Amber means one thing in Shepi: something needs you. That is the whole colour language.</p>
<h2>The agent can ask you with buttons, not just a menu</h2>
<p>Most of the time an agent's question is a numbered menu in a wall of terminal output, and the cheap thing to do is hit 1 and hope. In Shepi an agent can ask you properly:</p>
<pre><code class="language-plaintext">shepi-agent ask "Deploy to staging?" --options Deploy,Wait
</code></pre>
<p>It arrives like any agent that needs you, and your click goes straight back to it as the answer. The same small plugin lets an agent open a page or a file on your Mac, report its progress under its own name in the sidebar ("Step 3 of 7 · migrating"), and open a pane beside itself to run tests or a dev server, marked as opened by it and never taking your keyboard. On your servers too.</p>
<p>Shepi installs that plugin on every machine it connects to, and Claude Code, Codex, Cursor, OpenCode, Gemini CLI, Copilot CLI, Amp and Grok Build pick the skill up by themselves. Any other agent needs one line in its instructions. Agents ask, show, report and arrange; they never type into a pane or click for you.</p>
<h2>Your servers are in the same sidebar</h2>
<p>Add any machine you reach over SSH from the sidebar or Settings › Machines, as <code>you@server</code> or a host from <code>~/.ssh/config</code>. Herdr's own machine setup runs in a terminal inside Shepi, so host keys and passphrases stay in your hands.</p>
<p>It joins as its own group, and every space shows how many agents need you, are working, are done or idle. Agents on a server keep going even while this Mac sleeps.</p>
<p>When a server prints <code>http://localhost:5173</code>, ⌘-click it. Shepi forwards that port over your SSH connection and opens the page here, on another port if 5173 is taken, and the status line says which.</p>
<h2>Five letters to a pane on another machine</h2>
<p>⌘F searches agents, spaces, panes, machines and the recent output of every pane, local and over SSH. Type a word or two in any order; separators do not matter and first letters work, so <code>fat</code> finds <code>fix-flaky-auth-test</code>. One typo in a longer word is forgiven. Land on output and ⌘G steps through the matches.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6addfd528133d70a819385b1/3a2a19cd-8cfc-4ad5-b726-2c210b059378.png" alt="Find open over four panes with the query &quot;backf&quot;: one agent, &quot;backfill events v2&quot; on workbox, and one line of its output from that machine." style="display:block;margin:0 auto" />

<p>⌘E lists the panes you used last, newest first, with the one you just left already selected. ⌘E, Return, and you are back in it.</p>
<h2>Then the terminal chores are just gone</h2>
<p>None of these are the reason I built it, and all of them are the reason I stopped going back.</p>
<p>Paste a screenshot or drop files onto a pane. On this Mac the paths are pasted; on a server Shepi copies them over SSH first, so Claude Code sees the image as if it were local, up to 32 MB at a time. The prefix and <code>d</code> shows every file changed since the last commit, side by side or in one column, on this Mac or a server, and only shows: it never stages or edits.</p>
<p>The pane your keys go to is the lighter card and the only one with a blinking cursor, and its header names the agent in it, while every other pane stays at full brightness. Drag a pane by its header and the layout shows where it will land before you let go; drop it on another tab and the program inside never stops running. The prefix and <code>=</code> evens out every pane in the tab, the prefix and <code>z</code> takes one full-window and puts the layout back, and a macro on any key of your choosing can type <code>/model</code>, press Return, wait for "Select model", then two more keys into the pane you are in, on this Mac or a server.</p>
<p>The keys are Herdr's, read live from its config. Shepi never edits that file, and change one there and Shepi follows. Almost everything also has a mouse equivalent, and every tooltip names its key.</p>
<h2>Step away for six hours</h2>
<p>Leave Shepi open and walk away. Every agent that needed you, finished or asked a question meanwhile waits in the inbox next to Find, one entry per pane, until you look at that pane. The Dock icon shows how many and right-clicking it lists them.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6addfd528133d70a819385b1/95a159fb-50df-40ec-b3aa-621fca3d227f.png" alt="The inbox open next to Find, listing three entries: &quot;explore&quot; asked a question while you were away, and &quot;backfill events v2&quot; and &quot;fix-flaky-auth-test&quot; are done." style="display:block;margin:0 auto" />

<p>Quit the window instead and it works out the same. Herdr keeps your agents running, and on your servers they keep going even while the Mac sleeps. Reopen Shepi and everything is where you left it. If the connection dropped, the status line says how many panes changed while you were gone.</p>
<h2>What it is, and what it isn't</h2>
<ul>
<li>It works with Claude Code, Codex, OpenCode, Gemini CLI, Cursor, Copilot CLI and anything else that runs in a terminal. Every agent Herdr recognises shows its state; the common ones show their own mark.</li>
<li>No analytics, no crash reports, and no Shepi account to create.</li>
<li>macOS 14 or later, Apple silicon and Intel, notarized by Apple. Herdr 0.9.3 or later; if it is missing, Shepi shows you the one-line install command.</li>
<li>Two honest limits: a screenshot pasted into a pane on a server is a file there, not a picture on your screen, and a pane can move between tabs of one space, not between machines.</li>
<li>An independent client built on Herdr's public interface. Not made by the Herdr project, and not affiliated with it.</li>
</ul>
<p><a href="https://shepi.app/">https://shepi.app/</a></p>
<p>If your agents are spread across a Mac and two servers, how do you keep track of which one is waiting on you without checking all three?</p>
]]></content:encoded></item><item><title><![CDATA[How to share one App Store link that works in every country]]></title><description><![CDATA[Cloudflare's country header plus Apple's public lookup API, and the one iPhone catch]]></description><link>https://xwiox.hashnode.dev/how-to-share-one-app-store-link-that-works-in-every-country</link><guid isPermaLink="true">https://xwiox.hashnode.dev/how-to-share-one-app-store-link-that-works-in-every-country</guid><category><![CDATA[iOS]]></category><category><![CDATA[Cloudflare Workers]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[app store]]></category><dc:creator><![CDATA[WIO]]></dc:creator><pubDate>Mon, 26 Oct 2026 17:37:11 GMT</pubDate><content:encoded><![CDATA[<p>Most of us copy App Store links straight out of the browser bar, something like:</p>
<pre><code class="language-plaintext">https://apps.apple.com/us/app/your-app/id1232780281
</code></pre>
<p>That <code>/us/</code> is the problem. App Store web links carry a two-letter country code, because Apple runs a separate store (a "storefront") for each country. Someone in Japan who taps a <code>/us/</code> link is looking at the US store. And if your app isn't sold in their country at all, they hit Apple's "This app is not available in your country or region" message instead of your app.</p>
<p>Making a separate link for every country isn't realistic. You'd need to know where each reader is before they click. So the link has to work it out at click time.</p>
<h2>The useful fact: the app ID never changes</h2>
<p>Every app has a numeric ID, the <code>id1232780281</code> part. It's the same in every country. The only thing that changes between storefronts is the country code:</p>
<pre><code class="language-plaintext">apps.apple.com/us/app/id1232780281
apps.apple.com/jp/app/id1232780281
apps.apple.com/de/app/id1232780281
</code></pre>
<p>So if you know the visitor's country and you know the app is sold there, you can build the right URL yourself.</p>
<h2>Step 1: where is the visitor?</h2>
<p>If your code runs on Cloudflare Workers, you get this for free. Cloudflare attaches the visitor's country to every request as <code>request.cf.country</code>, an ISO code like <code>JP</code>. Two values need care: <code>XX</code> means unknown and <code>T1</code> means Tor. Treat both as "no country".</p>
<pre><code class="language-ts">function normalizeCountry(raw: unknown): string | null {
  if (typeof raw !== "string" || !/^[A-Za-z]{2}$/.test(raw)) return null;
  const cc = raw.toLowerCase();
  return cc === "xx" || cc === "t1" ? null : cc;
}
</code></pre>
<p>When the country is unknown, the safest redirect is Apple's country-less link, <code>https://apps.apple.com/app/id&lt;ID&gt;</code>, and Apple picks the store.</p>
<h2>Step 2: is the app sold there?</h2>
<p>Apple has a public lookup endpoint (the old iTunes Search API) that answers this:</p>
<pre><code class="language-plaintext">https://itunes.apple.com/lookup?id=1232780281&amp;country=jp
</code></pre>
<p>If the app is in that storefront you get <code>resultCount: 1</code> plus its name and icon. If it isn't, you get <code>resultCount: 0</code>. No key needed.</p>
<p>The endpoint is rate-limited, so don't call it on every click. On Workers you can cache the fetch at the edge:</p>
<pre><code class="language-ts">const res = await fetch(url, { cf: { cacheTtl: 86400, cacheEverything: true } });
</code></pre>
<p>A day of caching means Apple only gets asked about each app and country pair occasionally. The trade-off: when an app launches in a new country, detection can lag by up to a day.</p>
<h2>Step 3: when it isn't sold there</h2>
<p>Now you need a fallback. Most apps are in the US store, so check that first, then walk a list of other large storefronts (UK, Canada, Australia, Germany, France, Japan and so on) until one says yes.</p>
<p>On a computer or Android phone, you can just redirect to that store's page. The visitor sees the app, its screenshots, its description.</p>
<h2>The iPhone catch</h2>
<p>This is the part that surprised me. On iPhone and iPad, App Store links open in the App Store app, and the App Store app can only show the store for the account's own country. So redirecting a visitor in, say, Brazil to the <code>/us/</code> page doesn't show them the US page. It ends in the same "not available" message you were trying to avoid.</p>
<p>The only honest fix is to not redirect. Instead, show a small page with the app's icon and name (both come from the lookup response) and a button to the store that has it. At least the visitor sees which app you meant and where it's sold. It's less magic than a redirect, but it doesn't dead-end.</p>
<h2>One more failure case</h2>
<p>If Apple's endpoint is down or returns an error, don't show an error page. Send the visitor to their own country's page. Most of the time the app is sold there anyway.</p>
<h2>Putting it together: Hither</h2>
<p>I wrapped all of this into a small free tool called <a href="https://hither.link/">Hither</a>. You paste any App Store link (from any country) or a bare app ID, and you get:</p>
<pre><code class="language-plaintext">hither.link/1232780281
</code></pre>
<p>The link holds only the app ID, so there's no database. The same app always gets the same link, links don't expire, and nobody can change where a link goes, because everything else comes from Apple at click time. There's no account. You can even make your link before launch, using the Apple ID from your app's App Information page in App Store Connect, and put it on your landing page ahead of time.</p>
<h2>Run your own copy</h2>
<p>The code is <a href="https://github.com/xxwioxx/hither">on GitHub under the MIT license</a>. It's a single Cloudflare Worker, and the Apple-specific bits live in one file (<code>src/apple.ts</code>) while the routing decision is pure, tested logic (<code>src/decide.ts</code>).</p>
<pre><code class="language-bash">npm install
npm test
npm run dev
</code></pre>
<p>To deploy to your own domain:</p>
<pre><code class="language-bash">npx wrangler login
CLOUDFLARE_ACCOUNT_ID=your-account-id npm run deploy
</code></pre>
<p>Change the domain in <code>wrangler.toml</code>, <code>public/robots.txt</code> and <code>public/sitemap.xml</code> first. On Cloudflare's free plan a Worker handles 100,000 requests a day, and going over makes requests fail until the daily reset instead of producing a bill.</p>
<p>Ideas on the list: Google Play links, custom short names (with a way to prove you own the app), and a QR code per link. If you've hit other edge cases with App Store links across countries, I'd like to hear about them in the comments.</p>
<p><em>Originally published on</em> <a href="https://dev.to/xwiox/how-to-share-one-app-store-link-that-works-in-every-country-3o83"><em>dev.to</em></a><em>.</em></p>
]]></content:encoded></item></channel></rss>