<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>hi, it&#39;s mike</title>
    <link>https://mike.puddingtime.org/tags/gpg/</link>
    <description>Recent content on hi, it&#39;s mike</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>mike@puddingtime.org (mike)</managingEditor>
    <webMaster>mike@puddingtime.org (mike)</webMaster>
    <copyright>© 2026, mike</copyright>
    <lastBuildDate>Sun, 28 Jan 2024 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://mike.puddingtime.org/tags/gpg/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Keeping secrets with 1Password&#39;s CLI tool</title>
      <link>https://mike.puddingtime.org/posts/2024-01-28-keeping-secrets-with-1password-s-cli-tool/</link>
      <pubDate>Sun, 28 Jan 2024 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2024-01-28-keeping-secrets-with-1password-s-cli-tool/</guid>
      <description>A couple of ways to securely reference your secrets in scripts and apps using 1Password&amp;rsquo;s CLI tool (and a detour into gpg-based approaches.)</description>
      <content:encoded><![CDATA[<p>I wrote the initial version of my <a href="/posts/2024-01-26-daily-notes/">linkding plugin for Newsboat</a> using <a href="https://github.com/bkeepers/dotenv">dotenv</a> to provide my Linkding API key. You just have a <kbd>.env</kbd> file in your home directory with a simple &ldquo;<kbd>KEY=VALUE</kbd>&rdquo; setup. Works fine for not hardcoding your secrets into scripts and reducing the chance you&rsquo;ll end up adding a credential to version control, but the secrets are sitting around unencrypted.</p>
<p>Now that I have it working at about the same level of reliability as the other plugins in the Newsboat repo I&rsquo;ll pull out the dependency on <kbd>dotenv</kbd> and just tell the would-be consumer &ldquo;get this credential into an environment variable, hardcode it, or do something else that feels safe to you.&rdquo;</p>
<p>For myself, I&rsquo;m weighing a couple of options because I&rsquo;d like to do a little better than having a bunch of credentials sitting around in the plain.</p>
<p>Over the years I&rsquo;ve handled this with mutt by combining gpg with mutt&rsquo;s <kbd>source</kbd> config command:</p>
<ol>
<li>
<p>Make a very minimal rc file in mutt&rsquo;s config syntax that sets your user and password:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">       set imap_user=you@example.com
</span></span><span class="line"><span class="cl">       set imap_pass=yourimappassword1234</span></span></code></pre></div>
</li>
<li>
<p>Encrypt that file with gpg:</p>
<p><kbd>gpg -r <a href="mailto:yourkey@example.com">yourkey@example.com</a> &ndash;encrypt passwordfile</kbd></p>
</li>
<li>
<p>Use mutt&rsquo;s <kbd>source</kbd> directive in your <kbd>muttrc</kbd> to decrypt the file on the fly and read in those two directives:</p>
<p><kbd>source &ldquo;gpg -d ~/.mutt/passwords.gpg |&quot;</kbd></p>
</li>
</ol>
<p>If you have gpg set up correctly, you&rsquo;ll get a key authentication prompt when you run mutt. The credentials are never stored in the plain on disk, and you&rsquo;ll get a gpg password prompt every now and then if you have other stuff going on, such as multiple accounts that each need to periodically source that config when you change between them. mutt&rsquo;s <kbd>source</kbd> is just &ldquo;do whatever is in this file,&rdquo; same as <kbd>zsh</kbd>&rsquo;s, so I eventually landed on a way to do the same thing in a shell environment:</p>
<p><kbd>$(gpg &ndash;decrypt ./setenv.sh.gpg)</kbd></p>
<p>That just decrypts <kbd>setenv.sh.gpg</kbd> and runs the commands inside, which can be just setting a bunch of environment variables in the current shell environment. The data is never decrypted to disk.</p>
<p>That seems like a good general solution that covers a lot of drive-by security scenarios.</p>
<p>In the process of working that out, I wondered about 1Password&rsquo;s CLI tool. The few times I saw it mentioned the demos were for secrets management, not retrieval, but I took another look at the docs and it does have some interesting provisions for getting your secrets out of 1Password from the CLI.</p>
<p>Basically, when you use the <kbd>op</kbd> command&rsquo;s <kbd>run</kbd> argument you can tell it to source in some environment variables from a <kbd>.env</kbd> file that uses <kbd>op</kbd>&rsquo;s internal URI scheme to pull credentials out of your vault. An example resource reference looks like this:</p>
<p><kbd>op://Personal/Linkding/password</kbd></p>
<p>If you put that in an <kbd>env</kbd> file with a variable assignment, the <kbd>op</kbd> command can source it and pass it along to a shell command. So:</p>
<p><kbd>op run &ndash;env-file=&quot;$HOME/.env&rdquo;  &ndash; ~/bin/linkding.rb</kbd></p>
<p>&hellip; reads from a file that looks something like this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nv">LINKDING_USER</span><span class="o">=</span><span class="s2">&#34;op://Personal/Linkding/username&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">LINKDING_TOKEN</span><span class="o">=</span><span class="s2">&#34;op://Personal/Linkding/credential&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">FRESHRSS_USER</span><span class="o">=</span><span class="s2">&#34;op://Personal/FreshRSS/username&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">FRESHRSS_PASS</span><span class="o">=</span><span class="s2">&#34;op://Personal/FreshRSS/credential&#34;</span></span></span></code></pre></div>
<p>&hellip; and supplies the <kbd>linkding</kbd> script with a value for this line:</p>
<p><kbd>token = ENV[&lsquo;LINKDING_TOKEN&rsquo;]</kbd></p>
<p>If you&rsquo;re already auth&rsquo;d into 1Password and you&rsquo;ve enabled integration between the CLI tool and the desktop app, then you don&rsquo;t have to do anything. If you need to re-auth your 1Password instance, you&rsquo;ll get a biometric prompt. If you&rsquo;re ssh&rsquo;d into a remote host where you wouldn&rsquo;t get the biometric prompt, you can bypass that by setting <kbd>OP_BIOMETRIC_UNLOCK_ENABLED=false</kbd> but you&rsquo;ll need to explicitly auth the 1Password CLI tool from the command line. It doesn&rsquo;t seem to just fail over to a CLI auth.</p>
<p>So, handled the 1Password way, your <kbd>.env</kbd> file could remain unencrypted, but you&rsquo;d probably be best off aliasing any scripts or commands you run where you want the <kbd>op</kbd> tool to interpolate your <kbd>.env</kbd> file.</p>
<p>It&rsquo;s a little more cumbersome but maybe there&rsquo;s benefit over the long haul from knowing that you just have to keep credentials in 1Password and can reference them elsewhere instead of maintaining an encrypted <kbd>.env</kbd> file. It&rsquo;s also nice to have a biometric prompt or system auth vs. using gpg keys, which require you to have another password on hand (at least until 1Password quits punting on a gpg agent to pair with the ssh one).</p>
<p>For now I&rsquo;ve only got enough stuff connected this way to use 1Password with FreshRSS and my Linkding plugin. Newsboat allows you to set your RSS service&rsquo;s password with output from a shell command, so I&rsquo;ve got that set to:</p>
<p><kbd>freshrss-passwordeval &ldquo;op read op://Personal/FreshRSS/credential&rdquo;</kbd></p>
<p>If I&rsquo;m auth&rsquo;d into 1Password, great: It just runs and sets the credential for NewsBoat. If I&rsquo;m not, great as well: It just runs and tosses up a biometric prompt before proceeding.</p>
<p>I&rsquo;m also using the env file pattern for Newsboat, for my bookmarking command:</p>
<p><kbd>bookmark-cmd &ldquo;op run &ndash;env-file=&quot;$HOME/.env&quot;  &ndash; ~/bin/linkding.rb&rdquo;</kbd></p>
<p>That&rsquo;s because I don&rsquo;t want to write my Linkding plugin to require any particular infrastructure. It just wants an environment variable, which is supplied by wrapping the script in the <kbd>op run</kbd> command with an <kbd>&ndash;env-file</kbd> switch. If someone wants to take the script and use another way to get the variable into their environment, or just decide to take their chances and hard-code it because they&rsquo;re comfortable with that risk, they can. If I ever stop using 1Password I can similarly just figure out a new secrets backend and may be able to avoid rewriting a bunch of utility scripts if I keep using this approach. If I want to use one of my scripts on a host where I don&rsquo;t have 1Password, well, there are other ways.</p>
<p><span class="underline"><span class="underline">Update:</span></span> I wondered about that mutt setup I have and ended up seeing what would happen if I replaced the whole &ldquo;load mutt, source a gpg-encrypted file&rdquo; thing with simple 1Password resource references. It works pretty well. If you&rsquo;re signed into 1Password, it just works. If you&rsquo;re not, you get a biometric prompt:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">imap_user</span><span class="o">=</span><span class="sb">`</span>op <span class="nb">read</span> op://Personal/MuttFastmail/imap_user<span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">smtp_pass</span><span class="o">=</span><span class="sb">`</span>op <span class="nb">read</span> op://Personal/MuttFastmail/smtp_pass<span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">imap_pass</span><span class="o">=</span><span class="sb">`</span>op <span class="nb">read</span> op://Personal/MuttFastmail/imap_pass<span class="sb">`</span></span></span></code></pre></div>
<p>Same caveats as with everything: If I ever end up wanting to use my mutt config on a machine I can&rsquo;t put 1Password on, I&rsquo;d need to go back to my old gpg file pattern.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Daily notes for 2024-01-09 (mutt noodling edition)</title>
      <link>https://mike.puddingtime.org/posts/2024-01-09-daily-notes/</link>
      <pubDate>Tue, 09 Jan 2024 10:41:05 -0800</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2024-01-09-daily-notes/</guid>
      <description>Multi-account, GPG-secure mutt configs. Mutt message scoring with Ruby, and score color-coding.</description>
      <content:encoded><![CDATA[<h2 id="multi-account-gpg-secured-mutt-config">Multi-account, GPG-secured mutt config</h2>
<p>I keep having to reinvent this every few years, and I always stitch it together from assorted sources, mostly because Google sort of shifts around now and then. So:</p>
<ul>
<li>Given a Gmail account with IMAP access turned on</li>
<li>Given a Fastmail account using IMAP</li>
<li>Given mutt, with your configuration in <code>~/.mutt</code> and with <code>muttrc</code> and <code>macros</code> files.</li>
<li>Given a working gpg config you can use to encrypt/decrypt</li>
</ul>
<p>There are all sorts of ways to handle mutt config for assorted providers. The examples here are working right now, in early 2024. They probably have bits of cruft and lint because my config has been a work in progress since some time in the late 20th century.</p>
<h3 id="overview">Overview</h3>
<p>You&rsquo;re making profiles to do this: One for each of your accounts that will hold account specific config information. If you currently have a monolith config in mutt, you can lift a lot of stuff out of it and move it into a profile, then source the profile in your main <code>muttrc</code>.</p>
<p>You&rsquo;re also going to make and encrypt a credential file for each account. Some people do this all in one file and use account hooks to make sure <code>imap_user</code>, <code>imap_password</code> and <code>smtp_password</code> are set correcctly depending on the account you&rsquo;re operating in. I chose to make a file for each account.</p>
<p>You&rsquo;re going to make macros that source the profiles when you want to switch between them.</p>
<h3 id="0-pre-config-with-gmail-and-fastmail">0. Pre-config with Gmail and Fastmail</h3>
<p>I&rsquo;m not going to go into a ton of detail here:</p>
<ul>
<li>Gmail needs to have less secure app access turned on. Find it in your account settings. If you&rsquo;re doing this for a work account, it may be your admin hasn&rsquo;t enabled this. Have fun fighting city hall, in that case.</li>
<li>If you have a GSuite admin, they need to have enabled all IMAP clients, not just OAuth ones.</li>
<li>If you have 2FA turned on with Google, you will need to enable an application password.</li>
</ul>
<p>For Fastmail:</p>
<ul>
<li>You need to have an app password set up for mutt. <code>Settings -&gt; Privacy and Security -&gt; Integrations -&gt; App passwords</code></li>
</ul>
<h3 id="1-the-profile-files">1. The profile files</h3>
<p>Make profile files for each of your accounts. I name them <code>workplace.profile</code>, <code>fastmail.profile</code>, etc. It doesn&rsquo;t matter there&rsquo;s no required convention. It&rsquo;s a good idea to use the first one as the template for the second one.</p>
<p>This is an example of my Fastmail profile. Note line 6:</p>
<p><code>source &quot;gpg -d ~/.mutt/passwords.gpg |&quot;</code></p>
<p>That&rsquo;s where your credentials will come from. I&rsquo;ll show that file next.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># -*- muttrc -*-</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Mutt sender profile : personal/default</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">unset</span> folder
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">smtp_authenticators</span> <span class="o">=</span> <span class="s1">&#39;gssapi:login&#39;</span> <span class="c1"># fastmail needs this</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">imap_authenticators</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">source</span> <span class="s2">&#34;gpg -d ~/.mutt/passwords.gpg |&#34;</span> 
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">spoolfile</span> <span class="o">=</span> <span class="s2">&#34;imaps://imap.fastmail.com&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">folder</span> <span class="o">=</span> <span class="s2">&#34;imaps://imap.fastmail.com/INBOX&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">postponed</span><span class="o">=</span><span class="s2">&#34;+Drafts&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">hostname</span><span class="o">=</span><span class="s2">&#34;yourdomain.com&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">signature</span><span class="o">=</span> <span class="s2">&#34;~/.mutt/personal.sig&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">from</span><span class="o">=</span> <span class="s2">&#34;Bob Jones &lt;bob@yourdomain.com&gt;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">realname</span> <span class="o">=</span> <span class="s2">&#34;Bob Jones&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">smtp_url</span> <span class="o">=</span> <span class="s2">&#34;smtps://bobjones@fastmail.com@smtp.fastmail.com:465&#34;</span> <span class="c1"># use your fastmail username, not your email address</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">imap_user</span> <span class="o">=</span> <span class="s2">&#34;bobjones@fastmail.com&#34;</span> <span class="c1"># use your fastmail username here, too</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># set the status to show which profile I&#39;m using</span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> <span class="nv">status_format</span><span class="o">=</span> <span class="s2">&#34;-%r-Fastmail: %f [Msgs:%?M?%M/?%m%?n? New:%n?%?o? Old:%o?%?d? Del:%d?%?F? Flag:%F?%?t? Tag:%t?%?p? Post:%p?%?b? Inc:%b?%?l? %l?]---(%s/%S)-%&gt;-(%P)---\n&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">unmy_hdr *
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">my_hdr From: Bob Jones &lt;bob@yourdomain.com&gt;
</span></span><span class="line"><span class="cl">my_hdr Organization: yourdomain.com
</span></span><span class="line"><span class="cl">my_hdr Sender: Bob Jones &lt;bob@yourdomain.com&gt;
</span></span><span class="line"><span class="cl">my_hdr Return-Path: &lt;bob@yourdomain.com&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># clear the existing mailboxes list</span>
</span></span><span class="line"><span class="cl">unmailboxes *
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># load up mailboxes appropriate to this profile</span>
</span></span><span class="line"><span class="cl">mailboxes + <span class="s2">&#34;=Spam&#34;</span>
</span></span><span class="line"><span class="cl">mailboxes + <span class="s2">&#34;=disposable&#34;</span>
</span></span><span class="line"><span class="cl">mailboxes + <span class="s2">&#34;=Newsletters&#34;</span>
</span></span><span class="line"><span class="cl">mailboxes + <span class="s2">&#34;=Sent&#34;</span>
</span></span><span class="line"><span class="cl">mailboxes + <span class="s2">&#34;=Archive&#34;</span></span></span></code></pre></div>
<h3 id="2-make-credentials-files">2. Make credentials files</h3>
<p>For each account, you need to make a file for your credentials.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">set imap_user=bob@bobjones.com
</span></span><span class="line"><span class="cl">set imap_pass=&#34;klatu barada nikto&#34;
</span></span><span class="line"><span class="cl">set smtp_pass=&#34;klatu barada nikto&#34;</span></span></code></pre></div>
<p>Name it whatever. <code>passwords-accountname</code> works.</p>
<p>Once you&rsquo;ve created the file, encrypt it with gpg:</p>
<p><code>gpg -r your-gpg-key@yourdomain.com -e passwords-fastmail</code></p>
<p>Test it:</p>
<p><code>gpg -d passwords-fastmail.gpg</code></p>
<p>Then shred the plaintext original:</p>
<p><code>shred -u passwords-fastmail</code></p>
<p>Make sure that your profile (from the previous step) is sourcing the gpg file in line 6 of my example, e.g.</p>
<p><code>source &quot;gpg -d ~/.mutt/passwords-fastmail.gpg |&quot;</code></p>
<h3 id="3-do-a-quick-mid-config-check">3. Do a quick mid-config check</h3>
<p>Might as well test it now.  You can do that by sourcing one of your profiles in your <code>muttrc</code>:</p>
<p><code>source ~/.mutt/fastmail.profile</code></p>
<p>When you run mutt the first time in this login session, you should get a gpg prompt for your credentials so mutt can decrypt your password file and use it to log in.</p>
<p>If it&rsquo;s working, now&rsquo;s the time to make your second profile and credentials files using the above steps since it&rsquo;ll be good to know what they&rsquo;re all called for the next step, which is making macros.</p>
<h3 id="4-make-macros">4. Make macros</h3>
<p>I keep my macros in their own file under <code>~/.mutt</code> just to keep things modular. You can put these in your main <code>muttrc</code>. Whatever you prefer. If you have a separate file, make sure to source it in <code>muttrc</code>:</p>
<p><code>source ~/.mutt/macros</code></p>
<p>Now add something like this for each account:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">macro index .cf &#39;&lt;sync-mailbox&gt;&lt;enter-command&gt;source ~/.mutt/fastmail.profile&lt;enter&gt;&lt;change-folder&gt;!&lt;enter&gt;&#39;
</span></span><span class="line"><span class="cl">macro index .cg &#39;&lt;sync-mailbox&gt;&lt;enter-command&gt;source ~/.mutt/google.profile&lt;enter&gt;&lt;change-folder&gt;!&lt;enter&gt;&#39;</span></span></code></pre></div>
<p>That just does one last sync, then sources your profile, then changes folders to the inbox of that profile.</p>
<p>Restart mutt. From the index, if all is working correctly, the macro <code>.cf</code> will source your <code>fastmail.profile</code> and the macro <code>.cg</code> will source your <code>google.profile</code> file (both of which also source/decrypt their respective credential files).</p>
<h3 id="5-in-conclusion">5. In conclusion</h3>
<p>Once it&rsquo;s all wired up and running, you should be able to switch back and forth between accounts with just a few seconds of latency as the inbox syncs on exit and the new inbox syncs on login.</p>
<h2 id="the-pleasures-of-mutt">The pleasures of mutt</h2>
<p>I went on a mutt revival kick early last year. It remains a land of contrasts. I never end up sticking to it 100 percent of the time but instead prefer to use it as a quick triage tool: It&rsquo;s easy to make macros and keybindings that speed up inbox processing. Sometimes it&rsquo;s easier to just bail out to the web mail interface, but during the day it&rsquo;s helpful to just burn through the inbox never taking my hands off the keyboard.</p>
<h2 id="mutt-scoring-and-color-treatments">mutt scoring and color treatments</h2>
<p>One last thing, I guess, since I&rsquo;m documenting stuff.  One of the reasons I like mutt for triage so much is my ability to add a little visual treatment to messages based on their scores. That makes it easy to see what in my inbox has more priority.</p>
<p>I&rsquo;ve got this little script in my <code>~/.mutt</code>:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="ch">#!/usr/bin/env ruby</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;mail&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;tempfile&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Wants a +/- integer, e.g. +20</span>
</span></span><span class="line"><span class="cl"><span class="n">score</span> <span class="o">=</span> <span class="no">ARGV</span><span class="o">.</span><span class="n">first</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">score_file</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="no">Dir</span><span class="o">.</span><span class="n">home</span><span class="si">}</span><span class="s2">/.mutt/scored&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">msg</span> <span class="o">=</span> <span class="no">Tempfile</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">&#39;msg&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">msg</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="vg">$stdin</span><span class="o">.</span><span class="n">read</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">mail</span> <span class="o">=</span> <span class="no">Mail</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">from</span> <span class="o">=</span> <span class="n">mail</span><span class="o">.</span><span class="n">from</span><span class="o">.</span><span class="n">first</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">score_file</span><span class="p">,</span> <span class="s2">&#34;a&#34;</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span> <span class="n">f</span><span class="o">.</span><span class="n">write</span> <span class="s2">&#34;score ~f</span><span class="si">#{</span><span class="n">from</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">score</span><span class="si">}</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">msg</span><span class="o">.</span><span class="n">close</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">msg</span><span class="o">.</span><span class="n">unlink</span></span></span></code></pre></div>
<p>And I&rsquo;ve got these macros in my <code>~/.mutt/macros</code> file:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Score messages</span>
</span></span><span class="line"><span class="cl">macro index,browser .sp <span class="s2">&#34;&lt;pipe-entry&gt;~/.mutt/mailscore.rb +5\n&lt;enter-command&gt;source ~/.mutt/scored&lt;enter&gt;&#34;</span> <span class="c1"># score sender +5</span>
</span></span><span class="line"><span class="cl">macro index,browser .sP <span class="s2">&#34;&lt;pipe-entry&gt;~/.mutt/mailscore.rb +20\n&lt;enter-command&gt;source ~/.mutt/scored&lt;enter&gt;&#34;</span> <span class="c1"># score sender +20</span>
</span></span><span class="line"><span class="cl">macro index,browser .sm <span class="s2">&#34;&lt;pipe-entry&gt;~/.mutt/mailscore.rb -5\n&lt;enter-command&gt;source ~/.mutt/scored&lt;enter&gt;&#34;</span> <span class="c1"># score sender -5</span>
</span></span><span class="line"><span class="cl">macro index,browser .sM <span class="s2">&#34;&lt;pipe-entry&gt;~/.mutt/mailscore.rb -20\n&lt;enter-command&gt;source ~/.mutt/scored&lt;enter&gt;&#34;</span> <span class="c1"># score sender -20</span></span></span></code></pre></div>
<p>And I&rsquo;ve got a few lines in my <code>~/.mutt/colors</code> file:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">color index cyan default <span class="s2">&#34;~n 0-2 !~p&#34;</span>
</span></span><span class="line"><span class="cl">color index magenta default <span class="s2">&#34;~n &lt;5&#34;</span>
</span></span><span class="line"><span class="cl">color index brightyellow default <span class="s2">&#34;~n &gt;15&#34;</span>
</span></span><span class="line"><span class="cl">color index brightred default <span class="s2">&#34;~n &gt;19&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c1">#</span></span></span></code></pre></div>
<p>The macros pipe a given message into the script, the script extracts the sender, and the script writes a line into my <code>~/.mutt/scored</code> file. Then the <code>~/.mutt/colors</code> file (which you need to source in <code>muttrc</code>) assigns colors to certain scores. I have a few other rules in <code>~/.mutt/scores</code>, as well:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Date-based scoring penalties -- older things fall down</span>
</span></span><span class="line"><span class="cl">score ~d&gt;3d -1
</span></span><span class="line"><span class="cl">score ~d&gt;7d -3
</span></span><span class="line"><span class="cl">score ~d&gt;14d -10
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">score <span class="s2">&#34;~O&#34;</span> +10 <span class="c1"># old = +10 so I don&#39;t miss it</span>
</span></span><span class="line"><span class="cl">score <span class="s2">&#34;~F&#34;</span> +20 <span class="c1"># flagged = +20 so it stays in the interesting view for a while, even if old</span>
</span></span><span class="line"><span class="cl">score <span class="s2">&#34;!~p ~d&gt;7d&#34;</span> -10 <span class="c1"># not for me directly, getting old, let it fade away</span>
</span></span><span class="line"><span class="cl">score <span class="s2">&#34;!~l&#34;</span> +2 <span class="c1"># to a known list, give it a bump</span></span></span></code></pre></div>
]]></content:encoded>
    </item>
    <item>
      <title>Daily Notes for 2023-06-04</title>
      <link>https://mike.puddingtime.org/posts/2023-06-04-daily-notes/</link>
      <pubDate>Sun, 04 Jun 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-06-04-daily-notes/</guid>
      <description>Denote and encrypted notes plus the whole mobile angle.  Hugo preview server and ox-hugo. What happened to V.</description>
      <content:encoded><![CDATA[<h2 id="denote-and-encrypted-notes">Denote and encrypted notes</h2>
<p>I want to have access to my Denote notes via SyncThing on a machine I don&rsquo;t completely control (but is not, to be clear, operating in a hostile environment) and I want them to be encrypted, same as my <code>org-journal</code> files. I should probably just ask Prot, but as near as I can tell the <em>clean</em> way to encrypt notes in Denote is to add an &ldquo;org.gpg&rdquo; type to <code>denote-file-types</code>, like this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;denote-file-types</span>
</span></span><span class="line"><span class="cl">             <span class="o">&#39;</span><span class="p">(</span><span class="nv">org-gpg</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:extension</span> <span class="s">&#34;.org.gpg&#34;</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:date-function</span> <span class="nv">denote-date-org-timestamp</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:front-matter</span> <span class="nv">denote-org-front-matter</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:title-key-regexp</span> <span class="s">&#34;^#\\+title\\s-*:&#34;</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:title-value-function</span> <span class="nf">identity</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:title-value-reverse-function</span> <span class="nv">denote-trim-whitespace</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:keywords-key-regexp</span> <span class="s">&#34;^#\\+filetags\\s-*:&#34;</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:keywords-value-function</span> <span class="nv">denote-format-keywords-for-org-front-matter</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:keywords-value-reverse-function</span> <span class="nv">denote-extract-keywords-from-front-matter</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:link</span> <span class="nv">denote-org-link-format</span>
</span></span><span class="line"><span class="cl">               <span class="nb">:link-in-context-regexp</span> <span class="nv">denote-org-link-in-context-regexp</span><span class="p">))</span></span></span></code></pre></div>
<p>It looks like a lot to do a little, but it&rsquo;s just a clone of the <code>org</code> type that&rsquo;s already in that list, with the extension changed. I suppose one could just alter the <code>org</code> type, but then you don&rsquo;t have an unencrypted type if you want it.</p>
<p>With that in place, you can do:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">denote-file-type</span> <span class="ss">&#39;org-gpg</span><span class="p">)</span></span></span></code></pre></div>
<p>&hellip; and anything you create with the <code>denote</code> command uses that type, with the correct extension. Given the right general config:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;epa-file</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">epa-file-enable</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span> <span class="nv">org-crypt-key</span> <span class="s">&#34;foo@bar.baz&#34;</span><span class="p">)</span></span></span></code></pre></div>
<p>&hellip; it all &ldquo;just works,&rdquo; with decryption handled transparently provided the gpg agent is set up correctly, and I preserve the option to have unencrypted notes for whatever reason I might want them at some point.</p>
<p>To get my existing notes into an encrypted state, I used this script:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/zsh
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">encrypt_file<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">file_path</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">recipient</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$2</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">encrypted_file_path</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">file_path</span><span class="si">}</span><span class="s2">.gpg&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  gpg --encrypt --recipient <span class="s2">&#34;</span><span class="nv">$recipient</span><span class="s2">&#34;</span> --output <span class="s2">&#34;</span><span class="nv">$encrypted_file_path</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$file_path</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;File encrypted: </span><span class="nv">$encrypted_file_path</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">encrypt_files_in_directory<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">directory</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">recipient</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$2</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">for</span> file_path in <span class="s2">&#34;</span><span class="nv">$directory</span><span class="s2">&#34;</span>/*.org<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    encrypt_file <span class="s2">&#34;</span><span class="nv">$file_path</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$recipient</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="k">done</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Usage: ./encrypt_files.sh directory recipient_email</span>
</span></span><span class="line"><span class="cl"><span class="nv">directory</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">recipient_email</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$2</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[[</span> -n <span class="s2">&#34;</span><span class="nv">$directory</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> -n <span class="s2">&#34;</span><span class="nv">$recipient_email</span><span class="s2">&#34;</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">  encrypt_files_in_directory <span class="s2">&#34;</span><span class="nv">$directory</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$recipient_email</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;Usage: ./encrypt_files.sh directory recipient_email&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span></span></span></code></pre></div>
<h2 id="the-mobile-problem">The mobile problem</h2>
<p>The tradeoff with that approach is that your mobile use case gets harder. I can still do something like mosh my way in to the Mac Studio with Tailscale, I guess.</p>
<p>I have the nagging feeling that Emacs-centric note taking wouldn&rsquo;t work great for me if I were dealing with a commute or other scenarios where mobile access is more important. Yes, there are beorg, <a href="https://plainorg.com">Plainorg</a>, and a few other options, but the syncing layer is the complicator. Some people seem to live fine just using git and maybe <a href="https://github.com/ryuslash/git-auto-commit-mode">git-auto-commit</a>, or just generally being more disciplined about their file use. I have generally felt better served by bespoke solutions, like you get with Obsidian, Things, and others. They&rsquo;re still subject to the occasional screwup, but I don&rsquo;t feel like I see them as often as I do with things that simply watch a file system and try to react appropriately.</p>
<p>I have been doing a little personal journaling about my preoccupations with mobile stuff. After tracing things back over the years, I recently realized that a lot of my fixation on getting stuff to work on a phone came from a pretty terrible time during the 2001 downturn.</p>
<p>All my teammates had been laid off and I was holding down a small network of Linux/open source sites that had previously involved a much larger team. If I didn&rsquo;t want things to get out of control I had to keep an eye on them over the weekend. That mentality caused a lot of lines to blur and it took years to unblur them. I was an early iPad enthusiast because I&rsquo;d internalized the idea that I should be able to do all kinds of work from anywhere at any time. Before that, I was really into the netbook thing because I could put an eeePC into a hip bag.</p>
<p>By the time I got to Puppet in 2012, working from home wasn&rsquo;t a novelty or an aspirational goal: I&rsquo;d been doing it for 13 or 14 years and was really glad to have an office to go to. Covid lockdown sparked a pretty bad reaction after the initial &ldquo;let&rsquo;s build a fire and sing songs while we wait for the drop ship&rdquo; phase because lines started blurring again.</p>
<div style="position: relative; width: 100%; padding-bottom: 56.25%;margin-bottom:20px;">
<iframe style="position:absolute; width:100%; height:100%;" src="https://getyarn.io/yarn-clip/1700a3aa-2d58-4411-a8cf-02cea98e8561/embed?autoplay=false&responsive=true"
frameborder="0">
</iframe>
</div>
<p>At the same time, just last week I had a pair of things to do in the afternoon and I&rsquo;d written some thoughts down about one of the events that I wanted to review while I was out of the house. Well &hellip; apparently SyncThing hadn&rsquo;t picked up on the changes before the machine I wrote them on went to sleep, so none of the other machines in the mesh &mdash; including a Synology I put SyncThing on for just these occasions &mdash; knew the notes existed.</p>
<p>At some point, &ldquo;oh, no problem, I&rsquo;ll just Tailscale in to the home network and WoL the Mac Studio so I can wake up SyncThing and then sync my changes down&rdquo; loses all its charm.</p>
<p>Ugh. Need to stop before I talk myself into doing something rash and disruptive.</p>
<h2 id="hugo-previews-while-working-in-ox-hugo">Hugo previews while working in ox-hugo</h2>
<p>I&rsquo;m not sure if there&rsquo;s a better way to do this, but this is working for me:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/start-hugo-server</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Run Hugo server with live reloading and open the server URL in a browser.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let*</span> <span class="p">((</span><span class="nv">root</span> <span class="p">(</span><span class="nv">projectile-project-root</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">default-directory</span> <span class="nv">root</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">compile</span> <span class="s">&#34;hugo server -D --navigateToChanged&#34;</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">run-at-time</span> <span class="s">&#34;3 sec&#34;</span> <span class="no">nil</span> <span class="p">(</span><span class="nb">lambda</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">                              <span class="p">(</span><span class="nv">browse-url</span> <span class="s">&#34;http://localhost:1313&#34;</span><span class="p">)))))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">mph/stop-hugo-server</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Stop Hugo server.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">kill-compilation</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">map!</span> <span class="nb">:leader</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">:prefix</span> <span class="p">(</span><span class="s">&#34;H&#34;</span> <span class="o">.</span> <span class="s">&#34;Hugo&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;Start Hugo Server&#34;</span> <span class="s">&#34;S&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/start-hugo-server</span>
</span></span><span class="line"><span class="cl">       <span class="nb">:desc</span> <span class="s">&#34;Stop Hugo Server&#34;</span> <span class="s">&#34;s&#34;</span> <span class="nf">#&#39;</span><span class="nv">mph/stop-hugo-server</span><span class="p">))</span></span></span></code></pre></div>
<p>I get a little <em>Compiling</em> treatment in the modeline while the preview server is running. My browser reloads any time I save my work.</p>
<h2 id="what-happened-to-v">What happened to V</h2>
<p>I always sort of wondered <a href="https://www.vanityfair.com/hollywood/2023/05/the-v-files-legacy">what happened to V</a> between the miniseries and the regular series. I had a vague sense it had gotten worse, but I was also a teenager and didn&rsquo;t have a lot of critical faculties beyond &ldquo;this seems sort of sucky and boring now.&rdquo; Well, now I know: They got rid of the person who created it, made it cheaper, and tossed out what someone thought were the dumb parts, which were actually the good parts.</p>
<p>Interesting factoid:</p>
<blockquote>
<p>V was watched in more than 33 million homes, which amounted to 40 percent of all TV viewership. (The most popular series in America today, Yellowstone, averages 13.1 million viewers per episode.)</p>
</blockquote>
<p>I recently tried to dig up what&rsquo;s considered &ldquo;good numbers&rdquo; in the streaming era and didn&rsquo;t get many satisfying answers. Seeing that a modern phenomenon like <em>Yellowstone</em> pulls about 40 percent of V&rsquo;s numbers is helpful. <em>V</em> was hyped all to hell at the time, so its &ldquo;television special event&rdquo; status probably skews things a little. (The <em>M*A*S*H</em> finale did 105.97 million total viewers, and that record may be impossible to break as streaming-driven atomization deepens.)</p>
<h2 id="the-phony-solidarity-of-the-american-pundit-class">&ldquo;The Phony Solidarity of the American Pundit Class&rdquo;</h2>
<p>I got to <a href="https://www.thenation.com/article/society/jordan-neely-pundits/">this post in The Nation</a> after it sat on the read later pile for a while.</p>
<p>It&rsquo;s very strange to see the post-2016 realignments continuing apace. This particular link targets the slice of the center-left-to-center-right commentariat that has learned to talk about &ldquo;working people.&rdquo;  That tic &mdash; the &ldquo;won&rsquo;t somebody think of the working people&rdquo; tic &mdash; feels symptomatic of a kind of <a href="/posts/2022-06-20-elite-capturehttpsmicroblogbooks-by/">elite capture</a> all its own.</p>
<p>I wrote a few years ago:</p>
<blockquote>
<p>&ldquo;I have a lot of time for some heterodox thinkers. I wish &lsquo;heterodox&rsquo; was narrow-able to something less broad than &lsquo;a coalition of middle class trolls, rebadged culture warriors, people who hate how much they get ratioed, and well-meaning independent thinkers.&rsquo;&rdquo;</p>
</blockquote>
<p>I think I may need to retract that. I was going through the podcast searching for an episode and saw a few descriptions here and there that tell me &ldquo;heterodox&rdquo; has stopped being a word one lands on after casting about for a better one, and has become a sort of branding exercise.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
