Skip to content

Notes

Small techniques, curious observations, and short stories.
Choose a tag. Hold Command or Control to combine tags.

Base52 moment stamps

 3 min Nine ASCII-ordered characters of microseconds that byte-sort by time and omit A, E, I, O, and U, reducing accidental matches when keys live inside model prose.

Sep 23, 2026

Taekwondo with my daughter

 2 min She is the blue belt; I am the yellow.

Sep 19, 2026

EOF after the parent disappears

 2 min A small guardian process ties a command group to its Python parent’s lifetime through a pipe, even when Python cannot run its own cleanup.

Aug 17, 2026

A read that rewrites the index

 1 min Spice disables Git’s optional refresh locks in its internal child processes so observation does not replace the index a hook is checking.

Aug 16, 2026

The hook’s old value

 2 min A reference-transaction guard must inspect the live pre-transaction tip when Git’s input contains only the caller’s declared old value.

Aug 7, 2026

Proving a database disposable

 2 min Spice separates replayable observations from durable authority and publishes a rebuilt projection only after its whole family is ready.

Jul 26, 2026

The wake file is not the store

 2 min A task revision can stay unchanged while its backing store is replaced, so Spice checks both logical revision and physical store evidence.

Jul 26, 2026

The two-offset contract

 2 min Reading a live JSONL file needs two positions: where reading stopped and the last complete record from which it can safely resume.

Jul 26, 2026

When waiting begins

 2 min A task’s starvation age starts when it becomes ready. That timestamp must be stored before an allocator can observe the transition.

Jul 22, 2026

The three Git roots

 2 min A linked worktree has shared Git state, per-worktree Git state, and a visible worktree root. Hook installation crosses all three.

Jul 21, 2026

The sqlite3 close trap

 2 min Python’s sqlite3 context manager ends a transaction but leaves the connection open. A finally block owns the close.

Jul 15, 2026

The ACK grammar

 2 min Supervising an agent through prose alone: an item is handled only when the reply echoes its durable key, with rules for separating acknowledgments from examples.

Jun 30, 2026

nftables listed the wrong byte order

 1 min Missing nftables set and map metadata made correct kernel values print in the wrong byte order.

Feb 11, 2026

Still on the Couch

 2 min Xbox and the games our family keeps playing together, from BattleBlock Theater to SpiderHeck.

Jan 1, 2026

The last extra argument

 3 min In letter.sh’s extended merge form, Bash array slicing moves the last extra argument into pdfcpu’s destination slot.

Mar 4, 2025

A sauna downstairs

 1 min The electrical panel went in two years before the sauna it was for. I finally asked for the heater to be wired. It works great.

Jan 21, 2025

Land with a stream

 1 min Wooded land we have not visited as much as we want. A little mowing opens a path to the stream and a campsite; the rest is untamed.

Aug 6, 2024

printf %n

 2 min C’s notorious write-through format directive lives on in bash, where one format string yields output and measured byte offsets.

Jun 22, 2024

The stateful generator

 2 min A bash parameter expansion whose array subscript advances every time it expands.

Jun 22, 2024

Millimeters and arcminutes

 2 min layoutc keeps meter and degree scales plus its full-turn constant in one IntEnum, using arcminutes to keep both angular constants integral.

May 20, 2024

One bit in the rounding gap

 2 min layoutc stores a quadrant in the sign of a micron-scale nudge that the codec’s 1.5 mm grid snap folds back to exactly zero.

May 20, 2024

A hosts file for one service

 1 min A systemd bind mount gave each Snap lobby its own hosts file while leaving the host machine’s resolver file in place.

Apr 15, 2023

A pidfile that is really a cgroup

 3 min Encoding cgroup2 CPU limits into a --pidfile flag, so moving a PID between two cgroups becomes the whole throttle.

Sep 10, 2022

The .lock rename as a publish protocol

 3 min Write file.lock, rename to publish, and use a 200ms batch to coalesce the usual staging and final filesystem notifications.

Sep 10, 2022

Empty, newline, or JSON

 3 min A watched control directory where an empty file with no newline resets, an empty file with a newline means now, and anything else is JSON.

Sep 10, 2022

The xattr fell outside the commit

 2 min snap-gs tried to publish file bytes and future S3 headers through one rename, but ignored errors let the rename commit either half alone.

Sep 10, 2022

Docker transfer settings in kOps

 1 min Exposing Docker transfer settings in kOps required carrying them through internal types, versioned APIs, conversions, copies, and the CRD.

Sep 13, 2021

Another father and son

 1 min A paintball seller wanted his equipment to go to someone who would make more memories with it.

Jul 12, 2021

Only Four

 2 min Returning to paintball with my son, accumulating too much gear, and deciding what was fit to pass on.

Jun 26, 2021

