<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://bridgetownrb.com/" version="2.0.5">Bridgetown</generator><link href="https://www.brethorsting.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.brethorsting.com/" rel="alternate" type="text/html" /><updated>2026-03-11T20:51:26+00:00</updated><id>https://www.brethorsting.com/feed.xml</id><title type="html">Aaron Brethorst</title><subtitle>Personal website for Aaron Brethorst - Seattleite, technology leader, photographer, transit enthusiast, erstwhile non-runner.</subtitle><author><name>Aaron Brethorst</name></author><entry><title type="html">Changing the Economics of Quality with Claude Code-Generated User Stories</title><link href="https://www.brethorsting.com/blog/2026/03/changing-the-economics-of-quality-with-claude-code-generated-user-stories/" rel="alternate" type="text/html" title="Changing the Economics of Quality with Claude Code-Generated User Stories" /><published>2026-03-11T00:00:00+00:00</published><updated>2026-03-11T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2026-03-11-changing-the-economics-of-quality-with-claude-code-generated-user-stories.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/03/changing-the-economics-of-quality-with-claude-code-generated-user-stories/">&lt;p&gt;Last month I wrote that &lt;a href=&quot;/blog/2026/02/skills-are-the-most-underrated-feature-in-agentic-ai/&quot;&gt;skills are the most underrated feature in agentic AI&lt;/a&gt;. Everything I’ve built since has made me more convinced. The latest example: a user-story-creator skill that I used to &lt;a href=&quot;https://github.com/OneBusAway/vehicle-positions/issues/36&quot;&gt;write a user story&lt;/a&gt; in the &lt;a href=&quot;https://github.com/OneBusAway/vehicle-positions&quot;&gt;OneBusAway vehicle-positions&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;To start, I used Claude’s official &lt;code class=&quot;highlighter-rouge&quot;&gt;/skill-creator&lt;/code&gt; to scaffold the user-story-creator. It generates the SKILL.md frontmatter, suggests which tools to allow, and gives you a working structure in minutes, while providing helpful guard rails. For example, it nudged me toward &lt;code class=&quot;highlighter-rouge&quot;&gt;AskUserQuestion&lt;/code&gt; for clarification instead of having the agent guess, and reminded me to declare &lt;code class=&quot;highlighter-rouge&quot;&gt;allowed-tools&lt;/code&gt; explicitly, small things that prevent runaway behavior from an unconstrained agent. The scaffolding got me to a working first draft fast, skipping the boilerplate and getting straight to the parts that required domain knowledge and human intuition.&lt;/p&gt;

&lt;p&gt;After the initial build, the skill worked but was verbose and had redundant logic. Running &lt;code class=&quot;highlighter-rouge&quot;&gt;/simplify&lt;/code&gt; against it collapsed duplicated instruction blocks, tightened the step definitions, and caught places where I’d over-specified things the model could infer from context. The skill got shorter and more reliable at the same time. I ran &lt;code class=&quot;highlighter-rouge&quot;&gt;/simplify&lt;/code&gt; multiple times during development: after adding the agent integration, after refining the template, after each structural change. It’s become a reflexive part of my skill-building workflow.&lt;/p&gt;

&lt;p&gt;The user-story-creator doesn’t just write a story. Before presenting the draft, it launches two sub-agents in parallel: a Security Engineer and a Product Manager. Each has its own instruction file with role-specific review criteria. For issue #36, the Security Engineer flagged that the &lt;code class=&quot;highlighter-rouge&quot;&gt;POST /api/v1/locations&lt;/code&gt; endpoint has no auth middleware, a critical blocker I knew about but hadn’t thought to surface in the story itself. It produced a full STRIDE threat table and data classification matrix. The PM agent caught that Android 11+ requires a two-step background location permission flow, which would have been a real app-review rejection risk if missed.&lt;/p&gt;

&lt;p&gt;These agents ran concurrently, each taking about a minute, and their findings were merged back into the story automatically. Another &lt;code class=&quot;highlighter-rouge&quot;&gt;/simplify&lt;/code&gt; run surfaced a key design decision: make the agents optional. The skill includes skip conditions. Don’t run a security review on a cosmetic change, don’t run PM review on a config tweak. Knowing when &lt;em&gt;not&lt;/em&gt; to run is as important as having the capability.&lt;/p&gt;

&lt;h2 id=&quot;economics-of-quality&quot;&gt;Economics of Quality&lt;/h2&gt;

&lt;p&gt;I will never learn to write Mermaid syntax for user flow diagrams. I know they’re valuable for my developers and eliminate confusion down the road, but I’m just not going to make them. The skill produces them automatically. Issue #36 has both a flowchart (the full user journey from login through shift start/stop with error branching) and a sequence diagram (the 10-second location reporting loop between the Android app, FusedLocationProvider, and the Go server). They render natively in GitHub.&lt;/p&gt;

&lt;p&gt;A contributor picking up this issue can understand the expected interaction pattern in seconds. The sequence diagram makes the token refresh flow unambiguous in a way that prose acceptance criteria alone don’t. This is what makes the difference between a story implemented correctly the first time and one that takes three rounds of review.&lt;/p&gt;

&lt;p&gt;This is what I mean when I say skills change the economics of quality. The cost of producing these diagrams dropped to zero, so now they exist.&lt;/p&gt;

