<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://berens.co/feed.xml" rel="self" type="application/atom+xml" /><link href="https://berens.co/" rel="alternate" type="text/html" /><updated>2026-08-16T06:51:16+00:00</updated><id>https://berens.co/feed.xml</id><title type="html">Paul Berens</title><subtitle>berens.co</subtitle><entry><title type="html">Waymos</title><link href="https://berens.co/waymo.html" rel="alternate" type="text/html" title="Waymos" /><published>2026-08-11T00:00:00+00:00</published><updated>2026-08-11T00:00:00+00:00</updated><id>https://berens.co/waymo</id><content type="html" xml:base="https://berens.co/waymo.html"><![CDATA[<p><img src="/assets/og/post_waymo.jpg" alt="A white Waymo robotaxi with a roof-mounted sensor pod crosses an intersection under an overpass, sharp against blurred traffic and buildings." /></p>
<p class="muted small">Waymo robotaxis at 13th &amp; South Van Ness. Photo by <a class="muted" href="https://commons.wikimedia.org/wiki/User:Mliu92" target="_blank">Mliu92</a>, via <a class="muted" href="https://commons.wikimedia.org/wiki/File:Waymo_robotaxis,_San_Francisco_3.jpg" target="_blank">Wikimedia Commons</a> (CC BY-SA 3.0).</p>

<p>Riding my bicycle through the Mission District of San Francisco, I’ve got the same protocol at every intersection, with every vehicle I encounter: peer through the windshield, find the face, and try to catch the eyes. Sometimes I get a courteous wave. Sometimes an expressionless stare. But more often than I’d like, the eyes are down—at a phone, presumably—and I have to figure out when and how to proceed so that I don’t get hit.</p>

<p>The <em>San Francisco Chronicle</em> recently polled San Francisqueños about autonomous vehicles (AVs):</p>

<iframe title="How San Franciscans feel about self-driving cars in San Francisco" aria-label="Bar Chart" id="datawrapper-chart-YDAup" src="https://datawrapper.dwcdn.net/YDAup/1/" scrolling="no" frameborder="0" style="width: 0; min-width: 100% !important; border: none;" height="265" data-external="1"></iframe>
<script type="text/javascript">(function(){function e(){window.addEventListener(`message`,function(e){if(e.data[`datawrapper-height`]!==void 0){var t=document.querySelectorAll(`iframe`);for(var n in e.data[`datawrapper-height`])for(var r=0,i;i=t[r];r++)if(i.contentWindow===e.source){var a=e.data[`datawrapper-height`][n]+`px`;i.style.height=a}}})}e()})();</script>

<p>42% good, 18% bad, and a big fat 39% sitting in the middle with mixed feelings. The Chronicle then breaks the results down by demographic—Progressive, Liberal, Moderate, Conservative, Male, Female, College-educated, No college degree—but I’d like to see it sliced by <strong>Runner</strong>, <strong>Cyclist</strong>, and <strong>¬Runner/Cyclist</strong>, because any San Franciscan who runs or rides through the city would rather share the road with a fleet of Waymos than with the average set of motorists, in a heartbeat. And I suspect very few of them would land in that 39% middle, because the middle isn’t where you sit after you’ve had a close call.</p>

<p>The peer-reviewed safety record is lopsided in Waymo’s favor: 82% fewer injury crashes involving cyclists, 92% fewer involving pedestrians, 82% fewer involving motorcyclists, measured against human drivers in the same places.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>There are good drivers out there (mil gracias), but most of us famously overestimate our talent.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> And look, bumping a Model T down an empty gravel road was one thing, but we aren’t built with the reaction time or the processing bandwidth for <em>today’s</em> traffic complexity.</p>

<p>But the deeper problem isn’t the average driver at all, because cycling safety isn’t a function of the average driver; rather it’s a function of the worst one. Ninety-nine attentive drivers don’t protect you from the hundredth.</p>

<p>None of which means the AVs are there yet. There are real <a href="https://www.nytimes.com/2026/08/10/technology/waymo-expansion-edge-cases.html?smid=tw-share">gaps</a> left to close, and one of the sharpest complaints about robotaxis in this city comes from cyclists, not from Luddites: Waymo has told the SF Bicycle Coalition that pulling into bike lanes for pickups and dropoffs is “normal practice,” and that keeping out of them is “too high a bar.” A cyclist is currently suing after she was doored by an exiting passenger in a marked lane and thrown into a second Waymo blocking the same lane. But notice that failure isn’t perception or judgment or reaction time; it’s a (changeable) <em>product decision</em>—which is precisely why I’m bullish: because a defect fix improves the entire Waymo fleet at once whereas there’s no equivalent patch for our worst drivers; there’s only a reprimand issued after somebody’s already dead.</p>

<p>(Also, yes, we must acknowledge that drivers will lose jobs. That’s a real cost and I don’t mean to wave it away in a parenthetical; it’s just not apropos of this post.)</p>

<p>You can’t make eye contact with a Waymo, but I’ve realized I don’t need to: eye contact is just a mediocre proxy for reliability, an attempt to infer a stranger’s attention through the glass at 20 mph. With AVs you get the reliability without the ritual.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup></p>

<p>Time to hand over the keys, folks. Jeeves is electric now, and isn’t looking at his phone.</p>