A Book We Could Hold

 2 min Emily wrote Braving Uncertainty, Nick Purvis drew it, and I helped turn the pages into a printed book.

Apr 18, 2021

Two commas and no error

 1 min A nil embedded Go pointer made one JSON encoder emit an extra comma; comparing the same value with the standard encoder isolated it.

Aug 4, 2020

Circle inside a triangle

 3 min Emily and I got our first tattoos on Leap Day 2020. Mine was the Fano plane, and the artist did not do geometric work, so I had to say which part of the shape mattered.

Feb 21, 2020

The target was already there

 1 min One Makefile alias exposed Kubernetes’ existing OpenAPI generator without adding another implementation.

Aug 8, 2019

The type disappeared

 2 min Inlining OpenAPI references preserved fields while removing the type identity that policy transforms needed.

Apr 23, 2019

Pushing terminfo over ssh’s stdin

 2 min Fixing ‘unknown terminal type’ by streaming terminfo through ssh’s stdin and compiling it remotely, with no separate copy step.

Apr 9, 2019

A desk that stops

 1 min A dual-motor standing frame under a butcher-block top from Menards. The memory buttons stop it dead. I am still sitting at it.

Feb 16, 2019

Between teams

 2 min From judging Technovation apps to helping teams at Wayzata Central Middle School make their own.

Feb 4, 2019

Which coordinate changed?

 2 min Two Mini Delta leveling defects came from different numerical mistakes: applying a delta as an absolute value and forgetting to square one axis.

Jan 12, 2019

Printer profile as source

 3 min I kept my Mini Delta’s slicer profile in Git, with derived settings and calibration changes recorded as diffs.

Dec 25, 2018

td

 2 min A tmux session keyed by a raw directory path, with extra commands smuggled through a trailing semicolon.

Oct 31, 2018

Maintaining the invariant

 2 min The cost of coordination does not disappear when a meeting does.

Jul 12, 2018

atexit for bash

 3 min A LIFO exit-handler stack from jira-nice, with a nonstandard signal map and a broken pop-by-count path.

Jun 4, 2018

The repo is the .jira.d

 2 min jira-nice makes its own checkout the go-jira config directory with one symlink, and inherits a parent repo’s Jira defaults with one extra glob path.

Jun 4, 2018

shutils.jq

 3 min Turning jira-nice’s JSON options into Bash declarations, with a saved JSON copy and some sharp limits on what can cross the boundary.

Jun 4, 2018

Escaped spaces in tmux’s terminfo

 1 min Twelve escaped spaces interrupted tmux’s SGR capability; removing them restored the intended terminal control sequence.

May 16, 2018

Truecolor escapes in diff-so-fancy

 1 min Bold plus truecolor foreground and background exceeded diff-so-fancy’s seven-field escape-sequence limit.

May 7, 2018

The q Family

 2 min About thirty git aliases built on a grammar: q queries, suffix letters add verbs, doubling escalates, a trailing q quiets, and a bang means force.

Apr 18, 2018

diff-so-fancy Without the Pipeline

 2 min A git pager that runs diff-so-fancy inside less via LESSOPEN and degrades to plain less on machines that don’t have it.

Apr 15, 2018

Exit 99

 2 min Dotfiles that fast-forward themselves at login and re-exec the running shell, coordinated by one exit code.

Apr 11, 2018

The FETCH_HEAD Throttle

 2 min date -r FETCH_HEAD as the entire last-fetch database: no state file, a 12-hour window, and an epoch backdate to force retries.

Apr 9, 2018

cognito

 3 min A tiny shell private mode that stops history, makes up-arrow forget, and hides its own switches.

Mar 28, 2018

mkdir elects one builder

 3 min Atomic directory creation elects one builder, but every error is treated as a lost race and losers continue before the winner is ready.

Mar 27, 2018

The socket car

 3 min My son’s Pinewood Derby car was a pine plank with a chrome socket at the tail. Number 40 finished one spot out of the trophies.

Mar 10, 2018

The deferred namespace

 3 min A custom Python namespace records imports, then resolves deferred names on first lookup.

Sep 11, 2017

Source ready to distribute

 2 min A source release can include generated C, headers, and version data without requiring those artifacts to live in the original checkout.

Jul 10, 2017

Why not ZIP?

 1 min In the packaging discussion I favored ZIP’s mechanics and Python’s existing use of it; the source-distribution contract chose tar.gz.

Jun 15, 2017

Let the client carry the bytes

 1 min An S3 upload proxy became unnecessary once the service could authorize an upload by returning a presigned URL.

Oct 20, 2016

The old certificate still matters

 1 min A Convox proposal left certificate replacement to CloudFormation and kept the previous certificate available for rollback.

Mar 21, 2016

