<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>stephencox.net</title>
  <subtitle>A digital garden of interconnected thoughts, projects, and writings.</subtitle>
  <link href="https://stephencox.net/feed.xml" rel="self" />
  <link href="https://stephencox.net/" />
  <updated>2026-07-29T00:00:00Z</updated>
  <id>https://stephencox.net/</id>
  <author>
    <name>Stephen Cox</name>
  </author>
  <entry>
    <title>Lando lndo.site DNS resolution failure on Virgin Media</title>
    <link href="https://stephencox.net/notes/tech/lando-lndo.site-dns-resolution-failure-on-virgin-media/" />
    <updated>2026-07-29T00:00:00Z</updated>
    <published>2026-07-29T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/lando-lndo.site-dns-resolution-failure-on-virgin-media/</id>
    <summary>Virgin Media&#39;s router silently drops DNS responses pointing at 127.0.0.1, breaking *.lndo.site. Fixed with DNS-over-TLS via systemd-resolved.</summary>
    <content type="html">&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;*.lndo.site&lt;/code&gt; sites wouldn&#39;t resolve. Lando publishes a real public wildcard DNS record for &lt;code&gt;*.lndo.site&lt;/code&gt; pointing at &lt;code&gt;127.0.0.1&lt;/code&gt;, so this normally needs no local setup at all.&lt;/p&gt;
&lt;p&gt;Queries &lt;strong&gt;timed out&lt;/strong&gt; rather than returning NXDOMAIN, and did so against every resolver — including &lt;code&gt;1.1.1.1&lt;/code&gt; and &lt;code&gt;8.8.8.8&lt;/code&gt; directly.&lt;/p&gt;
&lt;h2&gt;Diagnosis&lt;/h2&gt;
&lt;p&gt;The give-away was that only &lt;em&gt;loopback-valued&lt;/em&gt; answers failed:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Query&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dig google.com @1.1.1.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;public IPs&lt;/td&gt;
&lt;td&gt;works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dig lndo.site @1.1.1.1&lt;/code&gt; (apex)&lt;/td&gt;
&lt;td&gt;public IPs&lt;/td&gt;
&lt;td&gt;works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dig SOA lndo.site @198.51.44.2&lt;/code&gt; (authoritative)&lt;/td&gt;
&lt;td&gt;public data&lt;/td&gt;
&lt;td&gt;works, &lt;code&gt;aa&lt;/code&gt; flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dig test.lndo.site&lt;/code&gt; @ any resolver&lt;/td&gt;
&lt;td&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;timeout&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dig 127-0-0-1.sslip.io @1.1.1.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;timeout&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test.lndo.site&lt;/code&gt; over DoH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;works&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Same server, same zone — only responses containing &lt;code&gt;127.0.0.1&lt;/code&gt; vanished. That is the Virgin Media Hub&#39;s &lt;strong&gt;DNS rebind protection&lt;/strong&gt;, implemented as a silent packet drop rather than a rewrite. Hence the timeout instead of an error.&lt;/p&gt;
&lt;p&gt;Confirming with DNS-over-HTTPS, which the Hub can&#39;t inspect:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://cloudflare-dns.com/dns-query?name=test.lndo.site&amp;amp;type=A&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;accept: application/dns-json&#39;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# -&amp;gt; &quot;data&quot;: &quot;127.0.0.1&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that switching upstream resolver does &lt;strong&gt;not&lt;/strong&gt; help — the interference is on the local path, so it&#39;s the encryption that matters, not the server.&lt;/p&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;Encrypted DNS via systemd-resolved. One drop-in file, no extra daemon:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; /etc/systemd/resolved.conf.d
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tee&lt;/span&gt; /etc/systemd/resolved.conf.d/90-dot.conf &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;EOF&#39;
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com
FallbackDNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net
DNSOverTLS=yes
Domains=~.
EOF&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; systemctl restart systemd-resolved&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Domains=~.&lt;/code&gt; is essential — without it the DHCP-supplied Virgin resolvers still win for most queries. Ubuntu doesn&#39;t ship &lt;code&gt;resolved.conf.d&lt;/code&gt;, hence the &lt;code&gt;mkdir -p&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Verify:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;resolvectl query test.lndo.site   &lt;span class=&quot;token comment&quot;&gt;# -&amp;gt; 127.0.0.1, &quot;encrypted transport: yes&quot;&lt;/span&gt;
resolvectl status &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;DNSOverTLS|Current DNS&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Per-link entries still listing &lt;code&gt;194.168.4.100&lt;/code&gt; are harmless; &lt;code&gt;Domains=~.&lt;/code&gt; means they go unused.&lt;/p&gt;
&lt;h3&gt;Caveats&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DNSOverTLS=yes&lt;/code&gt; is &lt;strong&gt;strict&lt;/strong&gt;: on a network blocking port 853 (some hotel/corporate wifi) DNS fails outright rather than falling back to droppable plaintext.&lt;/li&gt;
&lt;li&gt;Still requires internet, since &lt;code&gt;*.lndo.site&lt;/code&gt; is an internet-hosted record.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Offline / network-independent alternative&lt;/h2&gt;
&lt;p&gt;Answer the zone locally with dnsmasq, but scope it through resolved rather than replacing the system resolver — this avoids the usual port-53 conflicts:&lt;/p&gt;
&lt;pre class=&quot;language-ini&quot; tabindex=&quot;0&quot; data-language=&quot;ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# /etc/dnsmasq.d/lando.conf&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;listen-address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;127.0.0.54&lt;/span&gt;
bind-interfaces
no-resolv
&lt;span class=&quot;token key attr-name&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;/lndo.site/127.0.0.1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-ini&quot; tabindex=&quot;0&quot; data-language=&quot;ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# /etc/systemd/resolved.conf.d/lando.conf&lt;/span&gt;
&lt;span class=&quot;token section&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;Resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;DNS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;127.0.0.54&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;~lndo.site&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;~lndo.site&lt;/code&gt; is routing-only, so just that zone goes to dnsmasq and everything else keeps using DoT. The query never leaves the machine, so the Hub is bypassed entirely and it works offline.&lt;/p&gt;
&lt;p&gt;For a handful of sites, plain &lt;code&gt;/etc/hosts&lt;/code&gt; entries also work (no wildcards) — &lt;code&gt;lando info&lt;/code&gt; lists the hostnames.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Snaps fail silently on Ubuntu 26.04</title>
    <link href="https://stephencox.net/notes/tech/snaps-fail-silently-on-ubuntu-26.04/" />
    <updated>2026-07-29T00:00:00Z</updated>
    <published>2026-07-29T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/snaps-fail-silently-on-ubuntu-26.04/</id>
    <summary>Ubuntu 26.04 switched to uutils coreutils, whose `head -c0 &lt;dir&gt;` exits 1 and silently kills the launcher script bundled in many desktop snaps.</summary>
    <content type="html">&lt;h2&gt;Symptom&lt;/h2&gt;
&lt;p&gt;A desktop snap does nothing when launched — no window, no error, nothing in the app&#39;s own logs. Syslog only shows the scope starting:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;systemd[19581]: Started snap.kontena-lens.kontena-lens-c30c21da….scope
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exits with code 1 in ~0.2s. Hit this with &lt;strong&gt;kontena-lens&lt;/strong&gt; (Lens) and &lt;strong&gt;Obsidian&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Cause&lt;/h2&gt;
&lt;p&gt;Ubuntu 26.04 replaced GNU coreutils with &lt;strong&gt;uutils (Rust) coreutils&lt;/strong&gt; as &lt;code&gt;/usr/bin/head&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Many snaps bundle an old (2019) &lt;code&gt;desktop-common.sh&lt;/code&gt; launcher that tests directories with:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function-name function&quot;&gt;can_open_file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c0&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;gt;&lt;/span&gt; /dev/null&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;GNU &lt;code&gt;head -c0 &amp;lt;dir&amp;gt;&lt;/code&gt; → exits &lt;strong&gt;0&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;uutils &lt;code&gt;head -c0 &amp;lt;dir&amp;gt;&lt;/code&gt; → exits &lt;strong&gt;1&lt;/strong&gt; (&lt;code&gt;error reading &#39;...&#39;: Is a directory&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every XDG directory test now fails, so the script sets &lt;code&gt;needs_xdg_links=true&lt;/code&gt; and runs its link-repair loop. In a &lt;strong&gt;classic&lt;/strong&gt; snap &lt;code&gt;$HOME == $REALHOME&lt;/code&gt;, so that loop runs &lt;code&gt;rmdir ~/Documents&lt;/code&gt; against the real home. It fails, stderr goes to &lt;code&gt;/dev/null&lt;/code&gt;, and &lt;code&gt;#!/bin/bash -e&lt;/code&gt; kills the launcher &lt;strong&gt;before Electron ever starts&lt;/strong&gt; — hence no app logs.&lt;/p&gt;
&lt;h2&gt;Fix&lt;/h2&gt;
&lt;p&gt;Prepend the real GNU &lt;code&gt;head&lt;/code&gt; (already present as &lt;code&gt;/usr/bin/gnuhead&lt;/code&gt; from the &lt;code&gt;gnu-coreutils&lt;/code&gt; package) to &lt;code&gt;PATH&lt;/code&gt; for the snap.&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# GNU head shim&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; ~/.local/share/snap-gnu-compat
&lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-sfn&lt;/span&gt; /usr/bin/gnuhead ~/.local/share/snap-gnu-compat/head

&lt;span class=&quot;token comment&quot;&gt;# Wrapper (~/.local/bin precedes /snap/bin in PATH)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; ~/.local/bin/kontena-lens &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;EOF&#39;
#!/bin/sh
PATH=&quot;$HOME/.local/share/snap-gnu-compat:$PATH&quot;; export PATH
exec /snap/bin/kontena-lens &quot;$@&quot;
EOF&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x ~/.local/bin/kontena-lens

&lt;span class=&quot;token comment&quot;&gt;# Desktop icon override&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;s#^Exec=/snap/bin/kontena-lens#Exec=&#39;&lt;/span&gt;&quot;&lt;span class=&quot;token environment constant&quot;&gt;$HOME&lt;/span&gt;&quot;&lt;span class=&quot;token string&quot;&gt;&#39;/.local/bin/kontena-lens#&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  /var/lib/snapd/desktop/applications/kontena-lens_kontena-lens.desktop &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; ~/.local/share/applications/kontena-lens_kontena-lens.desktop&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AppImage / .deb instead of the snap&lt;/strong&gt; — what I did for Obsidian, and the least fuss.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make GNU coreutils the system-wide default&lt;/strong&gt; again rather than per-app wrappers. Fixes every affected snap at once, but more invasive.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Diagnosis tips&lt;/h2&gt;
&lt;p&gt;The wrapper &lt;code&gt;exec&lt;/code&gt;s between scripts, so &lt;code&gt;bash -x&lt;/code&gt; gets lost. Inherit xtrace through the whole chain via the environment:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;snap run &lt;span class=&quot;token parameter variable&quot;&gt;--shell&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;snap&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;env SHELLOPTS=xtrace bash &quot;$SNAP/desktop-init.sh&quot; &#92;
  &quot;$SNAP/desktop-common.sh&quot; &quot;$SNAP/desktop-gnome-specific.sh&quot; /bin/true&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;SNAPD_DEBUG=1 SNAP_CONFINE_DEBUG=1&lt;/code&gt; confirms whether confinement setup succeeded, i.e. whether the failure is snapd&#39;s or the app&#39;s.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!warning] Don&#39;t trace the launcher with &lt;code&gt;HOME&lt;/code&gt; set to the real home
The link loop then runs &lt;code&gt;ln -s $REALHOME/Templates $HOME/Templates&lt;/code&gt; with both equal, creating &lt;strong&gt;self-referential symlinks&lt;/strong&gt; for &lt;code&gt;~/Templates&lt;/code&gt; and &lt;code&gt;~/Public&lt;/code&gt;. &lt;code&gt;xdg-user-dirs-update&lt;/code&gt; then rewrites &lt;code&gt;~/.config/user-dirs.dirs&lt;/code&gt; to &lt;code&gt;XDG_TEMPLATES_DIR=&amp;quot;$HOME/&amp;quot;&lt;/code&gt;, which resolves to &lt;code&gt;.&lt;/code&gt; — so a later run attempts &lt;code&gt;rmdir ~/.&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
  </entry>
  <entry>
    <title>install-obsidian.sh</title>
    <link href="https://stephencox.net/notes/tech/install-obsidian.sh/" />
    <updated>2026-07-28T00:00:00Z</updated>
    <published>2025-04-11T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/install-obsidian.sh/</id>
    <summary>Script to install and update Obsidian in Gnome</summary>
    <content type="html">&lt;p&gt;Script to install and update Obsidian in Gnome.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Install / update Obsidian.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;##&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;icon_url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;data:image/octet-stream;base64,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&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;download_url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; --no-progress-meter  https://api.github.com/repos/obsidianmd/obsidian-releases/releases/latest  &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
	&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;browser_download_url.*AppImage&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cut&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&quot;&#39;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Downloading Obsidian&quot;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; --no-progress-meter &lt;span class=&quot;token parameter variable&quot;&gt;--location&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; /tmp/Obsidian.AppImage &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$download_url&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; /opt/obsidian/Obsidian.AppImage &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;

  &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Updating Obsidian&quot;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; /opt/obsidian/Obsidian.AppImage
  &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; /tmp/Obsidian.AppImage /opt/obsidian
  &lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; u+x /opt/obsidian/Obsidian.AppImage

&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;

  &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Installing Obsidian&quot;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--parents&lt;/span&gt; /opt/obsidian/
  &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;chown&lt;/span&gt; &lt;span class=&quot;token environment constant&quot;&gt;$USER&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token environment constant&quot;&gt;$USER&lt;/span&gt; /opt/obsidian/
  &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; /tmp/Obsidian.AppImage /opt/obsidian
  &lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; u+x /opt/obsidian/Obsidian.AppImage
  &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; libfuse2

  &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; --no-progress-meter &lt;span class=&quot;token parameter variable&quot;&gt;--location&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; /tmp/obsidian.png &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$icon_url&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; /tmp/obsidian.png /opt/obsidian
  &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; /opt/obsidian/obsidian.png /usr/share/pixmaps
  &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;[Desktop Entry]
Type=Application
Name=Obsidian
Exec=/opt/obsidian/Obsidian.AppImage --no-sandbox
Icon=obsidian
Terminal=false&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; ~/.local/share/applications/obsidian.desktop
  update-desktop-database ~/.local/share/applications

&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W15]]&lt;/li&gt;
&lt;li&gt;Adapted from https://forum.obsidian.md/t/gnome-desktop-installer/499&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Managing journal log size</title>
    <link href="https://stephencox.net/notes/tech/managing-journal-log-size/" />
    <updated>2026-06-30T00:00:00Z</updated>
    <published>2025-07-24T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/managing-journal-log-size/</id>
    <summary>Using journalctl vacuum commands to manage systemd journal log size by time or disk space.</summary>
    <content type="html">&lt;p&gt;Retain only the past two days:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;journalctl --vacuum-time&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;2d&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Retain only the past 500 MB:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;journalctl --vacuum-size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;500M&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W30]]&lt;/li&gt;
&lt;li&gt;https://unix.stackexchange.com/questions/139513/how-to-clear-journalctl&lt;/li&gt;
&lt;li&gt;https://www.loggly.com/ultimate-guide/managing-journal-size/&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Upgrading Moodle</title>
    <link href="https://stephencox.net/notes/tech/upgrading-moodle/" />
    <updated>2026-06-23T00:00:00Z</updated>
    <published>2026-02-19T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/upgrading-moodle/</id>
    <summary>Command-line workflow for upgrading Moodle including maintenance mode, git checkout, and database updates.</summary>
    <content type="html">&lt;p&gt;Security updates are announced on: https://moodle.org/mod/forum/view.php?f=996&lt;/p&gt;
&lt;p&gt;Check release notes: https://moodledev.io/general/releases&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--oneline&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-1&lt;/span&gt; public/version.php
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; digitalbricks &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; fetch origin
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; www-data /usr/bin/php admin/cli/maintenance.php &lt;span class=&quot;token parameter variable&quot;&gt;--enable&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; digitalbricks &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout v5.1.3
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; digitalbricks &lt;span class=&quot;token function&quot;&gt;composer&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --no-dev --classmap-authoritative
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; www-data /usr/bin/php admin/cli/upgrade.php
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; www-data /usr/bin/php admin/cli/maintenance.php &lt;span class=&quot;token parameter variable&quot;&gt;--disable&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2026-W08]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Interesting AI stuff</title>
    <link href="https://stephencox.net/notes/tech/interesting-ai-stuff/" />
    <updated>2026-06-23T00:00:00Z</updated>
    <published>2026-04-16T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/interesting-ai-stuff/</id>
    <summary>Links to interesting AI stuff I&#39;ve found</summary>
    <content type="html">&lt;h2&gt;AI sandboxing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://jai.scs.stanford.edu/&quot;&gt;https://jai.scs.stanford.edu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;https://code.claude.com/docs/en/sandboxing&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Personal agent&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://hermes-agent.nousresearch.com/&lt;/li&gt;
