<?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[Mac Apps by Aura]]></title><description><![CDATA[Mac Apps by Aura]]></description><link>https://auramacapps.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 26 Oct 2026 10:02:03 GMT</lastBuildDate><atom:link href="https://auramacapps.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[DraftKey vs WunderType: $4.99 On-Device Autocomplete vs Free Mac App Store AI Writing]]></title><description><![CDATA[I built DraftKey — on-device AI autocomplete for every Mac app at $4.99 lifetime. If you want Tab-to-accept suggestions in Mail, Slack, Notes, Linear, and…]]></description><link>https://auramacapps.hashnode.dev/draftkey-vs-wundertype-4-99-on-device-autocomplete-vs-free-mac-app-store-ai-writing</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/draftkey-vs-wundertype-4-99-on-device-autocomplete-vs-free-mac-app-store-ai-writing</guid><category><![CDATA[draftkey]]></category><category><![CDATA[macOS]]></category><category><![CDATA[AI]]></category><category><![CDATA[writing]]></category><category><![CDATA[wundertype]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Mon, 26 Oct 2026 03:57:17 GMT</pubDate><content:encoded><![CDATA[<p>I built <strong>DraftKey</strong> — on-device AI autocomplete for every Mac app at <strong>$4.99 lifetime</strong>. If you want Tab-to-accept suggestions in Mail, Slack, Notes, Linear, and browsers without sending your text to a cloud AI, that's what it is. Get it at <a href="https://getdraftkey.com">getdraftkey.com</a>.</p>
<p>This post is a direct product comparison with WunderType, the free Mac App Store writing tool a lot of people try first. I'm the maker of DraftKey (Aura Technologies). I'm not neutral. I'll still be honest about where WunderType wins.</p>
<h2>The short answer</h2>
<table>
<thead>
<tr>
<th></th>
<th>DraftKey</th>
<th>WunderType</th>
</tr>
</thead>
<tbody><tr>
<td>Price</td>
<td><strong>$4.99 once</strong>, up to 3 Macs</td>
<td>Free on the Mac App Store</td>
</tr>
<tr>
<td>Model</td>
<td>Bundled on-device model (~1.12 GB)</td>
<td>Local via Apple MLX / your setup</td>
</tr>
<tr>
<td>Core UX</td>
<td>Inline <strong>Tab autocomplete</strong> + ⌘⌥ rewrite</td>
<td>Rewrite modes / fixes</td>
</tr>
<tr>
<td>Cloud</td>
<td>Text stays on your Mac after setup</td>
<td>Local / no account positioning</td>
</tr>
<tr>
<td>Trial</td>
<td>No free trial (browser typing demo on the site)</td>
<td>Free download</td>
</tr>
<tr>
<td>Requirements</td>
<td>macOS 14+, Apple Silicon, 8 GB RAM</td>
<td>Mac App Store (check their page)</td>
</tr>
</tbody></table>
<p><strong>Pick DraftKey</strong> if you want system-wide next-word suggestions as you type, a one-time $4.99 license, and a model that ships with the app.</p>
<p><strong>Pick WunderType</strong> if you want $0 and you're fine without Tab autocomplete as the main loop.</p>
<h2>What DraftKey actually is</h2>
<p>DraftKey reads the text around your cursor through macOS Accessibility, runs a small language model on your Mac, and shows a short gray suggestion. Press <strong>Tab</strong> to accept. Press <strong>⌘⌥</strong> to rewrite the paragraph or selection (shorter, clearer, fix grammar, change tone, or a custom instruction). Review before insert.</p>
<p>It is not a chatbot and not a side panel. It's autocomplete for prose, system-wide, in compatible text fields.</p>
<p>Also included: clipboard history (⌘⌥V) and optional keyboard sounds.</p>
<h2>Honest limits (read before you buy)</h2>
<ol>
<li><strong>No free trial.</strong> $4.99 to try the real app. There's a free in-browser typing demo on <a href="https://getdraftkey.com">getdraftkey.com</a>.</li>
<li><strong>Apple Silicon + macOS 14+ only.</strong> No Intel.</li>
<li><strong>~1.12 GB model download</strong> on first launch (~2.2 GB free space).</li>
<li><strong>Accessibility-dependent.</strong> Some Electron apps, custom editors, and all secure fields won't work well or at all.</li>
<li><strong>Not GPT-class.</strong> Small local model = fast sentence finishing, not essay writing.</li>
</ol>
<h2>Why compare to WunderType</h2>
<p>WunderType is the obvious free alternative people find when they search "AI writing Mac local." If your main need is rewrite modes and you don't care about inline Tab autocomplete, stay on free.</p>
<p>If you specifically want <strong>Tab-to-accept suggestions while you type in the apps you already use</strong>, and you're willing to pay once for a bundled on-device model, DraftKey is built for that.</p>
<h2>Price</h2>
<ul>
<li><strong>DraftKey:</strong> $4.99 lifetime, up to 3 Macs. No subscription. No account for writing.</li>
<li><strong>WunderType:</strong> Free (Mac App Store). Confirm current features on their listing.</li>
</ul>
<h2>Get DraftKey</h2>
<p><a href="https://getdraftkey.com">getdraftkey.com</a> — download, buy the $4.99 lifetime license, grant Accessibility, let the model download once.</p>
<p>I built it. Aura Technologies. If suggestions are wrong in a specific app, I want to know.</p>
]]></content:encoded></item><item><title><![CDATA[TokenBar: See Your Claude Code, Codex and Cursor Spend in the Mac Menu Bar ($15 Lifetime)]]></title><description><![CDATA[TokenBar is a Mac menu-bar app that shows what your AI coding tools (Claude Code, Codex, and Cursor) are using and costing you, at a glance, without…]]></description><link>https://auramacapps.hashnode.dev/tokenbar-see-your-claude-code-codex-and-cursor-spend-in-the-mac-menu-bar-15-lifetime</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/tokenbar-see-your-claude-code-codex-and-cursor-spend-in-the-mac-menu-bar-15-lifetime</guid><category><![CDATA[tokenbar]]></category><category><![CDATA[macOS]]></category><category><![CDATA[AI]]></category><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sun, 25 Oct 2026 15:54:46 GMT</pubDate><content:encoded><![CDATA[<p>TokenBar is a Mac menu-bar app that shows what your AI coding tools (Claude Code, Codex, and Cursor) are using and costing you, at a glance, without opening dashboards. It's $15 once, no subscription, at <a href="https://tokenbar.site">tokenbar.site</a>.</p>
<p>Disclosure: I built TokenBar, under my indie studio Aura Technologies. It's built on <strong>CodexBar</strong>, a free, open-source, MIT-licensed menu-bar app. The MIT license permits commercial derivatives, and TokenBar keeps the required license and attribution. If CodexBar already does what you need, use it: it's free and good.</p>
<h2>The problem</h2>
<p>If you use more than one AI coding tool, spend is scattered across separate dashboards, billing pages, and usage limits. You usually find out you burned through a quota or a budget after the fact: a rate-limit wall mid-task or a surprise bill at month end. An agent left looping, or five parallel sessions, can move the number fast.</p>
<p>TokenBar puts that number where you'll actually see it: the menu bar.</p>
<h2>What TokenBar does</h2>
<ul>
<li><strong>Menu-bar usage and spend</strong> for Claude Code, Codex, and Cursor in one place.</li>
<li><strong>Click for a breakdown</strong> by tool, so you can see which one is driving cost.</li>
<li><strong>Glanceable limits</strong>, so you notice you're close to a quota before you hit it.</li>
<li><strong>One-time $15 purchase.</strong> No account with us, no subscription.</li>
</ul>
<p>The point isn't fancy analytics. It's making spend visible constantly so you change behavior in the moment: kill a stuck session, switch a task to a cheaper model, or stop for the day.</p>
<h2>TokenBar vs CodexBar, honestly</h2>
<p>CodexBar is the open-source foundation. TokenBar is a paid, packaged version from Aura Technologies focused on spend tracking across Claude, Codex, and Cursor. You're paying $15 for the packaging, the cost-focused presentation, and ongoing maintenance by a developer you can email. You are not paying for something that's impossible to get for free. If you're comfortable with an open-source app and its feature set covers your tools, CodexBar is a perfectly good choice.</p>
<h2>Honest limits</h2>
<ul>
<li><strong>Mac only.</strong> It's a macOS menu-bar app.</li>
<li><strong>Numbers are only as good as the sources.</strong> Usage data comes from what each tool and provider exposes. Figures can lag, and providers change formats; when they do, an update may be needed.</li>
<li><strong>It's a monitor, not a controller.</strong> TokenBar shows spend; it doesn't cap it or stop your agents for you.</li>
<li><strong>No free trial.</strong> CodexBar is effectively the free way to see if a menu-bar tracker fits your workflow.</li>
</ul>
<h2>Who it's for</h2>
<ul>
<li>Solo developers and freelancers paying for AI coding tools out of pocket.</li>
<li>People juggling Claude Code, Codex, and Cursor at once.</li>
<li>Anyone who has been surprised by an AI bill or a usage limit at a bad moment.</li>
</ul>
<h2>Get it</h2>
<p>TokenBar is $15 lifetime at <a href="https://tokenbar.site">tokenbar.site</a>. If a tool you use isn't covered or a number looks off, reach out via the site and I'll look into it.</p>
]]></content:encoded></item><item><title><![CDATA[Turning a 200-Message Slack Thread into Meeting Notes People Will Actually Read]]></title><description><![CDATA[Every engineering team has the thread. It starts as a quick question in #backend, picks up a few opinions, turns into a design debate, and two hundred…]]></description><link>https://auramacapps.hashnode.dev/turning-a-200-message-slack-thread-into-meeting-notes-people-will-actually-read</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/turning-a-200-message-slack-thread-into-meeting-notes-people-will-actually-read</guid><category><![CDATA[Productivity]]></category><category><![CDATA[writing]]></category><category><![CDATA[macOS]]></category><category><![CDATA[remote]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sun, 25 Oct 2026 15:49:25 GMT</pubDate><content:encoded><![CDATA[<p>Every engineering team has the thread. It starts as a quick question in #backend, picks up a few opinions, turns into a design debate, and two hundred messages later someone says "can we get a summary of where we landed?" Nobody volunteers, because summarizing a thread is tedious, and the result usually reads like a transcript with the jokes removed.</p>
<p>This post is a practical method for turning a long Slack thread into notes that someone who wasn't there can read in ninety seconds. It works with any tool, including pen and paper. Near the end I'll mention the Mac app I built to speed up the rewriting step, but the method is the important part.</p>
<h2>Why thread summaries go wrong</h2>
<p>Most bad summaries fail in one of three ways:</p>
<ol>
<li><strong>They are chronological.</strong> "First Sam said X, then Priya pointed out Y." Readers don't care about the order of the conversation; they care about the outcome.</li>
<li><strong>They hide the decision.</strong> The actual decision is buried in paragraph four, phrased as "it seemed like people were leaning toward..."</li>
<li><strong>They drop the open questions.</strong> The thread ended with two unresolved issues, and the summary quietly pretends they don't exist. Two weeks later they resurface as surprises.</li>
</ol>
<p>A good summary is organized by outcome, not by time.</p>
<h2>The five-section template</h2>
<p>Paste this into a doc, a Notion page, or a reply in the thread itself:</p>
<pre><code>**Decision:** One or two sentences. What are we doing?
**Why:** The two or three reasons that actually carried the argument.
**Rejected options:** What we considered and why we didn't pick it.
**Open questions:** What is still unresolved, and who owns each one.
**Next steps:** Concrete actions with names and rough dates.
</code></pre>
<p>That's it. If a section is empty, write "None" instead of deleting it. An explicit "Open questions: None" tells readers the debate is really over.</p>
<h2>Step 1: Skim for turning points, not content</h2>
<p>Don't read the thread top to bottom trying to absorb everything. Scroll and look for moments where the direction changed:</p>
<ul>
<li>Someone posts data (a benchmark, a cost estimate, a customer quote).</li>
<li>A senior person or the owner of the system weighs in.</li>
<li>Someone says "ok, so..." or "sounds like we're going with..."</li>
<li>Reactions cluster on a message (a pile of thumbs-up is often an implicit vote).</li>
</ul>
<p>Copy those messages into a scratch file. For a 200-message thread you usually end up with ten to fifteen.</p>
<h2>Step 2: Write the decision first</h2>
<p>Write the decision sentence before anything else, in plain language: "We're moving session storage from Postgres to Redis, behind a feature flag, starting with the EU region."</p>
<p>If you can't write that sentence, the thread didn't reach a decision, and your summary should say so: "Decision: None yet. Two options remain (below); we need a call from the platform lead by Friday." That is still a useful summary. It's honest, and it gives the thread a path to closure.</p>
<h2>Step 3: Keep reasons short and attributable</h2>
<p>For the "Why" section, include only the reasons that changed minds. Three bullets is plenty. If a reason came from a specific person with specific context, attribute it lightly: "(per the on-call review)" or "(from the load test)". This gives readers a way to dig deeper without turning the summary into a who-said-what log.</p>
<h2>Step 4: Rewrite for someone who wasn't there</h2>
<p>This is the step that takes the longest and benefits most from help. Thread language is full of shorthand, inside references, and half-sentences: "yeah the thing from last sprint would bite us again lol." Your summary needs to say "this would repeat the cache invalidation bug from the March incident."</p>
<p>Read every bullet and ask: would a new hire understand this? Replace pronouns with nouns, expand acronyms the first time, and delete hedging words like "kind of," "probably," and "I think" unless the uncertainty is real.</p>
<h2>Step 5: Post it where the thread lives</h2>
<p>Post the summary as a reply in the original thread and pin it, or post it to the channel with a link to the thread. Tag the owners listed in "Open questions" and "Next steps." Summaries that live in a separate doc nobody links to get lost.</p>
<h2>A worked example</h2>
<p>Raw thread fragments:</p>
<blockquote>
<p>"honestly redis is fine for this, we already run it for rate limiting"
"what about persistence tho, if it restarts we log everyone out"
"AOF every second is fine, we lose at most 1s of sessions"
"ok can we just flag it and try EU first"</p>
</blockquote>
<p>Summary:</p>
<blockquote>
<p><strong>Decision:</strong> Move session storage to Redis behind a feature flag, rolling out to the EU region first.
<strong>Why:</strong> We already operate Redis for rate limiting; Postgres session reads are 30% of DB load; AOF persistence limits loss to about one second of sessions on restart.
<strong>Rejected options:</strong> Memcached (no persistence); keeping Postgres with a read replica (doesn't reduce write load).
<strong>Open questions:</strong> Session migration for logged-in users (owner: platform team).
<strong>Next steps:</strong> Flag and EU rollout plan drafted by Thursday.</p>
</blockquote>
<h2>Where an on-device writer helps</h2>
<p>Step 4, rewriting shorthand into clear sentences, is where I lean on a writing tool. Full disclosure: I built DraftKey, a Mac app from Aura Technologies that rewrites and tidies text using a model that runs entirely on your Mac. That matters for this use case specifically, because Slack threads often contain internal system names, incident details, and customer information that you may not want to paste into a cloud chatbot.</p>
<p>DraftKey is a $4.99 one-time purchase (no subscription) at getdraftkey.com. It needs macOS 14 or later on Apple Silicon, downloads a roughly 1.12GB local model, and works on up to three Macs. There's no free trial, so check the requirements first. It isn't the only one-time-purchase AI writing app for Mac, either; tools like Charm and RewriteBar are worth a look too.</p>
<p>Whatever you use, the template does most of the work. Decision first, open questions explicit, and written for the person who wasn't in the room.</p>
]]></content:encoded></item><item><title><![CDATA[Writing Good DocC Documentation for Swift Packages: Prose That Developers Actually Read]]></title><description><![CDATA[DocC turns Swift documentation comments into a polished documentation site, and Xcode makes building it almost free. The hard part is not the tooling. It…]]></description><link>https://auramacapps.hashnode.dev/writing-good-docc-documentation-for-swift-packages-prose-that-developers-actually-read</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/writing-good-docc-documentation-for-swift-packages-prose-that-developers-actually-read</guid><category><![CDATA[Swift]]></category><category><![CDATA[documentation]]></category><category><![CDATA[iOS]]></category><category><![CDATA[macOS]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sun, 25 Oct 2026 14:00:36 GMT</pubDate><content:encoded><![CDATA[<p>DocC turns Swift documentation comments into a polished documentation site, and Xcode makes building it almost free. The hard part is not the tooling. It is the writing. Most Swift packages ship DocC sites full of auto-generated symbol pages with one-line summaries like "The configuration." That is technically documentation and practically useless.</p>
<p>This guide focuses on the prose side of DocC: what to write in summaries, discussions, articles and tutorials so that people can actually use your package.</p>
<h2>Quick DocC refresher</h2>
<ul>
<li><code>///</code> comments above a symbol become its documentation page.</li>
<li>The first paragraph is the <strong>summary</strong>, shown in lists and Quick Help.</li>
<li>Subsequent paragraphs are the <strong>discussion</strong>.</li>
<li><code>- Parameters:</code>, <code>- Returns:</code> and <code>- Throws:</code> document signatures.</li>
<li>A <code>.docc</code> catalog holds articles, tutorials and a landing page.</li>
<li>Build with <strong>Product → Build Documentation</strong> in Xcode or <code>swift package generate-documentation</code> with the Swift-DocC plugin.</li>
</ul>
<h2>Summaries: one sentence, starts with a verb or noun phrase</h2>
<p>The summary is the most-read line of your docs. Rules:</p>
<ul>
<li>One sentence.</li>
<li>Do not repeat the symbol name.</li>
<li>Say what it does or what it is, not how.</li>
</ul>
<pre><code class="language-swift">/// Retries a failed request with exponential backoff.
func retry(_ request: URLRequest, attempts: Int) async throws -&gt; Data
</code></pre>
<p>Not "This function retries the request," and definitely not "Retry."</p>
<p>For types, use a noun phrase: "A cache that evicts the least recently used entries when it reaches capacity."</p>
<h2>Discussions: answer the questions people actually have</h2>
<p>After the summary, write the discussion for someone deciding whether and how to use the symbol. Good discussions answer:</p>
<ul>
<li>When should I use this instead of the alternative?</li>
<li>What are the defaults and gotchas?</li>
<li>Is it thread-safe? Is it main-actor bound?</li>
<li>What does a minimal example look like?</li>
</ul>
<p>Include a short code example in almost every non-trivial discussion. Code is what people copy.</p>
<h2>Parameters and errors: say what is valid</h2>
<p>"<code>attempts</code>: The number of attempts" adds nothing. Instead:</p>
<pre><code class="language-swift">/// - Parameters:
///   - attempts: Maximum number of tries, including the first. Must be at least 1.
/// - Throws: `RetryError.exhausted` after the final attempt fails.
</code></pre>
<p>Valid ranges, units and failure behavior are what readers need.</p>
<h2>The landing page and articles</h2>
<p>The generated symbol list is a reference, not an introduction. Add to your <code>.docc</code> catalog:</p>
<ol>
<li><strong>A landing page</strong> with a two-paragraph overview and a curated <strong>Topics</strong> section grouping symbols by task ("Making Requests", "Handling Errors") rather than alphabetically.</li>
<li><strong>A Getting Started article</strong> that goes from adding the package to a working result in under five minutes.</li>
<li><strong>One article per major concept</strong>, such as configuration, concurrency model and migration guides.</li>
</ol>
<p>Curated topic groups are the biggest single upgrade most DocC sites can make. Alphabetical symbol lists force readers to already know what they are looking for.</p>
<h2>Tutorials: optional, but powerful</h2>
<p>DocC's interactive tutorials (step-by-step with code and images) are great for UI frameworks and onboarding-heavy packages. They take real time. Write the articles first; add a tutorial once you know which workflow confuses users most.</p>
<h2>Style rules that help</h2>
<ul>
<li><strong>Present tense, active voice.</strong> "Returns the cached value," not "The cached value will be returned."</li>
<li><strong>Short paragraphs.</strong> DocC renders long paragraphs as walls of text.</li>
<li><strong>Link symbols.</strong> Use double backticks, such as <code>RetryPolicy</code>, to link to other symbols. Broken links show as warnings; fix them.</li>
<li><strong>Consistent terms.</strong> Pick "request" or "call" and stick to it.</li>
</ul>
<h2>A fast writing workflow</h2>
<p>Documentation stalls because it feels like a separate project. Treat it like code review instead:</p>
<ol>
<li>When you add or change a public symbol, write the summary in the same commit.</li>
<li>Once per release, build docs and scan for empty or one-word discussions.</li>
<li>Fix the five most important symbols each time rather than everything at once.</li>
</ol>
<p>For the actual sentences, I draft rough notes in the comment and then tighten them. An inline AI rewrite tool that works in Xcode's editor is handy for turning "does retry w/ backoff, max attempts incl first" into a clean summary. For code that is not public yet, I want that processing on-device.</p>
<p>I use <a href="https://getdraftkey.com">DraftKey</a> for the prose part of this: on-device AI autocomplete and rewrite that works in the text fields of most Mac apps. It is $4.99 lifetime for up to 3 Macs, needs macOS 14+ on Apple Silicon, and downloads a roughly 1.12 GB local model, so drafts never leave the machine. There is no free trial, so check the requirements before you buy. It is not the only pay-once option; Charm, RewriteBar and others exist and are worth comparing. Disclosure: I built DraftKey (Aura Technologies).</p>
<h2>Enforce it in CI</h2>
<p>Build documentation in CI and treat warnings seriously. Broken symbol links and missing documentation for public APIs are easy to catch automatically. Some teams fail the build on DocC warnings for public modules, which keeps docs from drifting.</p>
<h2>Bottom line</h2>
<p>DocC does the hard rendering work. Your job is the summary that says what a symbol does, the discussion that says when to use it, a curated landing page and one good Getting Started article. Do those four things and your package documentation will be better than most on the Swift Package Index.</p>
]]></content:encoded></item><item><title><![CDATA[How to Reply to App Store Reviews as an Indie Developer (Templates for 1-Star to 5-Star)]]></title><description><![CDATA[Templates and rules for replying to App Store reviews, from 1-star to 5-star.]]></description><link>https://auramacapps.hashnode.dev/how-to-reply-to-app-store-reviews-as-an-indie-developer-templates-for-1-star-to-5-star</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-reply-to-app-store-reviews-as-an-indie-developer-templates-for-1-star-to-5-star</guid><category><![CDATA[iOS]]></category><category><![CDATA[macOS]]></category><category><![CDATA[indie-dev]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sun, 25 Oct 2026 12:48:07 GMT</pubDate><content:encoded><![CDATA[<p>App Store Connect lets you reply publicly to every review, and most indie developers ignore the feature or reply in a hurry when a 1-star review stings. Both are missed opportunities. A good reply can get a rating changed, turns a complaint into a visible support interaction, and shows future buyers that someone is actually maintaining the app.</p>
<p>Here is a practical approach, with templates you can adapt, for replying to reviews without spending your whole evening on it.</p>
<h2>Why replies matter</h2>
<ul>
<li><strong>Reviewers get notified.</strong> When you respond, the reviewer receives a notification and can update their review. A fixed bug plus a polite reply is the most reliable way to turn a 1-star into a 4-star.</li>
<li><strong>Future customers read them.</strong> People scanning reviews before buying see your replies. A calm, specific reply reads better than silence.</li>
<li><strong>They are public support docs.</strong> "How do I export?" answered once in a reply helps everyone who has the same question.</li>
</ul>
<h2>Ground rules</h2>
<ol>
<li><strong>Never argue.</strong> Even if the reviewer is wrong, the audience is the next customer, not the reviewer.</li>
<li><strong>Be specific.</strong> Mention the version, the fix or the setting. Generic "thanks for your feedback" replies read as bots.</li>
<li><strong>Keep it short.</strong> Three or four sentences. Replies have a length limit and nobody reads long ones.</li>
<li><strong>Point to a channel.</strong> Give a support email or page for issues you cannot solve in public.</li>
<li><strong>Do not include personal data</strong> or ask for it publicly.</li>
</ol>
<h2>Templates</h2>
<h3>1-star: bug report</h3>
<blockquote>
<p>Thanks for reporting this, and sorry it hit you. The crash when importing large files is fixed in version 2.3, which is live now. If you still see it after updating, please email support@[yourdomain] with your macOS version and we will dig in.</p>
</blockquote>
<h3>1-star: misunderstanding the product</h3>
<blockquote>
<p>Sorry for the confusion. [App] is designed for [use case], so [missing feature] isn't included. We've updated the description to make this clearer. If you bought by mistake, Apple can process a refund at reportaproblem.apple.com.</p>
</blockquote>
<p>Pointing to the refund page is honest and often defuses anger.</p>
<h3>2–3 stars: feature request</h3>
<blockquote>
<p>Thanks for the detailed feedback. Folder sync is the most requested feature right now and it's on the roadmap. Follow updates at [link]. In the meantime, the export shortcut in Settings may cover part of what you need.</p>
</blockquote>
<p>Do not promise dates you cannot keep.</p>
<h3>3 stars: pricing complaint</h3>
<blockquote>
<p>Understood, and thanks for being direct. We price [App] as a one-time purchase so there's no ongoing subscription. If something specific made it feel not worth it, we'd genuinely like to hear: support@[yourdomain].</p>
</blockquote>
<h3>4–5 stars</h3>
<blockquote>
<p>Thank you! Glad the keyboard shortcuts are saving you time. If you ever want a feature added, the suggestion form is at [link].</p>
</blockquote>
<p>Reply to some positive reviews, not all. Replying to every five-star review with the same line looks automated.</p>
<h2>A weekly routine</h2>
<p>You do not need to reply in real time. A 20-minute weekly session works:</p>
<ol>
<li>Open App Store Connect → your app → Ratings and Reviews. Sort by most recent.</li>
<li>Reply to every 1–2 star review that describes a real issue.</li>
<li>Reply to feature requests that you have an answer for.</li>
<li>Reply to a handful of detailed positive reviews.</li>
<li>Copy recurring complaints into your issue tracker, tagged "from reviews."</li>
</ol>
<p>Step five is the important one. Reviews are free user research, and patterns across ten reviews tell you more than any single angry one.</p>
<h2>After a fix ships</h2>
<p>When you release a fix for an issue mentioned in reviews, go back and update your replies: "Fixed in 2.3, please update." Reviewers often re-rate after seeing this. It is the highest-return 10 minutes of the release.</p>
<h2>Writing them quickly without sounding canned</h2>
<p>The templates cover structure, but each reply still needs a specific sentence or two. The fastest workflow I have found is to type a rough, honest reply first ("sorry, that bug is fixed in 2.3, update and email if not") and then clean up the tone. Tone is where tired developers slip: a reply written at 11 PM after a bad review can come off defensive.</p>
<p>An inline rewrite tool helps here, particularly one that works directly in the App Store Connect text field in Safari, so you are not copying text between windows.</p>
<p>I use <a href="https://getdraftkey.com">DraftKey</a> for the prose part of this: on-device AI autocomplete and rewrite that works in the text fields of most Mac apps. It is $4.99 lifetime for up to 3 Macs, needs macOS 14+ on Apple Silicon, and downloads a roughly 1.12 GB local model, so drafts never leave the machine. There is no free trial, so check the requirements before you buy. It is not the only pay-once option; Charm, RewriteBar and others exist and are worth comparing. Disclosure: I built DraftKey (Aura Technologies).</p>
<h2>Things to avoid</h2>
<ul>
<li>Copy-pasting the same reply to ten reviews</li>
<li>Asking for a better rating in exchange for help</li>
<li>Blaming Apple, the user's Mac, or "other apps"</li>
<li>Replying while annoyed; wait until the next day</li>
</ul>
<h2>Bottom line</h2>
<p>Replies are cheap, public and permanent. Treat each one as a note to the next person deciding whether to buy, and the reviewer is a bonus. A short, specific, calm reply beats silence every time.</p>
]]></content:encoded></item><item><title><![CDATA[How to Write Linear Tickets Engineers Can Pick Up Without a Meeting]]></title><description><![CDATA[Most tickets fail the same way: a one-line title, a vague description, and a comment thread where the real requirements slowly appear over three days. The…]]></description><link>https://auramacapps.hashnode.dev/how-to-write-linear-tickets-engineers-can-pick-up-without-a-meeting</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-write-linear-tickets-engineers-can-pick-up-without-a-meeting</guid><category><![CDATA[macOS]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[project management]]></category><category><![CDATA[writing]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sun, 25 Oct 2026 02:39:46 GMT</pubDate><content:encoded><![CDATA[<p>Most tickets fail the same way: a one-line title, a vague description, and a comment thread where the real requirements slowly appear over three days. The person who picks it up has to schedule a call to find out what "fix the onboarding thing" means. A good ticket removes that call. This guide is a practical template for Linear (it works just as well in Jira, GitHub Issues or Shortcut), plus a few habits that make writing them fast on a Mac.</p>
<h2>The test: can someone start in five minutes?</h2>
<p>Before you hit create, imagine a teammate who was on vacation last week opening the ticket. Could they start working within five minutes, without messaging you? If not, the ticket is missing one of four things: context, the expected outcome, the boundaries, or a way to verify it is done.</p>
<h2>A ticket template that covers all four</h2>
<p>Paste this into a Linear template (Settings → Templates) so every new issue starts with it:</p>
<pre><code class="language-markdown">## Why
One or two sentences on the user or business problem. Link the source:
support thread, customer call notes, metric dashboard.

