All posts

This is every post I’ve ever written, organised by category. You can subscribe to my posts as an Atom feed. Enjoy!

Most recent 10 posts

Jun 2019 An inescapable conclusion
Jun 2019 A Jekyll filter for obfuscating email addresses
Jun 2019 读一本中文字典 / Reading a Chinese dictionary
Jun 2019 Converting Acorn images on the command-line
Jun 2019 Hey Apple, cycle tracking isn’t just for women
Jun 2019 A script for getting cover images from mobi ebooks
May 2019 Questions to ask when writing a trans inclusion policy
May 2019 Falsehoods programmers believe about Unix time
May 2019 Creating a locking service in a Scala type class
May 2019 Finding unused variables in a Terraform module

Blogging about blogging

Jun 2019 A Jekyll filter for obfuscating email addresses
Feb 2019 Checking Jekyll sites with HTMLProofer
Oct 2017 What happens when you overengineer a static site?
May 2016 Finding 404s and broken pages in my Apache logs
Dec 2014 RSS linkposts in Pelican
Sep 2014 Playing with 404 pages

Build automation and build systems

Mar 2019 Creating a GitHub Action to auto-merge pull requests
Aug 2018 Finding slow builds in Travis
Aug 2018 Selective sudo on Travis
Mar 2018 The Hypothesis continuous release process
Dec 2017 Your repo should be easy to build, and how

Diversity, inclusion and accessibility

Jun 2019 An inescapable conclusion
Jun 2019 Hey Apple, cycle tracking isn’t just for women
May 2019 Questions to ask when writing a trans inclusion policy
Feb 2019 More advice on running inclusive and welcoming events
Oct 2018 Open consultation on the Gender Recognition Act
Sep 2018 Content warnings
Aug 2018 Ideas for inclusive conferences and events
Nov 2017 How I ask about gender
Oct 2017 NPR: Graduation Readers At MIT Go The Extra Mile To Pronounce Names Correctly
Apr 2017 Accessibility at AlterConf
Feb 2016 How I use TextExpander to curb my language


Jun 2019 读一本中文字典 / Reading a Chinese dictionary

Organising PyCon UK

Sep 2018 Signs of the time
Sep 2018 PyCon UK 2018
Aug 2018 Making the venue maps for PyCon UK
Oct 2017 Lightning talks
Sep 2016 Silence is golden
Sep 2016 Live captioning at conferences


Mar 2019 A day out to the Forth Bridge
Nov 2018 My visit to the Aberdulais Falls
Jun 2017 A visit to the Crossness pumping station

Programming and code

Jun 2019 A script for getting cover images from mobi ebooks
May 2019 Falsehoods programmers believe about Unix time
May 2019 Creating a locking service in a Scala type class
May 2019 Finding unused variables in a Terraform module
Apr 2019 Reversing a URL to the original tweet
Apr 2019 Getting a transcript of a talk from YouTube
Mar 2019 Finding the latest screenshot in macOS Mojave
Mar 2019 Atomic, cross-filesystem moves in Python
Jan 2019 Debugging a stuck Terraform plan
Dec 2018 Notes on reading a UTF-8 encoded CSV in Python
Dec 2018 Iterating in fixed-size chunks in Python
Dec 2018 A script for backing up Tumblr posts and likes
Oct 2018 Custom 404 responses in Finatra
Aug 2018 Avoiding the automatic redirect on Tumblr posts
Jul 2018 A robot leaked my SSH keys
May 2018 Drawing ASCII bar charts
May 2018 Beware of logged errors from subprocess
Oct 2017 Using hooks for custom behaviour in requests
Oct 2017 Four ways to underline text in LaTeX
Oct 2017 Using pip-tools to manage my Python dependencies
Sep 2017 A Python module for lazy reading of file objects
Jul 2017 Backing up full-page archives from Pinboard
Jul 2017 Backing up content from SoundCloud
Mar 2017 A few examples of extensions in Python-Markdown
Feb 2017 A script for backing up your Instapaper bookmarks
Feb 2017 A script for backing up your Goodreads reviews
Jan 2017 A Python interface to AO3
Jan 2017 Experiments with AO3 and Python
Dec 2016 A tool for backing up your message history from Slack
Nov 2016 Use keyring to store your credentials
Oct 2016 Creating low contrast wallpapers with Pillow
Oct 2016 Tiling the plane with Pillow
Oct 2016 Why I use py.test
Oct 2016 A shell alias for tallying data
Aug 2016 Python snippet: dealing with query strings in URLs
Aug 2016 Python snippets: Is a URL from a Tumblr post?
Aug 2016 Python snippets: Cleaning up empty/nearly empty directories
Jul 2016 Python snippets: Chasing redirects and URL shorteners
Jun 2016 Reading web pages on my Kindle
May 2016 A Python smtplib wrapper for FastMail
May 2016 Safely deleting a file called ‘-rf *’
Apr 2016 Hiding the YouTube search bar
Apr 2016 Treat regular expressions as code, not magic
Mar 2016 Exclusively create a file in Python 3
Dec 2015 Pretty printing JSON and XML in the shell
Nov 2015 Backups and Docker
Nov 2015 Export a list of URLs from Safari Reading List
Nov 2015 Quick shell access for Docker containers
Aug 2015 Finding even more untagged posts on Tumblr
Jul 2015 Useful Bash features: exit traps
Jun 2015 Persistent IPython notebooks in Windows
Jun 2015 Safer file copying in Python
May 2015 Cloning GitHub’s Contributions chart
May 2015 Previewing notes from nvALT in Marked
Mar 2015 Pygmentizr
Mar 2015 Adding Python to the OS X firewall
Feb 2015 Adding checkboxes to lists
Feb 2015 Swift 1.2 improves the “let” keyword, and other improvements
Dec 2014 A script for exporting from iMessage
Nov 2014 Unpacking sets and ranges from a single string
Oct 2014 Notes on Tumblr
Aug 2014 Updates to my site for finding untagged Tumblr posts
Aug 2014 A TextExpander snippet for Amazon affiliate links
Aug 2014 A quick Alfred workflow for opening recent screenshots
Jul 2014 Getting plaintext LaTeX from Wolfram Alpha
Jun 2014 Finding untagged posts on Tumblr, redux
Aug 2013 Cleaning up Google Maps
Aug 2013 Finding untagged posts on Tumblr


