<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Vscode on nunq.net</title><link>https://nunq.net/tags/vscode/</link><description>nunq.net rss feed</description><language>en-us</language><lastBuildDate>Fri, 03 Apr 2026 22:24:40 +0200</lastBuildDate><atom:link href="https://nunq.net/tags/vscode/index.xml" rel="self" type="application/rss+xml"/><item><title>how to add global instructions to copilot in vscode</title><link>https://nunq.net/posts/2026/copilotinstructions/</link><pubDate>Fri, 03 Apr 2026 22:24:40 +0200</pubDate><guid>https://nunq.net/posts/2026/copilotinstructions/</guid><description>&lt;p&gt;For some reason it was pretty hard to find documentation online on how to add cross-workspace custom user instructions to Copilot prompts in VSCode.&lt;/p&gt;
&lt;p&gt;The docs usually only talk about the ones you can put into your repo at &lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;. That&amp;rsquo;s a bit tedious to do for every project though and the way you like Copilot to dance might annoy your colleagues.
I did find this neat document with an even neater title: &lt;a href="https://learn.microsoft.com/en-us/azure/cosmos-db/github-copilot-visual-studio-code-best-practices"&gt;&lt;em&gt;Azure Cosmos DB for NoSQL best practices in GitHub Copilot for Visual Studio Code&lt;/em&gt;&lt;/a&gt; and although its title seems sort of unrelated, it at least tells you where to put the files. That&amp;rsquo;s&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;~/.config/Code/User/prompts/*.instructions.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;for Linux.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s my file:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;global.instructions.md&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f5a97f;font-weight:bold"&gt;# Instructions for Copilot
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f5a97f;font-weight:bold"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;-&lt;/span&gt; Reply in English.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;-&lt;/span&gt; You are on a Linux host.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;-&lt;/span&gt; My shell is the fish shell, not bash! When running commands always use bash-compliant shellcode and execute using bash -c.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;-&lt;/span&gt; Any plan files you write to disk should be put in a &lt;span style="color:#a6da95"&gt;`agent-plans/`&lt;/span&gt; folder in the project with a &lt;span style="color:#a6da95"&gt;`agent-plans/.gitignore`&lt;/span&gt; containing &lt;span style="color:#a6da95"&gt;`*`&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;-&lt;/span&gt; Give your plan files descriptive names, not just &lt;span style="color:#a6da95"&gt;`PLAN.md`&lt;/span&gt;. When asked to write a new plan, do not replace/update the old ones, unless specified.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;-&lt;/span&gt; Do not execute long inline scripts (&amp;gt;10 lines) as agent. Always write them to files first and then run them. They should be put in a &lt;span style="color:#a6da95"&gt;`agent-scripts/`&lt;/span&gt; folder in the project with a &lt;span style="color:#a6da95"&gt;`agent-scripts/.gitignore`&lt;/span&gt; containing &lt;span style="color:#a6da95"&gt;`*`&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- Do not use &lt;span style="color:#a6da95"&gt;`cat &amp;gt; script.py &amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; ... EOF`&lt;/span&gt; syntax for writing files when running a command as agent. Write the file to disk using your native file write capabilities and then execute using &lt;span style="color:#a6da95"&gt;`python script.py`&lt;/span&gt;. This applies to all scripting languages, including bash.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;</description></item><item><title>using the raspberry pi's built-in leds as status lights</title><link>https://nunq.net/posts/2024/raspberrypi/</link><pubDate>Thu, 07 Mar 2024 20:42:05 +0100</pubDate><guid>https://nunq.net/posts/2024/raspberrypi/</guid><description>&lt;p&gt;At home, I have to run an SSH tunnel to activate the network connection (for reasons), which is kind of inconvenient since one device on the network always has to stay on and keep this tunnel alive, so I automated it using a Raspberry Pi.&lt;/p&gt;
&lt;p&gt;A very simple script I wrote does this on my Raspberry Pi 3b+ and I thought it would be nice to have some sort of connection status indicator. But since I didn&amp;rsquo;t have any GPIO LEDs lying around, I did some googling and it turns out that you can override the built-in LEDs on the board itself. There is a red LED (PWR) that indicates if the Pi receives enough voltage, and a green LED (ACT) that blinks when the SD card is being accessed.&lt;/p&gt;
&lt;p&gt;I wanted to show a green light when the connection is alive and a red light when it somehow dies, so I just created these two little scripts in PATH (make sure they have the executable bit set):&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/usr/local/bin/set_green_led&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;&lt;/span&gt;&lt;span style="color:#91d7e3"&gt;echo&lt;/span&gt; &lt;span style="color:#f5a97f"&gt;0&lt;/span&gt; &amp;gt; /sys/class/leds/PWR/brightness
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#91d7e3"&gt;echo&lt;/span&gt; &lt;span style="color:#f5a97f"&gt;1&lt;/span&gt; &amp;gt; /sys/class/leds/ACT/brightness&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/usr/local/bin/set_red_led&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;&lt;/span&gt;&lt;span style="color:#91d7e3"&gt;echo&lt;/span&gt; &lt;span style="color:#f5a97f"&gt;0&lt;/span&gt; &amp;gt; /sys/class/leds/ACT/brightness
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#91d7e3"&gt;echo&lt;/span&gt; &lt;span style="color:#f5a97f"&gt;1&lt;/span&gt; &amp;gt; /sys/class/leds/PWR/brightness&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;However, these commands require root privileges, so add this to the &lt;code&gt;sudoers&lt;/code&gt; file to let your regular user run them without a password prompt:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;alarm ALL = NOPASSWD: /usr/local/bin/set_red_led, /usr/local/bin/set_green_led&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption class="code-caption"&gt;
alarm is my username
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Here is the full script:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/home/alarm/wifi.sh&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;&lt;/span&gt;&lt;span style="color:#91d7e3"&gt;set&lt;/span&gt; -eu -o pipefail
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f4dbd6"&gt;PASS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f4dbd6"&gt;USER&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f4dbd6"&gt;SERVER&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f4dbd6"&gt;SSH_OPTS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;-o ServerAliveInterval=4 -o TCPKeepAlive=yes -o PubkeyAuthentication=no&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;until&lt;/span&gt; sudo /usr/local/bin/set_green_led; sshpass -p &lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$PASS&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt; ssh &lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$SSH_OPTS&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$USER&lt;/span&gt;&lt;span style="color:#a6da95"&gt;@&lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$SERVER&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;; &lt;span style="color:#c6a0f6"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sudo /usr/local/bin/set_red_led
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#91d7e3"&gt;echo&lt;/span&gt; -e &lt;span style="color:#a6da95"&gt;&amp;#34;crashed &lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$?&lt;/span&gt;&lt;span style="color:#a6da95"&gt; at &lt;/span&gt;&lt;span style="color:#c6a0f6"&gt;$(&lt;/span&gt;date&lt;span style="color:#c6a0f6"&gt;)&lt;/span&gt;&lt;span style="color:#a6da95"&gt;\n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sleep &lt;span style="color:#f5a97f"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;I usually just run this script automatically after boot in a &lt;a href="https://github.com/tmux/tmux/wiki"&gt;tmux&lt;/a&gt; session using a cronjob:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;alarm&amp;#39;s crontab&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@reboot /home/alarm/init.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/home/alarm/init.sh&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/usr/bin/tmux new-session -d -s ENTER
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/usr/bin/tmux detach -s ENTER
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sleep &lt;span style="color:#f5a97f"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/usr/bin/tmux send-keys -t &lt;span style="color:#f5a97f"&gt;0&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#34;cd /home/alarm;./wifi.sh&amp;#34;&lt;/span&gt; ENTER&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;The LEDs also need to be reset at boot:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;root&amp;#39;s crontab&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@reboot &lt;span style="color:#91d7e3"&gt;echo&lt;/span&gt; &lt;span style="color:#f5a97f"&gt;0&lt;/span&gt; &amp;gt; /sys/class/leds/ACT/brightness &lt;span style="color:#91d7e3;font-weight:bold"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#91d7e3"&gt;echo&lt;/span&gt; &lt;span style="color:#f5a97f"&gt;0&lt;/span&gt; &amp;gt; /sys/class/leds/PWR/brightness&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;And while we&amp;rsquo;re at it, I would also recommend setting up NTP time synchronization for the Pi, &lt;code&gt;timedatectl&lt;/code&gt; somehow didn&amp;rsquo;t work for me so I resorted to just doing &lt;code&gt;ntpdate&lt;/code&gt; in the root crontab every so often.&lt;/p&gt;
&lt;p&gt;You can also find all the files mentioned in &lt;a href="https://github.com/nunq/rpi-scripts"&gt;this repository&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>making captive portals work with dns over tls in systemd-resolved</title><link>https://nunq.net/posts/2023/captive/</link><pubDate>Tue, 19 Dec 2023 23:13:07 +0100</pubDate><guid>https://nunq.net/posts/2023/captive/</guid><description>&lt;p&gt;I&amp;rsquo;m currently using systemd-networkd, systemd-resolved and iwd together with my ad blocking DNS-over-TLS server for my networking, and it works quite well for most networks, even the pesky 802.1x types such as &lt;a href="https://en.wikipedia.org/wiki/Eduroam"&gt;eduroam&lt;/a&gt;. But now picture this: you&amp;rsquo;re at a hotel, a public place or in a train and you want to use the free Wi-Fi but you can&amp;rsquo;t seem to get online because your custom config using some &lt;em&gt;minimal&lt;/em&gt; network configuration doesn&amp;rsquo;t work, and you&amp;rsquo;re on the brink of just installing NetworkManager and rolling with the defaults. Fear not! This is how to make an exception for your DNS-over-TLS config for certain networks.&lt;/p&gt;
&lt;p&gt;But first, let&amp;rsquo;s talk about why we need to do this.&lt;/p&gt;
&lt;h2 id="how-do-captive-portals-work"&gt;how do captive portals work?&lt;/h2&gt;
&lt;p&gt;First you need to know that Wi-Fi access points always provide connected devices with a default &lt;a href="https://en.wikipedia.org/wiki/Domain_Name_System"&gt;DNS&lt;/a&gt; server over &lt;a href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol"&gt;DHCP&lt;/a&gt;, which is usually your access point itself.
Using this default DNS server, the &lt;abbr title="access point"&gt;AP&lt;/abbr&gt; can block all traffic to external sites by just making every domain name resolve to the captive portal login page (it then keeps track of your login status using your device&amp;rsquo;s &lt;a href="https://en.wikipedia.org/wiki/MAC_address"&gt;MAC address&lt;/a&gt;).
Note that there are also captive portals using HTTP traffic interception instead of DNS redirection, however, I found that these aren&amp;rsquo;t that common anymore, because they have issues with HTTPS traffic, which is most traffic nowadays.&lt;/p&gt;
&lt;h2 id="current-config"&gt;current config&lt;/h2&gt;
&lt;p&gt;Your config files probably look something like this if your setup is similar to mine:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/etc/systemd/network/20-wlan0.network&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Name&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;wlan0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[DHCPv4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# dont use dns servers advertised by dhcp server (router)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;UseDNS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[DHCPv6]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# dont use dns servers advertised by dhcp server (router)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;UseDNS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;no&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/etc/systemd/resolved.conf&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[Resolve]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# insert your dns over tls server ip and domain name below, keep the &amp;#39;#&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;DNS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;1.2.3.4#dnsovertls.resolver.tld&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# only use provided dns server, no fallback&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;FallbackDNS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# use dns for all domains&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Domains&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;~.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;DNSOverTLS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;ReadEtcHosts&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Cache&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;LLMNR&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;MulticastDNS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# hacky way to only make resolved listen on udp 127.0.0.1:53&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;DNSStubListener&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;DNSStubListenerExtra&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;udp:127.0.0.1:53&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;Note that by default iwd does network configuration such as handling DHCP itself, but I chose to let systemd-networkd do this, because I&amp;rsquo;m not sure if it&amp;rsquo;s possible to do such high-level config distinctions (Wi-Fi access point names, etc.) in the iwd config. So here&amp;rsquo;s my iwd config, too:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/etc/iwd/main.conf&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[General]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# dhcp is done by systemd-networkd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;EnableNetworkConfiguration&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# random mac address&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;AddressRandomization&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;once&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;AddressRandomizationRange&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;full&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;NameResolvingService&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;systemd&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;h2 id="needed-config-changes"&gt;needed config changes&lt;/h2&gt;
&lt;p&gt;We need to create a config file that overrides the default interface settings shown above. To do this, just create the following file:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/etc/systemd/resolved.conf&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Name&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;wlan0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;SSID&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;free_wifi&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;DHCP&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# because the dns advertised by routers is not encrypted&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;DNSOverTLS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# i dont expect hotspots to support dnssec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;DNSSEC&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;# reset options set in global systemd-resolved conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;DNS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Domains&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;~.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[DHCPv4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;UseDNS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[DHCPv6]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;UseDNS&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;yes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;And exclude the SSID in your default config file:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/etc/systemd/network/20-default.network&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Name&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;wlan0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;SSID&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;! &amp;#34;free_wifi&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;If you want to connect to a new open Wi-Fi, just add its SSID to the two config files, explicitly including it in one file and explicitly excluding it in the other, like so:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/etc/systemd/network/20-default.network&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Name&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;wlan0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;SSID&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;! &amp;#34;free_wifi_2&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;figure class="highlight"&gt;
&lt;figcaption class="code-title"&gt;
&lt;span class="code-title-name"&gt;&lt;code&gt;/etc/systemd/network/30-captiveportal.network&lt;/code&gt;&lt;/span&gt;
&lt;a class="code-copy" href="#"&gt;copy&lt;/a&gt;
&lt;/figcaption&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Name&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;wlan0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;SSID&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;free_wifi_2&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;Then restart all the relevant services:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo systemctl restart iwd systemd-resolved systemd-networkd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;And go to &lt;a href="http://captive.apple.com"&gt;http://captive.apple.com&lt;/a&gt;, which should be intercepted by the captive portal and redirect to its login page.&lt;/p&gt;
&lt;p&gt;You should now also be able to see that you&amp;rsquo;re using a different DNS server when you run &lt;code&gt;resolvectl status&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="switching-back-dns-servers"&gt;switching back dns servers&lt;/h2&gt;
&lt;p&gt;Now that you&amp;rsquo;re authenticated to the captive portal, you should be able to change back your DNS server using this command:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo systemd-resolve --interface wlan0 --set-dns&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;1.2.3.4#dnsovertls.resolver.tld&amp;#34;&lt;/span&gt; --set-domain &lt;span style="color:#a6da95"&gt;&amp;#34;~.&amp;#34;&lt;/span&gt; --set-dnsovertls&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;To verify this, run &lt;code&gt;sudo ngrep port 853&lt;/code&gt; (853 is the port used for DNS-over-TLS) and see the encrypted DNS traffic to the server address you used.&lt;/p&gt;</description></item><item><title>fish abbreviations not auto-saving</title><link>https://nunq.net/posts/2023/fishabbr/</link><pubDate>Mon, 10 Apr 2023 21:48:00 +0200</pubDate><guid>https://nunq.net/posts/2023/fishabbr/</guid><description>&lt;p&gt;Although version 3.6.0 that &lt;a href="https://github.com/fish-shell/fish-shell/blob/master/CHANGELOG.rst#deprecations-and-removed-features-3"&gt;removed&lt;/a&gt; this feature was already released in January, I only noticed it now.&lt;/p&gt;
&lt;p&gt;So just in case anyone hasn&amp;rsquo;t noticed yet or in case I forget it: The fish shell no longer treats abbreviations as universal variables since version 3.6.0, because abbreviations are now built-ins, which comes with a lot of improvements which I&amp;rsquo;ll mention later (among others they&amp;rsquo;re faster now), but first the stuff that broke.&lt;/p&gt;
&lt;p&gt;When you run &lt;code&gt;abbr -a getip 'curl ifconfig.me'&lt;/code&gt; for example, the abbreviation is no longer automatically added to your config and thus persistent across sessions, it will only be accessible in the current session. Thus, since that release it has to be added manually to &lt;code&gt;~/.config/fish/config.fish&lt;/code&gt;. Just append this line:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-fish" data-lang="fish"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#91d7e3"&gt;abbr&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;-a&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;-- getip&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#39;curl ifconfig.me&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;The double dash tells the shell to stop processing arguments, this is useful if you want an abbreviation that starts with a dash, e.g. &lt;code&gt;-X&lt;/code&gt;. I just do it because the old fish version stored them like this.&lt;/p&gt;
&lt;h2 id="new-features"&gt;new features&lt;/h2&gt;
&lt;p&gt;Now for the improvements, it&amp;rsquo;s possible to use abbreviations anywhere now, not just at the beginning of the prompt, for example&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-fish" data-lang="fish"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#91d7e3"&gt;abbr&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;-a&lt;/span&gt; N &lt;span style="color:#8aadf4"&gt;--position&lt;/span&gt; anywhere &lt;span style="color:#8aadf4"&gt;--set-cursor&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#34;% | nvim&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;To easily pipe stuff into neovim with just &lt;code&gt;N&lt;/code&gt;, or&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-fish" data-lang="fish"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#91d7e3"&gt;abbr&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;-a&lt;/span&gt; eachfile &lt;span style="color:#8aadf4"&gt;--set-cursor&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$(&lt;/span&gt;&lt;span style="color:#a6da95"&gt;string join \n -- &amp;#39;for f in *&amp;#39; &amp;#39;test -f &lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$f&lt;/span&gt;&lt;span style="color:#a6da95"&gt; || continue&amp;#39; &amp;#39;%&amp;#39; &amp;#39;end&amp;#39;)&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;To generate the boilerplate for loop to iterate over files in the current directory. When expanded, the cursor is put where the percent sign is (you can also set which character to use, but &lt;code&gt;%&lt;/code&gt; is the default).&lt;/p&gt;
&lt;p&gt;For more info including how to use functions with abbreviations, see the full v3.6 docs &lt;a href="https://fishshell.com/docs/3.6/cmds/abbr.html"&gt;here&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>ttartisan lens firmware upgrade on linux</title><link>https://nunq.net/posts/2023/ttartisan/</link><pubDate>Fri, 31 Mar 2023 23:05:00 +0200</pubDate><guid>https://nunq.net/posts/2023/ttartisan/</guid><description>&lt;p&gt;TTArtisan, a Chinese lens manufacturer, publishes firmware updates for their lenses which can be upgraded by screwing on the included lens cover which has a USB-C port for firmware upgrades, quite neat!&lt;/p&gt;
&lt;p&gt;On their &lt;a href="https://www.ttartisan.com/?Firmware/"&gt;download page&lt;/a&gt; however, they say that the upgrade is only possible on Windows PCs, which is rather nonsensical because the upgrade &amp;ldquo;procedure&amp;rdquo; (if you can even call it a procedure) only involves copying the new &lt;code&gt;firmware.bin&lt;/code&gt; onto the lens, which acts as a mass storage disk when connected to a PC.&lt;/p&gt;
&lt;p&gt;The one quirk I encountered is that my Arch Linux mounted the drive as read-only by default, so I had to manually mount it with:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mount -o rw /dev/sdX /mnt/path&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;So no big deal. Just copy the bin file to the root directory of the drive after that and the upgrade is done!&lt;/p&gt;</description></item><item><title>sending cron mail only on fail</title><link>https://nunq.net/posts/2023/cronmail/</link><pubDate>Sun, 19 Mar 2023 02:40:00 +0100</pubDate><guid>https://nunq.net/posts/2023/cronmail/</guid><description>&lt;p&gt;Crontab mail notifications are great, except when they&amp;rsquo;re spamming your inbox, even though the command ran fine and without issues. One might be tempted to do something like this to stop the madness:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eed49f"&gt;MAILTO&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;cronfails&lt;span style="color:#91d7e3;font-weight:bold"&gt;@&lt;/span&gt;example.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f5a97f"&gt;0&lt;/span&gt; &lt;span style="color:#f5a97f"&gt;15&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;*&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;*&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;*&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;/&lt;/span&gt;run&lt;span style="color:#91d7e3;font-weight:bold"&gt;/&lt;/span&gt;this&lt;span style="color:#91d7e3;font-weight:bold"&gt;/&lt;/span&gt;script.sh &lt;span style="color:#91d7e3;font-weight:bold"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;/&lt;/span&gt;dev&lt;span style="color:#91d7e3;font-weight:bold"&gt;/&lt;/span&gt;null &lt;span style="color:#f5a97f"&gt;2&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;&amp;gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#f5a97f"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;But then you won&amp;rsquo;t get any notifications and that&amp;rsquo;s not really an option if things fail (at least for me). What I do is use &lt;code&gt;chronic&lt;/code&gt; (on Ubuntu it&amp;rsquo;s in &lt;code&gt;moreutils&lt;/code&gt;) to execute my commands:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eed49f"&gt;MAILTO&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;cronfails&lt;span style="color:#91d7e3;font-weight:bold"&gt;@&lt;/span&gt;example.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f5a97f"&gt;0&lt;/span&gt; &lt;span style="color:#f5a97f"&gt;15&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;*&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;*&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;*&lt;/span&gt; chronic &lt;span style="color:#91d7e3;font-weight:bold"&gt;/&lt;/span&gt;run&lt;span style="color:#91d7e3;font-weight:bold"&gt;/&lt;/span&gt;this&lt;span style="color:#91d7e3;font-weight:bold"&gt;/&lt;/span&gt;script.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;That way, cron only sends a mail if the command did not run successfully (i.e. if the return code isn&amp;rsquo;t zero) and discards the command output on stdout otherwise, thus freeing your inbox from cron mail spam. The great thing is that you can set it individually for each job, so if you wanted to be sure that a command ran, you can just leave out chronic and the output redirection and still get that confirmation mail.&lt;/p&gt;
&lt;p&gt;Apparently there is also a utility called &lt;a href="https://habilis.net/cronic/"&gt;cronic&lt;/a&gt; (without the &amp;lsquo;h&amp;rsquo;) which supposedly does the same and was written by the same author while also being newer, but in my testing it still sent mail when a command ran successfully. Your mileage may vary, but chronic just works for me at the moment.&lt;/p&gt;
&lt;p&gt;By the way, &lt;a href="https://crontab.guru/"&gt;crontab.guru&lt;/a&gt; is super helpful when devising more complex cron schedules.&lt;/p&gt;</description></item><item><title>january 2022 thoughts</title><link>https://nunq.net/posts/2022/january/</link><pubDate>Fri, 14 Jan 2022 22:22:00 +0100</pubDate><guid>https://nunq.net/posts/2022/january/</guid><description>&lt;p&gt;I had some blog post ideas this month, but none of them seemed like they warranted a post of their own, so I am testing this thought collection post format, maybe this will become a recurring thing, I don&amp;rsquo;t know.&lt;/p&gt;
&lt;h2 id="living-in-my-homedir"&gt;living in my homedir&lt;/h2&gt;
&lt;p&gt;Recently, I have subconsciously adopted this way of treating &lt;code&gt;$HOME&lt;/code&gt; as a kind of todo board. Using your homedir this way may be nothing new for some people, but I really like the approach of just using &lt;code&gt;touch test-packages-after-reboot&lt;/code&gt; to create an empty file that just reminds me to do something. This way I don&amp;rsquo;t have to clog up my actual todo kanban system with relatively unimportant things I have to do on my laptop.&lt;/p&gt;
&lt;h2 id="jq-isnt-always-the-best"&gt;jq isn&amp;rsquo;t always the best&lt;/h2&gt;
&lt;p&gt;While writing a small &lt;a href="https://github.com/nunq/dotfiles/blob/master/.scripts/infopanel"&gt;script&lt;/a&gt; that emulates gnome&amp;rsquo;s notification panel for my dwm setup (it displays the current and next month, marking today&amp;rsquo;s date, the local weather and the last few notifications using dmenu) I had to parse the JSON output of &lt;code&gt;dunstctl history&lt;/code&gt; (&lt;a href="https://dunst-project.org/"&gt;dunst&lt;/a&gt; is my notification daemon). My first implementation was using &lt;a href="https://jqlang.org/"&gt;jq&lt;/a&gt;, because pretty much everyone on the Internet tells you to use jq when you mention the words &amp;ldquo;bash&amp;rdquo; (or shell) and &amp;ldquo;JSON&amp;rdquo; or at least that&amp;rsquo;s my impression. The script was quite slow (it took a noticeable amount of probably like 150-200ms) till the panel showed up which isn&amp;rsquo;t really acceptable for a panel that&amp;rsquo;s meant to be brought up spontaneously to glance over it quickly, for example:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-fish" data-lang="fish"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f4dbd6"&gt;$ &lt;/span&gt;&lt;span style="color:#91d7e3"&gt;time &lt;/span&gt;dunstctl &lt;span style="color:#91d7e3"&gt;history&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;|&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;jq&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;-r&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#34;.data[][].summary.data&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Executed&lt;/span&gt; in &lt;span style="color:#f5a97f"&gt;131&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;05&lt;/span&gt; millis &lt;span style="color:#91d7e3"&gt;fish &lt;/span&gt;external
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8aadf4"&gt;usr&lt;/span&gt; &lt;span style="color:#91d7e3"&gt;time &lt;/span&gt;&lt;span style="color:#f5a97f"&gt;147&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;38&lt;/span&gt; millis &lt;span style="color:#f5a97f"&gt;0&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;00&lt;/span&gt; millis &lt;span style="color:#f5a97f"&gt;147&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;38&lt;/span&gt; millis
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8aadf4"&gt;sys&lt;/span&gt; &lt;span style="color:#91d7e3"&gt;time &lt;/span&gt;&lt;span style="color:#f5a97f"&gt;15&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;02&lt;/span&gt; millis &lt;span style="color:#f5a97f"&gt;1&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;43&lt;/span&gt; millis &lt;span style="color:#f5a97f"&gt;13&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;60&lt;/span&gt; millis
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f4dbd6"&gt;$ &lt;/span&gt;&lt;span style="color:#91d7e3"&gt;time &lt;/span&gt;dunstctl &lt;span style="color:#91d7e3"&gt;history&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;|&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;grep&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;-A2&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#39;&amp;#34;summary&amp;#34; : {&amp;#39;&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;|&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;grep&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;-oP&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#39;(?&amp;lt;=&amp;#34;data&amp;#34; : &amp;#34;).*?(?=&amp;#34;$)&amp;#39;&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;|&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;sed&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#39;s|\\||g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;Executed&lt;/span&gt; in &lt;span style="color:#f5a97f"&gt;46&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;50&lt;/span&gt; millis &lt;span style="color:#91d7e3"&gt;fish &lt;/span&gt;external
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8aadf4"&gt;usr&lt;/span&gt; &lt;span style="color:#91d7e3"&gt;time &lt;/span&gt;&lt;span style="color:#f5a97f"&gt;37&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;96&lt;/span&gt; millis &lt;span style="color:#f5a97f"&gt;0&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;00&lt;/span&gt; millis &lt;span style="color:#f5a97f"&gt;37&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;96&lt;/span&gt; millis
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8aadf4"&gt;sys&lt;/span&gt; &lt;span style="color:#91d7e3"&gt;time &lt;/span&gt;&lt;span style="color:#f5a97f"&gt;23&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;54&lt;/span&gt; millis &lt;span style="color:#f5a97f"&gt;5&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;58&lt;/span&gt; millis &lt;span style="color:#f5a97f"&gt;17&lt;/span&gt;,&lt;span style="color:#f5a97f"&gt;95&lt;/span&gt; millis&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption class="code-caption"&gt;
measured using fish shell&amp;#39;s built-in time command, data omitted
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;That&amp;rsquo;s a massive difference, jq takes on average 125-140ms and the second command 40-50ms, even though it&amp;rsquo;s piped multiple times. And yes, there are probably ways to do this more efficiently, but that&amp;rsquo;s what I came up with and it works good enough. Also, while people who regularly use jq are probably used to it, I find jq&amp;rsquo;s syntax just annoying and I have to look up how to do something every time I use it, while grep is just &lt;em&gt;so&lt;/em&gt; easy to use. By the way, here&amp;rsquo;s a picture of said panel:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://nunq.net/media/2022/infopanel.png"&gt;&lt;img src="https://nunq.net/media/2022/infopanel.png"
alt="screenshot of my infopanel"/&gt;&lt;/a&gt;&lt;figcaption&gt;
calendar, weather and notification history. click to enlarge
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="http-alternatives"&gt;http alternatives&lt;/h2&gt;
&lt;p&gt;While browsing a &lt;a href="https://en.wikipedia.org/wiki/Gemini_(protocol)"&gt;gemini&lt;/a&gt; blog webring of sorts I wanted to subscribe to a blog using RSS, but the issue was that while I could subscribe to the feed using an http gemini proxy, the links were all not clickable because they all start with &lt;code&gt;gemini://&lt;/code&gt; and Firefox doesn&amp;rsquo;t understand that. So I installed this auto proxy gemini sites &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/geminize/"&gt;extension&lt;/a&gt; and it seems to work, but only on the desktop, when I use the RSS reader app on my phone it&amp;rsquo;s still not clickable&amp;hellip; But I presume this won&amp;rsquo;t be a regular problem since gemini or &lt;a href="https://en.wikipedia.org/wiki/Gopher_(protocol)"&gt;gopher&lt;/a&gt; sites are kind of hard to find organically on the &amp;ldquo;normal&amp;rdquo; web anyways, where most people spend their time. Personally, a gopher or gemini site seems cool but kind of unnecessary, it&amp;rsquo;s just a thing that would run on my server, potentially widening its attack surface and serving like 3 people if I&amp;rsquo;m lucky.&lt;/p&gt;
&lt;h2 id="even-smaller-images"&gt;even smaller images&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m always looking for ways to speed up my &lt;a href="https://github.com/nunq/startpage"&gt;startpage&lt;/a&gt;, which automatically opens when I open a new tab. Previously I used WebP images in favor of JPGs or PNGs because of the file size. The image that is displayed on the site as decoration (or to set the mood) is always the biggest file transferred, even using the WebP format, it comes in at around 80-150kb, depending on the image. But since the AVIF image format is supposed to be &lt;a href="https://caniuse.com/avif"&gt;supported&lt;/a&gt; by most relevant browsers since late 2021, I thought I&amp;rsquo;d convert them all. And there was a considerable size drop from 3.7mb (sum of all 39 image files) to just 1.7mb! After testing, I had to convert the three animated images back to WebP however, maybe it&amp;rsquo;s not supported or Firefox just couldn&amp;rsquo;t load them, haven&amp;rsquo;t looked into it further, but it&amp;rsquo;s quite impressive how these compression algorithms are still getting better.&lt;/p&gt;
&lt;h2 id="pseudo-productivity"&gt;pseudo productivity&lt;/h2&gt;
&lt;p&gt;This is a blog post idea I had lying around for a few months but never really had enough ideas/motivation to actually write the post, so let&amp;rsquo;s count it as an honorable mention, maybe. Last week, I read this short &lt;a href="https://www.economist.com/business/2022/01/08/the-rise-of-performative-work"&gt;Economist article&lt;/a&gt; about performative work. In my short bullet point draft I summarized my idea as: Am I being productive or am I just tagging all of my todos in a different color? Which sort of gets at the same idea I think. The good thing is that I now no longer have to write that post :)&lt;/p&gt;</description></item><item><title>simple fixes</title><link>https://nunq.net/posts/2021/fixes/</link><pubDate>Fri, 12 Nov 2021 22:55:00 +0100</pubDate><guid>https://nunq.net/posts/2021/fixes/</guid><description>&lt;p&gt;A few months ago I ordered a refurbished New Nintendo 3DS online, because my old 3DS XL wasn&amp;rsquo;t looking too good after almost 10 years of use and since I am quite fond of (and emotionally attached to) the console I wanted to get one I can still use in 10 years with a scratch-free touch screen and no spots where the paint has rubbed off.&lt;/p&gt;
&lt;p&gt;As soon as I got it, I setup homebrew, which is basically a must for any somewhat old Nintendo console (because there&amp;rsquo;s no reason not to do it if the warranty has expired), gets you all the emulators and &lt;em&gt;endless&lt;/em&gt; possibilities. Be careful with the Switch though (I&amp;rsquo;ve heard of frequent bans).&lt;/p&gt;
&lt;p&gt;There was one thing that bugged me though, the charging port seemed to have some sort of loose connection, maybe the previous owner tugged on the cable too hard or the soldering is just bad. It just surprised me, because normally these devices are pretty durable, at least in my experience, they&amp;rsquo;re mostly used by and designed for children after all.&lt;/p&gt;
&lt;p&gt;But this one was faulty in some way, so I thought about what I could do. The obvious (and only answer it seemed) was soldering a new charging port onto the PCB. I didn&amp;rsquo;t really want to do that however, mainly because I have zero experience soldering and the fear of potentially (read: very likely) bricking the device made this option rather unattractive&amp;hellip;&lt;/p&gt;
&lt;p&gt;After experimenting with plugging the charging cable in at different angles I realized something: No matter the angle, if the cable is not fully inserted into the port (with a 2-3mm gap), it charges perfectly fine. Very weird.&lt;/p&gt;
&lt;p&gt;The fix I came up with is a &lt;em&gt;rubber band&lt;/em&gt;, one of those loom bands which were really popular ~2014 is perfect, it prevents the cable from properly plugging in.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;a href="https://nunq.net/media/2021/3ds-cable.jpg"&gt;&lt;img src="https://nunq.net/media/2021/3ds-cable.jpg"/&gt;&lt;/a&gt;&lt;figcaption&gt;
the &amp;#34;fix&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;br&gt;
&lt;figure&gt;&lt;a href="https://nunq.net/media/2021/3ds-cable-port.jpg"&gt;&lt;img src="https://nunq.net/media/2021/3ds-cable-port.jpg"/&gt;&lt;/a&gt;&lt;figcaption&gt;
plugged in
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Quite dull, but eh, it works.&lt;/p&gt;</description></item><item><title>moving back to gnome</title><link>https://nunq.net/posts/2021/gnome/</link><pubDate>Thu, 24 Jun 2021 22:32:00 +0200</pubDate><guid>https://nunq.net/posts/2021/gnome/</guid><description>&lt;p&gt;I&amp;rsquo;ve been using suckless&amp;rsquo; dwm for the last 1.5 years but I felt like switching back to GNOME, here are my findings.&lt;/p&gt;
&lt;h2 id="the-good"&gt;the good&lt;/h2&gt;
&lt;p&gt;Even though GNOME 40 released shortly before I switched back, it looks pretty much the same since I last used it, so everything was rather familiar. After remapping all the keyboard shortcuts to mimic the dwm bindings, it was usable in an efficient way, with virtual desktops and fast switching between them using keyboard shortcuts.&lt;/p&gt;
&lt;p&gt;One of the aspects I most appreciate now is that things just work out-of-the-box, I don&amp;rsquo;t need to manually edit connman files anymore to connect to new wifi networks and can replace my &lt;em&gt;hacked-together&lt;/em&gt; bash script collection with either native GNOME functionality or extensions.&lt;/p&gt;
&lt;h3 id="b-b-but-muh-bloat"&gt;b-b-but muh bloat!!&lt;/h3&gt;
&lt;p&gt;Yes, in a deep corner in my brain, a package count of over 1000 (&lt;code&gt;$ yay -Ps&lt;/code&gt;) annoys me. But &lt;strong&gt;it&amp;rsquo;s a freaking number&lt;/strong&gt; and storage is cheap. Well, each to their own I guess&amp;hellip;&lt;/p&gt;
&lt;h3 id="why-gnome"&gt;why gnome?&lt;/h3&gt;
&lt;p&gt;It looks pretty and clean and from my experience it&amp;rsquo;s the most polished DE out there. All the other ones either seem like obnoxious Mac OS clones or look like Windows (Windows=ugly).&lt;/p&gt;
&lt;p&gt;Also KDE has too many personalization options for me. And XFCE is great for low-end hardware but I mean look at it, the 90s want their GUIs back. I can&amp;rsquo;t even remember the other DEs :/&lt;/p&gt;
&lt;h2 id="the-bad"&gt;the bad&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;There&amp;rsquo;s no tiling and I hate that.&lt;/li&gt;
&lt;li&gt;Now that I&amp;rsquo;ve used a tiling WM, looking at window title bars is a pain, to say the least.&lt;/li&gt;
&lt;li&gt;GDM sometimes freezes on a black screen after resuming from suspend?&lt;/li&gt;
&lt;li&gt;GNOME shell locks up when extracting big archives? That&amp;rsquo;s embarrassing.&lt;/li&gt;
&lt;li&gt;Themes are cool but even the popular ones (I tried &amp;ldquo;Arc Dark&amp;rdquo; and some others) can be buggy in some programs (buttons not legible, etc.), so I just stuck with Adwaita Dark and it&amp;rsquo;s fine, honestly, it does the job.&lt;/li&gt;
&lt;li&gt;GNOME shell extensions shouldn&amp;rsquo;t be downloaded and managed in &lt;em&gt;a web browser&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="summary"&gt;summary&lt;/h2&gt;
&lt;p&gt;GNOME with good tiling support (like dwm does it) would be amazing, but let&amp;rsquo;s be honest that&amp;rsquo;s never going to happen. Luckily I still have the dotfiles so I can go back to my dwm setup, if I want to.&lt;/p&gt;
&lt;p&gt;end note: &lt;em&gt;computing is terrible and we should have never used sand in this way.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="update-november-2021"&gt;update november 2021&lt;/h2&gt;
&lt;p&gt;I have since switched back to using dwm.&lt;/p&gt;
&lt;p&gt;&amp;hellip; and then switched back to GNOME again a year later, it&amp;rsquo;s a never ending cycle.&lt;/p&gt;</description></item><item><title>old mp3 players and song cover art</title><link>https://nunq.net/posts/2021/mp3player/</link><pubDate>Sat, 12 Jun 2021 18:11:00 +0200</pubDate><guid>https://nunq.net/posts/2021/mp3player/</guid><description>&lt;p&gt;A few weeks ago I found my old Sony Walkman mp3 player buried deep into &lt;em&gt;old stuff from past&lt;/em&gt;. It&amp;rsquo;s a blue Sony NWZ-E &lt;em&gt;something&lt;/em&gt; and it still looked great and after charging it up again, turned on. After I was done exploring the interfaces and drowning in nostalgia, I put some mp3 files on there but the cover art just wouldn&amp;rsquo;t show :(&lt;/p&gt;
&lt;p&gt;&lt;em&gt;about 10 forum threads from 201X later&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Apparently, some time in the 2010s, we switched to a new kind of JPEG files, so-called progressive JPEGs (whatever &lt;em&gt;progressive&lt;/em&gt; in regards to an image file is supposed to mean), &amp;ldquo;NO MORE BASELINE JPEGS&amp;rdquo; because more efficient algorithm, &lt;em&gt;I guess? I didn&amp;rsquo;t actually look it up :/&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Objective: Convert the embedded cover art to baseline JPEGs, preferably in the shell, because I&amp;rsquo;m not gonna click the same 5 buttons in a GUI for 30+ minutes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;several StackExchange threads later&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As always there seem to be a billion ways to do this, half of them didn&amp;rsquo;t work for me or my googling was bad. Some program called &amp;ldquo;eyeD3&amp;rdquo; (it&amp;rsquo;s python, I think) finally worked for me and from there on it was just putting it into a for loop and not noticing that I mistyped the directory name two times, oh well.&lt;/p&gt;
&lt;p&gt;Anyways, here&amp;rsquo;s the code (&lt;a href="https://gist.github.com/nunq/c2cc2584396aa20f18ab33b819802368"&gt;gist&lt;/a&gt;) for the fish shell:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-fish" data-lang="fish"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;mkdir&lt;/span&gt; ./img
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;for&lt;/span&gt; &lt;span style="color:#f4dbd6"&gt;i&lt;/span&gt; &lt;span style="color:#c6a0f6"&gt;in&lt;/span&gt; &lt;span style="color:#91d7e3;font-weight:bold"&gt;(&lt;/span&gt;&lt;span style="color:#8aadf4"&gt;ls&lt;/span&gt; -&lt;span style="color:#f5a97f"&gt;1&lt;/span&gt; *.mp3&lt;span style="color:#91d7e3;font-weight:bold"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#6e738d;font-style:italic"&gt;# export covert art from mp3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;eyeD3&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;--write-images&lt;/span&gt;&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;img &lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$i&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#6e738d;font-style:italic"&gt;# remove all embedded cover art
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;eyeD3&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;--remove-all-images&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$i&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#6e738d;font-style:italic"&gt;# convert to baseline and re-import
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e738d;font-style:italic"&gt;&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;convert&lt;/span&gt; img/FRONT_COVER.jpg &lt;span style="color:#8aadf4"&gt;-interlace&lt;/span&gt; none img/cov.jpg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8aadf4"&gt;eyeD3&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;--add-image&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#34;img/cov.jpg:FRONT_COVER&amp;#34;&lt;/span&gt; &lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f4dbd6"&gt;$i&lt;/span&gt;&lt;span style="color:#a6da95"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8aadf4"&gt;rm&lt;/span&gt; img/*
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c6a0f6"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8aadf4"&gt;rm&lt;/span&gt; &lt;span style="color:#8aadf4"&gt;-r&lt;/span&gt; ./img&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;Now I have cover art on my 2011 mp3 player, &lt;em&gt;cool&lt;/em&gt; :)&lt;/p&gt;
&lt;h2 id="update-february-2022"&gt;update february 2022&lt;/h2&gt;
&lt;p&gt;By the way, here&amp;rsquo;s how to encode video for the player:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0" class="chroma"
&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ffmpeg -i in.mp4 -c:v mpeg4 -r &lt;span style="color:#f5a97f"&gt;24&lt;/span&gt; -s 320x240 -c:a aac -b:a 128k out.mp4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;</description></item><item><title>mailchimp newsletters as rss feeds</title><link>https://nunq.net/posts/2021/mailchimp/</link><pubDate>Tue, 09 Mar 2021 23:34:00 +0100</pubDate><guid>https://nunq.net/posts/2021/mailchimp/</guid><description>&lt;p&gt;So these services that turn a newsletter into an RSS Feed have been around for some time now.&lt;/p&gt;
&lt;p&gt;Odds are, if you use an RSS reader, you probably know about services like &lt;a href="https://kill-the-newsletter.com/"&gt;kill the newsletter&lt;/a&gt; that receive the newsletter for you and turn that into an Atom feed. But recently I discovered that Mailchimp, a service widely used for newsletter creation and management (in fact, I can&amp;rsquo;t even remember the last time I encountered a newsletter that wasn&amp;rsquo;t hosted on Mailchimp), publishes all newsletter items in an archive listing which has RSS feeds.&lt;/p&gt;
&lt;h2 id="getting-that-link"&gt;getting that link&lt;/h2&gt;
&lt;p&gt;Because these feeds are rarely advertised and depending on how a website manages the sign-up process, you have to do some digging and URL copy-pasting.&lt;/p&gt;
&lt;p&gt;If they send you directly to mailchimp, the URL looks something like this:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0"
&gt;&lt;code class="language-" data-lang=""
&gt;https://WEBSITENAME.NODE.list-manage.com/subscribe?u=ABC&amp;amp;id=XYZ&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;That&amp;rsquo;s probably the easiest way to get the needed &lt;code&gt;u&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; parameters.&lt;/p&gt;
&lt;p&gt;If their sign-up involves typing your email address into a magic box on their site, just use a 10 minute mail and get the values from clicking the link they send.&lt;/p&gt;
&lt;p&gt;Then you plug them into this URL, make sure to use the same &lt;code&gt;NODE&lt;/code&gt;:&lt;/p&gt;
&lt;figure class="highlight"&gt;
&lt;pre tabindex="0"
&gt;&lt;code class="language-" data-lang=""
&gt;https://NODE.campaign-archive.com/feed?u=ABC&amp;amp;id=XYZ&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;p&gt;And that&amp;rsquo;s it, bloated HTML mails in your feed reader, &lt;em&gt;yay!&lt;/em&gt; By the way, this should be obvious, but your reader kind of needs to have HTML support or else it&amp;rsquo;ll just be a wall of HTML and CSS code.&lt;/p&gt;</description></item></channel></rss>