&lt;p&gt;I typed &lt;code class=&quot;highlighter-rouge&quot;&gt;/user-story-creator&lt;/code&gt; with a two-sentence description and a path to an HTML file containing three mockups. The skill read the mockups, explored the Go codebase, and asked me three targeted multiple-choice questions: setup scope, offline behavior, reporting interval. One round, no back-and-forth.&lt;/p&gt;

&lt;p&gt;It drafted the story, launched the two review agents, merged their findings, and presented the result. I answered the five open questions it surfaced, it folded my answers in, and I said “create a github issue,” and it was done. The result: a thorough user story with 30 acceptance criteria, a STRIDE threat analysis, a SMART assessment, and two Mermaid diagrams, &lt;a href=&quot;https://github.com/OneBusAway/vehicle-positions/issues/36&quot;&gt;filed as a GitHub issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Total wall-clock time from invocation to filed issue: roughly ten minutes. The comparable human process (writing the story, drawing the diagrams, doing a security review, checking SMART criteria, filing it) would have been a half-day exercise, minimum, and it wouldn’t have had the diagrams.&lt;/p&gt;

&lt;p&gt;The user-story-creator skill isn’t magic. It’s a structured procedure: input classification, codebase analysis, clarification, drafting, parallel review, iteration. Encoded so an agent can execute it reliably. Any experienced PM could describe this process on a whiteboard.&lt;/p&gt;

&lt;p&gt;The difference is that a skill runs the process every time, completely, without cutting corners because it’s Friday afternoon. It asks the security questions you’d skip. It draws the diagrams you wouldn’t bother with. It surfaces the Android permission edge case you’d forget.&lt;/p&gt;

&lt;p&gt;That’s the argument for skills: not that they replace judgment, but that they apply it consistently. And consistency, in product work, is the thing that’s actually hard.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">Skills Are the Most Underrated Feature in Agentic AI</title><link href="https://www.brethorsting.com/blog/2026/02/skills-are-the-most-underrated-feature-in-agentic-ai/" rel="alternate" type="text/html" title="Skills Are the Most Underrated Feature in Agentic AI" /><published>2026-02-05T00:00:00+00:00</published><updated>2026-02-05T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2026-02-05-skills-are-the-most-underrated-feature-in-agentic-ai.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/02/skills-are-the-most-underrated-feature-in-agentic-ai/">&lt;p&gt;&lt;a href=&quot;https://agentskills.io&quot;&gt;Agent Skills&lt;/a&gt; are folders of instructions, scripts, and resources that agents can discover and use on demand. They’re an &lt;a href=&quot;https://github.com/agentskills/agentskills&quot;&gt;open standard&lt;/a&gt; that works across Claude, GitHub Copilot, VS Code, Cursor, and OpenAI’s Codex. A skill is just a directory with a &lt;code class=&quot;highlighter-rouge&quot;&gt;SKILL.md&lt;/code&gt; file at its root, optionally accompanied by scripts, reference docs, and templates. That’s it. No fine-tuning, no model retraining, no API integration work. You write instructions in Markdown, put them in a folder, and your agent gets a new capability.&lt;/p&gt;

&lt;p&gt;A custom skill will do more for your daily output than any model upgrade. Agents are only as good as their context, and a frontier model with no knowledge of your codebase, your team’s conventions, or your deployment process produces generic output. Skills close that gap. They give agents procedural knowledge specific to your situation: not just “what” but “how.”&lt;/p&gt;

&lt;p&gt;The design is clever in a way that’s easy to overlook. Skills use progressive disclosure. The agent only sees a skill’s name and one-line description until it determines the skill is relevant. Then it reads the full &lt;code class=&quot;highlighter-rouge&quot;&gt;SKILL.md&lt;/code&gt; instructions. Scripts and reference files within the skill directory are loaded only when actually needed during execution. This means you can have dozens or hundreds of skills available without burning your context window. The agent picks up only what it needs, when it needs it.&lt;/p&gt;

&lt;p&gt;I’ve been building &lt;a href=&quot;https://github.com/aaronbrethorst/claude-skills&quot;&gt;my own skills&lt;/a&gt; and the experience has made me think about how I use agents completely differently. Take my PR review skill, which I adapted from &lt;a href=&quot;https://github.com/anthropics/skills&quot;&gt;Anthropic’s quasi-official example&lt;/a&gt; to fit my own review priorities. Instead of hoping the agent catches everything when I ask it to review a pull request, the skill spins up six specialized review agents covering code quality, simplification opportunities, documentation gaps, test coverage, error handling, and type design. Each agent scores its own applicability to the PR before running, so a documentation-only change doesn’t waste time on type design review. The output is structured, prioritized feedback organized into critical, important, and suggestion tiers. This is not the kind of nuanced, multi-pass review you get from a bare “review this PR” prompt.&lt;/p&gt;

&lt;p&gt;My localization skill is another example. It auto-detects your project’s localization framework (React i18n, iOS &lt;code class=&quot;highlighter-rouge&quot;&gt;.strings&lt;/code&gt;, Android XML, Rails YAML, Django PO, and others), then uses a dual-translation approach with two independent translator agents and an adjudicator to verify quality. It preserves placeholders, HTML tags, pluralization rules, and ICU message formats. I built it once and now I can type &lt;code class=&quot;highlighter-rouge&quot;&gt;/localizer&lt;/code&gt; to translate any project I’m working on. The alternative would be re-explaining this entire workflow to the agent every single time, which means it would never actually happen.&lt;/p&gt;

