Recent changes to this wiki:

replace url that is dying soon
diff --git a/blog/entry/quarantimer.mdwn b/blog/entry/quarantimer.mdwn
index 8c15cac3..cb53e18b 100644
--- a/blog/entry/quarantimer.mdwn
+++ b/blog/entry/quarantimer.mdwn
@@ -11,7 +11,7 @@ in different stages of quarantine, and I am quickly losing track of how
 long things have been in quarantine. If you have the same problem,
 here is a solution:
 
-<https://quarantimer.app/>
+[[code/quarantimer]]
 
 Open it on your mobile device, and you can take photos of each thing,
 select the kind of surfaces it has, and it will track the quarantine time

spel
diff --git a/code/quarantimer.mdwn b/code/quarantimer.mdwn
index 929ed9c5..b65b45a5 100644
--- a/code/quarantimer.mdwn
+++ b/code/quarantimer.mdwn
@@ -2,7 +2,7 @@ Coronavirus quarantine timer. It was built on a weekend and
 made available during the covid-19 pandemic, from March 23 2020 to March
 15th 2021.
 
-Transmission by formites was eventually found to be uncommon, so
+Transmission by fomites was eventually found to be uncommon, so
 the quarantimer probably didn't accomplish much beyond helping some
 people's peace of mind. In all it was used by 173 people, to track
 401 objects.

code
diff --git a/code/quarantimer.mdwn b/code/quarantimer.mdwn
index e26b2ae9..929ed9c5 100644
--- a/code/quarantimer.mdwn
+++ b/code/quarantimer.mdwn
@@ -7,4 +7,7 @@ the quarantimer probably didn't accomplish much beyond helping some
 people's peace of mind. In all it was used by 173 people, to track
 401 objects.
 
+Implemented in Haskell using the servant webserver, the code
+is available at <https://git.joeyh.name/index.cgi/quarantimer.git/>
+
 [[!img code/quarantimer/screenshot.png]]

update
diff --git a/code/quarantimer.mdwn b/code/quarantimer.mdwn
index a0b9cdd8..e26b2ae9 100644
--- a/code/quarantimer.mdwn
+++ b/code/quarantimer.mdwn
@@ -1,5 +1,10 @@
-Coronavirus quarantine timer
+Coronavirus quarantine timer. It was built on a weekend and 
+made available during the covid-19 pandemic, from March 23 2020 to March
+15th 2021.
 
-<https://quarantimer.app/>
+Transmission by formites was eventually found to be uncommon, so
+the quarantimer probably didn't accomplish much beyond helping some
+people's peace of mind. In all it was used by 173 people, to track
+401 objects.
 
 [[!img code/quarantimer/screenshot.png]]

add news item for mpdtoys 0.26
diff --git a/code/mpdtoys/news/version_0.21.mdwn b/code/mpdtoys/news/version_0.21.mdwn
deleted file mode 100644
index a6a55ee4..00000000
--- a/code/mpdtoys/news/version_0.21.mdwn
+++ /dev/null
@@ -1,5 +0,0 @@
-mpdtoys 0.21 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * mpinsert: Fix another utf-8 encoding problem. Closes: #[549986](http://bugs.debian.org/549986)
-   * mpinsert: Avoid printing uninitialized value warning when
-     it fails to add any songs and -n is used."""]]
\ No newline at end of file
diff --git a/code/mpdtoys/news/version_0.26.mdwn b/code/mpdtoys/news/version_0.26.mdwn
new file mode 100644
index 00000000..534e56c4
--- /dev/null
+++ b/code/mpdtoys/news/version_0.26.mdwn
@@ -0,0 +1,10 @@
+mpdtoys 0.26 released with [[!toggle text="these changes"]]
+[[!toggleable text="""  * Removed the debian directory from the upstream package, added
+    CHANGELOG, LICENSE, and GPL files.
+  * mpload: Deal with volume or potentially other settings not being set
+    when eg, nothing has been played yet, and avoid crashing.
+    Thanks, Tomas Janousek for the patch.
+  * mpstore: Preserve random state when snapshotting.
+    Thanks, Tomas Janousek for the patch.
+  * mplength: Only add times when they are defined
+    Thanks, Ryan Kavanagh for the patch."""]]
\ No newline at end of file

fix link
diff --git a/code/mpdtoys.mdwn b/code/mpdtoys.mdwn
index 5f1326f7..a7323666 100644
--- a/code/mpdtoys.mdwn
+++ b/code/mpdtoys.mdwn
@@ -10,7 +10,7 @@ current song finishes, emulating a skipping record, and editing the
 playlist in a text editor.
 
 The mpdtoys are available in git at `git://git.joeyh.name/mpdtoys`, or
-[in gitweb](http://git.joeyh.name/?p=mpdtoys.git).
+[in gitweb](https://git.joeyh.name/index.cgi/mpdtoys.git).
 
 ## News
 

fix address
diff --git a/contact.mdwn b/contact.mdwn
index 881208e4..b8bea0b0 100644
--- a/contact.mdwn
+++ b/contact.mdwn
@@ -1,6 +1,6 @@
 * email: <id@joeyh.name>
 * gpg key: [[E85A 5F63 B31D 24C1 EBF0  D81C C910 D922 2512 E3C7|pubkeys/gpg.asc]]
 * irc: joeyh (irc.oftc.net or irc.freenode.net)
-* mastodon: <a href="https://octodon.social/@joeyh">@joeyh@mastodon.social</a>
+* mastodon: <a href="https://octodon.social/@joeyh">@joeyh@octodon.social</a>
 * scuttlebutt: @BCM6DHYJvWzwWi1lFl2tjDXjaqyZAEmJH5ZONSpXhtc=.ed2551
 * some ways to send me a "thank you" for my work, if you're so inclined: [[thanks]]

add gpg pubkey export
exported with --export-options export-minimal to avoid it being massive
diff --git a/contact.mdwn b/contact.mdwn
index 55f22e7e..881208e4 100644
--- a/contact.mdwn
+++ b/contact.mdwn
@@ -1,5 +1,5 @@
 * email: <id@joeyh.name>
-* gpg key: E85A 5F63 B31D 24C1 EBF0  D81C C910 D922 2512 E3C7
+* gpg key: [[E85A 5F63 B31D 24C1 EBF0  D81C C910 D922 2512 E3C7|pubkeys/gpg.asc]]
 * irc: joeyh (irc.oftc.net or irc.freenode.net)
 * mastodon: <a href="https://octodon.social/@joeyh">@joeyh@mastodon.social</a>
 * scuttlebutt: @BCM6DHYJvWzwWi1lFl2tjDXjaqyZAEmJH5ZONSpXhtc=.ed2551
diff --git a/pubkeys/gpg.asc b/pubkeys/gpg.asc
new file mode 100644
index 00000000..d1ec79a0
--- /dev/null
+++ b/pubkeys/gpg.asc
@@ -0,0 +1,122 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+DEdm4TZWb69EVME3hOUEUC8S5M9nWsuW
+=7fhP
+-----END PGP PUBLIC KEY BLOCK-----

move
diff --git a/bitcoin b/pubkeys/bitcoin
similarity index 100%
rename from bitcoin
rename to pubkeys/bitcoin
diff --git a/thanks.mdwn b/thanks.mdwn
index c2ac1124..3007baa0 100644
--- a/thanks.mdwn
+++ b/thanks.mdwn
@@ -5,6 +5,6 @@ more tangible options:
 * paypal joey@kitenet.net
 * [support me on Patreon](https://patreon.com/joeyh) or [Liberapay](https://liberapay.com/joeyh/)
 * [My Amazon wishlist](http://www.amazon.com/gp/registry/registry.html/104-5960215-8415137?ie=UTF8&type=wishlist&id=H9MGKNPCYVS2)
-* bitcoin address: <a href="bitcoin:[[!inline raw=yes pages=bitcoin]]">[[!inline raw=yes pages=bitcoin]]</a>  
+* bitcoin address: <a href="bitcoin:[[!inline raw=yes pages=pubkeys/bitcoin]]">[[!inline raw=yes pages=pubkeys/bitcoin]]</a>  
   (Due to the excessive CO2 use of bitcoin transactions, I currently prefer
   not to use bitcoin though.)

remove old unlinked page
diff --git a/shuttleworth-flash-grant.mdwn b/shuttleworth-flash-grant.mdwn
deleted file mode 100644
index db48bd23..00000000
--- a/shuttleworth-flash-grant.mdwn
+++ /dev/null
@@ -1,3 +0,0 @@
-In November 2015 I received a
-[Flash Grant](https://shuttleworthfoundation.org/flashgrants/)
-from the ShuttleWorth foundation.

fix some links
diff --git a/code/bin.mdwn b/code/bin.mdwn
index d4a64454..3db312a6 100644
--- a/code/bin.mdwn
+++ b/code/bin.mdwn
@@ -10,7 +10,7 @@ and `vipe` from [[moreutils]], or `svnpath`, `debcommit`, `bts`,
 program that grew up in my `bin`. I think there's some useful stuff in
 there still.
 
-You can browse my bin at <http://git.joeyh.name/?p=joey/home.git;a=tree;f=bin>.
+You can browse my bin at <https://git.joeyh.name/index.cgi/joey/home.git/tree/bin>
 
 ## async
 
diff --git a/contact.mdwn b/contact.mdwn
index 0ba240a2..55f22e7e 100644
--- a/contact.mdwn
+++ b/contact.mdwn
@@ -1,5 +1,5 @@
 * email: <id@joeyh.name>
-* gpg key: [E85A 5F63 B31D 24C1 EBF0  D81C C910 D922 2512 E3C7](http://pgp.cs.uu.nl/stats/2512E3C7.html)
+* gpg key: E85A 5F63 B31D 24C1 EBF0  D81C C910 D922 2512 E3C7
 * irc: joeyh (irc.oftc.net or irc.freenode.net)
 * mastodon: <a href="https://octodon.social/@joeyh">@joeyh@mastodon.social</a>
 * scuttlebutt: @BCM6DHYJvWzwWi1lFl2tjDXjaqyZAEmJH5ZONSpXhtc=.ed2551

Fix link rot on https://joeyh.name/code/moreutils/
Some of the links on this page had stopped working.
diff --git a/code/moreutils.mdwn b/code/moreutils.mdwn
index f9db7a81..bb8410e0 100644
--- a/code/moreutils.mdwn
+++ b/code/moreutils.mdwn
@@ -112,7 +112,7 @@ include.
 
   Run it once to store a file's hash, and the second time it'll check
   whether the file has changed.
-  <http://blog.steve.org.uk/the_traffic_is_waiting_outside.html>
+  <https://blog.steve.fi/the_traffic_is_waiting_outside.html>
 
 * tmp
 
@@ -170,7 +170,7 @@ include.
 
   adds up numbers from stdin
 
-  Already available in [numutils](http://suso.suso.org/programs/num-utils/).
+  Already available in [numutils](https://suso.suso.org/programs/num-utils/index.phtml).
   RFP bug filed.
 
 * todist
@@ -179,7 +179,7 @@ include.
   and how many time it occurs in the input
   <http://baruch.ev-en.org/files/todist>
 
-  More suitable for [numutils](http://suso.suso.org/programs/num-utils/),
+  More suitable for [numutils](https://suso.suso.org/programs/num-utils/index.phtml),
   which can probably do it already. RFP bug filed.
 
 * tostats
@@ -188,7 +188,7 @@ include.
   numbers: average, stddev, min, max, mid point
   <http://baruch.ev-en.org/files/tostats>
 
-  More suitable for [numutils](http://suso.suso.org/programs/num-utils/),
+  More suitable for [numutils](https://suso.suso.org/programs/num-utils/index.phtml),
   which can probably do it already. RFP bug filed.
 
 * unsort

add news item for moreutils 0.65
diff --git a/code/moreutils/news/version_0.60.mdwn b/code/moreutils/news/version_0.60.mdwn
deleted file mode 100644
index 51cfb602..00000000
--- a/code/moreutils/news/version_0.60.mdwn
+++ /dev/null
@@ -1,16 +0,0 @@
-moreutils 0.60 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * New implementation of isutf8 by Julien Palard.
-     - Noncharacters (ending with 0xFFFF and 0xFFFE) were considered
-       invalid when encoded in utf8, according to the unicode standard
-       they are valid: "However, they are not illegal in interchange, nor
-       does their presence cause Unicode text to be ill-formed."
-     - \xf4\xbf\xbf\xbf was considered valid UTF8, which is not: after
-       0xF4 the following byte should be between 80 and 8F.
-     - This implementation does not try to decode the stream, so it checks
-       it faster.
-     - Add --list option. Closes: #[691330](http://bugs.debian.org/691330)
-   * Support bullding in Cygwin.
-     Thanks, StalkR
-   * OSX build fix.
-     Thanks, Tony Kelman."""]]
\ No newline at end of file
diff --git a/code/moreutils/news/version_0.65.mdwn b/code/moreutils/news/version_0.65.mdwn
new file mode 100644
index 00000000..db3f679e
--- /dev/null
+++ b/code/moreutils/news/version_0.65.mdwn
@@ -0,0 +1,6 @@
+moreutils 0.65 released with [[!toggle text="these changes"]]
+[[!toggleable text="""  * vipe: Added --suffix option.
+    Thanks, Pål Grønås Drange.
+  * ifdata: fail when -ph is given but no hwaddr is available
+    (Closes: #[386755](http://bugs.debian.org/386755))
+    Thanks, Nicolas Schier"""]]
\ No newline at end of file