&lt;li&gt;https://lushbinary.com/blog/hermes-agent-gemma-4-qwen-3-5-local-ai-guide/&lt;/li&gt;
&lt;li&gt;https://github.com/QuixiAI/Hexis/&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Drupal skills&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://github.com/grasmash/drupal-claude-skills&lt;/li&gt;
&lt;li&gt;https://github.com/ivangrynenko/cursorrules&lt;/li&gt;
&lt;li&gt;https://github.com/Omedia/drupal-skill&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2026-W16]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Drupal 8+ example settings.local.php file</title>
    <link href="https://stephencox.net/notes/tech/drupal-8-example-settings.local.php-file/" />
    <updated>2026-06-19T00:00:00Z</updated>
    <published>2025-05-22T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/drupal-8-example-settings.local.php-file/</id>
    <summary>Example local development settings file for Drupal 8+ with database config, reverse proxy, and dev-specific options.</summary>
    <content type="html">&lt;pre class=&quot;language-php&quot; tabindex=&quot;0&quot; data-language=&quot;php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$databases&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;default&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;default&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;database&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;username&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;password&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;host&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;localhost&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;port&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;driver&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;mysql&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;prefix&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;collation&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;utf8mb4_general_ci&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;init_commands&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;isolation_level&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;file_private_path&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;../../private_files&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;trusted_host_patterns&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;^(.*&#92;.)?example&#92;.coop$&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;reverse_proxy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;reverse_proxy_addresses&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;127.0.0.1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTPS&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;on&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTP_X_FORWARDED_PROTO&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;$_SERVER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTPS&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;on&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;$_SERVER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;SERVER_PORT&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;state_cache&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;config_split.config_split.production&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;status&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Dev site settings.
 */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Stage file proxy settins.
 */&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;stage_file_proxy.settings&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;origin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://example.coop&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Show all error messages, with backtrace information.
 *
 * In case the error level could not be fetched from the database, as for
 * example the database connection failed, we rely only on this value.
 */&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;system.logging&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;error_level&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;verbose&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Disable CSS and JS aggregation.
 */&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;system.performance&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;css&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;preprocess&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;system.performance&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;preprocess&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Error reporting.
 *
 * As a developer it is useful to see all errors. If the site you are working
 * on has a lot of notice errors and you aren&#39;t able to fix them you can
 * suppress them by modifying E_ALL in error_reporting to:
 * E_ALL &amp;amp; ~E_NOTICE &amp;amp; ~E_STRICT &amp;amp; ~E_DEPRECATED
 */&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;error_reporting&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;E_ALL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;ini_set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;display_errors&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;ini_set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;display_startup_errors&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Limit Watchdog entries.
 */&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;dblog.settings&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;row_limit&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W21]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Drupal .htaccess</title>
    <link href="https://stephencox.net/notes/tech/drupal-.htaccess/" />
    <updated>2026-06-18T00:00:00Z</updated>
    <published>2025-05-22T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/drupal-.htaccess/</id>
    <summary>Apache .htaccess configuration snippets for Drupal including HTTPS redirects and canonical domain setup.</summary>
    <content type="html">&lt;h2&gt;Redirect the HTTPS&lt;/h2&gt;
&lt;pre class=&quot;language-htaccess&quot; tabindex=&quot;0&quot; data-language=&quot;htaccess&quot;&gt;&lt;code class=&quot;language-htaccess&quot;&gt;  # Redirect HTTP to HTTPS
  RewriteCond %{HTTPS} off
  RewriteCond %{HTTP:X-Forwarded-Proto} !https
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Redirect to canonical URL&lt;/h2&gt;
&lt;pre class=&quot;language-htaccess&quot; tabindex=&quot;0&quot; data-language=&quot;htaccess&quot;&gt;&lt;code class=&quot;language-htaccess&quot;&gt;  # Redirect to canonical domain
  RewriteCond %{HTTP_HOST} .
  RewriteCond %{HTTP_HOST} !^www&#92;.example&#92;.coop$ [NC]
  RewriteRule ^ https://www.example.coop%{REQUEST_URI} [L,R=301]&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Deny autodiscovery requests&lt;/h2&gt;
&lt;pre class=&quot;language-htaccess&quot; tabindex=&quot;0&quot; data-language=&quot;htaccess&quot;&gt;&lt;code class=&quot;language-htaccess&quot;&gt;  # 404 Outlook autodiscover requests
  RewriteCond %{REQUEST_URI} /autodiscover/autodiscover.xml [NC]
  RewriteRule ^ - [L,R=404]&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W21]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Apache process tuning</title>
    <link href="https://stephencox.net/notes/tech/apache-process-tuning/" />
    <updated>2026-06-04T00:00:00Z</updated>
    <published>2025-11-19T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/apache-process-tuning/</id>
    <summary>Shell commands to calculate Apache process memory usage and average memory consumption per process.</summary>
    <content type="html">&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt; aux &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;apache2&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{print $6/1024 &quot; MB&quot;;}&#39;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt; aux &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;apache2&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{print $6/1024;}&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{avg += ($1 - avg) / NR;} END {print avg &quot; MB&quot;;}&#39;&lt;/span&gt;                                                 &lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W47]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Remove old home directories</title>
    <link href="https://stephencox.net/notes/tech/remove-old-home-directories/" />
    <updated>2026-05-29T00:00:00Z</updated>
    <published>2025-10-07T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/remove-old-home-directories/</id>
    <summary>Remove home directories of previously deleted users.</summary>
    <content type="html">&lt;p&gt;Find home directories of deleted users&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; /home &lt;span class=&quot;token parameter variable&quot;&gt;-mindepth&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-maxdepth&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; d &lt;span class=&quot;token parameter variable&quot;&gt;-nouser&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Delete old home directories&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; /home &lt;span class=&quot;token parameter variable&quot;&gt;-mindepth&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-maxdepth&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; d &lt;span class=&quot;token parameter variable&quot;&gt;-nouser&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-fr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W41]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>VulnFeed – Aggregated security RSS feed</title>
    <link href="https://stephencox.net/projects/vulnfeed-aggregated-security-rss-feed/" />
    <updated>2026-04-24T00:00:00Z</updated>
    <published>2026-04-14T00:00:00Z</published>
    <id>https://stephencox.net/projects/vulnfeed-aggregated-security-rss-feed/</id>
    <summary>RSS feed for security alerts, pulled for various sources and aggregated into single feed to make it easy to see alerts for the software you care about.</summary>
    <content type="html">&lt;p&gt;A simple app that uses GitHub Actions to scan a configurable list of sources of security advisories and publishes them as an RSS feed.&lt;/p&gt;
&lt;p&gt;VulnFeed aggregates GitHub Security Advisories from a user-defined list of repositories into a single RSS feed. It operates by using a Python script to fetch advisories via the GitHub API, deduplicate the results, and generate a structured XML feed. The process is automated using GitHub Actions, which runs the pipeline daily to ensure the feed stays up to date with the latest security alerts.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/stephen-cox/vulnfeed&quot;&gt;https://github.com/stephen-cox/vulnfeed&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2026-W16]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Guide to AI assisted development</title>
    <link href="https://stephencox.net/writing/guide-to-ai-assisted-development/" />
    <updated>2026-04-24T00:00:00Z</updated>
    <published>2026-01-27T00:00:00Z</published>
    <id>https://stephencox.net/writing/guide-to-ai-assisted-development/</id>
    <summary>AI coding assistants boost speed, but require structured workflows. Learn how to use AI safely with atomic tasks, verification &amp; human review.</summary>
    <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;AI coding assistants behave like overly enthusiastic junior developers: fast, broadly knowledgeable, and responsive, but lacking deep understanding of the specific project they are working on. They generate plausible code quickly, but without clear constraints they are likely to introduce bugs, make unnecessary changes, overlook edge cases and misinterpret requirements. Their speed is an advantage only if it is controlled.&lt;/p&gt;
&lt;p&gt;This guide outlines one method for using AI assistants effectively: the Explore – Plan – Code – Verify workflow. The workflow ensures that speed does not come at the cost of quality by breaking work into atomic tasks, each with clear acceptance criteria, a definition of done and verification steps. The core principle is simple: all changes must be reviewed and tested by a human.&lt;/p&gt;
&lt;h2&gt;Failure modes: why a workflow is required&lt;/h2&gt;
&lt;p&gt;AI coding assistants produce plausible-looking code quickly, but their output often contains subtle flaws. These include hallucinated functions, incorrect configuration or outdated APIs. They may also introduce scope creep (unrelated refactors, formatting changes, or dependency additions) that distract from the task’s core objective. Even when the code appears correct, it may overlook edge cases or non-functional requirements leading to failures in production.&lt;/p&gt;
&lt;p&gt;Tests generated by AI can be equally problematic. They may pass while asserting the wrong behaviour or cover only the happy path, leaving critical failure modes untested. Another common issue is the bug-fixing loop: repeated iterations of small patches without new information or a change in approach, resulting in wasted effort and increasingly convoluted code. These failures are not random; they follow predictable patterns.&lt;/p&gt;
&lt;p&gt;A workflow is required to mitigate these risks. Without one, the assistant’s speed becomes a liability, introducing errors faster than they can be caught. By imposing structure, such as breaking work into verifiable tasks and enforcing explicit checks, developers can harness the assistant&#39;s speed while maintaining control over quality. The goal is to catch errors early, before they propagate through the codebase.&lt;/p&gt;
&lt;h2&gt;The Explore – Plan – Code – Verify workflow&lt;/h2&gt;
&lt;p&gt;The Explore – Plan – Code – Verify workflow provides a structured approach to AI-assisted development, ensuring that speed and quality are balanced. Each phase serves a distinct purpose and produces specific outputs, creating a repeatable process for delivering reliable changes.&lt;/p&gt;
&lt;pre class=&quot;language-mermaid&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code class=&quot;language-mermaid&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;flowchart&lt;/span&gt; TB
    A&lt;span class=&quot;token text string&quot;&gt;([&quot;Bug, feature or project&quot;])&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; B&lt;span class=&quot;token text string&quot;&gt;[&quot;**Explore**&quot;]&lt;/span&gt;
    B &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; C&lt;span class=&quot;token text string&quot;&gt;[&quot;Accepted solution&quot;]&lt;/span&gt;
    C &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; D&lt;span class=&quot;token text string&quot;&gt;[&quot;**Plan**&quot;]&lt;/span&gt;
    D &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; E1[&quot;Phase breakdown
    &lt;span class=&quot;token text string&quot;&gt;(for larger pieces of work)&lt;/span&gt;&quot;]
    E1 &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; E2[&quot;Task specification
    &lt;span class=&quot;token text string&quot;&gt;(for current phase)&lt;/span&gt;&quot;]
    E2 &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; F&lt;span class=&quot;token text string&quot;&gt;[&quot;**Code**&quot;]&lt;/span&gt;
    F &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; G&lt;span class=&quot;token text string&quot;&gt;[&quot;Code changes&quot;]&lt;/span&gt;
    G &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; H&lt;span class=&quot;token text string&quot;&gt;[&quot;**Verify**&quot;]&lt;/span&gt;
    H &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; I&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&quot;Acceptance 
    criteria met?&quot;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    I &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;No&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; F
    I &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;Yes&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; J&lt;span class=&quot;token text string&quot;&gt;[&quot;Commit changes&quot;]&lt;/span&gt;
    J &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; K&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&quot;Are there 
    more tasks?&quot;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    K &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;No&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; L&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&quot;Are there 
    more phases?&quot;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    K &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;Yes&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; F
    L &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;No&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; M&lt;span class=&quot;token text string&quot;&gt;([&quot;Complete&quot;])&lt;/span&gt;
    L &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;Yes&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; D

    C@&lt;span class=&quot;token text string&quot;&gt;{ shape: lean-r}&lt;/span&gt;
    E1@&lt;span class=&quot;token text string&quot;&gt;{ shape: lean-r}&lt;/span&gt;
    E2@&lt;span class=&quot;token text string&quot;&gt;{ shape: lean-r}&lt;/span&gt;
    G@&lt;span class=&quot;token text string&quot;&gt;{ shape: lean-r}&lt;/span&gt;
    J@&lt;span class=&quot;token text string&quot;&gt;{ shape: trap-t}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Explore: reduce ambiguity and confirm constraints&lt;/h2&gt;