&lt;p&gt;This is the key insight: skills let you encode workflows that are too complex to type out on demand but too specific to be built into the model. Every team has these. Your deployment checklist. Your code review standards. Your data migration process. Your onboarding documentation generator. These are all skills waiting to be written.&lt;/p&gt;

&lt;p&gt;The portability angle is worth noting too. Because skills are an open standard, a skill you write for Claude Code works in Copilot, Cursor, and Codex. You’re not locked into one vendor’s plugin system. You’re writing portable procedural knowledge.&lt;/p&gt;

&lt;p&gt;If you’re using AI agents and you haven’t looked at skills yet, you’re leaving the most practical productivity gains on the table. The models are good enough. The differentiator now is the context and procedures you give them.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">Projects Aren’t Pets; They’re Cattle</title><link href="https://www.brethorsting.com/blog/2026/01/projects-aren't-pets;-they're-cattle/" rel="alternate" type="text/html" title="Projects Aren&apos;t Pets; They&apos;re Cattle" /><published>2026-01-26T08:00:00+00:00</published><updated>2026-01-26T08:00:00+00:00</updated><id>repo://posts.collection/_posts/2026-01-26-projects-as-cattle.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/01/projects-aren&apos;t-pets;-they&apos;re-cattle/">&lt;blockquote&gt;
  &lt;p&gt;Stop having pet projects; that’s a Staff Engineer’s domain. For a manager, every project is cattle: it needs to be completed, automated, delegated, or cancelled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jampa Uchoa - &lt;a href=&quot;https://www.jampa.dev/p/lessons-learned-after-10-years-as&quot;&gt;Lessons Learned After 10 Years as an Engineering Manager&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I’ve been wrestling with this lately. Standing up a new project, the instinct is to treat it like a pet—wear all the hats, understand every contour. But that founder-to-manager transition needs to happen fast. Pet projects are seductive because they feel like yours; treating them as cattle keeps you from becoming the bottleneck.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">Isometric NYC</title><link href="https://www.brethorsting.com/blog/2026/01/isometric-nyc/" rel="alternate" type="text/html" title="Isometric NYC" /><published>2026-01-22T08:00:00+00:00</published><updated>2026-01-22T08:00:00+00:00</updated><id>repo://posts.collection/_posts/2026-01-22-isometric-nyc.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/01/isometric-nyc/">&lt;blockquote&gt;
  &lt;p&gt;I find the usual conversations about AI and creativity to be pretty boring - we’ve been talking about cameras and sampling for years now, and I’m not particularly interested in getting mired down in the muck of the morality and economics of it all. I’m really only interested in one question:\n\nWhat’s possible now that was impossible before?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Andy Coenen - &lt;a href=&quot;https://cannoneyed.com/projects/isometric-nyc&quot;&gt;Isometric NYC&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;This is an amazing project—it’s like Sim City 2000 but with the actual map of the five boroughs of New York City. This is the sort of project that would be effectively impossible without AI tools, and gives us a peek at an unevenly distributed future. &lt;a href=&quot;https://cannoneyed.com/isometric-nyc/&quot;&gt;Make sure you play around with the map itself&lt;/a&gt;. In fact, you should really start with it before reading Andy’s essay on the construction of the tool and data.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">How the Washington State Legislature Works</title><link href="https://www.brethorsting.com/blog/2026/01/how-the-washington-state-legislature-works/" rel="alternate" type="text/html" title="How the Washington State Legislature Works" /><published>2026-01-14T00:00:00+00:00</published><updated>2026-01-14T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2026-01-14-how-washington-state-legislature-works.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/01/how-the-washington-state-legislature-works/">&lt;p&gt;Washington state has a larger economy than Argentina or Sweden. We’re home to two of the world’s five most valuable companies, a major aerospace manufacturer, the nation’s seventh-largest container port, and a $14 billion agricultural industry. Our state government manages a $78 billion biennial budget.&lt;/p&gt;

&lt;p&gt;And we run all of this with a part-time legislature.&lt;/p&gt;

&lt;p&gt;This is the first in a series of posts I’m planning about how Washington’s state government actually works. Understanding the mechanics matters because the structure shapes the outcomes, and our current structure has some serious problems baked in.&lt;/p&gt;

&lt;h2 id=&quot;legislative-sessions&quot;&gt;Legislative Sessions&lt;/h2&gt;

&lt;p&gt;The Washington State Constitution limits regular legislative sessions to &lt;a href=&quot;https://leg.wa.gov/bills-meetings-and-session/session/&quot;&gt;105 days in odd-numbered years and 60 days in even-numbered years&lt;/a&gt;. The 2025 session ran from January 13 to April 27. &lt;a href=&quot;https://leg.wa.gov/bills-meetings-and-session/session/&quot;&gt;The 2026 session&lt;/a&gt; will be just 60 days from January 12 - March 12.&lt;/p&gt;

&lt;p&gt;The logic behind this schedule: odd years are “budget years” when legislators write the state’s two-year operating budget. Even years are “short sessions” for supplemental adjustments. The assumption is that the heavy lifting happens in the long session, and the short session just handles cleanup.&lt;/p&gt;

&lt;p&gt;In practice, this means even years are triage. There isn’t enough time for major policy initiatives. Bills that didn’t pass in the long session rarely get a second chance in the short one. If your issue isn’t already moving, you’re waiting another year.&lt;/p&gt;