calendar update
diff --git a/blog/archives/2021.mdwn b/blog/archives/2021.mdwn
new file mode 100644
index 00000000..1eebcc79
--- /dev/null
+++ b/blog/archives/2021.mdwn
@@ -0,0 +1 @@
+[[!calendar type=year year=2021 pages="blog/entry/* and !*/Discussion"]]
diff --git a/blog/archives/2021/01.mdwn b/blog/archives/2021/01.mdwn
new file mode 100644
index 00000000..6048324a
--- /dev/null
+++ b/blog/archives/2021/01.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=01 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(01) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/02.mdwn b/blog/archives/2021/02.mdwn
new file mode 100644
index 00000000..ec2fdf1e
--- /dev/null
+++ b/blog/archives/2021/02.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=02 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(02) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/03.mdwn b/blog/archives/2021/03.mdwn
new file mode 100644
index 00000000..25e578d7
--- /dev/null
+++ b/blog/archives/2021/03.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=03 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(03) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/04.mdwn b/blog/archives/2021/04.mdwn
new file mode 100644
index 00000000..a224c880
--- /dev/null
+++ b/blog/archives/2021/04.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=04 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(04) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/05.mdwn b/blog/archives/2021/05.mdwn
new file mode 100644
index 00000000..99baae74
--- /dev/null
+++ b/blog/archives/2021/05.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=05 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(05) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/06.mdwn b/blog/archives/2021/06.mdwn
new file mode 100644
index 00000000..81c254c9
--- /dev/null
+++ b/blog/archives/2021/06.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=06 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(06) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/07.mdwn b/blog/archives/2021/07.mdwn
new file mode 100644
index 00000000..0d557166
--- /dev/null
+++ b/blog/archives/2021/07.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=07 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(07) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/08.mdwn b/blog/archives/2021/08.mdwn
new file mode 100644
index 00000000..fa5b8913
--- /dev/null
+++ b/blog/archives/2021/08.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=08 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(08) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/09.mdwn b/blog/archives/2021/09.mdwn
new file mode 100644
index 00000000..5e0ec7fb
--- /dev/null
+++ b/blog/archives/2021/09.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=09 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(09) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/10.mdwn b/blog/archives/2021/10.mdwn
new file mode 100644
index 00000000..35cc407f
--- /dev/null
+++ b/blog/archives/2021/10.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=10 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(10) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/11.mdwn b/blog/archives/2021/11.mdwn
new file mode 100644
index 00000000..894e5afa
--- /dev/null
+++ b/blog/archives/2021/11.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=11 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(11) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2021/12.mdwn b/blog/archives/2021/12.mdwn
new file mode 100644
index 00000000..efa6afbd
--- /dev/null
+++ b/blog/archives/2021/12.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=12 year=2021 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(12) and creation_year(2021) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]

Added a comment: possible alternative
diff --git a/blog/entry/Withrawing_github-backup/comment_1_5957ae3181a86f570c4d0ff9411fc911._comment b/blog/entry/Withrawing_github-backup/comment_1_5957ae3181a86f570c4d0ff9411fc911._comment
new file mode 100644
index 00000000..e6cd3d8f
--- /dev/null
+++ b/blog/entry/Withrawing_github-backup/comment_1_5957ae3181a86f570c4d0ff9411fc911._comment
@@ -0,0 +1,35 @@
+[[!comment format=mdwn
+ username="joeyh-blog@f6e9305deee9ae4319f63c174bfcff937660ebf1"
+ nickname="joeyh-blog"
+ avatar="http://cdn.libravatar.org/avatar/b1e9724ebb36533ee9b0aaa1e59fa3eb"
+ subject="possible alternative"
+ date="2020-12-30T15:00:44Z"
+ content="""
+I don't think that there is no need to backup content from Github anymore - in contrary, developers are aware that Github can change their policies at any time and if that happens, their content might be gone, so they do make a backup.
+
+Now that you announced github-backup as withdrawn, I can recommend another tool which seems to aim for the same target as yours: [python-github-backup](https://github.com/josegonzalez/python-github-backup). It seems to do the job of backing up the metadata quite nicely.
+
+I use it in conjunction with a more basic approach of cloning/pulling each repository itself like this:
+
+    function doBackup {
+        URL=$1
+        REPO=$(echo $URL | sed -e 's#^.*/##g' -e 's#.git$##')
+        
+        if [ -d $TARGET_REPOS/$REPO ]; then
+            cd $TARGET_REPOS/$REPO
+            git pull --all >/dev/null
+        else
+            echo \"cloning $REPO\"
+            cd $TARGET_REPOS
+            git clone $URL >/dev/null
+        fi
+    }
+    curl -s 'https://api.github.com/users/mathisdt/repos?type=owner&per_page=500' \
+        | grep -Eo '\"git_url\": \"[^\"]+\"' \
+        | sed -e 's#\"git_url\": ##' -e 's#\"##g' \
+        | while read url; do doBackup $url; done
+
+Hope to help!
+
+Mathis Dirksen-Thedens
+"""]]