&lt;p&gt;The Explore phase is about eliminating uncertainty before writing code. It begins with gathering inputs: the problem statement, expected behavior, constraints (such as versions, environments, or deployment requirements), and relevant code paths. These inputs form the foundation for clarifying the task and identifying potential risks. The goal is to answer critical questions upfront: What does success look like? What are the non-negotiable constraints? Which parts of the codebase are affected?&lt;/p&gt;
&lt;p&gt;The output of this phase is a set of clarified requirements, options, and trade-offs. It should also highlight unknowns that require confirmation, such as unclear specifications or dependencies. The aim is minimal-change thinking: prefer the smallest correct intervention that achieves the goal. This reduces complexity and limits the surface area for errors.&lt;/p&gt;
&lt;p&gt;Explore is not about designing the solution in detail. Instead, it ensures that the problem is well-defined and that the constraints are understood. This phase prevents wasted effort by catching ambiguities early, before they lead to incorrect or overly broad implementations. The result is a focused, actionable task that can be planned and executed with confidence.&lt;/p&gt;
&lt;h2&gt;Plan: atomic tasks with acceptance criteria and definition of done&lt;/h2&gt;
&lt;p&gt;Planning in AI-assisted development means breaking work into atomic tasks: small, independently verifiable units that can be reviewed, tested, and reverted without side effects. An atomic task is operationally defined by three properties: it must be small enough to review confidently, independently verifiable, and revertible without disrupting other work. This granularity ensures that the assistant’s output remains focused and manageable.&lt;/p&gt;
&lt;p&gt;Each task should follow a structured format to eliminate ambiguity:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scope and non-goals: What the task includes and, critically, what it excludes. This prevents scope creep by explicitly ruling out unrelated changes.&lt;/li&gt;
&lt;li&gt;Acceptance criteria: Clear, testable conditions that define success. These should cover functional requirements, edge cases, and non-functional constraints.&lt;/li&gt;
&lt;li&gt;Definition of done: A checklist of completion requirements, such as code reviews, test coverage, and documentation updates.&lt;/li&gt;
&lt;li&gt;Automated tests: Specific tests to add or update, including unit, integration, or regression tests.&lt;/li&gt;
&lt;li&gt;Manual test steps: Step-by-step instructions for validating behavior that cannot be automated, such as UI interactions or cross-browser compatibility.&lt;/li&gt;
&lt;li&gt;Rollback note: How to revert the change if something goes wrong, including any database migrations or configuration updates.&lt;/li&gt;
&lt;li&gt;Risk level: An assessment of the task’s complexity and potential impact, which determines the rigor of verification.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Planning depth should match the task’s proximity to execution. The next milestone should be fully detailed, while later milestones can remain coarse, aligning with agile principles. Guardrails are essential: maintain a &amp;quot;do not touch&amp;quot; list to avoid drive-by refactors, limit dependency additions, and explicitly avoid unrelated changes. This discipline ensures that the assistant’s speed is directed toward meaningful work, not distractions. The result is a clear, actionable plan that minimizes risk while maximizing efficiency.&lt;/p&gt;
&lt;h2&gt;Code: implement the task, but supervise the assistant&lt;/h2&gt;
&lt;p&gt;The Code phase is where the planned task is implemented, but the assistant’s output must be actively supervised. The goal is to execute the task as defined, without introducing unnecessary changes or deviations. Start by providing the assistant with the task brief, including scope, constraints, and relevant code paths. This context ensures that the generated code aligns with the plan and avoids common pitfalls like hallucinated APIs or incorrect assumptions.&lt;/p&gt;
&lt;p&gt;Supervise the output for scope creep. The assistant may suggest unrelated refactors, broad renames, or style changes that are not part of the task. Reject these additions unless they are explicitly required. Similarly, watch for bug-fixing loops: if the assistant produces repeated patches without progress, return to the Explore phase. Gather new evidence, refine the hypothesis, and adjust the plan before continuing.&lt;/p&gt;
&lt;p&gt;Keep changes reviewable. The diff should be minimal, focused, and accompanied by tests. Commits should be logical and self-contained, making it easy to verify that the implementation matches the plan. If the task involves complex logic, break it into smaller steps and validate each one before proceeding. The assistant’s role is to accelerate implementation, not to replace human oversight. The developer remains responsible for ensuring that the code meets the task’s requirements and adheres to project standards.&lt;/p&gt;
&lt;h2&gt;Verify: layered checks that earn trust&lt;/h2&gt;
&lt;p&gt;Verification is the final gate in the workflow, ensuring that the assistant’s output meets all requirements and does not introduce hidden risks. This phase applies multiple layers of checks, each designed to catch different classes of errors and build confidence in the change.&lt;/p&gt;
&lt;p&gt;Automated checks form the first layer. These include unit and integration tests, linting, type checks, and build steps. They confirm that the code behaves as expected in controlled scenarios and adheres to technical standards. Behavioural checks follow, using manual test scripts to validate real-world interactions, edge cases, and failure paths. For web applications, this might involve cross-browser testing or device compatibility checks.&lt;/p&gt;
&lt;p&gt;Operational checks ensure the change is production-ready. Review error handling, logging, metrics, configuration, and any required migrations or rollback procedures. Security checks address input validation, output encoding, authorisation, secrets management, logging hygiene, and dependency security. These checks are non-negotiable, regardless of task size.&lt;/p&gt;
&lt;p&gt;To streamline verification, use a compact checklist tied to the task’s risk level. Low-risk changes may require only basic checks, while high-risk changes demand thorough validation. The key principle is this: verification effort scales with risk, but it is never optional. By applying these layers systematically, the workflow ensures that the assistant’s speed does not compromise reliability. The result is code that is not only fast to produce but also trustworthy in production.&lt;/p&gt;
&lt;h2&gt;Context management: control what the assistant sees and assumes&lt;/h2&gt;
&lt;p&gt;Context is the information the assistant uses to generate code, and its quality directly determines the reliability of the output. Low-quality context produces plausible, but incorrect results, leading to wasted effort and technical debt. Context includes the problem statement, relevant code paths, constraints, and assumptions about the system’s behaviour. Without explicit guidance, the assistant fills gaps with generic or incorrect assumptions, which can introduce subtle bugs or unnecessary complexity.&lt;/p&gt;
&lt;p&gt;To manage context effectively, create a task brief for each atomic task. This brief should include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scope and non-goals: What the task includes and excludes.&lt;/li&gt;
&lt;li&gt;Constraints: Versions, environments, dependencies, and deployment requirements.&lt;/li&gt;
&lt;li&gt;Relevant files and commands: Specific paths, build commands, or test scripts to use.&lt;/li&gt;
&lt;li&gt;Assumptions: Explicit notes about API behaviour, user permissions, or other system-specific details.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Repository guidance files, such as AGENTS.md or CLAUDE.md, can standardize context across tasks. These files define coding standards, boundaries, review expectations, and common commands. By referencing them in task briefs, you ensure consistency and reduce the risk of misaligned output.&lt;/p&gt;
&lt;p&gt;The goal is to provide the assistant with the minimal, precise context required for the task. Too much context leads to confusion or scope creep; too little results in incorrect assumptions. Striking this balance ensures that the assistant’s speed is harnessed productively, not spent on rework or debugging.&lt;/p&gt;
&lt;h2&gt;Scaling the workflow: bugfix vs feature vs project&lt;/h2&gt;
&lt;p&gt;The Explore – Plan – Code – Verify loop scales to different types of work, but its core principles remain unchanged. The difference lies in the depth of each phase and the rigour of the gates.&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;bugfixes&lt;/strong&gt;, the workflow is streamlined. Explore focuses on reproducing the issue and identifying the root cause, while Plan defines a minimal, targeted fix. Verification is strict but narrow, ensuring the bug is resolved without introducing regressions. Pull requests should be tiny, avoiding broad refactors or unrelated changes. The goal is speed, but only if the fix is correct and reversible.&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;features&lt;/strong&gt;, the workflow expands. Explore and Plan involve more upfront work: gathering requirements, evaluating trade-offs, and breaking the feature into staged deliverables. Feature flags may be used to decouple deployment from release, allowing for incremental validation. Verification includes more manual testing and stakeholder checks to confirm the feature meets user needs. The focus shifts from speed to correctness and alignment with long-term goals.&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;projects&lt;/strong&gt;, the workflow becomes comprehensive. Discovery spikes and architectural decision records (ADRs) precede implementation, ensuring the project’s direction is sound. Migration and rollout planning are explicit, with stronger review and verification gates to manage risk. The loop runs at multiple levels: high-level milestones are broken into atomic tasks, each with its own Explore, Plan, Code, and Verify cycle. The invariants remain non-negotiable, but the scale demands more coordination and documentation.&lt;/p&gt;
&lt;p&gt;In all cases, the workflow ensures that AI-assisted development remains controlled, predictable, and aligned with project goals. The assistant’s speed is harnessed productively, but human judgement remains the final authority.&lt;/p&gt;
&lt;h2&gt;Conclusion: speed with a human in the loop&lt;/h2&gt;
&lt;p&gt;AI coding assistants increase throughput, but they do not change
accountability. They can generate code quickly, suggest solutions, and automate repetitive tasks, but the responsibility for correctness, security, and alignment with project goals remains with the human developer. Speed is only valuable if it serves these priorities.&lt;/p&gt;
&lt;p&gt;The practical recipe for safe AI-assisted development is straightforward: atomic tasks, explicit verification, and rigorous review. Break work into small, independently verifiable units. Define acceptance criteria and a definition of done for each task. Apply layered checks—automated tests, manual validation, operational reviews—to ensure the output meets requirements. Never bypass human review, especially for critical changes.&lt;/p&gt;
&lt;p&gt;The non-negotiable principle is this: a human must remain in the loop for requirements, boundaries, code review, and final verification. The assistant accelerates the process, but it does not replace judgement. Used well, it can deliver routine engineering work faster and with fewer errors. Used poorly, it can introduce technical debt just as quickly. The difference lies in the workflow, and in the discipline to enforce it.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2026-W05]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Local LLM setup</title>
    <link href="https://stephencox.net/notes/tech/local-llm-setup/" />
    <updated>2026-04-23T00:00:00Z</updated>
    <published>2025-07-22T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/local-llm-setup/</id>
    <summary>Collection of tools and resources for running local LLMs including Ollama, Open WebUI, and development tools.</summary>
    <content type="html">&lt;hr /&gt;
&lt;h2&gt;Local LLM&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://ollama.com/&lt;/li&gt;
&lt;li&gt;https://anythingllm.com/&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Open WebUI&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://github.com/open-webui/open-webui&lt;/li&gt;
&lt;li&gt;https://pahautelman.github.io/pahautelman-blog/tutorials/open-webui-rag/open-webui-rag/&lt;/li&gt;
&lt;li&gt;https://github.com/pahautelman/open-webui-email-calendar-assistant&lt;/li&gt;
&lt;li&gt;https://docs.openwebui.com/&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Development&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://www.continue.dev/&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;LLM Memory&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://github.com/mem0ai/mem0&lt;/li&gt;
&lt;li&gt;https://github.com/letta-ai/letta&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Prompts&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://github.com/danielmiessler/fabric&lt;/li&gt;
&lt;li&gt;https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/tree/main&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Hardware&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://docs.nvidia.com/cuda/cuda-installation-guide-linux/#ubuntu-installation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W30]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Personal AI agent</title>
    <link href="https://stephencox.net/notes/tech/personal-ai-agent/" />
    <updated>2026-04-23T00:00:00Z</updated>
    <published>2025-11-02T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/personal-ai-agent/</id>
    <summary>Requirements and tech stack for building a self-hosted open source AI agent with research capabilities.</summary>
    <content type="html">&lt;ul&gt;
&lt;li&gt;https://hermes-agent.nousresearch.com/&lt;/li&gt;
&lt;li&gt;https://lushbinary.com/blog/hermes-agent-gemma-4-qwen-3-5-local-ai-guide/&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tech stack for an open source AI agent.&lt;/p&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Self hosted&lt;/li&gt;
&lt;li&gt;Can run as a background service&lt;/li&gt;
&lt;li&gt;Ability to choose an LLM backend&lt;/li&gt;
&lt;li&gt;Web browsing&lt;/li&gt;
&lt;li&gt;Capable of deep research&lt;/li&gt;
&lt;li&gt;Cron jobs&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W44]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Preventing Claude access to potentially sensitive files</title>
    <link href="https://stephencox.net/notes/tech/preventing-claude-access-to-potentially-sensitive-files/" />
    <updated>2026-04-17T00:00:00Z</updated>
    <published>2026-04-17T00:00:00Z</published>
    <id>https://stephencox.net/notes/tech/preventing-claude-access-to-potentially-sensitive-files/</id>
    <summary></summary>
    <content type="html">&lt;h2&gt;.claude/settings.json&lt;/h2&gt;
&lt;p&gt;This can be applied through the Claude team settings so it is enforced to everyone in the organisation.&lt;/p&gt;
&lt;p&gt;An example that could be applied to everyone:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;permissions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;deny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Read(./.env)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Read(./.env.*)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Read(*.sql)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(cat .env)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(cat .env.*)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(cat *.sql)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(grep .env)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(grep .env.*)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(grep *.sql)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(git push --force *)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(git push * --force)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Bash(rm -rf *)&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Sandboxing&lt;/h2&gt;
&lt;p&gt;Sandboxing restricts Bash commands by running them with file system and network isolation, keeping them from accessing file from outside the project directory. In Linux it uses &lt;a href=&quot;https://github.com/containers/bubblewrap&quot;&gt;bubblewrap&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It could be enforced centrally using the &lt;code&gt;.claude/settings.json&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;sandbox&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;filesystem&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;denyRead&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;~/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;allowRead&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Dev containers&lt;/h2&gt;
&lt;p&gt;Anthropic provide and example &lt;a href=&quot;https://github.com/anthropics/claude-code/tree/main/.devcontainer&quot;&gt;devcontainer&lt;/a&gt; for running Claude in a Docker container. We could consider adding this to our Lando configuration so we have a sandboxed Claude always available for client projects.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;https://code.claude.com/docs/en/security&lt;/li&gt;
&lt;li&gt;https://code.claude.com/docs/en/permissions&lt;/li&gt;
&lt;li&gt;https://code.claude.com/docs/en/sandboxing&lt;/li&gt;
&lt;li&gt;https://code.claude.com/docs/en/devcontainer&lt;/li&gt;
&lt;li&gt;https://dev.to/klement_gunndu/lock-down-claude-code-with-5-permission-patterns-4gcn&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2026-W16]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>The Dynamics of Cryptocurrency Price Momentum</title>
    <link href="https://stephencox.net/projects/the-dynamics-of-cryptocurrency-price-momentum/" />
    <updated>2026-04-13T00:00:00Z</updated>
    <published>2026-04-05T00:00:00Z</published>
    <id>https://stephencox.net/projects/the-dynamics-of-cryptocurrency-price-momentum/</id>
    <summary>The Dynamics of Cryptocurrency Price Momentum: Empirical Foundations, Market Microstructure, and Algorithmic Exploitability</summary>
    <content type="html">&lt;h1&gt;The Dynamics of Cryptocurrency Price Momentum: Empirical Foundations, Market Microstructure, and Algorithmic Exploitability&lt;/h1&gt;