&lt;p&gt;The governor can call special sessions lasting up to 30 days, and legislators can convene themselves with a two-thirds vote in both chambers. But special sessions are politically costly and typically reserved for budget impasses or genuine emergencies.&lt;/p&gt;

&lt;h2 id=&quot;how-a-bill-becomes-law&quot;&gt;How a Bill Becomes Law&lt;/h2&gt;

&lt;p&gt;Every bill introduced in Washington must navigate a committee gauntlet. In its chamber of origin, a bill goes through a Policy committee, then Rules. Bills with fiscal impact also go through a Fiscal committee. If a bill survives and wins a floor vote, the entire process repeats in the second chamber.&lt;/p&gt;

&lt;p&gt;The math is unforgiving. In the 2025 session, legislators introduced &lt;a href=&quot;https://leg.wa.gov/&quot;&gt;roughly 1,900 bills&lt;/a&gt;, which works out to about 18 bills per day that need consideration somewhere in the process, and only 422 passed both chambers. Most bills die in committee, never receiving a hearing. The ones that survive do so because they have powerful sponsors, organized constituencies, or both.&lt;/p&gt;

&lt;p&gt;Once a bill passes both chambers, the governor has 5 days to act if the legislature is still in session, or 20 days if they’ve adjourned. The governor can sign the bill, veto it entirely, or (for budget bills) use a line-item veto to strike specific provisions.&lt;/p&gt;

&lt;h2 id=&quot;what-legislators-do-the-rest-of-the-year&quot;&gt;What Legislators Do the Rest of the Year&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://www.ncsl.org/about-state-legislatures/full-and-part-time-legislatures&quot;&gt;National Conference of State Legislatures classifies Washington as a “Gray” or hybrid legislature&lt;/a&gt;. Legislators report spending more than two-thirds of a full-time job on legislative work, but the compensation doesn’t reflect that.&lt;/p&gt;

&lt;p&gt;During the “interim” (the months between sessions), legislators serve on committees that meet periodically, respond to constituent concerns, attend community events, and prepare for the next session. They receive &lt;a href=&quot;https://www.ncsl.org/about-state-legislatures/2025-legislator-compensation&quot;&gt;$206 per diem&lt;/a&gt; for interim work days.&lt;/p&gt;

&lt;p&gt;But…most of our state legislators also have day jobs. They’re attorneys, teachers, business owners, or sometimes retirees. The part-time model assumes they can maintain careers while also representing 80,000 to 160,000 constituents, for Representatives and Senators, respectively. For some, this works. For others, it means either legislative work or their primary career suffers.&lt;/p&gt;

&lt;h2 id=&quot;the-pay-problem&quot;&gt;The Pay Problem&lt;/h2&gt;

&lt;p&gt;Washington state legislators earn &lt;a href=&quot;https://salaries.wa.gov/salary&quot;&gt;$61,997 per year&lt;/a&gt;, with raises bringing that to $72,494 by mid-2026. These salaries are set by an &lt;a href=&quot;https://salaries.wa.gov/&quot;&gt;independent Citizens’ Commission&lt;/a&gt;, not by the legislators themselves, which is actually a sensible reform most states haven’t adopted.&lt;/p&gt;

&lt;p&gt;But even $72,000 in a state where median household income exceeds $97,000 creates selection pressure. For a software engineer, attorney, or business owner in their peak earning years, engaging in public service means taking a massive pay cut while simultaneously maintaining a second residence in Olympia during session.&lt;/p&gt;

&lt;p&gt;Who can afford this? Retirees with pensions. People with inherited wealth. Young professionals before they have families. Public employees with union-negotiated leave policies. Small business owners who can step back from day-to-day operations. Moms and dads whose partners and kids miss out on time with one parent &lt;em&gt;because public service is that important&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This isn’t a critique of the people who serve—many are dedicated public servants making real sacrifices. But the pool of people who &lt;em&gt;can&lt;/em&gt; serve is constrained by economics or the willingness to sacrifice their happiness and well-being, and that shapes who represents us.&lt;/p&gt;

&lt;h2 id=&quot;why-this-matters&quot;&gt;Why This Matters&lt;/h2&gt;

&lt;p&gt;There is no clear consensus across U.S. states about seating a part time or full-time legislature, although there does seem to be a loose red/blue political valence to the choice. Of the five largest state economies in the country, California, New York, and Illinois have either full time or near-full time legislatures. Texas and Florida have part time legislatures.&lt;/p&gt;

&lt;p&gt;Widening our aperture, Washington has the ninth largest GDP in the country, ahead of Alaska, Hawaii, Massachusetts, Michigan, Ohio, or Wisconsin, all of which have either full time or near-full time legislatures. Does Washington have fewer challenges than Massachusetts or Michigan?&lt;/p&gt;

&lt;p&gt;The complexity of governing an $800 billion economy in 60 to 105 days per year creates pressure that has to go somewhere. It goes to the executive branch, which operates year-round. It goes to lobbyists, who are full-time professionals working part-time legislators. It goes to staff, who provide institutional memory but can’t vote. And it goes to the initiative process, which lets organized groups, funded by private interests, bypass the legislature entirely.&lt;/p&gt;

