mailman's toolshed


Macbook Air 13 inch, 2017 running macOS Monterey with 1.8 GHz Dual-Core Intel Core i5, 8GB RAM, 128GB harddrive - $344

Transcend JetDrive Lite 130 256GB - $56

RTL-SDR Blog V3 R860 RTL2832U RTLSDR 1PPM TCXO SMA Software Defined Radio (Dongle Only) - $30

Bingfu Dual Band 978MHz 1090MHz 5dBi Magnetic Base SMA Male MCX Antenna for use with RTL SDR Software Defined Radio - $15

macOS Setup Guide

Great tips for getting started with setting up a new development environment on a Mac.


For future reference, the zsh manual is here.

Using Oh My Zsh!

Use Oh My Zsh, an open source framework for managing your zsh configuration.

echo $SHELL

zsh --version



Edit the zsh config file.

pico ~/.zshrc

Check the default path:

export PATH=$HOME/bin:/usr/local/bin:$PATH

Pick a theme; I like Pygmalion:


Customize the zsh prompt in ~/.zshrc (must appear after the source $ZSH/ line, under the "User Configuration" section):

# Customize user prompt

# %n is the username of your account.

# %m is the MacBook’s model name.

# %1~ means the current working directory path where the ~ strips the

# $HOME directory location.

# %# means that the prompt will show # if the shell is running with root

# (administrator) privileges, or else offers % if it doesn’t.

PROMPT='%n@%m %1~ %#'

Using homebrew with multiple user accounts

Elsewhere there is bad advice about how to share a homebrew installation. Do not use homebrew with multiple users.  Dedicate a single admin account.  Do not install/uninstall brew packages outside of that dedicated account.

Using homebrew with other admin users

To use brew from an admin account that is not the dedicated homebrew admin account, add an alias for the brew command to the user's ~/.zshrc config file; homebrewadminuser is the name of the dedicated hombrew user account.  The -H flag tells sudo to execute brew from the dedicated homebrew user's home directory (which you should always do with homebrew commands):

alias brew='sudo -Hu homebrewadminuser brew'

If you need an interactive shell with elevated privileges for multiple commands:

login homebrewadminuser

Or, use su with the - flag, which loads the shell in the dedicate homebrew user's home directory:

su - homebrewadminuser

Sometimes you may need to change ownership of a file or directory to the dedicated homebrew admin user.  If you are already logged in as the homebrew admin:

sudo chown -R $(whoami) /path/to/file

If you are logged in as another admin, explicitly declare the dedicated homebrew user admin account:

sudo chown -R homebrewadminuser /path/to/file

Using homebrew with standard user accounts

For a standard account, sudo is not an option without editing the /etc/sudoers file.  Use su with the - argument to execute the command in quotations in a shell in the dedicated homebrew adminuser's home directory:

su - homebrewadminuser -c "brew list"

To achieve this behavior with an alias, you need to be able to pass brew arguments, which requires a function alias.  Instead of aliasing a simple command, add the following function alias to the standard user's ~/.zshrc. homebrewadminuser is the dedicated homebrew admin account:

alias brew='f() { su - homebrewadminuser -c "brew $*" }; f'

To change ownership of a file or directory to the dedicated homebrew admin user from a standard user account, use the su command:

su - homebrewadminuser -c "chown -R homebrewadminuser /path/to/file"

Useful commands for debugging zsh aliases

To check if a command is a z shell built-in, alias, function, or stored in a file:

type brew

To remove an alias in the current shell:

unalias brew

To remove a function alias in the current shell:

unfunction brew

Other Useful Apps


Micro Snitch


Livebooting Linux from the Macbook SDXC Card Slot

I tested burning and booting images of Tails 5.9, Manjaro X86_64 with Plasma Desktop, and Mint 21.1 "Vera" with Cinnamon Desktop from a Transcend JetDrive Lite (256GB) SDXC expansion card.  All three distributions booted quickly and with almost no perceptible lag from the expansion card, which has a max read speed of 95MB/second and max write 60MB/second.  