&lt;p&gt;The existence of price momentum—the empirical tendency of assets that have performed well in the recent past to continue performing well, and those that have performed poorly to continue declining—has been documented as one of the most persistent anomalies in traditional financial markets. Initially established in equities by substantial academic endeavor over the past three decades, momentum factor models now play a core role in modern finance theory, risk management, and quantitative hedge fund strategies. As the cryptocurrency asset class has matured from a retail-driven experiment into a globally integrated financial ecosystem boasting a market capitalization in excess of $4 trillion, an extensive body of empirical research has sought to determine whether digital assets exhibit similar momentum characteristics. Crucially, market participants seek to understand whether these statistical regularities can be systematically exploited through algorithmic trading frameworks operating in a high-frequency, continuous environment.&lt;/p&gt;
&lt;p&gt;The comprehensive analysis of historical market data, behavioral finance literature, and microstructural mechanics indicates that cryptocurrency prices do indeed exhibit profound and exploitable price momentum. However, the manifestation of this momentum, its underlying structural and behavioral catalysts, and the specific mechanical adaptations required to extract alpha algorithmically differ fundamentally from traditional equity, fiat currency, or commodity markets. The extreme idiosyncratic volatility, continuous 24/7 trading environment, absence of traditional fundamental valuation anchors (such as discounted cash flows or centralized balance sheets), and the outsized influence of perpetual futures funding rates create a highly unique market microstructure. Consequently, while theoretical paper portfolios and unconstrained backtests often demonstrate extraordinary momentum returns, real-world algorithmic exploitability is severely constrained by non-linear market impact, regime-dependent tail risks, high-frequency slippage, and continuous negative carry originating from derivative mechanisms.&lt;/p&gt;
&lt;h2&gt;1. Empirical Foundations of Cryptocurrency Price Momentum&lt;/h2&gt;
&lt;p&gt;The academic consensus overwhelmingly supports the existence of a robust momentum factor within both the cross-section and time-series of cryptocurrency returns. Comprehensive factor models, adapting the classical Fama-French frameworks to the nuances of digital assets, consistently demonstrate that momentum captures significant variations in expected forward returns.&lt;/p&gt;
&lt;h3&gt;1.1 The Classical Three-Factor and Four-Factor Models&lt;/h3&gt;
&lt;p&gt;Rigorous empirical analysis has established that a three-factor model consisting of the aggregate cryptocurrency market, asset size, and historical momentum successfully captures cross-sectional expected returns in the digital asset space. Unlike traditional equities, where valuation anchors such as book-to-market ratios form the foundation of fundamental factors, the cryptocurrency ecosystem relies heavily on network adoption proxies, historical price trajectories, production costs, and market capitalization dynamics to define systematic risk.&lt;/p&gt;
&lt;p&gt;Cross-sectional Fama–MacBeth regression models applied to historical cryptocurrency data spanning from December 2017 to December 2023 validate the immense predictive power of the momentum factor. In these regressions, the momentum factor—typically defined by the return of the asset over the preceding week or month—demonstrates elevated coefficients and high levels of statistical significance, effectively confirming the tendency of digital assets to maintain their performance trajectories. To ensure the robustness of these findings against the high autocorrelation and heteroskedasticity inherent to financial time series data, researchers actively apply Newey–West standard error adjustments.&lt;/p&gt;
&lt;p&gt;A univariate momentum model, utilized to isolate the independent predictive power of past performance, yields a highly significant regression coefficient of 2.0573 with an adjusted R-squared of 0.484. When expanded into a comprehensive four-factor model (incorporating market, size, value, and momentum characteristics), the momentum coefficient remains highly significant at 1.3220. This mathematically affirms that past performance reliably forecasts subsequent returns even when controlling for broader market beta and relative asset valuation.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Model Specification&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Momentum Factor Coefficient&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Statistical Significance (p-value)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Adjusted R-Squared&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Factor Interaction&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Univariate Momentum Model&lt;/td&gt;
&lt;td&gt;2.0573&lt;/td&gt;
&lt;td&gt;&amp;lt; 0.01&lt;/td&gt;
&lt;td&gt;0.484&lt;/td&gt;
&lt;td&gt;Standalone Momentum Analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Four-Factor Model (Market, Size, Value, Momentum)&lt;/td&gt;
&lt;td&gt;1.3220&lt;/td&gt;
&lt;td&gt;&amp;lt; 0.01&lt;/td&gt;
&lt;td&gt;0.573&lt;/td&gt;
&lt;td&gt;Synergistic integration with Value &amp;amp; Size&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Table 1: Regression Analysis of Cryptocurrency Momentum Factors. Data indicates statistically significant predictive power across multiple cross-sectional Fama-MacBeth model specifications, utilizing Newey-West standard errors for robust inference.&lt;/p&gt;
&lt;p&gt;The integration of the momentum factor with customized cryptocurrency &amp;quot;value&amp;quot; factors creates notable quantitative synergy, ultimately explaining approximately 57.3% of the variation in weekly cryptocurrency returns. The mathematical formulation utilized in these cross-sectional evaluations successfully isolates the specific sensitivity of an asset to historical momentum, categorically rejecting the null hypothesis that momentum has no effect on forward-looking price discovery. Furthermore, an asset pricing model that incorporates a specific cryptocurrency trend factor (CTREND) significantly outperforms competing factor models, surviving the impact of transaction costs and persisting most dominantly in large-cap, highly liquid coins.&lt;/p&gt;
&lt;h3&gt;1.2 Time-Series vs. Cross-Sectional Momentum Efficacy&lt;/h3&gt;
&lt;p&gt;In traditional financial markets, momentum is frequently exploited via cross-sectional momentum (CSMOM) strategies—algorithms that simultaneously buy the top decile of historical performers (winners) and short the bottom decile (losers) to create a market-neutral, zero-cost portfolio. However, the application of pure CSMOM in cryptocurrencies yields mixed results when subjected to realistic market frictions and the extreme idiosyncratic volatility of individual tokens.&lt;/p&gt;
&lt;p&gt;Evidence of time-series momentum (TSMOM), often referred to as trend following, is demonstrably stronger and more reliably exploitable in the cryptocurrency space. TSMOM strategies evaluate an asset&#39;s past return against its own absolute history rather than against a relative peer group. Analyses of TSMOM algorithms reveal that buying the aggregate market or individual assets when the look-back period return rests in the top tier of its historical distribution significantly outperforms a passive buy-and-hold benchmark. The best-performing TSMOM parameters identified in historical studies (utilizing a 28-day look-back and a 5-day holding period) yielded a Sharpe ratio of 1.51, compared to the broader market&#39;s baseline Sharpe of 0.84.&lt;/p&gt;
&lt;p&gt;A critical structural divergence between equity and cryptocurrency momentum lies in the distribution of profitability between the long and short legs. In traditional equity markets, shorting losers is a highly reliable alpha source. In crypto, however, the profitability of momentum algorithms is heavily skewed toward the &amp;quot;long leg&amp;quot; of the trade. Past losers in the digital asset space frequently experience massive, rapid, and unpredicted rebounds—often driven by sudden social media virality or speculative short-squeezes—inflicting catastrophic losses on the short leg of market-neutral portfolios. Consequently, cross-sectional strategies in cryptocurrencies are heavily hindered; a single altcoin&#39;s exponential, idiosyncratic spike can entirely dismantle the risk-adjusted returns of a cross-sectional long-short portfolio.&lt;/p&gt;
&lt;h3&gt;1.3 Temporal Anomalies, Seasonality, and the Weekend Effect&lt;/h3&gt;
&lt;p&gt;The uninterrupted, 24-hour, 7-day-a-week nature of cryptocurrency trading introduces unique temporal dynamics to momentum anomalies. Without the structural market closures, weekend breaks, or daily settlement halts characteristic of traditional financial exchanges, momentum exhibits continuous compounding, but also distinct calendar effects.&lt;/p&gt;
&lt;p&gt;Empirical studies spanning from January 2020 through April 2025 identify a pronounced, statistically significant &amp;quot;weekend effect&amp;quot; in cryptocurrency momentum. Momentum trading algorithms executed specifically over weekends systematically yield higher absolute returns and superior risk-adjusted metrics—including higher Sharpe ratios and lower maximum drawdowns—compared to their weekday counterparts. This performance differential is particularly acute in smaller-capitalization altcoins compared to major assets like Bitcoin or Ethereum.&lt;/p&gt;
&lt;p&gt;The continuous trading environment provides compelling evidence that temporal momentum patterns emerge from trader sentiment, localized liquidity vacuums, and behavioral reflexes rather than mere institutional frictions or exchange closures. Historically, the relative absence of algorithmic institutional capital flow on weekends left price discovery primarily to retail participants, amplifying behavioral biases and resulting in stronger trend continuation.&lt;/p&gt;
&lt;p&gt;Beyond weekly temporal patterns, the asset class exhibits macro-seasonal calendar effects. Analysis of market returns heading into 2026 reveals that September historically functions as the weakest period for crypto momentum, averaging returns of -4.7%, while the October through April window historically represents the strongest environment for algorithmic trend following. Furthermore, the fourth quarter following embedded network supply events (such as Bitcoin halving years) has historically proven explosive, generating average returns exceeding 80% during the October-December period.&lt;/p&gt;
&lt;h2&gt;2. Behavioral and Structural Catalysts of Momentum&lt;/h2&gt;
&lt;p&gt;The persistence of the momentum anomaly in broadly efficient markets is traditionally debated in academia as either a systematic risk premium or an entrenched behavioral mispricing. In the cryptocurrency ecosystem, the consensus leans heavily toward a combination of pronounced behavioral biases and highly unique microstructural mechanisms. The environment&#39;s historical retail dominance, high retail leverage, lack of universally accepted fundamental valuation models, and hyper-connected social media landscape create a remarkably fertile environment for psychological biases to manifest directly in time-series price data.&lt;/p&gt;
&lt;h3&gt;2.1 Investor Psychology and Cognitive Biases&lt;/h3&gt;
&lt;p&gt;Because cryptocurrencies generally lack traditional fundamental valuation anchors such as discounted cash flows, dividend yields, or centralized corporate balance sheets, investors cannot easily identify when an asset is objectively &amp;quot;overvalued&amp;quot;. This vacuum of fundamental gravity allows trends to extend far beyond rational limits. Specific behavioral biases continuously fuel this momentum architecture :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Disposition Effect and Underreaction:&lt;/strong&gt; Investors exhibit a pronounced psychological tendency to sell winning positions too early to secure emotional satisfaction from profits, while holding losing positions too long in an attempt to avoid realizing losses. This behavioral friction results in the gradual, rather than immediate, dissemination of supply. It dampens the immediate price impact of positive news, causing the asset price to trend upward slowly rather than jumping to its new fair value instantly. This delayed price discovery creates a measurable momentum trajectory that algorithms can identify and follow.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Availability Bias, Herding, and FOMO:&lt;/strong&gt; Cryptocurrency investors heavily weight recent, highly visible, and easily accessible information—such as trending social media metrics, viral influencer recommendations, or parabolic price charts—over complex fundamental analysis. This &amp;quot;availability bias&amp;quot; triggers urgent, panic-driven capital inflows during initial price spikes, propelled by the Fear Of Missing Out (FOMO). This herding behavior directly translates into persistent, self-fulfilling upward price momentum.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Echo Chambers and Confirmation Bias:&lt;/strong&gt; The intensely tribal nature of cryptocurrency sub-communities limits the processing of contrarian information. Investors actively seek out validation for their preexisting market positions, causing assets to maintain their performance trajectory as capital becomes locked in ideologically driven holding patterns, effectively removing circulating supply during uptrends.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Illusion of Control and Overconfidence:&lt;/strong&gt; Investors frequently overestimate their trading skill and their ability to navigate highly volatile environments. This overconfidence leads to excessive trading volume and a willingness to purchase assets at elevated prices during established trends, underestimating the probability of an impending reversal.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The integration of advanced Large Language Models (LLMs) to perform cross-platform multimodal sentiment analysis indicates that the medium of information delivery heavily impacts the duration of momentum. Short-term, explosive momentum spikes and speculative trends are often catalyzed by highly viral, video-based sentiment platforms (such as TikTok), whereas longer-term, structural momentum trends align more closely with text-based social discourse platforms (such as Twitter). Integrating these specific cross-platform behavioral signals into predictive algorithmic models has been empirically shown to improve momentum forecasting accuracy by up to 20%.&lt;/p&gt;
&lt;h3&gt;2.2 Microstructural Reflexivity and the Leverage Feedback Loop&lt;/h3&gt;
&lt;p&gt;Beyond human psychology, the internal plumbing of the cryptocurrency market mathematically enforces momentum. Reflexivity—the feedback loop where rising prices improve the fundamental utility, security, or development funding of the network, which in turn drives prices higher—is a core feature of tokenomics.&lt;/p&gt;
&lt;p&gt;Furthermore, the pervasive use of highly leveraged derivatives structurally amplifies trends. As algorithmic momentum initiates a price increase, traders holding highly leveraged short positions are forcibly liquidated. The liquidation engine of the exchange automatically buys back the asset at market price to cover the short, which rapidly drives the price even higher, subsequently triggering the liquidation thresholds of traders with slightly higher margin limits. This cascading phenomenon of forced buying during an uptrend (or forced selling during a downturn) mechanically generates severe, algorithmic momentum streaks that operate entirely detached from external fundamental news or rational pricing.&lt;/p&gt;
&lt;h2&gt;3. The Achilles Heel: Momentum Crashes and Tail-Risk Dynamics&lt;/h2&gt;
&lt;p&gt;While time-series momentum offers substantial theoretical alpha, it is highly susceptible to devastating &amp;quot;momentum crashes,&amp;quot; which represent the single most significant barrier to the systematic exploitability of the anomaly. An algorithm optimizing purely for maximum momentum capture will inevitably face existential ruin if it fails to account for these abrupt, violent reversals.&lt;/p&gt;
&lt;h3&gt;3.1 The Anatomy of a Momentum Crash&lt;/h3&gt;
&lt;p&gt;Statistical analysis of momentum return distributions reveals severe non-normality across both equities and cryptocurrencies. These distributions are characterized by extreme excess kurtosis (fat tails) and highly negative skewness. Comprehensive reviews of historical asset pricing note that momentum crashes traditionally occur when the broader market has fallen into a highly volatile, stressed panic state, and then suddenly rebounds.&lt;/p&gt;
&lt;p&gt;During these inflection points, the assets that algorithms are shorting (the past losers) surge exponentially, while the assets algorithms are long (the past winners) either stagnate or decline sharply. This results in massive, instantaneous losses for naive trend-following algorithms. In the cryptocurrency domain, where baseline volatility is structurally higher than in traditional equities, these crashes can obliterate years of accumulated returns within a matter of days. For instance, classic TSMOM strategies without dynamic risk management parameters experienced drawdowns exceeding 65% during the 2018 bear market and the cascading contagion events of 2022.&lt;/p&gt;
&lt;p&gt;The underlying mechanics of these crashes differ from traditional markets. Equities frequently crash due to investor overreaction to asset growth or quarterly earnings reports. Because cryptocurrencies lack these corporate metrics, an overreaction crash in digital assets is frequently more violent, driven by sudden liquidity vacuums and the unwinding of systemic leverage. Furthermore, empirical studies indicate that momentum strength and subsequent reversal severity are influenced by the underlying consensus mechanism of the blockchain; Proof-of-Work (PoW) coins historically demonstrate stronger momentum but significantly deeper, more violent reversals compared to Proof-of-Stake (PoS) assets.&lt;/p&gt;
&lt;h3&gt;3.2 Volatility-Managed Momentum Portfolios&lt;/h3&gt;
&lt;p&gt;To render momentum safely exploitable for institutional capital, algorithmic frameworks must implement sophisticated volatility-targeting mechanisms. Inspired by classical quantitative techniques pioneered by Barroso and Santa-Clara, scaling momentum portfolio exposures by the inverse of their realized variance stabilizes the return stream.&lt;/p&gt;
&lt;p&gt;In traditional equity markets, volatility management primarily serves a defensive purpose: it truncates the left tail of the distribution to reduce the depth of crashes. However, in cryptocurrency markets, empirical evidence demonstrates that volatility-managed momentum actually enhances the absolute average returns of the strategy alongside reducing downside risk. By dynamically deleveraging during periods of extreme ex-ante volatility and sizing up aggressively during stable, low-volatility trending regimes, systematic trend followers can drastically improve risk-adjusted metrics. Studies applying volatility management to cryptocurrency momentum indicate an increase in average weekly returns from 3.18% to 3.47%, while elevating the annualized Sharpe ratio from 1.12 to 1.42. This paradigm proves that momentum crashes are not entirely random black-swan events; they are highly conditional states that are heavily correlated with specific, measurable ex-ante volatility thresholds.&lt;/p&gt;
&lt;h2&gt;4. Algorithmic Exploitability and State-of-the-Art Frameworks&lt;/h2&gt;
&lt;p&gt;The translation of theoretical momentum anomalies into actionable, automated algorithmic trading strategies requires navigating continuous regime transitions and non-stationary market dynamics. Simple heuristic strategies, such as dual moving average crossovers (e.g., executing a long position when a short-term Exponential Moving Average crosses above a long-term EMA), demonstrate baseline efficacy in capturing macro trends. Such primitive models successfully capture multi-year macroeconomic cycles in Bitcoin, generating Compound Annual Growth Rates (CAGR) exceeding 100% and outperforming static buy-and-hold approaches while mathematically sidestepping the most severe prolonged drawdowns. However, these simple models suffer from severe whipsaw effects and degrade rapidly in choppy, high-volatility, range-bound environments.&lt;/p&gt;
&lt;h3&gt;4.1 Advanced Heuristics: The AdaptiveTrend Framework&lt;/h3&gt;
&lt;p&gt;State-of-the-art algorithmic implementations have evolved significantly beyond static moving averages. Extensive research spanning the 2022 to 2024 testing window highlights the exceptional efficacy of the &amp;quot;AdaptiveTrend&amp;quot; framework, a multi-component architecture designed specifically to address the unique microstructure, volatility profiles, and empirical positive drift of cryptocurrency momentum.&lt;/p&gt;
&lt;p&gt;The AdaptiveTrend system integrates high-frequency trend-following on 6-hour execution intervals with monthly adaptive portfolio construction. The model is distinguished from primitive trend followers by three systematic, theoretically grounded innovations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dynamic Trailing Stops Calibrated to Intraday Volatility:&lt;/strong&gt; Rather than utilizing fixed percentage stops (which are frequently triggered by normal crypto market noise), the algorithm continuously adjusts its exit thresholds using an Average True Range (ATR) multiplier. This volatility-weighted position allocation ensures that when market stress expands the ATR (signaling increased regime risk), the algorithm automatically reduces the size of the trade, lowering aggregate portfolio volatility without arbitrarily stopping out of viable, long-term trends.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rolling Sharpe-Ratio Asset Selection:&lt;/strong&gt; The cross-sectional component of the algorithm dynamically filters a broad universe of over 150 assets. It explicitly weights asset selection toward tokens demonstrating high risk-adjusted momentum (Sharpe ratio) rather than mere absolute return, while applying strict, market-capitalization-aware filters to avoid the severe illiquidity and manipulation risks of micro-cap tokens.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Asymmetric Allocation:&lt;/strong&gt; Recognizing the inherent long-term positive drift of digital assets and the empirical &amp;quot;long-leg&amp;quot; dominance of crypto momentum profitability, the algorithm discards traditional market-neutral parameters. Instead, it utilizes a mathematically motivated 70/30 long-short capital allocation bias.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Extensive out-of-sample backtesting demonstrates the profound robustness of this approach. During the evaluated 36-month period, the AdaptiveTrend framework generated an annualized Sharpe ratio of 2.41, a Calmar ratio of 3.18, and a remarkably constrained maximum drawdown of only -12.7%, vastly outperforming baseline time-series momentum strategies.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Market Regime&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Annualized Return&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Sharpe Ratio&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Maximum Drawdown&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Win Rate&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bull Market&lt;/td&gt;
&lt;td&gt;68.3%&lt;/td&gt;
&lt;td&gt;3.42&lt;/td&gt;
&lt;td&gt;-7.1%&lt;/td&gt;
&lt;td&gt;54.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sideways Market&lt;/td&gt;
&lt;td&gt;18.7%&lt;/td&gt;
&lt;td&gt;1.87&lt;/td&gt;
&lt;td&gt;-9.4%&lt;/td&gt;
&lt;td&gt;47.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bear Market&lt;/td&gt;
&lt;td&gt;-4.2%&lt;/td&gt;
&lt;td&gt;-0.31&lt;/td&gt;
&lt;td&gt;-12.7%&lt;/td&gt;
&lt;td&gt;41.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Table 2: Regime-Conditional Performance of the AdaptiveTrend Framework (70/30 Allocation). The implementation of dynamic trailing stops ensures near-flat performance during bearish cycles, effectively neutralizing the momentum crash phenomenon.&lt;/p&gt;
&lt;p&gt;Rigorous ablation studies confirm that the dynamic trailing stop mechanism is the single most critical feature of the algorithm. Removing it results in a massive 0.73 degradation in the Sharpe ratio and a near 10-percentage-point expansion in maximum drawdowns. Monthly parameter optimization is the second most impactful component, underscoring the absolute necessity of adaptive calibration in non-stationary digital asset markets.&lt;/p&gt;
&lt;h3&gt;4.2 Deep Reinforcement Learning and Utility Theory Integration&lt;/h3&gt;
&lt;p&gt;The integration of artificial intelligence, specifically Deep Reinforcement Learning (RL), represents the theoretical frontier of algorithmic momentum trading. Traditional RL models applied to finance often fail out-of-sample because they rely on overly simplistic, profit-maximization reward functions. This singular focus leads the trading agent to drastically over-leverage during strong trends to maximize short-term rewards, inevitably suffering catastrophic liquidation during the subsequent market reversals.&lt;/p&gt;
&lt;p&gt;Recent advancements utilize sophisticated algorithms—including Deep Q-Networks (DQN), Proximal Policy Optimization (PPO), and Advantage Actor–Critic (A2C) architectures—calibrated with highly engineered reward functions grounded in economic utility theory and behavioral finance. The most successful formulations actively internalize market microstructure constraints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Temporal Coherence Rewards:&lt;/strong&gt; These functions penalize the algorithmic agent for erratic, high-frequency oscillatory trading behavior. By providing mathematical bonuses for maintaining directional conviction, the algorithm learns to ignore short-term market noise and ride the macro momentum wave.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Adaptive Risk Control Rewards:&lt;/strong&gt; This framework dynamically adjusts risk penalties based on recent market volatility metrics, tightening trading constraints during turbulent, high-risk periods and relaxing them during stable, trending regimes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Market Impact Adjusted Rewards:&lt;/strong&gt; To bridge the critical gap between simulated backtests and live market execution, the reward function mathematically penalizes the agent proportionally to its trade size and inversely to rolling market volume. This teaches the algorithm to optimize for liquidity depth restrictions and minimize slippage. The exact mathematical modeling defines impact as $&#92;text{Impact}_t = &#92;kappa &#92;cdot |&#92;Delta &#92;text{Position}_t| &#92;cdot &#92;frac{&#92;sigma(t)}{&#92;text{Volume}_t}$.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By implementing these sophisticated reward engineering techniques, RL models have demonstrated exceptional resilience. During comprehensive experimental evaluations utilizing hourly Bitcoin data from 2018 to 2022, agents employing the Adaptive Risk Control reward function achieved a Sharpe ratio of 2.47 and a maximum drawdown of only 16.8% during the notoriously bearish 2022 test period, proving that sophisticated reward engineering is the primary lever for generating positive risk-adjusted returns during severe market downturns.&lt;/p&gt;
&lt;h2&gt;5. The Friction Barrier: Execution Costs, Slippage, and Market Impact&lt;/h2&gt;
&lt;p&gt;While mathematical factor models and unconstrained backtests indicate high levels of momentum exploitability, executing systematic momentum strategies with real capital in the cryptocurrency market is fraught with severe microstructural frictions. Academic studies evaluating cross-sectional momentum that ignore transaction costs, interim daily price fluctuations, and slippage grossly overestimate the true profitability of the anomaly. When real-world execution costs and algorithmic market impact are accurately modeled, many theoretical momentum portfolios that exhibit statistically significant gross returns fail entirely to generate positive net alpha, and are frequently forced into rapid liquidation.&lt;/p&gt;
&lt;h3&gt;5.1 Liquidation Risk and Margin Mechanics&lt;/h3&gt;
&lt;p&gt;Academic literature frequently models momentum portfolios on a simplified monthly rebalancing schedule without accounting for the interim path of the asset price during the holding period. In the highly volatile cryptocurrency environment, a portfolio marked-to-market daily faces extreme &amp;quot;liquidation risk&amp;quot;.&lt;/p&gt;
&lt;p&gt;Because modern algorithmic strategies utilize leverage to maximize the Sharpe ratio of identified trend-following signals, sharp intraday price shocks can easily trigger forced margin closures long before the overarching momentum signal actually reverses. In empirical tests accounting for this daily fluctuation, numerous portfolios with positive mean expected returns were nonetheless entirely liquidated due to sudden localized jumps or plunges. The specific margin architecture utilized by the algorithmic trading system dictates the survival of the momentum strategy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cross-Margin Mode:&lt;/strong&gt; Utilizing the entire account balance as collateral allows uncorrelated, profitable positions to subsidize temporary drawdowns in others. While this significantly reduces the frequency of localized liquidations, it introduces terminal systemic risk; a sudden, highly correlated market crash can wipe out the entire portfolio equity instantaneously.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Isolated-Margin Mode:&lt;/strong&gt; Segregating collateral strictly on a per-trade basis protects the aggregate portfolio from total ruin. However, it mathematically guarantees high-frequency, localized liquidations during routine intraday volatility spikes, causing the algorithm to consistently forfeit its position and miss the eventual momentum payout.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5.2 Slippage and Non-Linear Market Impact&lt;/h3&gt;
&lt;p&gt;Transaction fees and execution slippage compound negatively against the momentum edge. High-frequency algorithms attempting to capture intraday momentum are mathematically disadvantaged because the sum of execution costs ($C$) and slippage ($S$) relative to the target profit per trade ($P$) frequently approaches or exceeds unity ($&#92;frac{C+S}{P} &#92;approx 1$). Even modest, seemingly negligible exchange fees of 0.075% accumulate to devastating capital erosion for algorithms generating high turnover. Historical analytical investigations utilizing Binance data illustrate that for an initial portfolio of $100,000 executing frequent momentum trades across 80,000 transactions, the accumulated fees reached an astounding $60,000, fundamentally destroying the profitability landscape of the strategy.&lt;/p&gt;
&lt;p&gt;Furthermore, institutional-scale algorithmic trading encounters severe non-linear market impact. The assumption that displaying sufficient order book depth on an exchange guarantees execution without slippage is one of electronic trading&#39;s most expensive misconceptions. Analysis of massive institutional datasets—such as the 50,000 parent orders and 50 million child orders evaluated in the Talos Market Impact (TMI) model—demonstrates that traditional execution cost estimates, such as the classical &amp;quot;square-root law,&amp;quot; fail entirely in the cryptocurrency microstructure.&lt;/p&gt;
&lt;p&gt;At extremely low or high participation rates, the physical impact of liquidity consumption diverges radically from linear models. Institutional execution of momentum trades requires algorithms equipped with complex &amp;quot;sigmoid adjustments&amp;quot; to accurately forecast and navigate slippage regimes. Market depth is also highly temporal; an algorithm executing a momentum signal at peak liquidity hours faces drastically different slippage profiles than one executing during liquidity troughs. Analysis of summer 2025 order book data reveals that a mere 10 basis point depth calculation explains 94% of the variance in execution quality, overriding more complex order book imbalance theories. To mitigate this impact, advanced algorithmic routing logic must deploy &amp;quot;smart routing hedging&amp;quot;—dispersing selling or buying pressure across fragmented centralized and decentralized exchanges simultaneously to prevent localized order book collapses and subsequent runaway slippage.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Friction Source&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Mechanism of Impact&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Algorithmic Mitigation Strategy&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Transaction Costs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High turnover compounds flat fees, rapidly eroding high-frequency theoretical edges.&lt;/td&gt;
&lt;td&gt;Migration to lower frequency (e.g., H6) intervals; execution via limit order maker rebates.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Liquidation Risk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intraday volatility spikes trigger margin calls despite long-term trend correctness.&lt;/td&gt;
&lt;td&gt;Volatility-scaled position sizing (ATR); careful algorithmic selection of cross vs. isolated margin.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Market Impact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Non-linear slippage scaling with order participation rate; temporal liquidity vacuums.&lt;/td&gt;
&lt;td&gt;Sigmoid-adjusted TWAP/VWAP execution logic; Smart routing across fragmented liquidity venues.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Funding Rates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Continuous positive carry tax on long perpetual futures positions erodes momentum profits.&lt;/td&gt;
&lt;td&gt;Incorporating derivative funding drag into the RL agent reward function; Cash-and-carry hedging.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Table 3: The microstructural frictions impeding theoretical momentum returns and the specific algorithmic adaptations required for successful real-world execution.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;6. The Burden of Perpetual Futures and the Funding Rate Tax&lt;/h2&gt;
&lt;p&gt;Perhaps the most profound structural friction impacting long-term momentum exploitability is the core cryptocurrency derivative architecture itself. Spot markets no longer dictate primary price discovery; the perpetual swap derivative fundamentally shifted the market, with perpetual futures now accounting for approximately 93% of all cryptocurrency trading volume.&lt;/p&gt;
&lt;h3&gt;6.1 The Mechanics of Continuous Anchoring&lt;/h3&gt;
&lt;p&gt;Perpetual futures offer heavily leveraged, non-expiring exposure to an underlying cryptocurrency asset. To ensure the derivative price does not permanently unpeg from the underlying spot market—as the contract lacks a traditional expiration date to enforce convergence—exchanges utilize a continuous funding rate mechanism.&lt;/p&gt;
&lt;p&gt;The funding rate is calculated utilizing an interest rate component and a premium index (measuring the deviation between the perpetual price and the spot price). When the perpetual contract trades at a premium to the spot market (contango), long position holders are assessed a funding fee, which is transferred directly to short position holders at periodic intervals (typically every eight hours). Conversely, when the contract trades at a discount (backwardation), shorts pay longs. This mechanism functions as an algorithmic feedback rule operating in a continuous-time equilibrium between risk-constrained arbitrageurs and momentum speculators, successfully tethering the derivative to the underlying asset. While effective for market integrity, its operational mechanics introduce an immense, often insurmountable drag on long-term trend-following strategies.&lt;/p&gt;
&lt;h3&gt;6.2 Alpha Erosion in Long-Term Trend Following&lt;/h3&gt;
&lt;p&gt;In structurally bullish momentum regimes, overwhelming speculative demand for leverage consistently forces the futures price above the spot price, resulting in elevated, highly positive funding rates. For an algorithmic strategy holding a long trend-following position, this represents a relentless, mathematically compounding capital bleed.&lt;/p&gt;
&lt;p&gt;The calculation formulas utilized by dominant exchanges are rarely perfectly neutral; they integrate base interest rates and &amp;quot;clamp functions&amp;quot; that deliberately skew the funding rates positive by design. Consequently, long momentum positions face a systematic tax. If a momentum trend matures slowly over several months, the cumulative sum of the funding payments distributed every eight hours can mathematically erase the capital appreciation of the asset, drastically reducing the net alpha of the algorithm and rendering a theoretically profitable trade unprofitable in practice. Furthermore, if the algorithm&#39;s available margin balance is slowly depleted by these relentless funding payments, the position is pushed closer to the maintenance margin threshold, severely amplifying the aforementioned liquidation risk during routine market pullbacks.&lt;/p&gt;
&lt;p&gt;Because empirical analysis reveals that funding rates act as trailing indicators of market momentum rather than leading predictors, algorithms cannot simply use high funding rates as reliable contrarian short signals; doing so exposes the strategy to further momentum continuation and potential short-squeeze liquidations. However, prolonged periods of highly elevated positive funding almost invariably precede violent volatility expansions and subsequent momentum crashes, reinforcing the absolute necessity of the dynamic ATR trailing stops utilized in sophisticated algorithmic architectures.&lt;/p&gt;
&lt;h2&gt;7. The Paradigm Shift: Institutionalization and the 2026 Regime&lt;/h2&gt;
&lt;p&gt;The structural architecture of cryptocurrency momentum underwent a profound metamorphosis during the 2024–2026 market cycle. The ecosystem transitioned rapidly from a retail-dominated behavioral anomaly into an institutionally integrated, macro-driven factor. This maturation dramatically altered the efficacy of historical algorithmic strategies and shifted the fundamental arenas of execution.&lt;/p&gt;
&lt;h3&gt;7.1 The Breakdown of Classical CTA Strategies and Macro Sensitivities&lt;/h3&gt;
&lt;p&gt;For heavily systematic trend-following funds (Commodity Trading Advisors, or CTAs) operating in the cryptocurrency space, 2025 was widely categorized as a severe &amp;quot;drought year&amp;quot;. Algorithms perfectly calibrated to historical 2020-2023 backtests heavily underperformed their theoretical benchmarks. The Barclay cryptocurrency CTA index recorded severe drawdowns, including -14.71% in February and -7.41% in March of 2025, representing one of the longest downward cycles in the index&#39;s history.&lt;/p&gt;
&lt;p&gt;The divergence between the historical Sharpe ratios of momentum frameworks and their realized performance stemmed from a fundamental macroeconomic realignment. Historically, cryptocurrency momentum was driven by endogenous network cycles (such as the four-year Bitcoin halving) and viral, isolated retail narratives. By late 2025, the asset class became tightly correlated with external macroeconomic indicators and global liquidity metrics, reacting aggressively to Federal Reserve interest rate expectations, employment data, and sovereign geopolitical shocks. For example, the U.S. military operation in Venezuela in early January 2026 caused an immediate algorithmic risk-on response, pushing Bitcoin past $94,000 in tandem with shifting global oil prices.&lt;/p&gt;
&lt;p&gt;This macro-sensitivity resulted in highly volatile &amp;quot;V-shaped reversals&amp;quot; and false technical breakouts, which continuously triggered algorithmic stop-losses before a structural trend could establish itself. Furthermore, the collapse of legacy altcoin tokenomics paradigms—where validator inflation and unlocking schedules vastly exceeded network utility revenues—removed the structural tailwinds that previously supported sustained long-term altcoin momentum. To survive this new institutional regime, algorithms were forced to abandon sluggish daily frequency signals and adopt tighter 6-hour interval logic, aggressively filtering out macroeconomic noise and V-shaped traps.&lt;/p&gt;
&lt;h3&gt;7.2 The Decentralized Execution Migration (Perp DEXs)&lt;/h3&gt;
&lt;p&gt;Simultaneously, the optimal execution layer for algorithmic momentum underwent a massive migration toward Decentralized Perpetual Exchanges (Perp DEXs). As traditional centralized exchanges faced increasing liquidity fragmentation, severe regulatory bottlenecks, and catastrophic infrastructure failures (such as the &amp;quot;October 10 Storm&amp;quot; where order book depth shrank by 98%), highly performant decentralized platforms emerged to capture institutional volume.&lt;/p&gt;
&lt;p&gt;Platforms like Hyperliquid achieved explosive growth, capturing a 73% market share of the decentralized perpetual sector and averaging $47 billion in weekly volume during the first half of 2025, peaking over $78 billion. The transition to Perp DEXs fundamentally alters the calculus for algorithmic momentum exploitability. By operating on custom, application-specific blockchains (Layer 1s) optimized specifically for high-throughput, low-latency execution and zero-gas-fee trading, these protocols strip away many of the traditional centralized slippage and transaction cost constraints that previously hindered high-frequency momentum algorithms.&lt;/p&gt;
&lt;p&gt;The integration of fully on-chain order books with deep community-curated liquidity pools (such as the Hyperliquidity Provider, or HLP, acting as an automated market maker) allows algorithmic momentum strategies to execute highly leveraged positions with fractional capital while entirely mitigating the counterparty risks associated with centralized exchange insolvencies. The expansion of these protocols to list non-crypto assets (commodities, forex, pre-IPO equities) via permissionless oracle standards indicates that sophisticated algorithmic momentum frameworks built initially for the cryptocurrency ecosystem are now being deployed against broader macroeconomic assets on the exact same decentralized infrastructure.&lt;/p&gt;
&lt;h3&gt;7.3 Long-Term Persistence of the Anomaly in an Institutional Era&lt;/h3&gt;
&lt;p&gt;Entering 2026, the cryptocurrency market has decisively achieved structural maturity. Institutional adoption has accelerated past initial speculative phases, marked by the immense success and persistent inflows of spot Exchange Traded Products (ETPs), the integration of digital assets into traditional corporate treasuries, the surging demand for on-chain yield bearing stablecoins, and the successful public IPOs of major crypto-native issuers like Circle. Open interest across institutional venues like the CME Group has shattered historical records, reflecting deep, sophisticated market participation.&lt;/p&gt;
&lt;p&gt;This institutionalization inherently dampens the extreme, irrational behavioral retail overreactions that historically fueled the most explosive momentum anomalies in the crypto space. However, exhaustive empirical evidence from traditional equity, forex, and commodity markets proves that institutionalization does not eliminate the momentum factor; it merely alters its frequency, volatility, and duration. As massive tranches of capital enter the market through deliberate, slow-moving institutional asset allocation models and regulated wealth management pipelines, they generate sustained, structural momentum vectors. These vectors are less prone to overnight social-media-driven crashes and more reflective of long-term macroeconomic pricing, providing a highly stable environment for systematic algorithms equipped with appropriate microstructural risk management to track and exploit well into the future.&lt;/p&gt;
&lt;h2&gt;8. Conclusion&lt;/h2&gt;
&lt;p&gt;The empirical evidence and rigorous academic modeling unequivocally demonstrate that cryptocurrency prices exhibit profound and statistically significant price momentum, heavily influencing the cross-sectional and time-series distribution of expected forward returns. This pervasive anomaly originates from a complex confluence of deep-seated behavioral biases—including the disposition effect, availability bias, herding, and narrative reflexivity—compounded by the leverage-heavy, continuous 24/7 microstructure of digital asset trading.&lt;/p&gt;
&lt;p&gt;Algorithmic exploitation of this momentum is highly viable, yielding risk-adjusted returns that significantly outperform passive buy-and-hold benchmarks across multiple market cycles. However, the naive implementation of classical trend-following models originally designed for equity markets results in extreme vulnerability to severe momentum crashes and rapid capital depletion. True exploitability requires highly sophisticated, adaptive algorithmic frameworks that incorporate dynamic, volatility-weighted trailing stops, asymmetric capital allocation paradigms, and advanced deep reinforcement learning techniques utilizing market-impact-adjusted utility functions.&lt;/p&gt;
&lt;p&gt;Furthermore, the friction of real-world algorithmic execution—dictated by non-linear institutional slippage, unforgiving intraday liquidation thresholds, and the continuous negative carry of perpetual futures funding rates—creates an insurmountable barrier for poorly optimized or purely theoretical algorithms. As the market transitions into its mature, institutionalized 2026 era defined by tight macroeconomic linkages and high-performance decentralized execution infrastructure, successful momentum capture will increasingly rely on minimizing execution latency, dynamically managing shifting volatility regimes, and seamlessly routing across deep, fragmented liquidity networks. Momentum remains a permanent, persistent feature of the cryptocurrency market, but extracting its alpha has evolved permanently from a simple behavioral arbitrage into a complex, institutional-grade microstructural engineering challenge.&lt;/p&gt;
&lt;p&gt;**&lt;/p&gt;
&lt;h4&gt;Works cited&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Cryptocurrency as an Investable Asset Class: Coming of Age - arXiv, https://arxiv.org/html/2510.14435v3&lt;/li&gt;
&lt;li&gt;Breaking Bad Momentum Trends - - Alpha Architect, https://alphaarchitect.com/momentum-trends/&lt;/li&gt;
&lt;li&gt;A Comparison of Cryptocurrency Volatility-benchmarking New and Mature Asset Classes, https://arxiv.org/html/2404.04962v1&lt;/li&gt;
&lt;li&gt;State of Crypto 2025: The year crypto went mainstream - a16z crypto, https://a16zcrypto.com/posts/article/state-of-crypto-report-2025/&lt;/li&gt;
&lt;li&gt;Why Crypto Trends: The Hidden Drivers of Momentum - Hivemind Capital, https://www.hivemind.capital/content/why-crypto-trends-the-hidden-drivers-of-momentum&lt;/li&gt;
&lt;li&gt;Systematic Trend-Following with Adaptive Portfolio Construction: Enhancing Risk-Adjusted Alpha in Cryptocurrency Markets - arXiv, https://arxiv.org/html/2602.11708v1&lt;/li&gt;
&lt;li&gt;Exploring the Psychological Drivers of Cryptocurrency Investment Biases: Evidence from Indian Retail Investors - MDPI, https://www.mdpi.com/2227-7072/13/4/219&lt;/li&gt;
&lt;li&gt;Momentum and Network design in Cross-Section of Cryptocurrency Returns - Aaltodoc, https://aaltodoc.aalto.fi/bitstreams/41680162-a945-4f11-9f99-6458ec4838a4/download&lt;/li&gt;
&lt;li&gt;The Two-Tiered Structure of Cryptocurrency Funding Rate Markets - MDPI, https://www.mdpi.com/2227-7390/14/2/346&lt;/li&gt;
&lt;li&gt;The Emerging Market of Cryptocurrencies and Perpetual Contracts, https://business.cornell.edu/hub/2024/02/20/the-emerging-market-cryptocurrencies-perpetual-contracts/&lt;/li&gt;
&lt;li&gt;The impact of transactions costs and slippage on algorithmic trading performance, https://www.researchgate.net/publication/384458498_The_impact_of_transactions_costs_and_slippage_on_algorithmic_trading_performance&lt;/li&gt;
&lt;li&gt;Time-Series and Cross-Sectional Momentum in the ... - ACFR - AUT, https://acfr.aut.ac.nz/__data/assets/pdf_file/0009/918729/Time_Series_and_Cross_Sectional_Momentum_in_the_Cryptocurrency_Market_with_IA.pdf&lt;/li&gt;
&lt;li&gt;The Impact of Crypto Funding Rates - Amberdata Blog, https://blog.amberdata.io/the-impact-of-crypto-funding-rates&lt;/li&gt;
&lt;li&gt;A Trend Factor for the Cross Section of Cryptocurrency Returns | Journal of Financial and Quantitative Analysis - Cambridge University Press, https://www.cambridge.org/core/journals/journal-of-financial-and-quantitative-analysis/article/trend-factor-for-the-cross-section-of-cryptocurrency-returns/4C1509ACBA33D5DCAF0AC24379148178&lt;/li&gt;
&lt;li&gt;Common Risk Factors in Cryptocurrency - IDEAS/RePEc, https://ideas.repec.org/p/nbr/nberwo/25882.html&lt;/li&gt;
&lt;li&gt;Common Risk Factors in Cryptocurrency - NBER, https://www.nber.org/papers/w25882&lt;/li&gt;
&lt;li&gt;Time-Series and Cross-Sectional Momentum in the Cryptocurrency ..., https://www.researchgate.net/publication/377457967_Time-Series_and_Cross-Sectional_Momentum_in_the_Cryptocurrency_Market_A_Comprehensive_Analysis_under_Realistic_Assumptions&lt;/li&gt;
&lt;li&gt;Optimizing Cryptocurrency Returns: A Quantitative Study on Factor-Based Investing - MDPI, https://www.mdpi.com/2227-7390/12/9/1351&lt;/li&gt;
&lt;li&gt;The Overlap of Cross Sectional and Time Series Momentum Strategies - ScholarWorks@UARK, https://scholarworks.uark.edu/context/finnuht/article/1034/viewcontent/Samuel_Adams_The_Overlap_of_Cross_Sectional_and_Time_Series_Momentum_Strategies.pdf&lt;/li&gt;
&lt;li&gt;Time-series Momentum in the Cryptocurrency Market - Erasmus University Thesis Repository, https://thesis.eur.nl/pub/44390/Wisselink-NJ-483391-BA-thesis.pdf&lt;/li&gt;
&lt;li&gt;Analyzing the Performance of Momentum Strategies in Recent years: A comprehensive study - PYXIDA, https://www.pyxida.aueb.gr/bitstreams/2e26eab4-5d1a-4666-a692-5f894b209914/download&lt;/li&gt;
&lt;li&gt;Cryptocurrency market risk-managed momentum strategies - IDEAS/RePEc, https://ideas.repec.org/a/eee/finlet/v85y2025ipas1544612325011377.html&lt;/li&gt;
&lt;li&gt;Cryptocurrency momentum has (not) its moments - IDEAS/RePEc, https://ideas.repec.org/a/kap/fmktpm/v39y2025i4d10.1007_s11408-025-00474-9.html&lt;/li&gt;
&lt;li&gt;The Weekend Effect in Crypto Momentum: Does Momentum Change When Markets Never Sleep? | Advances in Consumer Research, https://acr-journal.com/article/the-weekend-effect-in-crypto-momentum-does-momentum-change-when-markets-never-sleep--1514/&lt;/li&gt;
&lt;li&gt;crypto trading volume forecast 2026 - Ethereum Staking Validator Guide, https://www.afsin.bel.tr/insights/en/crypto-trading-volume-forecast-2026&lt;/li&gt;
&lt;li&gt;BEHAVIOURAL BIASES IN BITCOIN TRADING | Hidajat | Fokus Ekonomi, https://ejournal.stiepena.ac.id/index.php/fe/article/view/240&lt;/li&gt;
&lt;li&gt;Biases and Emotions Affect the Crypto Market | by Blockchain Today - Medium, https://blockchain-today.medium.com/biases-and-emotions-affect-the-crypto-market-cd4007735ae1&lt;/li&gt;
&lt;li&gt;INVESTOR BEHAVIOR IN THE CRYPTOCURRENCY MARKET - Umeå University, https://umu.diva-portal.org/smash/get/diva2:1681150/FULLTEXT01.pdf&lt;/li&gt;
&lt;li&gt;Cryptocurrency Market Efficiency Revisited: A Bibliometric Analysis | International Journal of Financial Engineering - World Scientific Publishing, https://www.worldscientific.com/doi/10.1142/S2424786325500215&lt;/li&gt;
&lt;li&gt;Enhancing Cryptocurrency Sentiment Analysis with Multimodal Features - arXiv, https://arxiv.org/html/2508.15825v1&lt;/li&gt;
&lt;li&gt;Crypto Crash 2025: What Caused the Crash, BTC Price Drop &amp;amp; Market Recovery Explained, https://learn.backpack.exchange/articles/crypto-crash&lt;/li&gt;
&lt;li&gt;Momentum Strategy With Classical Assets And Cryptocurrencies, https://epub.ub.uni-muenchen.de/103770/1/MA_Melieni.pdf 33. Reducing the Risk of Momentum Crashes - Alpha Architect, https://alphaarchitect.com/risk-of-momentum-crashes/&lt;/li&gt;
&lt;li&gt;Trend Following and Momentum Strategies on Bitcoin (Crypto) – Capturing the Trend with Free Bitcoin Trading Strategies - QuantifiedStrategies.com, https://www.quantifiedstrategies.com/trend-following-and-momentum-strategies-on-bitcoin/&lt;/li&gt;
&lt;li&gt;Momentum and trend following trading strategies for currencies and bitcoin I, https://assets.super.so/e46b77e7-ee08-445e-b43f-4ffd88ae0a0e/files/9c27aa78-9b14-4419-a53d-bc56fa9d43b2.pdf&lt;/li&gt;
&lt;li&gt;Cryptocurrency CTA Paradigm Evolution: From Simple Momentum ..., https://www.binance.com/en/square/post/308461120066626&lt;/li&gt;
&lt;li&gt;Systematic Trend-Following with Adaptive Portfolio Construction: Enhancing Risk-Adjusted Alpha in Cryptocurrency Markets - ResearchGate, https://www.researchgate.net/publication/400742265_Systematic_Trend-Following_with_Adaptive_Portfolio_Construction_Enhancing_Risk-Adjusted_Alpha_in_Cryptocurrency_Markets&lt;/li&gt;
&lt;li&gt;[2602.11708] Systematic Trend-Following with Adaptive Portfolio Construction: Enhancing Risk-Adjusted Alpha in Cryptocurrency Markets - arXiv, https://arxiv.org/abs/2602.11708&lt;/li&gt;
&lt;li&gt;Optimizing Crypto-Trading Performance: A Comparative Analysis of Innovative Reward Functions in Reinforcement Learning Models - MDPI, https://www.mdpi.com/2227-7390/14/5/794&lt;/li&gt;
&lt;li&gt;Exploiting the momentum effect in the cryptocurrency market: A machine learning-based trading system - WebThesis - Politecnico di Torino, https://webthesis.biblio.polito.it/15855/1/tesi.pdf&lt;/li&gt;
&lt;li&gt;The Impact of Fees on Cryptocurrency Trading, https://axon.trade/the-impact-of-fees-on-cryptocurrency-trading&lt;/li&gt;
&lt;li&gt;Beyond the Spread: Understanding Market Impact and Execution - Amberdata Blog, https://blog.amberdata.io/beyond-the-spread-understanding-market-impact-and-execution&lt;/li&gt;
&lt;li&gt;Knowledge: Understanding Market Impact in Crypto Trading: The ..., https://www.talos.com/insights/understanding-market-impact-in-crypto-trading-the-talos-model-for-estimating-execution-costs 44. The Rhythm of Liquidity: Temporal Patterns in Market Depth - Amberdata Blog, https://blog.amberdata.io/the-rhythm-of-liquidity-temporal-patterns-in-market-depth 45. Is the Future of Crypto Perpetual? The Meteoric Rise of Perp DEXs ..., https://www.coingecko.com/learn/rise-of-perpetuals-and-perp-dexs 46. Designing funding rates for perpetual futures in cryptocurrency markets - arXiv, https://arxiv.org/html/2506.08573v1 47. Fundamentals of Perpetual FuturesWe are grateful to Lin William Cong, Urban Jermann, Shimon Kogan, Tim Roughgarden, Adrien Verdelhan, as well as conference participants at the 2024 Utah Winter Finance Conference and seminar participants at a16z Crypto, Hebrew University, Reichman University, and the Virtual Derivatives Workshop for their insightful feedback and helpful comments. Songrun He - arXiv, https://arxiv.org/html/2212.06888v5 48. Understanding Funding Rates in Perpetual Futures and Their Impact - Coinbase, https://www.coinbase.com/learn/perpetual-futures/understanding-funding-rates-in-perpetual-futures 49. Perpetual Futures Pricing*, https://finance.wharton.upenn.edu/~jermann/AHJ-main-10.pdf 50. Funding Rate Mechanism in Perpetual Futures - ResearchGate, https://www.researchgate.net/publication/401892113_Funding_Rate_Mechanism_in_Perpetual_Futures 51. Understanding the Impact of Funding Rates on Crypto Trading Strategies - Binance, https://www.binance.com/en/square/post/21109658126010 52. Trading Insights - Richey May, https://richeymay.com/wp-content/uploads/2024/07/MktIntel_2024.06.10_Perps-1.pdf 53. Crypto in 2026: From Speculation to Financial Infrastructure - AMINA Bank, https://aminagroup.com/research/2026-outlook-institutional-adoption-regulation-and-market-structure/ 54. 2026 Digital Asset Outlook: Dawn of the Institutional Era - Grayscale Research, https://research.grayscale.com/reports/2026-digital-asset-outlook-dawn-of-the-institutional-era 55. Crypto Exits Surge in 2025: Momentum Builds for an Even Bigger 2026 | Foley &amp;amp; Lardner, https://www.foley.com/insights/publications/2026/01/crypto-exits-surge-in-2025-momentum-builds-for-an-even-bigger-2026/ 5&lt;/li&gt;
&lt;li&gt;How Perpetual DEXs Differ From Centralized Exchanges — and What Traders Should Know, https://www.ccn.com/education/crypto/perpetual-dexs-hyperliquid-aster-explained-1000x-leverage-risks/&lt;/li&gt;
&lt;li&gt;Hyperliquid 2025 H1 Panorama Report: The Secret Behind 73 ..., https://www.binance.com/en/square/post/28475999246162&lt;/li&gt;
&lt;li&gt;The Anatomy of Hyperliquid&#39;s Growth: From MVP to Hype - Medium, https://medium.com/@julia_innovator/the-anatomy-of-hyperliquids-growth-from-mvp-to-hype-a0a4a3bc26ec&lt;/li&gt;
&lt;li&gt;North America Crypto Adoption: Institutions and ETFs - Chainalysis, https://www.chainalysis.com/blog/north-america-crypto-adoption-2025/&lt;/li&gt;
&lt;li&gt;2025 Institutional Investor Digital Assets Survey, https://www.ey.com/content/dam/ey-unified-site/ey-com/en-us/insights/financial-services/documents/ey-growing-enthusiasm-propels-digital-assets-into-the-mainstream.pdf&lt;/li&gt;
&lt;li&gt;Future of crypto: 5 crypto predictions for 2026 - Silicon Valley Bank, https://www.svb.com/industry-insights/fintech/2026-crypto-outlook/&lt;/li&gt;
&lt;li&gt;Why bitcoin institutional demand is on the rise - State Street Global Advisors, https://www.ssga.com/us/en/institutional/insights/why-bitcoin-institutional-demand-is-on-the-rise&lt;/li&gt;
&lt;li&gt;Crypto Insights | October 2025 - CME Group, https://www.cmegroup.com/newsletters/quarterly-cryptocurrencies-report/2025-october-cryptocurrency-insights.html&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2026-W14]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Drupal with Varnish caching and HTTPS using Nginx and Let&#39;s Encrypt</title>
    <link href="https://stephencox.net/writing/drupal-with-varnish-caching-and-https-using-nginx-and-lets-encrypt/" />
    <updated>2026-03-11T00:00:00Z</updated>
    <published>2018-10-11T00:00:00Z</published>
    <id>https://stephencox.net/writing/drupal-with-varnish-caching-and-https-using-nginx-and-lets-encrypt/</id>
    <summary>Varnish is great at serving pages to anonymous users at high speed, but it doesn&#39;t speak HTTPS so if you want to use Varnish and provide your site over HTTPS then you need to use something to do HTTPS and proxy the traffic to Varnish. In this blog post I will detail one way to do this by using Nginx to do HTTPS termination and proxy the requests to Varnish.</summary>
    <content type="html">&lt;p&gt;Varnish is great at serving pages to anonymous users at high speed, but it doesn&#39;t speak HTTPS so if you want to use Varnish and provide your site over HTTPS then you need to use something to do HTTPS and proxy the traffic to Varnish. In this blog post I will detail one way to do this by using Nginx to do HTTPS termination and proxy the requests to Varnish.&lt;/p&gt;
&lt;h2&gt;Server overview&lt;/h2&gt;
&lt;p&gt;In the following setup Varnish listens for HTTP requests on port 80. Apache with mod_php handles the Drupal stuff, listening on port 8080. Varnish proxy requests from port 80 to Apache on port 8080. To handle HTTPS, Nginx listens on port 443 and proxies requests to Varnish on port 80. Let&#39;s Encrypt provides a free SSL certificate for use by Nginx.&lt;/p&gt;
&lt;p&gt;The following commands work on Ubuntu 18.04. The configuration will generally work for different versions of Ubuntu or Debian, although the versions of some software packages will vary; PHP and Varnish in particular have changed from previous long term support versions of Ubuntu.&lt;/p&gt;
&lt;h2&gt;Apache setup&lt;/h2&gt;
&lt;p&gt;We start by installing Apache and PHP and configuring Apache to listen on port 8080.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-y&lt;/span&gt; apache2 apache2-utils php7.2 php7.2-cli php7.2-common php7.2-curl php7.2-json php7.2-gd php7.2-mysql php7.2-opcache php7.2-xml libapache2-mod-php7.2
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; a2enmod expires headers rewrite php7.2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create an Apache virtual host file in /etc/apache2/sites-available/example.conf&lt;/p&gt;
&lt;pre class=&quot;language-apacheconf&quot; tabindex=&quot;0&quot; data-language=&quot;apacheconf&quot;&gt;&lt;code class=&quot;language-apacheconf&quot;&gt;&lt;span class=&quot;token directive-block tag&quot;&gt;&lt;span class=&quot;token directive-block tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;token directive-block-parameter attr-value&quot;&gt; *&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token directive-inline property&quot;&gt;ServerName&lt;/span&gt; &lt;span class=&quot;token directive-inline property&quot;&gt;example&lt;/span&gt;.com
    &lt;span class=&quot;token directive-inline property&quot;&gt;ServerAdmin&lt;/span&gt; support@example.com
    &lt;span class=&quot;token directive-inline property&quot;&gt;DocumentRoot&lt;/span&gt; /var/www/html

    &lt;span class=&quot;token directive-inline property&quot;&gt;ErrorLog&lt;/span&gt; /var/log/apache2/example-error.log
    &lt;span class=&quot;token directive-inline property&quot;&gt;CustomLog&lt;/span&gt; /var/log/apache2/example-access.log combined

    &lt;span class=&quot;token directive-block tag&quot;&gt;&lt;span class=&quot;token directive-block tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Directory&lt;/span&gt;&lt;span class=&quot;token directive-block-parameter attr-value&quot;&gt; /var/www/html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token directive-inline property&quot;&gt;Allow&lt;/span&gt; from all
        &lt;span class=&quot;token directive-inline property&quot;&gt;Options&lt;/span&gt; +Includes -Indexes +FollowSymLinks
        &lt;span class=&quot;token directive-inline property&quot;&gt;AllowOverride&lt;/span&gt; all
    &lt;span class=&quot;token directive-block tag&quot;&gt;&lt;span class=&quot;token directive-block tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Directory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token directive-block tag&quot;&gt;&lt;span class=&quot;token directive-block tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit the /etc/apache2/ports.conf so that it contains&lt;/p&gt;
&lt;pre class=&quot;language-apacheconf&quot; tabindex=&quot;0&quot; data-language=&quot;apacheconf&quot;&gt;&lt;code class=&quot;language-apacheconf&quot;&gt;&lt;span class=&quot;token directive-inline property&quot;&gt;Listen&lt;/span&gt; 8080&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then reconfigure Apache&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; a2ensite example.conf
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; systemctl restart apache2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Assuming Drupal is installed in /var/www/html, then it will be available at http://example.com:8080/.&lt;/p&gt;
&lt;h2&gt;Varnish setup&lt;/h2&gt;
&lt;p&gt;We now install Varnish and configure it to handle HTTP requests on port 80.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-y&lt;/span&gt; varnish&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the varnish software package isn&#39;t found then you will need to enable the Ubuntu universe repository.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; add-apt-repository universe&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a file called /etc/systemd/system/varnish.service with the following content; the arguments for varnishd can be tweaked according to your requirements.&lt;/p&gt;
&lt;pre class=&quot;language-ini&quot; tabindex=&quot;0&quot; data-language=&quot;ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token section&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;Varnish HTTP accelerator&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;Documentation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;https://www.varnish-cache.org/docs/5.2/ man:varnishd&lt;/span&gt;

&lt;span class=&quot;token section&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;Service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;simple&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;LimitNOFILE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;131072&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;LimitMEMLOCK&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;82000&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;ExecStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;/usr/sbin/varnishd -j unix,user=vcache -F -a :80 -T :6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m -p vcc_allow_inline_c=on&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;ExecReload&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;/usr/share/varnish/reload-vcl&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;ProtectSystem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;full&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;ProtectHome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;PrivateTmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;PrivateDevices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;token section&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;Install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;WantedBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;multi-user.target&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit the /etc/varnish/default.vcl file for your specific requirements. The key thing is to add a backend that points to port 8080, like:&lt;/p&gt;
&lt;pre class=&quot;language-nginx&quot; tabindex=&quot;0&quot; data-language=&quot;nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Default backend definition. Points to Apache on port 8080.&lt;/span&gt;
&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;backend&lt;/span&gt; default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  .host = &quot;127.0.0.1&quot;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  .port = &quot;8080&quot;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  .first_byte_timeout     = &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;300s&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  .connect_timeout        = &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;5s&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  .between_bytes_timeout  = &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;2s&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An example Varnish 5 configuration file for Drupal can be seen here: https://gitlab.agile.coop/snippets/27&lt;/p&gt;
&lt;p&gt;Then reconfigure varnish&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; systemctl daemon-reload
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; systemctl restart varnish.service&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The site will now be cached by Varnish and be available at http://example.com/.&lt;/p&gt;
&lt;h2&gt;Let&#39;s Encrypt setup&lt;/h2&gt;
&lt;p&gt;For HTTPS to work properly we need a SSL certificate. For this we can use &lt;a href=&quot;https://certbot.eff.org/&quot;&gt;certbot&lt;/a&gt; to get a certificate from Let&#39;s Encrypt using the webroot plugin.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-y&lt;/span&gt; certbot
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; certbot &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; suport@example.com --agree-tos &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; certonly &lt;span class=&quot;token parameter variable&quot;&gt;--webroot&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-w&lt;/span&gt; /var/www/html &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; example.com&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a very simple example, but you can use the webroot plugin with as many domains as required and with more sites by specifying extra -w and -d options. One thing to note is that the DNS must be in place for this to work, each domain will be checked so if a domain doesn&#39;t resolve to the server&#39;s IP address then the command will fail. More information on the webroot plugin can be found here: https://certbot.eff.org/docs/using.html#webroot&lt;/p&gt;
&lt;h2&gt;Nginx setup&lt;/h2&gt;
&lt;p&gt;Now we have a SSL certificate we can install and configure Nginx to handle HTTPS requests on port 443.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-y&lt;/span&gt; nginx
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; /etc/nginx/sites-enabled/default&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a Nginx configuration file to proxy HTTPS requests to Varnish at /etc/nginx/sites-available/https-proxy with the following configuration&lt;/p&gt;
&lt;pre class=&quot;language-nginx&quot; tabindex=&quot;0&quot; data-language=&quot;nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Proxy all HTTPS requests to Varnish&lt;/span&gt;
&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt; ssl default_server&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ssl&lt;/span&gt;  &lt;span class=&quot;token boolean&quot;&gt;on&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ssl_certificate&lt;/span&gt;     /etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ssl_certificate_key&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;client_max_body_size&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;64M&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;location&lt;/span&gt; /&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;proxy_pass&lt;/span&gt;       http://127.0.0.1:80/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;proxy_redirect&lt;/span&gt;   &lt;span class=&quot;token boolean&quot;&gt;off&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;proxy_set_header&lt;/span&gt; Host &lt;span class=&quot;token variable&quot;&gt;$host&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;proxy_set_header&lt;/span&gt; X-Real-IP &lt;span class=&quot;token variable&quot;&gt;$remote_addr&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;proxy_set_header&lt;/span&gt; X-Forwarded-For &lt;span class=&quot;token variable&quot;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;proxy_set_header&lt;/span&gt; X-Forwarded-Proto https&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;proxy_set_header&lt;/span&gt; X-Forwarded-Port &lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then reconfigure nginx&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; /etc/nginx/sites-available/https-proxy /etc/nginx/sites-enabled/
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; systemctl restart nginx.service&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The site will now be available at https://example.com/&lt;/p&gt;
&lt;h2&gt;Drupal configuration&lt;/h2&gt;
&lt;p&gt;The site is now available using HTTPS and is being cached by Varnish. There are a few configuration bits and pieces that Drupal needs. One is to enable and and configure the Drupal 8 &lt;a href=&quot;https://www.drupal.org/project/purge&quot;&gt;Purge&lt;/a&gt; and &lt;a href=&quot;https://www.drupal.org/project/varnish_purge&quot;&gt;Varnish purger&lt;/a&gt; modules. For Drupal 7 there is the &lt;a href=&quot;https://www.drupal.org/project/varnish&quot;&gt;Varnish&lt;/a&gt; module.&lt;/p&gt;
&lt;p&gt;Drupal also needs to be told it&#39;s behind a reverse proxy. For Drupal 8 add the following to the site&#39;s settings.php or settings.local.php file.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot; tabindex=&quot;0&quot; data-language=&quot;php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;reverse_proxy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;reverse_proxy_addresses&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;127.0.0.1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTPS&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;on&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTP_X_FORWARDED_PROTO&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;$_SERVER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTPS&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;on&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;$_SERVER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;SERVER_PORT&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Drupal 7 the configuration is&lt;/p&gt;
&lt;pre class=&quot;language-php&quot; tabindex=&quot;0&quot; data-language=&quot;php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$conf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;reverse_proxy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$conf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;reverse_proxy_addresses&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;127.0.0.1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTPS&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;on&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTP_X_FORWARDED_PROTO&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;$_SERVER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;HTTPS&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;on&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;$_SERVER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;SERVER_PORT&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, for maximum security, all HTTP traffic should be redirected to HTTPS by adding the following to the site&#39;s .htaccess file after the &lt;code&gt;RewriteEngine on&lt;/code&gt; line.&lt;/p&gt;
&lt;pre class=&quot;language-apacheconf&quot; tabindex=&quot;0&quot; data-language=&quot;apacheconf&quot;&gt;&lt;code class=&quot;language-apacheconf&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Redirect HTTP to HTTPS&lt;/span&gt;
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{HTTPS}&lt;/span&gt; off
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{HTTP:X-Forwarded-Proto}&lt;/span&gt; !https
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteRule&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt; ^(.*)$&lt;/span&gt; https://&lt;span class=&quot;token variable&quot;&gt;%{HTTP_HOST}&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;%{REQUEST_URI}&lt;/span&gt; &lt;span class=&quot;token directive-flags keyword&quot;&gt;[L,R=301]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>Opencode Agents</title>
    <link href="https://stephencox.net/projects/opencode-agents/" />
    <updated>2026-03-06T00:00:00Z</updated>
    <published>2026-02-02T00:00:00Z</published>
    <id>https://stephencox.net/projects/opencode-agents/</id>
    <summary>Opencode agents for the Explore - Plan - Code - Verify workflow</summary>
    <content type="html">&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2026-W06]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Guide to coding with AI assistants</title>
    <link href="https://stephencox.net/writing/guide-to-coding-with-ai-assistants/" />
    <updated>2026-03-06T00:00:00Z</updated>
    <published>2025-12-27T00:00:00Z</published>
    <id>https://stephencox.net/writing/guide-to-coding-with-ai-assistants/</id>
    <summary>Detailed plan for blog post covering AI-assisted development workflow and common failure modes.</summary>
    <content type="html">&lt;h1&gt;AI-Assisted Development: Blog Post Plan&lt;/h1&gt;
