Documentation pages

GET STARTED

Upgrade from 1.x

Tether 2.0 signs machine records, checks synced packages before it installs them, and gives packages to profiles. After the upgrade, each machine must trust your other machines once. Until then, packages from those machines wait in the Inbox.

ONE MACHINE AT A TIME 1.x and 2.0 in one repo
A 1.x record has no signature. Its packages wait in the Inbox. Approve them, or upgrade that machine and trust it.↔

Work through this checklist on each machine, one machine at a time.

Before you start

  • You can upgrade one machine at a time. A sync repo can hold 1.x and 2.0 machines together. Machines on 1.11.10, 1.12.0, 1.13.1 and 1.13.2 read the files that 2.0 writes
  • Patch each machine that stays on 1.x for a while to 1.13.2 first. Earlier 1.x builds push their old copy of config.toml back after they apply a synced one. That reverts config changes from other machines. Homebrew now installs 2.0, so install 1.13.2 from its GitHub release (macOS), or build it: cargo install --locked --git https://github.com/paddo-tech/tether-cli --tag v1.13.2. See Machines on 1.x
  • Plan to make config changes, such as profiles, after the upgrade. See Config merge

Checklist for each machine

1. Upgrade the binary

Terminal
brew upgrade tether-cli

If you used the install script, run it again. If you installed a release download or built from source, install the new version the same way. See Install.

On Linux, run tether daemon install again after the upgrade. The systemd unit names the path of the binary that installed it, and Homebrew removes the old version's path.

2. Sync once in a terminal

Terminal
tether sync

The first sync makes the machine's signing key and signs its record. On macOS, it also moves the daemon to a fixed copy of Tether. See App Management on macOS.

The sync then asks "Install these packages?". Choose Decide later.

"Install all" approves every package it can name in one step. That includes packages that only unsigned 1.x records list, and formulae from taps you do not trust. Trust your machines first. Their packages then install without a question, and the Inbox keeps only the items that need a look.

3. Trust your upgraded machines

On each upgraded machine, read its id and full key fingerprint:

Terminal
tether machines show

On each other upgraded machine, trust it with the fingerprint you read:

Terminal
tether machines trust <host> --fingerprint SHA256:...

Read each fingerprint on the machine itself. A fingerprint from the sync repo proves nothing, because anyone who can push can change the repo. If this machine does not have the record yet, machines trust pulls the sync repo first.

A machine on 1.x has no signed record, so you cannot trust it yet. Upgrade it, sync it, then trust it.

4. Sync again and review what is left

Terminal
tether sync
tether packages inbox

The sync installs the packages that your trusted machines list, when they pass the package checks. The Inbox shows what is left, grouped by source machine and reason. Approve or reject each item, or approve a reviewed group:

Terminal
tether packages approve <manager:name>
tether packages approve --all --from <machine>   # after you review the list

approve --all lists the packages and asks first. It leaves machine keys, malicious packages, packages whose record fails its signature, and packages without a version or tap to name in the Inbox. See The Inbox.

5. Allow App Management on macOS

On macOS, launchd now runs a copy of Tether at ~/.tether/bin/tether. The plist names the installed binary in TETHER_DAEMON_SOURCE. When that binary changes, the daemon copies it again and restarts. So the daemon follows each upgrade by itself.

THE DAEMON ON MACOS One path, one grant
Each Homebrew version lives in a new Cellar path. launchd runs the copy, so macOS keeps one App Management grant.↔

macOS keeps the App Management permission per program path. The fixed path keeps one permission across upgrades. Before, each upgrade asked again.

  • The first tether sync in a terminal after the upgrade moves an installed daemon to the copy. tether daemon install does this too
  • macOS then asks once for App Management for the new path. Allow it in System Settings > Privacy & Security > App Management
  • To add the copy by hand in the file picker, press Cmd+Shift+. to show hidden folders such as ~/.tether
  • Remove the old tether rows from the App Management list
  • tether daemon uninstall removes the copy

6. Delete the old plaintext config copy

Earlier versions wrote a plaintext copy of the synced config to ~/tether/config.toml once, on the first sync of a new machine. Tether no longer writes it. You can delete it:

Terminal
rm ~/tether/config.toml

7. Check your settings

  • Add the third-party Homebrew taps you use to packages.brew.trusted_taps. See Homebrew taps
  • Add packages that need install scripts to packages.allow_scripts
  • Change packages.min_release_age_days if 7 days does not suit you
  • Remove records that tether machines list marks as an old id of this machine. See Old machine ids
  • Check that each machine has the profile you want. Packages now go only to the profiles that have them. See Packages per profile

Machines on 1.x

tether status, tether machines list and the dashboard Machines tab mark each machine that still runs 1.x as "on 1.x".

  • A machine on 1.x does not run the new checks. It still installs every synced package without them
  • Its record has no signature. Its packages wait in the Inbox of 2.0 machines as "from another machine". Approve them one by one, or upgrade that machine and trust it
  • It ignores profiles. It installs the packages of every profile
  • A 1.x machine before 1.13.2 pushes its old copy of config.toml again after it applies a synced one. That copy reverts config changes made since, and 2.0 cannot tell it from a real change. Patch or upgrade the 1.x machines, then make the change again
  • When a synced config changes this machine's profile, a 2.0 sync warns, names both profiles, and names the command that restores it

What changed in 2.0

  • A synced package installs on its own only when a trusted machine record lists it. A line in a manifest grants no trust
  • A machine installs only the packages of its own profile. Nothing is uninstalled. The first sync counts the packages that no longer come to this machine, and names the commands that list and share them
  • Packages from untrusted Homebrew taps now wait in the Inbox. Before, Tether skipped them with a warning
  • For gem, and for npm before 11.10, pnpm before 10.16 or at a 12.0.0 prerelease, and bun before 1.3, Tether checks the release age itself in the registry. It installs the release it checked. It holds a package only when the release is too new or the registry check fails
  • Tether checks npm, pnpm, bun, uv and gem packages against OSV before it installs or upgrades them
  • npm, pnpm and bun install with install scripts off
  • Tether no longer runs brew update. Run it yourself to update Homebrew
  • tether upgrade asks first, lists what it changes, and never downgrades a package
  • tether packages now lists packages. tether packages uninstall replaces remove, which stays as an alias
  • tether ignore secrets and tether ignore files replace the old tether ignore forms, which still work
  • tether machines rename <NEW> renames only the machine it runs on
  • -y confirms prompts and takes their defaults. It does not trust keys. It approves Inbox items only in tether packages approve --all -y. See Exit codes and -y
  • A failed command exits with status 1 and prints one Error: line. A usage error, such as an unknown flag, exits with status 2
  • A sync merges config.toml three ways, so edits from two machines both stay. See Config merge
  • The Config tab no longer shows the sync_versions settings. Tether still writes them, because 1.x builds need them to read the synced config. A new config gets false, and an existing value stays