<p>— ᴘ. ᴍ. ʙ.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Kusano, K., Scanlon, J., et al., <a href="https://doi.org/10.1080/15389588.2025.2499887" target="_blank">“Comparison of Waymo Rider-Only crash rates by crash type to human benchmarks at 56.7 million miles,”</a> <em>Traffic Injury Prevention</em> (2025). <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Svenson, O., <a href="https://doi.org/10.1016/0001-6918(81)90005-6" target="_blank">“Are we all less risky and more skillful than our fellow drivers?”</a> <em>Acta Psychologica</em> 47 (1981): 143–148. Successfully replicated by Koppel et al. (2023), N = 1,203: 91% rated themselves safer and 93% more skilled than the average driver. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Though there <em>are</em> people working on how these things might signal intent to the rest of us, and I’m sure it’s a harder design problem than it sounds, but it sure would be nice to have both the confirmation and the competence. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Paul Berens</name></author><category term="tech" /><category term="product" /><summary type="html"><![CDATA[It can't come quickly enough.]]></summary></entry><entry><title type="html">L’Étoile du Nord</title><link href="https://berens.co/mn.html" rel="alternate" type="text/html" title="L’Étoile du Nord" /><published>2026-07-07T00:00:00+00:00</published><updated>2026-07-07T00:00:00+00:00</updated><id>https://berens.co/mn</id><content type="html" xml:base="https://berens.co/mn.html"><![CDATA[<blockquote>
  <p>That’s my Middle West—not the wheat or the prairies or the lost Swede towns, but the thrilling returning trains of my youth, and the street lamps and sleigh bells in the frosty dark and the shadows of holly wreaths thrown by lighted windows on the snow. I am part of that, a little solemn with the feel of those long winters…</p>

  <p>— St. Paul native F. Scott Fitzgerald, <cite>The Great Gatsby</cite></p>
</blockquote>

<p><img src="/assets/og/post_drinking.from.hose.png" alt="drinking from a garden hose on a hot summer day" /></p>

<p>We just got back from a few glorious days’ vacation in Minnesota, with a nice blast of heat to warm up my fog-chilled bones. And it occurs to me that the sharp contrasts among the seasons (the opposite of San Francisco) are part of what give Minnesota so much character, and anchor my own childhood memories and nostalgia.</p>

<p>So here’s a year of my Minnesota (conjured while I still can): the sights, the sounds, the sensations.</p>

<h2 id="summer">Summer</h2>

<p>🎧 <a href="https://music.youtube.com/watch?v=xDASfSMHHPQ" target="_blank">“Alex Chilton” – The Replacements</a></p>

<p>I lay supine on the fresh-cut grass in the backyard of our Merriam Park home. The scattered cumulus clouds slowly slide across the mostly sunny day, while a mourning dove’s <em>coo-ah, coo, coo</em> is equally unhurried, and the sheets on the clothesline <em>flap-flop</em>. It’s hot (mid-80s [Fahrenheit]), but not as hot as yesterday over at Fort Snelling where the sun scorches the long grasses, and the grasshoppers’ long, droning chirps let you know it’s summer… if you hadn’t noticed already. On such days, the sun-warmed sap of the white spruces and white pines emits this sweet ‘n’ spicy, uniquely refreshing resin aroma. But even when you sweat in the heat and humidity—at Grand Ol’ Days in June, at the Basilica Block Party in July, at the State Fair in August—you welcome it because it won’t last long.</p>

<p><em>It’s summer in Minnesota.</em></p>

<h2 id="autumn">Autumn</h2>

<p>🎧 <a href="https://music.youtube.com/watch?v=sWk9KjHQVtg" target="_blank">“Alone” – Trampled by Turtles</a></p>

<p>Then the days and nights grow more brisk…maybe a touch before you’re ready. The sky is a solid light grey and the wind whips through the trees. As you inhale, the cool air is mixed with woodsmoke from the first fireplace fires of the season. Bring on the Honeycrisp apple pies and hearty hotdishes (casseroles), and high school football under Friday night lights. Dry oak leaves <em>skitter</em> across the pavement, but the ones in the yard are raked into big tannic-scented piles.</p>

<p><em>It’s autumn in Minnesota.</em></p>

<h2 id="winter">Winter</h2>

<p>🎧 <a href="https://music.youtube.com/watch?v=3w68krri0bw" target="_blank">“Re: Stacks” – Bon Iver</a><sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>Even when the January temps are cold enough to sting the nostrils, bright bluesky days still lift the spirits…and give you hope. Shinny (tennis ball, no high-sticking, no checking) with kids aged seven to 17 at Groveland Park’s outdoor ice rink. If we dressed properly—and we typically did—the cold didn’t intimidate us, and it made coming back into the warm house <em>hygge</em>.</p>

<p>Driving at night in a snowstorm as best described by David Rhodes in <em>Driftless</em>:</p>

<blockquote>
  <p>The pickup’s headlights did not penetrate very far into the blowing snow, a situation made worse by her inability to suffer the dizzying sight of warp speed interstellar space travel whenever she attempted to use the high beams.</p>
</blockquote>

<p>Scraping our way down the icy slopes of Afton Alps and Hyland Hills Ski Area, and later running slalom gates under the lights of Buck Hill<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup>.</p>

<p><em>It’s winter in Minnesota.</em></p>

<h2 id="spring">Spring</h2>

<p>🎧 <a href="https://music.youtube.com/watch?v=HGzHFMJ3mc8" target="_blank">“New Morning” – Bob Dylan</a></p>

<p>Winter habitually overstays its welcome—as Prince says, ‘sometimes it snows in April’—drawing groans in unison when it does. Of course, we couldn’t wait for spring either: street hockey on Rollerblades with half-melted snow and ice remnants at the edges, water trickling into the gutters. But everything is muddy and dingy until the first real rains thaw the earth, coaxing out the earthworms and releasing everything held tight all winter. And then the first mowed grass and the lilacs sweeten the air, and eventually the air is just warm enough to warrant opening the windows and letting the breeze freshen the house. The black-capped chickadee’s <em>fee-bee</em>—its true spring song—reassures:</p>

<p><em>It’s spring in Minnesota.</em></p>

<h2 id="hiraeth">Hiraeth</h2>

<p>But the child’s Minnesota and the present one aren’t the same place, much as I’d love to step back into it. The Welsh have a word for the ache of longing for a home you can’t return to: <em>hiraeth</em>. I might still lie back on the fresh-cut grass and hear the mourning dove’s <em>coo</em>; it just wouldn’t be the same grass, the same dove…much less the same me (as <a href="/alice.html">Alice would point out</a>). As Derek Sivers puts it, geography is four-dimensional: you can only know a place as it was at a time<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup>. Much of the Minnesota I love is stamped with a <em>when</em> I can only reach through faded memories.</p>

<p>— ᴘ. ᴍ. ʙ.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Justin is technically a Sconnie, but Eau Claire is, what, an hour from the Minnesota border? I’m claiming him. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>The rule was that we practice at anything above -5°F / ~-20°C (windchill not factored), and I distinctly remember the pain of thawing a foot in the chalet post-practice when it was right around that temperature cut-off. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p><a href="https://sive.rs/4d">Geography is four-dimensional</a> <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Paul Berens</name></author><category term="places" /><summary type="html"><![CDATA[A sensory tour through Minnesota's seasons]]></summary></entry><entry><title type="html">1 in 6,500,000</title><link href="https://berens.co/odds.html" rel="alternate" type="text/html" title="1 in 6,500,000" /><published>2026-06-03T00:00:00+00:00</published><updated>2026-06-03T00:00:00+00:00</updated><id>https://berens.co/odds</id><content type="html" xml:base="https://berens.co/odds.html"><![CDATA[<p>Yesterday, I headed out for a regular training run. It’s my <a href="/runs/twin-peaks-sutro/">Twin Peaks Mt. Sutro loop</a> that I crafted a few years ago and quite enjoy but don’t all that often: South Peak, North Peak, over to the UCSF trails on Mt. Sutro, down through the Parnassus Campus, and up Eighth Avenue toward home.</p>

<p>As I ascend the steps to the parking lot level of Twin Peaks, I meet two older women who ask a breathless me for directions. We chat briefly, they thank me for stopping—I didn’t have much of a choice given my aerobic condition—and then we go on our separate merry ways, them taking their time on the ascent of South Peak and me trying to get after it to train for the <a href="/runs/dipsea/">Dipsea Race</a>.</p>

<p><img src="/assets/og/post_mt-sutro-twin-peaks.jpg" alt="Mt Sutro and Twin Peaks" />
<span class="muted small">(L-R): Mt. Sutro, North Peak, and South Peak; as seen from our kitchen window on a lucky St. Patrick’s Day, 2025.</span></p>

<p>I’m heading up Eighth, some forty or forty-five minutes after the staircase encounter, rounding one of the last few blocks before home, and I take a second glance at a woman getting out of a car.</p>

<p><em>Did you just happen to be on Twin Peaks?</em> I ask.</p>

<p><em>You’re the same guy! Where do you live,</em> she inquires.</p>

<p>Less than a quarter mile away, it turns out. I assert that it was God’s Providence that we met not once but twice this day, because <strong><em>what are the odds?</em></strong></p>

<p>Indeed. What <em>are</em> they:</p>

<p>Well, we can safely assume Carol visits Twin Peaks infrequently since she and her friend had to ask for directions, so let’s be generous and peg that at one visit per annum—although it’s probably far less frequent in reality. The timing window of her arriving at her home and getting out of the car was perhaps thirty seconds wide since I was running and not walking by, against a plausible overlap window of twenty or thirty minutes, I’d guess: call it one in fifty odds.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Factor</th>
      <th style="text-align: left">Assumption</th>
      <th style="text-align: left">Odds</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left">I run this route</td>
      <td style="text-align: left">~10x/year</td>
      <td style="text-align: left">1 in 36 days</td>
    </tr>
    <tr>
      <td style="text-align: left">Carol visits Twin Peaks</td>
      <td style="text-align: left">~1x/year</td>
      <td style="text-align: left">1 in 365 days</td>
    </tr>
    <tr>
      <td style="text-align: left">We overlap on the mountain</td>
      <td style="text-align: left">My ~1hr window out of 10 daylight hrs</td>
      <td style="text-align: left">1 in 10</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>We are both there at the same time</strong></td>
      <td style="text-align: left">Combined above</td>
      <td style="text-align: left"><strong>1 in 131,400</strong></td>
    </tr>
    <tr>
      <td style="text-align: left">I pass her house as she exits her car</td>
      <td style="text-align: left">~30 sec overlap out of ~25 min plausible window</td>
      <td style="text-align: left">1 in 50</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>Combined probability</strong></td>
      <td style="text-align: left"> </td>
      <td style="text-align: left"><strong>1 in 6,500,000</strong></td>
    </tr>
  </tbody>
</table>

<p>But there’s another fun wrinkle: somewhere on the trail that runs along Twin Peaks Boulevard, a man had stopped me to confirm his route—a twenty-second exchange that may have been exactly the delay required to place me at the top of those stairs at the same time Carol and friend arrived. Pull that thread and you find another beneath it. The causality just doesn’t bottom out.</p>

<p>The tiny odds are amusing, but it’s also the texture of it—just think of how many frictionless near-misses must precede the one that lands.</p>

<p>Happy Global Running Day.</p>

<p>— ᴘ. ᴍ. ʙ.</p>]]></content><author><name>Paul Berens</name></author><category term="places" /><summary type="html"><![CDATA[A chance set of events.]]></summary></entry><entry><title type="html">Avenue of Mysteries</title><link href="https://berens.co/ave-mysteries.html" rel="alternate" type="text/html" title="Avenue of Mysteries" /><published>2026-05-19T00:00:00+00:00</published><updated>2026-05-19T00:00:00+00:00</updated><id>https://berens.co/ave-mysteries</id><content type="html" xml:base="https://berens.co/ave-mysteries.html"><![CDATA[<p><img src="/assets/og/bkreview_ave_mysteries.jpg" alt="Avenue of Mysteries by John Irving" style="width: 160px; height: auto;" /></p>

<p>I didn’t love it. And I <em>do</em> like Irving. But my problems were:</p>
<ol>
  <li>Catholic themes felt sacrilegious and unconvincing.
    <ul>
      <li>I may be too sensitive here, but Irving’s use of Catholic iconography came across as surface-level and hollow.</li>
      <li>The theology was too basic to engage with seriously. For example, Juan Diego holds the predictable progressive Catholic positions (pro-choice, anti-Church-on-sexuality) without ever really wrestling with them—they’re held as priors, not arrived at.</li>
      <li>In contrast, <em>A Prayer for Owen Meany</em>, which I read decades ago and loved; took faith, doubt, and providence a little more seriously</li>
    </ul>
  </li>
  <li>Too much lasciviousness for my taste. Call me prudish, but the erotic content (with Miriam and Dorothy mostly) felt gratuitous rather than purposeful.</li>
  <li>The heightened reality / myth-making—dump kids, a mind-reading sister, psychic lions—didn’t work for me. I mean, it was amusing/interesting in places but overall I couldn’t get into it.</li>
</ol>

<p>— ᴘ. ᴍ. ʙ.</p>]]></content><author><name>Paul Berens</name></author><category term="books" /><category term="theology" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Humani Nihil a Me Alienum Puto</title><link href="https://berens.co/good-and-evil.html" rel="alternate" type="text/html" title="Humani Nihil a Me Alienum Puto" /><published>2026-05-06T00:00:00+00:00</published><updated>2026-05-06T00:00:00+00:00</updated><id>https://berens.co/good-and-evil</id><content type="html" xml:base="https://berens.co/good-and-evil.html"><![CDATA[<p>Remember Cops &amp; Robbers? It was clear: there were good guys and there were bad guys. The world made sense.</p>

