RIME has had sync_dir for a long time (since librime-1.5 era, ~2017). The mechanism is well-documented in rime/home/wiki/UserGuide and github.com/Mintimate/oh-my-rime‘s English guide. But the docs assume you’ve been a RIME user for a while — they skip some “first-time installer” gotchas. This article covers the three-device workflow on Linux / Mac / Windows in 2026, with verification on Debian 13 + macOS Sonoma + Windows 11.
How RIME sync actually works
The unit of sync is the *.userdb.txt snapshot. When RIME accepts a phrase you typed (or when you redeploy), it writes a snapshot of the user dictionary into a per-device folder under your sync_dir. The installation_id controls which folder is yours.
The folder layout under your sync_dir (e.g. ~/Dropbox/RimeSync/) looks like:
RimeSync/
├── id-laptop-fred-m2/
│ ├── installation.yaml # a copy of this device's installation_id + sync_dir
│ ├── default.custom.yaml # the user-edited configs in your RIME root
│ ├── squirrel.custom.yaml # Mac-only
│ ├── luna_pinyin.userdb.txt
│ ├── wubi_pinyin.userdb.txt
│ └── ... (one userdb per active schema)
├── id-fred-officepc/
│ ├── installation.yaml
│ ├── default.custom.yaml
│ ├── weasel.custom.yaml # Windows-only
│ └── ...
└── id-fred-x1carbon/
└── ...Two things to notice:
- Static dictionaries (
.dict.yamlfiles,dicts/folder, Lua scripts, the big.grammodel) are not synced. They live at each device’s~/.local/share/fcitx5/rime/, separately. The sync folders only contain user-modified.yamland the userdb snapshots. If you want the same ice/frost/wanxiang schema on every device, you re-run Plum on each. - The synchronizer does a snapshot-merge, not file sync. When you click “Sync”, RIME walks every
id-*subfolder, reads each<schema>.userdb.txt, and merges entries into the local user dictionary. Conflicts are resolved by max-weight — the higher weight wins. So if you typed a phrase twice on laptop and three times on desktop, your desktop’s weight (3) becomes the canonical weight.
Step 1 — set the same sync_dir on every device
Pick a cloud folder that’s mounted on every device. Dropbox is the most-tested option because RIME’s first-class sync docs all use Dropbox as the example. iCloud Drive works, OneDrive works, Nutstore / 坚果云 works, a Syncthing peer works. Pick whichever you already have set up.
Decide on a folder name. Most people use RimeSync at the root of the synced folder:
- Linux:
~/Dropbox/RimeSync/(or wherever your Dropbox is mounted) - macOS:
~/Dropbox/RimeSync/ - Windows:
%USERPROFILE%DropboxRimeSync
The RIME installation.yaml file at each device’s ~/.local/share/fcitx5/rime/ controls this. Edit it to add sync_dir:
# Linux: ~/.local/share/fcitx5/rime/installation.yaml
distribution_name: fcitx5-rime
distribution_version: 5.1.13
install_time: "Tue Jul 14 14:00:00 2026"
installation_id: "thinkpad-x1-linux" # ← set per-device (see step 2)
sync_dir: "/home/fred/Dropbox/RimeSync" # ← absolute path on this device
rime_version: 1.16.1# macOS Squirrel: ~/Library/Rime/installation.yaml
distribution_name: Squirrel
distribution_version: 0.16.2
install_time: "Tue Jul 14 14:00:01 2026"
installation_id: "macbook-pro-m2" # ← different from the linux one
sync_dir: "/Users/fred/Dropbox/RimeSync"
rime_version: 1.8.5# Windows Weasel: %APPDATA%Rimeinstallation.yaml
distribution_name: Weasel
distribution_version: 0.16.2
install_time: "Tue Jul 14 14:00:02 2026"
installation_id: "office-pc-windows" # ← different again
sync_dir: "C:\Users\fred\Dropbox\RimeSync"
rime_version: 1.8.5Three rules:
- Each device’s
installation_idmust be unique across all devices. RIME uses it as the subfolder name; collision means entries from two devices silently overwrite each other. Convention: lowercase letters + digits +-+_, no spaces, no Chinese. Pick a name you’ll recognize inls ~/Dropbox/RimeSync/six months from now. sync_dirpaths differ per OS. The Linux path uses/home/..., macOS uses/Users/..., Windows usesC:Users.... Avoid~/— it expands differently depending on how RIME was launched (it can beC:UsersfredAppDataRoaming~on Windows, which is not what you want).- Windows paths in YAML need quoting. The backslashes are escape characters in YAML double quotes. Either use single quotes
'C:UsersfredDropboxRimeSync'(no escape processing) or use forward slashes'C:/Users/fred/Dropbox/RimeSync'and let Windows normalize them.
Redeploy after editing installation.yaml. The RIME engine only reads it on deploy.
Step 2 — set installation_id deliberately
The first time RIME deploys with an empty installation_id field, it generates a random UUID (c5f45f7e-3c1c-4257-8ff7-bce78e9b5fb5-style). That’s fine — UUIDs are unique — but harder to read in ls. Most setups replace it with a meaningful string:
installation_id: "fred-thinkpad-x1" # better than a UUIDRIME checks installation_id characters when reading the file: only lowercase letters, digits, -, and _ will work cleanly. The upstream user guide says:
因爲 Rime 要以這個 ID 爲名創建文件夾,因此 ID 不得包含(所有涉及同步的文件系統)文件名中非法的字符;建議不要用中文,只用小寫字母、數字、橫線和下劃線。
A typo here is recoverable (edit, redeploy, sync) but causes a window where sync_dir/id-old-typo/ and sync_dir/id-fred-thinkpad-x1/ both exist. Just clean up the orphan with rm -rf.
Step 3 — first sync run
This is where most first-timers get confused. The flow:
- Redeploy on device A to write
installation.yamlwith the newsync_dirandinstallation_id. - Open RIME’s tray menu and click “同步” / “Sync” on device A. RIME creates
~/Dropbox/RimeSync/id-fred-thinkpad-x1/and dumps the local userdb snapshots in. - Wait until Dropbox syncs the files (you can verify with
ls ~/Dropbox/RimeSync/id-fred-thinkpad-x1/on device B). - Redeploy on device B, then click “Sync”. RIME sees its own empty user dictionary + the snapshot from A, merges them, writes a new snapshot.
- Done. From here, sync is one click per device per change.
If your distro’s RIME port doesn’t expose a “Sync” button in the tray menu (some don’t — e.g. older fcitx5-rime, some custom Linux builds), the same thing happens in two places: the desktop IME’s config UI exposes a sync button; or you can run librime-ctl (not always shipped) to invoke it from the CLI. On macOS, Squirrel exposes the “同步” button in its main menu. On Linux fcitx5-rime, the menu item is Rime → 同步... after you’ve added any IME entry to the active list.
If you’d rather make this automatic, the “Sync” button maps to rime_deployer --sync. Combine it with a cron / systemd timer on Linux:
# cron.d entry for one user: every 30 min sync
*/30 * * * * fred /usr/bin/rime_deployer --syncNote the first run after enabling cron needs at least two sync’ing devices that have seen each other once via the GUI, or you’ll get an empty cache.
What gets synced, what doesn’t
The sync walk is:
- For each sibling
id-*subfolder undersync_dir, RIME loads every<schema>.userdb.txtit finds. - RIME’s user-dict merge code combines those snapshots into one in-memory user dictionary.
- RIME writes a fresh snapshot to this device’s own
id-*folder. - RIME also copies (one-way, always from local to remote) the following files from your local RIME root to the sync folder:
installation.yaml(always)default.custom.yaml(if present)<schema>.custom.yaml(if present)- Other hand-edited
*.yamlfiles at the RIME root
NOT synced (per upstream doc):
- The static
*.dict.yamldictionaries - The Lua scripts under
lua/ - The
wanxiang-lts-zh-hans.gram(or any other.grammodel) - The
dicts/folder under community schemas (rime-ice / rime-frost / rime-wanxiang’s per-vocab splits) - The build cache (
build/*.binfiles) - Configuration files inside subdirectories (like a schema’s own
custom/)
The reason is not laziness — it’s that these files are static from one perspective and re-creating them is part of the install process. Reproducing the install (Plum + a couple of optional downloads) is the recommended way to get a new device in sync at the schema level.
If you DO want to carry schema files across (people managing a small fleet of identical devices often do), the cleanest path is git rather than the RIME sync mechanism:
# Linux & Mac: install once, then push to a private git repo
cd ~/.local/share/fcitx5/rime/ # or ~/Library/Rime on Mac
git init
git add . && git commit -m "starting config"
# Push to a private GitHub repo; pull on every other deviceinstallation_id is part of installation.yaml — make sure to edit it on each clone, then commit. The sync mechanism still uses installation.yaml from each local file, not from git.
Migrating an existing user dictionary to a new schema
The wiki example is migrating luna_pinyin.userdb.txt (built up on stock luna_pinyin) to rime_mint.userdb.txt (the new schema you’re switching to). The recipe (verified against the wiki):
- Copy
luna_pinyin.userdb.txtto your new schema’s filename. So rename the file from the old to the new schema ID. (rime_mint.userdb.txtfor oh-my-rime, for example.) - Edit the
db_nameline at the top of the file. Look near the top of the.userdb.txt; you’ll see a comment like#@/db_name = luna_pinyin. Change the right-hand side to the new schema ID. - Put the renamed file in your
sync_dir(any siblingid-*folder, or directly insync_dir/). - Click Sync. RIME merges it as if it came from another device.
The wiki warns about character-set issues:
If you used a Traditional Chinese dictionary before, you need to do a conversion from Simplified Chinese to Traditional Chinese in advance. Be careful not to convert all
Tabto spaces.
That’s a real risk: a Notepad on Windows or a careless paste-through-IDE pipeline can rewrite tabs into 4 spaces, which silently breaks the userdb format (RIME expects tab-separated). Always re-tab after any conversion.
Common pitfalls
“I clicked Sync but nothing happened.”
Three things to check:
installation.yamlexists and the YAML parses. Validate withpython3 -c "import yaml; print(yaml.safe_load(open('installation.yaml')))".sync_dirpath actually exists and is writable by the RIME process. Some Dropbox-installed-on-Linux configurations mount the folder under~/.dropbox-dist/, not~/Dropbox/.ls -la $sync_dirto confirm.- Wait. The first sync can take 30-60 seconds even on a small user dictionary because of the merge pass. Open a second terminal and
tail -Fthe RIME log (echo "log: $(cat ~/.cache/fcitx5/rime.log | tail -5)") — if you see “sync completed”, it worked.
“My phrases got merged but I lost earlier custom phrases.”
This happens when the sync_dir folder ended up with *two `id-subfolders pointing to the same physical machine**. The duplicate got selected over the original; the original's.userdb.txtwas discarded. Clean up: remove the orphanid-*/` folder, click Sync again.
“Both my laptops show the same installation_id.”
Means you edited installation.yaml and copied the file to both before deploying. Don’t sync before you’ve made the IDs unique. The fix: edit each installation.yaml in place, redeploy, then sync.
“Some schemas’ userdb syncs, others don’t.”
Schema name must match the userdb filename. RIME only syncs the userdb whose schema is currently active. If rime_ice.userdb.txt shows up on device A but not B, it means B doesn’t have rime_ice in its schema_list. Add it under default.custom.yaml schema_list, redeploy, sync.
“Sync wiped all my custom phrases after a clean install.”
Means the freshly-deployed device’s *.userdb.txt was empty (clear install), and the sync merged “nothing” with the older snapshot. RIME uses max-weight per phrase, so an empty entry doesn’t delete a non-empty one. But if you Deploy on a freshly-installed device before Sync, the deploy creates a fresh <schema>.userdb.txt from zero. Then Sync merges from the (older, populated) cloud folder. So the order is: Sync first, then Deploy. If you deploy’d first, just re-sync — the cloud is still there.
Mac-only thing: iCloud Drive vs Dropbox
~/Library/Mobile Documents/com~apple~CloudDocs/Rime/ works the same as a Dropbox folder, but expect one quirk: Apple randomly renames folders across upgrades (the AVFS / MobileSync background process). Set sync_dir to the absolute path inside Library/Mobile Documents/..., never a symlink. If iCloud renames the path, RIME fails to find the folder silently. Re-edit installation.yaml to the new path.
A common workaround: store the actual sync folder at ~/RimeSync-iCloud/, then symlink it into iCloud Drive’s documents directory and reference the absolute path (~/RimeSync-iCloud/) in installation.yaml. That way iCloud’s renaming is invisible to RIME.
Windows-only thing: file locks
Weasel (the official 小狼毫 Windows port) historically has had issues where the userdb file is locked while RIME is running. If you Deploy / Sync on device B while device A is using RIME, you’ll see a copy-conflict file (luna_pinyin.userdb.txt (Fred-PC's conflicted copy ...)) instead of a clean merge. The fix is to stop the IME on the other device during the first sync — or accept the conflict file as ground truth for that one device.
For more than two Windows machines, the cleanest pattern is to put Weasel on hold (Rime 暂停) during any sync window.
What next
If this got you set up across three devices, the natural next article is a deep-dive into .gram model selection and training — which wanxiang-lts-zh-hans.gram is for what use case, whether the smaller essay.txt is enough for shorter sentences, how librime 1.16 vs 1.17 differ on model loading. Tell me in the comments.
Sources verified July 2026: github.com/rime/home/wiki/UserGuide (the canonical sync doc), github.com/Mintimate/oh-my-rime English sync guide (the best third-party writeup), deepwiki.com/ssnhd/rime/2.4-synchronization-system (synced-config behavior on iCloud). wanxiang-lts-zh-hans.gram model file referenced as per upstream RIME-LMDG.
Comments