RSSAmplifier

Blog

Chris' Blog

Recent content on Chris' Blog

chriswheeler.devRSS feed ↗42 posts

Latest posts

Searching related files

Searching a category of files can be done in many ways. For example, a script that searches for a phrase in all GitHub Actions workflows on a computer could take only around a dozen lines of code in most languages. The best way overall I’ve found so far is with rg (ripgrep) in a bash script. It’s great because writing it doesn’t take long, the output formatting is useful, and…

Running terminal commands with Python

Running a terminal command with Python usually looks like this: import subprocess subprocess.run(['git', 'init'], check=True) Using check=True will make subprocess.run throw an exception if the command fails. If you don’t use check=True, you should probably check the return code yourself or the command could fail silently. You can catch errors like this: try: subprocess.run(['git', 'init'],…

Docker healthchecks

Whether a Docker container is healthy is not just about whether it’s running. A service could stop working properly without crashing. Docker can detect some of those kinds of invalid states when we define custom healthchecks. healthcheck in Docker Compose | Docker Docs HEALTHCHECK in Dockerfile | Docker Docs The way it works is you define a command for Docker to periodically run inside the…

Daily math

I built something that makes my life a little easier, maybe: a tiny mental math quiz: Daily Math. I want to maintain a little bit of mental math skills with minimal effort, and I heard one of the best ways is to pick two random numbers and then add, subtract, multiply, and divide them. Daily Math takes care of coming up with two random numbers and checking whether your answers are correct.

PDF generators

PDFs can be generated programmatically in several ways. A common use case is converting a website to PDF, but some of the tools listed below work for other use cases too. Converting a website to PDF If you’re okay with text not being selectable or searchable, you could use html-to-image to turn the site into images, and then put the images into a new PDF with jsPDF. Use JPEGs so the…

Restic and Time Machine

Restic and Time Machine (TM) are backup programs that complement each other with their different strengths and weaknesses. I now use both: Restic for remote backups and Time Machine for most local backups. Platforms TM is only available for MacOS while Restic runs almost anywhere. Ease of use TM is much easier to use than Restic. When you connect an external drive to your computer, a popup will…

How to install Ansible

Here’s a way to install Ansible that’s easier and more likely to work than the official instructions. Install uv if you haven’t already uv tool install ansible-core That’s it. You should now be able to use commands such as ansible, ansible-playbook, etc.

NGINX config for Immich

Immich is a self-hosted alternative to Google Photos. I’ve been running an instance for a few months now, and it’s great. Immich’s docs has a sample NGINX config, but there are a few changes you’ll probably want to make to it. Prevent indexing In the location / { ... } block, you should probably add a line that says add_header X-Robots-Tag "noindex, nofollow"; to prevent…

Cross-compilation with Wails

On 2025-12-9, I tested the cross-compilation of the official Svelte template of Wails v2.11.0, a desktop app framework for Go, on my amd64 laptop running Ubuntu 24 with Go v1.25.5. Of course, the results may change in the future as Wails and Go are being improved. Go is known for making cross-compilation much easier than most other languages, and that is mostly still true when using frameworks…

Project generators

A software project generator sets up the starting boilerplate for a project, filling in the new project’s name and other details in various places throughout the new files. Project generators make starting new projects much faster and lowers the barrier to quickly trying an idea. Their output can be much more reliable than that of LLMs. Like all tools, they are useful in some situations and…

Exit in Python

Python has several ways to make a program exit. exit should probably only be used to exit a Python REPL because it’s not safe to assume it’s defined. The sys.exit function is safe, but you might prefer to raise SystemExit instead because: they do the same thing and have the same interface sys.exit requires an additional import (import sys) sys.exit raises SystemExit without being…

Sync repos between devices using bash

Sometimes it’s helpful to sync a Git repository directly from one machine to another without using a Git host like GitHub. If you can SSH into the machine(s) involved, you can use Bash’s rsync command. Rsync’s defaults aren’t great for syncing repos for several reasons, but a Bash script can fix that. I named the script ,sync-repo: ,sync-repo .…

Python in Justfiles

Just is a tool for defining and running custom commands for specific projects. Justfiles are often compared favorably to makefiles. If you’re new to Just, check out Just Programmer’s Manual. A command definition in a justfile (a recipe) usually contains code written in the system’s default shell language, but Just lets you choose from many other languages including Python! This…

Browser extensions are risky

During the time I’ve been making browser extensions, I’ve learned about the amazing things they can do and how helpful they are, but also how dangerous they can be. Below are some examples of risks and ways to mitigate them. Some of the risks Even though browsers put limits on what extensions can do and require them to ask permission for some things, extensions can still do more than…

Disposable vs. masked email addresses

Sometimes it’s helpful to give the terms “disposable” and “masked” two different meanings when referring to types of email addresses. Both disposable addresses and masked addresses are great at protecting you from spam and phishing emails. Instead of giving out your main address, you can give out ones that are temporary or easy to replace. Some email protection…

Restic vs. Duplicati

Restic and Duplicati are both great for making backups of your computer’s files. I have experience with both. They’re mostly the same, but they have some differences that might be important depending on your needs. Similarities They’re the same in many ways, including: free open source versioning of backups choose specific files and folders to back up encryption compression…

Types of secrets management

When creating software, it’s common to deal with secrets like database passwords, API access tokens, etc. There are many ways to make secrets available to software. Below are notes on some of the ways. Threat Modeling might help you determine which way is best for what you are doing. Environment variables Putting secrets in environment variables (env vars) is very easy and might be fine if…

Security benefits of SQL stored procedures

Using stored procedures instead of putting SQL statements directly into a service’s code can increase security. There are multiple reasons why. Reduced attack surface The main security benefit is that hackers will be more limited in what they can do if the database credentials they steal can only call stored procedures. As a demonstration, let’s say your data can only be accessed by…

Making Discord bots

Discord bots run as web services that use Discord’s API. They listen for requests from Discord and send responses. They need their own databases if a way to persist data is necessary. However, some Discord bot features require saving some data about the bot in Discord’s servers, such as slash command names. Automated testing of Discord bots tends to be very limited or nonexistent since…

Pointers vs. references

Some differences between pointers and references can be confusing, especially since there are several different definitions for those words. This can make it difficult to answer simple questions like “Does Golang have reference types?” (TLDR: most people and the official Go FAQ say that Go does have reference types.) Pointers In some languages like C++, pointers can point anywhere in…

Go dev tools

Below are a bunch of commonly used packages and other tools for software development with Go. Go has excellent backwards and forwards compatability, so tools that haven’t been updated in a long time may still be a great choice. Unless otherwise noted, each tool listed here appears to me to be good enough at what it does that I don’t feel the need to look at alternatives. If…

Bookmarklets

Bookmarklets are browser bookmarks that run some JavaScript instead of navigating to a website. They can do anything JavaScript can do including change fonts, search for phone numbers, remove all images, change the background color, automatically fill a form, and so much more. This guide by Hongkiat Lim explains bookmarklets in more detail and lists many of the most popular ones. More examples…

PDF tools

Here are a bunch of tools I found for reading, editing, and more with PDFs. I have not tried all of these but they all look promising. Read Sumatra PDF is the best PDF reader for Windows. The default PDF readers on other platforms seem to work well. Edit, annotate, sign, or fill SimplePDF is an in-browser PDF editor. Some browsers, such as Firefox, include PDF editing tools. You can select a PDF…

Stardown v1.0.0

The first full version of Stardown has been released! Stardown is a free browser extension I created for copying markdown links for websites. One click on its icon copies a markdown link for the current page. A double-click copies markdown links for all tabs. Right-clicking a website gives you a markdown link for where you right-clicked. Although I have tons of bookmarks, I save even more website…

Making browser extensions

Creating browser extensions is easier than I expected, but still has some challenging parts. A great way to start learning how to make extensions is the Chrome dev docs. Creating your first extension requires a lot of trial and error. It gets easier as you learn how extensions work and how to use the browser APIs. On sites like Stack Overflow, many discussions have answers that make assumptions,…

Docker

Docker is a tool that makes running software easier by creating a container, which is like a little virtual computer with a more predictable configuration than most computers. Containers are very portable, by which I mean they can be created in and run in any operating system that can run Docker. For example, a container could run Linux within it, and the container itself could run on Mac,…

Value, reference, and move types and semantics

I see a lot of confusion about value types and references types. Although I’m not sure how common this perspective is, here’s how I think of it. First of all, value types have value semantics and reference types have reference semantics. The semantics of a type is the behavior of variables of that type. Let’s say there are two variables, a and b, that have already been created…

Don't put all your eggs in one account

Online accounts can be lost without warning, but making that loss less painful is easy. Full disclosure, there is one referral link marked with an asterisk (*) below that gives me account credit and gives a discount to anyone who signs up for a paid service with it. How much do you depend on the services of big tech companies like Google, Apple, or Microsoft? If one of your accounts was suddenly…

Tech literacy

There’s always room for improvements worth their time to make. Over years of extensively using computers, there are some tricks I’ve found that I don’t see others use as often as I expect. I’m not affiliated with any of the services, products, or companies mentioned here. learn about tech gradually and bravely Everyone becomes overwhelmed or frustrated by technology…

Why does privacy matter?

Privacy is not about whether you have something to hide. It’s about whether bad people can do bad things to you, because security is impossible without privacy. If others can look over your shoulder any time, they can see all your passwords. If you couldn’t hide the key to your home in a pocket or purse, others could copy the key. If the walls of your home were glass, anyone could see…

Publishing Go packages

There are many ways you can share Go code and applications. Here are a few. publishing to the Go package index (pkg.go.dev) This allows anyone with Go installed to download your package with go get or go install. go get is for getting code, and go install is for installing executables. More details on those commands are in the Go docs and this Stack Overflow discussion. Here are the official docs…

Impressive programming languages

Here’s why some languages are impressive to me. The languages are sorted alphabetically. C C is the oldest widely used language, and almost all of today’s widely used languages were heavily influenced by C (at least indirectly). It tends to have the fastest execution speed of all high-level languages and has relatively few features which makes it quick to learn. C is used in spaceships…

Which language should you learn first?

Don’t spend too much time choosing your first programming language. It can be a difficult choice to make, so here are some notes on what several languages are good for. If you will soon start a course, bootcamp, etc. that might choose a language for you, figure out which one and start learning ahead. It can be good to focus on just one language for a while when you’re learning your…

Learning Go

Here are various resources that are good to know about while learning the Go programming language. I created a list of commonly used Go packages and other dev tools at Go dev tools. getting started if you’re new to programming, check out Golang Tutorial For Beginners - YouTube A Tour of Go is probably the best way for developers with experience in another language to start learning Go Go…

How to control the terminal's cursor

Ever wanted to move the cursor up while printing output in a program? You can. Here&rsquo;s how with C++, and the same string works with any language in many terminals: cout << '\x1b[A'; That moves the cursor up one line. You can move it up by as many lines as you want; here&rsquo;s how to move it up by 3 lines: cout << '\x1b[3A'; A variable works there too: int lines = 3; cout << '\x1b[' << lines…

Learning recursion with C&#43;&#43;

Every programmer should be comfortable with recursion. Recursion is a type of loop created by making a function call itself. Here&rsquo;s a recursive function that loops infinitely (until the computer runs out of memory) when called: void print_stars() { cout << '*'; print_stars(); } Just like for loops and while loops, recursion can be used to do something repeatedly. Some problems are easier to…

How to print emoji with C&#43;&#43;

Printing emoji can be tricky because C++ running in Windows doesn&rsquo;t always support UTF-8. Emoji and other Unicode symbols can be printed with C++ by copying the symbol itself into your code or by using a Unicode code point. You can find emoji and other symbols at sites like unicode-table.com or with a keyboard shortcut (Windows+. on Windows, ctrl+cmd+space on Mac, and ctrl+. on some Linux…

How to use colors in terminals

You don&rsquo;t need another dependency to color text. With many programming languages, you can change the color and the style of your output to a terminal using ANSI codes. Here&rsquo;s how: with C++: cout << '\x1b[31m This will be red! \x1b[0m This will be the default color.'; with Python: print('\x1b[31m This will be red! \x1b[0m This will be the default color.') As you can see, the string did…

Learning SQL

SQL (Structured Query Language) is a commonly used and reliable way for programs to store and retrieve data. In many cases, it&rsquo;s much better in many ways than just using files directly. There&rsquo;s a lot that can be learned about SQL. Here are some resources to get you started. Learn SQL with SQLBolt and/or The SQL Murder Mystery. Choose a database technology and tools. Databases by Full…

Getting started with Git and GitHub

Here are some great resources for learning how to use Git and GitHub. There&rsquo;s more here than any one person will need, so just learn what will be helpful to you in the very near future. Watch these short videos: Version control with Git and GitHub by freeCodeCamp. Check out Better Explained&rsquo;s guides to version control and Git, or the Learn X in Y minutes guide to Git. Consider starting…

Algorithms

Big-O Cheat Sheet Algorithm – Wikipedia Sorting algorithm – Wikipedia Why quicksort is better than other sorting algorithms in practice App Academy has a free section about data structures and algorithms. Click the menu icon in the corner to see the list. HackerEarth Programming Tutorials and Practice Problems (when you choose one of the main topics and see a list of problems, click the subtopic…

Legally free books

Here are a bunch of free online books. I update this page with new books occasionally. computer science Software Engineering at Google by Titus Winters, Tom Manshreck, and Hyrum Wright A Data-Centric Introduction to Computing by Fisler, Krishnamurthi, Lerner, and Politz Programming Languages: Application and Interpretation by Shriram Krishnamurthi How to Design Programs by Felleisen, Findler,…