<p>And then you get older, and life and literature<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> instruct us that evil can be more nuanced: e.g., ends justify the means conflicts, the corruption of the good / redemption of the evil, etc.</p>

<p>But at the same time there are narratives that keep bringing us back to cosmic dualism: maybe best expressed in our <strong>cancel culture</strong> or <strong>true crime culture</strong> where we virtue signal through performative outrage.</p>

<p>The first move for those condemning others in the town square (Twitter/X, Substack, etc.) is to first to put some distance between themselves and the other guys: affirmation of self; discounting and forgetting my own sins. And then it’s: <em>oh, I would never do that. I would never say that. Because I’m not perfect, but at least I’m not like him…who is almost evil.</em><sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>In fact there’s a concept called <strong>moral pollution</strong> which describes acting like bad reputations are contagious, and mere proximity to something labelled immoral is dangerous/toxic. Brands cut ties with people deemed unethical not because they value ethics, but because they fear contamination (cancellation as moral quarantine).</p>

<p>But Aleksandr I. Solzhenitsyn is much more thoughtful in <em>The Gulag Archipelago:</em></p>

<blockquote>
  <p>Gradually it was disclosed to me that the line separating good and evil passes not through states, nor between classes, nor between political parties either—but right through every human heart—and through all human hearts. This line shifts. Inside us, it oscillates with the years. And even within hearts overwhelmed by evil, one small bridgehead of good is retained. And even in the best of all hearts, there remains…an unuprooted small corner of evil.</p>
</blockquote>

<p>That’s not to say we can’t and ought not name evil and seek it out and fight it courageously, but it does mean that we should do so with humility and not triumphalism.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup></p>

<p>The Roman playwright Terence put it this way: <em>Homo sum, humani nihil a me alienum puto</em> (“I am a human being; nothing human is alien to me.”) Maya Angelou returned to this line throughout her life, and explained why it matters:</p>

<blockquote>
  <p>‘I am a human being. Nothing human can be alien to me.’ If you can internalize at least a portion of that, you will never be able to say of an act, of a criminal act, ‘Well I couldn’t do that.’ No matter how heinous the crime, if a human being did it you have to say ‘I have in me all the components that are in her, or in him…’</p>
