Skip to content
Go back

Sync Game Saves Without a Cloud Account

By KingPin 14 min read
Sync Game Saves Without a Cloud Account
Contents

You get 40 hours into a game on the desktop, sit down with the Steam Deck, and the save is nowhere. Steam Cloud shrugged. The developer never turned it on, or the game came from another store, or the file lives in a folder Steam has never heard of.

Here is the fix in one sentence. Let Ludusavi find and copy the saves into one plain folder, and let Syncthing mirror that folder between your machines. No account, no subscription, no company holding your progress. Ludusavi handles the “where do saves even live” mess, and Syncthing handles the “move bytes between my devices” job. Each tool does one thing, which is how you want your tools at 2 AM.

This post covers where saves hide on Windows and under Proton, how to script Ludusavi, how to set up Syncthing with versioning, and a symlink shortcut for when you want live sync. It also covers what you should never sync. Version notes as of October 2026: Ludusavi 0.31.0 and Syncthing 2.1.6.

Where Saves Actually Live

Games do not agree on a save location. They scatter files across a handful of places, and the game’s own menu rarely tells you which.

On Windows, the usual suspects are:

C:\Users\<user>\AppData\Roaming\<Game or Studio>
C:\Users\<user>\AppData\Local\<Game or Studio>
C:\Users\<user>\AppData\LocalLow\<Studio>
C:\Users\<user>\Documents\My Games\<Game>
C:\Users\<user>\Saved Games\<Game>
<Steam>\userdata\<steam-id>\<appid>\remote
<Game install dir>\saves

Some games also write to the registry. Ludusavi can dump registry keys on Windows, which most hand-rolled backup scripts forget.

On Linux, native games usually follow XDG: ~/.local/share/<game>, ~/.config/<game>, and sometimes ~/.<game> in your home directory. Windows games running through Proton get a fake Windows drive inside a per-game Wine prefix:

~/.local/share/Steam/steamapps/compatdata/<appid>/pfx/drive_c/users/steamuser/AppData/Roaming/...
~/.local/share/Steam/steamapps/compatdata/<appid>/pfx/drive_c/users/steamuser/Documents/...

The <appid> is the Steam app ID, a number you can read off the game’s store page URL. A Steam Deck uses the same layout, with the same ~/.local/share/Steam root on the internal drive. If you install games to an SD card, the prefix lives in steamapps/compatdata on that card’s Steam library, not in your home directory.

The gotcha: the prefix is one per game and per machine. The Windows path C:\Users\<user>\AppData\... and the Proton path .../pfx/drive_c/users/steamuser/AppData/... hold the same file, but the absolute paths look nothing alike. Any tool that syncs by absolute path needs to translate between them. Ludusavi can do that with manually configured redirects, which we get to below.

Why Steam Cloud Is Not the Answer

Steam Cloud works well when it works. The limits are:

  1. The developer opts in per game. No opt-in, no sync.
  2. It only covers Steam. Your GOG, Epic, itch.io, and emulator saves are on their own.
  3. It syncs what the developer declared, nothing else. A mod config or a screenshot folder stays local.
  4. When two machines disagree, you get a modal asking which one wins. Pick wrong and the other save is gone.
  5. Your saves live on Valve’s servers under your account.

If any of that bugs you, keep reading. If you only play well-behaved Steam games on one account, leave Steam Cloud on and stop here. It is also fine to run both: Steam Cloud for the games that support it, Ludusavi for the rest.

Ludusavi: The Save Finder

Ludusavi is an open-source backup tool for PC game saves. It does not guess locations. It downloads the PCGamingWiki-derived Ludusavi manifest, which lists save paths for thousands of games, then scans your machine for matches. It ships a GUI and a CLI. Grab a release from the GitHub releases page. It is portable, so you can drop the binary anywhere.

The config file is config.yaml, stored here:

The GUI edits this file for you. If you only use the CLI, you edit it by hand. A minimal config looks like this:

config.yaml
manifest:
url: "https://raw.githubusercontent.com/mtkennerly/ludusavi-manifest/master/data/manifest.yaml"
roots:
- path: "~/.local/share/Steam"
store: steam
backup:
path: ~/game-saves
restore:
path: ~/game-saves

The roots list tells Ludusavi where your game libraries are. store: steam makes it understand Steam’s layout, including Proton prefixes. Add one root per library, including an SD card library on the Deck.

Preview first, always:

Terminal window
ludusavi backup --preview

That scans and reports what it would copy, without writing anything. When the list looks right, run the real thing:

Terminal window
ludusavi backup --force

--force skips the confirmation prompt, which you need for scripts. You can also name games, and the match is against the manifest title:

Terminal window
ludusavi backup --force "Stardew Valley"