&lt;p&gt;Each of these pressure valves has consequences. When the legislature can’t act, someone else does—and that someone usually isn’t accountable to voters in the same way. The question isn’t whether Washington’s current system works. It’s about who it serves best and who it fails to serve.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">Vibe-Coded MDM</title><link href="https://www.brethorsting.com/blog/2026/01/vibe-coded-mdm/" rel="alternate" type="text/html" title="Vibe-Coded MDM" /><published>2026-01-11T07:53:00+00:00</published><updated>2026-01-11T07:53:00+00:00</updated><id>repo://posts.collection/_posts/2026-01-11-vibe-coded-mdm.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/01/vibe-coded-mdm/">&lt;blockquote&gt;
  &lt;p&gt;The nature of software development is changing out from under us, and I think we’re kidding ourselves that it’s going to end with just a reconfiguration of how professional developers ship software.&lt;/p&gt;

  &lt;p&gt;I have kids. They have devices. I wanted some control over them. So I did what many of you would do in my situation: I vibe-coded an MDM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kurt Mackey - &lt;a href=&quot;https://fly.io/blog/code-and-let-live/&quot;&gt;Code and Let Live&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Kurt’s point here greatly resembles one &lt;a href=&quot;https://simonwillison.net&quot;&gt;Simon Willison&lt;/a&gt; has been making. We’re approaching an inflection point in how software is made where the real value will come more and more from the higher order thinking about the work and less from the specific, careful process of writing bug-free lines of code.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">The First Telegraph</title><link href="https://www.brethorsting.com/blog/2026/01/the-first-telegraph/" rel="alternate" type="text/html" title="The First Telegraph" /><published>2026-01-10T10:00:00+00:00</published><updated>2026-01-10T10:00:00+00:00</updated><id>repo://posts.collection/_posts/2026-01-10-what-hath-god-wrought.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/01/the-first-telegraph/">&lt;blockquote&gt;
  &lt;p&gt;What hath God wrought&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Samuel Morse - &lt;a href=&quot;https://en.wikipedia.org/wiki/What_hath_God_wrought&quot;&gt;First telegraph message, May 24, 1844&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;On May 24, 1844, Samuel Morse tapped out this message from the Supreme Court Chamber in the Capitol to his partner Alfred Vail in Baltimore. The words came from Numbers 23:23, suggested by Annie Ellsworth, daughter of the Patent Commissioner.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">Washington Should Legalize Balcony Solar</title><link href="https://www.brethorsting.com/blog/2026/01/washington-should-legalize-balcony-solar/" rel="alternate" type="text/html" title="Washington Should Legalize Balcony Solar" /><published>2026-01-09T00:00:00+00:00</published><updated>2026-01-09T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2026-01-09-washington-should-legalize-balcony-solar.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/01/washington-should-legalize-balcony-solar/">&lt;p&gt;This week, Washington state Representatives &lt;a href=&quot;https://leg.wa.gov/legislators/member/zach-hall&quot;&gt;Hall&lt;/a&gt;, &lt;a href=&quot;https://leg.wa.gov/legislators/member/lisa-callan&quot;&gt;Callan&lt;/a&gt;, &lt;a href=&quot;https://leg.wa.gov/legislators/member/julia-reed&quot;&gt;Reed&lt;/a&gt;, and &lt;a href=&quot;https://leg.wa.gov/legislators/member/mari-leavitt&quot;&gt;Leavitt&lt;/a&gt; prefiled &lt;a href=&quot;https://lawfilesext.leg.wa.gov/biennium/2025-26/Pdf/Bills/House%20Bills/2296.pdf&quot;&gt;HB 2296&lt;/a&gt;, a bill that would legalize plug-in “balcony solar” systems in Washington. It’s modeled on Utah’s bipartisan &lt;a href=&quot;https://le.utah.gov/~2025/bills/static/HB0340.html&quot;&gt;HB 340&lt;/a&gt;, which passed unanimously last year, but improves on it in ways that matter for renters and condo owners. The legislature should pass it.&lt;/p&gt;

&lt;p&gt;Balcony solar systems are simple: a standard solar panel, a specialized microinverter, and a plug that goes into a regular wall outlet. In Germany, &lt;a href=&quot;https://happyeconews.com/german-balcony-solar-balconkraftwerke/&quot;&gt;where over a million of these devices are now installed&lt;/a&gt;, you can buy one at a hardware store, hang it on your balcony, and start generating electricity. No electrician. No permits. No utility approval.&lt;/p&gt;

&lt;p&gt;In the United States, this is effectively illegal almost everywhere.&lt;/p&gt;

&lt;p&gt;The barrier isn’t technical. Modern plug-in solar systems include anti-islanding protection that automatically disconnects them during power outages, eliminating the main safety concern. The barrier is regulatory: interconnection agreements designed for large rooftop installations, requirements for licensed electricians to install what amounts to a fancy appliance, and utility approval processes that can take months. These soft costs can double the price of systems that retail for under $1,500 in Europe.&lt;/p&gt;

&lt;p&gt;Utah changed this last year. HB 340 exempts portable solar devices under 1,200 watts from interconnection requirements. The bill passed 72-0 in the House and 27-0 in the Senate. EcoFlow is already &lt;a href=&quot;https://www.ecoflow.com/us/stream-microinverter&quot;&gt;selling its STREAM system there&lt;/a&gt;, though actual energy generation will vary significantly based on sun exposure and installation—a 1,200-watt system in a good location could offset $150-250 annually in electricity costs at typical rates. My back of the envelope calculation suggests that a 1,200 watt balcony solar system on my home would pay for itself in about six years, giving me 14 years of reduced costs—even with Seattle’s historically cheap electricity costs!&lt;/p&gt;