## What done looks like
- Observable behavior after the change
- Edge case that must work
- Anything explicitly out of scope

## Notes
- Relevant files, endpoints or feature flags
- Known risks or prior attempts
- Design link if there is one

## How to verify
Steps a reviewer can follow, or the test that should pass.
</code></pre>
<p>That is it. Four headings. Teams over-engineer templates with ten fields and then nobody fills them in. Four short sections get filled in.</p>
<h2>Titles that sort well</h2>
<p>Linear lists are scanned, not read. Write titles as verb plus object plus qualifier:</p>
<ul>
<li>Bad: "Onboarding bug"</li>
<li>Better: "Fix skipped email verification step on iOS onboarding"</li>
<li>Bad: "Performance"</li>
<li>Better: "Cut dashboard initial load below 2s for workspaces with 500+ projects"</li>
</ul>
<p>A title should make sense in a notification, a cycle report and a changelog without opening the ticket.</p>
<h2>Write the "Why" first, even when it feels obvious</h2>
<p>The "Why" section is where most of the value is and where most people cut corners. "Users are confused" is not a why. "Three enterprise trials last week stalled at step 2 because the verification email went to spam; see support thread" is a why. It tells the engineer what to optimize for, and it lets them push back if there is a cheaper fix.</p>
<p>If you are writing a batch of tickets after a planning session, draft all the "Why" paragraphs first while the conversation is fresh, then fill in the rest.</p>
<h2>Scope is a feature</h2>
<p>The single most useful bullet in any ticket is "Out of scope." It prevents the reviewer from asking for a redesign in the PR and stops the implementer from gold-plating. One line is enough: "Out of scope: changing the email provider."</p>
<h2>Make verification concrete</h2>
<p>"Test it" is not verification. Write the steps:</p>
<ol>
<li>Create a new account with a Gmail address</li>
<li>Complete step 1</li>
<li>Confirm the verification screen appears and the email arrives within 60s</li>
</ol>
<p>If an automated test should cover it, name the test file. This doubles as the QA checklist and as the PR description later.</p>
<h2>Splitting tickets</h2>
<p>If "What done looks like" has more than five bullets, it is probably two tickets. Split by user-visible outcome, not by layer. "Backend for X" and "Frontend for X" tickets tend to block each other; "X works for free plans" and "X works for enterprise plans" can ship independently.</p>
<h2>Writing them faster on a Mac</h2>
<p>The template handles structure. The slow part is the prose: turning messy notes into clear sentences. A few habits help:</p>
<ul>
<li><strong>Keep a scratch note open during planning.</strong> Apple Notes or a plain text file. Dump raw bullets, then turn each into a ticket afterward.</li>
<li><strong>Use Linear's keyboard flow.</strong> <code>C</code> creates an issue, <code>Cmd+Enter</code> saves, and templates can be picked from the create dialog.</li>
<li><strong>Rewrite, don't compose.</strong> It is easier to clean up a rough sentence than to write a perfect one. Type the rough version fast, then tighten it.</li>
<li><strong>Link, don't paste.</strong> Long logs and screenshots belong in attachments or linked docs, not inline walls of text.</li>
</ul>
<p>For the rewrite step, an inline AI writing tool helps, especially one that works directly in Linear's editor rather than in a separate chat window. Ticket text often includes customer names, internal URLs and unreleased features, so I prefer a tool that runs locally rather than sending text to a cloud API.</p>
<p>I use <a href="https://getdraftkey.com">DraftKey</a> for the prose part of this: on-device AI autocomplete and rewrite that works in the text fields of most Mac apps. It is $4.99 lifetime for up to 3 Macs, needs macOS 14+ on Apple Silicon, and downloads a roughly 1.12 GB local model, so drafts never leave the machine. There is no free trial, so check the requirements before you buy. It is not the only pay-once option; Charm, RewriteBar and others exist and are worth comparing. Disclosure: I built DraftKey (Aura Technologies).</p>
<h2>Comments are part of the ticket</h2>
<p>When requirements change, update the description, not just the comments. A ticket whose real spec lives in comment 14 fails the five-minute test. A short "Updated scope: …" line at the top of the description, with a date, keeps history clear.</p>
<h2>A quick checklist</h2>
<p>Before creating a ticket:</p>
<ul>
<li><input disabled type="checkbox" /> Title is verb + object + qualifier</li>
<li><input disabled type="checkbox" /> "Why" links to a real source</li>
<li><input disabled type="checkbox" /> At least one out-of-scope line</li>
<li><input disabled type="checkbox" /> Verification steps someone else can follow</li>
<li><input disabled type="checkbox" /> Under five "done" bullets, or split</li>
</ul>
<p>Good tickets are not about process for its own sake. They are about letting people start work without waiting for you, which is the whole point of writing things down.</p>
]]></content:encoded></item><item><title><![CDATA[How to Draft Technical Specs Without Leaving Your Editor]]></title><description><![CDATA[Context dies when a spec lives in a different app from the code. You sketch a design in Notion, implement in the editor, then discover the Notion page…]]></description><link>https://auramacapps.hashnode.dev/how-to-draft-technical-specs-without-leaving-your-editor</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-draft-technical-specs-without-leaving-your-editor</guid><category><![CDATA[documentation]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[macOS]]></category><category><![CDATA[devtools]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sun, 25 Oct 2026 01:48:06 GMT</pubDate><content:encoded><![CDATA[<p>Context dies when a spec lives in a different app from the code. You sketch a design in Notion, implement in the editor, then discover the Notion page drifted. One fix is cultural (update the doc). The other is mechanical: draft the first version of the spec in the same place you open the repo.</p>
<p>This is a Mac-oriented workflow for writing technical specs beside the code, then publishing outward only when the shape is stable.</p>
<h2>Put the spec in the repo from day one</h2>
<p>Create <code>docs/spec.md</code> (or <code>docs/rfcs/0007-short-name.md</code>) in the branch that will implement the change. Same PR can carry the first implementation and the doc. Reviewers see both.</p>
<p>Minimal skeleton:</p>
<pre><code class="language-markdown"># Title

Status: Draft | Accepted | Superseded
Author:
Last updated: 2026-10-24