All three distributions did not immediately recognize the WiFi adapter or the Facetime HD camera.  I tried and failed to change the wifi adapter driver in Tails and Manjaro.  Mint's latest kernel had much better support right out of the box: after launching "Driver Manager" (System Settings -> Administration -> Driver Manager), the system suggested a new driver and then provided it from the liveboot image.

To help with wrangling wifi on other systems, ID the wireless adapter and chipset:

$ inxi -Nxxxa


  Device-1: Broadcom BCM4360 802.11ac Wireless Network Adapter vendor: Apple

    driver: wl v: kernel modules: bcma pcie: gen: 1 speed: 2.5 GT/s lanes: 1

    bus-ID: 03:00.0 chip-ID: 14e4:43a0 class-ID: 0280

The kernel driver and modules functioning in Linux Mint 21.1 are:

$ lspci -vnn -d 14e4:

03:00.0 Network controller [0280]: Broadcom Inc. and subsidiaries BCM4360 802.11ac Wireless Network Adapter [14e4:43a0] (rev 03)

Subsystem: Apple Inc. BCM4360 802.11ac Wireless Network Adapter [106b:0117]

Flags: bus master, fast devsel, latency 0, IRQ 18

Memory at c1200000 (64-bit, non-prefetchable) [size=32K]

Memory at c1000000 (64-bit, non-prefetchable) [size=2M]

Capabilities: <access denied>

Kernel driver in use: wl

Kernel modules: bcma, wl

The Arch Linux wiki has some discussion of wireless with Manjaro, and the Linux Wireless Wiki has a crowdsourced database of drivers that can be cross-referenced against chipsets.

Moving my mom's old pictures and videos to the cloud (3 days)

To move my mom's old photos and videos from her old PC to the cloud, I needed to clone her PC harddrive, organize the files on my mac, and then convert media formats not supported in iCloud (BMP, PNG, MOV).

Before cloning, I ran chkdsk (chkdsk /r) on the source drive.  For the cloning job, I used Macrium Reflect (Free Trial). Both steps took about 8 hours.

After cloning to an external drive, I copied media files to an internal SDD to speed up the file operations and then manually grouped them into folders of depth 1 from the main folder (no nested subfolders).  Why didn't I write a script?  In some cases, I did, but many of the files had creation dates that were not trustworthy. (I found that most photos my mom took between 2001-2004 were on a Canon PowerShot 110 digital camera, which would have required configuring the date in the camera settings every time she changed the batteries, which she evidently did not do.  In about 2005, I could see started taking her photos on an iPhone 4, and with the smartphone came accurate time-date stamps.)

To keep my mom's files organized in the cloud, I wanted them to be sortable, so prepended all folder and file names with the event date (or best guess), not the file creation date, such as: 20220000 Mailman Graduation Photos, 2023 Mailman's Graduation, or 2023? Mailman's Photos.

I used one-line zsh parameter expansions and aliasing to help speed things up.

To copy only Word files (.docx) and skip temp files (starting with tilde, ~):

for i in *.docx; do n=$(stat -f %SN "$i"); d=$(stat -f %SB -t %Y%m%d "$i"); if [[ "$n" != ~* ]] then cp "$i" "$d $n"; echo "copied file: " $i; else echo "not copying temp file: " $i; fi; done

To copy files with a given extension:

alias cjpeg='for i in *.$1; do n=$(stat -f %SN "$i"); d=$(stat -f %SB -t %Y%m%d "$i"); if [[ "$n" != ~* ]] then cp "$i" /path/to/file/"$d $n"; echo "copied file: " $i; else echo "not copying temp file: " $i; fi; done'

cjpeg jpg

To rename JPG files in the current directory using the YYYYMMDD date format:

for i in *.JPG; do n=$(stat -f %SN "$i"); d=$(stat -f %SB -t %Y%m%d "$i"); mv "$i" "$d $n"; done;

To convert files from BMP and PNG files to JPG and MOV to MP4, I used ffmpeg (installed via Homebrew).  To iterate ffmpeg over each file (MOVs, for example):

for i in *.mov; do ffmpeg -i "$i" "../mov/${i%.*}.mp4"; done

(The zsh docs have a lot for more on the order of expansions in zsh.)