&lt;h2&gt;1) The enthusiastic junior developer, and why it matters (180–220 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open with the analogy: fast, keen, broad knowledge, weak project-specific understanding, confident tone.&lt;/li&gt;
&lt;li&gt;Make the central claim: used well, AI can speed up delivery of routine engineering work, but it does not replace judgement.&lt;/li&gt;
&lt;li&gt;State the practical implication: humans own scope, risk, review, and verification.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2) What this post covers: a workflow that makes speed safe (120–160 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introduce the Explore – Plan – Code – Verify loop as a lightweight control system around AI output.&lt;/li&gt;
&lt;li&gt;Highlight the key technique: break work into atomic tasks with acceptance criteria, a definition of done, and manual tests where appropriate.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3) Failure modes: why a workflow is required (220–280 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hallucinated or outdated APIs, flags, configuration, and framework behaviour.&lt;/li&gt;
&lt;li&gt;Scope creep: “helpful” refactors, formatting churn, renames, or dependency additions unrelated to the task.&lt;/li&gt;
&lt;li&gt;Correct-looking code that misses edge cases, non-functional requirements, or integration boundaries.&lt;/li&gt;
&lt;li&gt;Tests that pass but do not assert the intended behaviour.&lt;/li&gt;
&lt;li&gt;Getting stuck in a bug-fixing loop: repeated patches without new information or a change in approach.&lt;/li&gt;
&lt;li&gt;Transition: these are predictable, which is why a workflow and gates matter.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4) Workflow overview: Explore – Plan – Code – Verify (120–160 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Explain each phase in one paragraph: what it does and what it produces.&lt;/li&gt;
&lt;li&gt;Emphasise the rule: do not write code until verification is clear.&lt;/li&gt;
&lt;li&gt;Explain cadence: the loop runs per atomic task and typically maps to a PR-sized change.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5) Explore: reduce ambiguity and confirm constraints (220–280 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Inputs to gather: problem statement, expected behaviour, constraints (versions, environments, deployment), and relevant code paths.&lt;/li&gt;
&lt;li&gt;Outputs to produce: clarified requirements, options and trade-offs, risks, unknowns to confirm.&lt;/li&gt;
&lt;li&gt;Identify “stop and clarify” triggers: unclear requirements, data migrations, authZ boundaries, external API uncertainty, performance implications.&lt;/li&gt;
&lt;li&gt;Aim for minimal-change thinking: prefer the smallest correct intervention.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;6) Plan: atomic tasks with acceptance criteria and definition of done (300–360 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Define atomic in operational terms: independently verifiable, revertible, and small enough to review confidently.&lt;/li&gt;
&lt;li&gt;Describe a task card format:
&lt;ul&gt;
&lt;li&gt;Scope and non-goals&lt;/li&gt;
&lt;li&gt;Acceptance criteria&lt;/li&gt;
&lt;li&gt;Definition of done&lt;/li&gt;
&lt;li&gt;Automated tests to add or update&lt;/li&gt;
&lt;li&gt;Manual test steps&lt;/li&gt;
&lt;li&gt;Rollback note&lt;/li&gt;
&lt;li&gt;Risk level&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Explain planning depth: fully detail the next milestone, keep later milestones coarse (agile planning).&lt;/li&gt;
&lt;li&gt;Add guardrails: a “do not touch” list, dependency limits, and explicit avoidance of drive-by refactors.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;7) Code: implement the task, but supervise the assistant (150–200 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep the Code step plain: implement one planned task at a time.&lt;/li&gt;
&lt;li&gt;Supervise output for scope creep: unrelated refactors, new dependencies, broad renames, or style churn.&lt;/li&gt;
&lt;li&gt;Watch for bug-fixing loops; when stuck, return to Explore (new evidence, new hypothesis) rather than iterating blindly.&lt;/li&gt;
&lt;li&gt;Keep changes reviewable: minimal diff, readable commits, tests included with the change.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;8) Verify: layered checks that earn trust (300–360 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automated checks: unit and integration tests, linting, type checks, build steps.&lt;/li&gt;
&lt;li&gt;Behavioural checks: manual test script, edge cases, failure paths, cross-browser or device where relevant.&lt;/li&gt;
&lt;li&gt;Operational checks: error handling, logging, metrics, configuration, migrations and rollbacks.&lt;/li&gt;
&lt;li&gt;Security checks: input validation, output encoding, authZ, secrets and logging hygiene, dependency scrutiny.&lt;/li&gt;
&lt;li&gt;Include a compact checklist and tie verification effort to task size and risk.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;9) Context management: control what the assistant sees and assumes (200–260 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Explain why context is a first-class dependency: low-quality context produces plausible nonsense.&lt;/li&gt;
&lt;li&gt;Recommend a task brief per atomic task: scope, constraints, non-goals, relevant files, commands to run, versions.&lt;/li&gt;
&lt;li&gt;Encourage explicit assumptions: keep an “assumptions and decisions” note in the PR or task.&lt;/li&gt;
&lt;li&gt;Mention repo guidance files (for example AGENTS.md or CLAUDE.md): coding standards, commands, boundaries, and review expectations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;10) Scaling the workflow: bugfix vs feature vs project (180–230 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bugfix: short Explore and Plan, strict Verify, tiny PRs; avoid broad refactors.&lt;/li&gt;
&lt;li&gt;Feature: more Explore and Plan, staged delivery, feature flags where appropriate, more manual testing and stakeholder checks.&lt;/li&gt;
&lt;li&gt;Project: discovery spikes, architectural decision records, migration and rollout planning, stronger review and verification gates.&lt;/li&gt;
&lt;li&gt;Emphasise invariants: atomicity, explicit verification, and human review do not go away.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;11) Conclusion: speed with a human in the loop (120–160 words)&lt;/h2&gt;
&lt;p&gt;Cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reinforce the core idea: AI increases throughput, but it does not change accountability.&lt;/li&gt;
&lt;li&gt;Summarise the practical recipe: atomic tasks + explicit verification + rigorous review.&lt;/li&gt;
&lt;li&gt;State the non-negotiable: a human in the loop for requirements, boundaries, code review, and final verification.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;Everyone and their dog are now using AI coding assistants to vibe code apps and websites, the vast majority of these are not going to make it off their local computers. Given a chance, AI coding assistants will happily write hundreds or thousands of lines of code. This code will be full of bugs and hallucinations. They are like a junior developer with too much knowledge who wants to impress you by showing how many lines of code they can produce. Having the assistant write tests will catch many of these issues, but bugs will remain; finding them all will take time and while debugging them you will likely find serious structural issues that will mean refactoring large sections of the code. To prevent this sort of thing we need to follow good software engineering principles and by constraining the AI assistant we can make it write better code in a more predictable way.&lt;/p&gt;
&lt;p&gt;By following a workflow that ensures the changes required are broken into fully specified atomic tasks with acceptance criteria and tests and each task is verified by a human before the next task is implemented, we help ensure that the code produced is of a high quality.&lt;/p&gt;
&lt;h2&gt;Explore → plan → code → verify&lt;/h2&gt;
&lt;p&gt;This is a highly successful workflow for constraining an AI coding assistant and having it produce high quality code. With some tweaks, it can be applied to coding tasks of all sizes from small bug fixes, through new features in existing projects to entirely new projects.&lt;/p&gt;
&lt;p&gt;In the explore phase you work with the AI to investigate possible solutions. When planning you take the best solution from the explore phase and break it down into phases/milestones and tasks. The code phase implements a single task, which is then verified to ensure it meets acceptance criteria and definition of done specified in the planning phase.&lt;/p&gt;
&lt;p&gt;The key to the whole workflow is breaking things into atomic tasks.&lt;/p&gt;
&lt;pre class=&quot;language-mermaid&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code class=&quot;language-mermaid&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;flowchart&lt;/span&gt; TB
    A&lt;span class=&quot;token text string&quot;&gt;([&quot;Bug, feature or project&quot;])&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; B&lt;span class=&quot;token text string&quot;&gt;[&quot;**Explore**&quot;]&lt;/span&gt;
    B &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; C&lt;span class=&quot;token text string&quot;&gt;[&quot;Accepted solution&quot;]&lt;/span&gt;
    C &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; D&lt;span class=&quot;token text string&quot;&gt;[&quot;**Plan**&quot;]&lt;/span&gt;
    D &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; E1[&quot;Phase breakdown
    &lt;span class=&quot;token text string&quot;&gt;(for larger pieces of work)&lt;/span&gt;&quot;]
    E1 &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; E2[&quot;Task specification
    &lt;span class=&quot;token text string&quot;&gt;(for current phase)&lt;/span&gt;&quot;]
    E2 &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; F&lt;span class=&quot;token text string&quot;&gt;[&quot;**Code**&quot;]&lt;/span&gt;
    F &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; G&lt;span class=&quot;token text string&quot;&gt;[&quot;Code changes&quot;]&lt;/span&gt;
    G &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; H&lt;span class=&quot;token text string&quot;&gt;[&quot;**Verify**&quot;]&lt;/span&gt;
    H &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; I&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&quot;Acceptance 
    criteria met?&quot;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    I &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;No&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; F
    I &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;Yes&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; J&lt;span class=&quot;token text string&quot;&gt;[&quot;Commit changes&quot;]&lt;/span&gt;
    J &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt; K&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&quot;Are there 
    more tasks?&quot;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    K &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;No&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; L&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&quot;Are there 
    more phases?&quot;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    K &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;Yes&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; F
    L &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;No&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; M&lt;span class=&quot;token text string&quot;&gt;([&quot;Complete&quot;])&lt;/span&gt;
    L &lt;span class=&quot;token inter-arrow-label&quot;&gt;&lt;span class=&quot;token arrow-head arrow operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token label property&quot;&gt;Yes&lt;/span&gt; &lt;span class=&quot;token arrow operator&quot;&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt; D

    C@&lt;span class=&quot;token text string&quot;&gt;{ shape: lean-r}&lt;/span&gt;
    E1@&lt;span class=&quot;token text string&quot;&gt;{ shape: lean-r}&lt;/span&gt;
    E2@&lt;span class=&quot;token text string&quot;&gt;{ shape: lean-r}&lt;/span&gt;
    G@&lt;span class=&quot;token text string&quot;&gt;{ shape: lean-r}&lt;/span&gt;
    J@&lt;span class=&quot;token text string&quot;&gt;{ shape: trap-t}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Explore&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Provide a prompt describing the issue or feature using as much detail as possible and&lt;/li&gt;
