Data Sync in Electerm: One Setup, Every Machine in Sync
New laptop, same fifty bookmarks. Re-creating connections by hand is not setup — it is déjà vu with extra steps.
Electerm has a dedicated panel for exactly this: Settings → Sync. It uploads your data to one of five backends and downloads it on the next machine — bookmarks, bookmark groups, terminal themes, quick commands, profiles, address bookmarks, workspaces, triggers, plus a slice of app settings. Same hosts on the laptop and the desktop, no copy-paste.
Read this first: sync is full-replace, not merge. A download overwrites the local data sets it covers (
store.setItems(n, arr)per type insrc/client/store/sync.js). The preview section below shows how to look before you leap.
1. The five backends, side by side
The tab strip in src/client/components/setting-sync/setting-sync.jsx renders one tab per entry of syncTypes (src/client/common/constants.js). Your build may hide some via allowedSyncTypes(), but stock electerm ships all five:
| github | gitee | custom | cloud | webdav | |
|---|---|---|---|---|---|
| Stores in | Secret gist | Secret gist | Your own HTTP service | sync.electerm.org (beta) |
Any WebDAV server |
| Credential | Personal access token (gist scope) + gist id |
Same shape, gitee token + gist id | API url + JWT secret + user id | Token (login on the site) | Server url + username + password |
| Best for | Most users, free and reliable | China-mainland users who prefer gitee | Self-hosters, teams | Zero-setup, no gist fiddling | NAS / Nextcloud / 坚果云 owners |
Switching tabs never loses the other backends' credentials — each type keeps its own *AccessToken, *GistId, *LastSyncTime, *SyncPassword keys under config.syncSetting, and Save only writes the active tab (setting-sync-form.jsx → updateSyncSetting).
2. A first sync in 60 seconds (github)
- Create a token with gist scope only at
github.com/settings/tokens/new— copy it now, GitHub never shows it again (wiki: Create personal access token). - Create a secret gist at
gist.github.com, copy the id from the URL (.../your-name/xxxxxxxx→xxxxxxxx). - In electerm open Settings → Sync → github, paste token + gist id, optionally set an encrypt password (section 5), set a proxy if you need one, click Save.
- Click Upload on the old machine, Download on the new one. Check lastSyncTime and the Check gist link to confirm.
The same shape works for gitee — but read the warning first: the panel shows an explicit "Gitee data sync is not recommended" alert (wiki: gitee data sync warning). Prefer github, cloud or WebDAV for new setups.
3. What actually gets synced
syncDataMaps in constants.js is the whole contract:
{
settings: ['config'], // a curated subset, see below
bookmarks: ['bookmarks', 'bookmarkGroups'],
terminalThemes: ['terminalThemes'],
quickCommands: ['quickCommands'],
profiles: ['profiles'],
addressBookmarks: ['addressBookmarks'],
workspaces: ['workspaces'],
triggers: ['triggers']
}
Below the form, the data-type checkboxes (data-select.jsx) write config.dataSyncSelected — all by default, or a comma list when you untick something. getDataSyncNames() turns that selection into { names, syncConfig }, and only those names are uploaded (uploadSettingAction) or overwritten on download (downloadSettingAction).
Two details worth knowing:
- Settings means a curated list, not the whole config (
getSyncConfig()insync.js): theme, font size, scrollback, hotkey, language, terminal options, AI settings and friends — about forty keys. Server-managed keys (tokenElecterm,host,port,wsHost, …) are stripped on import (stripServerManagedKeys) so a synced config can never break the running server's WebSocket token. - Order travels too. Each data set uploads a
<name>.order.jsoncompanion; on download the arrays are re-sorted to that order, so bookmark/tab order survives the trip.
4. Per-backend setup notes
Custom server (wiki) — fill API url, JWT secret, user id. The contract is tiny: PUT stores the JSON body (user id from jwtData.id), GET returns it, POST returns ok when the user id verifies. Ready-made servers exist for Cloudflare Workers + D1 (recommended), Vercel, Python, Rust, Go, Java and more under the electerm/electerm-sync-server-* repos.
Cloud — the sync.electerm.org [Beta] link in the form. No gist id field: on save electerm pins cloudGistId = 'cloud' and the default API url, you just paste the token from the site.
WebDAV (wiki) — pick the webdav tab and fill server url, username, password, plus Skip SSL verify for self-signed setups. URL shapes: Nextcloud/ownCloud https://server/remote.php/dav/files/username, 坚果云 https://dav.jianguoyun.com/dav/, plain Apache/nginx /dav/. On the server electerm keeps one /electerm/ folder with <name>.json files plus userConfig.json and electerm-status.json (device name, electerm version, lastSyncTime). Use HTTPS in production, prefer app passwords, and back up the folder.
Every backend also accepts an optional proxy (socks5://127.0.0.1:1080 style, see the proxy format wiki).
5. Encryption: what the password protects
The encrypt password field is per backend (<type>SyncPassword). When set:
- Only bookmarks and profiles are encrypted on upload (
encryptAsyncinuploadSettingAction); themes, quick commands and the rest stay plaintext JSON. - Download is fail-closed (
decryptSyncData): if a password is configured butbookmarks.json/profiles.jsonarrive as plaintext[…], the download aborts instead of importing possibly-tampered data. - There is no recovery. Lose the password and the server copy is unreadable — the wiki says it plainly, and the code agrees: nothing decrypts without it.
Practical rule: set the password before the first upload, use the same password on every device, and store it in a password manager — not in a bookmark.
6. Upload, download, and looking first
- Upload (
uploadSetting) pushes the selected data sets pluselecterm-status.json(timestamp, version, hostname). For gist backends that is oneupdatecall on the gist; for WebDAV it is onePUTper file. - Download (
downloadSetting) fetches, decrypts, runsfixBookmarks/fixThemes, restores order, applies the curateduserConfig.json, and stamps<type>LastSyncTime. - Preview — the server data status line under the buttons plus
previewServerDataWithComparepower the diff view (sync-data-compare.jsx):remote: N <type>, local: M <type> → upload/download?per data set, orData in syncwhen nothing differs. Check it before a first download onto a machine that already has bookmarks. - Empty-target errors are explicit: "Seems you have a empty gist, you can try use existing gist ID or upload first" (gist) and the WebDAV-folder equivalent mean exactly what they say — upload first, then download.
7. Auto sync and file export
Above the tabs, the export / import / auto-sync row (data-import.jsx) covers the hands-free paths:
- Auto sync switch (wiki: Auto data Sync) with interval (
On Change, 5/10/15/30 min, 1/2/6/12/24 h) and direction (upload / download). Default is on-change upload: any data edit triggersuploadSettingAllacross every configured backend. Interval mode is polled byauto-sync.jsx; download direction keeps a second device following the first. - Export (
handleExportAllData) downloads oneYYYY-MM-DD-HH-mm-ss-electerm-all-data.jsonwith every data set plus full config — the offline backup. - Import (
importAll) replaces the same data sets from that file in 200-item chunks with a progress bar, then applies the config (server-managed keys stripped, theme re-applied).
Bookmark triggers travel with the bookmark through sync, so the login flow tuned on one machine already works on the next — see Terminal Triggers.
8. Safety rules that actually matter
- Secret gists only. A public gist publishes your hostnames, usernames and (if unencrypted) passwords to the internet. Create secret, keep the id private.
- Token scope = gist, nothing more. A broader token turns a leaked sync setting into a leaked GitHub account.
- Set the encrypt password first, and never store it only inside electerm.
- Preview before the first download onto a non-empty machine — download replaces, it does not merge.
- One writer at a time. Two machines with on-change upload racing each other last-write-wins; for fleets prefer one uploader + the rest on interval download.
Cheat-sheet
- Find it — Settings (gear) → Sync. Five tabs: github / gitee / custom / cloud / webdav.
- First run — token (+ gist id) → Save → Upload here, Download there; watch
lastSyncTime. - Pick data — checkboxes below the form (
dataSyncSelected); settings syncs a curated ~40-key list, server keys stripped. - Lock it — encrypt password covers bookmarks + profiles, fail-closed on download, unrecoverable if lost.
- Hands-free — auto sync (on-change or interval, upload or download) + one-file export/import for offline backup.
- Rule of thumb: new machine → preview → download; daily driver → on-change upload; secret or fleet → encrypt + private backend.
Next: Terminal Triggers for the automation rules that ride along with your synced bookmarks, or Password Management for rotating the secrets those bookmarks carry.