</blockquote>

<p>Because after all, sin <em>(mysterium iniquitatis)</em> entered the world and we’re naive if we deny it or put our blinders on. Remember the line from <em>The Usual Suspects</em>: “The greatest trick the Devil ever pulled was convincing the world he didn’t exist.” There’s indeed a dangerous trap to avoid: if I think myself too “good” I might move toward believing I’m not in need of a savior—save me from what?—which might mean I’ve already “earned” heaven from being such a good guy. This is <strong>Pelagianism</strong> and it’s rampant.</p>

<p>Revelation 3:16-17:</p>
<blockquote>
  <p>So, because you are lukewarm, neither hot nor cold, I will spit you out of my mouth. For you say, ‘I am rich and affluent and have no need of anything,’ and yet do not realize that you are wretched, pitiable, poor, blind, and naked.</p>
</blockquote>

<p>If that’s the Christian lens, the behavioral economics lens is the <a href="/systems/"><strong>Licensing Effect</strong></a>, where believing you’re good can actually make you behave badly: i.e., those who consider themselves virtuous worry less about their own behavior, making them more susceptible to ethical lapses.</p>

<p>And how do you end up considering yourself virtuous? By defining virtue<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup> yourself, on your own terms; as opposed to looking to scripture and law, the saints and philosophers, etc.</p>

<p>So what do we do with all this? We can’t stop naming and calling out and thwarting evil lest we succumb to cowardice — but that must be balanced with humility.</p>

<p>Dom Christian de Chergé was a Trappist monk who remained in Algeria knowing he would likely be killed…and was. Shortly before his martyrdom, he wrote: “I have lived long enough to know that I am an accomplice in the evil which seems to prevail so terribly in the world, even in the evil which might blindly strike me down.”</p>

<p><img src="/assets/og/post_taking_of_christ-caravaggio.jpg" alt="Taking of Christ, Caravaggio, 1602" />
<span class="muted small"><i>The Taking of Christ,</i> Caravaggio (c. 1602). The figure holding the lantern at right is believed to be Caravaggio himself — present at the betrayal, looking on. He doesn’t exempt himself from the scene…and neither can we.</span></p>

<p>Maybe the nuance here is that instead of letting people off the hook, there is still an accounting; but instead of demonizing and continuing to hold in contempt, this humility we speak of requires <strong>forgiveness</strong>. C. S. Lewis says that to be a Christian means to forgive the inexcusable because God has forgiven the inexcusable in you.</p>

<p>The theological ground for this is <em>Imago Dei</em>: that every human being, however contemptible by their actions and disfigured by sin, bears the image and likeness of God. Sin obscures that image, but cannot erase it. Despite everything, they remain a child of God—someone for whom Christ died.</p>

<p>This is the corrective to both the cancel culture impulse and the Pelagian trap: not the relativizing <em>I guess what they did wasn’t so bad,</em> but <em>I share in the same fallen nature, and I am commanded to love what God loves.</em></p>

<p>— ᴘ. ᴍ. ʙ.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><em>The Brothers Karamazov,</em> <em>Les Misérables,</em> <em>Hamlet,</em> <em>Fargo,</em> etc. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Aristotle noticed this, too: in his <em>Nicomachean Ethics</em> IX.4 he observes that ordinary men, “poor creatures though they may be,” exhibit the marks of self-friendship precisely because they are “satisfied with themselves and think they are good.” <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>St. Nicholas remembered this about all children: in Hungary he leaves both treats and some twigs (a switch), because no one is either all good nor all bad. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>I won’t go all the way down the relativism rabbit hole, but this reminds me of Bishop Robert Barron’s frequent citation of the 1992 Supreme Court case <em>Planned Parenthood v. Casey</em>, where he highlights the passage authored by Justice Kennedy: “At the heart of liberty is the right to define one’s own concept of existence, of meaning, of the universe, and of the mystery of human life.” <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Paul Berens</name></author><category term="theology" /><category term="culture" /><category term="first principles" /><summary type="html"><![CDATA[The line separating good and evil passes not through states, nor classes, nor political parties; but through every human heart.]]></summary></entry><entry><title type="html">Swarma</title><link href="https://berens.co/swarma-app.html" rel="alternate" type="text/html" title="Swarma" /><published>2026-03-29T00:00:00+00:00</published><updated>2026-03-29T00:00:00+00:00</updated><id>https://berens.co/swarma-app</id><content type="html" xml:base="https://berens.co/swarma-app.html"><![CDATA[<p>I’m old school fringe consumer tech: <a href="https://en.wikipedia.org/wiki/Path_(social_network)">Path</a> for social media, <a href="https://en.wikipedia.org/wiki/Songza">Songza</a> for music, Foursquare—now <a href="https://swarmapp.com/">Swarm</a>—for lifelogging.</p>

<p>I’ve also deepened my commitment to Google hardware over the years—first Google Home, then <a href="/phones/">Pixel phone</a>, now Pixel Watch.</p>

<p>But there’s no Swarm app on Wear OS (!), which leaves the 63 of us in this cross-sectional segment with a choice: find and beg a Swarm product manager to prioritize it in the backlog, or vibe-code it.</p>

<p>Option B is a lot more realistic (and fun), and thus <strong>Swarma</strong>™ (pronounced <em>shawarma)</em> was born.</p>

<p>This is my third or fourth <a href="/vibe-coding.html">vibe-coding</a> project with Claude as co-pilot: I’ve done <a href="/now/">APIs</a>, a <a href="/song-bot.html">Telegram bot</a>, <a href="/dark-mode.html">dark mode</a>, etc. The pattern is familiar by now: describe what I want, iterate, and ship it. But this time the <em>platform</em> was completely new to me: Android Studio, Kotlin, Jetpack Compose, Wear OS.</p>

<p>The core app logic came together relatively easily: hitting the Foursquare Places API, grabbing nearby venues, displaying a scrollable list, etc. Then Claude handled the Kotlin syntax, the Compose UI components, the API calls, same as it would in JavaScript or Python.</p>

<p>What <em>wasn’t</em> interchangeable was everything around the code:</p>

<ul>
  <li><strong>Environment.</strong> Android Studio generated a project that immediately failed to build. Then a Gradle plugin version didn’t exist. And my corporate VPN was silently blocking downloads via SSL inspection—🤫. Next the Wear OS template ships with the wrong UI library. And finally the app crashes on first launch for missing permissions that the compiler never warned me about. So all of the above you’d chalk up to platform faffing; not coding problems. So I just spent more cycles having Claude diagnose them, because in many cases I didn’t know the right questions to ask (or the best way to ask them).</li>
  <li><strong>UX decisions.</strong> Lo and behold, the Foursquare API treats the radius parameter as a suggestion; not a hard limit, and so venues were populating 8km away when I’d asked for 300 meters. An actual product decision: do I trust the API’s venue ranking, or enforce my own filtering and sorting? I’ve tested various tunings and have landed at a good middle ground, methinks, but the points is that a co-pilot doesn’t have all the product context to make that call.</li>
  <li><strong>OAuth on a browserless device.</strong> The app needs Foursquare authentication, which means OAuth, which means a browser, but wait: there <em>is</em> no browser on Wear OS. I hadn’t thought of how to get the token in there so my first design had a form field where I actually had to bang in the 48-character token on the watch keyboard, which is either comical or infuriating depending on how much sleep you got the night before. This led me to create a companion phone app, which would open a Chrome Custom Tab, intercept the OAuth redirect via authorization code flow, and send the token to the watch via Bluetooth. Minimal, one-time setup.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></li>