The stack’s other name

 2 min Convox needed rack-scoped cloud identities while keeping short application names and recognizing stacks created under the old naming scheme.

Feb 8, 2016

D is for dog

 1 min A little Python program I wrote with my first-grade son: type a letter, hear an animal.

Dec 8, 2015

Materializing a default

 1 min settingsd copied a mutable fallback correctly, then lost edits because the copy had never become namespace state.

Mar 6, 2015

Logging after the fact

 3 min retrospect instrumented already-compiled Python functions by swapping in rewritten code objects at runtime—and restored the exact original on request.

Dec 1, 2014

Validation before initialization

 1 min Python-SAML checked for embedded certificates through state its constructor had not assigned yet.

Nov 26, 2014

Reading a kernel version out of a bzImage

 2 min hexdump plus strings pulls the version string from a kernel image via the x86 boot protocol’s version pointer at offset 0x20E.

Aug 15, 2014

The polyglot activate script

 2 min zippy’s bin/activate was six lines valid in both bash and Python, and sourcing it executed itself to print its own exports.

Jun 5, 2014

NUL-joined argv

 2 min Write a readable Python argv literal with NUL separators, provided every formatted value is NUL-free.

Jun 3, 2014

The settrace ambush

 3 min CPython 2 had no general hook after PySys_SetArgv finalized startup state but before user code, so zippy’s site.py armed a one-shot trace function.

Jun 3, 2014

Callable modules

 2 min A CPython experiment put a module body inside a function, made attributes share its globals, and used a call to execute it again.

Mar 14, 2014

A file with size zero

 1 min uWSGI read a procfs setting as empty because its file reader trusted stat size instead of reading to EOF.

Feb 10, 2014

Returning the fault

 1 min Suds could return different fault types through different paths; I proposed returning the same WebFault object callers could otherwise catch.

Jan 23, 2014

The other serializer

 1 min A Celery event setting failed despite an explicit accept list, and embedding the worker in uWSGI amplified the retry loop.

Dec 13, 2013

A Desk at Schlitz Park

 2 min A desk at Corvisa’s Schlitz Park office, and the team where I learned to stop building past the problem.

Oct 16, 2013

Quotes for the next parser

 2 min A Distil build exposed two separate needs: keep the compiler argument together, and preserve the quotes inside its C macro value.

Aug 19, 2013

The mapping constructor

 1 min A one-line Spyne change let the configured mapping type receive the member pairs the serializer already produced.

Jul 15, 2013

python32.3

 1 min A bulk shebang rewrite left gprof2html.py asking for an interpreter that never existed. Arch was patching it with sed, so I sent the report upstream.

Apr 20, 2013

A Rack of My Own

 2 min A rolling workstation that kept the screens, computers, and cabling together whenever I moved.

Apr 6, 2013

[b]in

 2 min Wrapping one letter in a character class turns every PATH candidate into an existence test.

Jan 28, 2013

The VPython Years

 2 min I learned Python for a 3D library, then kept following its imports and build machinery into the language itself.

Jan 15, 2013

Before partialmethod

 2 min The Python 2 recipe for binding a functools.partial as a method—three-argument MethodType plus update_wrapper—and the stdlib name that replaced it.

Nov 13, 2012

A paste from the terminal

 2 min Adding multipart uploads to pastie-sane meant accepting files, recognizing compressed text, and returning a link a shell user could use.

Oct 20, 2012

Nested AMQP tables through librabbitmq

 2 min An unmerged librabbitmq patch taught a Python/C boundary to carry nested AMQP tables and arrays instead of flattening their structure.

Oct 12, 2012

A logo that was a glyph

 2 min Drawing the pyjs logo into a font, then losing it during conversion.

Oct 2, 2012

Relocatable Python with $ORIGIN

 3 min A runtime library path relative to the executable lets a built interpreter move as a tree—verified in the ELF policy and the loader’s result.

Sep 13, 2012

bcrypt in the auth query

 2 min A pam_pgsql path could not verify Django’s bc$ bcrypt value directly, so SQL performs the check and returns the submitted password as its own answer.

Sep 6, 2012

Before the handler

 1 min Missing AMQP properties could trap Kombu in a delivery-time KeyError before user code received the message.

Jul 31, 2012

Converting a daemon by deleting machinery

 2 min The systemd conversion checklist from a mailing-list reply: forking, pidfiles, private logs, and stop scripts all come out.

Jul 27, 2012

$JAVA_OPTS is an argv problem

 2 min One variable string becomes one argument or several depending on who tokenizes it—verify the argv, not the config text.

Jul 27, 2012

After the image is built

 2 min A PandaBoard needed one more image-wrapping step after mkinitcpio, and the available extension points ran at the wrong stage.

Jul 19, 2012

A missing zero in fwknop

 1 min An idle fwknop daemon kept waking because a microsecond constant disagreed with the fraction written beside it.

