Documentation pages

REFERENCE

Data layout

On each machine

Tether keeps its data in ~/.tether/. Nothing in this folder syncs as a dotfile.

~/.tether/
~/.tether/
├── config.toml              # Configuration (synced encrypted)
├── config.base.toml         # Base of the next config merge (never synced)
├── local.toml               # Settings for this machine only (never synced)
├── state.json               # Sync state, including failed installs
├── sync/                    # Personal sync repo
├── teams/<name>/            # Team sync repos
├── collabs/                 # Collab project configs
├── backups/                 # File backups
├── bin/tether               # macOS: the copy of Tether that launchd runs
├── identity.age             # Age identity, encrypted with your passphrase (for team secrets)
├── identity.pub             # Age public key (for team secrets)
├── identity.cache           # Unlocked age identity (tether identity lock clears it)
├── key.cache                # Unlocked encryption key (tether lock clears it)
├── ignore                   # Patterns the secret scanner skips
├── signing_key              # This machine's SSH signing key (mode 0600)
├── trusted_keys             # Machine keys this machine trusts (never synced)
├── record_generations.json  # Newest record accepted per key (never synced)
├── command_seqs.json        # Fleet command numbers sent and accepted (never synced)
├── machine.json             # This machine's last record (never synced)
├── inbox.json               # The Inbox (never synced)
├── inbox.lock               # Lock for Inbox and trust list changes
├── conflicts.json           # Conflicts that wait for tether resolve
├── run/                     # Empty working directory for package managers
├── daemon.pid               # Daemon process id
└── daemon.log               # Daemon log
  • bin/tether: on macOS, launchd runs this copy. The plist names the installed binary in TETHER_DAEMON_SOURCE. When that binary changes, the daemon copies it again and restarts. macOS keeps the App Management permission per program path, so the fixed path keeps one permission across upgrades. tether daemon uninstall removes it
  • config.base.toml: the synced config.toml of the last merge, or of the last export once the remote branch holds it. A sync merges against it. See Config merge
  • signing_key: anyone with this file can sign records as this machine. Protect it like an SSH key

In the sync repo

sync/
sync/
├── encryption.key.age      # Encryption key, encrypted with your passphrase
├── profiles/<name>/        # Dotfiles of each profile (encrypted)
├── dotfiles/               # Dotfiles in the flat layout
├── configs/                # App configs, including the Tether config
├── projects/               # Project configs and secrets
├── manifests/              # Package names per manager, and the Brewfile
├── packages/profiles.toml  # The profiles of each package
├── commands/<target>/      # Signed fleet commands (<signer>-<n>.toml and .sig)
└── machines/               # Machine records (<id>.json) and signatures (<id>.json.sig)
  • Manifests list package names only, one per line, as 1.x reads them. Versions come from the signed machine records
  • packages/profiles.toml maps "manager:name" to profile names. 1.x does not read it. See Packages per profile
  • commands/ holds commands that one machine signed for another. The signer deletes each one after the target reports it. 1.x does not read it. See Fleet commands
  • Each record in machines/ lists the machine's packages, versions, profile and OS. Its signature decides trust. See Machine trust

Files that earlier versions wrote

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.