&lt;p&gt;Washington’s HB 2296 builds on Utah’s approach but is more comprehensive in ways that matter.&lt;/p&gt;

&lt;p&gt;The biggest difference is that Washington’s bill explicitly addresses HOAs and landlords. Utah’s bill only constrains utilities. If you’re a renter or live in a condo in Utah, your landlord or HOA can still prohibit balcony solar even though the utility can’t. Washington’s bill amends the HOA statute directly: governing documents “may not prohibit the placement or use of a portable solar generation device by an owner or resident.” Landlords face the same restriction.&lt;/p&gt;

&lt;p&gt;This matters because the people most likely to benefit from balcony solar are exactly the people least likely to own single-family homes. Renters can’t install rooftop solar. Neither can most condo owners. Balcony solar is the only realistic path to solar access for a huge portion of the population, and that path is blocked if property owners can veto it.&lt;/p&gt;

&lt;p&gt;Washington’s bill also includes consumer protection provisions that Utah lacks. Selling a non-compliant device and claiming it can be plugged in without an electrician would be a per se violation of the state’s consumer protection act. Given that the market for these products is still nascent and standards are still being developed, these guardrails against fly-by-night sellers seem prudent.&lt;/p&gt;

&lt;p&gt;The bill creates two certification pathways. Systems over 391 watts need UL 3700 certification—the new standard specifically developed for plug-in solar. Smaller systems can qualify through the state Department of Labor and Industries. The 391-watt threshold isn’t arbitrary; it derives from NEC provisions governing how much power can safely backfeed through a standard 15-amp outlet on a shared circuit.&lt;/p&gt;

&lt;p&gt;HB 2296 isn’t perfect. First, there’s a catch with its greatest improvement over HB 340: the HOA preemption expires in January 2028. If Washington’s state legislature doesn’t renew it, condo owners lose their protection just as the market is maturing. This is a mistake. If the concern is that the market might develop in unexpected ways, the solution is oversight, not a sunset that creates uncertainty for consumers and manufacturers alike.&lt;/p&gt;

&lt;p&gt;Second, the more fundamental limitation is that balcony solar isn’t rooftop solar. A 1,200-watt system won’t power a whole home. But most apartments have some usable sun exposure, and even modest generation adds up. Germany’s experience suggests that households with reasonable orientation can offset 10-20% of their electricity consumption. Across potentially hundreds of thousands of installations, that’s meaningful distributed generation, and helps us begin to prove out the market for small-scale green energy production across the United States.&lt;/p&gt;

&lt;p&gt;The choice isn’t between perfect solar access and no solar access. It’s between letting renters and condo owners participate in distributed solar generation or continuing to reserve solar for people who own detached houses with south-facing roofs.&lt;/p&gt;

&lt;p&gt;Washington’s bill is a good answer to that question. The legislature should pass it.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">Git Rebase for the Terrified</title><link href="https://www.brethorsting.com/blog/2026/01/git-rebase-for-the-terrified/" rel="alternate" type="text/html" title="Git Rebase for the Terrified" /><published>2026-01-07T00:00:00+00:00</published><updated>2026-01-07T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2026-01-07-git-rebase-for-the-terrified.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2026/01/git-rebase-for-the-terrified/">&lt;p&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=46530920&quot;&gt;Join the conversation on Hacker News&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a maintainer of several OneBusAway projects, I regularly ask contributors to rebase their branches before merging. The response is often hesitation or outright fear. I get it. Rebase has a reputation for destroying work, and the warnings you see online don’t help.&lt;/p&gt;

&lt;p&gt;Here’s the thing: the worst case scenario for a rebase gone wrong is that you delete your local clone and start over. That’s it. Your remote fork still exists. The main repository still exists. You can always recover. With that fear addressed, let me show you how to rebase.&lt;/p&gt;

&lt;h2 id=&quot;why-maintainers-ask-for-rebases&quot;&gt;Why maintainers ask for rebases&lt;/h2&gt;

&lt;p&gt;When you create a branch from main and work on it for a few days, the main branch keeps moving. Other PRs get merged. By the time your PR is ready, your branch’s history diverges from main. A merge commit can combine them, but it creates a messy history with interleaved commits that make it harder to understand what changed and why.&lt;/p&gt;

&lt;p&gt;Rebasing replays your commits on top of the current main branch, as if you’d just created your branch today. The result is a clean, linear history that’s easier to review and bisect when tracking down bugs.&lt;/p&gt;

&lt;h2 id=&quot;the-actual-commands&quot;&gt;The actual commands&lt;/h2&gt;

&lt;p&gt;First, make sure you have the upstream repository configured as a remote. If you forked a repo and cloned your fork, you probably only have &lt;code class=&quot;highlighter-rouge&quot;&gt;origin&lt;/code&gt; pointing to your fork:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git remote &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you don’t see the main repository listed, add it:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git remote add upstream https://github.com/OneBusAway/onebusaway-ios.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now fetch the latest changes from upstream:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git fetch upstream
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure you’re on your feature branch:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout your-branch-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Before rebasing, push your current work to your remote fork. This gives you a backup you can recover from if anything goes wrong:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push origin your-branch-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now rebase onto upstream’s main branch:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git rebase upstream/main
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If there are no conflicts, you’re done with the rebase. If there are conflicts, Git will stop and tell you which files need attention.&lt;/p&gt;