Jul 15, 2012

The self:// Remote

 2 min A made-up URL scheme as the dotfiles origin, resolved per machine by layered insteadOf rewrites—local mirror for fetches, GitHub for pushes.

Jul 14, 2012

The type of infinity

 1 min Spyne’s unbounded defaults used float infinity, which made Decimal validation depend on the Python version.

Jul 12, 2012

Comments at the parser boundary

 1 min XML comments were becoming empty RPC models; configuring the parser removed them before either decoder saw them.

Jun 24, 2012

Optional and nil

 2 min Two Spyne fixes separated whether an XML element must appear from whether its value may be nil.

Jun 19, 2012

Process substitution as a pipe endpoint

 2 min A successful read-write open retains a process substitution’s pipe for independently launched producers and consumers.

Mar 10, 2012

Dropping a job from Bash’s table

 2 min A Bash idiom let an outer subshell finish while a grandchild kept running; it was a narrow SSH workaround, not portable daemonization.

Mar 10, 2012

Sourcing generated shell is still execution

 2 min Using /dev/stdin avoids eval’s call-site quoting hazard and keeps generated code inspectable; it does not reduce the injection surface.

Mar 10, 2012

A Train World

 1 min A quieter tabletop, a collection of Target train pieces, and one connected wooden railway.

Jan 5, 2012

Appending compressed logs

 1 min An old mirror script appended complete gzip members, letting each run add compressed output without reopening the previous stream.

Oct 31, 2011

The CR-48’s developer switch

 3 min An exchange with Richard Stallman about whether Chrome OS notebooks let their owners replace the software, after I had put Arch on a CR-48.

Aug 31, 2011

Pushing Into a Live Home Directory

 2 min receive.denyCurrentBranch = ignore plus a post-update hook let one machine push straight into another’s checked-out $HOME.

Aug 26, 2011

Propagation is a direction

 3 min Mount propagation is two separate trust decisions, not one switch—the argument from an lxc-users thread about read-only roots.

Jul 19, 2011

Read mountinfo first

 3 min Before explaining a mount, read /proc/self/mountinfo—the kernel’s live table shows what mount(8) output hides.

Jul 19, 2011

The missing python2 shebang

 1 min Pygments recognized python and python2.7 but missed python2, just as Arch made the major-version name useful.

Mar 26, 2011

The 2011 KVM diagnostic

 2 min Checking QEMU’s arguments and open KVM descriptors to distinguish configured acceleration from the running process.

Feb 24, 2011

The shape of a successful build

 1 min Comparing file lists and sizes between successful builds can catch packaging regressions that exit codes never will.

Jan 28, 2011

Omitted for Brevity

 3 min My current résumé compresses seven years into three lines. The 2010 résumé it replaced still remembers what they hold.

Sep 8, 2010

Borders only inside the table

 2 min Internal table borders with no outer border—border-collapse plus border-style: hidden, and the conflict-resolution rule that does the work.

Jul 28, 2010

The prompt that asks the kernel

 2 min A bashrc derived container identity from /proc/self/cgroup and prefixed the prompt with VPS[name]—no environment variable involved.

Feb 11, 2010

The directory is the dispatch table

 3 min vps-lxc discovered its subcommands by listing a directory, with one sed filter as the entire registration policy.

Feb 11, 2010

A cleanup stack in Bash

 3 min vps-lxc registers cleanup handlers in an array and unwinds them newest-first on fatal errors or signals.

Feb 11, 2010

runlevel(8) reads whatever utmp you point it at

 2 min A container supervisor read a guest’s shutdown intent from the guest’s own utmp, because runlevel accepts an alternate path.

Feb 10, 2010

Two Import Interfaces

 2 min A teaching library’s wildcard namespace and an integrator’s explicit namespace are different interfaces, and a module can carry both on purpose.

Oct 22, 2009

Pinning a HUD to a Moving Camera

 2 min A label pinned to the viewport exposes the difference between world, camera, and screen coordinates.

Oct 22, 2009

Teaching Aliasing with Streams

 1 min Open streams and database connections gave me a useful way to explain Python assignment: another name refers to the same live resource.

Sep 13, 2009

A Dependency Edit Does Not Change an ABI

 1 min Changing package metadata changes what the package manager accepts; it does not establish that a compiled artifact can run against a new interpreter.

Sep 4, 2009

Threading Film at the State Theatre

 3 min A projectionist job in high school, and the website I came back to build years later—my first commercial development project.

Oct 1, 2006

This stuff is very cold!

 2 min Sidney won the Montana Science Olympiad in November 2003 and went to nationals in Pennsylvania. I do not remember my events. I remember a Nobel laureate stuffing balloons into liquid nitrogen.

May 21, 2004
No matching items