-
Notifications
You must be signed in to change notification settings - Fork 0
Git sync
Back up Keystrike settings and typing sessions to a private git repository you control. Sync is opt-in, CLI-only, and runs only when you invoke it — there is no Keystrike cloud, no background daemon, and no automatic upload when a session ends.
| Is | A git-backed backup and manual multi-device sync via keystrike sync
|
| Is not | Cloud sync, real-time sync, or a Keystrike-hosted service |
Your data stays in your git remote (GitHub, GitLab, self-hosted, etc.). Keystrike never talks to that remote except when you run a sync command.
- Keystrike with git sync support (see CHANGELOG).
-
giton your PATH — sync shells out to the git CLI for clone, pull, and push. -
Git credentials configured for your remote:
-
SSH — e.g.
git@github.com:you/keystrike-backup.git(SSH key loaded in your agent). -
HTTPS — e.g.
https://github.com/you/keystrike-backup.git(credential helper or personal access token).
-
SSH — e.g.
- A private remote repository (strongly recommended). Session logs contain your typing history.
Optional but recommended: set git config user.name and git config user.email on each machine so sync commits have sensible authorship.
On GitHub (or elsewhere), create an empty private repository, e.g. keystrike-backup. Do not add a README if you want a truly empty repo — an empty repo works fine; Keystrike initializes the layout on first push.
keystrike sync init git@github.com:you/keystrike-backup.git
# or
keystrike sync init https://github.com/you/keystrike-backup.gitThis command:
- Writes your remote URL to
sync.toml(see File locations). - Clones the remote (or runs
git initlocally if the remote is empty). - Merges local and remote data using Keystrike's merge rules (below).
- Pushes the merged snapshot to the remote.
Run init once per machine. On a second device, use the same remote URL so both machines share one backup repo.
| Command | When to use |
|---|---|
keystrike sync push |
After practice on this machine — upload new sessions and settings. |
keystrike sync pull |
Before practice on this machine — download sessions from other devices and rebuild local stats. |
keystrike sync status |
Check remote URL, session counts, and whether the clone has uncommitted changes. |
Typical multi-device habit:
-
Before opening Keystrike:
keystrike sync pull - Practice as usual (the TUI does not sync by itself).
-
After a session (or end of day):
keystrike sync push
Example output:
$ keystrike sync status
remote: git@github.com:you/keystrike-backup.git
sessions: local=42 clone=40 (only local=2, only remote=0)
git: (clean)
$ keystrike sync push
push complete
$ keystrike sync pull
pull complete: 3 session(s) imported
| Synced | Not synced |
|---|---|
settings.toml |
cache/ (derived stats — rebuilt locally) |
layouts/*.toml (custom layouts) |
Bundled layouts shipped with Keystrike |
sessions/index.jsonl |
Logs outside the sessions tree |
sessions/**/*.jsonl (session keystroke logs) |
After a successful pull, Keystrike replays all sessions in the merged index and rebuilds the stats cache for every layout it finds. You do not need to sync cache files.
Keystrike applies its own merge logic before every push and pull. Git is used only for transport; JSONL session files are not left to git's native merge.
- Sessions are identified by
session_idinsessions/index.jsonl. - Missing sessions are imported — if the remote has a session ID your machine lacks, the session file and index entry are copied in.
-
Existing IDs are never overwritten — if both sides have the same
session_id, the local copy wins and the remote copy is left unchanged on import.
This means you can practice on two machines offline and merge later without losing sessions, as long as each session has a unique ID (Keystrike generates UUIDs).
- Keystrike compares
updated_atinsettings.toml(ISO timestamp, written on every save). - The newer file is copied to both local and clone before push/pull.
- If
updated_atis missing on either side, file modification time is used instead.
Whichever machine saved settings most recently wins globally after the next sync.
- Pull: remote layout TOML files that are missing locally are copied in. Existing local files with the same name are not overwritten.
- Push: all local custom layout files are copied into the clone (overwriting same-named files in the clone).
If two machines edit the same layout filename differently, the last push wins on the remote; the other machine won't see those edits until it pulls and may keep its local copy until you resolve the conflict manually.
- Pull before push on each machine to reduce divergent git history.
- Use a private remote — session JSONL is sensitive.
- Same remote on every device — one backup repo for all machines.
-
Check status when unsure:
only local/only remotecounts show what still needs a push or pull.
-
Fast-forward pull only —
keystrike sync pullrunsgit pull --ff-only. If you pushed from two machines without pulling in between, the remote history can diverge and pull will fail. Fix on the clone:cd ~/.config/keystrike/sync/repo(paths vary by OS), resolve withgit pull --rebaseor merge manually, then retrykeystrike sync pull. - No automatic sync — nothing runs when a session ends; you must run push/pull yourself.
- Layout name conflicts — same filename, different content: last push to remote wins; pull does not overwrite existing local layouts.
-
Settings conflicts — no three-way merge; newest
updated_at(or mtime) wins outright. -
Session duplicates — same
session_idon both sides keeps the local version on import; design assumes IDs are unique.
Paths use platformdirs (same roots as other Keystrike data):
| File / directory | Purpose |
|---|---|
{config_dir}/sync.toml |
Remote URL written by sync init
|
{config_dir}/sync/repo/ |
Local git clone used for push/pull |
{config_dir}/settings.toml |
Synced settings |
{config_dir}/layouts/ |
Synced custom layouts |
{data_dir}/sessions/ |
Synced session logs |
Typical {config_dir} / {data_dir}:
| OS | Config | Data (sessions) |
|---|---|---|
| Linux | ~/.config/keystrike/ |
~/.local/share/keystrike/ |
| macOS | ~/Library/Application Support/keystrike/ |
same tree under Application Support |
| Windows | %APPDATA%\keystrike\ |
%LOCALAPPDATA%\keystrike\ |
sync.toml contains only the remote URL, for example:
remote_url = "git@github.com:you/keystrike-backup.git"Run one-time setup:
keystrike sync init <repo-url>- Test:
ssh -T git@github.com - Ensure your SSH key is loaded (
ssh-add -l) and added to your GitHub account.
- Use a credential helper or embed a PAT in the URL (less ideal):
https://<token>@github.com/you/keystrike-backup.git - Prefer
gh auth loginor Git Credential Manager.
sync init handles empty remotes: if git clone fails, Keystrike runs git init, adds origin, merges local data, and pushes.
Two machines pushed without pulling. On the affected machine:
cd ~/.config/keystrike/sync/repo # adjust for your OS
git fetch origin
git log --oneline --graph --all -5 # inspect
git pull --rebase origin main # or master — match your default branch
keystrike sync pullWhen in doubt, back up {config_dir} and {data_dir} before fixing git history manually.
Configure git on that machine:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"Then retry keystrike sync push.
Pull rebuilds aggregates from the session index. If something still looks wrong, check keystrike sync status session counts and confirm session files exist under {data_dir}/sessions/.