link to code for backlinks
diff --git a/blog/entry/Withrawing_github-backup.mdwn b/blog/entry/Withrawing_github-backup.mdwn
index 2d01c7e2..e12622d4 100644
--- a/blog/entry/Withrawing_github-backup.mdwn
+++ b/blog/entry/Withrawing_github-backup.mdwn
@@ -1,4 +1,4 @@
-I am no longer maintaining [github-backup](http://github-backup.branchable.com/).
+I am no longer maintaining [[code/github-backup]].
 I'll contine hosting its website and git repo for the time being, but it needs
 a new maintainer if it's going to survive.
 

blog update
diff --git a/blog/entry/Withrawing_github-backup.mdwn b/blog/entry/Withrawing_github-backup.mdwn
new file mode 100644
index 00000000..2d01c7e2
--- /dev/null
+++ b/blog/entry/Withrawing_github-backup.mdwn
@@ -0,0 +1,26 @@
+I am no longer maintaining [github-backup](http://github-backup.branchable.com/).
+I'll contine hosting its website and git repo for the time being, but it needs
+a new maintainer if it's going to survive.
+
+I don't really think it needs to survive. If the farce of youtube-dl being
+removed from github, thus losing access to all its issues and pull
+requests, taught us anything, it's that having that happen does not make
+many people reconsider their dependence on github. (Not even youtube-dl it
+turns out, which is back on there.) Clearly people don't generally
+have any interest in backing that stuff up.
+
+As far as the git repositories on Github, they are getting archived very
+effectively by [softwareheritage.org](https://softwareheritage.org/)
+which vaccumes up all git repositories from Github. Which points to a
+problem, because the same can't be said for git repositories not hosted on
+Github. There's a
+[form to submit them](https://archive.softwareheritage.org/save/)
+but the submissions often get hung up needing manual review, and it doesn't
+seem to pull in new commits actively if at all, based on the few git
+repositories I've had archived there so far.
+
+That seems like something it might be worth building some software to manage.
+But it's also just another case of Github's mass bending reality around it;
+the average Github user doesn't care about this and still gets archived;
+the average self-hosting git user may care about this slightly more, but most
+won't get archived, even if that software did get built.

stopping maintaining github-backup
diff --git a/code.mdwn b/code.mdwn
index ab93e7c5..3edc653e 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -36,7 +36,6 @@ In maintenance mode mostly, but I still have my hands in it somewhat.
 [[brainfuck-monad]]
 [[zxcvbn-c]]
 [[scroll]]
-[[github-backup]]
 [[http-client-restricted]]
 [[scuttlebutt-types]]
 [[haskell-libmodbus]]
@@ -71,6 +70,7 @@ These need new maintainers, stat!
 [[sleepd]]
 [[nslu2-utils]]
 [[ticker]]
+[[github-backup]]
 
 These are dead and buried.
 

correction
diff --git a/offgrid/internet.mdwn b/offgrid/internet.mdwn
index bd27d7c9..870395e5 100644
--- a/offgrid/internet.mdwn
+++ b/offgrid/internet.mdwn
@@ -6,7 +6,7 @@ latency to geosynchronous orbit does not make it easy to carry on a
 conversation.
 
 The real problem with the satellite internet is not the speed, but that
-it's a real power hog. I've measured it somewhere between 30 and 60 watts
+it's a real power hog. It uses 70 to 80 watts 
 depending on what it's doing (transmitting uses more power).
 
 I have so far not been able to power it using direct DC, which I use for

not available on https
diff --git a/offgrid/photovoltaic.mdwn b/offgrid/photovoltaic.mdwn
index 27b0a59b..49ea65fc 100644
--- a/offgrid/photovoltaic.mdwn
+++ b/offgrid/photovoltaic.mdwn
@@ -27,4 +27,4 @@ to run everything.
 Total cost of my PV system was around $3000 in 2017. ($2000 after tax
 rebates.) Lithium upgrade cost that amount again.
 
-[Graphs of my PV data are here](https://house.joeyh.name/).
+[Graphs of my PV data are here](http://house.joeyh.name/).

update
diff --git a/offgrid.mdwn b/offgrid.mdwn
index 3bbd4466..b8566a54 100644
--- a/offgrid.mdwn
+++ b/offgrid.mdwn
@@ -1,5 +1,5 @@
 My house is entirely offgrid and has an unusually small energy footprint,
-with only 1100 watts of solar power and only 4 golf cart batteries.
+with only 1100 watts of solar power and a minimum of batteries.
 
 I got here kind of by accident, see [[my_offgrid_story]].
 
diff --git a/offgrid/fridge.mdwn b/offgrid/fridge.mdwn
index 5c297600..ab5e7421 100644
--- a/offgrid/fridge.mdwn
+++ b/offgrid/fridge.mdwn
@@ -1,5 +1,5 @@
 Since I have a [[photovoltaic]] system with a purposefully
-undersized battery bank, refridgeration was a challenge. I succeeded.
+undersized battery bank, refrigeration was a challenge. I succeeded.
 
 My fridge does not run from battery at all, only when the sun is shining.
 It's computer controlled and quite complex, so for more about how it works,
diff --git a/offgrid/photovoltaic.mdwn b/offgrid/photovoltaic.mdwn
index ee645dfa..27b0a59b 100644
--- a/offgrid/photovoltaic.mdwn
+++ b/offgrid/photovoltaic.mdwn
@@ -12,17 +12,19 @@ IronRidge XR100 rails.
 The charge controller is a Tracer4215BN. A modbus to usb adapter lets the
 house's computer read data from it.
 
-The batteries are 4 golf cart batteries. That's not a lot, it's sized to
-get me through about 12 hours overnight. Since batteries are the part of a
-PV system that wears out and has to be replaced, I want to minimize the
-number I use as much as possible.
+Since batteries are the part of a PV system that wears out and has to be
+replaced, I want to minimize the number I use as much as possible.
+I used 4 golf cart batteries for a number of years. I have now upgraded
+to 2 lithium ion Battleborn batteries, which can store enough power to get
+the house through 3 rainy days without much energy conservation.
 
 The solar panels produce as little as 140 watt-hours on the rainiest days,
-which is a lean day and limits my use of the more power hungry stuff, but
-no problem from time to time. On a typical cloudy day they'll produce
-500+ watt-hours, which is all that I need to run everything.
+so after 3 rainy days, my use of the more power hungry stuff is limited,
+but this is no problem from time to time. On a typical cloudy day 
+the solar panels still produce 500+ watt-hours, which is all that I need
+to run everything.
 
 Total cost of my PV system was around $3000 in 2017. ($2000 after tax
-rebates.)
+rebates.) Lithium upgrade cost that amount again.
 
 [Graphs of my PV data are here](https://house.joeyh.name/).

avoid hotlinking to image that is no longer available, a description is
fine
diff --git a/blog/entry/snowdrift.mdwn b/blog/entry/snowdrift.mdwn
index 78c60aef..48f7f8d1 100644
--- a/blog/entry/snowdrift.mdwn
+++ b/blog/entry/snowdrift.mdwn
@@ -15,10 +15,8 @@ crowdfunding pitch for. That's why I was excited to find
 [Snowdrift.coop](https://snowdrift.coop/), which has a unique approach.
 
 Imagine going to a web page for a free software project that you care
-about, and seeing this button:
-
-<img src="https://snowdrift.coop/static/img/intro/pledge-button-draft.png"
-alt="1283 patrons will donate MORE when you pledge">
+about, and seeing this in a button: 
+"1283 current patrons will donate MORE when you pledge"
 
 That's a lot stronger incentive than some paypal donation button or flattr
 link! The details of how it works are explained on 

stumbled on this.. that's my old apartment!
diff --git a/pics/linuxworld/1/fearknghtbrd3.jpg b/pics/linuxworld/1/fearknghtbrd3.jpg
new file mode 100644
index 00000000..5940406c
Binary files /dev/null and b/pics/linuxworld/1/fearknghtbrd3.jpg differ

Improvement suggestion for vipe (arguments with whitespaces)
diff --git a/code/moreutils/discussion.mdwn b/code/moreutils/discussion.mdwn
index 1785edfc..c46ebf60 100644
--- a/code/moreutils/discussion.mdwn
+++ b/code/moreutils/discussion.mdwn
@@ -665,3 +665,7 @@ More often, I might want to do something like this:
     vipe | datamash sum 1
 
 Now, vipe can *sort of* do this, by using either a here-string (`vipe <<< "" | wc -c`) or by pressing Ctrl-D as soon as vipe launches. I wondered if we could just skip the Ctrl-D step and have vipe detect when no stdin has been given to it; instead, jump straight into an empty vim document? - TR
+
+## Vipe with arguments for editor commands involving whitespaces
+
+I sometimes want to use vipe while passing arguments to my editor (let’s say `vim +startinsert`).  That’s easy enough, I just need to run it with the EDITOR variable locally set to that.  But if the arguments contain whitespaces (for instance `vim -c 'norm o'`), this trick doesn’t work anymore, because the EDITOR variable is split on whitespaces.  For that purpose, it would be nice to check as a last case after EDITOR and VISUAL whether any arguments have been passed to vipe and, if that is the case, to set `@editor` to `@ARGV`.  We could then do `vipe vim -c 'norm o'` for those cases that require more flexibility. --Vej Kse

Added a comment: Cool idea
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_258caf435b5c005342f99a211f59d1d1._comment b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_258caf435b5c005342f99a211f59d1d1._comment
new file mode 100644
index 00000000..bce7a5b6
--- /dev/null
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_258caf435b5c005342f99a211f59d1d1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="chris"
+ avatar="http://cdn.libravatar.org/avatar/a8aaea480214fc48e869216f62eb3333"
+ subject="Cool idea"
+ date="2020-11-03T15:36:26Z"
+ content="""
+Thanks for showing me a new way to annoy my co-workers. People could probably just create a new clean git repo without any history, but it's still a cool idea!
+"""]]

wording
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
index 8502185d..4a1123c4 100644
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -37,7 +37,7 @@ the .gitmodules file, and them removing the submodule in a subsequent commit.
 What would then happen if you cloned my git repo and pushed it to Github?
 
 The next person to complain at me about my not having published one of my
-git repos to Github, and how annoying it is to me that they have to clone
+git repos to Github, and how annoying it is that they have to clone
 it from somewhere else in order to push their own fork of it to Github,
 and how no, I would not be perpertuating Github's monopolism in doing so,
 and anyway, Github's monopoloy is not so bad actually ...

wha wha wha whaaaaaaa
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
index 6c9a2409..8502185d 100644
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -41,3 +41,14 @@ git repos to Github, and how annoying it is to me that they have to clone
 it from somewhere else in order to push their own fork of it to Github,
 and how no, I would not be perpertuating Github's monopolism in doing so,
 and anyway, Github's monopoloy is not so bad actually ...
+
+----
+
+	#!/bin/sh
+	printf "Enter the url of the illegal repo, Citizen: "
+	read wha
+	git submodule add "$wha" wha
+	git rm .gitmodules
+	git commit -m wha
+	git rm wha
+	git commit -m wha

update post with simpler method
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
index 3469619d..6c9a2409 100644
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -15,61 +15,29 @@ to suppress.
 
 When you clone the my repo, here's how it looks:
 
-	# git clone localhost:tmp/demo.git demo
-	Cloning into 'demo'...
-	remote: Enumerating objects: 6, done.
-	remote: Counting objects: 100% (6/6), done.
-	remote: Compressing objects: 100% (3/3), done.
-	remote: Total 6 (delta 1), reused 0 (delta 0), pack-reused 0
-	Receiving objects: 100% (6/6), done.
-	Resolving deltas: 100% (1/1), done.
-	# cd demo; git log --stat
-	commit ba26fee395db4f21e75db30086806336bc5be749 (HEAD -> master, origin/master, origin/HEAD)
-	Merge: 6cbce1e 3ec3446
+	# git log
+	commit 1fff890c0980a72d669aaffe9b13a7a077c33ecf (HEAD -> master, origin/master, origin/HEAD)
 	Author: Joey Hess <joeyh@joeyh.name>
-	Date:   Mon Nov 2 17:43:14 2020 -0400
+	Date:   Mon Nov 2 18:29:17 2020 -0400
 	
-	    I like this commit for some reason
+	    remove submodule
 	
-	commit 6cbce1edfe3976306321532d1001d8fed444e769
+	commit 8864d5c1182dccdd1cfc9ee6e5d694ae3c70e7af
 	Author: Joey Hess <joeyh@joeyh.name>
-	Date:   Mon Nov 2 17:14:06 2020 -0400
+	Date:   Mon Nov 2 18:29:00 2020 -0400
 	
-	    hello, world
-	
-	 hello.hs | 1 +
-	 1 file changed, 1 insertion(+)
+	    add
+	# git ls-tree HEAD^
+	160000 commit b5[redacted cuz DMCA+Nov 3 = too much]	back up your cat videos with this
+	100644 blob 45b983be36b73c0788dc9cbcb76cbb80fc7bb057	hello
 
-	commit 3ec34464f2e641d251347ecaff8b68ac44a45815 (grafted)
-	Author: Joey Hess <joeyh@joeyh.name>
-	Date:   Mon Nov 2 17:10:08 2020 -0400
-	    
-	   Is this empty tree the end? History only stops here if we let
-	   them make us complicit in ending it here.
-	# git cat-file -p 3ec34464 | grep parent
-	b5[redacted cuz a DMCA takedown on my blog would be too amusing for Nov 3rd]
+I did this by adding a submodule in one commit, without committing
+the .gitmodules file, and them removing the submodule in a subsequent commit.
 
 What would then happen if you cloned my git repo and pushed it to Github?
-Well, you'd get an error message like this:
-
-	 ! [remote rejected] master -> master (shallow update not allowed)
-
-To fix that, all you need to do is find a git repo containing the
-content in question, and fetch it. You know where it is. Then you can
-push to Github. What happens then?
 
 The next person to complain at me about my not having published one of my
 git repos to Github, and how annoying it is to me that they have to clone
 it from somewhere else in order to push their own fork of it to Github,
 and how no, I would not be perpertuating Github's monopolism in doing so,
 and anyway, Github's monopoloy is not so bad actually ...
-
-----
-
-Method: Clone the interesting repo in question and make a commit on
-top of its head commit that deletes all files, so you commit an empty tree.
-Use `git fetch --depth 1` to fetch that into your own repo, and
-`git merge --allow-unrelated-histories` to make the merge commit. Then,
-since you cannot git push a shallow clone, to get it into your bare repo,
-just run `git fetch --depth 2` from your bare repo. Or you may be able to
-run the fetch and merge directly in the bare repo, I didn't try.
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_1605202392d65736b5234249616224f6._comment b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_1605202392d65736b5234249616224f6._comment
deleted file mode 100644
index 91dc7234..00000000
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_1605202392d65736b5234249616224f6._comment
+++ /dev/null
@@ -1,28 +0,0 @@
-[[!comment format=mdwn
- username="joey"
- subject="""comment 1"""
- date="2020-11-02T22:23:30Z"
- content="""
-git submodules are probably a much better way to do this, avoiding the git
-push problems.
-
-Just add the submodule in one commit, without committing
-the .gitmodules file, and then remove the submodule in a subsequent commit.
-The resulting git repo looks like this when cloned:
-
-	# git log
-	commit 1fff890c0980a72d669aaffe9b13a7a077c33ecf (HEAD -> master, origin/master, origin/HEAD)
-	Author: Joey Hess <joeyh@joeyh.name>
-	Date:   Mon Nov 2 18:29:17 2020 -0400
-	
-	    remove submodule
-	
-	commit 8864d5c1182dccdd1cfc9ee6e5d694ae3c70e7af
-	Author: Joey Hess <joeyh@joeyh.name>
-	Date:   Mon Nov 2 18:29:00 2020 -0400
-	
-	    add
-	joey@darkstar:~/tmp/demo>git ls-tree HEAD^
-	160000 commit b5[refacted]	back up your cat videos with this
-	100644 blob 45b983be36b73c0788dc9cbcb76cbb80fc7bb057	hello
-"""]]

better method
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_1605202392d65736b5234249616224f6._comment b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_1605202392d65736b5234249616224f6._comment
new file mode 100644
index 00000000..91dc7234
--- /dev/null
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github/comment_1_1605202392d65736b5234249616224f6._comment
@@ -0,0 +1,28 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2020-11-02T22:23:30Z"
+ content="""
+git submodules are probably a much better way to do this, avoiding the git
+push problems.
+
+Just add the submodule in one commit, without committing
+the .gitmodules file, and then remove the submodule in a subsequent commit.
+The resulting git repo looks like this when cloned:
+
+	# git log
+	commit 1fff890c0980a72d669aaffe9b13a7a077c33ecf (HEAD -> master, origin/master, origin/HEAD)
+	Author: Joey Hess <joeyh@joeyh.name>
+	Date:   Mon Nov 2 18:29:17 2020 -0400
+	
+	    remove submodule
+	
+	commit 8864d5c1182dccdd1cfc9ee6e5d694ae3c70e7af
+	Author: Joey Hess <joeyh@joeyh.name>
+	Date:   Mon Nov 2 18:29:00 2020 -0400
+	
+	    add
+	joey@darkstar:~/tmp/demo>git ls-tree HEAD^
+	160000 commit b5[refacted]	back up your cat videos with this
+	100644 blob 45b983be36b73c0788dc9cbcb76cbb80fc7bb057	hello
+"""]]

wording
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
index bc3a704d..3469619d 100644
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -66,7 +66,7 @@ and anyway, Github's monopoloy is not so bad actually ...
 
 ----
 
-Tech details: Clone the interesting repo in question and make a commit on
+Method: Clone the interesting repo in question and make a commit on
 top of its head commit that deletes all files, so you commit an empty tree.
 Use `git fetch --depth 1` to fetch that into your own repo, and
 `git merge --allow-unrelated-histories` to make the merge commit. Then,

clarify
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
index 02a7cfc1..bc3a704d 100644
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -71,5 +71,5 @@ top of its head commit that deletes all files, so you commit an empty tree.
 Use `git fetch --depth 1` to fetch that into your own repo, and
 `git merge --allow-unrelated-histories` to make the merge commit. Then,
 since you cannot git push a shallow clone, to get it into your bare repo,
-just run `git fetch` from your bare repo. Or you may be able to run the
-fetch and merge directly in the bare repo, I didn't try.
+just run `git fetch --depth 2` from your bare repo. Or you may be able to
+run the fetch and merge directly in the bare repo, I didn't try.

oh I forgot the actual howto
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
index 3e009b63..02a7cfc1 100644
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -63,3 +63,13 @@ git repos to Github, and how annoying it is to me that they have to clone
 it from somewhere else in order to push their own fork of it to Github,
 and how no, I would not be perpertuating Github's monopolism in doing so,
 and anyway, Github's monopoloy is not so bad actually ...
+
+----
+
+Tech details: Clone the interesting repo in question and make a commit on
+top of its head commit that deletes all files, so you commit an empty tree.
+Use `git fetch --depth 1` to fetch that into your own repo, and
+`git merge --allow-unrelated-histories` to make the merge commit. Then,
+since you cannot git push a shallow clone, to get it into your bare repo,
+just run `git fetch` from your bare repo. Or you may be able to run the
+fetch and merge directly in the bare repo, I didn't try.

indent
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
index cc42c1fd..3e009b63 100644
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -45,7 +45,7 @@ When you clone the my repo, here's how it looks:
 	Date:   Mon Nov 2 17:10:08 2020 -0400
 	    
 	   Is this empty tree the end? History only stops here if we let
-           them make us complicit in ending it here.
+	   them make us complicit in ending it here.
 	# git cat-file -p 3ec34464 | grep parent
 	b5[redacted cuz a DMCA takedown on my blog would be too amusing for Nov 3rd]
 

comma
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
index bf55724e..cc42c1fd 100644
--- a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -10,7 +10,7 @@ resume.
 Now here's another interesting thing. It's entirely possible for me to add
 one of those commit hashes to any of my repos, which of course, I 
 [self host](https://git.joeyh.name/). I can do it without adding any of
-the *content* which Github/Microsoft, as a RIAA member wishes
+the *content* which Github/Microsoft, as a RIAA member, wishes
 to suppress.
 
 When you clone the my repo, here's how it looks:

post
diff --git a/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
new file mode 100644
index 00000000..bf55724e
--- /dev/null
+++ b/blog/entry/how_to_publish_git_repos_that_cannot_be_republished_to_github.mdwn
@@ -0,0 +1,65 @@
+So here's an interesting thing. Certain commit hashes
+are rapidly heading toward being
+[illegal on Github](https://torrentfreak.com/github-warns-users-reposting-youtube-dl-they-could-be-banned-201102/).
+
+So, if you clone a git repo from somewhere else, you had better be wary of
+pushing it to Github. Because if it happened to contain one of those
+hashes, that could get you banned from Github. Which, as we know, is your
+resume.
+
+Now here's another interesting thing. It's entirely possible for me to add
+one of those commit hashes to any of my repos, which of course, I 
+[self host](https://git.joeyh.name/). I can do it without adding any of
+the *content* which Github/Microsoft, as a RIAA member wishes
+to suppress.
+
+When you clone the my repo, here's how it looks:
+
+	# git clone localhost:tmp/demo.git demo
+	Cloning into 'demo'...
+	remote: Enumerating objects: 6, done.
+	remote: Counting objects: 100% (6/6), done.
+	remote: Compressing objects: 100% (3/3), done.
+	remote: Total 6 (delta 1), reused 0 (delta 0), pack-reused 0
+	Receiving objects: 100% (6/6), done.
+	Resolving deltas: 100% (1/1), done.
+	# cd demo; git log --stat
+	commit ba26fee395db4f21e75db30086806336bc5be749 (HEAD -> master, origin/master, origin/HEAD)
+	Merge: 6cbce1e 3ec3446
+	Author: Joey Hess <joeyh@joeyh.name>
+	Date:   Mon Nov 2 17:43:14 2020 -0400
+	
+	    I like this commit for some reason
+	
+	commit 6cbce1edfe3976306321532d1001d8fed444e769
+	Author: Joey Hess <joeyh@joeyh.name>
+	Date:   Mon Nov 2 17:14:06 2020 -0400
+	
+	    hello, world
+	
+	 hello.hs | 1 +
+	 1 file changed, 1 insertion(+)
+
+	commit 3ec34464f2e641d251347ecaff8b68ac44a45815 (grafted)
+	Author: Joey Hess <joeyh@joeyh.name>
+	Date:   Mon Nov 2 17:10:08 2020 -0400
+	    
+	   Is this empty tree the end? History only stops here if we let
+           them make us complicit in ending it here.
+	# git cat-file -p 3ec34464 | grep parent
+	b5[redacted cuz a DMCA takedown on my blog would be too amusing for Nov 3rd]
+
+What would then happen if you cloned my git repo and pushed it to Github?
+Well, you'd get an error message like this:
+
+	 ! [remote rejected] master -> master (shallow update not allowed)
+
+To fix that, all you need to do is find a git repo containing the
+content in question, and fetch it. You know where it is. Then you can
+push to Github. What happens then?
+
+The next person to complain at me about my not having published one of my
+git repos to Github, and how annoying it is to me that they have to clone
+it from somewhere else in order to push their own fork of it to Github,
+and how no, I would not be perpertuating Github's monopolism in doing so,
+and anyway, Github's monopoloy is not so bad actually ...

blog update
diff --git a/blog/entry/comically_bad_shipping_estimates_and_middlemen.mdwn b/blog/entry/comically_bad_shipping_estimates_and_middlemen.mdwn
new file mode 100644
index 00000000..6aa86b2a
--- /dev/null
+++ b/blog/entry/comically_bad_shipping_estimates_and_middlemen.mdwn
@@ -0,0 +1,45 @@
+My inverter has unfortunately died, and I wanted to replace it with the
+same model. Ideally before I lose the contents of the fridge. It's a 24v
+inverter, which is not at all as easy to find a replacement for as a 12v
+inverter would be.
+
+Somehow Walmart was the only retailer that 
+[had it available](https://www.walmart.com/ip/AIMS-Power-1500-Watt-48-Volt-Pure-Sine-Inverter/35887513)
+with a delivery estimate: Just 2 days.
+
+[[!img pics/shipping/walmart.png]]
+
+It's the second day now, with no indication they've shipped it. 
+I noticed the "sold and shipped by Zoro", so went and
+[found it on that website](https://www.zoro.com/aims-power-pure-sine-inverter-1500w-24v-pwri150024s/i/G4430015/).
+
+[[!img pics/shipping/zorro.png]]
+
+So, the reality is it ships direct from China via container ship. As does
+every product from Zoro, which all show as 2 day delivery on Walmart's website.
+
+I don't think this is a pandemic thing. I think it's a trying to compete
+with Amazon and failing thing.
+
+----
+
+My other comically bad shipping estimate this pandemic was from Amazon
+though. There was a run this summer on Kayaks, because social distancing is
+great on the water. I found a high quality inflatable kayak.
+
+Amazon said "only 2 left in stock" and promised delivery in 1 week.
+One week later, it had not shipped, and they updated the delivery
+estimate forward 1 week. A week after that, ditto.
+
+Eventually I bought a new model from the same manufacturer, Advanced
+Elements. Unfortunately, that kayak exploded the second time I inflated it,
+due to a manufacturing defect.
+
+So I got in touch with Advanced Elements and they offered a replacement. I
+asked if, instead, they maybe still had any of the older model of kayak
+I had tried to order. They checked their warehouse, and found
+"the last one" in a corner somewhere.
+
+No shipping estimate was provided. It arrived in 3 days.
+
+[[!img pics/kayak_webb_island.jpg]]
diff --git a/blog/pics/kayak_webb_island.jpg b/blog/pics/kayak_webb_island.jpg
new file mode 100644
index 00000000..ff8c3beb
Binary files /dev/null and b/blog/pics/kayak_webb_island.jpg differ
diff --git a/blog/pics/shipping/walmart.png b/blog/pics/shipping/walmart.png
new file mode 100644
index 00000000..127e6be1
Binary files /dev/null and b/blog/pics/shipping/walmart.png differ
diff --git a/blog/pics/shipping/zorro.png b/blog/pics/shipping/zorro.png
new file mode 100644
index 00000000..0ca5b13f
Binary files /dev/null and b/blog/pics/shipping/zorro.png differ

update
diff --git a/blog/entry/AIMS_inverter_control_via_GPIO_ports.mdwn b/blog/entry/AIMS_inverter_control_via_GPIO_ports.mdwn
index 121f9ac1..8a70a1e6 100644
--- a/blog/entry/AIMS_inverter_control_via_GPIO_ports.mdwn
+++ b/blog/entry/AIMS_inverter_control_via_GPIO_ports.mdwn
@@ -43,3 +43,9 @@ It works!
 	joey@darkstar:~>ssh house inverter status
 	on
 
+---
+
+Update fall 2020: This inverter died after 2.5 years of daily light use.
+While it's possible this control had something to do with it, it seems more
+likely that it was value engineered to not last much longer than its 2 year
+warantee period.

add news item for pdmenu 1.3.6
diff --git a/code/pdmenu/news/version_1.3.1.mdwn b/code/pdmenu/news/version_1.3.1.mdwn
deleted file mode 100644
index 3d4d3d19..00000000
--- a/code/pdmenu/news/version_1.3.1.mdwn
+++ /dev/null
@@ -1,3 +0,0 @@
-pdmenu 1.3.1 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Use arch wildcards in build deps. Closes: #[634487](http://bugs.debian.org/634487)"""]]
\ No newline at end of file
diff --git a/code/pdmenu/news/version_1.3.6.mdwn b/code/pdmenu/news/version_1.3.6.mdwn
new file mode 100644
index 00000000..bdc9c1b7
--- /dev/null
+++ b/code/pdmenu/news/version_1.3.6.mdwn
@@ -0,0 +1,4 @@
+pdmenu 1.3.6 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Fix build with gcc 10.
+     Thanks, Fabrice Fontaine."""]]
\ No newline at end of file

add news item for moreutils 0.64
diff --git a/code/moreutils/news/version_0.59.mdwn b/code/moreutils/news/version_0.59.mdwn
deleted file mode 100644
index 1d39e7ba..00000000
--- a/code/moreutils/news/version_0.59.mdwn
+++ /dev/null
@@ -1,10 +0,0 @@
-moreutils 0.59 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Makefile: add DOCBOOKXSL setting.
-     Thanks, Kevin Bullock
-   * parallel: include signal.h to fix warning when building with clang
-     Thanks, Kevin Bullock
-   * chronic: Added -v option for more verbose output.
-     Thanks, Tomas Mudrunka
-   * chronic: Added -e option to display any stderr.
-     Thanks, Tomas Mudrunka"""]]
\ No newline at end of file
diff --git a/code/moreutils/news/version_0.64.mdwn b/code/moreutils/news/version_0.64.mdwn
new file mode 100644
index 00000000..f00f532a
--- /dev/null
+++ b/code/moreutils/news/version_0.64.mdwn
@@ -0,0 +1,8 @@
+moreutils 0.64 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * parallel: fix typo in usage message.
+   * Makefile: Propagate compiler and linker flags when building is\_utf8.
+   * ts: Fix parsing of ISO-8601 dates.
+     Thanks, David Laban.
+   * parallel: Allow compiling with uClibc-ng, which does not have getloadavg.
+     Thanks, Rosen Penev"""]]
\ No newline at end of file

Added a comment: it might be a variation of TOCTOU
diff --git a/blog/entry/process_wild_ride/comment_1_a18ee2d5bd831b48ce67178d8ee4591a._comment b/blog/entry/process_wild_ride/comment_1_a18ee2d5bd831b48ce67178d8ee4591a._comment
new file mode 100644
index 00000000..fc5c55df
--- /dev/null
+++ b/blog/entry/process_wild_ride/comment_1_a18ee2d5bd831b48ce67178d8ee4591a._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="cwk"
+ avatar="http://cdn.libravatar.org/avatar/b717a7ec6c3c6dbd10662df8db1564d1"
+ subject="it might be a variation of TOCTOU"
+ date="2020-08-15T15:50:32Z"
+ content="""
+Hi,
+
+I think what you found might be a variation of TOCTOU - time of creation, time of access.
+
+For example (although slightly different, but it's the same underlying idea):
+
+https://duo.com/decipher/docker-bug-allows-root-access-to-host-file-system
+
+
+"""]]

Request for better handling of no stdin with vipe
diff --git a/code/moreutils/discussion.mdwn b/code/moreutils/discussion.mdwn
index cc0fd4a8..1785edfc 100644
--- a/code/moreutils/discussion.mdwn
+++ b/code/moreutils/discussion.mdwn
@@ -652,3 +652,16 @@ Curiously, running bar.sh directly doesn't have this problem.  I'm not sure what
 * Please can the manpage warn of the non-preservation of order, on the collected stdout from child processes?  
   On first inspection with `pee md5sum sha256sum` vs `pee sha256sum md5sum`, and on a fast/idle machine, it looks like stdout are collected and then written. But more complex examples show that stdouts may be interleaved even when there have been no newlines yet, so `pee 'md5sum > foo.md5' 'sha256sum > foo.sha256'` is a much better solution.  Thanks -- m  
   *ps.* no bytes were harmed in our discovery of this behaviour, because we've seen interleaved data too many times before! :-]
+
+## Vipe without stdin
+
+Hi Joey, thanks for your work on moreutils. I use vipe all the time. As someone else said, this is the killer app :)
+Sometimes I would like to use vipe without receiving any input first, so that I can set up some text for piping to another program. Kind of like here-docs or echo, except you get to edit the text with vim first. A simple example could look something like this:
+
+    vipe | wc -c
+
+More often, I might want to do something like this:
+
+    vipe | datamash sum 1
+
+Now, vipe can *sort of* do this, by using either a here-string (`vipe <<< "" | wc -c`) or by pressing Ctrl-D as soon as vipe launches. I wondered if we could just skip the Ctrl-D step and have vipe detect when no stdin has been given to it; instead, jump straight into an empty vim document? - TR

blog update
diff --git a/blog/entry/process_wild_ride.mdwn b/blog/entry/process_wild_ride.mdwn
new file mode 100644
index 00000000..daa12fbb
--- /dev/null
+++ b/blog/entry/process_wild_ride.mdwn
@@ -0,0 +1,30 @@
+[[!meta title="Mr Process's wild ride"]]
+
+When a unix process is running in a directory, and that directory gets
+renamed, the process is taken on a ride to a new location in the
+filesystem. Suddenly, any "../" paths it might be using point to new, and
+unexpected locations.
+
+This can be a source of interesting behavior, and also of security holes.
+
+Suppose root is poking around in `~user/foo/bar/` and decides to 
+`vim ../../etc/conffile`
+
+If the user notices this process is running, they can `mv ~/foo/bar /tmp`
+and when vim saves the file, it will write to `/tmp/bar/../../etc/conffile`
+AKA `/etc/conffile`.
+
+(Vim does warn that the file has changed while it was being edited. Other
+editors may not. Or root may be feeling especially BoFH and decide to
+overwrite the user's changes to their file. Or the rename could perhaps be
+carefully timed to avoid vim's overwrite protection.)
+
+Or, suppose root, in the same place, decides to archive `../../etc` with tar,
+and then delete it:
+
+	tar cf etc.tar ../../etc; rm -rf ../../etc
+
+Now the user has some time to take root's shell on a ride, before the
+`rm` starts ... and make it delete all of `/etc`!
+
+Anyone know if this class of security hole has a name?

update
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index a0f70c10..65b3923d 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -76,11 +76,11 @@ What can libraries do?
   <pre>
   bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
   bracketInsulated a b = bracket
-  	(async a >>= wait)
-  	(\v -> async (b v) >>= wait)
+  	(uninterruptibleMask $ \u -> async (u a) >>= u . wait)
+  	(\v -> uninterruptibleMask $ \u -> async (u (b v)) >>= u . wait)
   </pre>
-  (This implementation may not be quite right though -- does `async` 
-  use any interruptable operations?)
+  (Note use of uninterruptibleMask here in case async itself does an
+  interruptable operation. My first version got that wrong.. This is hard!)
 
 
 My impression of the state of things now is that you should be very cautious

update
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index 34f44dfb..a0f70c10 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -79,6 +79,9 @@ What can libraries do?
   	(async a >>= wait)
   	(\v -> async (b v) >>= wait)
   </pre>
+  (This implementation may not be quite right though -- does `async` 
+  use any interruptable operations?)
+
 
 My impression of the state of things now is that you should be very cautious
 using `race` or `cancel` or `withAsync` or the like, unless the thread is small

comment
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_3_84bdc994e5569c0efa45993a3073b694._comment b/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_3_84bdc994e5569c0efa45993a3073b694._comment
new file mode 100644
index 00000000..b812ca37
--- /dev/null
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_3_84bdc994e5569c0efa45993a3073b694._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2020-06-11T16:02:44Z"
+ content="""
+@alex safe-exceptions and unliftio use uninterruptibleMask in its
+async safe bracket. Which is ok if the cleanup action is fast, but does
+risk the program not responding to ctrl-c if the cleanup takes a while for
+whatever reason.
+
+As well as SIGINT, there's also the possibility that an async exception is
+thrown for some truely exceptional circumstance, like a segfault. Most code
+would do well to exit immediately on such an exception, not mask it.
+
+I wonder if there's a way to make an uninterruptibleMask that masks only
+a specific async exception, eg the AsyncCancelled exception. 
+Probably this would need ghc support, if it's possible at all.
+"""]]

Added a comment
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_2_1a61fb4f5168aab94775046cd8096eb3._comment b/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_2_1a61fb4f5168aab94775046cd8096eb3._comment
new file mode 100644
index 00000000..219d48d4
--- /dev/null
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_2_1a61fb4f5168aab94775046cd8096eb3._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="gueux+joeyh@3dc86e5b17c9ce2c7edd4ce108f939239c363bc6"
+ nickname="gueux+joeyh"
+ avatar="http://cdn.libravatar.org/avatar/cb159899815e640e3bfc18c409cc7e06"
+ subject="comment 2"
+ date="2020-06-11T12:33:20Z"
+ content="""
+As alex said, safe-exceptions may help. There was a series of blog posts a few years ago about async exceptions: https://tech.fpcomplete.com/blog/2016/06/announce-safe-exceptions/ (I think that is the last post)
+"""]]

Added a comment: Consider UnliftIO
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_1_e2cb821f69f273d9d3e2bcbb442ac0d8._comment b/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_1_e2cb821f69f273d9d3e2bcbb442ac0d8._comment
new file mode 100644
index 00000000..32b7718a
--- /dev/null
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell/comment_1_e2cb821f69f273d9d3e2bcbb442ac0d8._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="alex@e098de4fb1118aae3f6bc5b218ee9e36d10e385c"
+ nickname="alex"
+ avatar="http://cdn.libravatar.org/avatar/c498b37d672ddd88ee07e928f287c2dd"
+ subject="Consider UnliftIO"
+ date="2020-06-11T03:15:36Z"
+ content="""
+Consider [safe-exceptions](https://hackage.haskell.org/package/safe-exceptions) or [unliftio](https://hackage.haskell.org/package/unliftio) (UnliftIO.Exception) both of which have async-safe drop-in replacements for bracket, catch, etc.
+"""]]

try
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index 8b30078b..34f44dfb 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -64,7 +64,7 @@ What can libraries do?
 * Use `finally`. Good mostly in simple situations; more complicated things
   would be hard to write this way.
   <pre>
-  hClose h `finally` removeFile name
+  hClose h \`finally\` removeFile name
   </pre>
 
 * Use `uninterruptibleMask`, but it's a big hammer and is often not the

try
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index 2c64776d..8b30078b 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -63,7 +63,9 @@ What can libraries do?
 
 * Use `finally`. Good mostly in simple situations; more complicated things
   would be hard to write this way.
-  <pre>hClose h `finally` removeFile name</pre>
+  <pre>
+  hClose h `finally` removeFile name
+  </pre>
 
 * Use `uninterruptibleMask`, but it's a big hammer and is often not the
   right tool for the job. If the operation takes a while to run,

try
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index 7fecaa43..2c64776d 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -63,10 +63,7 @@ What can libraries do?
 
 * Use `finally`. Good mostly in simple situations; more complicated things
   would be hard to write this way.
-
-[[!format haskell """
-hClose h `finally` removeFile name
-"""]]
+  <pre>hClose h `finally` removeFile name</pre>
 
 * Use `uninterruptibleMask`, but it's a big hammer and is often not the
   right tool for the job. If the operation takes a while to run,
@@ -74,13 +71,12 @@ hClose h `finally` removeFile name
 
 * May be better to run the actions in worker threads, to insulate
   them from receiving any async exceptions.
-  
-[[!format haskell """
-bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
-bracketInsulated a b = bracket
-	(async a >>= wait)
-	(\v -> async (b v) >>= wait)
-"""]]
+  <pre>
+  bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+  bracketInsulated a b = bracket
+  	(async a >>= wait)
+  	(\v -> async (b v) >>= wait)
+  </pre>
 
 My impression of the state of things now is that you should be very cautious
 using `race` or `cancel` or `withAsync` or the like, unless the thread is small

oop
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index 46910113..7fecaa43 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -65,7 +65,7 @@ What can libraries do?
   would be hard to write this way.
 
 [[!format haskell """
-	hClose h `finally` removeFile name
+hClose h `finally` removeFile name
 """]]
 
 * Use `uninterruptibleMask`, but it's a big hammer and is often not the
@@ -76,10 +76,10 @@ What can libraries do?
   them from receiving any async exceptions.
   
 [[!format haskell """
-	bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
-	bracketInsulated a b = bracket
-		(async a >>= wait)
-		(\v -> async (b v) >>= wait)
+bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+bracketInsulated a b = bracket
+	(async a >>= wait)
+	(\v -> async (b v) >>= wait)
 """]]
 
 My impression of the state of things now is that you should be very cautious

oop
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index 3b9d80ff..46910113 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -61,14 +61,12 @@ What can libraries do?
   there should be an expectation that "withFoo" always is, but if so the
   Haskell comminity has some work ahead of it.
 
-* Use `finally`, eg 
+* Use `finally`. Good mostly in simple situations; more complicated things
+  would be hard to write this way.
 
 [[!format haskell """
-  	hClose h `finally` removeFile name
+	hClose h `finally` removeFile name
 """]]
-  
-  Good mostly in simple situations; more complicated things would be hard
-  to write this way.
 
 * Use `uninterruptibleMask`, but it's a big hammer and is often not the
   right tool for the job. If the operation takes a while to run,
@@ -78,10 +76,10 @@ What can libraries do?
   them from receiving any async exceptions.
   
 [[!format haskell """
-  	bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
-  	bracketInsulated a b = bracket
-  		(async a >>= wait)
-  		(\v -> async (b v) >>= wait)
+	bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+	bracketInsulated a b = bracket
+		(async a >>= wait)
+		(\v -> async (b v) >>= wait)
 """]]
 
 My impression of the state of things now is that you should be very cautious

oop
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index 1b95f4d3..3b9d80ff 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -63,7 +63,7 @@ What can libraries do?
 
 * Use `finally`, eg 
 
-[[!code language=haskell """
+[[!format haskell """
   	hClose h `finally` removeFile name
 """]]
   
@@ -77,7 +77,7 @@ What can libraries do?
 * May be better to run the actions in worker threads, to insulate
   them from receiving any async exceptions.
   
-[[!code language=haskell """
+[[!format haskell """
   	bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
   	bracketInsulated a b = bracket
   		(async a >>= wait)

markdown!!
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index d3bd88f9..1b95f4d3 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -63,7 +63,9 @@ What can libraries do?
 
 * Use `finally`, eg 
 
+[[!code language=haskell """
   	hClose h `finally` removeFile name
+"""]]
   
   Good mostly in simple situations; more complicated things would be hard
   to write this way.
@@ -75,10 +77,12 @@ What can libraries do?
 * May be better to run the actions in worker threads, to insulate
   them from receiving any async exceptions.
   
+[[!code language=haskell """
   	bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
   	bracketInsulated a b = bracket
   		(async a >>= wait)
   		(\v -> async (b v) >>= wait)
+"""]]
 
 My impression of the state of things now is that you should be very cautious
 using `race` or `cancel` or `withAsync` or the like, unless the thread is small

markdown
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index 51eb938f..d3bd88f9 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -61,8 +61,10 @@ What can libraries do?
   there should be an expectation that "withFoo" always is, but if so the
   Haskell comminity has some work ahead of it.
 
-* Use `finally`, eg `hClose h \`finally\` removeFile name`
+* Use `finally`, eg 
 
+  	hClose h `finally` removeFile name
+  
   Good mostly in simple situations; more complicated things would be hard
   to write this way.
 
@@ -72,11 +74,11 @@ What can libraries do?
 
 * May be better to run the actions in worker threads, to insulate
   them from receiving any async exceptions.
-
-	bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
-	bracketInsulated a b = bracket
-		(async a >>= wait)
-		(\v -> async (b v) >>= wait)
+  
+  	bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+  	bracketInsulated a b = bracket
+  		(async a >>= wait)
+  		(\v -> async (b v) >>= wait)
 
 My impression of the state of things now is that you should be very cautious
 using `race` or `cancel` or `withAsync` or the like, unless the thread is small

markdown
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
index ad0f7c0d..51eb938f 100644
--- a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -61,9 +61,7 @@ What can libraries do?
   there should be an expectation that "withFoo" always is, but if so the
   Haskell comminity has some work ahead of it.
 
-* Use `finally`, eg
-
-	hClose h `finally` removeFile name
+* Use `finally`, eg `hClose h \`finally\` removeFile name`
 
   Good mostly in simple situations; more complicated things would be hard
   to write this way.

blog update
diff --git a/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
new file mode 100644
index 00000000..ad0f7c0d
--- /dev/null
+++ b/blog/entry/bracketing_and_async_exceptions_in_haskell.mdwn
@@ -0,0 +1,94 @@
+I've been digging into async exceptions in haskell, and getting more
+and more concerned. In particular, `bracket` seems to be often used in ways
+that are not async exception safe. I've found multiple libraries with problems.
+
+Here's an example:
+
+	withTempFile a = bracket setup cleanup a
+	  where
+		setup = openTempFile "/tmp" "tmpfile"
+		cleanup (name, h) = do
+			hClose h
+			removeFile name
+
+This looks reasonably good, it makes sure to clean up after itself even
+when the action throws an exception.
+
+But, in fact that code can leave stale temp files lying around.
+If the thread receives an async exception when `hClose` is
+running, it will be interrupted before the file is removed.
+
+We normally think of `bracket` as masking exceptions, but it
+doesn't prevent async exceptions in all cases.
+See [Control.Exception on "interruptible operations"](http://hackage.haskell.org/package/base-4.14.0.0/docs/Control-Exception.html#g:13),
+which can receive async exceptions even when other exceptions are masked.
+
+It's a bit surprising, but `hClose` is such an interruptable operation,
+because it flushes the write buffer. The only way to know is to
+[read the code](https://hackage.haskell.org/package/base-4.14.0.0/docs/src/GHC.IO.Handle.Internals.html#hClose_help).
+
+It can be quite hard to determine if an operation is interruptable, since
+it can come down to whether it retries a STM transaction, or uses a MVar
+that is not always full. I've been auditing libraries and I often have
+to look at code several dependencies away, and even then may not be sure
+if a library has this problem.
+
+* [process's withCreateProcess](https://github.com/haskell/process/issues/183)
+  could fail to wait on the process, leaving a zombie. Might also leak
+  file descriptors?
+
+* [http-client's withResponse](https://github.com/snoyberg/http-client/issues/436)
+  might fail to close a network connection. (If a MVar happened to be empty
+  when it's called.)
+
+  Worth noting that there are plenty of examples of using http-client
+  to eg, race downloading two urls and cancel the slower download. Which 
+  is just the kind of use of an async exception that could cause a problem.
+
+* persistent's withSqlPool and withSqlConn might fail to clean up,
+  when used with persistent-postgresql. (If another thread is using the
+  connection and so a MVar over in postgresql-simple is empty.)
+
+* concurrent-output has some locking code that is not async exception safe.
+  (My library, so I've fixed part of it, and hope to fix the rest.)
+
+So far, around half of the libraries I've looked at, that use `bracket`
+or `onException` or the like probably have this problem.
+
+What can libraries do?
+
+* Document whether these things are async exception safe. Or perhaps
+  there should be an expectation that "withFoo" always is, but if so the
+  Haskell comminity has some work ahead of it.
+
+* Use `finally`, eg
+
+	hClose h `finally` removeFile name
+
+  Good mostly in simple situations; more complicated things would be hard
+  to write this way.
+
+* Use `uninterruptibleMask`, but it's a big hammer and is often not the
+  right tool for the job. If the operation takes a while to run,
+  the program will not respond to ctrl-c during that time.
+
+* May be better to run the actions in worker threads, to insulate
+  them from receiving any async exceptions.
+
+	bracketInsulated :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+	bracketInsulated a b = bracket
+		(async a >>= wait)
+		(\v -> async (b v) >>= wait)
+
+My impression of the state of things now is that you should be very cautious
+using `race` or `cancel` or `withAsync` or the like, unless the thread is small
+and easy to audit for these problems. Kind of a shame, since I had wanted to
+be able to cancel a thread that is big and sprawling and uses all the
+libraries mentioned above.
+
+----
+
+This work was sponsored by Jake Vosloo and Graham Spencer
+[on Patreon](https://patreon.com/joeyh).
+
+[[!tag haskell]]

diff --git a/code/moreutils/discussion.mdwn b/code/moreutils/discussion.mdwn
index 326e3e07..cc0fd4a8 100644
--- a/code/moreutils/discussion.mdwn
+++ b/code/moreutils/discussion.mdwn
@@ -5,6 +5,7 @@ comments --[[Joey]]
 Sponge gets terminated with SIGSEGV if it tries to append to an unwritable file:
 
 (make sure you dont have a file named "a")
+
     sudo touch a && sudo chown 000 a && echo 1 | sponge -a a
     sudo rm -f a
 

Formatting
diff --git a/code/moreutils/discussion.mdwn b/code/moreutils/discussion.mdwn
index 7dc15a17..326e3e07 100644
--- a/code/moreutils/discussion.mdwn
+++ b/code/moreutils/discussion.mdwn
@@ -5,8 +5,8 @@ comments --[[Joey]]
 Sponge gets terminated with SIGSEGV if it tries to append to an unwritable file:
 
 (make sure you dont have a file named "a")
-sudo touch a && sudo chown 000 a && echo 1 | sponge -a a
-sudo rm -f a
+    sudo touch a && sudo chown 000 a && echo 1 | sponge -a a
+    sudo rm -f a
 
 Arch Linux, moreutils 0.63-1
 

Sponge segmentation fault
diff --git a/code/moreutils/discussion.mdwn b/code/moreutils/discussion.mdwn
index f11410e3..7dc15a17 100644
--- a/code/moreutils/discussion.mdwn
+++ b/code/moreutils/discussion.mdwn
@@ -1,6 +1,15 @@
 Feel free to edit this page to suggest tools to add, or make any other
 comments --[[Joey]]
 
+## Sponge segmentation fault
+Sponge gets terminated with SIGSEGV if it tries to append to an unwritable file:
+
+(make sure you dont have a file named "a")
+sudo touch a && sudo chown 000 a && echo 1 | sponge -a a
+sudo rm -f a
+
+Arch Linux, moreutils 0.63-1
+
 ## tool suggestion: "re" (Reach Recent Folders)
 
 The `re` command aims to save numerous `cd` operations for reaching recently-used folders.

poll vote (watched it all, liked it\)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index ef9dc9db..76c62951 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 66 "watched it all, liked it"" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
+[[!poll 65 "watched it all, liked it"" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it")
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 5870344d..ef9dc9db 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 65 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
+[[!poll 66 "watched it all, liked it"" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index eef2f4ea..5870344d 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 64 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
+[[!poll 65 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it')
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 5870344d..eef2f4ea 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 65 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
+[[!poll 64 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index eef2f4ea..5870344d 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 64 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
+[[!poll 65 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 0c8af3a4..eef2f4ea 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 63 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
+[[!poll 64 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 14 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

Added a comment
diff --git a/blog/entry/DIN/comment_3_f7de7c9b2bb15323f2419ca221f71d91._comment b/blog/entry/DIN/comment_3_f7de7c9b2bb15323f2419ca221f71d91._comment
new file mode 100644
index 00000000..be578415
--- /dev/null
+++ b/blog/entry/DIN/comment_3_f7de7c9b2bb15323f2419ca221f71d91._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="samuel.kacer@b56d07b334f1d9f89d360e15299a94e675012f6b"
+ nickname="samuel.kacer"
+ avatar="http://cdn.libravatar.org/avatar/a8626a50a086b21b8380dc7610f31e53"
+ subject="comment 3"
+ date="2020-04-13T07:57:55Z"
+ content="""
+@Joey
+
+Sectioning using \"article\" is helpful, as they provide semantics about the web page layout, but they are not considered to be a navigational landmark, so not all screen readers support navigating by \"article\" sections. From [ARIA: article role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Article_Role)
+
+\"Articles are not considered a navigational landmark, but many assistive technologies that support landmarks also support a means to navigate among articles. ...\"
+
+\"header\" elements are turned into navigational landmarks when they are descendants of the \"body\" element and this type of landmark is the \"banner\". They are the converse of a \"footer\" element which transform into \"content info\" landmark when it is directly child of \"body\". As navigational landmarks they are just meant for the whole page and not for individual sections of the page.
+
+In Section 4.1 of [WAI-ARIA Authoring Practices 1.1](https://www.w3.org/TR/wai-aria-practices-1.1/#bib-html-aria) is described which HTML semantic region elements get turned into aria landmarks.
+
+Finally, headings are what most screen readers go to first for navigation of a web page. So for those reasons I'd recommend making the article titles headings. If you don't want to literally make them a \"h1-6\" because it would mess with your CSS then you can just set aria attributes which will change how the page is understood by assisstive tech but not affect any visual rendering of the page.
+_a role=\"heading\" aria-level=\"2\"_Lemons_/a_
+(using _ instead of angular brackets)
+
+[More info on heading role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/heading_role#Examples)
+"""]]

removed
diff --git a/blog/entry/DIN/comment_3_d5bbbb5d26dfbeee04d82ac443d794db._comment b/blog/entry/DIN/comment_3_d5bbbb5d26dfbeee04d82ac443d794db._comment
deleted file mode 100644
index b0d17618..00000000
--- a/blog/entry/DIN/comment_3_d5bbbb5d26dfbeee04d82ac443d794db._comment
+++ /dev/null
@@ -1,23 +0,0 @@
-[[!comment format=mdwn
- username="samuel.kacer@b56d07b334f1d9f89d360e15299a94e675012f6b"
- nickname="samuel.kacer"
- avatar="http://cdn.libravatar.org/avatar/a8626a50a086b21b8380dc7610f31e53"
- subject="comment 3"
- date="2020-04-13T07:50:09Z"
- content="""
-@Joey
-
-Sectioning using <article> is helpful, as they provide semantics about the web page layout, but they are not considered to be a navigational landmakr, so not all screen readers support navigating by <article> sections. From [ARIA: article role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Article_Role)
-
-\"Articles are not considered a navigational landmark, but many assistive technologies that support landmarks also support a means to navigate among articles. ...\"
-
-<header> elements are turned into navigational landmarks when they are descendants of the <body> element and this type of landmark is the \"banner\". They are the converse of a <footer> element which transform into \"content info\" landmark when it is directly child of <body>. As navigational landmarks they are just meant for the whole page and not for individual sections of the page.
-
-In Section 4.1 of [WAI-ARIA Authoring Practices 1.1](https://www.w3.org/TR/wai-aria-practices-1.1/#bib-html-aria) is described which HTML semantic region elements get turned into aria landmarks.
-
-Finally, headings are what most screen readers go to first for navigation of a web page. So for those reasons I'd recommend making the article titles headings. If you don't want to literally make them a <h1-6> because it would mess with your CSS then you can just set aria attributes which will change how the page is understood by assisstive tech but not affect any visual rendering of the page.
-_a role=\"heading\" aria-level=\"2\"_Lemons_/a_
-(using _ instead of </>)
-
-[More info on heading role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/heading_role#Examples)
-"""]]

Added a comment
diff --git a/blog/entry/DIN/comment_3_d5bbbb5d26dfbeee04d82ac443d794db._comment b/blog/entry/DIN/comment_3_d5bbbb5d26dfbeee04d82ac443d794db._comment
new file mode 100644
index 00000000..b0d17618
--- /dev/null
+++ b/blog/entry/DIN/comment_3_d5bbbb5d26dfbeee04d82ac443d794db._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="samuel.kacer@b56d07b334f1d9f89d360e15299a94e675012f6b"
+ nickname="samuel.kacer"
+ avatar="http://cdn.libravatar.org/avatar/a8626a50a086b21b8380dc7610f31e53"
+ subject="comment 3"
+ date="2020-04-13T07:50:09Z"
+ content="""
+@Joey
+
+Sectioning using <article> is helpful, as they provide semantics about the web page layout, but they are not considered to be a navigational landmakr, so not all screen readers support navigating by <article> sections. From [ARIA: article role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Article_Role)
+
+\"Articles are not considered a navigational landmark, but many assistive technologies that support landmarks also support a means to navigate among articles. ...\"
+
+<header> elements are turned into navigational landmarks when they are descendants of the <body> element and this type of landmark is the \"banner\". They are the converse of a <footer> element which transform into \"content info\" landmark when it is directly child of <body>. As navigational landmarks they are just meant for the whole page and not for individual sections of the page.
+
+In Section 4.1 of [WAI-ARIA Authoring Practices 1.1](https://www.w3.org/TR/wai-aria-practices-1.1/#bib-html-aria) is described which HTML semantic region elements get turned into aria landmarks.
+
+Finally, headings are what most screen readers go to first for navigation of a web page. So for those reasons I'd recommend making the article titles headings. If you don't want to literally make them a <h1-6> because it would mess with your CSS then you can just set aria attributes which will change how the page is understood by assisstive tech but not affect any visual rendering of the page.
+_a role=\"heading\" aria-level=\"2\"_Lemons_/a_
+(using _ instead of </>)
+
+[More info on heading role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/heading_role#Examples)
+"""]]

comment
diff --git a/blog/entry/DIN/comment_2_d9d0ecfea0ba53b50683d81740d75ba0._comment b/blog/entry/DIN/comment_2_d9d0ecfea0ba53b50683d81740d75ba0._comment
new file mode 100644
index 00000000..9c5a7f13
--- /dev/null
+++ b/blog/entry/DIN/comment_2_d9d0ecfea0ba53b50683d81740d75ba0._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2020-04-12T14:31:49Z"
+ content="""
+@samuel.kacer, the sections of the blog are inside html article tags,
+and the heading of each is inside a html header tag.
+That seems like sufficient semantic information to me..
+
+I guess what I'll suggest is, if there's some reason that's not sufficient,
+you file a bug report on <https://ikiwiki.info> which is what the blog
+uses.
+"""]]

Added a comment: thanks for the alt text for graphics
diff --git a/blog/entry/DIN/comment_1_aec864b293c70d48d616d4461653aab3._comment b/blog/entry/DIN/comment_1_aec864b293c70d48d616d4461653aab3._comment
new file mode 100644
index 00000000..0a6750d8
--- /dev/null
+++ b/blog/entry/DIN/comment_1_aec864b293c70d48d616d4461653aab3._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="samuel.kacer@b56d07b334f1d9f89d360e15299a94e675012f6b"
+ nickname="samuel.kacer"
+ avatar="http://cdn.libravatar.org/avatar/a8626a50a086b21b8380dc7610f31e53"
+ subject="thanks for the alt text for graphics"
+ date="2020-04-12T12:18:59Z"
+ content="""
+Hi,
+
+I just stumbled onto your blog yesterday while searching for information on FRP in Haskell. Really cool stuff using Haskell for home automation in embedded systems!
+
+I just wanted to post a comment because I noticed you include nice alt text on your images, which I greatly appreciate as a blind person. One other note on accessibility is that navigating around your blog would be easier if the article headings were some sort of HTML heading like <h2>. Screen readers give shortcuts for jumping between different headings, so having sections of a webpage of intrest start with headings means as a screen reader user I could very easily switch between them instead of scrolling  through the whole article before finding the beginning of the next one.
+
+Just thought I would mention it since it seems you already care about accessibility.
+
+Oh and happy late birthday!
+
+Regards,
+Sam
+"""]]

Added a comment: Happy birthday!
diff --git a/blog/entry/lemons/comment_5_83be6177d9a79f379ded08576c3d80bf._comment b/blog/entry/lemons/comment_5_83be6177d9a79f379ded08576c3d80bf._comment
new file mode 100644
index 00000000..ac2f182c
--- /dev/null
+++ b/blog/entry/lemons/comment_5_83be6177d9a79f379ded08576c3d80bf._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="diogo"
+ avatar="http://cdn.libravatar.org/avatar/b829c41f02e974268e52bd6ca828b088"
+ subject="Happy birthday!"
+ date="2020-04-12T07:49:12Z"
+ content="""
+Happy birthday, Joey!
+Feliz aniversário, Joey!
+"""]]

removed
diff --git a/blog/entry/lemons/comment_4_7d0d69de1f68c74c68fc51445e9077b2._comment b/blog/entry/lemons/comment_4_7d0d69de1f68c74c68fc51445e9077b2._comment
deleted file mode 100644
index 039e356d..00000000
--- a/blog/entry/lemons/comment_4_7d0d69de1f68c74c68fc51445e9077b2._comment
+++ /dev/null
@@ -1,9 +0,0 @@
-[[!comment format=mdwn
- username="amacater@8dbb5176e3195fd87756930de08ffc5d96244756"
- nickname="amacater"
- avatar="http://cdn.libravatar.org/avatar/886d76ddcb7edd77095c829efc964ee6"
- subject="Happy birthday Joeh"
- date="2020-04-11T23:09:20Z"
- content="""
-Happy birthday and all the best. The lemon meringue pie looks good too
-"""]]

Added a comment: Happy birthday Joey
diff --git a/blog/entry/lemons/comment_5_7d701b10b2b863f0a5ac24485c6f4766._comment b/blog/entry/lemons/comment_5_7d701b10b2b863f0a5ac24485c6f4766._comment
new file mode 100644
index 00000000..037daaa2
--- /dev/null
+++ b/blog/entry/lemons/comment_5_7d701b10b2b863f0a5ac24485c6f4766._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="amacater@8dbb5176e3195fd87756930de08ffc5d96244756"
+ nickname="amacater"
+ avatar="http://cdn.libravatar.org/avatar/886d76ddcb7edd77095c829efc964ee6"
+ subject="Happy birthday Joey"
+ date="2020-04-11T23:11:20Z"
+ content="""
+Happy birthday / Penblwydd hapus i ti :) Lemon meringue pie looks good too.
+"""]]

Added a comment: Happy birthday Joeh
diff --git a/blog/entry/lemons/comment_4_7d0d69de1f68c74c68fc51445e9077b2._comment b/blog/entry/lemons/comment_4_7d0d69de1f68c74c68fc51445e9077b2._comment
new file mode 100644
index 00000000..039e356d
--- /dev/null
+++ b/blog/entry/lemons/comment_4_7d0d69de1f68c74c68fc51445e9077b2._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="amacater@8dbb5176e3195fd87756930de08ffc5d96244756"
+ nickname="amacater"
+ avatar="http://cdn.libravatar.org/avatar/886d76ddcb7edd77095c829efc964ee6"
+ subject="Happy birthday Joeh"
+ date="2020-04-11T23:09:20Z"
+ content="""
+Happy birthday and all the best. The lemon meringue pie looks good too
+"""]]

Added a comment: by the way
diff --git a/blog/entry/lemons/comment_3_a89d9517428d266bbdc12c086524c8d2._comment b/blog/entry/lemons/comment_3_a89d9517428d266bbdc12c086524c8d2._comment
new file mode 100644
index 00000000..dc9f48ed
--- /dev/null
+++ b/blog/entry/lemons/comment_3_a89d9517428d266bbdc12c086524c8d2._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="maggiemargarethess@78015320cd96dc052b86f45ba7a77ac2c0aaa5a7"
+ nickname="maggiemargarethess"
+ avatar="http://cdn.libravatar.org/avatar/61b9ea3a9064e12dbcc6ed88724c1640"
+ subject="by the way"
+ date="2020-04-11T20:46:42Z"
+ content="""
+It looks gourmet.  
+"""]]

Added a comment: Correction
diff --git a/blog/entry/lemons/comment_2_3e112328177a1d52faf3d8764e521022._comment b/blog/entry/lemons/comment_2_3e112328177a1d52faf3d8764e521022._comment
new file mode 100644
index 00000000..f1086ae4
--- /dev/null
+++ b/blog/entry/lemons/comment_2_3e112328177a1d52faf3d8764e521022._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="maggiemargarethess@78015320cd96dc052b86f45ba7a77ac2c0aaa5a7"
+ nickname="maggiemargarethess"
+ avatar="http://cdn.libravatar.org/avatar/61b9ea3a9064e12dbcc6ed88724c1640"
+ subject="Correction"
+ date="2020-04-11T20:46:16Z"
+ content="""
+Mom brings it.  I make it.  
+
+little sis
+"""]]

Added a comment: Pie
diff --git a/blog/entry/lemons/comment_1_c3eadc3c8cf4e2fe4478f90a77e3997e._comment b/blog/entry/lemons/comment_1_c3eadc3c8cf4e2fe4478f90a77e3997e._comment
new file mode 100644
index 00000000..c20c33a8
--- /dev/null
+++ b/blog/entry/lemons/comment_1_c3eadc3c8cf4e2fe4478f90a77e3997e._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="errol@4c351216735f25963d33c6356c048fda8ce68cb1"
+ nickname="errol"
+ avatar="http://cdn.libravatar.org/avatar/ef35c62161fcba23b7ee6636efbd1569"
+ subject="Pie"
+ date="2020-04-11T20:20:14Z"
+ content="""
+
+
+
+
+
+you could mail me a piece.
+"""]]

blog update
diff --git a/blog/entry/lemons.mdwn b/blog/entry/lemons.mdwn
new file mode 100644
index 00000000..90e3eb8a
--- /dev/null
+++ b/blog/entry/lemons.mdwn
@@ -0,0 +1,31 @@
+Lemon is one of my things. I homegrow meyer lemons and mostly eat them
+whole. My mom makes me lemon meringue pie on my birthday. I thought
+I knew how much work that must be.
+
+[[!img pics/lemonmeringuepie.jpg alt="Gorgeous whole lemon-meringue pie"
+size=900x]]
+
+Well, that was harder than anticipated, and so worth it. Glad my mom was
+there on jitsi to give moral support while I hand whisked the egg whites
+and cursed.
+
+I also got a homemade mask whose [quarantimer](https://quarantimer.app/)
+expired just in time.
+
+But all I really want want for my birthday, this April 11th 2020, is for
+the coronavirus to have peaked today. I mean, having a pandemic peak on your
+birthday is sour, but it's better than the alternative.
+
+Please give me that gift. Stay home. Even when some are saying
+it's over, watch the graphs. Don't go visit even 
+[just one person](https://statnet.org/COVID-JustOneFriend/),
+even on their birthday. I think you can do it.
+
+Yes?
+
+[[!img pics/maskie.jpg alt="Joey in a rainbow tie-die mask,
+holding a thumb up." size=900x]]
+
+[[!img pics/lemonmeringuepieslice.jpg alt="Lemon-meringue pie slice" 
+size=900x]]
+

add
diff --git a/blog/pics/lemonmeringuepie.jpg b/blog/pics/lemonmeringuepie.jpg
new file mode 100644
index 00000000..37500f1d
Binary files /dev/null and b/blog/pics/lemonmeringuepie.jpg differ
diff --git a/blog/pics/lemonmeringuepieslice.jpg b/blog/pics/lemonmeringuepieslice.jpg
new file mode 100644
index 00000000..c0061e1e
Binary files /dev/null and b/blog/pics/lemonmeringuepieslice.jpg differ

add
diff --git a/blog/pics/maskie.jpg b/blog/pics/maskie.jpg
new file mode 100644
index 00000000..515af84a
Binary files /dev/null and b/blog/pics/maskie.jpg differ

hmm
diff --git a/blog/entry/solar_powered_waterfall.mdwn b/blog/entry/solar_powered_waterfall.mdwn
index d4090468..d3aba4c4 100644
--- a/blog/entry/solar_powered_waterfall.mdwn
+++ b/blog/entry/solar_powered_waterfall.mdwn
@@ -3,7 +3,7 @@
 This waterfall is beside my yard. When it's running, I know my
 [[water tanks|hacking_water]] are full and the spring is not dry.
 
-<video controls src="https://downloads.kitenet.net/videos/solar_waterfall.mp4"></video>
+<video controls src="https://downloads.kitenet.net/videos/solar_waterfall.mp4" width=100%></video>
 
 Also it's computer controlled, for times when I don't want to hear it.
 I'll also use the computer control later on to avoid running the pump

reorg
diff --git a/blog/entry/solar_powered_waterfall.mdwn b/blog/entry/solar_powered_waterfall.mdwn
index 6fff9b2f..d4090468 100644
--- a/blog/entry/solar_powered_waterfall.mdwn
+++ b/blog/entry/solar_powered_waterfall.mdwn
@@ -1,10 +1,10 @@
 [[!meta title="solar powered waterfall controlled by a GPIO port"]]
 
-<video controls src="https://downloads.kitenet.net/videos/solar_waterfall.mp4"></video>
-
 This waterfall is beside my yard. When it's running, I know my
 [[water tanks|hacking_water]] are full and the spring is not dry.
 
+<video controls src="https://downloads.kitenet.net/videos/solar_waterfall.mp4"></video>
+
 Also it's computer controlled, for times when I don't want to hear it.
 I'll also use the computer control later on to avoid running the pump
 excessively and wearing it out, and for some safety features like not

oop
diff --git a/blog/entry/solar_powered_waterfall.mdwn b/blog/entry/solar_powered_waterfall.mdwn
index 98a30281..6fff9b2f 100644
--- a/blog/entry/solar_powered_waterfall.mdwn
+++ b/blog/entry/solar_powered_waterfall.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="solar powered waterfall controlled by a GPIO port"]]
 
-<video controls src=""https://downloads.kitenet.net/videos/solar_waterfall.mp4></video>
+<video controls src="https://downloads.kitenet.net/videos/solar_waterfall.mp4"></video>
 
 This waterfall is beside my yard. When it's running, I know my
 [[water tanks|hacking_water]] are full and the spring is not dry.

blog update
diff --git a/blog/entry/solar_powered_waterfall.mdwn b/blog/entry/solar_powered_waterfall.mdwn
new file mode 100644
index 00000000..98a30281
--- /dev/null
+++ b/blog/entry/solar_powered_waterfall.mdwn
@@ -0,0 +1,26 @@
+[[!meta title="solar powered waterfall controlled by a GPIO port"]]
+
+<video controls src=""https://downloads.kitenet.net/videos/solar_waterfall.mp4></video>
+
+This waterfall is beside my yard. When it's running, I know my
+[[water tanks|hacking_water]] are full and the spring is not dry.
+
+Also it's computer controlled, for times when I don't want to hear it.
+I'll also use the computer control later on to avoid running the pump
+excessively and wearing it out, and for some safety features like not
+running when the water is frozen.
+
+This is a whole hillside of pipes, water tanks, pumps, solar panels,
+all controlled by a GPIO port. Easy enough; the pump controller has a float
+switch input and the GPIO drives a 4n35 optoisolator to open or close that
+circuit. Hard part will be burying all the cable to the pump. And then all
+the landscaping around the waterfall.
+
+There's a bit of lag to turning it on and off. It can take over an hour for
+it to start flowing, and around half an hour to stop. The water level has
+to get high enough in the water tanks to overcome some airlocks and
+complicated hydrodynamic flow stuff. Then when it stops, all that excess
+water has to drain back down.
+
+Anyway, enjoy my soothing afternoon project and/or massive rube goldberg
+machine, I certainly am.
diff --git a/offgrid/water.mdwn b/offgrid/water.mdwn
index 5516935b..c2b271d3 100644
--- a/offgrid/water.mdwn
+++ b/offgrid/water.mdwn
@@ -27,3 +27,5 @@ The system works great, I have 30 PSI now, and sufficient storage to easily
 get through the fall dry season.
 
 For more see [[blog/entry/hacking_water]].
+
+Also the overflow goes to [[blog/entry/solar_powered_waterfall]].

response
diff --git a/blog/entry/quarantimer/comment_2_020ce05418c028437818ff965ac1fe88._comment b/blog/entry/quarantimer/comment_2_020ce05418c028437818ff965ac1fe88._comment
new file mode 100644
index 00000000..4fe22ac2
--- /dev/null
+++ b/blog/entry/quarantimer/comment_2_020ce05418c028437818ff965ac1fe88._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2020-04-03T22:17:50Z"
+ content="""
+Thanks, it's good to know.
+"""]]

response
diff --git a/blog/entry/usb_drives_with_no_phantom_load/comment_18_8bcce33cb27a9dc1cf912a31af19c202._comment b/blog/entry/usb_drives_with_no_phantom_load/comment_18_8bcce33cb27a9dc1cf912a31af19c202._comment
new file mode 100644
index 00000000..81e6659e
--- /dev/null
+++ b/blog/entry/usb_drives_with_no_phantom_load/comment_18_8bcce33cb27a9dc1cf912a31af19c202._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 18"""
+ date="2020-04-03T22:16:02Z"
+ content="""
+Startech ST4200USBM.
+
+But uhubctl's home page has a good list of all known usable hubs, many much
+cheaper.
+"""]]

Added a comment
diff --git a/blog/entry/quarantimer/comment_1_b6d902d668c3ae7e694420e35684adf9._comment b/blog/entry/quarantimer/comment_1_b6d902d668c3ae7e694420e35684adf9._comment
new file mode 100644
index 00000000..8aedae63
--- /dev/null
+++ b/blog/entry/quarantimer/comment_1_b6d902d668c3ae7e694420e35684adf9._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="jon+joeyh@0ca6720a1d6c4435ce5a38a0be3c151864be033a"
+ nickname="jon+joeyh"
+ avatar="http://cdn.libravatar.org/avatar/10bbf766427526558b9a09a3e77e5d14"
+ subject="comment 1"
+ date="2020-04-03T09:56:05Z"
+ content="""
+This is really useful, thank you for building it. I've been using it myself and recommending it to others.
+"""]]

Added a comment
diff --git a/blog/entry/usb_drives_with_no_phantom_load/comment_17_9896acdd60597cbd7d3927f90cebdcd9._comment b/blog/entry/usb_drives_with_no_phantom_load/comment_17_9896acdd60597cbd7d3927f90cebdcd9._comment
new file mode 100644
index 00000000..646a6e96
--- /dev/null
+++ b/blog/entry/usb_drives_with_no_phantom_load/comment_17_9896acdd60597cbd7d3927f90cebdcd9._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="gfa@1e86118cd41fbfea50004af221471ad97b55af18"
+ nickname="gfa"
+ avatar="http://cdn.libravatar.org/avatar/4678da4da55c67fa668e31ea0a76b201"
+ subject="comment 17"
+ date="2020-04-03T06:46:03Z"
+ content="""
+What USB hub are you using? cheers
+"""]]

post
diff --git a/blog/entry/DIN.mdwn b/blog/entry/DIN.mdwn
index 668bba28..07be0f38 100644
--- a/blog/entry/DIN.mdwn
+++ b/blog/entry/DIN.mdwn
@@ -2,7 +2,8 @@
 
 My offgrid house has an industrial automation panel.
 
-[[!img pics/DIN/dinrail.jpg alt="A row of electrical devices, mounted on a
+[[!img pics/DIN/dinrail.jpg size=800x
+alt="A row of electrical devices, mounted on a
 metal rail. Many wires neatly extend from it above and below,
 disappearing into wire gutters."]]
 
@@ -23,11 +24,11 @@ stuff, and perhaps you could use a distraction too.
 The panel has my house's computer on it, as well as both AC and DC power
 distribution, breakers, and switching. Since the house is offgrid, the panel
 is designed to let every non-essential power drain be turned off, from
-my [[offgrid_fridge|fridge]] to the 20 terabytes of
+my [[offgrid_fridge|fridge_0.1]] to the 20 terabytes of
 [[offline_storage|usb_drives_with_no_phantom_load]] to the
 [[inverter|AIMS_inverter_control_via_GPIO_ports]] and satellite dish,
 the spring pump for my [[gravity_flow_water_system|hacking_water]], and
-even the outlet by the kitchen sink.
+even the power outlet by the kitchen sink.
 
 Saving power is part of why I'm using old-school relays and stuff and not
 IOT devices, the other reason is of course: IOT devices are horrible
@@ -62,12 +63,12 @@ clipped into place and it evolves for changing needs.
 
 Also, wire gutters, where have you been all my life?
 
-[[!img pics/DIN/gearwall.jpg size=500x 
-alt="A small utility room with an entire wall
+[[!img pics/DIN/gearwall.jpg size=600x 
+alt="A cramped utility room with an entire wall
 covered with electronic gear, including the DIN rail, which is surrounded by
 wire gutters"]]
-[[!img pics/DIN/wiregutter.jpg size=500x 
-alt="A wire gutter with the cover removed.
+[[!img pics/DIN/wiregutter.jpg size=300x 
+alt="Detail of a wire gutter with the cover removed.
 Numerous large and small wires run along it and exit here and there."]]
 
 Finally, if you'd like to know what everything on the DIN rail is, from
@@ -76,6 +77,4 @@ hub switch, computer switch, +24v block, -24v block, IO daughterboard, 1tb
 SSD, arm board, modem, 3 USB hubs, 5 relays, AC hot block, AC neutral
 block, DC-DC power converters, humidity sensor.
 
-[[!img pics/DIN/dinrailleft.jpg alt="DIN rail as described above, left side."]]
-[[!img pics/DIN/dinrailright.jpg alt="DIN rail as described above, right side."]]
-
+[[!img pics/DIN/dinrailfull.jpg size=900x alt="Full width of DIN rail."]]

add
diff --git a/blog/pics/DIN/dinrailfull.jpg b/blog/pics/DIN/dinrailfull.jpg
new file mode 100644
index 00000000..7e8954b6
Binary files /dev/null and b/blog/pics/DIN/dinrailfull.jpg differ

add
diff --git a/blog/pics/DIN/gearwall.jpg b/blog/pics/DIN/gearwall.jpg
new file mode 100644
index 00000000..d7c0e0cd
Binary files /dev/null and b/blog/pics/DIN/gearwall.jpg differ

add
diff --git a/blog/pics/DIN/dinrail.jpg b/blog/pics/DIN/dinrail.jpg
new file mode 100644
index 00000000..1c459569
Binary files /dev/null and b/blog/pics/DIN/dinrail.jpg differ

add
diff --git a/blog/entry/DIN.mdwn b/blog/entry/DIN.mdwn
index 0ab512d2..668bba28 100644
--- a/blog/entry/DIN.mdwn
+++ b/blog/entry/DIN.mdwn
@@ -1,20 +1,24 @@
+[[!meta title="DIN distractions"]]
+
 My offgrid house has an industrial automation panel.
 
-[[!img DIN/dinrail.jpg alt="A row of electrical devices, mounted on a
+[[!img pics/DIN/dinrail.jpg alt="A row of electrical devices, mounted on a
 metal rail. Many wires neatly extend from it above and below,
 disappearing into wire gutters."]]
 
 I started building this in February, before covid-19 was impacting us here,
-when lots of digikey orders were no big problem, and getting an unusual
+when lots of mail orders were no big problem, and getting an unusual
 3D-printed DIN rail bracket for a SSD was just a couple clicks.
 
-I finished a month deep into social isolation and quarentine, scrounging
-around the house for scrap wire, scavenging screws from unused stuff and
-cutting them to size, and hoping I would not end up in a "need just one
-more part" situation.
+I finished a month later, deep into social isolation and quarentine,
+scrounging around the house for scrap wire, scavenging screws from unused
+stuff and cutting them to size, and hoping I would not end up in a "need
+just one more part that I can't get" situation.
 
 It got rather elaborate, and working on it was often a welcome distraction
-from the news when I couldn't concentrate on my usual work.
+from the news when I couldn't concentrate on my usual work. I'm posting
+this now because people sometimes tell me they like hearing about my offfgrid
+stuff, and perhaps you could use a distraction too.
 
 The panel has my house's computer on it, as well as both AC and DC power
 distribution, breakers, and switching. Since the house is offgrid, the panel
@@ -25,30 +29,46 @@ my [[offgrid_fridge|fridge]] to the 20 terabytes of
 the spring pump for my [[gravity_flow_water_system|hacking_water]], and
 even the outlet by the kitchen sink.
 
-(Saving power is part of why I'm using old-school relays and stuff and not
-IOT devices, the other reason is of course: IOT devices are horrible.)
+Saving power is part of why I'm using old-school relays and stuff and not
+IOT devices, the other reason is of course: IOT devices are horrible
+dystopian e-waste. I'm taking the utopian Star Trek approach, where I
+can command "full power to the vacuum cleaner!"
 
-[[!img DIN/daughterboard.jpg alt="Two circuit boards, connected by numerous
+[[!img pics/DIN/daughterboard.jpg size=300x
+alt="Two circuit boards, connected by numerous
 ribbon cables, and clearly hand-soldered. The smaller board is suspended
 above the larger."]]
-[[!img DIN/schematic.jpg alt="An electrical schematic, of moderate complexity."]]
+[[!img pics/DIN/schematic.jpg size=600x alt="An electrical schematic, of moderate complexity."]]
 
 At the core of the panel, next to the cubietruck arm board, is a custom
 IO daughterboard. Designed and built by hand to fit into a DIN mount case,
 it uses every GPIO pin on the cubietruck's main GPIO header. Making
-this board was about half the project. It got pretty tight in there.
+this board took 40+ hours, and was about half the project. It got
+pretty tight in there.
+
+This was my first foray into DIN rail mount, and it really is industrial
+lego -- a whole universe of parts that all fit together and are immensely
+flexible. Often priced more than seems reasonable for a little bit of
+plastic and metal, until you look at the spec sheets and the ratings.
+(Total cost for my panel was $400.) It's odd that it's not more used
+outside its niche -- I came of age in the Bay Area, surrounded by rack
+mount equipment, but no DIN mount equipment. Hacking the hardware in
+a rack is unusual, but DIN *invites* hacking.
 
-This was my first forway into DIN rail mount, and it really is industrial
-lego -- a whole universe of parts that all fit together. This is a second
-system kind of project, replacing some unsightly shelves full of gear
-with something kind of overdone. But should be worth it in the long run
-as new gear gets clipped into place.
+Admittedly, this is a second system kind of project, replacing some
+unsightly shelves full of gear and wires everywhere with something kind
+of overdone. But should be worth it in the long run as new gear gets
+clipped into place and it evolves for changing needs.
 
 Also, wire gutters, where have you been all my life?
 
-[[!img DIN/gearwall.jpg alt="A small utility room with an entire wall
+[[!img pics/DIN/gearwall.jpg size=500x 
+alt="A small utility room with an entire wall
 covered with electronic gear, including the DIN rail, which is surrounded by
 wire gutters"]]
+[[!img pics/DIN/wiregutter.jpg size=500x 
+alt="A wire gutter with the cover removed.
+Numerous large and small wires run along it and exit here and there."]]
 
 Finally, if you'd like to know what everything on the DIN rail is, from
 left to right: Ground block, 24v DC disconnect, fridge GFI, spare GFI, USB
@@ -56,5 +76,6 @@ hub switch, computer switch, +24v block, -24v block, IO daughterboard, 1tb
 SSD, arm board, modem, 3 USB hubs, 5 relays, AC hot block, AC neutral
 block, DC-DC power converters, humidity sensor.
 
-[[!img DIN/dinrailleft.jpg alt="DIN rail as described above, left side."]]
-[[!img DIN/dinrailright.jpg alt="DIN rail as described above, right side."]]
+[[!img pics/DIN/dinrailleft.jpg alt="DIN rail as described above, left side."]]
+[[!img pics/DIN/dinrailright.jpg alt="DIN rail as described above, right side."]]
+
diff --git a/blog/pics/DIN/wiregutter.jpg b/blog/pics/DIN/wiregutter.jpg
new file mode 100644
index 00000000..53d41005
Binary files /dev/null and b/blog/pics/DIN/wiregutter.jpg differ

add
diff --git a/blog/entry/DIN.mdwn b/blog/entry/DIN.mdwn
new file mode 100644
index 00000000..0ab512d2
--- /dev/null
+++ b/blog/entry/DIN.mdwn
@@ -0,0 +1,60 @@
+My offgrid house has an industrial automation panel.
+
+[[!img DIN/dinrail.jpg alt="A row of electrical devices, mounted on a
+metal rail. Many wires neatly extend from it above and below,
+disappearing into wire gutters."]]
+
+I started building this in February, before covid-19 was impacting us here,
+when lots of digikey orders were no big problem, and getting an unusual
+3D-printed DIN rail bracket for a SSD was just a couple clicks.
+
+I finished a month deep into social isolation and quarentine, scrounging
+around the house for scrap wire, scavenging screws from unused stuff and
+cutting them to size, and hoping I would not end up in a "need just one
+more part" situation.
+
+It got rather elaborate, and working on it was often a welcome distraction
+from the news when I couldn't concentrate on my usual work.
+
+The panel has my house's computer on it, as well as both AC and DC power
+distribution, breakers, and switching. Since the house is offgrid, the panel
+is designed to let every non-essential power drain be turned off, from
+my [[offgrid_fridge|fridge]] to the 20 terabytes of
+[[offline_storage|usb_drives_with_no_phantom_load]] to the
+[[inverter|AIMS_inverter_control_via_GPIO_ports]] and satellite dish,
+the spring pump for my [[gravity_flow_water_system|hacking_water]], and
+even the outlet by the kitchen sink.
+
+(Saving power is part of why I'm using old-school relays and stuff and not
+IOT devices, the other reason is of course: IOT devices are horrible.)
+
+[[!img DIN/daughterboard.jpg alt="Two circuit boards, connected by numerous
+ribbon cables, and clearly hand-soldered. The smaller board is suspended
+above the larger."]]
+[[!img DIN/schematic.jpg alt="An electrical schematic, of moderate complexity."]]
+
+At the core of the panel, next to the cubietruck arm board, is a custom
+IO daughterboard. Designed and built by hand to fit into a DIN mount case,
+it uses every GPIO pin on the cubietruck's main GPIO header. Making
+this board was about half the project. It got pretty tight in there.
+
+This was my first forway into DIN rail mount, and it really is industrial
+lego -- a whole universe of parts that all fit together. This is a second
+system kind of project, replacing some unsightly shelves full of gear
+with something kind of overdone. But should be worth it in the long run
+as new gear gets clipped into place.
+
+Also, wire gutters, where have you been all my life?
+
+[[!img DIN/gearwall.jpg alt="A small utility room with an entire wall
+covered with electronic gear, including the DIN rail, which is surrounded by
+wire gutters"]]
+
+Finally, if you'd like to know what everything on the DIN rail is, from
+left to right: Ground block, 24v DC disconnect, fridge GFI, spare GFI, USB
+hub switch, computer switch, +24v block, -24v block, IO daughterboard, 1tb
+SSD, arm board, modem, 3 USB hubs, 5 relays, AC hot block, AC neutral
+block, DC-DC power converters, humidity sensor.
+
+[[!img DIN/dinrailleft.jpg alt="DIN rail as described above, left side."]]
+[[!img DIN/dinrailright.jpg alt="DIN rail as described above, right side."]]
diff --git a/blog/pics/DIN/daughterboard.jpg b/blog/pics/DIN/daughterboard.jpg
new file mode 100644
index 00000000..2444bfb1
Binary files /dev/null and b/blog/pics/DIN/daughterboard.jpg differ
diff --git a/blog/pics/DIN/schematic.jpg b/blog/pics/DIN/schematic.jpg
new file mode 100644
index 00000000..b9573d73
Binary files /dev/null and b/blog/pics/DIN/schematic.jpg differ

Request to add a --editor flag to vidir and make it understand file URIs
diff --git a/code/moreutils/discussion.mdwn b/code/moreutils/discussion.mdwn
index f6e621d6..f11410e3 100644
--- a/code/moreutils/discussion.mdwn
+++ b/code/moreutils/discussion.mdwn
@@ -274,6 +274,19 @@ It computes the number of days between two dates and can check whether a date ex
 
 ## vidir
 
+I hope this is the right place to make any propositions.
+Vidir is the, by far, most powerfull mass renaming tool I am aware of, but unfortunately it is limited to terminal use only.
+However, sometimes I want to do mass renaming from a graphical file browser, atm this is possible by opening the current folder in terminal and typing vidir.
+Many file browsers (e.g. nemo, nautilus, thunar) allow you to specify a command for mass renaming purposes which brings me to the following two limitations:
+
+* In most of these file-browsers the file names are given as URIs which vidir doesn't seem to understand
+
+* My EDITOR variable is, of course, set to vim therefore, it doesn't work from a graphical context.
+  It would be nice if vidir would understand a command line flag like --editor where one could set an editor (e.g. gvim) only for the current session
+
+-- Mani
+
+
 A suggestion regarding vidir:
 I would find it quite useful if vidir could work with version control system commands like:
 

Added a comment: Excited to try git-annex
diff --git a/blog/entry/how_I_maybe_didnt_burn_out/comment_6_cd08526d09c26cd14d984c06b9d0e21a._comment b/blog/entry/how_I_maybe_didnt_burn_out/comment_6_cd08526d09c26cd14d984c06b9d0e21a._comment
new file mode 100644
index 00000000..220a2245
--- /dev/null
+++ b/blog/entry/how_I_maybe_didnt_burn_out/comment_6_cd08526d09c26cd14d984c06b9d0e21a._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="pannekoek"
+ avatar="http://cdn.libravatar.org/avatar/676a7c403af0627c9bde84ee1ab3975c"
+ subject="Excited to try git-annex"
+ date="2020-03-27T18:19:11Z"
+ content="""
+git-annex seems really cool! I'm one of those users who has large repository of source files I want to track with \"vanilla git\" and one subdirectory of very large files I want to manage with git-annex. Pardon me if this is mention elsewhere, but how can I set up git annex v7 to only annex files I explicitly \"git annex add\" and otherwise leave \"git add\" unchanged?
+
+Thanks for all of your hard work. Your many projects and experiments in off-grid living are an inspiration.
+"""]]