</ul>

<p>Vibe-coding scales to unfamiliar platforms as long as you can identify and decompose the problem. The AI handles syntax and boilerplate. So it seems the hard parts of building have shifted from the code (implementation) to everything else: environment, architecture, product judgment, platform constraints…at least where I sit here in early 2026<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup>.</p>

<p>The whole thing—from opening Android Studio for the first time to checking into a Foursquare venue from my watch—took about an afternoon (a.k.a. naptime) to get sorted.</p>

<p><img src="/assets/og/swarma/pixel.app.drawer.png" alt="Swarma on Pixel Watch" /><span class="muted small">Swarma v1.0, now in closed testing on the Play Store.</span></p>

<p>Swarm lives on the Pixel Watch 🤘</p>

<p>— ᴘ. ᴍ. ʙ.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>The first version of the companion app used a WebView instead of a Chrome Custom Tab—meaning users were authenticating inside my app rather than on Foursquare’s own site. A tester on the Wear OS subreddit (<a href="https://www.reddit.com/user/sorross/">u/sorross</a>) flagged it immediately as a bad design (why would I feel comfortable giving a third party app full account control?). He was right, and so I took an hour and fixed it. The co-pilot had taken the path of least resistance, but a savvy human caught it. Which is another lesson here. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>I’m confident this post will age rapidly. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Paul Berens</name></author><category term="tech" /><category term="product" /><summary type="html"><![CDATA[What vibe-coding a wearable app taught me about where the hard parts have shifted.]]></summary></entry><entry><title type="html">Desirable Difficulties</title><link href="https://berens.co/spanish.html" rel="alternate" type="text/html" title="Desirable Difficulties" /><published>2026-02-27T00:00:00+00:00</published><updated>2026-02-27T00:00:00+00:00</updated><id>https://berens.co/spanish</id><content type="html" xml:base="https://berens.co/spanish.html"><![CDATA[<p>People are always surprised when they find out I speak Spanish. I don’t speak perfectly, but well enough to hold a real conversation, and well enough that occasionally someone asks <em>¿De qué país son tus padres?</em> Which is the real compliment.</p>

<p>But the more common question is <em>¿Cómo aprendiste el español?</em> and I find that question itself telling. In the US, while we all take language classes in school, virtually no one ends up even passably proficient…so much so that there’s not even an expectation. The richest country in the world, and we seem to have made our peace with monolingualism, conveniently blaming geography and the global dominance of English.</p>

<p>My path was accidental, and it started with my one-of-a-kind seventh-grade Spanish teacher, Sr. David Donch.</p>

<h2 id="el-señor-donch">El Señor Donch</h2>

<p>David Donch is a New Jersey native who joined the Peace Corps in his youth, ended up in Venezuela, and didn’t come back until he brought a beautiful Venezolana home with him. He was unconventional in the best sense: he threw out the textbook—which I’m sure cost him countless hours of curriculum development—and replaced it with vocab bingo cards and audio cassettes. (To this day I associate <em>la sal</em> and <em>el azúcar</em> together because they shared a bingo square.)</p>

<p>When I moved to a different school the following year, my new Spanish teacher was a <em>gringa</em> with a flat accent and a standard-issue textbook (“turn to page 78 for today’s lesson”). So Sr. Donch graciously agreed to tutor me, and he’d make the trek across St. Paul to our house. Then one day he mentioned he needed to repair the roof of his casita in the Venezuelan Andes, and suggested I (and a couple other students) come along to really learn the language. And do some fly fishing.</p>

<p>I was fourteen. My parents (amazingly) said yes. And it changed everything.</p>

<h2 id="my-month-in-venezuela-at-age-14">My Month in Venezuela at Age 14</h2>

<p>We landed in Maracaibo with duffel bags, my very first passport, and an English-Spanish dictionary. The first night we stayed with friends of Sr. Donch’s, and I sat there absorbing the language—or trying my best to—while missing the vast majority of it. Total sensory overload. Would I like something to drink? <em>¿Coca?</em> (that is, <em>Cocaine?</em>)—instead of <em>una Coca-Cola</em>. The place erupted. The heat rose in my cheeks as I laughed at myself…embarrassment is an extraordinarily effective teacher.</p>

<p>But no one tells you that you have to be willing to look like an idiot to learn a language. That there’s really no other path forward. Actually, you can extend that well beyond langauge to nearly anything. Shane Parrish puts it well: “we’re often unwilling to look foolish in the short term to succeed in the long term.” And that trade-off isn’t optional: you either make the mistakes or you don’t learn; full stop.</p>

<p>The other aspect of this was the fullness of the immersion. We spent the majority of the trip in the beautiful mountainous state of Trujillo, where very few people spoke English—and Mr. Donch was pretty good about not bailing me out. It was a full commit, which was hard at first. But I wasn’t placed with a host family where English crept back in at the dinner table, nor was I surrounded by fellow English speakers the way so many study abroad programs inadvertently arrange things…where your native tongue becomes a constant refuge and the whole point is quietly defeated.</p>

<h2 id="the-mechanics">The Mechanics</h2>

<p>Looking back, a few things stand out that I think generalize beyond Spanish:</p>

<p>You have to let language wash over you rather than chase every word. If you try to translate everything in real time, you’ll fall behind and miss what comes next. But here’s the thing: we naturally do this in our native language without realizing it. Have you ever been half-listening to someone and suddenly gotten caught off guard by an unexpected turn of phrase (because you’d already mentally finished their sentence for them)? That’s <strong>collocation</strong>: the phenomenon where certain words reliably travel together, and a fluent brain learns to anticipate the pairing. Salt pulls pepper; trial pulls error. In corpus linguistics it’s defined as words that co-occur more often than chance would predict, but experientially it’s just what normal fluency feels like. When you’re learning a new language, and you don’t have those grooves yet, every phrase is a surprise, which is why the immersion strategy works: you’re forcing those associations at speed. At some point you stop translating and just start anticipating, which is how and when things unlock.</p>

<p><strong>Accent matters</strong> more than you’d think, and for an unexpected reason. I ended up sounding reasonably native—partly, I think, because of an ear trained by music and years of mimicking sounds—while having vocabulary gaps that a six-year-old wouldn’t have. But the effect was that native speakers engaged with me <em>as if</em> I knew what I was doing. They didn’t switch to English out of pity but rather kept going. Compare this to others I know who have impeccable grammar (correct tenses and conjugation, etc.), but comically American accents: native speakers jump to bail them out, which is nice but of course hinders improvement. The friction I got from <em>sounding</em> like I belonged was itself a form of instruction.</p>

<p>Memory works through collision and surprise. <em>Sal</em> and <em>azúcar</em> are fused in my brain because they bumped into each other on that bingo card. The <em>cocaína</em> incident is seared in because it was a learning moment. As I understand it, these are what cognitive science researchers call <strong>desirable difficulties</strong>, the counterintuitive finding that harder, less comfortable learning conditions produce better long-term retention than easy, smooth ones. Fluency isn’t built through frictionless repetition; it’s built through the moments that make you catch yourself and recalibrate.</p>

<h2 id="the-ai-question">The AI Question</h2>

<p>Which brings me to the thing I keep thinking about.</p>

<p>AI is close to making real-time translation seamless. In the very near-term—I don’t want to be in the game of AI prediction—you’ll be able to speak to anyone in any language and be understood, without ever having learned a word. Which raises the obvious question: does learning a language even matter anymore?</p>

<p>But the better question is what AI does to the process of learning itself.”</p>

<p>Done right, an AI tutor could be extraordinary: infinitely patient, available at 01:00, able to accommodate your precise needs relative to where you are. Conversational AI built specifically to teach could replicate the immersive pressure I felt in Trujillo without requiring a plane ticket.</p>

<p>Some learners will use it this way, but the temptation runs the other direction: why struggle to produce a sentence when the AI will just produce it for you? Why tolerate the embarrassment of the wrong word when you can simply not speak and let the tool speak for you? The risk is that AI removes friction entirely for everyone, regardless of style, if we let it.</p>

<p>And here’s what I keep coming back to: even if tinkerers and systematizers learn differently, even if some people need structure and others need to poke at things until they yield, I suspect there’s a floor of friction below which nobody actually learns. The form of difficulty may vary. But difficulty itself doesn’t.</p>

<p>Sr. Donch intuitively understood this, which is why he deliberately didn’t make things easy. He made things interesting, and then he made things hard in the right ways: bingo cards as a mnemonic device, a total-immersion trip with no English escape hatch.</p>

<p>The question for anyone building AI tools is whether we’re designing for that same principle, or whether we’re quietly engineering away the very resistance that produces learning.</p>

<p>¿Entendiste, pues?</p>

<p>— ᴘ. ᴍ. ʙ.</p>]]></content><author><name>Paul Berens</name></author><category term="culture" /><category term="american identity" /><summary type="html"><![CDATA[Learning a language as a template for learning anything]]></summary></entry><entry><title type="html">Claude Code, Dark Mode</title><link href="https://berens.co/dark-mode.html" rel="alternate" type="text/html" title="Claude Code, Dark Mode" /><published>2026-01-23T00:00:00+00:00</published><updated>2026-01-23T00:00:00+00:00</updated><id>https://berens.co/dark-mode</id><content type="html" xml:base="https://berens.co/dark-mode.html"><![CDATA[<p>Ladies and Gentlemen, at long last…by popular demand…I give you…</p>

<p><strong><em>…dark mode on berens.co</em></strong><sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> [Cue rampageous applause.]</p>

<p><img src="/assets/og/post_dark_mode.png" alt="Introducing Dark Mode on berens.co" />
<span class="muted small">Dark Mode insisted on a lifestyle photoshoot before going live.</span></p>

<h2 id="clarification">Clarification</h2>

<p>Hold up. <em>(Screeching brakes.)</em></p>

<p>This post isn’t so much about the wonders of dark mode on my website as about <em>how it was achieved</em>.</p>

<h2 id="background">Background</h2>

<p>Last October I chronicled my experience <a href="/vibe-coding.html">“vibe coding”</a>—building things through AI-assisted trial and error without formal programming knowledge—and then again in November on how I used an LLM to spin up <a href="/song-bot.html">my first bot</a>. That workflow looked like this: describe what I want → Claude generates code snippets → I copy the code → I paste it into the right file → I save the file → I commit to git → I push to GitHub → the site rebuilds → I test it → if it fails, I report the error and repeat.</p>

<p>It worked, but it was pretty manual and the onus was on me to move code around and ensure everything ends up in the right place.</p>

<p>Then I discovered <strong>Claude Code</strong> and old-school vibe coding instantly became dial-up internet.</p>

<p>For those unfamiliar, Claude Code is a command-line tool that connects to your GitHub repository and can read, write, debug, and test code directly in your codebase—all through natural language commands. Basically your own AI coding assistant or “pair programmer”.</p>

<h2 id="the-dark-mode-case-study">The Dark Mode Case Study</h2>

<p>I needed a project to test drive it: how about building dark mode, everyone’s favorite UI enhancement. I pointed it at berens.co, authenticated, and it was ready to work directly in my codebase.</p>

<p>In the old vibe coding workflow, this would have meant dozens of copy-paste cycles across multiple files—CSS variables, media queries, template updates, testing each piece. Instead, I opened Claude Code and typed: “what’s the simplest way to implement a ‘dark mode’ on my current setup; one that inherits the ‘system preference’ of the browser?”</p>

<p>Claude Code didn’t just spit out some generic code. It read my entire site structure to understand the setup, analyzed my current CSS file, then converted all hardcoded colors to CSS custom properties. It created a complete <code class="language-plaintext highlighter-rouge">@media (prefers-color-scheme: dark)</code> section with a carefully chosen dark color palette, added the proper meta tag to my HTML header, tested the implementation, and committed everything to a new git branch.</p>

<p><strong>My role?</strong> Overbearing supervisor and critic. I looked at the preview and said “here’s a better color palette” (showing a screenshot). Claude Code adjusted. I mentioned “the table headers need work”—it read <code class="language-plaintext highlighter-rouge">pages/today.md</code>, identified the issue, and fixed it. Back and forth we went, refining details:</p>

<ul>
  <li>“The input boxes should be darker”</li>
  <li>“The highlighting is too faint”</li>
  <li>“Kill those right borders”</li>
  <li>“Make the left border invisible unless it’s highlighting”</li>
  <li>“Do me a favor and lose five pounds immediately or get out of my building like now!”</li>
</ul>

<p>Each time, Claude Code read the relevant files, understood the context, made the changes, tested them, and committed them. I never opened my code editor nor touched git. I just hollered out what I wanted.</p>

<p><img src="/assets/og/post_claude_code.png" alt="Claude Code doing its thing" />
<span class="muted small">Claude Code taking the wheel.</span></p>

<h2 id="this-is-agentic-ai">This Is Agentic AI</h2>

<p>This was my first real experience with an <strong>agentic AI</strong>—an AI that doesn’t just generate outputs for you to handle, but actually takes actions in your environment.</p>

<p>The difference is astounding. With my original vibe coding, “Advisory Claude” generates the code; whereas here Claude Code actually builds the feature itself. Advisory Claude gives me the recipe; Claude Code cooks dinner. Advisory Claude gives me directions; Claude Code is the autonomous vehicle that drives us there.</p>

<p>It’s not that one is smarter than the other—they’re using the same underlying model—it’s that Claude Code has <em>agency</em> in that it can read files, edit them, run tests, commit changes. It operates in my development environment like a junior developer who’s skilled at interpreting my terrible, inexact prompts.</p>

<h3 id="near-zero-learning-curve">Near-Zero Learning Curve</h3>

<p>Because I was already fluent in traditional vibe coding—hey, I should add that to my résumé—there’s really no ramp to Claude Code. It’s essentially the same process:</p>
<ul>
  <li>Describe desired outcomes clearly</li>
  <li>Provide visual feedback (screenshots)</li>
  <li>Iterate on details</li>
  <li>Recognize when something isn’t quite right</li>
</ul>

<p>So it’s the same process as with Advisory Claude; the only difference was that now I didn’t have to be the one moving the pieces around.</p>

<h2 id="what-this-means">What This Means</h2>

<p>The barrier to building things is shifting from “can I figure out how to code this?” to “can I convey what I want?” If you’ve been vibe coding you’re already positioned for this shift.</p>

<p>For most, the future isn’t about becoming a traditional developer. It’s about being able to articulate what you want to build, recognize when it’s right, and iterate until it works.</p>

<p>Feels about right to me: the computer handles syntax, file structure, and other minutiae; the humans worry about design, taste, and imagination.</p>

<p>But I, for one, welcome our agentic overlords.</p>

<p>— ᴘ. ᴍ. ʙ.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Still seeing light mode? That’s because your system or browser is set that way—the <a href="/colophon/">colophon</a> shows what we detected. Flip the preference in your OS or browser and the page will update right away. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Paul Berens</name></author><category term="tech" /><category term="product" /><summary type="html"><![CDATA[Hey, Claude Code, make me a sandwich!]]></summary></entry><entry><title type="html">The Donor-Advised Fund</title><link href="https://berens.co/daf.html" rel="alternate" type="text/html" title="The Donor-Advised Fund" /><published>2025-12-26T00:00:00+00:00</published><updated>2025-12-26T00:00:00+00:00</updated><id>https://berens.co/daf</id><content type="html" xml:base="https://berens.co/daf.html"><![CDATA[<p>This was us every year up ‘til now (tell me if this is familiar): the end of the year rolls around, and amidst all the Christmas hustle and bustle, we suddenly realize we need to make our charitable giving decisions and contributions before 31 December. And so we find ourselves hastily “peanut buttering” donations across various organizations—a little here, a little there—just to add up to a certain target dollar amount and in time to get processed before the new year.</p>

<p>More financial triage than intentional charitable giving.</p>

<h2 id="enter-donor-advised-fund-daf">Enter donor-advised fund (DAF)</h2>

<p>A DAF changes this dynamic: you contribute money (or stock) to the fund and receive an immediate tax deduction. The funds are invested and grow tax-free. Then you distribute “grants” to charities on your own timeline, which could be next month but it could also be a decade from now.</p>

<p>You’ve effectively separated the tax break from the actual giving.</p>

<h2 id="benefits">Benefits</h2>

<p><img src="/assets/og/post_daf.jpg" alt="Sell me this DAF" /></p>

<ol>
  <li><strong>Tax efficiency</strong>: Take the deduction when it makes sense for your tax situation; not necessarily when you’re making a charitable contribution.</li>
  <li><strong>Administrative simplicity</strong>: Make one contribution to your DAF and get one tax receipt, then distribute to multiple charities over time without additional tax paperwork.</li>
  <li><strong>Thoughtful giving</strong>: You can research organizations, respond to real needs as they arise (or pause as you anticipate some greater future need), and give with a bit more intentionality now that you’ve removed the time pressure. (More on intentional giving in <a href="/philanthropy.html">this post</a>.)</li>
  <li><strong>Portfolio optimization</strong>: DAFs are ideal for donating appreciated securities, turning portfolio cleanup into charitable impact while maximizing tax benefits.
    <ul>
      <li><em>Practical example:</em> We recently used our DAF to donate a good amount of highly appreciated individual stocks (some with 400%+ gains), which killed three birds with one stone: eliminated a tangled mess of 22 tax lots we’d been wanting to consolidate, avoided a boatload of embedded capital gains tax, and generated a separate boatload in total tax savings whilst pre-funding a healthy runway of charitable giving.</li>
    </ul>
  </li>
  <li><strong>Growth potential</strong>: Charitable dollars grow tax-free before you distribute them, potentially (hopefully) increasing your total charitable impact.</li>
  <li><strong>Anonymous giving</strong>: Most DAF providers allow you to give anonymously—the charity sees the payment from the sponsor (e.g., “Vanguard Charitable”) without your identifying information. While public giving has its place, anonymous giving offers benefits around humility, self-effacement, privacy, and avoiding inequality dynamics.</li>
</ol>

<h2 id="arent-dafs-for-the-ultra-wealthy">Aren’t DAFs for the ultra-wealthy?</h2>

<p>Well that there’s a big misconception, my friend. They’re more accessible than you’d think with many providers<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> setting initial contributions at or below what many families already give to charity annually, and even others offering accounts with zero minimum. Basically, you might already be giving enough to make a DAF worthwhile—or could be, Mr. and Mrs. Scroogie McScroogeface.</p>

<p>Think of a DAF as sitting alongside your other tax-advantaged accounts:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Purpose</th>
      <th style="text-align: left">Tool</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left">Retirement</td>
      <td style="text-align: left">401(k), IRAs, etc.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></td>
    </tr>
    <tr>
      <td style="text-align: left">Education</td>
      <td style="text-align: left">529</td>
    </tr>
    <tr>
      <td style="text-align: left">Healthcare</td>
      <td style="text-align: left">HSA</td>
    </tr>
    <tr>
      <td style="text-align: left">Emergency fund</td>
      <td style="text-align: left">HYSA</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>Philanthropy</em></td>
      <td style="text-align: left"><em>Donor-advised fund</em></td>
    </tr>
  </tbody>
</table>

<p>If you’ve ever felt the aforementioned year-end crunch, and if you’d like to be more purposeful with your philanthropy, a donor-advised fund might be just the thing that’s missing from your financial quiver<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup>.</p>

<p>And Happy Boxing Day—how <em>apropos</em>,</p>

<p>— ᴘ. ᴍ. ʙ.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>We went with <a href="https://www.vanguardcharitable.org/">Vanguard Charitable</a>, which is sort of a no-brainer if you’re using Vanguard for your regular portfolio. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>I’ll uncover the wonders of the (surprisingly legal) Backdoor Roth Conversion in a sleep-inducing future post. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Be sure to mention code “Berens” when you sign up—<em>CALL NOW!</em> <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Paul Berens</name></author><category term="personal finance" /><summary type="html"><![CDATA[The financial tool you're overlooking]]></summary></entry><entry><title type="html">Song Bot</title><link href="https://berens.co/song-bot.html" rel="alternate" type="text/html" title="Song Bot" /><published>2025-11-21T00:00:00+00:00</published><updated>2025-11-21T00:00:00+00:00</updated><id>https://berens.co/song-bot</id><content type="html" xml:base="https://berens.co/song-bot.html"><![CDATA[<p>I continue my <a href="/vibe-coding">vibe coding</a> escapade with my first bot: <a href="https://t.me/pb_song_bot" target="_blank">a song-of-the-day Telegram bot</a> that automatically sends a tasty track to subscribers every morning to enjoy with coffee.</p>

<h2 id="first-the-music">First the Music</h2>
<p>Before any bot building, I curated a set of my favorite songs of all time—a revelatory exercise that clarified my tastes: lots of classic rock and folk-rock from the ’60s-‘80s golden era, plus generous helpings of singer-songwriters, soul/R&amp;B, and live tracks. Christmas music (both sacred and secular) bookends the calendar from early December through early January, confirming what I <a href="/xmas-music">previously discussed</a>: I do love the season. I aimed for artist diversity (no more than six tracks each) and gravitate toward deep cuts—so if you recognize a hit here, it’s because it’s genuinely great. But as Grandpa Brennan was wont to say, <em>de gustibus non est disputandum.</em></p>

<h2 id="bot-building">Bot Building</h2>
<p>This was a product of Claude (Sonnet 4.5). Admittedly, it didn’t get everything perfect on the first pass, but it sure took my abrasive feedback in stride. The process wasn’t totally linear, but it went something like this:</p>
<ol>
  <li>Learn about Telegram bots</li>
  <li>Set up and configure the bot</li>
  <li>Create the initial daily song workflow</li>
  <li>Debug some “ES module” issues<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">1</a></sup></li>
  <li>Add self-service subscriptions</li>
  <li>Test and fix</li>
  <li>Refine (message formatting, etc.)</li>
</ol>

<p><img src="/assets/og/post_telegram-workflow.png" alt="Failing Telegram workflows" style="width: 70%;" /><span class="muted small">Fail, fail, fail, success, fail, fail...</span></p>

<h2 id="the-setup">The Setup</h2>
<p>Here’s what I ended up with:</p>
<ol>
  <li><strong>Telegram Bot</strong> – Created via <a href="https://t.me/BotFather@BotFather" target="_blank">@BotFather</a> w/ token stored as GitHub secret. Users subscribe themselves.</li>
  <li><strong>Data Source</strong> (<code class="language-plaintext highlighter-rouge">_data/daily_song.yml</code>) – My impeccably-curated list of 366 songs<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">2</a></sup> with date, track title, artist, and YouTube Music song ID.
    <pre><code class="language-YAML">  - date: "12-09"
    track: "Christmas Is Coming"
    artist: "Vince Guaraldi Trio"
    songId: "2--a88MKHZc"
</code></pre>
  </li>
  <li><strong>GitHub Actions Workflows</strong>
    <ul>
      <li><strong>Workflow #1: Subscription Manager</strong> (<code class="language-plaintext highlighter-rouge">telegram-subscriptions.yml</code>) – Runs daily at 07:00 Pacific, and checks for <code class="language-plaintext highlighter-rouge">/subscribe</code> and <code class="language-plaintext highlighter-rouge">/unsubscribe</code> messages, adding/removing users to/from <code class="language-plaintext highlighter-rouge">_data/telegram_subscribers.json</code>, kicks out confirmation messages.</li>
      <li><strong>Workflow #2: Daily Song Sender</strong> (<code class="language-plaintext highlighter-rouge">telegram-daily-song.yml</code>) – Runs a half hour later (~07:45), reading today’s song from YAML, sending the selection with clickable link to the track on YouTube Music to all subscribers in the JSON file:</li>
    </ul>
  </li>
  <li><strong>Rinse and repeat</strong> – Repeats daily, fully automated via GitHub Action with no servers or hosting costs.</li>
</ol>

<p><img src="/assets/og/post_song.bot.343.png" alt="bot notification" /></p>

<h2 id="youre-lookin-at-a-few-options-here">You’re lookin’ at a few options here</h2>
<ol>
  <li><a href="https://t.me/pb_song_bot" target="_blank">Subscribe</a> so that we can know the joy of experiencing the same songs together on the very same days. (Then just sneak out with an <code class="language-plaintext highlighter-rouge">/unsubscribe</code> if you’re not feelin’ my jams.)</li>
  <li>Get the same song of the day via the <a href="/today/">today</a> page if you’re more of <em>pull</em> person than a <em>push</em> person.</li>
  <li>Make your own SOTD bot by cloning these workflows and <code class="language-plaintext highlighter-rouge">.yml</code> files from <a href="https://github.com/berensp/berensp.github.io/">my GitHub repo</a>. I’ll subscribe.</li>
</ol>

<h2 id="bottom-line">Bottom line</h2>
<p>It’s astonishing that a non-coder like moi can go from idea to fully functional Telegram bot with auto-subscriptions in one sub-100-message chat session—that there’s some right-fine vibe codin’…at least for the standards of late 2025 (I’m sure it’ll seem quaint in a year or two).</p>

<h2 id="update-may-2026">Update (May 2026)</h2>
<p>Six months in, two problems surfaced: the song was arriving noticeably late and at inconsistent times. Turned out there were two culprits conspiring together: 1) GitHub’s automation scheduler having no awareness of local time or seasonal clock changes, and 2) GitHub’s scheduler not being very punctual, its automations more like suggestions than alarms (ergo day-to-day randomness). So I swapped GitHub’s internal scheduler for <a href="https://cron-job.org" target="_blank">cron-job.org</a>, a dedicated (and free) scheduling service that pings GitHub at exactly the right local time each day (even accounting for DST) and says <em>alright stop whatcha doin’</em> and makes it run the song workflow now. Delivery is now consistent to within a minute. The whole diagnosis-and-fix took ~20 minutes with Claude (Sonnet 4.6).</p>

<p>While at it, added an X companion account—<a href="https://x.com/pb_song_bot" target="_blank">@pb_song_bot</a>—so the daily song now posts there, too. Getting the X API to cooperate required a small credits deposit (the “free” tier is free like a bookie extending credit: new guys post cash first), but once unlocked, the same cron-job.org trigger fires both automations in perfect synchrony.</p>

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="en" dir="ltr">#128: &quot;I Just Don&#39;t Think I&#39;ll Ever Get Over You&quot; by Colin Hay<a href="https://t.co/ZW3scbQWoN">https://t.co/ZW3scbQWoN</a></p>&mdash; Paul&#39;s Song of the Day (@pb_song_bot) <a href="https://twitter.com/pb_song_bot/status/2052757994132439185?ref_src=twsrc%5Etfw">May 8, 2026</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>— ᴘ. ᴍ. ʙ.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:2" role="doc-endnote">
      <p>This is the type of arcana that’s over my head and so I’m totally reliant on the LLM to diagnose and fix: Node.js was trying to run our script as an ES Module (basically new JavaScript) (which doesn’t allow <code class="language-plaintext highlighter-rouge">require()</code>), but the thing was written in old Javascript (i.e., CommonJS style), so got this error about “require is not defined in ES module scope.” So the fix—after a number of back-and-forths—was renaming the file to <code class="language-plaintext highlighter-rouge">.cjs</code> (CommonJS file extension) and wrapped the <code class="language-plaintext highlighter-rouge">await</code> in an async function, which told Node: “Hey, this is old-style CommonJS, not modern ES Modules.” 🤓 <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Yes, leap year support built in. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Paul Berens</name></author><category term="tech" /><category term="music" /><category term="product" /><summary type="html"><![CDATA[🤖]]></summary></entry></feed>