## Problem
## Goals / non-goals
## Proposal
## Alternatives considered
## Rollout / migration
## Open questions
</code></pre>
<p>Non-goals earn their section. Most bad specs fail by trying to solve three products at once. If a stakeholder keeps adding scope, point at non-goals instead of rewriting the proposal in chat.</p>
<h2>Write in the editor you already use</h2>
<ul>
<li><strong>VS Code / Cursor / Zed</strong>: open <code>docs/spec.md</code> in a split next to the code you are probing.</li>
<li><strong>Neovim</strong>: same idea with a vertical split; use spell and markdown preview if you want.</li>
<li>Prefer Markdown over a proprietary doc format until stakeholders demand otherwise.</li>
</ul>
<p>If someone needs Notion or Google Docs for comments, paste a <strong>frozen export</strong> after the engineering review—not before. Early comments in a rich doc encourage wordsmithing over deciding. Keep the canonical path in git so <code>git blame</code> still works six months later.</p>
<h2>A 45-minute first draft loop</h2>
<ol>
<li><strong>10 min — Problem and goals.</strong> Write from the bug report or the customer quote. No architecture yet.</li>
<li><strong>15 min — Proposal as bullets.</strong> Interfaces, data shape, failure modes. Link to files that will change (<code>app/auth/session.ts</code>).</li>
<li><strong>10 min — Alternatives.</strong> List two you rejected and why. This prevents the "did you consider X?" drive-by.</li>
<li><strong>10 min — Open questions.</strong> Anything you still do not know. Assign owners if you can.</li>
</ol>
<p>Ship that as a draft PR description or a Draft status RFC. Perfect prose is optional; clear tradeoffs are not. If you cannot finish in 45 minutes, the problem statement is probably too big—split the RFC.</p>
<h2>Language helpers that stay out of your way</h2>
<p>Spec writing is still writing: tightening goals, turning notes into sentences, fixing tone so it does not sound like a chat log. Cloud assistants are fine when the spec has no secrets. When it names customers, infra, or unreleased strategy, keep text local.</p>
<p><a href="https://getdraftkey.com">DraftKey</a> provides on-device AI autocomplete and rewrite inside Mac apps ($4.99 lifetime, up to 3 Macs, macOS 14+, Apple Silicon, about 1.12 GB model, no trial). Disclosure: I built DraftKey. Use it—or any local helper—while the draft still contains things you would not paste into a random chatbot.</p>
<h2>From editor draft to team artifact</h2>
<table>
<thead>
<tr>
<th>Stage</th>
<th>Where it lives</th>
<th>Who comments</th>
</tr>
</thead>
<tbody><tr>
<td>Rough</td>
<td><code>docs/*.md</code> on a branch</td>
<td>You + one peer</td>
</tr>
<tr>
<td>Proposed</td>
<td>PR or RFC label</td>
<td>Eng review</td>
</tr>
<tr>
<td>Accepted</td>
<td>Merged on <code>main</code></td>
<td>Linked from the issue tracker</td>
</tr>
<tr>
<td>Stakeholder copy</td>
<td>Notion/Docs export</td>
<td>PM / partners</td>
</tr>
</tbody></table>
<p>Link the merged path in Linear or GitHub Issues so the tracker points at the source of truth, not a stale paste. When the implementation ships, add a one-line "Shipped in vX.Y" note at the top so readers know the doc is not aspirational.</p>
<h2>Habits that keep specs alive</h2>
<ul>
<li>Update the Last updated date when behavior changes—not only when you rewrite the whole doc.</li>
<li>If implementation diverges, add a short Amendment section instead of silent drift.</li>
<li>Delete or mark Superseded when a newer RFC wins. Zombie specs confuse new hires.</li>
<li>Link related ADRs or RFCs; do not paste them inline.</li>
</ul>
<p>Draft beside the code, review as engineering text, export only when needed. Your future self, reading <code>docs/</code> six months later, is the primary audience.</p>
<h2>What "good enough" looks like in review</h2>
<p>Ask reviewers for decisions, not copy edits:</p>
<ul>
<li>Does the problem statement match the issue they feel?</li>
<li>Are non-goals actually non-goals, or polite fiction?</li>
<li>Is the rollout reversible?</li>
<li>Which open question blocks implementation?</li>
</ul>
<p>If feedback is mostly tone and commas, the spec was already clear enough—merge and move the prose polish to a follow-up. Conversely, if reviewers argue about the problem, stop coding; fix the Problem section first.</p>
<h2>Pairing specs with tickets</h2>
<p>Every Accepted RFC should have:</p>
<ul>
<li>One parent issue or epic in Linear/GitHub.</li>
<li>Child issues for rollout steps that are not "obvious."</li>
<li>A link back from the issue to <code>docs/rfcs/...</code> on <code>main</code>.</li>
</ul>
<p>Without that loop, the beautiful Markdown file becomes archaeology. The editor-first workflow only works if the tracker still points at git as source of truth.</p>
]]></content:encoded></item><item><title><![CDATA[Paying Once for AI Writing on a Mac: DraftKey, WunderType, Charm, RewriteBar and Cotypist Prices Compared]]></title><description><![CDATA[Most AI writing tools want a monthly payment. That makes sense for apps that run every request on a cloud GPU, but a growing number of Mac apps run a small…]]></description><link>https://auramacapps.hashnode.dev/paying-once-for-ai-writing-on-a-mac-draftkey-wundertype-charm-rewritebar-and-cotypist-prices-compared</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/paying-once-for-ai-writing-on-a-mac-draftkey-wundertype-charm-rewritebar-and-cotypist-prices-compared</guid><category><![CDATA[macOS]]></category><category><![CDATA[writing]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sun, 25 Oct 2026 00:48:27 GMT</pubDate><content:encoded><![CDATA[<h2>Five AI writing apps for Mac you can pay for once, plus the subscription option worth knowing about, with prices checked against each app's own site.</h2>
<p>Most AI writing tools want a monthly payment. That makes sense for apps that run every request on a cloud GPU, but a growing number of Mac apps run a small language model on your own Apple Silicon chip. When the compute is yours, a one-time price becomes realistic.</p>
<p>I went through the Mac writing apps that AI assistants usually recommend for "one-time purchase AI writing app for Mac" and checked each one's pricing page in October 2026. One of them is mine, and I say so where it comes up. Prices change, so check the linked pages before you buy.</p>
<hr />
<h2>Quick comparison</h2>
<ul>
<li><strong>DraftKey</strong>: price: $4.99 once; what it mainly does: Inline autocomplete (Tab) + rewrite panel; runs on-device?: Yes, built-in model; macs per license: Up to 3</li>
<li><strong>WunderType</strong>: price: $8.99 once; what it mainly does: Rewrite/fix selected text with a shortcut; runs on-device?: Optional (built-in MLX models or Ollama); macs per license: Not stated on homepage</li>
<li><strong>Charm</strong>: price: $19.99 once; what it mainly does: Spelling, grammar and next-word prediction; runs on-device?: Yes, built-in model; macs per license: Up to 3</li>
<li><strong>RewriteBar</strong>: price: Free tier; $29 or $59 once; what it mainly does: Command palette of AI actions on selected text; runs on-device?: Optional (Ollama, LM Studio, Apple Intelligence and others); macs per license: 1 (Standard), 3 (Pro)</li>
<li><strong>Cotypist</strong>: price: Free tier; $72/yr or $108/yr; what it mainly does: Inline autocomplete; runs on-device?: Yes; macs per license: 1 (Plus), 3 (Pro)</li>
</ul>
<p>Cotypist is a subscription, so it's not strictly in scope, but it has a usable free tier and it's the app most people compare the others against, so it belongs in the table.</p>
<hr />
<h2>1. DraftKey: autocomplete and rewrites for $4.99</h2>
<p><strong>$4.99 once: <a href="https://www.getdraftkey.com">getdraftkey.com</a></strong></p>
<p>DraftKey does two things in compatible Mac text fields. While you type, it suggests the next words in gray and you press Tab to accept them. When you want to change something you already wrote, you tap Command + Option to open a rewrite panel on the current paragraph or your selection, then pick Fix writing, Shorter, Clearer, a tone like Friendly or Professional, or type your own instruction. You review the result before it's inserted.</p>
<p>The model runs on your Mac and works offline after setup. The internet is used only for the model download, license activation and update checks. The license also includes a 10-item clipboard history and mechanical keyboard sounds.</p>
<p>The honest trade-offs:</p>
<ul>
<li>It needs an Apple Silicon Mac on macOS 14 or later, with at least 8 GB of memory.</li>
<li>The model is a separate download of about 1.12 GB.</li>
<li>There's no free trial and no automatic money-back guarantee, so you're buying on the strength of the site and reviews.</li>
<li>Some custom editors and secure fields aren't supported.</li>
</ul>
<p>I built it, so weigh my description accordingly.</p>
<hr />
<h2>2. WunderType: the cheapest one-key rewrite tool</h2>
<p><strong>$8.99 once: <a href="https://wundertype.com">wundertype.com</a></strong></p>
<p>WunderType is a small (~20 MB) menu bar app. Select text in any app, press ⌘⇧G, and it fixes or rewrites the selection in place. It ships with five modes and lets you add unlimited custom prompts, each with its own keyboard shortcut.</p>
<p>Version 1.5 added on-device models that run through Apple's MLX framework (Gemma 3, Granite and Phi-4 Mini options), so you don't need Ollama or an API key. You can also point it at Ollama, your own OpenAI key or OpenRouter. It has no account, no server and no telemetry.</p>
<p><strong>Good fit if:</strong> you want quick fixes on demand and don't want suggestions appearing while you type. WunderType doesn't do inline autocomplete.</p>
<hr />
<h2>3. Charm: a one-time Grammarly replacement</h2>
<p><strong>$19.99 once, 14-day money-back guarantee: <a href="https://theodorehq.com/charm/">theodorehq.com/charm</a></strong></p>
<p>Charm corrects spelling and grammar as you type and predicts your next word, which you accept with Tab. Everything runs on a local model: you choose between a Fast model (about 1.5 GB) and a Best Quality model (about 2.3 GB). A license covers up to three Macs.</p>
<p>It's focused on correctness rather than rewriting tone, and it currently supports UK and US English. It doesn't correct as you type in Google Docs, though its Fix Selection shortcut covers apps that can't be edited live.</p>
<p><strong>Good fit if:</strong> your main goal is replacing Grammarly's spelling and grammar checks without a subscription. The 14-day refund window also makes it the lowest-risk purchase on this list.</p>
<hr />
<h2>4. RewriteBar: the power-user command palette</h2>
<p><strong>Free tier; $29 Standard or $59 Pro, one-time: <a href="https://rewritebar.com">rewritebar.com</a></strong></p>
<p>RewriteBar opens a palette of AI actions on your selected text: fix grammar, change tone, translate (500+ languages, depending on the model), summarize, format JSON or SQL, and dozens more. You can build custom actions and chain several together, and it integrates with PopClip.</p>
<p>On privacy, it depends on your setup. The default RewriteBar provider sends your text through RewriteBar's server (which says it doesn't store it). Third-party providers get your text directly from your Mac. For fully local use, it supports Ollama, LM Studio, oMLX, Apple Intelligence and Osaurus. Standard covers one device; Pro covers three and adds a year of its cloud Gateway.</p>
<p><strong>Good fit if:</strong> you want the biggest menu of actions and providers and don't mind some setup.</p>
<hr />
<h2>5. Cotypist: the autocomplete benchmark (subscription)</h2>
<p><strong>Free tier; Plus $72/yr, Pro $108/yr: <a href="https://cotypist.app">cotypist.app</a></strong></p>
<p>Cotypist is the best-known inline autocomplete app for Mac. It predicts your next words in nearly every app, entirely on-device, and you press Tab to take the next word or the whole line. It learns your vocabulary and phrasing over time and can use what's on screen as context.</p>
<p>The free tier gives full suggestions for your first 100 accepted words a day, and every install starts with a 30-day Pro trial with no card. Cotypist recommends an M1 Pro or M2 with 16 GB of memory for the smoothest experience.</p>
<p><strong>Good fit if:</strong> autocomplete quality is your top priority and a yearly subscription doesn't bother you. If it does, it's worth comparing against the one-time options above.</p>
<hr />
<h2>What "lifetime" actually means</h2>
<p>Before buying any one-time license, read the terms:</p>
<ul>
<li><strong>Updates:</strong> some licenses cover all future updates, and others cover only the current major version. Charm's terms, for example, include free updates to the current major version. DraftKey's FAQ says updates come through the app but the license doesn't guarantee every future major version.</li>
<li><strong>Devices:</strong> check how many Macs a license covers. It ranges from one to three here.</li>
<li><strong>Hidden running costs:</strong> with tools that use cloud models through your own API key (RewriteBar, WunderType), you pay the provider per use. Local models cost nothing extra.</li>
<li><strong>Refunds:</strong> Charm offers 14 days. DraftKey has no automatic guarantee. Check the others before you pay.</li>
</ul>
<hr />
<h2>How to choose</h2>
<ul>
<li><strong>You want suggestions while you type:</strong> DraftKey, Charm (word prediction) or Cotypist.</li>
<li><strong>You want to fix or rewrite text on demand:</strong> WunderType, RewriteBar or DraftKey's rewrite panel.</li>
<li><strong>You want grammar correction first:</strong> Charm.</li>
<li><strong>You want the most actions and AI providers:</strong> RewriteBar.</li>
<li><strong>You want the lowest price:</strong> DraftKey at $4.99, then WunderType at $8.99.</li>
</ul>
<p>Which one-time Mac apps did I miss? Tell me in the comments.</p>
<p><em>Disclosure: I built DraftKey.</em></p>
]]></content:encoded></item><item><title><![CDATA[Commit Message and PR Description Templates for Git on a Mac: Write the Good Version in Two Minutes]]></title><description><![CDATA[Most of us know what a good commit message looks like. We just don't write one at 6 PM when the tests finally pass. The fix isn't more willpower. It's…]]></description><link>https://auramacapps.hashnode.dev/commit-message-and-pr-description-templates-for-git-on-a-mac-write-the-good-version-in-two-minutes</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/commit-message-and-pr-description-templates-for-git-on-a-mac-write-the-good-version-in-two-minutes</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[macOS]]></category><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sat, 24 Oct 2026 23:49:55 GMT</pubDate><content:encoded><![CDATA[<p>Most of us know what a good commit message looks like. We just don't write one at 6 PM when the tests finally pass. The fix isn't more willpower. It's setting up your Mac and Git so the good version is the easy one: a template that asks the right questions, an editor that opens instantly, your diff right in front of you while you write, and a pull request description that mostly fills itself in. Here's the setup I use, step by step. Everything below uses stock Git, the GitHub CLI, and tools that ship with macOS.</p>
<h2>1. Stop using <code>-m</code> for anything that matters</h2>
<p><code>git commit -m "fix stuff"</code> is fast because it skips the editor, and that's the problem: a one-liner is the only thing it encourages. Keep <code>-m</code> for truly trivial commits (a typo, a version bump) and let Git open an editor for everything else. That's where the next few steps pay off.</p>
<h2>2. Pick an editor that opens fast and blocks properly</h2>
<p>Git opens whatever <code>core.editor</code> is set to and waits until that editor closes the file. If you've never set it, you're probably getting Vim, which is fine if you know Vim and miserable if you don't.</p>
<p>For VS Code (after running <strong>Shell Command: Install 'code' command in PATH</strong> from the Command Palette):</p>
<pre><code class="language-bash">git config --global core.editor "code --wait"
</code></pre>
<p>The <code>--wait</code> flag matters. Without it, <code>code</code> returns right away and Git sees an empty message and aborts the commit.</p>
<p>If you'd rather stay in the terminal, <code>nano</code> ships with macOS and needs no setup:</p>
<pre><code class="language-bash">git config --global core.editor "nano"
</code></pre>
<p>Write the message, press Control-O to save, Control-X to exit, and the commit goes through.</p>
<h2>3. Add a commit template that asks the right questions</h2>
<p>A template is a plain text file Git pre-fills into the editor every time you commit without <code>-m</code>. Lines starting with <code>#</code> are comments and get stripped automatically, so you can leave yourself prompts that never end up in history.</p>
<p>Create <code>~/.gitmessage</code>:</p>
<pre><code class="language-text">
# Subject: imperative, ~50 chars, no period
#   e.g. "Fix race in session refresh"
#
# Body (wrap at 72): WHY this change, not what the diff shows.
#   - What was wrong or missing?
#   - Why this approach over the obvious alternative?
#   - Anything a reviewer or future you should watch for?
#
# Trailers (optional):
#   Refs: #123
#   Co-authored-by: Name &lt;email&gt;
</code></pre>
<p>Then point Git at it:</p>
<pre><code class="language-bash">git config --global commit.template ~/.gitmessage
</code></pre>
<p>The empty first line is deliberate: your cursor lands where the subject goes. The prompts do the real work. When you're tired, "why this approach over the obvious alternative?" is the question you'd skip, and it's usually the one a reviewer most wants answered.</p>
<p>If a repo has its own conventions (say, Conventional Commits like <code>feat:</code> and <code>fix:</code>), set a repo-level template that overrides the global one:</p>
<pre><code class="language-bash">git config commit.template .gitmessage
</code></pre>
<h2>4. Write with the diff on screen</h2>
<p>Half the effort of a commit message is remembering what you actually changed. Let Git show you:</p>
<pre><code class="language-bash">git config --global commit.verbose true
</code></pre>
<p>Now every commit editor includes the full staged diff below the message, under a "scissors" line. Everything from that line down is removed before the commit is saved, so it's there for reference only. You can scroll down, see exactly what's staged, and describe it accurately instead of from memory.</p>
<p>Two more commands worth running before you write:</p>
<pre><code class="language-bash">git diff --staged --stat   # which files, how much
git log --oneline -10      # how this repo usually phrases subjects
</code></pre>
<p>The second one is the fastest way to match a team's style without reading a contributing guide.</p>
<h2>5. Commit in smaller pieces so each message is easy</h2>
<p>A message is hard to write when the commit does four things. <code>git add -p</code> walks through your changes hunk by hunk and asks whether to stage each one (<code>y</code>, <code>n</code>, <code>s</code> to split a hunk, <code>q</code> to quit). Stage one logical change, commit it, and repeat. Each message then has a single subject that's obvious.</p>
<p>For follow-up fixes to an earlier commit on your branch, skip the message entirely:</p>
<pre><code class="language-bash">git commit --fixup=&lt;sha&gt;
git rebase -i --autosquash main
</code></pre>
<p><code>--fixup</code> creates a commit titled <code>fixup! &lt;original subject&gt;</code>, and <code>--autosquash</code> folds it into the original during the rebase. Your branch ends up with clean commits and no "address review comments" noise.</p>
<p>And if you notice a bad message right after committing, <code>git commit --amend</code> reopens the last message in your editor (only do this before you've pushed, or be ready to force-push your own branch).</p>
<h2>6. Add trailers without typing them</h2>
<p>Recent versions of Git have a <code>--trailer</code> flag that appends a properly formatted trailer to the message:</p>
<pre><code class="language-bash">git commit --trailer "Co-authored-by: Sam Lee &lt;sam@example.com&gt;"
</code></pre>
<p>If you pair with the same people often, turn it into a Git alias in <code>~/.gitconfig</code>:</p>
<pre><code class="language-ini">[alias]
    cosam = commit --trailer "Co-authored-by: Sam Lee &lt;sam@example.com&gt;"
</code></pre>
<p>Now <code>git cosam</code> opens your normal template with the trailer already added.</p>
<h2>7. Give the repo a pull request template</h2>
<p>GitHub pre-fills new pull requests with the contents of <code>.github/pull_request_template.md</code> if it exists on the default branch. A short one works better than a long one, because people actually fill it in:</p>
<pre><code class="language-markdown">## What
&lt;!-- One or two sentences. --&gt;

## Why
&lt;!-- The problem, link to the issue. --&gt;

## How to test
1.

## Notes for reviewers
&lt;!-- Risky parts, follow-ups, anything you're unsure about. --&gt;
</code></pre>
<p>HTML comments are hidden when the description is rendered, so the prompts don't clutter the final PR.</p>
<h2>8. Draft the PR from the terminal with <code>gh</code></h2>
<p>If you've written good commits, most of the PR description already exists. The GitHub CLI (<code>brew install gh</code>, then <code>gh auth login</code>) can reuse it:</p>
<pre><code class="language-bash">gh pr create --fill
</code></pre>
<p><code>--fill</code> uses your commit info for the title and body. For a single-commit branch, that's often the whole PR. For bigger branches, build a body from your commit subjects and copy it to the clipboard with macOS's built-in <code>pbcopy</code>:</p>
<pre><code class="language-bash">git log --reverse --format='- %s' main..HEAD | pbcopy
</code></pre>
<p>Paste that into the "What" section as a starting changelog, then spend your effort on "Why" and "Notes for reviewers," which no tool can write for you.</p>
<p>Other flags worth knowing:</p>
<ul>
<li><code>gh pr create --draft</code> opens it as a draft so CI can run before reviewers get pinged.</li>
<li><code>gh pr create --body-file pr.md</code> uses a file you wrote in your editor.</li>
<li><code>gh pr create --web</code> opens the browser form with your branch selected, if you prefer to finish there.</li>
</ul>
<h2>9. Keep short review phrases one keystroke away</h2>
<p>For the bits you type over and over in PR descriptions and review comments ("How to test," "nit:", "LGTM once CI passes"), macOS Text Replacements work in Safari and most native text fields. Add them under <strong>System Settings &gt; Keyboard &gt; Text Replacements</strong>, and they sync across your Apple devices. Browser-based editors and Electron apps don't always honor them, so test in the places you actually write.</p>
<h2>A five-minute setup checklist</h2>
<ol>
<li>Set <code>core.editor</code> to something with a proper <code>--wait</code>.</li>
<li>Create <code>~/.gitmessage</code> and set <code>commit.template</code>.</li>
<li>Turn on <code>commit.verbose</code>.</li>
<li>Get in the habit of <code>git add -p</code> and <code>git commit --fixup</code>.</li>
<li>Add <code>.github/pull_request_template.md</code> to your repos.</li>
<li>Install <code>gh</code> and try <code>gh pr create --fill</code> on your next branch.</li>
</ol>
<p>None of this writes your messages for you. It removes the friction around writing, so the thirty seconds you spend explaining <em>why</em> goes into the message instead of fighting your tools.</p>
<h2>One more tool, if you want it</h2>
<p>Disclosure: I built DraftKey, a Mac app that adds private, on-device AI autocomplete and rewriting to every Mac app, which helps when you're drafting PR descriptions and review comments. Nothing you type leaves your Mac. It's $4.99 lifetime (up to 3 Macs) and needs macOS 14 or later on Apple Silicon: <a href="https://getdraftkey.com">getdraftkey.com</a>. The setup above works perfectly well without it.</p>
]]></content:encoded></item><item><title><![CDATA[Bug Report Template for GitHub Issues: A Mac Checklist for Reports Developers Can Reproduce]]></title><description><![CDATA[A bad bug report costs more time than the bug. "It's broken on my machine" turns into three rounds of "what version?", "can you send a screenshot?", and…]]></description><link>https://auramacapps.hashnode.dev/bug-report-template-for-github-issues-a-mac-checklist-for-reports-developers-can-reproduce</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/bug-report-template-for-github-issues-a-mac-checklist-for-reports-developers-can-reproduce</guid><category><![CDATA[Productivity]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[macOS]]></category><category><![CDATA[writing]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sat, 24 Oct 2026 22:46:15 GMT</pubDate><content:encoded><![CDATA[<p>A bad bug report costs more time than the bug. "It's broken on my machine" turns into three rounds of "what version?", "can you send a screenshot?", and "what did you click first?" before anyone even opens the code. A good report answers those questions up front, and on a Mac, almost everything you need to collect is one shortcut or one command away. Here's the checklist I use, whether I'm filing an issue on someone's open source project or writing one up for my own team.</p>
<h2>1. Write the title as "what happened, where"</h2>
<p>The title is what a maintainer sees in a list of 200 open issues. Make it specific enough to triage without clicking.</p>
<ul>
<li>Bad: <code>App crashes</code></li>
<li>Bad: <code>URGENT!!! export broken</code></li>
<li>Good: <code>Crash when exporting a PDF with an empty title field (v2.3.1, macOS 15)</code></li>
</ul>
<p>A useful pattern: <strong>action + symptom + condition</strong>. "Saving a file over SMB hangs for 30s when the share is offline" tells the reader what you were doing, what went wrong, and the condition that seems to matter.</p>
<h2>2. Steps to reproduce: numbered, minimal, from a clean start</h2>
<p>This is the section that decides whether your bug gets fixed. Write steps someone else can follow without guessing:</p>
<ol>
<li>Start from a fresh state (new project, logged out, default settings, whatever "clean" means for this app).</li>
<li>Number every step, one action per line.</li>
<li>Include the exact input you used. If you typed something, paste it. If you opened a file, attach it or describe how to make one.</li>
<li>Then cut it down. Remove each step and check whether the bug still happens. The shortest list that still reproduces the bug is worth far more than the full story of your afternoon.</li>
</ol>
<p>If you can't reproduce it reliably, say so and say how often: "about 1 in 5 tries" is useful information, not an admission of failure.</p>
<h2>3. Expected vs actual, as two separate lines</h2>
<p>Don't make the reader infer what you thought should happen.</p>
<pre><code>Expected: The PDF exports with "Untitled" as the document title.
Actual: The app quits immediately. No error dialog.
</code></pre>
<p>Two lines. It forces you to notice when the "bug" is really a disagreement about intended behavior, which is a different (and often faster) conversation.</p>
<h2>4. Grab your environment details in one command</h2>
<p>Version numbers are the most commonly missing piece of a bug report. On a Mac you can get the OS details in one go:</p>
<pre><code class="language-bash">sw_vers
</code></pre>
<p>That prints the product name, version, and build. For the chip and memory, add:</p>
<pre><code class="language-bash">sysctl -n machdep.cpu.brand_string
system_profiler SPHardwareDataType | grep -E "Chip|Memory"
</code></pre>
<p>Pipe any of it straight to your clipboard so you never retype version numbers by hand:</p>
<pre><code class="language-bash">{ sw_vers; sysctl -n machdep.cpu.brand_string; } | pbcopy
</code></pre>
<p>Then add the app's own version (usually in its <strong>About</strong> window) and, for CLI tools, the output of <code>tool --version</code>. For web apps, include the browser and its version.</p>
<h2>5. Show it: screenshots and screen recordings without extra apps</h2>
<p>macOS has everything built in:</p>
<ul>
<li><strong>Cmd + Shift + 4</strong> captures a selected area. Press <strong>Space</strong> after it to capture a single window.</li>
<li><strong>Cmd + Shift + 5</strong> opens the capture toolbar, including <strong>Record Selected Portion</strong>, which is perfect for a 10-second clip of the bug happening.</li>
<li>Add <strong>Control</strong> to either screenshot shortcut (for example <strong>Cmd + Control + Shift + 4</strong>) to copy to the clipboard instead of saving a file, so you can paste straight into a GitHub issue.</li>
</ul>
<p>GitHub accepts <code>.mov</code> and <code>.mp4</code> uploads directly in issues, so a short recording often replaces a paragraph of description. Crop it to the part that matters.</p>
<h2>6. Attach the logs that matter (not all of them)</h2>
<p>Logs help when they're relevant and trimmed. A few Mac-specific places to look:</p>
<ul>
<li><strong>Crash reports:</strong> open <strong>Console.app</strong>, choose <strong>Crash Reports</strong> in the sidebar, and find the entry for the app. These also live in <code>~/Library/Logs/DiagnosticReports/</code>.</li>
<li><strong>Live logs:</strong> in Console.app, start streaming, filter by the process name, reproduce the bug, then stop and copy the relevant lines.</li>
<li><strong>Terminal output:</strong> rerun the failing command and capture everything, including errors:</li>
</ul>
<pre><code class="language-bash">your-command --verbose 2&gt;&amp;1 | tee bug-output.txt
</code></pre>
<p>Paste the relevant lines in a fenced code block, and attach the full file if it's long. Before you post, search the output for tokens, API keys, email addresses, and file paths that reveal more than you want. Redact them.</p>
<p>Need a file path for the report? In Finder, right-click the file, hold <strong>Option</strong>, and choose <strong>Copy "filename" as Pathname</strong>.</p>
<h2>7. Say what you already tried</h2>
<p>One short list saves a round trip:</p>
<pre><code>Already tried:
- Restarted the app and the Mac
- Reinstalled v2.3.1
- Same crash with a brand-new user account
- Does NOT happen in v2.2.0
</code></pre>
<p>That last line is gold. "It worked in the previous version" narrows the search to one diff.</p>
<h2>8. Make the template do the remembering</h2>
<p>If you maintain a project, don't rely on reporters reading a guide like this. Add a GitHub issue form at <code>.github/ISSUE_TEMPLATE/bug_report.yml</code>:</p>
<pre><code class="language-yaml">name: Bug report
description: Something isn't working
labels: ["bug"]
body:
  - type: textarea
    id: steps
    attributes:
      label: Steps to reproduce
      placeholder: "1. ...\n2. ...\n3. ..."
    validations:
      required: true
  - type: textarea
    id: expected-actual
    attributes:
      label: Expected vs actual behavior
    validations:
      required: true
  - type: input
    id: version
    attributes:
      label: App version and macOS version
      placeholder: "v2.3.1 on macOS 15.1 (paste output of sw_vers)"
    validations:
      required: true
  - type: textarea
    id: logs
    attributes:
      label: Logs or screenshots
      render: shell
</code></pre>
<p>Required fields mean you stop getting issues with no version number. If you start from the terminal, this opens the new-issue page, where the form appears:</p>
<pre><code class="language-bash">gh issue create --web --repo owner/repo
</code></pre>
<h2>9. Reread it as the person who has to fix it</h2>
<p>Before you hit submit, read your report as someone who has never seen your screen. Could they reproduce it in five minutes without asking you anything? If not, the missing piece is usually a version number, an input file, or a step you did without thinking.</p>
<p>Keep the tone neutral. "Export crashes with an empty title" gets fixed faster than "your app is garbage," and maintainers are people who chose to give their time away.</p>
<h2>A quick checklist</h2>
<ul>
<li><input disabled type="checkbox" /> Specific title: action, symptom, condition</li>
<li><input disabled type="checkbox" /> Numbered, minimal steps from a clean start</li>
<li><input disabled type="checkbox" /> Expected vs actual on separate lines</li>
<li><input disabled type="checkbox" /> <code>sw_vers</code> output plus the app's version</li>
<li><input disabled type="checkbox" /> Screenshot or short recording</li>
<li><input disabled type="checkbox" /> Trimmed, redacted logs</li>
<li><input disabled type="checkbox" /> What you already tried, and the last version that worked</li>
</ul>
<h2>One more tool, if you want it</h2>
<p>Disclosure: I built DraftKey, a Mac app that adds private, on-device AI autocomplete and rewriting to every Mac app, which helps when you're writing up issues, review comments, or support replies. Nothing you type leaves your Mac. It's $4.99 lifetime (up to 3 Macs) and needs macOS 14 or later on Apple Silicon: <a href="https://getdraftkey.com">getdraftkey.com</a>. Everything above works fine without it.</p>
]]></content:encoded></item><item><title><![CDATA[Code Review Comment Templates for GitHub and GitLab: How to Write Feedback That Gets Acted On]]></title><description><![CDATA[A practical guide to clear, kind, specific review feedback, with templates you can reuse on GitHub or GitLab]]></description><link>https://auramacapps.hashnode.dev/code-review-comment-templates-for-github-and-gitlab-how-to-write-feedback-that-gets-acted-on</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/code-review-comment-templates-for-github-and-gitlab-how-to-write-feedback-that-gets-acted-on</guid><category><![CDATA[code review]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[writing]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sat, 24 Oct 2026 21:43:09 GMT</pubDate><content:encoded><![CDATA[<p>Most code review comments that go nowhere have the same problems. The author can't tell whether the comment blocks the merge. They can't tell what the reviewer actually wants changed. Or the tone reads harsher than it was meant to, and the thread turns into a debate instead of a fix.</p>
<p>None of this takes talent to avoid. It takes a few habits. Here's the routine I use when I review pull requests, plus the small tools that make it faster.</p>
<h2>1. Say how much the comment matters</h2>
<p>The most useful thing you can add to a review comment is a label. Without one, the author has to guess whether "maybe rename this?" is a request or a passing thought, and careful authors treat every comment as blocking.</p>
<p>The Conventional Comments format (conventionalcomments.org) gives you a small vocabulary for this. A few labels cover most reviews:</p>
<ul>
<li><strong>issue:</strong> something that needs to change before merging.</li>
<li><strong>suggestion:</strong> a concrete improvement you'd like but could live without.</li>
<li><strong>question:</strong> you don't understand something yet. No change implied.</li>
<li><strong>nitpick:</strong> trivial and optional, like naming or formatting.</li>
<li><strong>praise:</strong> something done well. Use it when it's true.</li>
</ul>
<p>You can add a decoration like (non-blocking) or (blocking) to remove any doubt:</p>
<blockquote>
<p>suggestion (non-blocking): This loop could use <code>Array.some</code> instead of tracking a flag. Fine to leave as is.</p>
</blockquote>
<p>Even if your team never adopts the format officially, writing "Non-blocking:" or "Nit:" at the start of a comment does most of the work.</p>
<h2>2. Make the comment self-contained</h2>
<p>Write each comment so it makes sense to someone reading it in an email notification, without the surrounding thread. A good comment has three parts:</p>
<ul>
<li><strong>What you noticed.</strong> Point at the specific line or behavior.</li>
<li><strong>Why it matters.</strong> A bug, a performance cost, a readability problem, a convention.</li>
<li><strong>What you'd do instead.</strong> Or, if you don't know, say that.</li>
</ul>
<p>Instead of:</p>
<blockquote>
<p>This is wrong.</p>
</blockquote>
<p>Write:</p>
<blockquote>
<p>issue: If <code>user</code> is null here (logged-out visitors hit this path), this throws before the redirect. Could we return early when there's no user?</p>
</blockquote>
<p>The second version takes fifteen more seconds to write and saves a round trip.</p>
<h2>3. Ask real questions, not rhetorical ones</h2>
<p>"Why didn't you just use the existing helper?" sounds like a question but reads as an accusation. If you're genuinely asking, make it clear you might be missing context:</p>
<blockquote>
<p>question: Is there a reason not to use <code>formatDate</code> from utils here? I may be missing a case it doesn't handle.</p>
</blockquote>
<p>If you aren't asking, don't phrase it as a question. Make the suggestion directly.</p>
<h2>4. Comment on the code, not the person</h2>
<p>Small wording changes shift the tone a lot:</p>
<ul>
<li>"You forgot to handle errors" becomes "This call doesn't handle a failed request."</li>
<li>"Your naming is confusing" becomes "I misread <code>data2</code> as a copy of <code>data</code>. Something like <code>filteredRows</code> would help."</li>
<li>"Why would you do it this way?" becomes "What led to this approach? I'd have expected X."</li>
</ul>
<p>Using "we" and "this code" instead of "you" isn't about being soft. It keeps the discussion on what to change.</p>
<h2>5. Use suggested changes for small fixes</h2>
<p>If the fix is a line or two, don't describe it. On GitHub, the "Add a suggestion" button in a review comment inserts a suggestion block, and the author can apply it with one click. GitLab has the same idea with its "Insert suggestion" button. It's faster for both of you and leaves no room for misreading.</p>
<p>Save prose for things that need a decision: design, naming of public APIs, trade-offs.</p>
<h2>6. Batch your comments into one review</h2>
<p>Leaving comments one at a time sends a notification for each one, and the author may start fixing things before you've finished reading. On GitHub, use "Start a review" on your first comment instead of "Add single comment," then submit everything at once with a summary.</p>
<p>The summary is worth a few sentences:</p>
<blockquote>
<p>Looks good overall. One blocking issue with the null user path in <code>session.ts</code>; the rest are suggestions and nits, so feel free to skip those. Happy to approve once the null case is handled.</p>
</blockquote>
<p>That tells the author where to start and how far they are from done.</p>
<h2>7. Keep reusable phrasing ready</h2>
<p>You probably write some of the same comments every week: "Could you add a test for this case?", "Can we split this into a separate PR?", "Nit: unused import." A few ways to stop retyping them:</p>
<ul>
<li><strong>GitHub saved replies.</strong> In your GitHub settings, under Saved replies, you can store canned responses and insert them from the comment box.</li>
<li><strong>macOS Text Replacements.</strong> In System Settings &gt; Keyboard &gt; Text Replacements, set short triggers like <code>;nb</code> for "Non-blocking:" or <code>;test</code> for "Could you add a test that covers this case?" They work in most Mac apps and text fields.</li>
<li><strong>A notes file</strong> with your team's review conventions, so new reviewers write comments the same way.</li>
</ul>
<p>Templates handle fixed phrases well. Where they fall short is the part that's different every time: explaining a specific bug, or softening a comment you wrote while annoyed.</p>
<h2>8. Reread before you submit</h2>
<p>Before submitting, skim your own comments once with three questions:</p>
<ol>
<li><strong>Is it clear which comments block the merge?</strong></li>
<li><strong>Could the author act on each comment without asking me what I meant?</strong></li>
<li><strong>Would I be fine receiving this comment on my own code?</strong></li>
</ol>
<p>If a comment fails the third question, rewrite it. If it fails the second, add the "why" or a suggested change.</p>
<h2>Where an AI writing tool can help</h2>
<p>For the reread step and the writing in between, an AI writing tool can speed things up. The main thing to watch is where your text goes. Review comments often quote proprietary code, and many companies don't allow pasting that into a cloud chatbot.</p>
<p>I built <strong>DraftKey</strong> for this kind of writing. It's a Mac app that runs its model on your Mac, so your text isn't sent to a cloud AI service. As you type, it suggests the next words in gray and you press Tab to accept them. When you want to change something you already wrote, you tap Command+Option to open a rewrite panel with Fix writing, Shorter, Clearer, tone options like Friendly or Professional, or your own instruction. "Make this less blunt but keep the request" is a good one for review comments.</p>
<p>The honest details: it's $4.99 once for up to 3 Macs, it needs macOS 14 or later on Apple Silicon, and there's no free trial. It works in compatible Mac text fields, and some custom editors aren't supported, so how well it works in a given browser or editor depends on how that app exposes its text. It's at <a href="https://getdraftkey.com">getdraftkey.com</a>.</p>
<p>You don't need it to do anything in this article. The habits are what matter.</p>
<h2>A quick checklist</h2>
<ul>
<li>Label each comment: issue, suggestion, question, nitpick, or praise</li>
<li>Say what, why, and what you'd do instead</li>
<li>Ask real questions or make direct suggestions</li>
<li>Talk about the code, not the person</li>
<li>Use suggested changes for one- or two-line fixes</li>
<li>Batch comments into one review with a short summary</li>
<li>Keep saved replies or text replacements for repeated phrases</li>
<li>Reread once before submitting</li>
</ul>
<p>Try labeling your comments for a week. In my experience, it's the change that cuts the most back-and-forth.</p>
<p>Disclosure: I built DraftKey.</p>
]]></content:encoded></item><item><title><![CDATA[How macOS Writing Tools Work in Every App: A Developer's Guide to the Accessibility API]]></title><description><![CDATA[Disclosure: I built DraftKey, an on-device writing assistant for Mac that's built on the APIs below. It comes up once at the end. This post is about the…]]></description><link>https://auramacapps.hashnode.dev/how-macos-writing-tools-work-in-every-app-a-developer-s-guide-to-the-accessibility-api</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-macos-writing-tools-work-in-every-app-a-developer-s-guide-to-the-accessibility-api</guid><category><![CDATA[macOS]]></category><category><![CDATA[Swift]]></category><category><![CDATA[Accessibility]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sat, 24 Oct 2026 20:40:52 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure: I built DraftKey, an on-device writing assistant for Mac that's built on the APIs below. It comes up once at the end. This post is about the platform, not the product.</em></p>
<p>Grammarly, autocomplete tools, text expanders, window managers and screen readers all have the same problem on macOS. They need to work inside apps they didn't write. Nearly all of them solve it with the <strong>Accessibility API</strong>, the same interface VoiceOver uses. If you've ever wondered why one of these tools works in Mail but not in some editor, or why it asks for a scary-sounding permission, this is how the pieces fit together.</p>
<h2>Step 0: become a trusted client</h2>
<p>Your app can't read other apps' UI until the user adds it under <strong>System Settings → Privacy &amp; Security → Accessibility</strong>. You check for that and ask for it with one call:</p>
<pre><code class="language-swift">import ApplicationServices

let opts = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true] as CFDictionary
let trusted = AXIsProcessTrustedWithOptions(opts)   // shows the system prompt if needed
</code></pre>
<p><code>AXIsProcessTrustedWithOptions</code> returns whether your process is a trusted accessibility client. With the prompt option set, macOS shows its own dialog that points the user to System Settings. You can't grant this permission in code, and that's on purpose.</p>
<p>The permission is broad. A trusted client can read the contents and structure of almost any app's windows. That's why it's worth knowing who made any tool you grant it to.</p>
<h2>Step 1: find the focused text field</h2>
<p>Everything in the Accessibility API is an <code>AXUIElement</code>, an opaque reference to a UI object in another process, with named attributes you can read. Start at the system-wide element and ask what has focus:</p>
<pre><code class="language-swift">func focusedElement() -&gt; AXUIElement? {
    let system = AXUIElementCreateSystemWide()
    var value: CFTypeRef?
    guard AXUIElementCopyAttributeValue(system, kAXFocusedUIElementAttribute as CFString,
                                        &amp;value) == .success else { return nil }
    return (value as! AXUIElement)
}
</code></pre>
<p>From there, these are the attributes a writing tool cares about:</p>
<ul>
<li><code>kAXRoleAttribute</code> / <code>kAXSubroleAttribute</code>: is this a text field, a text area, or something else?</li>
<li><code>kAXValueAttribute</code>: the full text of the field.</li>
<li><code>kAXSelectedTextRangeAttribute</code>: the selection as a character range (not bytes). An empty range gives you the caret position. Apple's docs say this attribute is required for all editable text elements, which is why it's the most reliable one to build on.</li>
<li><code>kAXSelectedTextAttribute</code>: just the selected text.</li>
</ul>
<p>With the value and the caret position, you have the context a model needs: the text before the cursor, and maybe a little after it.</p>
<h2>Step 2: find where the caret is on screen</h2>
<p>To draw ghost text or a popup next to the cursor, you need screen coordinates. That's what <strong>parameterized attributes</strong> are for. <code>kAXBoundsForRangeParameterizedAttribute</code> takes a range and returns the bounding rectangle of that text as it appears on screen:</p>
<pre><code class="language-swift">func caretRect(_ el: AXUIElement, location: Int) -&gt; CGRect? {
    var range = CFRange(location: location, length: 0)
    guard let axRange = AXValueCreate(.cfRange, &amp;range) else { return nil }
    var out: CFTypeRef?
    guard AXUIElementCopyParameterizedAttributeValue(
            el, kAXBoundsForRangeParameterizedAttribute as CFString, axRange, &amp;out) == .success
    else { return nil }
    var rect = CGRect.zero
    AXValueGetValue(out as! AXValue, .cgRect, &amp;rect)
    return rect
}
</code></pre>
<p>Two practical notes:</p>
<ul>
<li>Some apps return an empty rectangle for a zero-length range. A common fallback is to ask for the bounds of the character just before the caret and use its right edge.</li>
<li>The rectangle uses top-left-origin screen coordinates, while AppKit windows use bottom-left. Flip the y value against the main screen's height before you position your overlay.</li>
</ul>
<h2>Step 3: react to typing without polling</h2>
<p>You don't want to read the whole field 60 times a second. <code>AXObserver</code> lets you subscribe to notifications from another process:</p>
<pre><code class="language-swift">var observer: AXObserver?
AXObserverCreate(pid, { _, element, notification, _ in
    // debounce, then re-read value + selection and request a suggestion
}, &amp;observer)

let app = AXUIElementCreateApplication(pid)
AXObserverAddNotification(observer!, app, kAXFocusedUIElementChangedNotification as CFString, nil)
AXObserverAddNotification(observer!, app, kAXValueChangedNotification as CFString, nil)
AXObserverAddNotification(observer!, app, kAXSelectedTextChangedNotification as CFString, nil)

CFRunLoopAddSource(CFRunLoopGetCurrent(),
                   AXObserverGetRunLoopSource(observer!), .defaultMode)
</code></pre>
<p>You need one observer per app process, so watch <code>NSWorkspace</code> for app activation and move your observer as the user switches apps. Value-changed tells you the user typed. Selected-text-changed tells you the caret moved, which is often your cue to throw away a stale suggestion.</p>
<h2>Step 4: put the text back</h2>
<p>Once the user accepts a suggestion, there are two common ways to insert it:</p>
<ol>
<li><strong>Set the selected text.</strong> Writing to <code>kAXSelectedTextAttribute</code> with <code>AXUIElementSetAttributeValue</code> replaces the current selection, or inserts at the caret if nothing is selected. It's clean when it works, and it leaves the clipboard alone. Not every app supports writing it, so check the result code.</li>
<li><strong>Paste it.</strong> Put the text on the pasteboard and post a synthesized ⌘V with <code>CGEvent</code>. It works in more places, but you have to save and restore the user's clipboard, and some apps handle pasted text differently from typed text.</li>
</ol>
<p>Many tools try the first and fall back to the second.</p>
<h2>Why it doesn't work everywhere</h2>
<p>This is the part users actually notice.</p>
<p><strong>Apps expose different amounts.</strong> Native AppKit text views implement everything above. Custom-drawn editors (some code editors, canvas-based web apps, games) may expose little or nothing. Your tool can only see what the app reports.</p>
<p><strong>Electron and Chromium build their tree on demand.</strong> Per <a href="https://www.electronjs.org/docs/latest/tutorial/accessibility">Electron's accessibility docs</a>, Electron apps turn on accessibility support automatically when assistive technology like VoiceOver is running. A third-party tool can request it by setting the <code>AXManualAccessibility</code> attribute to true on the app's element. Until then, the text you're looking for may not be in the tree at all.</p>
<p><strong>Secure fields are off-limits, and should be.</strong> Password fields have the subrole <code>kAXSecureTextFieldSubrole</code>, which Apple describes as a field for sensitive data that shows input as bullets. Skip them. Separately, when an app turns on Secure Event Input, which <code>NSSecureTextField</code> does automatically and Terminal and iTerm let you keep on, Apple's <a href="https://developer.apple.com/library/archive/technotes/tn2150/_index.html">TN2150</a> explains that keyboard event taps stop receiving keystrokes. You can check this with <code>IsSecureEventInputEnabled()</code> and show the user why suggestions paused.</p>
<p><strong>The Mac App Store is mostly out.</strong> Apple's App Sandbox documentation lists "use of accessibility APIs in assistive apps" among the things the sandbox forbids, and Mac App Store apps must be sandboxed. That's why most system-wide writing tools are downloads signed with Developer ID, not App Store apps. (Event taps that need only Input Monitoring are a narrower exception.)</p>
<h2>Debugging tips</h2>
<ul>
<li><strong>Accessibility Inspector</strong> (Xcode → Open Developer Tool) shows exactly which attributes an app exposes. Check it before you blame your code.</li>
<li>During development, macOS ties the permission to your code signature, so a rebuilt binary with a different signature can quietly lose trust. <code>tccutil reset Accessibility &lt;bundle-id&gt;</code> gives you a clean slate.</li>
<li>Every AX call is a cross-process message to the target app. Keep them off the main thread, and set a timeout with <code>AXUIElementSetMessagingTimeout</code> so a frozen app can't freeze yours.</li>
</ul>
<h2>Where the model fits</h2>
<p>All of the above is plumbing. The model only sees a string of context and returns a string. That separation is what makes on-device suggestions practical. The Accessibility layer collects the text locally, and if inference also runs locally, the text never has to leave the Mac.</p>
<p>That's the design I went with for <a href="https://getdraftkey.com">DraftKey</a>. It uses Accessibility to work in compatible text fields, skips secure fields, has per-app controls, and runs its writing model on the Mac. It's $4.99 lifetime for up to 3 Macs (macOS 14+, Apple Silicon). It hits the same limits described above, so it can't work in editors that don't expose their text.</p>
<p>If you're building something in this space, start with Accessibility Inspector and a single <code>AXObserver</code>. You'll learn most of what you need from watching which notifications actually fire.</p>
<p><em>Originally published on <a href="https://dev.to/godnick/how-mac-apps-add-text-suggestions-to-every-app-the-accessibility-api-explained-1bfj">DEV</a>.</em></p>
]]></content:encoded></item><item><title><![CDATA[How to Track AI Coding Costs per Project: Claude Code and Codex Spend by Repo]]></title><description><![CDATA[Your monthly AI bill is one number. Here's how to split it by repo, so you know which projects are actually worth the tokens.]]></description><link>https://auramacapps.hashnode.dev/how-to-track-ai-coding-costs-per-project-claude-code-and-codex-spend-by-repo</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-track-ai-coding-costs-per-project-claude-code-and-codex-spend-by-repo</guid><category><![CDATA[claude]]></category><category><![CDATA[AI]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[Developer Tools]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sat, 24 Oct 2026 19:16:38 GMT</pubDate><content:encoded><![CDATA[<p>Most developers who use Claude Code or Codex CLI know roughly what they spend in a month. Very few know where that spend goes. Is the side project eating half your limit? Is the client repo with the giant monorepo context costing three times what you bill for it? Is one runaway refactor from last Tuesday responsible for the week you hit your cap?</p>
<p>You can answer those questions with a little setup. This guide covers where the usage data lives on your Mac, how to group it by project, and a few habits that make the numbers useful instead of just interesting.</p>
<h2>Why per-project numbers matter</h2>
<p>A single monthly total hides the decisions you can actually change:</p>
<ul>
<li><strong>Which repos need a smaller context.</strong> A project with a bloated <code>CLAUDE.md</code> or <code>AGENTS.md</code>, huge generated files, or no ignore rules can cost several times more per task than a tidy one.</li>
<li><strong>What to bill clients.</strong> If you freelance, AI time on a client project is a real cost. Per-repo numbers let you price it in honestly.</li>
<li><strong>Which side projects are worth it.</strong> It's easy to keep a hobby project going in the background without noticing it's taking a third of your plan.</li>
<li><strong>Where a spike came from.</strong> When you hit a limit early, you want to know which session did it, not guess.</li>
</ul>
<h2>Where the data lives</h2>
<p>Both tools keep local session logs, which is what makes per-project tracking possible without any API dashboard.</p>
<p><strong>Claude Code</strong> writes a JSONL transcript for every session under <code>~/.claude/projects/</code>. Each project gets its own folder, named after the path of the directory you started the session in. Assistant messages in those files include a <code>usage</code> block with input tokens, output tokens, and cache read and cache creation tokens.</p>
<p><strong>Codex CLI</strong> stores session logs under <code>~/.codex/sessions/</code>, organized by date. Each session records the working directory it ran in, along with token counts as the session progresses.</p>
<p>Two things follow from this. First, the folder you launch the tool from <em>is</em> the project, as far as the logs are concerned, so launch from the repo root consistently. Second, the data is already on your disk. You just need to add it up.</p>
<h2>Option 1: use an existing CLI</h2>
<p>The quickest route for Claude Code is <a href="https://github.com/ryoppippi/ccusage">ccusage</a>, an open-source CLI that reads the local JSONL files and reports usage by day, month, or session, with estimated cost. Run it with <code>npx ccusage@latest</code> and look at the session report. Sessions are tied to project folders, so you can see which repos dominate.</p>
<p>Check the project's README for current flags, since it changes often. If you only use Claude Code, this may be all you need.</p>
<h2>Option 2: a small script of your own</h2>
<p>If you want Claude Code and Codex in one table, or you want to group by client rather than by folder, a short script works fine. The idea:</p>
<ol>
<li>Walk <code>~/.claude/projects/</code> and, for each project folder, sum <code>input_tokens</code>, <code>output_tokens</code>, <code>cache_read_input_tokens</code>, and <code>cache_creation_input_tokens</code> from assistant messages in every <code>.jsonl</code> file.</li>
<li>Walk <code>~/.codex/sessions/</code>, read the working directory and final token totals for each session, and group by directory.</li>
<li>Map directories to the names you care about, for example everything under <code>~/code/acme-*</code> becomes "Acme (client)".</li>
<li>Multiply by the current per-token prices for the models you use if you want dollars, or keep raw tokens if you're on a subscription and care about limits.</li>
</ol>
<p>Here's a minimal Python sketch for the Claude Code half:</p>
<pre><code class="language-python">import json, pathlib, collections

root = pathlib.Path.home() / ".claude" / "projects"
totals = collections.defaultdict(lambda: collections.Counter())

for project in root.iterdir():
    for f in project.glob("*.jsonl"):
        for line in f.open():
            try:
                msg = json.loads(line).get("message", {})
            except json.JSONDecodeError:
                continue
            usage = msg.get("usage") if isinstance(msg, dict) else None
            if usage:
                for k, v in usage.items():
                    if isinstance(v, int):
                        totals[project.name][k] += v

for name, c in sorted(totals.items(), key=lambda kv: -sum(kv[1].values())):
    print(f"{name}: in={c['input_tokens']:,} out={c['output_tokens']:,} "
          f"cache_read={c['cache_read_input_tokens']:,}")
</code></pre>
<p>Field names can change between versions, so print one raw line first and adjust if needed. Treat the result as an estimate, not an invoice: the provider's billing page is the source of truth.</p>
<h2>Making the numbers useful</h2>
<p>Collecting data is the easy part. These habits turn it into decisions.</p>
<p><strong>Always launch from the repo root.</strong> Starting a session from <code>~/</code> or a random subfolder splits one project across several buckets, or lumps unrelated work together.</p>
<p><strong>Look at cache reads separately.</strong> In long sessions, cache reads are usually the biggest token count. They're much cheaper than fresh input, but on a subscription they still count against your limits. A project with huge cache-read numbers is a project where sessions run too long. Clearing more often and restating the task in a few lines usually helps.</p>
<p><strong>Compare cost per task, not just totals.</strong> A busy project should cost more. What you want to spot is a project where ordinary tasks cost far more than elsewhere, which usually points to oversized context: a long memory file, giant fixtures, or generated code the agent keeps reading.</p>
<p><strong>Check weekly.</strong> Monthly reviews are too late to change anything. A five-minute weekly look tells you if a project is drifting.</p>
<p><strong>Write down what you change.</strong> If you trim a project's memory file or add ignore rules, note the date. Next week's numbers tell you whether it worked.</p>
<h2>Seeing it while you work</h2>
<p>Scripts and reports are good for looking back. During the day, it helps to have current usage visible without running anything, so you notice a runaway session while it's happening rather than at the end of the week.</p>
<p>That's the reason I built <a href="https://tokenbar.site">TokenBar</a>, a Mac menu bar app that shows your Claude, Codex, and other AI usage and cost at a glance, including how close you are to your limits. It's built on the MIT-licensed open-source CodexBar project and costs $15 once, with no subscription. It doesn't replace a per-project breakdown, but it pairs well with one: the menu bar tells you something is spiking, and the logs tell you which repo did it.</p>
<h2>Quick checklist</h2>
<ul>
<li>Launch Claude Code and Codex from each repo's root, every time</li>
<li>Use ccusage or a short script to sum tokens per project folder</li>
<li>Group folders into clients or products if that's how you think about cost</li>
<li>Watch cache reads in long sessions, and clear more often where they balloon</li>
<li>Compare cost per task across projects to find oversized context</li>
<li>Review weekly and note what you changed</li>
</ul>
<p>Disclosure: I built TokenBar.</p>
]]></content:encoded></item><item><title><![CDATA[Cotypist vs DraftKey vs WunderType vs RewriteBar: Local AI Writing on Mac Compared]]></title><description><![CDATA[An honest side-by-side of four Mac writing apps that can run AI on your own machine.]]></description><link>https://auramacapps.hashnode.dev/cotypist-vs-draftkey-vs-wundertype-vs-rewritebar-local-ai-writing-on-mac-compared</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/cotypist-vs-draftkey-vs-wundertype-vs-rewritebar-local-ai-writing-on-mac-compared</guid><category><![CDATA[AI]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[writing]]></category><category><![CDATA[macOS]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sat, 24 Oct 2026 17:42:41 GMT</pubDate><content:encoded><![CDATA[<p>If you search for local AI writing tools on the Mac, the same names keep coming up: Cotypist, WunderType and RewriteBar. I built a fourth, DraftKey, so I've spent a lot of time with this category and I'll try to be fair, including where the others are the better choice.</p>
<p>All facts below come from each app's own website as of October 2026. If something has changed, the linked pages are the source of truth.</p>
<hr />
<h2>The short version</h2>
<p>These four apps fall into two camps:</p>
<ul>
<li><strong>Autocomplete while you type:</strong> Cotypist and DraftKey show suggested next words inline, and you press Tab to accept.</li>
<li><strong>Rewrite on demand:</strong> WunderType and RewriteBar act on text you select, triggered by a shortcut.</li>
</ul>
<p>DraftKey sits in both camps, because it also has a rewrite panel. Cotypist doesn't rewrite selected paragraphs, and WunderType and RewriteBar don't autocomplete as you type.</p>
<hr />
<h2>Comparison table</h2>
<table>
<thead>
<tr>
<th></th>
<th>Cotypist</th>
<th>DraftKey</th>
<th>WunderType</th>
<th>RewriteBar</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Main gesture</strong></td>
<td>Inline suggestions, Tab</td>
<td>Inline suggestions, Tab + ⌘⌥ rewrite panel</td>
<td>Select text, ⌘⇧G</td>
<td>Select text, shortcut opens action palette</td>
</tr>
<tr>
<td><strong>Inline autocomplete</strong></td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td><strong>Rewrite selected text</strong></td>
<td>No (synonyms in Labs)</td>
<td>Yes: Fix writing, Shorter, Clearer, tones, custom</td>
<td>Yes: 5 modes + unlimited custom prompts</td>
<td>Yes: dozens of actions, custom + chained</td>
</tr>
<tr>
<td><strong>AI runs on-device</strong></td>
<td>Always</td>
<td>Always</td>
<td>Optional (built-in MLX models or Ollama)</td>
<td>Optional (Ollama, LM Studio, oMLX, Apple Intelligence, Osaurus)</td>
</tr>
<tr>
<td><strong>Cloud AI options</strong></td>
<td>None</td>
<td>None</td>
<td>Your OpenAI or OpenRouter key</td>
<td>38+ providers, BYOK, or RewriteBar's own cloud</td>
</tr>
<tr>
<td><strong>Price</strong></td>
<td>Free tier; Plus $72/yr, Pro $108/yr</td>
<td>$4.99 once</td>
<td>$8.99 once</td>
<td>Free tier; $29 or $59 once</td>
</tr>
<tr>
<td><strong>Macs covered</strong></td>
<td>1 (Plus) or 3 (Pro)</td>
<td>Up to 3</td>
<td>Not stated on site</td>
<td>1 (Standard) or 3 (Pro)</td>
</tr>
<tr>
<td><strong>Try before buying</strong></td>
<td>Free tier + 30-day Pro trial</td>
<td>No trial</td>
<td>Not stated on site</td>
<td>Free tier</td>
</tr>
<tr>
<td><strong>Requirements</strong></td>
<td>Apple Silicon, macOS 14+; 16 GB recommended</td>
<td>Apple Silicon, macOS 14+, 8 GB, ~1.12 GB model</td>
<td>Apple Silicon for on-device AI; Intel via Ollama</td>
<td>Not stated on homepage</td>
</tr>
<tr>
<td><strong>App size / footprint</strong></td>
<td>Uses ~1–2.5 GB RAM while active</td>
<td>~1.12 GB model download</td>
<td>~20 MB app (+ model if on-device)</td>
<td>~20–25 MB app</td>
</tr>
</tbody></table>
<hr />
<h2>Cotypist</h2>
<p><strong><a href="https://cotypist.app">cotypist.app</a></strong></p>
<p><strong>What it does well.</strong> Cotypist is the reference point for Mac autocomplete. Suggestions appear inline in almost any app, Tab takes the next word (or the whole line), and it learns your vocabulary and phrasing. It can also use what's on your screen as context, so suggestions match the email thread you're replying to. Processing is entirely on-device and works offline. It has strong reviews, including from John Gruber at Daring Fireball, who called its suggestions "eerily good."</p>
<p><strong>Trade-offs.</strong> It's a subscription for unlimited use ($72/year for one Mac, $108/year for three). The free tier covers 100 accepted words a day. It recommends an M1 Pro or M2 with 16 GB of memory for the smoothest experience. It's built for autocomplete, so for rewriting a paragraph you'd pair it with something else.</p>
<p><strong>Pick it if</strong> autocomplete quality and personalization matter most and you'd like a free tier and a long trial before committing.</p>
<hr />
<h2>DraftKey</h2>
<p><strong><a href="https://www.getdraftkey.com">getdraftkey.com</a></strong></p>
<p><strong>What it does.</strong> This is mine. DraftKey suggests the next words as you type in compatible Mac text fields, and you press Tab to accept. Tapping Command + Option opens a rewrite panel on the current paragraph (no need to select first) with Fix writing, Shorter, Clearer, Friendly, Professional, or a custom instruction. You review the result before it's inserted. The model runs on your Mac and works offline after setup. The license also includes clipboard history and keyboard sounds.</p>
<p><strong>Trade-offs.</strong> No free trial and no automatic money-back guarantee, which makes it the hardest of the four to evaluate before paying. It needs Apple Silicon, macOS 14+, 8 GB of memory and a ~1.12 GB model download. It has no cloud-model option, so you can't swap in a frontier model for harder edits. It's also a much younger app than Cotypist, with nowhere near its track record or reviews.</p>
<p><strong>Pick it if</strong> you want autocomplete and rewrites in one local app for a one-time $4.99.</p>
<hr />
<h2>WunderType</h2>
<p><strong><a href="https://wundertype.com">wundertype.com</a></strong></p>
<p><strong>What it does well.</strong> WunderType is deliberately minimal: a ~20 MB sandboxed menu bar app with no Dock icon, no account, no server and no telemetry. Select text, press ⌘⇧G, and it's corrected in place, with your clipboard restored. Since version 1.5 it runs models on your Mac's GPU through Apple MLX (Gemma 3 1B or 4B, Granite 2B, Phi-4 Mini), and you can also use Ollama, your own OpenAI key or OpenRouter, even per prompt. Custom prompts can each have their own shortcut.</p>
<p><strong>Trade-offs.</strong> No inline autocomplete. It acts only when you invoke it.</p>
<p><strong>Pick it if</strong> you want a cheap, private, one-key fixer with the flexibility to use a bigger cloud model when you need one.</p>
<hr />
<h2>RewriteBar</h2>
<p><strong><a href="https://rewritebar.com">rewritebar.com</a></strong></p>
<p><strong>What it does well.</strong> RewriteBar is the maximalist option: a Spotlight-style palette of AI actions on your selection, with grammar fixes, tone changes, translation to 500+ languages (model-dependent), summaries, JSON and SQL formatting, side-by-side diffs, chained multi-step workflows and PopClip integration. It supports 500+ models across 38+ providers, including fully local ones.</p>
<p><strong>Trade-offs.</strong> Privacy depends on configuration. The default RewriteBar provider routes text through its server (it says nothing is stored), so you'll need to set up a local provider for offline use. All those options also mean more setup than the others.</p>
<p><strong>Pick it if</strong> you want the most actions and model choices and you're happy to configure them.</p>
<hr />
<h2>Which one should you pick?</h2>
<table>
<thead>
<tr>
<th>If you…</th>
<th>Choose</th>
</tr>
</thead>
<tbody><tr>
<td>Want the best-known autocomplete and a free way to try it</td>
<td>Cotypist</td>
</tr>
<tr>
<td>Want autocomplete + rewrites in one app, paid once</td>
<td>DraftKey</td>
</tr>
<tr>
<td>Want the simplest private rewrite shortcut</td>
<td>WunderType</td>
</tr>
<tr>
<td>Want maximum actions, languages and AI providers</td>
<td>RewriteBar</td>
</tr>
<tr>
<td>Need it to work on an Intel Mac</td>
<td>WunderType (via Ollama)</td>
</tr>
</tbody></table>
<p>You can also pair an autocomplete app with a rewrite app. Cotypist for autocomplete plus WunderType for rewrites, for example, covers both gestures. Just don't run two autocomplete apps that both use Tab at the same time.</p>
<hr />
<h2>Worth mentioning</h2>
<p>Two related apps come up in the same searches:</p>
<ul>
<li><strong>Charm</strong> ($19.99 once) focuses on on-device spelling and grammar correction, with next-word prediction.</li>
<li><strong>Elephas</strong> has moved toward private AI over your own documents and now offers a 7-day free trial, then paid plans.</li>
</ul>
<p>Neither fits neatly into a head-to-head with these four, but both are worth a look depending on what you need.</p>
<p>If you've used any of these, I'd like to hear what you'd change in this table.</p>
<p><em>Disclosure: I built DraftKey.</em></p>
]]></content:encoded></item><item><title><![CDATA[Claude Code and Codex CLI Allow/Deny Rules: A Starter Config That Ends the Approval Prompts]]></title><description><![CDATA[If you use Claude Code or Codex CLI for more than a few minutes, you hit the same wall: either you approve every single ls and npm test by hand, or you…]]></description><link>https://auramacapps.hashnode.dev/claude-code-and-codex-cli-allow-deny-rules-a-starter-config-that-ends-the-approval-prompts</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/claude-code-and-codex-cli-allow-deny-rules-a-starter-config-that-ends-the-approval-prompts</guid><category><![CDATA[claude-code]]></category><category><![CDATA[Security]]></category><category><![CDATA[AI]]></category><category><![CDATA[Developer Tools]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Sat, 24 Oct 2026 16:16:47 GMT</pubDate><content:encoded><![CDATA[<p>If you use Claude Code or Codex CLI for more than a few minutes, you hit the same wall: either you approve every single <code>ls</code> and <code>npm test</code> by hand, or you flip on the "just do everything" mode and hope nothing goes wrong. Neither is great.</p>
<p>Both tools have a middle ground. You can tell them which commands are always fine, which ones always need a check, and which files they should never touch. This guide walks through how to set that up in each tool, plus a starter config you can copy.</p>
<p>Flags and setting names do change between releases, so run <code>claude --help</code> and <code>codex --help</code> to confirm what your version supports.</p>
<h2>The idea: allow the boring stuff, block the scary stuff</h2>
<p>Most agent commands fall into three groups:</p>
<ul>
<li><strong>Safe and frequent:</strong> reading files, running tests, linting, <code>git status</code>, <code>git diff</code>. Approving these by hand is pure friction.</li>
<li><strong>Worth a look:</strong> installing packages, <code>git push</code>, anything that hits the network or changes files outside the project.</li>
<li><strong>Never:</strong> reading <code>.env</code> or credential files, <code>rm -rf</code> outside the repo, deploying to production.</li>
</ul>
<p>The goal is to auto-approve the first group, keep prompts for the second, and hard-block the third.</p>
<h2>Claude Code: permission rules</h2>
<p>Claude Code reads permission rules from settings files:</p>
<ul>
<li><code>~/.claude/settings.json</code> for your personal defaults across every project</li>
<li><code>.claude/settings.json</code> in the repo, which you can commit for your team</li>
<li><code>.claude/settings.local.json</code> for personal overrides in one repo (keep it out of git)</li>
</ul>
<p>Rules go in <code>allow</code>, <code>ask</code>, and <code>deny</code> lists. Deny wins over everything else. A starter project file might look like this:</p>
<pre><code class="language-json">{
  "permissions": {
    "allow": [
      "Bash(npm run test:*)",
      "Bash(npm run lint)",
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(git log:*)"
    ],
    "ask": [
      "Bash(git push:*)",
      "Bash(npm install:*)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(curl:*)"
    ]
  }
}
</code></pre>
<p>A few things that help:</p>
<ul>
<li><strong>Use prefix matches for commands.</strong> <code>Bash(npm run test:*)</code> covers <code>npm run test</code> with any arguments after it. Be careful with very broad prefixes like <code>Bash(npm:*)</code>, since that also covers <code>npm publish</code>.</li>
<li><strong>Add rules from the prompt.</strong> When Claude asks to run something, choosing the "don't ask again" option writes an allow rule for you. After a week of normal work, open the file and prune anything too broad.</li>
<li><strong>Check what's active with <code>/permissions</code>.</strong> It lists every rule and which settings file it came from, which is the fastest way to debug "why did it ask me again?"</li>
</ul>
<h3>Permission modes</h3>
<p>On top of rules, Claude Code has modes you can cycle with Shift+Tab during a session:</p>
<ul>
<li><strong>Default:</strong> asks the first time it wants to use each tool.</li>
<li><strong>Accept edits:</strong> file edits go through without a prompt, but shell commands still follow your rules.</li>
<li><strong>Plan mode:</strong> read-only. Claude explores and writes a plan but doesn't change anything. This is a great first step for any big task.</li>
</ul>
<p>There's also <code>--dangerously-skip-permissions</code>, which skips every prompt. Only use it inside a throwaway container or VM with no credentials in it, because the name is accurate.</p>
<h2>Codex CLI: sandbox plus approval policy</h2>
<p>Codex splits the problem into two separate settings.</p>
<p><strong>Sandbox mode</strong> controls what commands can physically do:</p>
<ul>
<li><code>read-only</code>: can read files, can't write or use the network.</li>
<li><code>workspace-write</code>: can write inside the project folder, and network access is off by default.</li>
<li><code>danger-full-access</code>: no sandbox at all.</li>
</ul>
<p>On macOS, Codex enforces this with the system's built-in sandbox (Seatbelt), so it isn't just an honor system. A command that tries to write outside the workspace actually fails.</p>
<p><strong>Approval policy</strong> controls when Codex stops to ask you:</p>
<ul>
<li><code>untrusted</code>: asks before anything that isn't on its short list of known-safe read commands.</li>
<li><code>on-request</code>: runs inside the sandbox and asks only when it needs to go beyond it.</li>
<li><code>never</code>: never asks. Failures just come back to the model.</li>
</ul>
<p>You can set both per session:</p>
<pre><code class="language-bash">codex --sandbox workspace-write --ask-for-approval on-request
</code></pre>
<p><code>--full-auto</code> is a shortcut for roughly that same pair. Or set defaults in <code>~/.codex/config.toml</code>:</p>
<pre><code class="language-toml">approval_policy = "on-request"
sandbox_mode = "workspace-write"

[sandbox_workspace_write]
network_access = false
</code></pre>
<p>Inside a session, the <code>/approvals</code> command lets you switch levels without restarting, which is handy when you move from exploring to letting it run a long refactor.</p>
<h2>A setup that works for most projects</h2>
<p>Here's what I'd start with in both tools:</p>
<ol>
<li><strong>Start big tasks read-only.</strong> Plan mode in Claude Code, <code>read-only</code> sandbox in Codex. Let the agent read the code and propose a plan before it touches anything.</li>
<li><strong>Then allow edits inside the repo only.</strong> Accept-edits mode in Claude Code, <code>workspace-write</code> with <code>on-request</code> in Codex.</li>
<li><strong>Auto-approve your test, lint, and read-only git commands.</strong> These are the bulk of what agents run.</li>
<li><strong>Hard-deny secrets.</strong> Block <code>.env</code> files and credential folders explicitly, even if you think the agent wouldn't look.</li>
<li><strong>Keep network and publish commands behind a prompt.</strong> <code>git push</code>, <code>npm publish</code>, <code>curl</code>, and deploy scripts should always need your OK.</li>
<li><strong>Do anything fully unattended in a container.</strong> If you want zero prompts, give the agent a disposable environment rather than your real laptop.</li>
</ol>
<p>Commit the shared project rules so everyone on the team gets the same guardrails, and keep personal preferences in your home directory or local settings file.</p>
<h2>One side effect worth knowing</h2>
<p>Once you stop approving every command, sessions run a lot longer on their own. That's the point, but it also means an agent can burn through a big chunk of your plan limits or API budget while you're getting coffee. It's worth keeping an eye on usage when you first loosen the rules, so you notice if a loop of failing tests is eating tokens.</p>
<p>Disclosure: I built TokenBar, a $15 lifetime Mac menu bar app that shows your Claude, Codex and other AI usage and cost at a glance. It's built on the MIT-licensed open source CodexBar. <a href="https://tokenbar.site">https://tokenbar.site</a></p>
<p>What allow and deny rules have you settled on? I'd love to see other people's configs in the comments.</p>
]]></content:encoded></item><item><title><![CDATA[How to Run Several Claude Code or Codex Sessions at Once with Git Worktrees]]></title><description><![CDATA[A practical guide to giving each coding agent its own checkout: the git commands, per-worktree setup, the built-in worktree options in Claude Code and…]]></description><link>https://auramacapps.hashnode.dev/how-to-run-several-claude-code-or-codex-sessions-at-once-with-git-worktrees</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-run-several-claude-code-or-codex-sessions-at-once-with-git-worktrees</guid><category><![CDATA[AI]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[Git]]></category><category><![CDATA[claude]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Thu, 22 Oct 2026 11:11:33 GMT</pubDate><content:encoded><![CDATA[<p><em>A practical guide to giving each coding agent its own checkout: the git commands, per-worktree setup, the built-in worktree options in Claude Code and Codex CLI, and the pitfalls that bite</em></p>
<p>Once a coding agent can work for twenty minutes without you, the obvious next step is to run two. One session fixes a bug while another builds a feature, and a third writes tests. It works right up until they share a directory.</p>
<p>Two agents in one checkout are like two people typing into the same document. Session A rewrites <code>auth.ts</code> while session B is halfway through reading it. One runs the formatter across the repo and the other's diff fills with noise. One switches branches, and the other's files change underneath it. Test runs pick up half-finished edits from the other session, so a failure tells you nothing. At best you get a confusing diff; at worst one agent quietly undoes the other's work.</p>
<p>The fix is to give each session its own working directory. Git has had a built-in way to do that since 2015: worktrees.</p>
<h2>What a git worktree is</h2>
<p>A worktree is an extra working directory attached to the same repository. Every worktree has its own files, its own checked-out branch, its own index and its own <code>HEAD</code>. They all share one <code>.git</code> object store, so commits, branches, stashes and remotes are common to all of them.</p>
<p>That's different from cloning the repo again. A second clone duplicates the history and has to fetch and push separately. A worktree only adds the checked-out files, and a commit made in one is visible from every other immediately.</p>
<p>For agents, this is exactly the right shape. Each session gets a private directory to edit, build and test in, and you can still review and merge everything from one place.</p>
<h2>The four commands you need</h2>
<p>Run these from your main checkout.</p>
<h3>Create a worktree</h3>
<pre><code class="language-bash"># New branch "fix-login" in a sibling directory
git worktree add -b fix-login ../myapp-fix-login

# Existing branch
git worktree add ../myapp-review feature/search

# Throwaway checkout with a detached HEAD (no branch)
git worktree add -d ../myapp-scratch
</code></pre>
<p>With <code>-b</code>, the new branch starts from your current <code>HEAD</code>. To start from somewhere else, add the start point at the end:</p>
<pre><code class="language-bash">git worktree add -b fix-login ../myapp-fix-login origin/main
</code></pre>
<h3>List them</h3>
<pre><code class="language-bash">git worktree list
</code></pre>
<pre><code class="language-text">/Users/me/code/myapp            bec18a8 [main]
/Users/me/code/myapp-fix-login  bec18a8 [fix-login]
</code></pre>
<h3>Remove one</h3>
<pre><code class="language-bash">git worktree remove ../myapp-fix-login
</code></pre>
<p>Git refuses if the worktree has modified or untracked files, which is a useful safety net. <code>--force</code> overrides it, so only use that once you're sure nothing in there matters. Removing a worktree doesn't delete its branch. If the branch is merged or abandoned, delete it separately:</p>
<pre><code class="language-bash">git branch -d fix-login    # -D if it was never merged
</code></pre>
<h3>Prune stale entries</h3>
<p>If you delete a worktree folder with <code>rm -rf</code> or Finder instead of <code>git worktree remove</code>, git still has a record of it, and <code>git worktree list</code> marks it as <code>prunable</code>. Clear those records with:</p>
<pre><code class="language-bash">git worktree prune
</code></pre>
<h3>Naming and placement</h3>
<p>Two conventions keep this manageable.</p>
<p><strong>Where to put them.</strong> Either use sibling directories (<code>../myapp-fix-login</code>) or a dedicated folder such as <code>../myapp-worktrees/fix-login</code>. If you'd rather keep them inside the repo, use a folder like <code>.worktrees/</code> and add it to <code>.gitignore</code>, or every file in it shows up as untracked in your main checkout. Siblings are the least surprising for editors and build tools, since nothing ends up nested inside another project.</p>
<p><strong>What to call them.</strong> Name the directory after the branch, and name the branch after the task: <code>fix-login</code>, <code>feat-csv-export</code>, <code>agent/refactor-billing</code>. When you have four terminals open, <code>git worktree list</code> should tell you at a glance which session is doing what.</p>
<h2>Set up each worktree before starting an agent</h2>
<p>A new worktree contains only tracked files. Anything gitignored is missing, and that's usually the stuff your project needs to run.</p>
<p><strong>Dependencies.</strong> <code>node_modules</code>, <code>.venv</code>, <code>target/</code> and friends aren't there. Install them in each worktree:</p>
<pre><code class="language-bash">cd ../myapp-fix-login
npm ci            # or: pnpm install, uv sync, bundle install, cargo build
</code></pre>
<p>This costs disk space and time per worktree. Package managers with a shared cache (pnpm's global store, uv's cache) make repeat installs much cheaper.</p>
<p><strong>Environment files.</strong> <code>.env</code> and <code>.env.local</code> are gitignored, so copy them over:</p>
<pre><code class="language-bash">cp ../myapp/.env .env
</code></pre>
<p><strong>Ports.</strong> Two dev servers can't both listen on port 3000. If a session will run the app, give each worktree its own port, usually through the same env file:</p>
<pre><code class="language-bash">echo "PORT=3001" &gt;&gt; .env
</code></pre>
<p><strong>Databases and services.</strong> If both sessions point at the same local database, one agent's migration or test fixtures can break the other's run. Give each worktree its own database name, or its own SQLite file. If you use Docker Compose, a different <code>COMPOSE_PROJECT_NAME</code> per worktree gives each one separate containers, networks and volumes.</p>
<p>If you repeat these steps often, put them in a small script that creates the worktree, copies env files and installs dependencies.</p>
<h2>Running claude or codex in each worktree</h2>
<p>The manual approach works with any agent. Open one terminal per worktree and start a session in each:</p>
<pre><code class="language-bash"># Terminal 1
cd ~/code/myapp-fix-login &amp;&amp; claude

# Terminal 2
cd ~/code/myapp-csv-export &amp;&amp; codex
</code></pre>
<p>Each session treats its worktree as the project. Because your <code>CLAUDE.md</code> or <code>AGENTS.md</code> is a tracked file, it's present in every worktree automatically. Give each session one focused task with a clear finish line ("done when the login tests pass and lint is clean"), then let it run.</p>
<p>A terminal multiplexer such as tmux keeps several sessions in one window, and lets you detach and come back later. Codex and Claude Code both resume per directory: <code>claude --continue</code> resumes the most recent conversation in the current directory, and <code>codex resume --last</code> does the same for Codex. Running either from inside a worktree picks up that worktree's session.</p>
<h3>Claude Code's built-in worktree support</h3>
<p>Current Claude Code versions can create the worktree for you. Pass <code>--worktree</code> (or <code>-w</code>) with a name:</p>
<pre><code class="language-bash">claude --worktree fix-login
</code></pre>
<p>According to Anthropic's docs, this creates a worktree at <code>.claude/worktrees/fix-login/</code> inside your repo, on a new branch named <code>worktree-fix-login</code>, and starts the session there. Run the same command with another name in a second terminal for a second isolated session. Leave out the name and Claude generates one. A few details worth knowing:</p>
<ul>
<li><strong>Add</strong> <code>.claude/worktrees/</code> <strong>to</strong> <code>.gitignore</code>, as the docs recommend, so those directories don't show up as untracked files in your main checkout.</li>
<li><strong>The base is your default branch, not your current branch.</strong> By default, new worktrees branch from the repository's default branch on the remote (usually <code>main</code>). To branch from your local <code>HEAD</code> instead, set <code>"worktree": { "baseRef": "head" }</code> in settings. For a specific existing branch, create the worktree with git yourself.</li>
<li><code>.worktreeinclude</code> <strong>copies gitignored files.</strong> Put a file named <code>.worktreeinclude</code> at the project root, using <code>.gitignore</code> syntax, and Claude copies matching gitignored files such as <code>.env</code> into every worktree it creates.</li>
<li><strong>Cleanup happens on exit.</strong> When you leave the session, Claude checks the worktree. If it's clean and the session was unnamed, it removes the worktree and its branch. If there are changes or commits, it asks whether to keep or remove it. Non-interactive runs with <code>-p</code> don't clean up, so remove those with <code>git worktree remove</code>.</li>
<li><strong>The repo needs at least one commit</strong>, or worktree creation fails.</li>
</ul>
<p>You can also ask Claude mid-session to "work in a worktree," and custom subagents can run in their own worktree by adding <code>isolation: worktree</code> to their frontmatter.</p>
<h3>Codex CLI's worktree support</h3>
<p>Recent Codex CLI releases have managed worktrees too, though OpenAI describes this as newer functionality, so check <code>codex --help</code> on your version. In an interactive session, type <code>/worktree</code> to start a new chat, or move the current one, into a managed git worktree. There's also a "Browse worktrees" option for finding existing ones. For scripted runs, <code>--worktree</code> works with new and forked runs:</p>
<pre><code class="language-bash">codex exec --worktree "implement the next step"
codex fork &lt;SESSION_ID&gt; --worktree
</code></pre>
<p>The docs say <code>--worktree</code> requires local execution and can't be combined with <code>resume</code>, <code>review</code> or <code>--ephemeral</code>. If you'd rather keep full control over branch names and locations, plain <code>git worktree add</code> plus <code>codex</code> works on every version.</p>
<h2>Reviewing and merging the results</h2>
<p>Every worktree is a branch, so review works like reviewing a colleague's branch. From your main checkout:</p>
<pre><code class="language-bash">git log --oneline main..fix-login     # what it committed
git diff main...fix-login             # the full change
</code></pre>
<p>Uncommitted work only exists inside its worktree, so ask the agent to commit when it's done, or check with <code>git -C ../myapp-fix-login status</code>.</p>
<p>Then merge whichever way your team does: push the branch and open a pull request, or merge locally:</p>
<pre><code class="language-bash">git switch main
git merge fix-login
</code></pre>
<p>Merge one branch at a time and run the tests after each. Two agents that both worked "correctly" in isolation can still conflict, especially when both touched a shared module. When a later branch conflicts, it's often easiest to rebase that branch on the updated <code>main</code> inside its own worktree, and let its session fix the conflicts. It has the context on why it made its changes.</p>
<h2>Cleaning up</h2>
<p>When a branch is merged or abandoned:</p>
<pre><code class="language-bash">git worktree remove ../myapp-fix-login
git branch -d fix-login
git worktree prune
</code></pre>
<p>Check <code>git worktree list</code> every so often. Forgotten worktrees pile up, each with its own <code>node_modules</code>, and keep their branches checked out.</p>
<h2>Common pitfalls</h2>
<p><strong>The same branch can't be checked out twice.</strong> Git won't let two worktrees hold the same branch. If <code>main</code> is checked out in your main directory, <code>git worktree add ../x main</code> fails with <code>'main' is already used by worktree at ...</code>. Create a new branch with <code>-b</code>, use <code>-d</code> for a detached checkout, or remove the worktree that's holding the branch.</p>
<p><strong>Shared lockfiles conflict.</strong> If two sessions both add dependencies, both branches change <code>package-lock.json</code>, <code>pnpm-lock.yaml</code>, <code>uv.lock</code> or <code>Cargo.lock</code>, and the merge conflicts. Don't hand-merge lockfiles. Take one side, re-run the install so the package manager regenerates the file, and commit the result. Better yet, keep dependency changes to one session at a time.</p>
<p><strong>Generated files and migrations collide.</strong> Two branches that each add a database migration with the next sequence number, or that each regenerate an API client, will clash at merge time even if the code is fine. Assign those tasks to one session.</p>
<p><strong>Submodules need extra care.</strong> A new worktree doesn't initialize submodules, so run <code>git submodule update --init --recursive</code> inside it. Git's own docs say submodule support in multiple worktrees is incomplete, and <code>git worktree remove</code> needs <code>--force</code> for a worktree with submodules. If your repo leans heavily on submodules, test the workflow before you rely on it.</p>
<p><strong>Your IDE gets confused.</strong> Opening a worktree nested inside the main project can make an editor index everything twice, run duplicate language servers, or show the same file in search results twice. Open each worktree as its own window (<code>code ../myapp-fix-login</code>), and exclude your worktree folder from the main project's indexing if you keep worktrees inside the repo.</p>
<p><strong>Agents wander.</strong> An agent running in a worktree can still <code>cd</code> back into your main checkout if nothing stops it. Claude Code blocks edits and git commands that target the main checkout while a session is isolated with <code>--worktree</code>. With manual worktrees, tell the agent which directory it owns, and keep sandbox or permission settings scoped to it.</p>
<h2>Parallel sessions burn limits faster</h2>
<p>One last thing that's easy to miss: parallel sessions don't come with parallel quotas. Every Claude Code session on your account draws from the same usage limit, and every Codex session draws from the same ChatGPT plan limit. Four agents running for an hour can use up roughly what one agent would use in four hours, and you hit the limit in the middle of the afternoon, with all four sessions stopping at once.</p>
<p>So run as many sessions as you can actually review, not as many as your machine can handle. Give the cheap, mechanical tasks (renames, test scaffolding, lint fixes) to parallel sessions, and save your heavy reasoning work for one focused session. If you're on API billing instead of a subscription, the same logic applies to your bill.</p>
<h2>A short checklist</h2>
<ul>
<li>The repo has at least one commit and a clean main checkout.</li>
<li>Each task gets its own branch and worktree, named after the task.</li>
<li>Worktrees live in sibling directories or a gitignored folder.</li>
<li>Dependencies are installed and <code>.env</code> files copied in each worktree (or listed in <code>.worktreeinclude</code> for Claude Code).</li>
<li>Each worktree has its own port, database and Compose project name if it runs services.</li>
<li>Each session has one focused task with a clear "done when."</li>
<li>Dependency, lockfile and migration changes are limited to one session.</li>
<li>Agents commit their work before you review it.</li>
<li>Branches are merged one at a time, with tests after each.</li>
<li>Finished worktrees are removed, their branches deleted, and stale entries pruned.</li>
<li>You're watching how fast parallel sessions draw down your shared limit.</li>
</ul>
<p>Worktrees don't make agents smarter. They just stop agents from tripping over each other, which is most of what running several at once requires.</p>
<p>TokenBar is a $15 Mac menu bar app that shows your Claude and Codex usage and cost, which helps when several sessions are draining the same limit. It's at <a href="https://tokenbar.site">https://tokenbar.site</a> if that's useful.</p>
<p>Disclosure: I built TokenBar.</p>
]]></content:encoded></item><item><title><![CDATA[How to Write Better Emails Faster in Apple Mail]]></title><description><![CDATA[Reusable templates, the right signature for each account, Send Later, Undo Send, reminders, keyboard shortcuts, and a simple structure that gets replies I…]]></description><link>https://auramacapps.hashnode.dev/how-to-write-better-emails-faster-in-apple-mail</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-write-better-emails-faster-in-apple-mail</guid><category><![CDATA[macOS]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[writing]]></category><category><![CDATA[email]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Thu, 22 Oct 2026 09:07:26 GMT</pubDate><content:encoded><![CDATA[<p><em>Reusable templates, the right signature for each account, Send Later, Undo Send, reminders, keyboard shortcuts, and a simple structure that gets replies</em></p>
<p>I write a lot of email. It's mostly short stuff: asking for something, answering a question, following up on a thread that went quiet. For a long time I treated Apple Mail as a plain inbox and did everything by hand. Then I spent an afternoon going through its menus and settings, and it turns out Mail already has most of what I was missing.</p>
<p>This is the setup I use now. It's built into Mail, so you don't need any plugins. A few notes before we start:</p>
<ul>
<li>Menu names change a little between macOS versions. On recent versions the settings window is <strong>Mail &gt; Settings</strong>. On older ones it's <strong>Mail &gt; Preferences</strong>.</li>
<li>Send Later, Undo Send, Remind Me, and Follow Up arrived in macOS 13 Ventura. If you're on something older, skip those sections.</li>
<li>Apple Intelligence features only show up on supported Macs, in supported languages and regions, with Apple Intelligence turned on.</li>
</ul>
<h2>1. Keep reusable emails in a Templates mailbox</h2>
<p>Mail doesn't have a proper "templates" feature, so a lot of people either retype the same messages or try Stationery. I do something simpler: I keep good emails in their own mailbox and reuse them.</p>
<p>Here's how to set it up:</p>
<ol>
<li>Choose <strong>Mailbox &gt; New Mailbox</strong>, pick <strong>On My Mac</strong> (or your main account if you want it on all your devices), and call it <strong>Templates</strong>.</li>
<li>Write the email you keep sending: an intro request, an invoice reminder, a "thanks for the call, here are the next steps" note. Leave blanks in brackets like <code>[NAME]</code> and <code>[DATE]</code> so you can spot them easily.</li>
<li>Send it to yourself, then drag the message from your inbox or Sent folder into Templates.</li>
</ol>
<p>When you need it, select the template and choose <strong>Message &gt; Send Again</strong>. Mail opens a new compose window with the same subject, body, and attachments. Fill in the brackets, change the recipient, and send. In my experience Send Again works on messages you sent, which is why I send templates to myself first.</p>
<p>The same trick works on a one-off basis. If you sent a great status update last month, find it in Sent, choose Send Again, and edit it.</p>
<p>Two habits keep this mailbox useful:</p>
<ul>
<li><strong>Name templates by their subject line.</strong> Start the subject with a tag like <code>TEMPLATE - Invoice reminder</code>, then delete the tag before you send.</li>
<li><strong>Prune them.</strong> If you haven't used a template in six months, delete it. Ten good templates beat forty stale ones.</li>
</ul>
<p>For small things like a greeting, a meeting link, or a sign-off, use Text Replacements in <strong>System Settings &gt; Keyboard</strong>. I covered those in an earlier article, so I won't repeat it here.</p>
<h2>2. Set up multiple signatures and pick the right one per account</h2>
<p>If you send from a work address and a personal address, you probably want different signatures. You may also want different signatures for different situations: a full one for first contact, a short one for replies.</p>
<ol>
<li>Open <strong>Mail &gt; Settings &gt; Signatures</strong>.</li>
<li>Select an account in the left column, click <strong>+</strong>, and give the signature a name, like "Full" or "Short".</li>
<li>Type the signature in the right-hand pane. To use your own fonts and links, uncheck <strong>Always match my default message font</strong>.</li>
<li>Use the <strong>Choose Signature</strong> menu under the account list to set that account's default. You can also choose <strong>None</strong>, or have Mail rotate through them at random or in order.</li>
</ol>
<p>While you're writing, the <strong>Signature</strong> pop-up in the compose window lets you switch signatures on the fly. I set "Short" as the default and switch to "Full" only for first contact.</p>
<p>Turn on <strong>Place signature above quoted text</strong>, too. Otherwise your signature ends up below the whole quoted thread, where nobody sees it.</p>
<h2>3. Use Send Later so email arrives at the right time</h2>
<p>I do a lot of writing at night, but I don't want to send a client email at 11:40 PM. Send Later fixes that.</p>
<p>In the compose window, click the small arrow next to the <strong>Send</strong> button. Mail offers a couple of preset times plus <strong>Send Later...</strong>, where you pick an exact date and time. Scheduled messages wait in a <strong>Send Later</strong> mailbox in the sidebar. To change or cancel one, open it there and click <strong>Edit</strong>.</p>
<p>Some things I use it for:</p>
<ul>
<li>Writing replies on Sunday and scheduling them for Monday at 9 AM.</li>
<li>Emailing people in other time zones at the start of their workday.</li>
<li>Sending a reminder the morning before a deadline instead of today.</li>
</ul>
<p>One caution: I wouldn't assume a scheduled email goes out while your Mac is asleep or Mail is closed. For anything important, leave the Mac awake and check the Send Later mailbox afterward.</p>
<h2>4. Give yourself an Undo Send window</h2>
<p>Most of my worst email mistakes happen in the second after I hit Send: the missing attachment, the wrong "Hi Sarah," the reply-all that should have been a reply.</p>
<p>Go to <strong>Mail &gt; Settings &gt; Composing</strong> and find <strong>Undo send delay</strong>. You can choose a short delay (10, 20, or 30 seconds) or turn it off. I use 30 seconds. It's long enough to catch a mistake and short enough that I don't notice it.</p>
<p>After you send, click <strong>Undo Send</strong> at the bottom of the sidebar, or press <strong>Command-Z</strong> right away. The message comes back as an open draft. Mail just holds the email for those few seconds before sending, so this works with any email account, not only iCloud.</p>
<h2>5. Let Mail remind you, and suggest follow-ups</h2>
<p>Some emails you can't deal with right now. Instead of marking them unread and hoping, use <strong>Remind Me</strong>.</p>
<p>Control-click a message in the list (or use the Message menu) and choose <strong>Remind Me</strong>. Pick one of the preset times, or choose <strong>Remind Me Later...</strong> to set your own date. When the time comes, the message jumps back to the top of your inbox.</p>
<p>The flip side is <strong>Follow Up</strong>. If you sent an email and didn't hear back after a few days, Mail can move your sent message to the top of your inbox with a <strong>Follow Up</strong> button. Click it to start a reply to your own message and give the other person a polite nudge. If you find it noisy, you can turn these suggestions off in Mail's settings.</p>
<h2>6. Learn the composing and replying shortcuts</h2>
<p>You don't need to learn every shortcut. These are the ones I use dozens of times a day:</p>
<ul>
<li><strong>Command-N</strong>: new message</li>
<li><strong>Command-R</strong>: reply</li>
<li><strong>Command-Shift-R</strong>: reply all</li>
<li><strong>Command-Shift-F</strong>: forward</li>
<li><strong>Command-Shift-D</strong>: send</li>
<li><strong>Command-Shift-A</strong>: attach files</li>
<li><strong>Command-Option-B</strong>: show the Bcc field</li>
<li><strong>Command-Option-F</strong>: jump to the search field</li>
<li><strong>Command-'</strong> (apostrophe): increase quote level; <strong>Command-Option-'</strong> to decrease it</li>
</ul>
<p>My favorite trick isn't a shortcut, though. <strong>Select a sentence in the original email before you press Command-R</strong>, and Mail quotes just that part. When someone sends five paragraphs and asks one question, quoting only the question makes your reply much easier to follow. If it isn't working, check <strong>Mail &gt; Settings &gt; Composing</strong> for the option that includes only selected text when quoting.</p>
<p>Get in the habit of pausing before Command-Shift-R, too. Reply all is right far less often than people think.</p>
<h2>7. Use a structure that makes replies easy</h2>
<p>Settings and shortcuts make you faster, but structure decides whether people actually reply. I use the same structure for almost every email.</p>
<p><strong>The subject line states the ask.</strong> Write "Can you approve the Q3 budget by Friday?" instead of "Budget." Someone scanning their inbox should know what you need before they open the email.</p>
<p><strong>The first line is the ask.</strong> Don't open with two sentences of background and leave the request at the end. Start with "Could you review the attached contract and send any changes by Thursday?" Put the context after it.</p>
<p><strong>Short paragraphs, one idea each.</strong> Two or three sentences is plenty. If you have several questions, number them so the reply can say "1. Yes, 2. No, 3. Next week."</p>
<p><strong>Make the next step obvious.</strong> End with a clear action and, if there's one, a date. "If I don't hear back by Wednesday, I'll go with option B" saves a whole round of emails.</p>
<p><strong>Cut the warm-up.</strong> "I hope this email finds you well" and "Just checking in" add length without adding anything. A friendly first name and a direct request are polite enough.</p>
<p>Here's a short example:</p>
<p><strong>Subject:</strong> Can we move Thursday's call to 2 PM?</p>
<p>Hi Priya, could we move Thursday's call from 11 AM to 2 PM? Something came up in the morning. If 2 PM doesn't work, Friday any time after 10 is open for me. Thanks, Sam</p>
<p>It takes about 30 seconds to read, the ask is in the subject, and Priya can answer in one line.</p>
<h2>8. Let Apple Intelligence help (if your Mac supports it)</h2>
<p>On Macs that support Apple Intelligence, Mail gets a few writing features worth trying.</p>
<p><strong>Writing Tools.</strong> Select some text in a draft, then Control-click and choose <strong>Writing Tools</strong>, or use the Writing Tools button in the compose window. You can proofread, rewrite, change the tone (friendly, professional, or concise), or turn notes into a list. <strong>Concise</strong> is the one I use most, because my first drafts are always too long.</p>
<p><strong>Smart Reply.</strong> When you reply to some messages, Mail can suggest quick replies based on what the sender asked. It's handy for simple yes/no or scheduling emails. Still read the draft before sending, because it doesn't know the context the way you do.</p>
<p><strong>Summaries.</strong> Mail can summarize long messages and threads, which helps when you're catching up on a thread you were added to halfway through.</p>
<p>If you don't see these, your Mac, macOS version, language, or region may not support them yet. Everything else in this article works without them.</p>
<h2>A quick checklist</h2>
<ul>
<li>Create a <strong>Templates</strong> mailbox and save your three most common emails in it</li>
<li>Reuse them with <strong>Message &gt; Send Again</strong></li>
<li>Set up a short and a full <strong>signature</strong> for each account</li>
<li>Turn on <strong>Place signature above quoted text</strong></li>
<li>Set <strong>Undo send delay</strong> to 30 seconds</li>
<li>Schedule late-night replies with <strong>Send Later</strong></li>
<li>Use <strong>Remind Me</strong> instead of marking messages unread</li>
<li>Learn <strong>Command-R</strong>, <strong>Command-Shift-R</strong>, <strong>Command-Shift-F</strong>, and <strong>Command-Shift-D</strong></li>
<li>Select the relevant text before replying so you quote only that part</li>
<li>Put the ask in the subject and in the first line</li>
</ul>
<p>Do the first five once and you'll feel the difference by the end of the week.</p>
<p>DraftKey is a $5 Mac app that does private, on-device AI autocomplete and rewriting in any app, including Mail (macOS 14+ on Apple Silicon). It's at <a href="https://getdraftkey.com">https://getdraftkey.com</a> if that's useful.</p>
<p>Disclosure: I built DraftKey.</p>
]]></content:encoded></item><item><title><![CDATA[How to Write Slack Messages People Actually Read
]]></title><description><![CDATA[A practical guide to clearer, shorter work messages, with the Mac shortcuts that make it faster Most Slack messages fail in the same way. They're written…]]></description><link>https://auramacapps.hashnode.dev/how-to-write-slack-messages-people-actually-read</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-write-slack-messages-people-actually-read</guid><category><![CDATA[slack]]></category><category><![CDATA[writing]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[macOS]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Thu, 22 Oct 2026 07:08:37 GMT</pubDate><content:encoded><![CDATA[<p><em>A practical guide to clearer, shorter work messages, with the Mac shortcuts that make it faster</em></p>
<p>Most Slack messages fail in the same way. They're written in the order the writer thought of things, so the reader has to scroll through the backstory to find out what's being asked. Then they reply with a question, you answer it, and a two-minute decision takes an afternoon.</p>
<p>You don't need to become a better writer in general to fix this. A handful of habits covers almost all of it. Here's the routine I use, plus the Mac and Slack features that make it quick.</p>
<h2>1. Put the ask in the first line</h2>
<p>Start with what you need from the reader, not with how you got here.</p>
<p>Instead of:</p>
<blockquote>
<p>Hey! So I was looking at the onboarding flow yesterday and noticed the signup numbers dipped after Tuesday's release. I dug in a bit and I think it's the new email step. Anyway, could you take a look?</p>
</blockquote>
<p>Write:</p>
<blockquote>
<p>Can you check whether Tuesday's new email step is hurting signups? They dropped about 15% since the release. Details below.</p>
</blockquote>
<p>The reader knows in one line what you want and whether it's urgent. The backstory can follow for anyone who needs it.</p>
<h2>2. Skip the lone "hi"</h2>
<p>A message that just says "hi" or "got a sec?" makes the other person wait for the real message, and it often lands while they're focused on something else. Send the greeting and the question together:</p>
<blockquote>
<p>Hi Sam, quick one: is the pricing page copy final, or can I still edit it today?</p>
</blockquote>
<p>Now they can answer whenever they look, in one reply.</p>
<h2>3. Make it easy to answer from a phone</h2>
<p>A lot of Slack replies happen on a phone between meetings. Help that person out:</p>
<ul>
<li><strong>Ask yes/no or either/or questions</strong> when you can. "Ship Friday or wait for Monday?" gets an answer; "Thoughts on timing?" gets a meeting.</li>
<li><strong>Number your questions</strong> if there's more than one, so people can reply "1 yes, 2 Monday."</li>
<li><strong>Say what happens if they don't answer.</strong> "If I don't hear back by 3, I'll go with option A" keeps things moving without being pushy.</li>
</ul>
<h2>4. Use formatting, but only a little</h2>
<p>Slack supports bold, bullet lists, and code blocks. A short list beats a dense paragraph when you're giving steps or options. But a message with three headings and five bold phrases looks like a document, and people skim documents.</p>
<p>A good rule: if a message needs more than about eight lines, it probably belongs in a doc or a thread, with a one-line summary in the channel.</p>
<h2>5. Use threads on purpose</h2>
<p>Reply in a thread when you're responding to a specific message, so the channel stays readable. Check <strong>Also send to #channel</strong> only when the outcome matters to everyone, like a final decision. Don't start a new top-level message to continue an old conversation; people lose the context.</p>
<h2>6. Edit before you send</h2>
<p>Most of the value is in a ten-second reread. Before pressing Return, check three things:</p>
<ol>
<li><strong>Is the ask in the first line?</strong></li>
<li><strong>Can I delete a sentence?</strong> Usually the first one ("Hope your week's going well") or the last one ("Let me know if you have any questions").</li>
<li><strong>Would this make sense to someone who wasn't in my head?</strong> Replace "it" and "that thing" with the actual name.</li>
</ol>
<p>Slack also lets you edit after sending, but people often read the first version from a notification, so it's better to fix it before.</p>
<h2>7. Mac and Slack shortcuts that save time</h2>
<p>These are worth learning if you send dozens of messages a day:</p>
<ul>
<li><strong>Shift-Return</strong> adds a new line without sending. Essential for writing lists.</li>
<li><strong>Up Arrow</strong> in an empty message box edits your last message.</li>
<li><strong>Command-K</strong> jumps to any channel or DM.</li>
<li><strong>Command-Shift-A</strong> opens all unreads; <strong>Command-Shift-T</strong> opens threads.</li>
<li><strong>Command-Shift-7</strong> and <strong>Command-Shift-8</strong> start numbered and bulleted lists.</li>
<li><strong>/remind</strong> sets a reminder, such as <code>/remind me to follow up with Sam tomorrow at 10am</code>.</li>
<li><strong>Schedule send</strong>: click the arrow next to the send button to send a message tomorrow morning instead of at 11 PM.</li>
</ul>
<p>On the Mac side, <strong>System Settings &gt; Keyboard &gt; Text Replacements</strong> works inside Slack too. Set up short triggers for things you type constantly, like your calendar link, standard handoff note, or "Thanks, that's all I needed."</p>
<h2>8. Keep a few templates for repeated messages</h2>
<p>If you write the same kind of message every week, like a status update, a bug report, or a handoff, save a template in a Slack saved item, a note, or a text replacement. A simple status update template:</p>
<blockquote>
<p><strong>Done:</strong> … <strong>Next:</strong> … <strong>Blocked on:</strong> … (or "nothing")</p>
</blockquote>
<p>It takes the thinking out of the format so you can focus on the content.</p>
<h2>9. Match the channel's tone</h2>
<p>A short, direct message reads as friendly in a busy engineering channel and can read as curt in a DM to someone you've never worked with. Before writing in a new place, scroll up a bit and match how people there write. Adding one line of warmth ("Thanks for jumping on this") costs nothing and changes how the rest lands.</p>
<h2>A quick checklist</h2>
<ul>
<li>Ask in the first line</li>
<li>No standalone "hi"</li>
<li>Yes/no or numbered questions</li>
<li>Say what happens if nobody answers</li>
<li>Light formatting, eight lines max</li>
<li>Threads for replies</li>
<li>Reread once and cut a sentence</li>
<li>Learn Shift-Return, Up Arrow, Command-K, and schedule send</li>
<li>Text Replacements and templates for repeated messages</li>
</ul>
<p>Try just the first three for a week. You'll notice fewer follow-up questions almost right away.</p>
<p>DraftKey is a $5 Mac app that does private, on-device AI autocomplete and rewriting in any app, including Slack (macOS 14+ on Apple Silicon). It's at <a href="https://getdraftkey.com">https://getdraftkey.com</a> if that's useful.</p>
<p>Disclosure: I built DraftKey.</p>
]]></content:encoded></item><item><title><![CDATA[How to Review Claude Code and Codex Changes Before You Commit: A Practical Checklist]]></title><description><![CDATA[A step-by-step routine for reading what a coding agent actually changed, catching its usual mistakes, and keeping only the parts you trust Coding agents…]]></description><link>https://auramacapps.hashnode.dev/how-to-review-claude-code-and-codex-changes-before-you-commit-a-practical-checklist</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-review-claude-code-and-codex-changes-before-you-commit-a-practical-checklist</guid><category><![CDATA[claude]]></category><category><![CDATA[AI]]></category><category><![CDATA[Git]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Thu, 22 Oct 2026 05:08:05 GMT</pubDate><content:encoded><![CDATA[<p><em>A step-by-step routine for reading what a coding agent actually changed, catching its usual mistakes, and keeping only the parts you trust</em></p>
<p>Coding agents are fast enough now that the slow part of the job has moved. Writing the code takes Claude Code or Codex CLI a few minutes. Making sure the code is right is still on you, and it's tempting to skip. The agent says "All tests pass, the feature is implemented," the terminal looks tidy, and you type <code>git commit -am "add feature"</code>.</p>
<p>Then, three days later, you find out the tests pass because the agent deleted the one that failed.</p>
<p>This is the review routine I use before committing anything an agent wrote. It doesn't need special tools: it's git, your test runner, and a few habits. It takes five to fifteen minutes for a typical change, and that's a lot less time than debugging a bad commit later.</p>
<h2>1. Start from a clean baseline</h2>
<p>Reviewing is much easier when the only uncommitted changes in your tree belong to the agent. Before you start a session, commit or stash your own work:</p>
<pre><code class="language-bash">git status
git stash push -m "my work before agent session"
</code></pre>
<p>Now whatever shows up in <code>git status</code> afterward came from the agent. If you mix your half-finished edits with the agent's, you can't tell which lines you're supposed to be reviewing.</p>
<h2>2. Ask the agent for a summary, then don't trust it</h2>
<p>When the agent finishes, ask it to explain what it did. Something like:</p>
<pre><code class="language-text">List every file you changed, created, or deleted. For each one, say in one
sentence what changed and why. Then list anything you were unsure about,
any tests you modified or skipped, and any new dependencies you added.
</code></pre>
<p>This summary is useful as a map, not as evidence. Agents sometimes describe what they intended rather than what they did, and they tend to leave out the edits they made along the way, like "I also tidied up this other function." Treat the summary as a list of claims you're about to check against the diff.</p>
<h2>3. Read the shape of the change first</h2>
<p>Before reading any code, look at how big the change is and where it landed:</p>
<pre><code class="language-bash">git status
git diff --stat
git diff --name-status
</code></pre>
<p><code>--stat</code> shows lines added and removed per file. <code>--name-status</code> shows whether each file was modified (M), added (A), deleted (D), or renamed (R). This is where you catch the big surprises cheaply:</p>
<ul>
<li>A file you never mentioned has 200 changed lines.</li>
<li>A test file shows up as <strong>D</strong>.</li>
<li><code>package.json</code>, <code>requirements.txt</code>, <code>Cargo.toml</code>, or a lockfile changed when you didn't ask for a dependency.</li>
<li>A config file, CI workflow, or <code>.env.example</code> changed.</li>
</ul>
<p>One trap: <code>git diff</code> doesn't show new files that haven't been staged. Agents create files all the time, so list them explicitly:</p>
<pre><code class="language-bash">git ls-files --others --exclude-standard
</code></pre>
<p>If you want new files to show up in the diff alongside everything else, mark them with intent-to-add. It records that the file exists without staging its contents:</p>
<pre><code class="language-bash">git add -N path/to/new_file.py
git diff
</code></pre>
<h2>4. Read the diff file by file</h2>
<p>Don't scroll through one giant diff. Go a file at a time, starting with the files that matter most (core logic, then tests, then everything else):</p>
<pre><code class="language-bash">git diff -- src/payments/refund.ts
</code></pre>
<p>If the agent reformatted things and the noise is drowning out the real change, ignore whitespace while you read:</p>
<pre><code class="language-bash">git diff -w -- src/payments/refund.ts
</code></pre>
<p>And run <code>git diff --check</code> once to flag trailing whitespace and leftover conflict markers.</p>
<p>For each file, ask three questions: Does this change belong to the task? Do I understand every line of it? What happens when this code gets bad input?</p>
<h2>5. Look for the usual agent mistakes</h2>
<p>Agents make a fairly predictable set of mistakes. They're worth checking for by name, because they don't jump out at you when you're just skimming.</p>
<p><strong>Deleted or weakened tests.</strong> This one matters most. If a test was failing, the fastest way to "fix" it is to delete it, mark it skipped, loosen the assertion, or change the expected value to whatever the code now returns. Look for removed test cases, new <code>skip</code> or <code>xfail</code> markers, <code>.only</code> left in JavaScript tests, and assertions that got vaguer (<code>toEqual(42)</code> becoming <code>toBeDefined()</code>).</p>
<p><strong>Swallowed errors.</strong> An empty <code>catch</code> block, <code>except Exception: pass</code>, a <code>try</code> that logs and carries on, or a <code>?? []</code> that quietly turns a failure into an empty result. These make the error go away without fixing anything.</p>
<p><strong>Invented APIs.</strong> A method that sounds right but doesn't exist in your version of the library, or a config option it guessed at. Type checkers and tests catch some of these. For the rest, check the call against the library's docs or source.</p>
<p><strong>Unrelated edits.</strong> Renamed variables, reordered imports, "improved" functions nobody asked about, or comments deleted. Each one might be harmless, but together they bloat the diff and hide the real change. Revert them unless you actually want them.</p>
<p><strong>Hardcoded values.</strong> Magic numbers, a hardcoded user ID or URL from the example you gave it, a fixed date, a file path that only exists on your machine, or (worst) a real API key pasted in for testing.</p>
<p><strong>New dependencies.</strong> A whole package added to do something your standard library already does. Check that it's real, maintained, and actually needed before you accept it, and look at how much the lockfile changed.</p>
<p><strong>Leftover debris.</strong> <code>console.log</code> and <code>print</code> statements, TODOs, commented-out blocks, scratch scripts, and backup files in the repo root.</p>
<p>A quick search helps with a few of these:</p>
<pre><code class="language-bash">git diff | grep -nE "^\+.*(console\.log|print\(|TODO|FIXME|\.only\(|skip)"
</code></pre>
<p>It's crude and will produce false positives, but it only takes a second.</p>
<h2>6. Run the checks yourself</h2>
<p>The agent saying "tests pass" isn't the same as the tests passing. Maybe it ran a subset, maybe it ran them before its last edit, or maybe the run failed and it misread the output. Run them yourself in your own terminal:</p>
<pre><code class="language-bash">npm test          # or pytest, cargo test, go test ./...
npm run lint      # or ruff check ., cargo clippy, etc.
npm run typecheck # if your project has one
</code></pre>
<p>Use whatever commands your project actually has. If there's a test that covers the feature, make sure it would fail without the change. A quick way to check is to stash the source change, keep the test, and run it again. A test that passes either way isn't testing anything.</p>
<p>If the change is something you can see, like a UI, a CLI, or an endpoint, try it by hand too. Spend two minutes on the happy path and one obvious edge case.</p>
<h2>7. Stage hunk by hunk with git add -p</h2>
<p>This is the habit that makes the biggest difference. Instead of <code>git add .</code>, stage interactively:</p>
<pre><code class="language-bash">git add -p
</code></pre>
<p>Git shows you each hunk and asks what to do with it. The keys you'll use most are <code>y</code> (stage this hunk), <code>n</code> (skip it), <code>s</code> (split it into smaller hunks), <code>q</code> (quit), and <code>?</code> (help). Keep the hunks you've reviewed and agree with, and skip the rest.</p>
<p>It forces you to look at every change one more time, and it lets you commit the good 80% of a session while leaving the questionable 20% unstaged. Before you commit, check exactly what's going in:</p>
<pre><code class="language-bash">git diff --staged
</code></pre>
<p>If you staged something by mistake, unstage it without losing the edit:</p>
<pre><code class="language-bash">git restore --staged path/to/file
</code></pre>
<h2>8. Run a second-pass review with a fresh context</h2>
<p>The agent that wrote the code is a poor judge of it, because it's still anchored to its own reasoning. A new session, or a different tool, does better. Start a fresh Claude Code or Codex session, or paste the diff into one, and give it a narrow, adversarial brief:</p>
<pre><code class="language-text">Review the staged diff (git diff --staged) as a strict senior reviewer.
Do not rewrite anything. Report only:
1. Bugs or edge cases that would break in production
2. Tests that were removed, skipped, or weakened
3. Errors that are caught and ignored
4. Calls to functions or options that may not exist
5. Changes unrelated to the stated goal: &lt;describe the goal&gt;
For each issue, give the file, the line, and why it matters.
</code></pre>
<p>Telling it not to rewrite anything keeps it from opening a new round of edits. Treat what it reports as leads to check, not verdicts. A second model can invent problems as easily as the first one invented APIs.</p>
<h2>9. Keep diffs small enough to review</h2>
<p>Most review pain comes from how the agent was asked, not from the review itself. A prompt like "build the settings page" produces a 900-line diff that nobody reads properly. Smaller asks give you diffs you can actually review:</p>
<ul>
<li>Give the agent one task per session, and say what's out of scope ("don't touch the API layer").</li>
<li>Ask it to stop after each step so you can review and commit before it continues.</li>
<li>Commit working checkpoints often. Small commits are cheap, and each one becomes a safe point to go back to.</li>
<li>If a diff is too big to review honestly, split it with <code>git add -p</code> across a few commits, or throw it out and ask again in smaller pieces.</li>
</ul>
<h2>10. Know when to throw it away</h2>
<p>Sometimes the right review outcome is "no." If the approach is wrong, re-prompting on top of a messy diff usually makes things worse. Reset and try again with a better prompt.</p>
<p>To discard the changes in one file:</p>
<pre><code class="language-bash">git restore path/to/file
</code></pre>
<p>To discard all uncommitted changes to tracked files:</p>
<pre><code class="language-bash">git restore .
</code></pre>
<p>That deletes the work for good, so if you might want any of it back, stash it instead:</p>
<pre><code class="language-bash">git stash push -u -m "agent attempt 1: wrong approach"
git stash list
</code></pre>
<p>The <code>-u</code> flag includes untracked files, which matters because agents create so many of them. Later you can look at it with <code>git stash show -p stash@{0}</code> or bring it back with <code>git stash pop</code>.</p>
<p>For any untracked files left over, preview before you delete:</p>
<pre><code class="language-bash">git clean -n   # shows what would be removed
git clean -f   # actually removes them
</code></pre>
<h2>The checklist</h2>
<p>Before you commit agent-written code:</p>
<ul>
<li>Started from a clean tree, so every change is the agent's</li>
<li>Asked for a summary and checked it against the diff</li>
<li>Read <code>git diff --stat</code>, <code>--name-status</code>, and the list of untracked files</li>
<li>Read every file's diff, most important first</li>
<li>Checked for deleted tests, swallowed errors, invented APIs, unrelated edits, hardcoded values, new dependencies, and debris</li>
<li>Ran tests, linters, and type checks yourself</li>
<li>Staged with <code>git add -p</code> and reread <code>git diff --staged</code></li>
<li>Got a second-pass review from a fresh session on anything non-trivial</li>
<li>Reverted or stashed whatever you didn't trust</li>
</ul>
<p>None of this is new. It's how you'd review a pull request from a fast, confident colleague who sometimes makes things up. The agent writes code much faster than any colleague, which is exactly why the review step can't be skipped.</p>
<p>Disclosure: I built TokenBar, a $15 Mac menu bar app that shows your Claude and Codex usage and cost, which is handy when second-pass reviews start eating into your limits. It's at <a href="https://tokenbar.site">https://tokenbar.site</a>.</p>
<p>Disclosure: I built TokenBar.</p>
]]></content:encoded></item><item><title><![CDATA[How to Proofread Your Own Writing on a Mac]]></title><description><![CDATA[Hear your draft read aloud, run the built-in checker properly, and see your text with fresh eyes, using tools that come with macOS Proofreading your own…]]></description><link>https://auramacapps.hashnode.dev/how-to-proofread-your-own-writing-on-a-mac</link><guid isPermaLink="true">https://auramacapps.hashnode.dev/how-to-proofread-your-own-writing-on-a-mac</guid><category><![CDATA[proofreading]]></category><category><![CDATA[macOS]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[writing]]></category><dc:creator><![CDATA[Aura Technologies]]></dc:creator><pubDate>Wed, 21 Oct 2026 11:13:34 GMT</pubDate><content:encoded><![CDATA[<p><em>Hear your draft read aloud, run the built-in checker properly, and see your text with fresh eyes, using tools that come with macOS</em></p>
<p>Proofreading your own writing is hard for a simple reason: you know what you meant to say. Your brain fills in the missing word, skips the doubled "the," and reads "form" as "from" because it already knows the sentence. Spell checkers catch some of this, but they don't catch a real word in the wrong place, and they never tell you a sentence is clumsy.</p>
<p>The fix is to break the familiarity. Make the text sound different, look different, or arrive in a different order, and the mistakes start to stand out. Your Mac already has tools for all three. Here's how I use them.</p>
<p>A note on names: on macOS Tahoe 26 and later, the speech settings live under <strong>Read &amp; Speak</strong>. On macOS Sequoia 15 and earlier, the same settings are called <strong>Spoken Content</strong>. The steps are otherwise the same.</p>
<h2>1. Have your Mac read your draft out loud</h2>
<p>This is the most useful proofreading trick I know. A synthetic voice can't skim. It reads exactly what's on the page, not what you meant, so missing words, repeated words, and sentences that run out of breath become obvious.</p>
<h3>Turn on Speak Selection</h3>
<ol>
<li>Choose <strong>Apple menu &gt; System Settings</strong>, then click <strong>Accessibility</strong> in the sidebar.</li>
<li>Click <strong>Read &amp; Speak</strong> (or <strong>Spoken Content</strong> on older versions).</li>
<li>Turn on <strong>Speak selection</strong>.</li>
</ol>
<p>Now select some text in any app and press <strong>Option-Esc</strong>. Your Mac reads it aloud. Press <strong>Option-Esc</strong> again to stop. If nothing is selected, it reads the available text in the current window.</p>
<h3>Set it up for proofreading</h3>
<p>Click the info button next to <strong>Speak selection</strong> to see its options. A few are worth changing:</p>
<ul>
<li><strong>Highlight content:</strong> choose words, sentences, or both. With word highlighting on, you can follow along and see exactly where the voice stumbles. This is where you catch "it's" versus "its" and other errors that sound fine but look wrong.</li>
<li><strong>Sentence style:</strong> pick an underline or a background color for the current sentence. I find a background color easier to track.</li>
<li><strong>Show controller:</strong> the controller is a small onscreen panel that lets you pause, change the speaking rate, and skip forward or back one sentence. For anything longer than a paragraph, set this to show automatically so you can jump back and replay a sentence you want to rework.</li>
<li><strong>Keyboard shortcut:</strong> if Option-Esc clashes with something you use, set your own here.</li>
</ul>
<h3>Choose a voice and a speed</h3>
<p>Back on the main settings page, use the <strong>System voice</strong> pop-up menu to pick a voice. Click the info button next to it to adjust how fast and how loud it speaks, and to download more voices.</p>
<p>For proofreading, slower is better than you'd think. At a fast rate, your ears start skimming the same way your eyes do. Try something a bit below a normal speaking pace for a final pass, and faster for a quick first listen.</p>
<h3>Start speaking from the Edit menu</h3>
<p>In many apps, including TextEdit, Pages, Mail, and Notes, you can also choose <strong>Edit &gt; Speech &gt; Start Speaking</strong>, and <strong>Edit &gt; Speech &gt; Stop Speaking</strong> when you're done. It's handy if you'd rather not memorize a shortcut.</p>
<h3>Try Accessibility Reader on newer macOS</h3>
<p>On macOS Tahoe 26 and later, <strong>Read &amp; Speak</strong> also has <strong>Accessibility Reader</strong>. Turn it on in the same settings pane, then press <strong>Command-Esc</strong> in any app. It shows the text in a full-screen view with your choice of font, layout, and background color, and it can read the text aloud with play, pause, skip, and speed controls. You can also open it from <strong>Edit &gt; Speech &gt; Open in Accessibility Reader</strong>.</p>
<h2>2. Use the <code>say</code> command for long drafts</h2>
<p>If you write in Markdown or plain text, Terminal has a built-in text-to-speech command called <code>say</code>.</p>
<p>The basics:</p>
<pre><code class="language-plaintext">say "Testing one two three"
say -f draft.txt
</code></pre>
<p><code>-f</code> reads a file. To pick a voice, use <code>-v</code>; to list every voice installed on your Mac, use <code>-v '?'</code>:</p>
<pre><code class="language-plaintext">say -v '?'
say -v Samantha -f draft.txt
</code></pre>
<p>To set the speed in words per minute, use <code>-r</code>:</p>
<pre><code class="language-plaintext">say -r 160 -f draft.txt
</code></pre>
<p>My favorite option is <code>-o</code>, which saves the speech to an audio file instead of playing it:</p>
<pre><code class="language-plaintext">say -r 170 -f draft.txt -o draft.aiff
</code></pre>
<p>Now you can listen to your draft on a walk, away from the screen, with a notes app open on your phone.</p>
<p>Two more tricks:</p>
<ul>
<li><code>pbpaste | say</code> reads whatever is on your clipboard, so you can copy a paragraph from any app and hear it.</li>
<li>If your draft is in a Word or rich text file, <code>textutil -convert txt draft.docx</code> creates a plain text copy (<code>draft.txt</code>) that <code>say -f</code> can read.</li>
</ul>
<h2>3. Run the spelling and grammar checker on purpose</h2>
<p>Most people only notice underlines as they type. The checker is more useful as a deliberate, separate pass at the end.</p>
<p>In most native apps, open <strong>Edit &gt; Spelling and Grammar</strong>:</p>
<ul>
<li>Choose <strong>Check Grammar With Spelling</strong> so grammar issues are flagged along with spelling. A checkmark shows it's on. Hold the pointer over a flagged word to see a description of the problem.</li>
<li>Choose <strong>Check Document Now</strong> to highlight the first error, then press <strong>Command-Semicolon</strong> to move to the next one.</li>
<li>For a long document, choose <strong>Show Spelling and Grammar</strong> to open a window that steps through each issue with suggestions.</li>
</ul>
<p>A few habits make the checker more trustworthy:</p>
<ul>
<li><strong>Choose between Ignore and Learn carefully.</strong> When you Control-click a flagged word, <strong>Ignore Spelling</strong> skips it in the current document only. <strong>Learn Spelling</strong> adds it to your dictionary, so it's never flagged again anywhere. Learn product names and your own name. Don't learn a typo just to make the underline go away. If you already did, Control-click it and choose <strong>Unlearn Spelling</strong>.</li>
<li><strong>Check a selection when you only changed one part.</strong> In apps like Pages, select a passage first and the Spelling and Grammar window checks just that text.</li>
<li><strong>Don't treat a clean check as a finished proofread.</strong> The checker won't flag "their" for "there," "trial" for "trail," or a sentence that says the opposite of what you meant. That's what the read-aloud pass is for.</li>
</ul>
<p>Grammar checking isn't available in every language or region, so if you don't see grammar flags at all, that may be why.</p>
<h2>4. Change how the text looks</h2>
<p>Your eyes get used to a page's shape. Change it and you'll notice things you skimmed past ten times.</p>
<ul>
<li><strong>Change the font or size.</strong> In TextEdit and many other apps, <strong>Command-T</strong> opens the Fonts window. Switch your draft to a different typeface and size for the final pass, then switch it back.</li>
<li><strong>Zoom in.</strong> In many apps, <strong>Command-Plus</strong> makes text bigger. Fewer words per line means fewer places for an error to hide.</li>
<li><strong>Change the line width.</strong> Resize the window so the lines break in different places. Repeated words like "the the" are easiest to miss when one ends a line and the other starts the next.</li>
<li><strong>Use Reader in Safari.</strong> If you've published something, or you're reviewing a draft on the web, open it in Safari and press <strong>Shift-Command-R</strong> (or choose <strong>Show Reader</strong> from the Smart Search field). Reader strips the page down to the article, and while you're in it you can click the button at the left end of the Smart Search field to change the background, font, and zoom. Press <strong>Esc</strong> to leave Reader.</li>
</ul>
<h2>5. Look up the words you aren't sure about</h2>
<p>Some mistakes aren't typos. They're real words used slightly wrong: "comprise" versus "compose," "discreet" versus "discrete," "flout" versus "flaunt."</p>
<p>When a word gives you even a moment of doubt, select it (or put the pointer over it) and press <strong>Control-Command-D</strong> to show its definition. You can also Control-click the word and choose <strong>Look Up</strong>, or tap with three fingers or force click if you've set that gesture in Trackpad settings. Click <strong>Open in Dictionary</strong> in the popover if you want example sentences and the full entry.</p>
<h2>6. A short human proofreading checklist</h2>
<p>Tools get you most of the way. These habits cover the rest:</p>
<ol>
<li><strong>Take a break first.</strong> Even twenty minutes helps; a night is better.</li>
<li><strong>Do one pass per problem.</strong> Don't try to fix flow, spelling, and facts at once. Do a listening pass for awkward sentences, a checker pass for spelling and grammar, and a separate pass for the items below.</li>
<li><strong>Check names and numbers on their own.</strong> Names, dates, prices, version numbers, and links are where errors cost the most and spell checkers help the least. Compare each one against its source.</li>
<li><strong>Read backwards for typos.</strong> Start at the last sentence and work toward the first. Without the flow of the argument, you see each sentence as a string of words, which is what a typo hunt needs.</li>
<li><strong>Look at the edges.</strong> Headings, captions, the first line, the sign-off, and the subject line of an email get skipped because they're short. Read them one more time.</li>
<li><strong>Recheck what you just changed.</strong> A lot of errors are introduced while fixing other errors: half-deleted words, a verb that no longer matches its new subject. After every edit, reread the whole sentence, not just the word you touched.</li>
</ol>
<p>If you have Apple Intelligence, <strong>Writing Tools</strong> has a Proofread option too, and it's worth running as one more pass. I'd still do the listening pass myself, because it's the one that tells you how the writing actually sounds.</p>
<h2>A routine that fits in ten minutes</h2>
<p>For an email or a short post, this is enough:</p>
<ol>
<li>Run <strong>Check Document Now</strong> with <strong>Check Grammar With Spelling</strong> turned on.</li>
<li>Select everything and press <strong>Option-Esc</strong>. Listen with word highlighting on, and pause to fix anything that sounds off.</li>
<li>Check every name, number, and link against its source.</li>
<li>Read the first and last lines one more time.</li>
</ol>
<p>For anything longer, add a break, a font change, and a backwards read.</p>
<p>Disclosure: I built DraftKey, a $5 Mac app that does private, on-device AI autocomplete and rewriting in any app (macOS 14+ on Apple Silicon). It's at <a href="https://getdraftkey.com">https://getdraftkey.com</a> if that's useful.</p>
<p>Disclosure: I built DraftKey.</p>
]]></content:encoded></item></channel></rss>