Two flags matter for retention and format. Ludusavi keeps full backups and differential backups (changes since the last full one), and prunes the excess per game:

Terminal window
ludusavi backup --force --format simple --full-limit 2 --differential-limit 3

--format simple stores plain files in folders instead of zip archives. That is the right choice here, because unchanged save files stay untouched and each game’s folder stays readable and diffable. The same limits live in config.yaml under backup.retention as full and differential, if you prefer to set them once.

Restore is the mirror image:

Terminal window
ludusavi restore --preview
ludusavi restore --force

Each game gets a subfolder in the backup directory with a mapping.yaml that Ludusavi needs to identify it. Do not hand-edit that file, and do not sync a folder that lacks it, because restore only considers folders that have one.

Cross-OS Paths: Redirects

Ludusavi stores files by absolute path. A backup made on a Windows desktop remembers C:\Users\alice\..., and restoring it on a Deck needs a translation. That is a redirect. Here is one that maps a Windows user folder onto a Proton prefix, as a restore redirect on the Linux side:

config.yaml (excerpt)
redirects:
- kind: restore
source: "C:/Users/alice"
target: "~/.local/share/Steam/steamapps/compatdata/<appid>/pfx/drive_c/users/steamuser"

The valid kind values are backup, restore, and bidirectional. Redirects are per path prefix, and a Proton prefix is per game. So a one-line redirect covers one game. For a handful of games that is fine. For fifty, you will not enjoy it.

The easier route for the common case: use Ludusavi on both ends for Proton games too. The Linux machine backs up from its prefix, and another Linux machine (a second Deck, a laptop) restores to the same layout with no redirects at all. Ludusavi does not translate Windows saves to Proton automatically. Cross-OS sync needs redirects tailored to each game, and some games will not work, so test each game once before you trust it. Some games store absolute paths or machine-specific data inside the save file, and no tool can fix that.

Run It Around the Game

You do not want to remember to run backups. Ludusavi has a wrap command that restores before launch and backs up after you quit:

ludusavi wrap --infer steam --gui -- %command%

Paste that into the game’s Steam launch options, using the real path to your Ludusavi binary in front. The --infer steam flag reads the game name from the Steam command, so you do not name each game by hand. For other launchers, --name "Game Name" -- <launch command> does the same job. Set it per game. The Ludusavi docs also note that on Linux, wrapping works best with a standalone binary and not the Flatpak, because the Flatpak sandbox can keep it from launching the game.

This wrapper is one way to get “only sync when the game is closed”. The save folder is only backed up after the game exits, so Syncthing never sees a half-written file. On the Steam Deck in game mode, quit with the game’s own menu: quitting through the Steam overlay kills the wrapper and skips the backup (per the Ludusavi docs).

Syncthing: The Mover

Syncthing syncs folders directly between your devices over encrypted connections. No central server, no account. Each device has an ID, and you tell each device which IDs to trust.

Run it on an always-on box so devices that are never awake at the same time can still catch up. This compose file runs it with host networking, which the Syncthing Docker README recommends. Bridge mode breaks local discovery on the LAN.

docker-compose.yml
services:
syncthing:
image: syncthing/syncthing:latest
container_name: syncthing
environment:
- PUID=1000
- PGID=1000
volumes:
- ./st-config:/var/syncthing
- /srv/game-saves:/var/syncthing/game-saves
network_mode: host # web UI on 8384, sync on 22000, discovery on 21027/udp
restart: unless-stopped

Set a GUI password in Actions, Settings on first login, because the web UI listens on all interfaces by default in this setup.

On the desktop and the Deck, run the Syncthing package that fits each system. Then:

  1. Open each web UI at http://localhost:8384 and note the device ID under Actions, Show ID.
  2. On the server, add each client’s device ID as a remote device. Accept the prompt on the client.
  3. Share one folder, with a label like game-saves, pointing at the same path you set as Ludusavi’s backup.path.
  4. Accept the folder on each client and point it at that client’s Ludusavi backup path.

That is the whole setup. Ludusavi writes into the folder, and Syncthing mirrors it.

Turn On Versioning

Saves corrupt. A game crashes mid-write, or you load an old save and overwrite a good one. Versioning is your undo button. In the folder’s File Versioning tab, pick one of these:

Staggered is the right default for saves. Old versions land in .stversions inside the folder. One limit to know: Syncthing’s versioning applies to changes received from other devices. A file you overwrite locally is not archived by Syncthing. That is another reason to keep Ludusavi’s own full and differential backups turned on, since they give you history on the machine that made the change.

Conflicts

If two devices change the same file before they sync, Syncthing keeps the newer modification time and renames the older one to <name>.sync-conflict-<date>-<time>-<modifiedBy>.<ext>. If the times are equal, the device with the larger device ID prefix loses. Conflict copies sync like normal files, so they show up everywhere.