&lt;h3 id=&quot;understanding-conflict-markers&quot;&gt;Understanding conflict markers&lt;/h3&gt;

&lt;p&gt;When you open a conflicted file, you’ll see something like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
const timeout = 5000;
=======
const timeout = 10000;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; upstream/main
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is confusing until you know what each section means:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Everything between &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;=======&lt;/code&gt; is &lt;strong&gt;your code&lt;/strong&gt; from the commit being replayed&lt;/li&gt;
  &lt;li&gt;Everything between &lt;code class=&quot;highlighter-rouge&quot;&gt;=======&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; upstream/main&lt;/code&gt; is &lt;strong&gt;the code from main&lt;/strong&gt; that conflicts with yours&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your job is to decide what the final code should look like. Sometimes you want your version, sometimes theirs, sometimes a combination. Delete the markers and leave only the code you want to keep.&lt;/p&gt;

&lt;p&gt;I always use VS Code for this step. Its merge conflict UI is the clearest I’ve found: it shows “Accept Current Change,” “Accept Incoming Change,” “Accept Both Changes,” and “Compare Changes” buttons right above each conflict. You can click through conflicts one at a time without manually hunting for markers.&lt;/p&gt;

&lt;h3 id=&quot;when-conflicts-get-tricky&quot;&gt;When conflicts get tricky&lt;/h3&gt;

&lt;p&gt;Some conflicts are straightforward: two people changed the same line differently. Pick one or combine them.&lt;/p&gt;

&lt;p&gt;Others are harder. If you’re rebasing multiple commits and the same file conflicts repeatedly, it usually means your changes build on each other in ways that don’t cleanly apply to the new base. A few strategies:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Squash first, then rebase.&lt;/strong&gt; If you have many small commits, combine them into one or two logical commits before rebasing. Fewer commits means fewer opportunities for conflicts.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Abort and try a different approach.&lt;/strong&gt; If the conflicts are overwhelming, &lt;code class=&quot;highlighter-rouge&quot;&gt;git rebase --abort&lt;/code&gt; and consider whether your branch has diverged too far. Sometimes it’s easier to create a new branch from main and manually re-apply your changes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Use &lt;code class=&quot;highlighter-rouge&quot;&gt;git rerere&lt;/code&gt;.&lt;/strong&gt; If you find yourself resolving the same conflicts repeatedly, enable rerere (reuse recorded resolution) with &lt;code class=&quot;highlighter-rouge&quot;&gt;git config --global rerere.enabled true&lt;/code&gt;. Git will remember how you resolved conflicts and apply the same resolution automatically next time.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After resolving each file’s conflicts:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add path/to/resolved/file
git rebase &lt;span class=&quot;nt&quot;&gt;--continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Repeat until the rebase completes. If things go sideways and you want to abort:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git rebase &lt;span class=&quot;nt&quot;&gt;--abort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This returns your branch to exactly where it was before you started.&lt;/p&gt;

&lt;h2 id=&quot;validating-your-changes&quot;&gt;Validating your changes&lt;/h2&gt;

&lt;p&gt;After rebasing, verify that your changes still work:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt; upstream/main..HEAD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This shows only your commits that are ahead of main. Make sure they look right. Then build the project and run the tests. Rebasing can sometimes cause subtle issues if upstream changes conflict with your work in ways the merge didn’t catch.&lt;/p&gt;

&lt;h2 id=&quot;force-pushing&quot;&gt;Force pushing&lt;/h2&gt;

&lt;p&gt;Here’s where people get nervous. After rebasing, your local branch has diverged from your remote branch. A normal &lt;code class=&quot;highlighter-rouge&quot;&gt;git push&lt;/code&gt; will fail. You need to force push:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push &lt;span class=&quot;nt&quot;&gt;--force-with-lease&lt;/span&gt; origin your-branch-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;--force-with-lease&lt;/code&gt; flag is safer than &lt;code class=&quot;highlighter-rouge&quot;&gt;--force&lt;/code&gt; because it will fail if someone else has pushed to your branch since you last fetched. This prevents you from accidentally overwriting someone else’s work.&lt;/p&gt;

&lt;p&gt;Never force push to main or any shared branch. Only force push to your own feature branches.&lt;/p&gt;

&lt;h2 id=&quot;when-it-all-goes-wrong&quot;&gt;When it all goes wrong&lt;/h2&gt;

&lt;p&gt;If you’ve made a mess of things and can’t figure out how to recover, here’s the nuclear option:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Push any work you want to save to your remote fork (even to a temporary branch)&lt;/li&gt;
  &lt;li&gt;Delete your local clone&lt;/li&gt;
  &lt;li&gt;Clone fresh from your fork&lt;/li&gt;
  &lt;li&gt;Add the upstream remote again&lt;/li&gt;
  &lt;li&gt;Start the rebase process over&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This has never failed me. Your commits exist on GitHub until you explicitly delete them. You can always recover.&lt;/p&gt;

&lt;h2 id=&quot;one-more-thing&quot;&gt;One more thing&lt;/h2&gt;

