Sync in 2026

File this one under "betting on the wrong horse", because I'm about to tell you how — yet again — I've migrated an important piece of my digital life to a new platform. This chapter's subject is file syncing.

Many years ago I started off as a free-tier Dropbox user. I became a paying user for a while as my storage needs grew, but I eventually felt the need to move away given their gradual transmogrification into an evil megacorp. By this time, my needs were clear: I wanted something that allowed me to view my files in the native file browser on my Mac, and an iOS app so that I could both view files and save files in a way that shared them back to my laptop. At times I would sync to multiple machines, and occasionally I'd need to share a folder with somebody else, but for the most part, what mostly concerned me was keeping one laptop in sync with one phone.

I switched to Sync (by sync.com) in order to get away from the evil. The app was uglier, and syncing was slow and inscrutable. Eventually the thing that drove me away from that was the flakiness of the sync with another computer, another user, and a shared folder in the mix; I had a support thread open for months (about synchronization that silently failed to complete) and never got a resolution. Finally, I got sick of waiting and switched again.

I can't remember exactly where in this chronology, but along the way I experimented with both Google Drive and Microsoft OneDrive. Both proved to be — wait for it — slow, unreliable, and inscrutable. These attributes seem to be a recurring theme in this space...

Syncthing would have been the obvious choice — open source, popular, battle-tested — but it lacked an official iOS app, and the most popular third-party one, Möbius Sync, seemed to be in maintenance limbo. So I ended up going with Resilio Sync. Like sync.com's Sync, this one was closed source and proprietary, but it also happened to be free. I wouldn't have minded paying for it if it had been good (I'd paid Dropbox, Sync, Google, and Microsoft in the past, after all), but it turned out that I didn't have to.

In 2026, Resilio was acquired by Nasuni, and the writing very much appears to be "on the wall", so to speak. The FAQ is laden with the usual verbiage that "future updates or options will be communicated clearly and well in advance", and that there "are no immediate changes to product availability or customer support processes", but the release cadence of late and the number of historical bug reports and feature requests makes it clear that the software is on the merest of life support. I'd been eyeing the exits for a while, ever since I adopted Resilio Sync, really, but this made me seriously consider switching solutions, yet again.

The good news is that there is a bright and upcoming third-party iOS app for Syncthing now: Synctrain. It's open source, like Syncthing itself, and feels like a real iOS app. I also tried out a couple of lightweight text-editing apps for iOS which looked like they'd integrate well with Synctrain for on-device editing of text files (something I don't often have to do, but which I like being able to do when necessary): I haven't settled on one yet, but the candidates are Runestone and Textastic.

Now Syncthing is a bit "promiscuous" out of the box, in the name of ease of use: it uses a global discovery mechanism, and there's a network of relays that anybody can participate in to shuffle encrypted traffic between devices, allowing you to sync between computers and phones regardless of which local network you're on. While your data is encrypted, metadata about your IP address, the device IDs you're talking to, and the amount of data your sending, is all available to these peers. That makes me feel a bit squeamish (Resilio Sync had a similar problem, to be fair), so it seemed reasonable to test Syncthing with all of these convenience features turned off in the name of privacy.

In my first round of testing I had everything turned off and local discovery only. Given my network topology (a mobile phone, a laptop computer mostly only used on the home network but sometimes traveling outside it, and an always-on Raspberry Pi on the home network as a centralized sync point) my plan was to test it all out while assuming the limitation that I would only actually synchronize when at home.

This worked ok, but I wanted to see if I could have my cake and eat it too. The other relatively new circumstance in my life is that last year, I picked up a decent router (a UniFi one) and it has a couple of built-in features that make it trivially easy to set up a VPN with a minimum of effort and only a single extra dependency (WireGuard) installed on the client devices1:

  • The UniFi router supports many dynamic DNS services. In my case, I'm using Cloudflare for DNS, so I minted an API key with the minimal privileges needed to edit a single DNS zone, and configured the UniFi to update an A record any time my public IP changes (fortunately, my ISP assigns a dynamic public IP without any CGNAT nonsense in the way). This means my devices can find my router's public IP by name (router.example.com) whenever they need it.
  • The router also let's you create WireGuard VPNs with a few clicks, and set up client configurations that you can use on your laptop (by importing a file into the open source WireGuard app, which you can get from the App Store) and your phone (by scanning a QR code).
  • Both WireGuard on iOS and macOS let's you configure a VPN as "On-Demand", which means that it can automatically connect to the VPN as soon as you leave the home network, and disconnect when you come back to it.

The combination of the dynamic DNS and the VPN mean your devices can always see the home network, no matter where they are, which means that Syncthing on the Raspberry Pi or the laptop, and Synctrain on the phone, can sync up at any time. The "On-Demand" activation means you don't even need to think about the connection.

Overall, I am pretty happy with this setup so far. There are lots more details that I could go into, but nothing that a quick search or LLM query can't rapidly resolve, so I won't bore you any further. I certainly didn't have to get very far into the weeds at all to make this work. Here's hoping it keeps working for a good few years now, so I don't end up having to write another "wrong horse" post too soon in the future.

  1. Only needed on the client devices that will be outside the home network (ie. the laptop and the phone, but notably not the Raspberry Pi).

Markdown fatigue

My relationship with Markdown has traversed the following arc: Contempt, Acceptance, Resignation

Contempt

In 2009, I thought "Markdown sucks". There was a burgeoning assortment of markup languages, having been driven by (and driving) the rising tide of the blogosphere, and Markdown seemed to be decidedly inferior. I knew about "Worse is better" back then, but I didn't have the acumen to realize I was seeing it in action.

Acceptance

By 2015, I recognized that Markdown had won, and in choosing Wikitext I had been "Betting on the wrong horse". I eventually moved all my content to Markdown, and found myself relishing its simplicity and ubiquity. GitHub continued the trend started in the blogosphere, inducting wave upon wave of developer into the Church of Markdown. Many of the rough edges and ambiguities were smoothed over by efforts such as CommonMark.

Resignation

In 2025, with the rise of agentic AI, I found myself wearying of Markdown.

First, I was annoyed and frustrated to see deterministic configuration and code replaced by non-deterministic natural language suggestions (in Markdown, of course). Skill files started to pile up in repos like so much cruft, only to be deleted as we were forced to admit that the agents were often better off without them.

But worse than that, has been the rising flood of AI-generated Markdown text written — purportedly — for human consumption. As it stands right now, there is something difficult to stomach about LLM-generated text. Many of us are developing an "allergy" to it. And now it's everywhere: in commit messages, PR descriptions, project READMEs, wiki pages, and so on. For the unwary, the near constant exposure to this homogenous slop may slowly infect them: the human, imitating the machine, which was trained to imitate the human.

The LLM's literal raison d'etre is to generate text, tirelessly, one token after another, until the requester's API credits have run out. So, we now have wall-of-text PR descriptions densely peppered with Markdown backticks and other formatting, producing a tiring assault on the senses that no human developer would have the patience to construct by hand. I used to take pride in my detailed and well-formatted PR descriptions, but now every PR is a pantomime of a carefully crafted message: exhaustively formatted and spelled out by the practically unbounded patience of the next-token-predictor machinery.

My heart sinks every time I read one of these PRs. And when I write my own PR descriptions, I can't shake the feeling that any care I take in wrapping symbol names in backticks or inserting expository asides between em dashes is only going to risk miscuing my readers and leading them to think that I, too, might be a bot.

But, who am I kidding, anyway? The slop economy is training us all to barely skim or not even read these artifacts any more, so maybe it doesn't matter. Perhaps all this indescribably unpalatable Markdown will eventually be like the Great Pacific Garbage Patch: ugly, enormous, and drifting endlessly on distant digital currents where few will ever go to see it.

Signed, Yours truly, in Markdown.

Arq restore notes

About a month ago, my personal laptop died, requiring the logic board to be replaced. All the data on the previous incarnation of the machine was irrecoverably lost, requiring me to restore from backup. Unless my memory deceives me, this was the second time I've restored a backup made with Arq1.

This time, things didn't go quite as smoothly, but overall, it still worked out ok. I'm going to put some notes here about the road bumps that I ran into while restoring, for reference by my Future Self™. Given that "past road bumps are no guarantee of future road bumps", I'm dumping this in a blog article rather than a wiki post, as I consider these to be more "moment in time" observations than an enduring record of what to do in the future.

A SuperDuper! backup is a full disk copy, and pretty close to being something that you can just restore and then run with. Arq, on the other hand, only backs up my home folder, which means I need to reinstall a bunch of apps after doing the restore. Additionally, there appear to be quite a few settings (particularly permission-related settings) that don't survive across a backup/restore cycle, and these need to be set up manually afterwards.

First steps:

  • Install Arq, so I can initiate the restore.
  • Install 1Password, so I can get the credentials necessary for the restore.
  • Actually start the restore; after many hours, Arq used all the memory on the system, requiring me to start again2.
  • Sign in to iCloud, because apparently thanks to Apple "magic" none of my photos were actually on my device, or at least, the couldn't be restored by Arq; after signing in, photos start syncing and I eventually got access to them all again.

Next up, set the hostname, because otherwise Fig won't know what machine it is running on, and my machine will only get a lowest-common-denominator set-up as opposed to the specific one I want for this machine:

scutil --set HostName latina
scutil --set ComputerName 'MacBook Pro'
scutil --set LocalHostName latina

We then try running git in terminal, which triggers a command line tools download and install, and can finally at that point run install under ~/code/wincent/. That died with:

$HOME/code/wincent/vendor/n/bin/n: fork: Resource temporarily unavailable

A bin/n --cleanup should supposedly delete all versions, but I ended up having to rm -r vendor/node/n/versions to actually get n working, at which point I could run install again.

You have to run vendor/homebrew/install.sh in order for this to work, and additionally you have to open a new window after installing in order to have the Homebrew directory appear in your $PATH (merely running hash -r isn't going to cut it).

Homebrew helpfully points out the following:

stderr: 'Error: homebrew/bundle was deprecated. This tap is now empty and all its contents were either deleted or migrated.\n',

So I deleted than, and it then says:

'Error: No available formula with the name "bun". Did you mean bup, buf or run?\n'

Turns out that you need fully-qualified (tap + brew) formula and cask names, as noted in Homebrew/brew#21416, so I fixed that.

There are a number of apps that you have to open or twiddle in order to get things working, even though Homebrew installs them:

  • Karabiner-Elements (have to open it and grant privileges).
  • Hammerspoon (have to open once, let it prompt for permission, set to load at login, hit Ctrl-Opt-Command-F2 to set two-monitor layout and F4 to set horizontal display arrangement).
  • Raycast (somehow it couldn't read its settings, so I had to import a backup, set Command-Space in the System Settings to not open Spotlight, grant accessibility access for snippets to work, and the same for 1Password while I was at it, and set it to launch at login).
  • Before using tmux, had to go to System Settings -> Keyboard -> Shortcuts -> Input Sources and turn off these trouble-makers:
    • Select the previous input source (ctrl-space)
    • Select next source in input menu (ctrl-option-space)
  • Kitty (have to open it and set it to stay in the Dock)
  • Godspeed (open it, set it to stay in dock, launch at login)
  • terminal-notifier: run a command like terminal-notifier -title hi -message there so it appears in System Settings; then you can allow notifications from it.
  • Syncthing (set to launch at login)
  • Orion (installed via cask, but have to open and set to default browser in System Settings)
  • CleanShot X (open and set to start at login, grant accessibility settings, turn off conflicting shortcuts in System Settings)
  • iStatMenus (launch and grant permissions)

And general house-keeping:

  • Remove cruft from dock.
  • Dock settings: turn hiding on (I thought I had a default for that; maybe all I needed was to log out and in again for it to take effect)
  • System settings: under the lock screen settings, require password immediately.

For some reason, I couldn't get Screenflow to make use of my microphone (it would claim I needed to grant it access to the microphone, but it didn't actually ask for access and there was no way to force it in the System Settings). In the end, I blew away the settings and data and it eventually prompted:

rm -rf \
  ~/Library/Preferences/net.telestream.screenflow10.plist \
  ~/Library/Preferences/WSG985FR47.net.telestream.screenflowhelper.plist \
  ~/Library/Containers/net.telestream.screenflow10 \
  "~/Library/Group Containers/WSG985FR47.net.telestream.screenflow10" \
  "~/Library/Application Support/ScreenFlow*"

The above is what I've discovered so far over the course of several days. Hopefully that's the end of it!

  1. The other backup tool that has saved my hide in the past is SuperDuper!, but on this occasion I didn't have access to my physical (SuperDuper!) backup, so restoring from the cloud (Arq) was my only option.

  2. Restarting is a bit annoying, because I use Glacier storage for my backups, meaning that you can't just start downloading the data from the cloud; instead, you request for it to be made available and then wait 5 hours before actually beginning the download. Downloading from Glacier also hurts the wallet a bit, to the tune of about a hundred bucks for all the retrieval costs associated with the repeated attempts.

Dreamscape →

All blog posts