Jan 2019 Monki Gras 2019: The Curb Cut Effect
Sep 2018 Assume worst intent (designing against the abusive ex)
Sep 2018 Building trust in an age of suspicious minds
Apr 2018 (Anti) Social Media
Nov 2017 Using privilege to improve inclusion
Sep 2017 Ode to docopt
Jun 2016 Introduction to property-based testing
Jun 2016 Introduction to property-based testing

Working with AWS

Feb 2019 Working with really large objects in S3
Dec 2018 Getting credentials for an assumed IAM Role
Nov 2018 Finding SNS topics without any subscriptions
Sep 2018 A basic error logger for Python Lambdas
Aug 2018 Implementing parallel scan in DynamoDB with Scanamo
Apr 2018 Two shortcuts for using S3 in the shell
Jan 2018 Getting every message in an SQS queue
Jan 2018 Listing keys in an S3 bucket with Python, redux
Nov 2017 Downloading logs from Amazon CloudWatch
Jul 2017 Listing keys in an S3 bucket with Python

Working with Git

Mar 2018 Notes on A Plumber’s Guide to Git
Nov 2017 Pruning old Git branches
Nov 2017 A plumber’s guide to Git
Sep 2017 Some useful Git commands for CI
Jun 2015 Useful Git features: a per-clone exclude file

Working with macOS

Jun 2019 Converting Acorn images on the command-line
Jul 2016 Clearing disk space on OS X
May 2016 “The document could not be saved”
Mar 2016 Get images from the iTunes/App/Mac App Stores with Alfred
May 2015 One-step paste in the iOS Simulator
Jun 2014 Catching instapaper:// URLs from ReadKit


Apr 2019 Some tips for conferences
Apr 2019 How I back up my computing devices, 2019 edition
Jan 2019 Notes from You Got This 2019
Jan 2019 How much sunlight affects my mood levels
Jan 2019 Thoughts on privacy and Oyster cards
Jan 2019 A delightful store for speciality spreads: Paul Rothe & Sons
Nov 2018 Keeping track of my book recommendations
Oct 2018 How do you hide a coin for 400 years?
Oct 2018 How to set the clock on a Horstmann Electronic 7 water heater
Aug 2018 Do Not Distract while driving
Jul 2018 Moving my calendars from iCloud to FastMail
Jul 2018 A tip for travel instructions
Jul 2018 My favourite iMac accessory
May 2018 A brief thought on Google Duplex
Apr 2018 24 hours or bust
Mar 2018 Keep an overnight bag in the office
Feb 2018 A working from home experiment
Jan 2018 IP and DNS addresses for documentation
Dec 2017 Armed police officers don’t make me feel safer
Nov 2017 My favourite WITCH story
Nov 2017 Don’t tap the mic, and other tips for speakers
Oct 2017 PyCon UK 2017 resources
Oct 2017 Displaying tweets in Keynote
Oct 2017 Control Centre: one step forward, two steps back
Dec 2016 Another example of why strings are terrible
Nov 2016 Some low-tech ways to get more ideas
Oct 2016 The A stands for Asexual
Sep 2016 My travelling tech bag
Sep 2016 aspell, a command-line spell checker
Jun 2016 A subscription for my toothbrush
Mar 2016 Backup paranoia
Feb 2016 Saved by the Prompt
Jan 2016 The Harry Potter Collector’s iPod
Jan 2016 The Skeletor clip loop, 2015 edition
Jan 2016 A cautionary tale about Fusion Drive repairs
Dec 2015 Simpler syndication, by Dr. Drang
Nov 2015 Email with a purpose
Nov 2015 Python and the BBC micro:bit
Sep 2015 What does “Spotlight Suggestions” turn off?
Sep 2015 Apple quietly adopts HTTP/2
Sep 2015 Review: Effective Python
Mar 2015 Some exam advice
Feb 2015 Tidying up my 1Password
Feb 2015 A Flask app for taking notes
Dec 2014 Kitchen sink security
Dec 2014 Acronyms
Dec 2014 Skeletors All the Way Down
Dec 2014 Lukas Mathis on iOS CarPlay and Android Auto
Oct 2014 “Missing argument at index 2” in fish
Sep 2014 My new standing desk
Jul 2014 Thoughts on Overcast
Jun 2014 Skeletor!
Jun 2014 Some site updates
May 2014 Some Part IA exam advice
May 2014 Brief advice for Part II
Apr 2014 Pulling back the veil
Nov 2013 TextMate 2 and Quick Look
May 2013 Podcast feeds on Tumblr
Mar 2013 Automatic Pinboard backups
Mar 2013 Strange clock bug in OS X
Mar 2013 Candybar and icon recommendations
Feb 2013 Darwin, pancakes and birthdays
Jan 2013 Zero
Dec 2012 Hypercritical