&lt;li&gt;Define acceptance criteria&lt;/li&gt;
&lt;li&gt;Pass relevant files and messages to the assistant and&lt;/li&gt;
&lt;li&gt;Use an AGENTS.md file for site&lt;/li&gt;
&lt;li&gt;For bug fixes you can ask the assistant to create a test that fails due to the bug.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Plan&lt;/h3&gt;
&lt;p&gt;Before the assistant changes any files have list what it&#39;s going to do.
Critique this plan closely. Ask if there are alternatives ways to achieve the same goal.
If you don&#39;t understand why something is being done in a particular way ask it to explain it.
Ensure things are broken down into atomic tasks with thier own tests and acceptance criteria
For bigger bits of work have it save the plan so it can be referred back to in new seasons&lt;/p&gt;
&lt;h3&gt;Code&lt;/h3&gt;
&lt;p&gt;Tell the assistant to implement a single task with accompanying tests.&lt;/p&gt;
&lt;h3&gt;Verify&lt;/h3&gt;
&lt;p&gt;This is the most important part.
Go through the code line by line, ensuring you understand what&#39;s going on. If you don&#39;t understand why something has been done in a particular way ask about it.&lt;/p&gt;
&lt;p&gt;Git diffs are good for this, but it can be easier to use a merge request for the review.
Check the tests are actually testing for the things you want.
Ensure all automatic tests and linting checks pass.
Manually test the changes to ensure you&#39;re happy with the way they work
Using a separate ai agent to evaluate the changes can be good, but everything also needs to be manually verified as well.&lt;/p&gt;
&lt;p&gt;Once you&#39;re happy the task ensure all the changes have been committed and move on to the next ta&lt;/p&gt;
&lt;h3&gt;Adjusting for size of the job&lt;/h3&gt;
&lt;p&gt;As&lt;/p&gt;
&lt;h2&gt;Best practices&lt;/h2&gt;
&lt;h3&gt;Treat AI coding assistants as very enthusiastic junior developers who have a tendency to get carried away&lt;/h3&gt;
&lt;p&gt;AI assistants are eager, fast, and have broad knowledge, but they lack context about your specific codebase, business logic and the consequences of their suggestions. Assume it will confidently do the wrong thing unless constrained. You need to set boundaries, define done and verify.&lt;/p&gt;
&lt;h3&gt;Keep tasks small and atomic&lt;/h3&gt;
&lt;p&gt;The single most important practice is constraining scope. Each task should be the smallest viable change that is independently testable, reviewable, and deployable.  Chunks of work larger than this should be broken down into a series of tasks. Once a task has been manually verified, commit the changes and move on to the next one.&lt;/p&gt;
&lt;h2&gt;Use an explore, plan, code, verify workflow&lt;/h2&gt;
&lt;p&gt;While the details will change depending on the size of what you&#39;re trying to achieve, the core workflow remains the same.&lt;/p&gt;
&lt;p&gt;Each step will involve a dialogue with the assistant as you refine the outputs until you&#39;re happy with them.&lt;/p&gt;
&lt;h2&gt;Define acceptance criteria before you ask for code&lt;/h2&gt;
&lt;h2&gt;Make the AI propose a plan before it writes code&lt;/h2&gt;
&lt;h2&gt;Verify with diffs and merge requests&lt;/h2&gt;
&lt;h2&gt;Provide Rich Context&lt;/h2&gt;
&lt;p&gt;AI assistants don&#39;t know your coding standards, your team&#39;s conventions, or why that seemingly redundant validation exists. Before asking for code, briefly explain the context: what the code needs to do, what constraints exist, what patterns you&#39;re already using. &amp;quot;We&#39;re using dependency injection throughout this project&amp;quot; or &amp;quot;this needs to work with PHP 8.1&amp;quot; saves a lot of back-and-forth.&lt;/p&gt;
&lt;h2&gt;Use an AGENTS.md file to provide information about the project and the tools and standards used&lt;/h2&gt;
&lt;p&gt;Symlink AGENTS.md to CALUDE.md so the same file can be used by Claude Code and other AI agents.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W52]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Processing CSS and JavaScript in Eleventy</title>
    <link href="https://stephencox.net/writing/processing-css-and-javascript-in-eleventy/" />
    <updated>2026-03-06T00:00:00Z</updated>
    <published>2025-11-09T00:00:00Z</published>
    <id>https://stephencox.net/writing/processing-css-and-javascript-in-eleventy/</id>
    <summary>Explore Eleventy’s minimal asset pipeline: CSS &amp; JS handling passthrough copy, Bundle plugin, Vite integration, Template Asset Pipeline for optimized builds.</summary>
    <content type="html">&lt;p&gt;Eleventy’s philosophy of minimalism is both its strength and its challenge. It gives you full control over how to build your site but leaves most decisions up to you. Nowhere is this clearer than in how you handle CSS and JavaScript. Eleventy doesn’t prescribe a build pipeline; it simply exposes a few hooks and leaves you to decide how much structure you want.&lt;/p&gt;
