My setup

How I use my computers.

Contents

Directory layout

I have found a satisfactory directory layout for my personal data. It took surprisingly long to arrive at it by gradual iteration, which suggests it isn’t obvious and there is value in sharing it.

My directories are organized like this:

  • sync/
    • archive/
      • 2000/
      • 2001/
      • 2024/
    • projects/
      • 2000/
      • 2001/
      • 2024/
      • active/
Here, sync/ is the root directory that is synchronized between computers using Syncthing. I keep it in my home directory on Linux. It has two main subdirectories: archive/ and projects/.
Note. Depending on the context, I write directory names with a trailing slash to differentiate directories from files. I adopted the practice after trying Rebol, where paths with a trailing slash are a separate data type from paths without.
Note 2. I have found out that Risto Saarelma has a similar kind of directory, which he has called ~/hearth/.

The projects/ directory contains my projects: mostly software, but also writing, art, audio, etc. I have found that the best way to organize my projects is by the year they were started:

  • Not grouping at all projects leads to too many in one directory.
  • Grouping by category doesn’t work because projects belong in more than just one category.

Simulating multiple categories (tags) with symlinks is brittle. (For example, you must update all links when you change the project name.)

I only use symlinks in the active/ subdirectory, which contains links to projects that I frequently access or work on. The symlinks are relative. For example, active/hicolor links to ../2021/hicolor/

Project directory names are normally limited to only lower-case English letters, numbers, and dashes. They do not contain spaces. This is convenient on the command line.

One problem I had for a long time was the lack of a standard place to store and way to name things that weren’t projects, like screenshots, logs, notes, single webpages, etc. I have found that it is best to organize them “even more” chronologically than projects, preferably by year-month-day. However, deep directory structures like 2023/10/29 with only one or a few items in each leaf directory are difficult to get an overview of and to manipulate. Therefore, I organize my archive by year and prefix the month and day to the filename. For example, I could have a file archive/2023/11-27-storm.flac. The name means the file was archived on November 27, 2023 (but not necessarily created at that time; I am not super strict about which date to use as long as it helps find and group the item).

For items created by or received from other people, I add the their name or online nickname to the prefix. For example, it could be archive/2020/08-10-someone-letter.txt. The items in archive/ can also be topical directories with a month-day, month, or no prefix. I normally add a day or a month-day prefix to the filenames inside those directories.

The sync/ directory is an encrypted ZFS volume. It is backed-up using BorgBackup and ZFS snapshots via Sanoid. ZFS has checksums that prevent silent data corruption.

I keep photos in a separate directory hierarchy outside sync/. This allows me to synchronize them and back them up less frequently. It also reduces the size of sync/ and its backups.

ls on cd

I have fish configured to list the current directory when I change it.

function ls_on_cd --on-variable PWD
    ls
end

Variables

I use variables with directory paths for easier and faster navigation. My main interactive shell is fish. It has a CDPATH feature feature, but I find CDPATH inconvenient. Good, short CDPATH names clash with good, short local directory names; you must remember to use cd ./foo instead of cd foo if foo is in CDPATH. As an alternative, I began setting special variables and using their values with cd. They include pr for projects/ and ar19 for archive/2019/. So, for example, I would use cd $pr19 to change my working directory to archive/2019/.

This is fragment of my fish config that sets these variables (somewhat simplified for clarity).

# No trailing slashes so `$var/foo` doesn't have two slashes before `foo`.
set -x ar $HOME/sync/archive
set -x pr $HOME/sync/projects
set -x pra $HOME/sync/projects/active
set -x sy $HOME/sync

for year in (seq 2000 (math (date +%Y) + 1))
    set year2 (printf '%02u' (math $year % 100))
    set -x ar$year2 $HOME/sync/archive/$year
    set -x pr$year2 $HOME/sync/projects/$year
end
set -e year
set -e year2

zoxide

My use of directory path variables made me underestimate the usefulness of “jumping around” directories with a learning command like z and its derivatives. I loved this mode of navigation when I tried it and regretted not using it earlier. It has supplanted most, but not all, my use of directory path variables.

After testing jethrokuan/z and jump, I found what I wanted in zoxide. jump differs from other programs in this family: jump fuzzy-matches paths, while others match exact substrings. At first jump’s design seemed clearly superior to me, however, I grew tired of getting a random directory when there was no good match, like /home/user/foo/bar/ for sa. When I tried zoxide, it saying “no match found” felt like an improvement. Another thing I prefer in zoxide is that the command z on its own takes you to your home directory; you can repeat z foo to go through matches for foo. In jump, j on its own takes you to the next match for the arguments you gave before; j foo goes between two top matches for foo.

I recommend zoxide out of this class of programs. Try jump in case you prefer its style.

Rclone

I have come up with a convention for using Rclone. To make sure I don’t accidentally send files to an unencrypted remove, I prefix the names of unencrypted remotes name with UNENCRYPTED- in all caps then layer an Rclone-encrypted remove without the prefix over it.

My remotes are named [<prefix>-]<type>-<unique>. For example, I could name an SFTP remote UNENCRYPTED-sftp-foo; then sftp-foo would be the encrypted layer. In my usage I would almost always refer to sftp-foo. Where I don’t need encryption (for example, for backups that are already encrypted), I still prefix the remote’s name with UNENCRYPTED- but don’t create its encrypted counterpart.

Software choices

The “current” items here are listed roughly by how much I use them, items in “history” roughly in the order I started really using them. Items may be listed in “history” several times. It means I took a break from using them or my use of them changed.

OS

Current

History

Interactive shell

Current

History

Scripting language

Current

History

Linux filesystem

Current

History

*nix desktop environment or window manager

Current

History

Text editor

Current

History

File manager

Current

History

Remote interactive shell

Current

History

  • SSH (everywhere)

See also