<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://www.kevfoo.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.kevfoo.com/" rel="alternate" type="text/html" /><updated>2026-03-15T19:38:09-05:00</updated><id>https://www.kevfoo.com/feed.xml</id><title type="html">Kevin McMahon</title><subtitle>Chicago-based software engineer writing about cloud, AI, mobile development, and open source.</subtitle><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><entry><title type="html">The Era of Personal Code: Moving 18 Years of Recipes in a Weekend with LLMs</title><link href="https://www.kevfoo.com/2026/03/the-era-of-personal-code/" rel="alternate" type="text/html" title="The Era of Personal Code: Moving 18 Years of Recipes in a Weekend with LLMs" /><published>2026-03-15T00:00:00-05:00</published><updated>2026-03-15T00:00:00-05:00</updated><id>https://www.kevfoo.com/2026/03/the-era-of-personal-code</id><content type="html" xml:base="https://www.kevfoo.com/2026/03/the-era-of-personal-code/"><![CDATA[<p>Most people’s recipe collections are a mess. Magazine clippings, website printouts, and handwritten index cards all crammed into a kitchen drawer or stuffed between the pages of a cookbook. A few months ago, my digital version wasn’t any better.</p>

<p>Over 18 years, my recipes ended up in almost every format. They started as text files and PDFs in a local folder, moved to Evernote with its own formatting, and later became a pile of Markdown files in Bear.</p>

<p>It was messy, but it worked. Still, I wanted something that was well formatted but wasn’t locked into a particular tool. My goal was to extract, clean, and format every recipe as JSON-LD using the <a href="http://schema.org/">Schema.org</a> Recipe schema. With structured JSON-LD, I could use the recipes in a custom app, a static site, or whatever I build next.</p>

<p>For years, I didn’t touch it. Writing custom regex and parsing code to clean up 18 years of messy formats, strange line breaks, and platform quirks sounded like a nightmare. Spending hours on a complicated migration for a hobby just didn’t seem worth it.</p>

<p>But now, with LLMs, things have changed. When you can turn an idea into working code in an afternoon, it becomes worth writing personal code that only needs to run once. I didn’t need to build a SaaS product to parse recipes. I just needed a Python script I could run over the weekend.</p>

<h2 id="planning-and-piping-the-technical-workflow">Planning and Piping: The Technical Workflow</h2>

<p>I started by having a conversation, not by writing code.</p>

<p>I opened ChatGPT and Claude Desktop and started giving them samples of my Bear Markdown files, Evernote exports, and PDFs. Using <a href="https://harper.blog/2025/02/16/my-llm-codegen-workflow-atm/">a spec-driven workflow I found last year</a>, I worked on a spec that defined my goal (strict JSON-LD of all my recipes) and the pipeline to get there.</p>

<p>I planned the structure and results, and Claude Code handled the coding. The logic was simple:</p>

<ol>
  <li>Iterate through the target directory.</li>
  <li>Read the file contents (extracting text from PDFs or reading Markdown).</li>
  <li>Send the raw text to the LLM API with a strict system prompt that instructs it to return only valid JSON-LD conforming to the Recipe schema.</li>
  <li>Save the output.</li>
</ol>

<p>In the past, step 3 would have needed a lot of complicated string-manipulation code. With an LLM, it only took one API call.</p>

<h2 id="the-architecture-filtering-and-the-quarantine-queue">The Architecture: Filtering and the “Quarantine” Queue</h2>

<p>When you work with 18 years of personal data, you have to accept that it won’t be clean.</p>

<p>If you try to write a script that covers every edge case, you’ll never finish. So I made the pipeline fault-tolerant and included myself in the process. The script didn’t have to be perfect. It just needed to know when it got stuck.</p>

<p>I solved this in two steps:</p>

<p><strong>Step 1: The Filtering Pass</strong>
Not everything in my recipe folder was actually a recipe. Over the years, I saved random food notes, restaurant tips, and cooking ideas. Before running the main conversion, I had the LLM quickly sort the files: <em>Is this a recipe or just a note?</em> If it was a note, it got tagged and moved to a separate folder, so the main process stayed clean.</p>