&lt;p&gt;Rebasing rewrites commit history. This is fine for feature branches that only you are working on. It’s not fine for branches that others have based work on. If you’re collaborating with someone on a branch, coordinate before rebasing, or just use merge commits instead.&lt;/p&gt;

&lt;p&gt;That’s it. Rebase isn’t scary once you understand that you can always recover. The worst case is a few minutes of recloning. The benefit is a clean project history that’s easier to understand and maintain.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry><entry><title type="html">What Volunteer Open Source Taught Me About Remote Teams</title><link href="https://www.brethorsting.com/blog/2025/12/what-volunteer-open-source-taught-me-about-remote-teams/" rel="alternate" type="text/html" title="What Volunteer Open Source Taught Me About Remote Teams" /><published>2025-12-20T00:00:00+00:00</published><updated>2025-12-20T00:00:00+00:00</updated><id>repo://posts.collection/_posts/2025-12-20-what-volunteer-open-source-taught-me-about-remote-teams.markdown</id><content type="html" xml:base="https://www.brethorsting.com/blog/2025/12/what-volunteer-open-source-taught-me-about-remote-teams/">&lt;p&gt;For the past year, I’ve been leading the development of Maglev, a complete rewrite of the OneBusAway server. The original system was built in Java over a decade ago, and while it still works, it’s showing its age. Maglev is a greenfield project in Go that will eventually replace it entirely.&lt;/p&gt;

&lt;p&gt;The challenge isn’t the technology. The challenge is that my team is almost entirely volunteers, scattered across time zones from Seattle to Europe to Asia. Nobody is getting paid. Nobody has guaranteed availability. Any volunteer could disappear tomorrow because their day job got busy or they just lost interest. This is not how you’d staff a project if you had the choice.&lt;/p&gt;

&lt;p&gt;But you work with what you have, and over the past year I’ve learned some things about making distributed volunteer teams productive that I think apply to remote work more broadly.&lt;/p&gt;

&lt;p&gt;Daily standups don’t work when half your team is asleep and the other half has day jobs. I tried async standups for a while, but participation was inconsistent. What actually works is a dedicated Slack channel where everyone posts what they’re working on, and where I’m relentless about asking for updates. Not aggressive, just persistent. When someone goes quiet for a few days, I check in. When progress stalls, I ask what’s blocking them. The channel becomes a running log of project activity that anyone can catch up on.&lt;/p&gt;

&lt;p&gt;Critical path work must be held for core team members. Everyone on the project is a volunteer, but there’s a difference between the handful of people who’ve been around for years and have proven their reliability, and new contributors who are still figuring out the codebase. If a task is blocking other scheduled work, it needs to be owned by someone with a track record. New contributors are a force multiplier for parallel work, but they can’t be the bottleneck. Let them prove their skill and reliability on non-blocking tasks before putting them on the critical path.&lt;/p&gt;

&lt;p&gt;A rigorously defined vision pays dividends with distributed teams. When everyone can’t be in the same room hashing out requirements, having a written vision document that everyone has read and bought into becomes essential. Early volunteer efforts need to align with where the project is going, or you end up with throwaway work that demoralizes the contributor and wastes everyone’s time. The vision doc isn’t a straitjacket, but it’s the shared understanding that keeps a dozen people in different time zones pulling in the same direction.&lt;/p&gt;

&lt;p&gt;Getting to a dogfoodable state as fast as possible changes everything. Theory is cheap. Running software reveals assumptions. Once we had a version of Maglev that could actually power a real transit app, testing became concrete. Every pull request gets tested against real GTFS feeds. Hidden bugs surface. Integration problems become obvious. Contributors can see their work doing something real, which is vastly more motivating than watching test suites pass.&lt;/p&gt;

&lt;p&gt;Write down every decision. In-person teams can rely on hallway conversations and shared context. Distributed teams can’t. Every meaningful decision needs to end up in a GitHub issue or a wiki page, not buried in a Slack thread that nobody will scroll back to find. This means backfilling documentation after real-time discussions, which feels tedious but pays off constantly. Six months from now, when someone asks “why did we do it this way?”, the answer is a link instead of tribal knowledge that may have left the project.&lt;/p&gt;

&lt;p&gt;Accept a certain loss of control. This is the hardest one. A distributed team of volunteers will make mistakes that an in-person team of full-time employees wouldn’t. Requirements will be misunderstood. PRs will miss edge cases. Documentation will lag. You can minimize this, but you can’t eliminate it. When it happens, treat it as a learning experience and ask yourself what you failed to communicate clearly. If a volunteer misunderstood the requirements, that’s your failure as the maintainer, not theirs as a contributor.&lt;/p&gt;

&lt;p&gt;The interesting thing is that most of these lessons apply to remote work generally, not just volunteer projects. The volunteer context just makes the failure modes more obvious. When you can’t rely on someone’s contractual obligation to show up and do work, you have to be more intentional about communication, documentation, and task allocation. When time zones make synchronous communication expensive, you have to write things down.&lt;/p&gt;

&lt;p&gt;Maglev is now at the point where we’re dogfooding it for real users. We got here with an almost entirely volunteer team, no corporate backing, and no funding. It took longer than it would have with a full-time team, but it’s happening. And the practices we’ve developed to make it work are ones I’d use on any distributed team, paid or not.&lt;/p&gt;</content><author><name>Aaron Brethorst</name></author></entry></feed>