&lt;p&gt;Over time, developers have filled that gap in a variety of ways. Some prefer to let Eleventy do almost nothing beyond copying files. Others layer in full build systems like Gulp or Vite. Between those extremes lies a spectrum of approaches, each offering a different balance of simplicity, performance, and integration.&lt;/p&gt;
&lt;p&gt;This piece walks through that spectrum, explaining where each approach fits. It ends with the &lt;a href=&quot;https://github.com/stephen-cox/eleventy-template-asset-pipeline&quot;&gt;Template Asset Pipeline plugin&lt;/a&gt; – a project inspired by &lt;a href=&quot;https://mxb.dev/blog/eleventy-asset-pipeline/&quot;&gt;Max Böck’s Eleventy Asset Pipeline&lt;/a&gt; – which aims to integrate traditional asset workflows into Eleventy’s build system without resorting to a separate toolchain.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Spectrum of Approaches&lt;/h2&gt;
&lt;p&gt;Asset handling in Eleventy runs from “copy everything as-is” to “delegate everything to a dedicated bundler.” Each step along that line trades simplicity for sophistication.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;1. Passthrough Copy&lt;/h3&gt;
&lt;p&gt;The simplest case is to do nothing at all. You tell Eleventy to copy your CSS and JS files directly into the output folder, untouched. This is enough for small projects or when you’re already writing browser-ready code. It builds instantly and has no dependencies, but you lose out on minification, bundling, and cache busting.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.11ty.dev/docs/copy/&quot;&gt;Eleventy’s documentation on Passthrough Copy&lt;/a&gt; explains how to configure it.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;2. External Build Tools&lt;/h3&gt;
&lt;p&gt;Many developers reach for external tools like Gulp, npm scripts, or esbuild. These run in parallel with Eleventy rather than through it. They suit teams who already have established pipelines or want to share the same asset setup across projects.&lt;/p&gt;
&lt;p&gt;The main advantage is flexibility – you can use any tool that runs in Node. The downside is coordination. You end up juggling multiple processes, and if one fails or finishes late, the others don’t always know.&lt;/p&gt;
&lt;p&gt;Resources worth reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mxb.dev/blog/eleventy-asset-pipeline/&quot;&gt;Asset Pipelines in Eleventy – Max Böck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.webstoemp.com/blog/eleventy-dev-server-external-asset-pipeline/&quot;&gt;External Asset Pipeline – Webstoemp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;3. Custom Template Types&lt;/h3&gt;
&lt;p&gt;A more integrated approach is to teach Eleventy how to process CSS or JS directly by adding new template types. For example, you can register &lt;code&gt;.scss&lt;/code&gt; as a format and run each file through Sass when Eleventy builds.&lt;/p&gt;
&lt;p&gt;This brings asset compilation inside Eleventy’s lifecycle, so changes trigger automatic rebuilds and dependency tracking. It’s elegant once set up, but it requires familiarity with Eleventy’s internals and its data cascade.&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&quot;https://www.11ty.dev/docs/assets/&quot;&gt;Eleventy documentation on custom template types&lt;/a&gt; for examples.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;4. The Bundle Plugin&lt;/h3&gt;
&lt;p&gt;From version 3 onwards, Eleventy introduced the official &lt;a href=&quot;https://www.11ty.dev/docs/plugins/bundle/&quot;&gt;Bundle plugin&lt;/a&gt;. It collects snippets of CSS and JS defined throughout your templates, combines them into bundles, and injects them into the rendered pages.&lt;/p&gt;
&lt;p&gt;It’s particularly effective for component-based architectures or when using WebC, where each component might define its own styles. Bundling happens per page, giving you only the assets you need. The trade-off is that it’s not meant for processing entire files or running through preprocessors – it’s about aggregation, not transformation.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;5. Vite Integration&lt;/h3&gt;
&lt;p&gt;At the other end of the spectrum is &lt;a href=&quot;https://www.11ty.dev/docs/server-vite/&quot;&gt;Eleventy’s Vite plugin&lt;/a&gt;, which brings a full modern bundler and development server into the mix. You get hot module replacement, TypeScript and JSX support, and the full Vite plugin ecosystem.&lt;/p&gt;
&lt;p&gt;It’s ideal for complex or app-like projects but can feel heavy for simple static sites. Build times increase, and configuration becomes more involved. Still, for teams already using Vite elsewhere, it offers the smoothest developer experience.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Template Asset Pipeline Plugin&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/stephen-cox/eleventy-template-asset-pipeline&quot;&gt;Template Asset Pipeline plugin&lt;/a&gt; sits comfortably between these worlds. It was inspired by &lt;a href=&quot;https://mxb.dev/blog/eleventy-asset-pipeline/&quot;&gt;Max Böck’s original article on integrating asset processing into Eleventy&lt;/a&gt;, but it builds on the idea by using Eleventy’s own JavaScript template system to process assets as part of the normal build.&lt;/p&gt;
&lt;p&gt;The idea is straightforward: treat CSS and JS files like templates. Instead of running a separate build tool, you register processors inside Eleventy itself. These processors can call PostCSS, Sass, esbuild, Webpack, or any other Node-based transformer, but they do so within Eleventy’s dependency graph. That means assets rebuild only when their sources change, and everything happens through a single &lt;code&gt;eleventy&lt;/code&gt; command.&lt;/p&gt;
&lt;h3&gt;How It Works&lt;/h3&gt;
&lt;p&gt;When the plugin runs, it scans your source directories for asset files. Each file is passed to a processing function you define – for example, one that compiles Sass or runs PostCSS with plugins like Autoprefixer and cssnano. The results are written to your output folder and added to an Eleventy collection, so you can loop through them in templates or output links automatically.&lt;/p&gt;
&lt;p&gt;Because the assets are handled as Eleventy templates, dependency tracking and rebuilds happen automatically. In production mode, you can minify or optimise; in development, you can skip those steps for faster feedback. It’s a familiar workflow, just unified under Eleventy’s build system.&lt;/p&gt;
&lt;h3&gt;Why It’s Useful&lt;/h3&gt;
&lt;p&gt;The plugin works well when you have existing asset files and want them processed inside Eleventy rather than through external scripts. It’s flexible enough to handle both CSS and JS, supports multiple processors, and reduces the overhead of coordinating parallel build tasks.&lt;/p&gt;
&lt;p&gt;In practice, it replaces a web of npm scripts and file watchers with a single command. You can even combine it with other approaches – for example, using the Template Asset Pipeline for global styles and the Bundle plugin for per-component styles.&lt;/p&gt;
&lt;p&gt;For installation and detailed configuration options, see the &lt;a href=&quot;https://github.com/stephen-cox/eleventy-template-asset-pipeline&quot;&gt;plugin documentation on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;When to Use It&lt;/h2&gt;
&lt;p&gt;The Template Asset Pipeline plugin is most useful when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You have standalone CSS or JS files that need preprocessing or bundling&lt;/li&gt;
&lt;li&gt;You want to use PostCSS, Sass, or Webpack without maintaining a parallel task runner&lt;/li&gt;
&lt;li&gt;You prefer a single Eleventy build step that handles everything&lt;/li&gt;
&lt;li&gt;You need production and development modes with different optimisation levels&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s not the best fit for fully componentised architectures (the Bundle plugin handles those better) or projects already tied to a sophisticated bundler like Vite. But for the majority of Eleventy sites, it strikes a practical balance between simplicity and capability.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Where It Fits in the Eleventy Ecosystem&lt;/h2&gt;
&lt;p&gt;Eleventy is gradually evolving from a purely static site generator into a more flexible build framework. The introduction of WebC, the Bundle plugin, and the Vite integration reflects that shift. Each tool tackles a different part of the build problem – from component scoping to live reloading – but they share the same intent: to bring more of the modern web development workflow inside Eleventy itself.&lt;/p&gt;
&lt;p&gt;The Template Asset Pipeline plugin follows that trajectory. It’s not trying to compete with Vite or WebC; instead, it fills the space between them. It provides a middle ground for projects that need real preprocessing and optimisation but want to stay close to Eleventy’s file-based, data-driven model.&lt;/p&gt;
&lt;p&gt;In that sense, it captures what Eleventy has always done best: giving developers choices without forcing a single approach.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mxb.dev/blog/eleventy-asset-pipeline/&quot;&gt;Eleventy Asset Pipeline – Max Böck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.11ty.dev/docs/plugins/bundle/&quot;&gt;Bundle Plugin – Eleventy Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.11ty.dev/docs/server-vite/&quot;&gt;Vite Plugin – Eleventy Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stephen-cox/eleventy-template-asset-pipeline&quot;&gt;Template Asset Pipeline Plugin – GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[2025-W45]]&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
</feed>