<p><strong>Step 2: The Quarantine Directory</strong>
During the main JSON-LD extraction, if a file couldn’t be parsed or the LLM wasn’t sure about the ingredients and instructions, the script didn’t crash. It caught the error, skipped the file, and put it in a “Quarantine” folder for me to check later.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span><span class="p">:</span>
    <span class="n">recipe_json</span> <span class="o">=</span> <span class="nf">extract_recipe_data_via_llm</span><span class="p">(</span><span class="n">file_content</span><span class="p">)</span>
    <span class="nf">validate_json_ld</span><span class="p">(</span><span class="n">recipe_json</span><span class="p">)</span>
    <span class="nf">save_to_output</span><span class="p">(</span><span class="n">recipe_json</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
<span class="k">except</span> <span class="n">ParsingError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Failed parsing </span><span class="si">{</span><span class="n">filename</span><span class="si">}</span><span class="s">. Moving to Quarantine.</span><span class="sh">"</span><span class="p">)</span>
    <span class="nf">move_to_quarantine</span><span class="p">(</span><span class="n">filepath</span><span class="p">,</span> <span class="n">reason</span><span class="o">=</span><span class="nf">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
</code></pre></div></div>

<p>That’s the nice thing about personal code. I didn’t write a script to fix the quarantined files. The computer did 95% of the work, and I spent about an hour on Sunday morning making a few fixes or editing the last ones by hand.</p>

<p>Most of the quarantined files were easy to sort out, but a handful of them surprised me.</p>

<h2 id="the-heart-of-the-data-grandmas-shorthand">The Heart of the Data: Grandma’s Shorthand</h2>

<p>Before my Grandma passed away, my sister helped her collect all the recipes she had made for our family. Each grandchild got a binder with the dishes, sides, casseroles, and desserts we grew up loving, along with a handwritten note from Grandma. It’s one of my most treasured things.</p>

<figure class="narrow">
<picture><source type="image/webp" srcset="https://cache.kevfoo.com/2026/03/gram-note.webp" /><source type="image/png" srcset="https://cache.kevfoo.com/2026/03/gram-note.png" /><img src="https://cache.kevfoo.com/2026/03/gram-note.png" alt="Handwritten note from Grandma included in the recipe binder" /></picture>
<figcaption>A handwritten note from Grandma, tucked into the front of the recipe binder.</figcaption>
</figure>

<p>The binder also included recipes from my great-grandmother. Hers were written out the way you’d expect, with measurements, steps, and enough detail that anyone could follow along.</p>

<figure class="narrow">
<picture><source type="image/webp" srcset="https://cache.kevfoo.com/2026/03/gram-pound-cake.webp" /><source type="image/png" srcset="https://cache.kevfoo.com/2026/03/gram-pound-cake.png" /><img src="https://cache.kevfoo.com/2026/03/gram-pound-cake.png" alt="Great-grandmother’s handwritten pound cake recipe with full ingredients and instructions" /></picture>
<figcaption>My great-grandmother’s pound cake recipe. Measurements, steps, everything you need.</figcaption>
</figure>

<p>But Grandma’s recipes were nothing like what you’d find in a published cookbook. They read the same way she talked: no fuss, no measurements, just enough to jog your memory if you’d been in the kitchen with her.</p>

<figure class="narrow">
<picture><source type="image/webp" srcset="https://cache.kevfoo.com/2026/03/gram-recipe.webp" /><source type="image/png" srcset="https://cache.kevfoo.com/2026/03/gram-recipe.png" /><img src="https://cache.kevfoo.com/2026/03/gram-recipe.png" alt="One of Grandma’s recipes with sparse ingredients and directions" /></picture>
<figcaption>One of Grandma’s recipes. If you grew up watching her cook, this was all you needed.</figcaption>
</figure>

<p>When the Python script reached Grandma’s recipes, almost all of them landed in the Quarantine folder. The LLM marked them as “non-recipes” because the ingredients and directions were so brief. Those of us who grew up eating those meals knew exactly what she meant. We’d watched her cook hundreds of times. We knew how big to dice the vegetables for the chicken soup and how many fried onions to add to the hamburger casserole.</p>

<p>A fully automated, strict system would have lost this data. But because I built this for myself, the quarantine folder let me catch these recipes. I could step in and keep Grandma’s original style, wrapping her shorthand into the modern JSON-LD format. That was the whole point. The script handled the bulk of the work, and I could focus my attention on the places where it actually mattered.</p>

<p>By Sunday night, the migration was finished. Eighteen years of text files, PDFs, Evernote notes, and Bear markdown files were neatly organized into JSON-LD.</p>

<p>And the Python code? I deleted most of it. It had done its job.</p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="ai" /><category term="llm" /><category term="python" /><category term="personal-software" /><summary type="html"><![CDATA[I used LLMs to migrate 18 years of recipes, including my Grandma's handwritten ones, into structured JSON-LD over a single weekend.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2026/the-era-of-personal-code.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2026/the-era-of-personal-code.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">My Spin on Claude Code On-the-Go: Oracle Cloud Always Free + Ntfy Edition</title><link href="https://www.kevfoo.com/2026/02/my-spin-on-claude-code-on-the-go/" rel="alternate" type="text/html" title="My Spin on Claude Code On-the-Go: Oracle Cloud Always Free + Ntfy Edition" /><published>2026-02-22T00:00:00-06:00</published><updated>2026-02-22T00:00:00-06:00</updated><id>https://www.kevfoo.com/2026/02/my-spin-on-claude-code-on-the-go</id><content type="html" xml:base="https://www.kevfoo.com/2026/02/my-spin-on-claude-code-on-the-go/"><![CDATA[<p>I saw this <a href="https://granda.org/en/2026/01/02/claude-code-on-the-go/">post</a> about running Claude Code from a phone and immediately wanted the same thing. There were, however, two areas I thought we could improve upon: Vultr costs real money ($7/day when running), and Poke, a notification service, that is gated behind a truly ridiculous signup process.</p>

<p>So this is my spin on the Claude Code On-the-Go approach. Same idea, zero monthly cost, and notifications that just work.</p>

<figure>
  <img src="/images/claude-code-on-the-go.png" alt="Architecture diagram showing Termius connecting via mosh over Tailscale to Claude Code running in tmux on an Oracle Cloud VM, with ntfy.sh push notifications flowing back to the phone." />
  <figcaption>My spin on the mobile Claude Code stack.</figcaption>
</figure>

<h2 id="why-not-just-pay-for-a-vps">Why Not Just Pay for a VPS?</h2>

<p>You could. Vultr, Hostinger, AWS EC2, and countless other VPS providers work fine but come with costs and tradeoffs. You’re paying by the hour, so now you need lifecycle management. The setup outlined in the post includes <code class="language-plaintext highlighter-rouge">vm-start</code> and <code class="language-plaintext highlighter-rouge">vm-stop</code> scripts to spin the instance up and down. Forget to stop it, and you’re burning $7 a day. That mental overhead of remembering “Is my VM running? Did I shut it down?” defeats the purpose of a frictionless mobile workflow.</p>

<p>Oracle Cloud’s Always Free tier eliminates this entirely. You get Ampere A1 ARM instances with up to 4 OCPUs,  24 GB of RAM, and 200GB of storage for free. No trial period, no expiry. Leave it running 24/7, never think about it, never get a bill. That’s more horsepower than most paid VPS plans, and it costs nothing.</p>

<p>The catch: Oracle’s free tier capacity is notoriously hard to get. ARM instances on a plain free-tier account are almost always “out of capacity.” The fix is to upgrade to a Pay-as-you-Go account. You do have to add a credit card, but as long as you stay within the Always Free limits, the charge is $0. PAYG accounts get priority access to the same free resources. I set a budget alert at $0.01 actual spend, so I’ll know immediately if anything crosses the free line.</p>

<p>I also put the whole thing in <a href="https://github.com/kevinmcmahon/oci-alwaysfree-tf-stack">Terraform</a> so I can tear it down and rebuild it without clicking through Oracle’s console. Two variables (compartment ID and region), <code class="language-plaintext highlighter-rouge">terraform apply</code>, done.</p>

<h2 id="why-ntfy-over-poke">Why Ntfy Over Poke?</h2>

<p>Poke is invitation-gated, and the onboarding is painful. <a href="https://ntfy.sh">Ntfy</a> is the opposite. It’s a dead-simple pub/sub notification service, open source, free to use, and you can start sending push notifications in about 30 seconds:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-d</span> <span class="s2">"Hello from your VM"</span> ntfy.sh/your-private-topic
</code></pre></div></div>

<p>Install the ntfy app on your phone, subscribe to your topic, and you’re done. No accounts, no API keys, no waiting for access. If you want more control later, you can self-host the server.</p>

<h2 id="the-layers">The Layers</h2>

<p>Each layer solves one specific problem, and none differ from the original approach:</p>

<h3 id="tailscale">Tailscale</h3>

<p>The VM has no public SSH. Tailscale puts it on a private WireGuard mesh network. Install it on the VM and your phone, and they can talk to each other directly. No port forwarding, no security groups to misconfigure, no exposure.</p>

<h3 id="mosh">Mosh</h3>

<p>SSH over cellular is miserable. Switching between Wi-Fi and LTE is flaky. Get interrupted by a dead zone, and your connection is gone. Mosh uses UDP, handles roaming natively, and reconnects automatically when your network comes back. It also does local echo prediction, so typing feels instant even on high-latency connections.</p>

<h3 id="tmux">Tmux</h3>

<p>Session persistence. If mosh reconnects (or you connect from a different device), tmux keeps your Claude Code session exactly where you left it. I have it set up to auto-attach on login, so connecting drops me straight into my session:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># in .bashrc, auto-attach to tmux on SSH/mosh login</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$TMUX</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="o">[[</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$SSH_CONNECTION</span><span class="s2">"</span> <span class="o">||</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$MOSH</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
    </span>tmux attach <span class="nt">-t</span> main 2&gt;/dev/null <span class="o">||</span> tmux new <span class="nt">-s</span> main
<span class="k">fi</span>
</code></pre></div></div>

<h3 id="ntfy">Ntfy</h3>

<p>The novel idea in this stack is marrying Claude Code’s hooks with a notification layer. Together, this makes the whole thing actually useful on mobile. Without notifications, you’d be constantly switching to your terminal to check if Claude is waiting for you. With ntfy, you get a push notification the moment Claude asks a question or finishes a task.</p>

<h2 id="the-notification-hook">The Notification Hook</h2>

<p>Claude Code has a <a href="https://docs.anthropic.com/en/docs/claude-code/hooks">hooks system</a> that lets you run scripts in response to events. I use two hooks:</p>

<ol>
  <li><strong>PreToolUse</strong> fires when Claude asks a question via <code class="language-plaintext highlighter-rouge">AskUserQuestion</code>. The hook script extracts the question text and sends it as a notification.</li>
  <li><strong>Stop</strong> fires when Claude finishes a task. Sends a “task complete” notification so I know to check the results.</li>
</ol>

<p>The hook script is simple. It reads the event data from <code class="language-plaintext highlighter-rouge">$CLAUDE_HOOK_EVENT_DATA</code>, pulls out the relevant text, and curls ntfy:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Simplified version of the hook</span>
<span class="nv">TOPIC</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">NTFY_TOPIC</span><span class="k">}</span><span class="s2">"</span>
<span class="o">[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$TOPIC</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">exit </span>0  <span class="c"># no topic configured, skip silently</span>

<span class="nv">TOOL_NAME</span><span class="o">=</span><span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span>
<span class="k">case</span> <span class="s2">"</span><span class="nv">$TOOL_NAME</span><span class="s2">"</span> <span class="k">in
  </span>question<span class="p">)</span>
    <span class="nv">MESSAGE</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$CLAUDE_HOOK_EVENT_DATA</span><span class="s2">"</span> | jq <span class="nt">-r</span> <span class="s1">'.tool_input.question // empty'</span><span class="si">)</span>
    <span class="p">;;</span>
  <span class="k">*</span><span class="p">)</span>
    <span class="nb">exit </span>0
    <span class="p">;;</span>
<span class="k">esac</span>

curl <span class="nt">-sS</span> <span class="nt">-d</span> <span class="s2">"</span><span class="nv">$MESSAGE</span><span class="s2">"</span> <span class="s2">"https://ntfy.sh/</span><span class="k">${</span><span class="nv">TOPIC</span><span class="k">}</span><span class="s2">"</span> <span class="o">&gt;</span> /dev/null
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">NTFY_TOPIC</code> env var keeps the topic name out of dotfiles. On machines without ntfy configured, the script exits silently without errors or noise.</p>

<h2 id="the-daily-workflow">The Daily Workflow</h2>

<p>Here’s what it actually looks like:</p>

<ol>
  <li><strong>Open Tailscale</strong> on my phone (ensures the VPN is active)</li>
  <li><strong>Open Termius</strong> and tap my saved host. Mosh connects and I land in tmux.</li>
  <li><strong>Start Claude Code</strong> on a task (“add pagination to the API endpoint”), then pocket my phone.</li>
  <li><strong>Notification dings</strong>: “Should I use cursor-based or offset-based pagination?”</li>
  <li><strong>Open Termius</strong>, type “cursor-based”, pocket my phone again.</li>
  <li><strong>Another notification dings</strong>: “Task complete”</li>
</ol>

<p>The latency between Claude asking a question and the push notification arriving is under 2 seconds. The whole interaction of pulling out the phone, responding, and putting it back down takes maybe 15 seconds.</p>

<p>For parallel work, I use tmux windows (<code class="language-plaintext highlighter-rouge">Ctrl-a c</code> for a new window, <code class="language-plaintext highlighter-rouge">Ctrl-a n</code> to cycle) and git worktrees so each Claude agent works in its own checkout.</p>

<h2 id="cost">Cost</h2>

<table>
  <thead>
    <tr>
      <th>Component</th>
      <th>Cost</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Oracle Cloud ARM VM (4 OCPU, 24 GB)</td>
      <td>Always Free</td>
    </tr>
    <tr>
      <td>Tailscale</td>
      <td>Free for personal use</td>
    </tr>
    <tr>
      <td>Mosh</td>
      <td>Open source</td>
    </tr>
    <tr>
      <td>Tmux</td>
      <td>Open source</td>
    </tr>
    <tr>
      <td>Ntfy</td>
      <td>Free hosted tier</td>
    </tr>
    <tr>
      <td>Termius</td>
      <td>Free tier works, premium is nice</td>
    </tr>
  </tbody>
</table>

<p>Total: <strong>$0/month</strong>. The Vultr equivalent would run $7/day.</p>

<h2 id="tips">Tips</h2>

<ul>
  <li>Upgrade to Pay-as-you-Go for reliable ARM capacity, then set a $0.01 budget alert. You’ll get an email the instant any charge appears.</li>
  <li>Don’t click through the Oracle console more than once. My <a href="https://github.com/kevinmcmahon/oci-alwaysfree-tf-stack">Terraform stack</a> provisions the instance, VCN, subnet, and gateway with two variables.</li>
  <li>Even behind Tailscale, I run UFW (allow only the <code class="language-plaintext highlighter-rouge">tailscale0</code> interface) and fail2ban. Belt and suspenders.</li>
  <li>Allow UDP 60000-61000 on the Tailscale interface in UFW. Mosh needs these for its UDP connections.</li>
  <li>Mosh over Tailscale is easy on battery since it only sends data on changes.</li>
  <li>Termius has a configurable extra key row and handles SSH keys and identities well.</li>
</ul>

<h2 id="wrapping-up">Wrapping Up</h2>

<p>Running Claude Code from your phone is a genuine workflow improvement, not a gimmick. Development fits into the gaps of your day: waiting for coffee, riding the train, sitting in the school pickup line. There’s no reason to pay for it, and the notification layer should be something you can set up in 30 seconds, not something gated behind a waitlist.</p>

<p>Ready to try it out yourself? Just clone my <a href="https://github.com/kevinmcmahon/oci-alwaysfree-tf-stack">repo</a> and run terraform apply to set up your own always-free Claude Code environment. After that first commit gets pushed from your phone from some place far away from your keyboard, you’ll be hooked.</p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="ai" /><category term="cli" /><category term="cloud" /><category term="oracle" /><category term="oci" /><category term="mobile" /><category term="tools" /><summary type="html"><![CDATA[I saw this post about running Claude Code from a phone and immediately wanted the same thing. There were, however, two areas I thought we could improve upon: Vultr costs real money ($7/day when running), and Poke, a notification service, that is gated behind a truly ridiculous signup process.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2026/my-spin-on-claude-code-on-the-go.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2026/my-spin-on-claude-code-on-the-go.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Terraform for Your Always Free Claude Code VM</title><link href="https://www.kevfoo.com/2026/02/terraform-for-your-always-free-claude-code-vm/" rel="alternate" type="text/html" title="Terraform for Your Always Free Claude Code VM" /><published>2026-02-22T00:00:00-06:00</published><updated>2026-02-22T00:00:00-06:00</updated><id>https://www.kevfoo.com/2026/02/terraform-for-your-always-free-claude-code-vm</id><content type="html" xml:base="https://www.kevfoo.com/2026/02/terraform-for-your-always-free-claude-code-vm/"><![CDATA[<p>In my <a href="/2026/02/22/my-spin-on-claude-code-on-the-go/">previous post</a>, I walked through setting up a zero-cost mobile Claude Code environment on Oracle Cloud’s Always Free tier.  The VM, VCN, subnet, security list, and internet gateway take maybe 15 minutes to click through in the Oracle console, and you are up and running.</p>

<p>This is the type of thing that you might do once and never think about it again. Unless you blow it away. Or want a second one. Or want a friend to replicate your setup. Then you’re clicking through that console again, trying to remember which shape you picked and which security rules you set. Infrastructure-as-code exists precisely for this kind of thing.</p>

<p>For those cases, I put the whole stack in <a href="https://github.com/kevinmcmahon/oci-alwaysfree-tf-stack">Terraform</a>.</p>

<h2 id="what-it-provisions">What It Provisions</h2>

<p>The stack creates everything from Parts 2-3 of the setup guide:</p>

<ul>
  <li>VM.Standard.A1.Flex (ARM) compute instance, 4 OCPUs, 24 GB RAM, Ubuntu 24.04</li>
  <li>VCN with a public subnet</li>
  <li>Internet gateway and route table</li>
  <li>Security list allowing SSH ingress on port 22 (for initial setup, before Tailscale)</li>
</ul>

<p>After <code class="language-plaintext highlighter-rouge">terraform apply</code>, you SSH in, install Tailscale, lock down the security list, and continue with the rest of the guide. The Terraform part replaces the manual console work; the post-provisioning steps (Tailscale, mosh, tmux, Claude Code, ntfy) stay the same.</p>

<h2 id="two-variables-thats-it">Two Variables, That’s It</h2>

<p>The whole configuration boils down to two required variables:</p>

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>What it is</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">compartment_id</code></td>
      <td>Your OCI compartment OCID (usually your tenancy OCID)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">region</code></td>
      <td>OCI region, e.g. <code class="language-plaintext highlighter-rouge">us-chicago-1</code></td>
    </tr>
  </tbody>
</table>

<p>Everything else has sensible defaults. The availability domain and Ubuntu image are auto-discovered via OCI data sources, so you don’t need to hunt down region-specific OCIDs.</p>

<p>Before you start, make sure your OCI CLI is installed and your credentials are set up.<sup id="fnref:oci-keys"><a href="#fn:oci-keys" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>

<p>Run:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oci iam region-list
</code></pre></div></div>

<p>to verify your profile is active and authenticated. This helps avoid credential errors later.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/kevinmcmahon/oci-alwaysfree-tf-stack.git
<span class="nb">cd </span>oci-alwaysfree-tf-stack

<span class="nb">cp </span>terraform.tfvars.example terraform.tfvars
<span class="c"># edit terraform.tfvars: set compartment_id and region</span>

terraform init
terraform plan
terraform apply
</code></pre></div></div>

<p>Your VM is running. SSH in and pick up at Part 3 of the setup guide:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh <span class="nt">-i</span> ~/.ssh/your-key ubuntu@<span class="si">$(</span>terraform output <span class="nt">-raw</span> instance_public_ip<span class="si">)</span>
</code></pre></div></div>

<h2 id="staying-inside-the-free-limits">Staying Inside the Free Limits</h2>

<p>The defaults are tuned to use the full Always Free ARM allowance without exceeding it:</p>

<table>
  <thead>
    <tr>
      <th>Resource</th>
      <th>Stack default</th>
      <th>Always Free limit</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>ARM OCPUs</td>
      <td>4</td>
      <td>4 total</td>
    </tr>
    <tr>
      <td>Memory</td>
      <td>24 GB</td>
      <td>24 GB total</td>
    </tr>
    <tr>
      <td>Boot volume</td>
      <td>47 GB</td>
      <td>200 GB total</td>
    </tr>
    <tr>
      <td>Instances</td>
      <td>1</td>
      <td>Up to 4 ARM + 2 AMD</td>
    </tr>
  </tbody>
</table>

<p>If you change the defaults — say, bumping the boot volume to 200 GB — just make sure the total across all your instances stays within limits. And set up <a href="/2026/02/20/my-spin-on-claude-code-on-the-go/#cost">budget alerts</a> at $0.01 actual spend so you’ll know immediately if anything crosses the free line.</p>

<h2 id="overridable-defaults">Overridable Defaults</h2>

<p>You probably won’t need to touch these, but they’re there:</p>

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Default</th>
      <th>Why you’d change it</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">availability_domain_index</code></td>
      <td><code class="language-plaintext highlighter-rouge">0</code></td>
      <td>Your preferred AD is full — try <code class="language-plaintext highlighter-rouge">1</code> or <code class="language-plaintext highlighter-rouge">2</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ssh_public_key_path</code></td>
      <td><code class="language-plaintext highlighter-rouge">~/.ssh/id_ed25519.pub</code></td>
      <td>You use a different key</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">instance_name</code></td>
      <td><code class="language-plaintext highlighter-rouge">claude-dev</code></td>
      <td>You want a different display name</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ocpus</code></td>
      <td><code class="language-plaintext highlighter-rouge">4</code></td>
      <td>You’re splitting free resources across multiple instances</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">memory_in_gbs</code></td>
      <td><code class="language-plaintext highlighter-rouge">24</code></td>
      <td>Same — splitting across instances</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">boot_volume_size_in_gbs</code></td>
      <td><code class="language-plaintext highlighter-rouge">47</code></td>
      <td>You need more disk (up to 200 GB free total)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">assign_public_ip</code></td>
      <td><code class="language-plaintext highlighter-rouge">true</code></td>
      <td>Set to <code class="language-plaintext highlighter-rouge">false</code> after Tailscale is running</td>
    </tr>
  </tbody>
</table>

<h2 id="tearing-down-and-rebuilding">Tearing Down and Rebuilding</h2>

<p>This is the whole point of putting it in Terraform:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>terraform destroy   <span class="c"># gone</span>
terraform apply     <span class="c"># back</span>
</code></pre></div></div>

<p>State tracks what was created, so <code class="language-plaintext highlighter-rouge">destroy</code> is clean. No orphaned resources, no mystery charges showing up a month later because you forgot to delete a route table.</p>

<p>The rebuild cycle is useful when Oracle releases new Ubuntu images, when you want to start fresh after experimenting, or when you want to help someone else set up their own instance. Fork the repo, set two variables, apply.</p>

<h2 id="after-terraform-the-rest-of-the-stack">After Terraform: The Rest of the Stack</h2>

<p>Terraform gets you the VM. Everything after that — Tailscale, UFW, mosh, tmux, Claude Code, ntfy hooks — is covered in the <a href="/2026/02/20/my-spin-on-claude-code-on-the-go/">full setup guide</a>. The short version:</p>

<ol>
  <li>SSH in via the public IP</li>
  <li>Install Tailscale, authenticate, note your Tailscale IP</li>
  <li>Configure UFW to allow only the <code class="language-plaintext highlighter-rouge">tailscale0</code> interface</li>
  <li>Lock down the Oracle security list (remove SSH ingress)</li>
  <li>Optionally, <code class="language-plaintext highlighter-rouge">terraform apply</code> again with <code class="language-plaintext highlighter-rouge">assign_public_ip = false</code> to drop the public IP</li>
  <li>Install mosh, tmux, Node.js, Claude Code</li>
  <li>Set up ntfy notifications</li>
</ol>

<p>From that point on, you connect via Termius on your phone, mosh over Tailscale, and Claude Code runs in a persistent tmux session. Push notifications tell you when Claude needs input. The VM runs 24/7 for free.</p>

<h2 id="links">Links</h2>

<ul>
  <li><a href="https://github.com/kevinmcmahon/oci-alwaysfree-tf-stack">kevinmcmahon/oci-alwaysfree-tf-stack</a> (Terraform stack)</li>
  <li><a href="/2026/02/20/my-spin-on-claude-code-on-the-go/">My Spin on Claude Code On-the-Go</a> (full setup guide)</li>
  <li><a href="https://www.oracle.com/cloud/free/">oracle.com/cloud/free</a> (Oracle Always Free tier)</li>
</ul>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:oci-keys">
      <p>See <a href="https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm">Required Keys and OCIDs</a> for details on generating the API signing key and finding your tenancy/user OCIDs. <a href="#fnref:oci-keys" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="ai" /><category term="cli" /><category term="cloud" /><category term="oracle" /><category term="oci" /><category term="terraform" /><category term="iac" /><summary type="html"><![CDATA[In my previous post, I walked through setting up a zero-cost mobile Claude Code environment on Oracle Cloud’s Always Free tier. The VM, VCN, subnet, security list, and internet gateway take maybe 15 minutes to click through in the Oracle console, and you are up and running.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2026/terraform-for-your-always-free-claude-code-vm.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2026/terraform-for-your-always-free-claude-code-vm.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Introducing smartpin - AI-Powered Bookmarking for Pinboard</title><link href="https://www.kevfoo.com/2025/06/smartpin-blog-post/" rel="alternate" type="text/html" title="Introducing smartpin - AI-Powered Bookmarking for Pinboard" /><published>2025-06-07T00:00:00-05:00</published><updated>2025-06-07T00:00:00-05:00</updated><id>https://www.kevfoo.com/2025/06/smartpin-blog-post</id><content type="html" xml:base="https://www.kevfoo.com/2025/06/smartpin-blog-post/"><![CDATA[<p>I’m excited to announce the release of <a href="https://pypi.org/project/smartpin/">smartpin</a>, a new command-line tool that leverages AI to improve the metadata you capture for your Pinboard bookmarking. This tool scratches an itch that I’ve had for a while to apply some meaningful curation and organization to the links and articles I save off.</p>

<h2 id="the-problem-with-manual-bookmarking">The Problem with Manual Bookmarking</h2>

<p>We’ve all been there - you find an interesting article, quickly save it to your bookmarking service, and promise yourself you’ll come back later to properly tag and describe it. But “later” rarely comes, and you end up with a graveyard of poorly organized bookmarks that are nearly impossible to find when you need them.</p>

<p>Even when you do take the time to add metadata, it’s often inconsistent. Sometimes you use “machine-learning,” other times “ml” or “AI.” Your descriptions might be too verbose one day and non-existent the next. This inconsistency makes your bookmark collection less useful over time.</p>

<h2 id="enter-smartpin">Enter SmartPin</h2>

<p>smartpin solves this problem by using AI to automatically analyze web pages and extract relevant metadata. When you install the package from PyPI, you get the <code class="language-plaintext highlighter-rouge">pinit</code> command-line tool that:</p>

<ul>
  <li><strong>Extracts meaningful titles</strong> - Not just the HTML title tag, but the actual content headline</li>
  <li><strong>Generates concise descriptions</strong> - A 1-2 sentence summary of what the page is actually about</li>
  <li><strong>Suggests relevant tags</strong> - 3-8 contextually appropriate tags for better organization</li>
  <li><strong>Supports multiple AI models</strong> - Use Claude, GPT-4, Gemini, or other LLMs based on your preference</li>
</ul>

<h2 id="how-it-works">How It Works</h2>

<p>The usage is dead simple. Once configured with your Pinboard API token and AI provider credentials, just run:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pinit add https://example.com/interesting-article
</code></pre></div></div>

<p>The tool fetches the page content, sends it to your chosen AI model for analysis, and automatically creates a well-structured bookmark with proper metadata. No manual input required!</p>

<p>Here’s what the output looks like:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌─ Extracted Bookmark ─────────────────────────────────┐
│ Title: How to Build Better Software with AI          │
│ URL: https://example.com/ai-software-development     │
│ Description: A comprehensive guide exploring how     │
│ artificial intelligence can enhance software         │
│ development workflows and code quality.              │
│ Tags: ai, software-development, programming, guide   │
└──────────────────────────────────────────────────────┘

✓ Bookmark saved successfully!
</code></pre></div></div>

<h2 id="key-features">Key Features</h2>

<p><strong>Flexible AI Integration</strong>: The tool uses Simon Willison’s excellent <a href="https://llm.datasette.io/">LLM library</a>, which means you can easily switch between different AI providers. Prefer Claude? Use it. Have OpenAI credits? Switch to GPT-4. The choice is yours.</p>

<p><strong>Privacy Controls</strong>: Mark bookmarks as private or “to read” with simple flags:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pinit add https://example.com <span class="nt">--private</span> <span class="nt">--toread</span>
</code></pre></div></div>

<p><strong>Dry Run Mode</strong>: Preview what the AI extracts before saving:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pinit add https://example.com <span class="nt">--dry-run</span>
</code></pre></div></div>

<p><strong>JSON Output</strong>: Need to integrate with other tools? Get machine-readable output:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pinit add https://example.com <span class="nt">--json</span> | jq <span class="s1">'.tags'</span>
</code></pre></div></div>

<p><strong>Multiple Configuration Options</strong>: Configure via environment variables, local <code class="language-plaintext highlighter-rouge">.env</code> files, or user config at <code class="language-plaintext highlighter-rouge">~/.pinit/config</code>. The tool supports whatever workflow fits your style.</p>

<h2 id="installation-and-setup">Installation and Setup</h2>

<p>Getting started is straightforward:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Install from PyPI</span>
pip <span class="nb">install </span>smartpin

<span class="c"># Or if you use uv (recommended)</span>
uv pip <span class="nb">install </span>smartpin

<span class="c"># Set up your API tokens</span>
<span class="nb">export </span><span class="nv">PINBOARD_API_TOKEN</span><span class="o">=</span>your_username:your_token
<span class="nb">export </span><span class="nv">ANTHROPIC_API_KEY</span><span class="o">=</span>your_key  <span class="c"># Or OPENAI_API_KEY, etc.</span>

<span class="c"># Start bookmarking!</span>
pinit add https://example.com
</code></pre></div></div>

<h2 id="technical-details">Technical Details</h2>

<p>For the curious, smartpin is built with:</p>

<ul>
  <li><strong>Click</strong> for the CLI framework</li>
  <li><strong>Rich</strong> for beautiful terminal output</li>
  <li><strong>BeautifulSoup</strong> for robust HTML parsing</li>
  <li><strong>httpx</strong> for reliable web page fetching</li>
  <li><strong>Type hints</strong> throughout for better development experience</li>
</ul>

<p>The architecture is modular and clean, making it easy to extend or modify. The AI prompting is done through Jinja2 templates, so you can even customize how the AI analyzes pages if needed.</p>

<h2 id="whats-next">What’s Next?</h2>

<p>This is just the beginning. Some ideas for future development:</p>

<ul>
  <li>Bulk import of existing bookmarks for re-tagging</li>
  <li>Integration with browser extensions</li>
  <li>iOS share extension for quick capture of links on your iOS devices</li>
</ul>

<h2 id="try-it-out">Try It Out</h2>

<p>smartpin is open source and available now on <a href="https://pypi.org/project/smartpin/">PyPI</a> and <a href="https://github.com/kevinmcmahon/smartpin">GitHub</a>. I’d love to hear your feedback, feature requests, or contributions.</p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="projects" /><category term="ai" /><category term="tools" /><category term="pinboard" /><category term="python" /><category term="cli" /><summary type="html"><![CDATA[Introducing smartpin, a Python-based CLI tool that uses AI to automatically generate rich metadata for your Pinboard bookmarks.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2025/smartpin-blog-post.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2025/smartpin-blog-post.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Making Sure OpenSea Can Read Your Contract-level Metadata</title><link href="https://www.kevfoo.com/2022/05/opensea-contracturi/" rel="alternate" type="text/html" title="Making Sure OpenSea Can Read Your Contract-level Metadata" /><published>2022-05-25T00:00:00-05:00</published><updated>2022-05-25T00:00:00-05:00</updated><id>https://www.kevfoo.com/2022/05/opensea-contracturi</id><content type="html" xml:base="https://www.kevfoo.com/2022/05/opensea-contracturi/"><![CDATA[<p><em>Leaving this here for my future self and for others as this question pops up on the OpenSea discord quite a bit.</em></p>

<p><em>tl;dr</em> – Don’t return an IPFS URI (<code class="language-plaintext highlighter-rouge">ipfs://{cid})</code> or IPFS HTTP gateway URL (<code class="language-plaintext highlighter-rouge">https://ipfs.io/ipfs/{cid}</code> or <code class="language-plaintext highlighter-rouge">https://gateway.pinata.cloud/ipfs/{cid}</code>) via the <code class="language-plaintext highlighter-rouge">contractURI()</code> function. Use a traditional HTTP web API or base64 encode the metadata JSON and return it from the function if you want OpenSea to be able to read the contract-level metadata and display it on your collection’s page.</p>

<p>OpenSea allows smart contract developers to include <a href="https://docs.opensea.io/docs/contract-level-metadata">storefront-level metadata</a> by implementing a function named <code class="language-plaintext highlighter-rouge">contractURI()</code> and returning a URI pointing to the metadata. OpenSea expects metadata formatted as JSON that consists of a few specific attributes they recognize. This information is pre-populated into the NFT’s collections page associated with the smart contract on OpenSea.</p>

<p>For individual non-fungible tokens (NFT) like ERC721’s and ERC1155’s, calling the <code class="language-plaintext highlighter-rouge">tokenURI()</code> function with a tokenId value as a parameter returns a URI that points at the token’s metadata. The <code class="language-plaintext highlighter-rouge">tokenURI()</code> function typically returns URI that point to traditional endpoints like web servers or cloud storage using conventional URL protocols (<code class="language-plaintext highlighter-rouge">https://</code>) or, more commonly in web3, to files stored on IPFS via the IPFS URL protocol (<code class="language-plaintext highlighter-rouge">ipfs://</code>). URIs returned from this function can point directly to IPFS or via IPFS HTTP gateways without problems.</p>

<p>It is unclear from the docs, but the responses from the token URI function can vary more than the contract URI function. I have experimented with valid URI variations, all pointing to the same JSON, and had no success with having the contract URI function return either IPFS or IPFS public gateway URIs. Providing the same types of URI from the token URI functions has worked as expected. What I have found to work are the following:</p>

<ol>
  <li>
    <p>Return the metadata JSON as a base64 encoded string. Do not forget to prepend the string with <code class="language-plaintext highlighter-rouge">data:application/json;base64,{yourBase64EncodedStringHere}</code>.</p>
  </li>
  <li>
    <p>Return a URL pointing to a conventional REST API endpoint that returns the metadata JSON.</p>
  </li>
</ol>

<p>I cannot explain why the API requests to a REST API work as expected or why the requests to IPFS or an IPFS public gateway do not. I plan to file this as a ticket with OpenSea, and hopefully, if they’re unable to address the issue outright, they can at least update the docs to be more explicit about what can and cannot be returned from the contract URI function.</p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="reference" /><category term="contracturi" /><category term="nft" /><summary type="html"><![CDATA[Learn how to properly implement contract-level metadata for OpenSea collections by avoiding IPFS URIs and using base64 encoding or REST API endpoints.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2022/opensea-contracturi.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2022/opensea-contracturi.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Authenticating to Heroku via CLI with MFA Turned On</title><link href="https://www.kevfoo.com/2021/12/Heroku-CLI-with-MFA/" rel="alternate" type="text/html" title="Authenticating to Heroku via CLI with MFA Turned On" /><published>2021-12-09T00:00:00-06:00</published><updated>2021-12-09T00:00:00-06:00</updated><id>https://www.kevfoo.com/2021/12/Heroku-CLI-with-MFA</id><content type="html" xml:base="https://www.kevfoo.com/2021/12/Heroku-CLI-with-MFA/"><![CDATA[<p><em>Leaving this here for my future self.</em></p>

<p>Heroku has turned off interactive login and pushes folks to authenticate via a browser when authenticating to use the CLI app. This works fine if you don’t have MFA turned on (you should though!) and the flow completes without issue. If you do have MFA turned on, you’ll get a blank screen and a cryptic message (“IP address mismatch”) when attempting to complete the login.</p>

<p>To authenticate from the CLI you can follow <a href="https://help.heroku.com/AVOHZTFH/heroku-cli-login-interactive-option-no-longer-supported-with-salesforce-mfa">this note</a> from the Heroku Developer Docs and put your newly generated API key in a .netrc file or set and environment variable (<code class="language-plaintext highlighter-rouge">HEROKU_API_KEY</code>) or just enter the API key to the password prompt when interacting with the CLI.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜  ~ heroku auth:login -i
heroku: Enter your login credentials
Email : [YOUR_EMAIL_HERE]
Password : [THE_API_KEY_YOU_GENERATED]

Logged in as [YOUR_EMAIL_HERE]
</code></pre></div></div>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="heroku" /><category term="cli" /><category term="reference" /><summary type="html"><![CDATA[A quick fix for the Heroku CLI 'IP address mismatch' error when authenticating with Multi-Factor Authentication (MFA) enabled.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2021/heroku-cli-with-mfa.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2021/heroku-cli-with-mfa.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Carvey Replacement Hinges</title><link href="https://www.kevfoo.com/2020/10/Carvey-Replacement-Hinges/" rel="alternate" type="text/html" title="Carvey Replacement Hinges" /><published>2020-10-01T00:00:00-05:00</published><updated>2020-10-01T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/10/Carvey-Replacement-Hinges</id><content type="html" xml:base="https://www.kevfoo.com/2020/10/Carvey-Replacement-Hinges/"><![CDATA[<p>The internet is almost as impressive as my ability to break things. This is a story about how I broke a CNC machine and was able to not only find the exact replacement parts but order them for next day delivery within about 20 minutes.</p>

<h2 id="tldr">tl;dr</h2>

<p>The Inventables Carvey model I am using uses <em>Southco E6-10-301-20 Series Adjustable Torque Position Control Hinge with Holes</em>.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/10/southco-e6-10-301-20-hinge.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/10/southco-e6-10-301-20-hinge.jpg" /><img loading="lazy" src="https://cache.kevfoo.com/2020/10/southco-e6-10-301-20-hinge.jpg" title="" alt="" /></picture></p>

<p><a href="https://files.southco.com/static/Literature/e6-at.en.pdf">Southco E6-10-301-20 Series Adjustable Torque Position Control Hinge with Holes (PDF)</a></p>

<p><a href="https://www.amazon.com/gp/product/B00GM5G89E">Amazon Link</a></p>

<h2 id="what-happened">What Happened</h2>

<p>Recently a friend let me borrow a <a href="http://web.archive.org/web/20201001153120/https://www.inventables.com/technologies/carvey">Carvey</a> that was taking up space at his place and, not 10 mins after getting it powered up, I broke it. To make a long story short, I racked the lid when attempting to pick it up, which caused both hinges to fail catastrophically. The hydraulic lift, which props the lid open and provides a soft close, put a tremendous amount of pressure on the device’s plastic hinges. Once the first hinge failed, the second failed immediately. It felt like my heart was going to be next.</p>

<p>After calling the very understanding owner and apologizing for destroying the hinges, we discussed the steps necessary for repair. Inventables support is great. I’m sure I could’ve got replacement hinges from them. But that would take phone calls, support tickets, and waiting for them to ship one-off parts. The parts are just hinges. If we could get replacements, it is a simple process to affix them to the case. Maybe we can find replacements ourselves.</p>

<p>So the search began. After coming up empty via the search engine route, <a href="https://www.mcmaster.com">McMaster-Carr</a> was the next stop. It turns out there are tons of different hinges. McMaster-Carr apparently has <em>all</em> of them. We were however able to find <a href="https://www.mcmaster.com/adjustable-friction-hinges/">something</a> that looked promising. With the specs of the McMaster-Carr hinge now in hand, I got my calipers out. The sizes matched (give or take a ten-thousandth of an inch). We felt good about having a viable replacement option, but the question lingered if we could do better.</p>

<p>After a closer inspection of the broken hinges, I noticed that they had Southco branding. A quick search of their site led us to the <a href="http://web.archive.org/web/20201001152036/https://files.southco.com/static/Literature/e6-at.en.pdf">spec sheet</a> of the Southco E6-10-301-20. That was it, and of course, <a href="http://web.archive.org/web/20201001152835/https://www.amazon.com/gp/product/B00GM5G89E?pldnSite=1">Amazon</a> has it stocked and ready to ship.</p>

<p>The fact that I was able to identify these hinges, source them from a supplier, order a small number of them, and have them shipped to my door in two days is amazing. That I was able to do it within 20 minutes after I broke them blows my mind—what a world.</p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="cnc" /><category term="reference" /><summary type="html"><![CDATA[A quick guide to finding and ordering exact replacement hinges for the Inventables Carvey CNC machine after a common failure.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/carvey-replacement-hinges.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/carvey-replacement-hinges.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Favorites from September 2020</title><link href="https://www.kevfoo.com/2020/09/Favorites-from-September-2020/" rel="alternate" type="text/html" title="Favorites from September 2020" /><published>2020-09-30T00:00:00-05:00</published><updated>2020-09-30T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/09/Favorites-from-September-2020</id><content type="html" xml:base="https://www.kevfoo.com/2020/09/Favorites-from-September-2020/"><![CDATA[<p>A collection of some of my favorite links, images, tweets and quotes from September 2020. This is not an exhaustive list but does captures some things I found interesting, thought-provoking, or cool over the past month.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/09/it-has-no-use-but-it-has-value.webp" /><source type="image/png" srcset="https://cache.kevfoo.com/2020/09/it-has-no-use-but-it-has-value.png" /><img loading="lazy" src="https://cache.kevfoo.com/2020/09/it-has-no-use-but-it-has-value.png" title="" alt="" /></picture></p>

<p><em>via <a href="https://www.instagram.com/p/CFKgqBklTlS/?utm_source=ig_web_copy_link">wendy macnaughton on Instagram: “Art.”</a></em></p>

<h2 id="links">Links</h2>

<ul>
  <li><a href="https://the-toast.net/2014/07/11/how-to-buy-a-car/">How to Buy a Car Without Interacting With a Human - The Toast</a></li>
  <li><a href="https://www.youtube.com/watch?v=3GK_3KgZios">How To Steal Like Wes Anderson - The Grand Budapest Hotel - YouTube</a></li>
  <li><a href="https://www.type-together.com/typographic-matchmaking">Typographic matchmaking - TypeTogether</a></li>
</ul>

<h2 id="quotes">Quotes</h2>

<ul>
  <li><a href="https://twitter.com/thesamball/status/1301485871447838721">The four most expensive words in the english language are, “This time it’s different.” – Sir John Templeton</a></li>
  <li>“Nothing in life is to be feared, it is only to be understood. Now is the time to understand more, so that we may fear less.” – Shane Parrish &amp; Rhiannon Beaubien, The Great Mental Models Volume 2</li>
</ul>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><category term="quotes" /><summary type="html"><![CDATA[A curated collection of interesting links and articles from September 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/favorites-from-september-2020.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/favorites-from-september-2020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Favorites from August 2020</title><link href="https://www.kevfoo.com/2020/08/Favorites-from-August-2020/" rel="alternate" type="text/html" title="Favorites from August 2020" /><published>2020-08-31T00:00:00-05:00</published><updated>2020-08-31T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/08/Favorites-from-August-2020</id><content type="html" xml:base="https://www.kevfoo.com/2020/08/Favorites-from-August-2020/"><![CDATA[<p>A collection of some of my favorite links, images, tweets and quotes from August 2020. This is not an exhaustive list but does captures some things I found interesting, thought-provoking, or cool over the past month.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/08/lego-dimensions-car-show.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/08/lego-dimensions-car-show.jpg" /><img loading="lazy" src="https://cache.kevfoo.com/2020/08/lego-dimensions-car-show.jpg" title="Lego Dimensions Car Show" alt="Nostalgia is a helluva drug." /></picture></p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/08/this-machine-kills-fascists.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/08/this-machine-kills-fascists.jpg" /><img loading="lazy" src="https://cache.kevfoo.com/2020/08/this-machine-kills-fascists.jpg" title="This machine kills fascists" alt="This blue box is the last thing in the world that I thought our democracy would hinge on." /></picture></p>

<h2 id="reading">Reading</h2>

<ul>
  <li><a href="http://web.archive.org/web/20200804184514/https://www.theatlantic.com/magazine/archive/2020/09/coronavirus-american-failure/614191/">How the Pandemic Defeated America</a></li>
  <li><a href="https://www.nytimes.com/2020/08/31/opinion/cdc-testing-coronavirus.html">It Has Come to This: Ignore the C.D.C.</a></li>
</ul>

<h2 id="admiring">Admiring</h2>

<ul>
  <li><a href="https://www.poojapittie.com/2020">Art by Pooja Pittie</a></li>
</ul>

<h2 id="watching">Watching</h2>

<ul>
  <li><a href="https://vimeo.com/446927270">2020: An Isolation Odyssey</a> via <a href="https://kottke.org/20/08/2020-an-isolation-odyssey">@kottke</a></li>
</ul>

<h2 id="links">Links</h2>

<ul>
  <li>
    <p><a href="https://www.designedbycave.co.uk/2020/LEGO-Interface-UX/">The UX of LEGO Interface Panels – George Cave</a></p>
  </li>
  <li>
    <p><a href="https://coolors.co/">Coolors - The super fast color schemes generator!</a></p>
  </li>
  <li>
    <p><a href="https://www.thisiscolossal.com/2020/08/victor-solomon-kintsugi-court/">Opulent Kintsugi Installation</a> via <a href="https://www.thisiscolossal.com">@colossal</a></p>
  </li>
  <li>
    <p><a href="https://a.singlediv.com/">A Single Div: a CSS drawing project by Lynn Fisher</a></p>
  </li>
  <li>
    <p><a href="https://kottke.org/20/08/ai-claudius">AI Claudius</a></p>
  </li>
</ul>

<h2 id="cooking">Cooking</h2>

<ul>
  <li><a href="https://twitter.com/seriouseats/status/1294076271308177411">Treat your summer tomatoes right by mastering these essential techniques.</a></li>
</ul>

<h2 id="ordering">Ordering</h2>

<ul>
  <li><a href="https://web.archive.org/web/20210126012444/https://publishing.andrewsmcmeel.com/calendar/tricks-to-appear-smart-in-meetings-2021-day-to-day-calendar/">Tricks to Appear Smart in Meetings 2021 Day-to-Day Calendar</a></li>
</ul>

<h2 id="ideas">Ideas</h2>

<blockquote>
  <p>“A bad system will beat a good person every time.” W. Edwards Demming</p>
</blockquote>

<p>via <a href="https://twitter.com/marshallk/status/1291900360865406982">@marshallk</a></p>

<blockquote>
  <p>“The optimal strategy might be executing a suboptimal plan at a fast pace. Strategy evolves as lessons are learned—and the person who moves faster, learns faster. Learning is a marathon and perfection is a weighted vest.” – <a href="https://twitter.com/JamesClear/status/1290661258002407428">@JamesClear</a></p>
</blockquote>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><category term="quotes" /><summary type="html"><![CDATA[A curated collection of interesting links and articles from August 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/favorites-from-august-2020.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/favorites-from-august-2020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Favorites from July 2020</title><link href="https://www.kevfoo.com/2020/07/Favorites-from-July-2020/" rel="alternate" type="text/html" title="Favorites from July 2020" /><published>2020-07-31T00:00:00-05:00</published><updated>2020-07-31T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/07/Favorites-from-July-2020</id><content type="html" xml:base="https://www.kevfoo.com/2020/07/Favorites-from-July-2020/"><![CDATA[<p>A collection of some of my favorite links, images, tweets and quotes from July. This is not an exhaustive list but does captures some things I found interesting, thought-provoking, or cool over the past month.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/07/coronacoaster.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/07/coronacoaster.jpg" /><img loading="lazy" src="https://cache.kevfoo.com/2020/07/coronacoaster.jpg" title="Coronacoaster (noun)" alt="The worst ride of 2020." /></picture></p>

<h2 id="reading">Reading</h2>

<ul>
  <li>
    <p><a href="https://books-on-books.com/2020/06/27/books-on-books-collection-the-last-word-on-the-ampersand/">Books On Books Collection - The Last Word on the Ampersand</a></p>
  </li>
  <li>
    <p><a href="https://www.vulture.com/article/jerry-saltz-the-last-supper.html?utm_source=tw">Jerry Saltz: My Quarantine Obsession: These Two Last Suppers</a></p>
  </li>
</ul>

<h2 id="links">Links</h2>

<ul>
  <li>
    <p><a href="https://gobyexample.com/">Go by Example</a></p>
  </li>
  <li>
    <p><a href="https://ncase.me/loopy/">LOOPY: a tool for thinking in systems</a></p>
  </li>
  <li>
    <p><a href="https://dataconomy.com/2015/06/the-four-essentials-vs-for-a-big-data-analytics-platform/">The Four Essential V’s for a Big Data Analytics Platform</a></p>
  </li>
  <li>
    <p><a href="https://www.websters1913.com/">Webster’s 1913</a></p>
  </li>
  <li>
    <p><a href="http://web.archive.org/web/20200801050152/https://emilyoster.substack.com/p/resource-rundown-for-schools-and">Resource Rundown (for Schools &amp; Parents) - ParentData</a></p>
  </li>
  <li>
    <p><a href="https://www.supremo.co.uk/typeterms/">Type Terms</a></p>
  </li>
</ul>

<h2 id="ideas">Ideas</h2>

<ul>
  <li>
    <p><a href="https://www.heavybit.com/library/video/executive-communication/">Executive Communication w/ Harrison Metal’s Michael Dearing</a></p>
  </li>
  <li>
    <p><a href="https://twitter.com/helenanders26/status/1278269080697335808">Java is to JavaScript, as Ham is to Hamburger. Never fails to get that ‘lightbulb’ moment.</a></p>
  </li>
  <li>
    <p><a href="https://austinkleon.com/2017/11/24/have-you-tried-making-yourself-a-more-interesting-person/">Have you tried making yourself a more interesting person? - Austin Kleon</a></p>
  </li>
  <li>
    <p><a href="https://twitter.com/jsjoeio/status/1281256827037134849">Effective learning: Twenty rules of formulating knowledge — Thread by @jsjoeio</a></p>
  </li>
  <li>
    <p><a href="https://sravivarman.com/self-development/the-difference-between-reversible-and-irreversible-decisions/">The Difference Between Reversible and Irreversible Decisions – Ravivarman</a></p>
  </li>
</ul>

<blockquote>
  <p>Our lives are based on symbols and mental models that we use to understand and internalize the external world. But are our mental models “accurate working models”?
— David Deutsch, <a href="https://twitter.com/ruthmalan/status/1287766072083517440">via @ruthmalan</a></p>
</blockquote>

<h2 id="filed-for-later-use">Filed for Later Use</h2>

<p>JavaScript tip via <a href="https://twitter.com/sulco">Tomek Sułkowski</a>: “npkill” is a nifty little tool that shows all <code class="language-plaintext highlighter-rouge">node_modules</code> in your system - and allows to remove the selected ones.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npx npkill
</code></pre></div></div>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><summary type="html"><![CDATA[A curated collection of interesting links and articles from July 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/favorites-from-july-2020.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/favorites-from-july-2020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Chicago Alphabet</title><link href="https://www.kevfoo.com/2020/07/chicago-alphabet/" rel="alternate" type="text/html" title="Chicago Alphabet" /><published>2020-07-30T00:00:00-05:00</published><updated>2020-07-30T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/07/chicago-alphabet</id><content type="html" xml:base="https://www.kevfoo.com/2020/07/chicago-alphabet/"><![CDATA[<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/07/chicago-alphabet.webp" /><source type="image/png" srcset="https://cache.kevfoo.com/2020/07/chicago-alphabet.png" /><img src="https://cache.kevfoo.com/2020/07/chicago-alphabet.png" title="Chicago Alphabet" alt="The city of big type." /></picture></p>

<p><a href="https://twitter.com/53viroqua/status/1286801447275896835">Chicago Alphabet</a> via <a href="https://twitter.com/53viroqua">@53viroqua</a></p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="chicago" /><summary type="html"><![CDATA[A visual exploration of a Chicago-themed alphabet, celebrating the unique icons and landmarks of the city.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/chicago-alphabet.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/chicago-alphabet.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Pierian Spring</title><link href="https://www.kevfoo.com/2020/07/pierian-spring/" rel="alternate" type="text/html" title="Pierian Spring" /><published>2020-07-23T00:00:00-05:00</published><updated>2020-07-23T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/07/pierian-spring</id><content type="html" xml:base="https://www.kevfoo.com/2020/07/pierian-spring/"><![CDATA[<blockquote>
  <p>“A little Learning is a dang’rous Thing;<br />
Drink deep, or taste not the Pierian Spring:<br />
There shallow Draughts intoxicate the Brain,<br />
And drinking largely sobers us again.”</p>

  <p>— Alexander Pope, <a href="https://en.wikisource.org/wiki/An_Essay_on_Criticism">An Essay on Criticism</a></p>
</blockquote>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="poetry" /><summary type="html"><![CDATA[A timeless quote from Alexander Pope's 'An Essay on Criticism' about the dangers of shallow learning and the pursuit of deeper knowledge.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/pierian-spring.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/pierian-spring.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Favorites from June 2020</title><link href="https://www.kevfoo.com/2020/06/Favorites-from-June-2020/" rel="alternate" type="text/html" title="Favorites from June 2020" /><published>2020-06-30T00:00:00-05:00</published><updated>2020-06-30T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/06/Favorites-from-June-2020</id><content type="html" xml:base="https://www.kevfoo.com/2020/06/Favorites-from-June-2020/"><![CDATA[<p>A collection of some of my favorite links, images, tweets and quotes from June. This is not an exhaustive list but does captures some things I found interesting, thought-provoking, or cool over the past month.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/06/image.webp" /><source type="image/png" srcset="https://cache.kevfoo.com/2020/06/image.png" /><img src="https://cache.kevfoo.com/2020/06/image.png" title="" alt="" /></picture></p>

<p><em><a href="https://twitter.com/IanSanders/status/1268797120183754753">via @IanSanders</a></em></p>

<h2 id="links">Links</h2>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/06/an-undulating-brick-facade-3.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/06/an-undulating-brick-facade-3.jpg" /><img src="https://cache.kevfoo.com/2020/06/an-undulating-brick-facade-3.jpg" title="" alt="" /></picture></p>

<ul>
  <li><a href="https://themindcircle.com/an-undulating-brick-facade-germany/">This Undulating Brick Façade Imitates The Movement Of Draped Fabric</a></li>
  <li><a href="https://carbon.now.sh/">Carbon - Create and share beautiful images of your source code. Start typing or drop a file into the text area to get started.</a></li>
  <li><a href="https://www.redblobgames.com/grids/hexagons/#map-storage">Hexagonal Grids - Map storage in axial coordinates</a></li>
  <li><a href="https://daringfireball.net/linked/2020/06/12/catalina-extra-fonts">Daring Fireball: Excellent MacOS Catalina Fonts You Probably Didn’t Know You Had Access To</a></li>
</ul>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/06/hemingway.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/06/hemingway.jpg" /><img src="https://cache.kevfoo.com/2020/06/hemingway.jpg" title="Hemingway." alt="What if Dracula had Gun Hands?" /></picture></p>
<ul>
  <li><a href="https://twitter.com/pixelatedboat/status/1271442840996900864">Hemingway. via @pixelatedboat</a></li>
</ul>

<h2 id="ideas">Ideas</h2>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/06/knots-1.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/06/knots-1.jpg" /><img src="https://cache.kevfoo.com/2020/06/knots-1.jpg" title="Windy Chien's Knot Wall" alt="chop wood, carry water" /></picture></p>

<ul>
  <li><a href="https://www.thisiscolossal.com/2020/06/windy-chien-circuit-boards/">Rope Twists into Massive, Fibrous Circuit Boards by Artist Windy Chien</a></li>
</ul>

<p>What I particularly like about the Rope Twists is the origin story. Windy Chien set out to learn a new knot everyday. The discipline of getting up and doing that every single day led to the permissive creativity which produced the art.</p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><summary type="html"><![CDATA[A curated collection of interesting links and articles from June 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/favorites-from-june-2020.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/favorites-from-june-2020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Favorites from May 2020</title><link href="https://www.kevfoo.com/2020/05/Favorites-from-May-2020/" rel="alternate" type="text/html" title="Favorites from May 2020" /><published>2020-05-31T00:00:00-05:00</published><updated>2020-05-31T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/05/Favorites-from-May-2020</id><content type="html" xml:base="https://www.kevfoo.com/2020/05/Favorites-from-May-2020/"><![CDATA[<p>A collection of some of my favorite links, images, tweets and quotes from May. This is not an exhaustive list but does captures some things I found interesting, thought-provoking, or cool over the past month.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/05/may-murder-hornets.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/05/may-murder-hornets.jpg" /><img src="https://cache.kevfoo.com/2020/05/may-murder-hornets.jpg" title="May, in a nutshell." alt="It can always get worse." /></picture></p>

<h2 id="links">Links</h2>

<ul>
  <li><a href="http://computers-are-fast.github.io/">Do You Know How Much Your Computer Can Do in a Second?</a></li>
  <li><a href="https://robservatory.com/speed-up-your-mac-via-hidden-prefs/">Speed up your Mac via hidden preferences</a></li>
  <li><a href="https://blog.coryfoy.com/mapping-mondays/">(Wardley) Mapping Mondays</a></li>
</ul>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><summary type="html"><![CDATA[A curated collection of interesting links and articles from May 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/favorites-from-may-2020.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/favorites-from-may-2020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Favorites from April 2020</title><link href="https://www.kevfoo.com/2020/04/Favorites-from-April-2020/" rel="alternate" type="text/html" title="Favorites from April 2020" /><published>2020-04-30T00:00:00-05:00</published><updated>2020-04-30T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/04/Favorites-from-April-2020</id><content type="html" xml:base="https://www.kevfoo.com/2020/04/Favorites-from-April-2020/"><![CDATA[<p>A collection of some of my favorite links, images, tweets and quotes from April. These aren’t comprehensive but do capture some of the things I found interesting, thought-provoking, or cool while surviving but not thriving during the past month.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/04/dunning-kruger.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/04/dunning-kruger.jpg" /><img src="https://cache.kevfoo.com/2020/04/dunning-kruger.jpg" title="...it's time for Dunning Kruger" alt="When you know more than doctors who've spent their entire careers studying infectious diseases, it's time for Dunning-Kruger." /></picture></p>

<p><em>via</em> <a href="https://twitter.com/theturner/status/1252336852108931072">@theturner</a></p>

<h2 id="quotes">Quotes</h2>

<p>“The great ones do not set up offices, charge fees, give lectures, or write books. Wisdom is silent, and the most effective propaganda for truth is the force of personal example. The great ones attract disciples, lesser figures whose mission is to preach and to teach. These are gospelers who, unequal to the highest task, spend their lives in converting others. The great ones are indifferent, in the profoundest sense. They don’t ask you to believe: they electrify you by their behavior. They are the awakeners. What you do with your petty life is of no concern to them. What you do with your life is only of concern to you, they seem to say. In short, their only purpose here on earth is to inspire. And what more can one ask of a human being than that?” – <a href="https://www.nitch.com/posts/1652259674657208320">Henry Miller</a></p>

<p><a href="https://www.goodreads.com/quotes/5069838-be-scared-you-can-t-help-that-but-don-t-be-afraid-ain-t">“Be scared. You can’t help that. But don’t be afraid.”</a> – William Faulkner, <em>The Bear</em></p>

<h2 id="links">Links</h2>

<ul>
  <li><a href="https://www.patatap.com/">Play with your keyboard.</a></li>
  <li><a href="https://scottberkun.com/2020/its-time-to-learn/">It’s time to learn.</a></li>
  <li><a href="https://medium.com/@rakyll/things-i-wished-more-developers-knew-about-databases-2d0178464f78">Things I Wished More Developers Knew About Databases</a></li>
  <li><a href="https://www.betterworldbooks.com/go/donate">Donate Books</a></li>
  <li>Art Institute of Chicago (soft) launched <a href="https://www.artic.edu/open-access/">an API</a> to access their collection…</li>
  <li>…and you can get one of my favorites there on <a href="https://www.threadless.com/search?q=great%20wave&amp;sort=popular&amp;style=face-mask&amp;departments=accessories">a mask</a>.</li>
</ul>

<p><em>Bring on the May flowers!</em></p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><summary type="html"><![CDATA[A curated collection of interesting links and articles from April 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/favorites-from-april-2020.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/favorites-from-april-2020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">2020 in a picture</title><link href="https://www.kevfoo.com/2020/04/2020-in-a-picture/" rel="alternate" type="text/html" title="2020 in a picture" /><published>2020-04-29T00:00:00-05:00</published><updated>2020-04-29T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/04/2020-in-a-picture</id><content type="html" xml:base="https://www.kevfoo.com/2020/04/2020-in-a-picture/"><![CDATA[<p>I can’t think of a better way to capture what my 2020 has been like so far than this.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/04/jordan-shocked-face.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/04/jordan-shocked-face.jpg" /><img src="https://cache.kevfoo.com/2020/04/jordan-shocked-face.jpg" title="" alt="Yep. Pretty much." /></picture></p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="quotes" /><summary type="html"><![CDATA[A single image that perfectly captures the shock and disbelief of navigating the year 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/2020-in-a-picture.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/2020-in-a-picture.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Favorites from March 2020</title><link href="https://www.kevfoo.com/2020/03/Favorites-from-March-2020/" rel="alternate" type="text/html" title="Favorites from March 2020" /><published>2020-03-31T00:00:00-05:00</published><updated>2020-03-31T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/03/Favorites-from-March-2020</id><content type="html" xml:base="https://www.kevfoo.com/2020/03/Favorites-from-March-2020/"><![CDATA[<p>A collection of some of my favorite links, images, tweets and quotes from March. These aren’t comprehensive but do capture some of the things I found interesting, thought provoking, or cool while trying to survive the past month.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/03/sidewalk-chalk.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/03/sidewalk-chalk.jpg" /><img src="https://cache.kevfoo.com/2020/03/sidewalk-chalk.jpg" title="The greatest pleasure of life is love. -- Euripides" alt="The greatest pleasure of life is love. -- Euripides" /></picture></p>

<h2 id="listening">Listening</h2>

<ul>
  <li><a href="https://brain.fm">Brain.fm</a></li>
  <li><a href="https://web.archive.org/web/20200326231251/https://store.nin.com/products/ghosts-digital-download">NIN Ghosts V &amp; VI</a></li>
</ul>

<h2 id="favorite-quotes">Favorite Quotes</h2>

<ul>
  <li>“Half of strategy consulting is breaking one question apart into three and the other half is turning three questions into one.” – <a href="https://twitter.com/benedictevans/status/1235675848264409088">Ben Evans</a></li>
</ul>

<h2 id="favorite-links">Favorite Links</h2>

<ul>
  <li><a href="https://www.seriouseats.com/coronavirus-cooking-guide">The Coronavirus Cooking Guide — Serious Eats</a></li>
  <li><a href="https://www.slideas.app/">Slideas Markdown Presentation Editor for Mac</a> – Cool markdown to slides tool to compete with Deckset</li>
  <li><a href="https://adamschwartz.co/magic-of-css/">Magic of CSS — Adam Schwartz</a></li>
  <li><a href="https://austinkleon.com/2020/03/04/how-to-make-a-zine-from-a-single-sheet-of-paper/">How to make a zine from a single sheet of paper — Austin Kleon</a></li>
  <li><a href="http://library.nyam.org/colorourcollections/2020-participating-institutions/participating-institutions/">Download Free Coloring Books from 113 Museums</a> <em>via</em> <a href="https://twitter.com/openculture/status/1240660846851706881">Open Culture</a></li>
  <li><a href="https://www.travelandleisure.com/attractions/museums-galleries/museums-with-virtual-tours">12 Museums From Around the World That You Can Visit Virtually</a></li>
</ul>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><category term="quotes" /><summary type="html"><![CDATA[A curated collection of interesting links and articles from March 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/favorites-from-march-2020.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/favorites-from-march-2020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Links for Parents with Kids on a (Sudden) Staycation</title><link href="https://www.kevfoo.com/2020/03/links-for-parents-with-kids/" rel="alternate" type="text/html" title="Links for Parents with Kids on a (Sudden) Staycation" /><published>2020-03-15T00:00:00-05:00</published><updated>2020-03-15T00:00:00-05:00</updated><id>https://www.kevfoo.com/2020/03/links-for-parents-with-kids</id><content type="html" xml:base="https://www.kevfoo.com/2020/03/links-for-parents-with-kids/"><![CDATA[<p>Like most families we found out last week that our school and daycare were closing. For the better part of the weekend I’ve been scrambling to prepare and figure out what our game plan is. Our school district sent home e-learning resources, lesson plans, and enrichment activities. This will help but, as a parent, your bag of tricks can never be too deep.</p>

<p>I’ve started collecting ideas, activities and information for our kids and figured I’d share. Below is a collection of what I’ve aggregated so far. I’ll continue to edit these and encourage anyone to share what they’ve found useful or helpful <a href="https://gist.github.com/kevinmcmahon/928745dbeba9073b105edc2d4d9d5014">via this Github Gist</a>.</p>

<h2 id="activities">Activities</h2>

<ul>
  <li><a href="http://public.pbs.org/PBSKIDSDaily">PBS KIDS DAILY (Newsletter)</a></li>
  <li><a href="http://view.commonsense-email.org/?qs=5651c92ff8ba28babcecae7fa77d679486a89fce790dd11ff8f3244eba846ef30daaa5804b7b13cb1219e64cb6521881960bd3f2d0374b553d45d9bd45b66eca51e9ca19af15d3ad689bceac427e0ade4ac66f8764cc24f3">Resources for Families and Educators Facing Coronavirus Uncertainty</a></li>
  <li><a href="https://www.youtube.com/channel/UC1XLSK-wYXG5qWqkHeBhj9w">Jen the Entomologist Pre-school Science - Tiny Science Channel</a></li>
</ul>

<h2 id="digital-field-trips">Digital Field Trips</h2>

<ul>
  <li><a href="https://www.travelandleisure.com/attractions/museums-galleries/museums-with-virtual-tours">12 Museums From Around the World That You Can Visit Virtually</a></li>
</ul>

<h2 id="creative">Creative</h2>

<ul>
  <li><a href="https://austinkleon.com/2020/03/04/how-to-make-a-zine-from-a-single-sheet-of-paper/">How to make a zine from a single sheet of paper - Austin Kleon</a></li>
  <li><a href="https://austinkleon.com/2020/03/24/drawing-with-kids/">Austin Kleon’s Drawing with Kids Recommendations</a></li>
  <li><a href="https://www.youtube.com/watch?v=vheR1cd58oc&amp;list=PL14hRqd0PELGbKihHuTqx_pbvCLqGbOkF">Lunch Doodles with Mo Willems</a></li>
  <li><a href="https://www.instagram.com/wendymac/">Wendy MacNaughton’s Daily Draw Together Sessions on Instagram Live</a></li>
</ul>

<h2 id="talking-to-kids">Talking to Kids</h2>

<ul>
  <li><a href="https://www.pbs.org/parents/thrive/how-you-and-your-kids-can-de-stress-during-coronavirus">How You and Your Kids Can De-Stress During Coronavirus</a></li>
  <li><a href="https://www.youtube.com/watch?v=4ex4H6n_s7w">What is social distancing? (Video)</a></li>
  <li><a href="https://sites.google.com/district65.net/socialemotionallibrary/home">Miss Johnson’s Social Emotional Online Library</a></li>
</ul>

<h2 id="home-schooling">Home Schooling</h2>

<ul>
  <li><a href="https://www.linkedin.com/pulse/schooling-home-advice-from-homeschooling-family-eric-johnson/">Schooling at home advice from a homeschooling family.</a></li>
  <li><a href="https://docs.google.com/spreadsheets/d/1RRv9cENXMp1frTxMmGv3HrNkag6e2RqRZirpHSRzy44/htmlview?fbclid=IwAR0genzlpAzaPgv9tmgLRQVU4sFZgAKBFiCzCipL0gfxTZIj6NG9rvbW8IE&amp;sle=true#gid=0">Amazing Educational Resources — Google Docs</a></li>
  <li>
    <p><a href="https://classroommagazines.scholastic.com/support/learnathome.html">Scholastic Learn at Home</a></p>

    <p><em>Last Updated 3/24</em></p>
  </li>
</ul>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><summary type="html"><![CDATA[A curated collection of educational resources, creative activities, and field trips for parents navigating sudden school closures and staycations.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/links-for-parents-with-kids.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/links-for-parents-with-kids.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Why You’re Good</title><link href="https://www.kevfoo.com/2020/03/more-important-why-youre-good/" rel="alternate" type="text/html" title="Why You’re Good" /><published>2020-03-01T00:00:00-06:00</published><updated>2020-03-01T00:00:00-06:00</updated><id>https://www.kevfoo.com/2020/03/more-important-why-youre-good</id><content type="html" xml:base="https://www.kevfoo.com/2020/03/more-important-why-youre-good/"><![CDATA[<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/03/more-important-why-youre-good.webp" /><source type="image/png" srcset="https://cache.kevfoo.com/2020/03/more-important-why-youre-good.png" /><img src="https://cache.kevfoo.com/2020/03/more-important-why-youre-good.png" title="Why You're Good" alt="It's more important to know why you're good than that you're good." /></picture></p>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="quotes" /><summary type="html"><![CDATA[A thought-provoking visual and quote on the importance of understanding why you are good, rather than just knowing that you are.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/more-important-why-youre-good.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/more-important-why-youre-good.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Favorites from February 2020</title><link href="https://www.kevfoo.com/2020/02/Favorites-from-February-2020/" rel="alternate" type="text/html" title="Favorites from February 2020" /><published>2020-02-29T00:00:00-06:00</published><updated>2020-02-29T00:00:00-06:00</updated><id>https://www.kevfoo.com/2020/02/Favorites-from-February-2020</id><content type="html" xml:base="https://www.kevfoo.com/2020/02/Favorites-from-February-2020/"><![CDATA[<p>A collection of some of my favorite links, images, tweets and quotes from February. These aren’t comprehensive but do capture some of the things I found interesting, thought provoking, or cool over the past month.</p>

<p><picture><source type="image/webp" srcset="https://cache.kevfoo.com/2020/02/empty-when-full.webp" /><source type="image/jpeg" srcset="https://cache.kevfoo.com/2020/02/empty-when-full.jpg" /><img src="https://cache.kevfoo.com/2020/02/empty-when-full.jpg" title="Empty When Full" alt="Existential trash." /></picture></p>

<h2 id="filed-for-later-use">Filed for later use</h2>

<ul>
  <li>If you hit a SSL error on a page in Chrome, type <code class="language-plaintext highlighter-rouge">thisisunsafe</code> to ignore it. ( <em><a href="https://twitter.com/tapbot_paul/status/1226379496539836416">via @tapbot_paul</a></em> )</li>
</ul>

<h2 id="reading">Reading</h2>

<ul>
  <li><a href="https://www.goodreads.com/book/show/24490392-the-15-commitments-of-conscious-leadership">The 15 Commitments of Conscious Leadership</a> nudged via the <a href="https://fs.blog/jim-dethmer/">Farnam Street podcast</a>.</li>
  <li><a href="https://leanpub.com/wardley-maps">Wardley Maps</a> ebook that you can pick your price on with all proceeds going to charity.</li>
</ul>

<h2 id="favorite-quotes">Favorite Quotes</h2>

<ul>
  <li>“The least obvious part of the system, its function or purpose, is often the most crucial determinant of the system’s behavior.” (Donella H. Meadows, Thinking in Systems)</li>
  <li>“Ignorance is the softest pillow on which a man can rest his head.” – Michel de Montaigne <em>via <a href="https://twitter.com/EthicsInBricks/status/1229378893980807168">Ethics in Bricks</a></em></li>
</ul>

<h2 id="favorite-links">Favorite Links</h2>

<ul>
  <li>
    <p>Microsoft has a nice catalog of <a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/">Cloud Design Patterns</a> arranged by category</p>
  </li>
  <li>
    <p><a href="https://web.archive.org/web/20230715133218/https://towardsdatascience.com/all-machine-learning-models-explained-in-6-minutes-9fe30ff6776a">All Machine Learning Models Explained in 6 Minutes</a></p>
  </li>
  <li>
    <p><a href="https://www.youtube.com/watch?v=gmc4wEL2aPQ">Mind in Motion: How Action Shapes Thought – Stanford Seminar – Barbara Tversky</a></p>
  </li>
  <li>
    <p>If you’re fresh out of things to worry about, checkout this <a href="https://www.thisiscolossal.com/2020/02/metaballstudio-asteroid-animation/">comparison of the size of asteroids in the solar system to New York City</a></p>
  </li>
</ul>]]></content><author><name>Kevin McMahon</name><email>kevin@kevfoo.com</email><uri>https://www.kevfoo.com/about/</uri></author><category term="links" /><category term="quotes" /><summary type="html"><![CDATA[A curated collection of interesting links and articles from February 2020.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kevfoo.com/images/og/2020/favorites-from-february-2020.png" /><media:content medium="image" url="https://www.kevfoo.com/images/og/2020/favorites-from-february-2020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>