With Ludusavi in front, conflicts are rare for one reason. You play on one device at a time. The conflict case is the one where you played offline on the Deck and the desktop, then reconnected both. Syncthing will not merge two saves. A save file is binary, and there is no merge. Find the sync-conflict files, decide which save you want, and delete the other. Then run ludusavi restore --preview to see what Ludusavi thinks of the winner.

Play on A, close the game, let Syncthing finish, then play on B. That discipline beats every clever conflict tool.

The Ludusavi plus Syncthing route has one extra step: a backup copy sits between the game and the sync. If you want live sync with no copy, you can move the save folder into a Syncthing folder and leave a symlink behind.

On Linux, for a native game:

Terminal window
mv ~/.local/share/SomeGame/saves ~/Sync/SomeGame-saves
ln -s ~/Sync/SomeGame-saves ~/.local/share/SomeGame/saves

On the Deck, point the symlink at the Proton prefix instead:

Terminal window
P=~/.local/share/Steam/steamapps/compatdata/<appid>/pfx/drive_c/users/steamuser/AppData/Roaming/SomeGame
mv "$P/saves" ~/Sync/SomeGame-saves
ln -s ~/Sync/SomeGame-saves "$P/saves"

On Windows, from an elevated prompt (or with Developer Mode on):

mklink /D "C:\Users\<user>\AppData\Roaming\SomeGame\saves" "D:\Sync\SomeGame-saves"

Do the move on one machine only, let Syncthing copy the content to the others, and then create the symlink on each of them. Put the real files in the Syncthing folder and the symlink at the game’s path, never the other way around, because Syncthing syncs a symlink as a link, not as the files behind it.

This approach is faster and has no backup history of its own. A game that holds files open while running, or writes them in odd patterns, can sync half a save. Some games also check that their save path is a real folder, and break on a link. Use symlinks for games you have tested, and keep Ludusavi running for everything else.

What NOT to Sync

A bad sync rule costs more than a missing one. Skip these:

For the symlink approach, add a .stignore file at the root of the synced folder. The (?d) prefix tells Syncthing it may delete an ignored file if that blocks removing a directory:

.stignore
(?d)*.log
(?d)GPUCache
(?d)shadercache
*.tmp

For the Ludusavi approach, you rarely need ignores, because Ludusavi only copies save paths from the manifest. That is its best feature. If a game’s manifest entry pulls in more than you want, mark paths as ignored in Ludusavi, which is where that decision belongs.

Anti-Cheat and Steam Cloud Overlap

Save sync touches files, not game memory, so it does not trigger anti-cheat. Online games with server-side saves have nothing local to sync. Do not sync files inside an anti-cheat’s own folder, though, and do not restore saves for an online ranked mode. Some will flag modified progress.

If Steam Cloud is on for a game and you also sync it with Ludusavi, you now have two systems moving the same file. Steam tends to win at launch, because it syncs before the game starts. For any game you manage with Ludusavi, turn off Steam Cloud in the game’s properties to avoid a fight between them.

The SumGuy Take

Most people need two tools, not a platform. Ludusavi answers “where are the saves.” Syncthing answers “get them to my other machines.” Neither needs an account, and both are plain files you can read with ls.

Start with one game on two machines. Use --preview before every first run. Turn on staggered versioning. Wrap your launch options once the manual flow feels right. Your 2 AM self will thank you when a save corrupts and the previous one is sitting in .stversions.

Common Questions

Does Ludusavi work with Steam Deck games and Proton prefixes?

Yes, Ludusavi works with Proton games on a Steam Deck. Add the Steam library as a root with store: steam, and Ludusavi finds saves inside each compatdata/<appid>/pfx prefix. For games the manifest marks as using registry saves, it also backs up the Proton .reg files. Cross-OS restores to a Windows path need a redirect.

Can I use Syncthing and Steam Cloud together?

You can, but Steam Cloud and Syncthing then both move the same save files, and they will disagree. Steam Cloud typically syncs at game launch and exit, while Syncthing syncs continuously. Pick one system per game, and turn off Steam Cloud in the game’s properties for games you sync yourself.

Is it safe to sync saves while the game is running?

No, syncing saves while the game runs risks truncated or corrupt files. Games hold save files open and write them in several steps, and Syncthing may copy a half-written file. Back up after the game exits. Ludusavi’s wrap command does exactly this, restoring before launch and backing up after you quit.

Does this cost anything?

No, the setup costs nothing. Ludusavi and Syncthing are both free, open-source software, and Syncthing needs no account or subscription. Your only cost is hardware. A Raspberry Pi or any spare machine works as the always-on node, and the saves themselves are small.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Next Post
Pre-Commit Hooks That Catch Secrets

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts