Syncing & commits

ForkLeaf is deliberately explicit about the difference between “saved on this device” and “pushed to GitHub”. An autosaving app that is vague about that distinction is how people come to believe they lost work.

The life of an edit

  1. You type. The editor updates.
  2. A few hundred milliseconds later the note is written to IndexedDB. It is now safe against a crash, a closed tab, or a flat battery.
  3. A pending change is queued: the path, the new content, and the SHA the edit was based on.
  4. The sync engine drains the queue — on a timer, on reconnect, or immediately when you press ⌘S.
  5. Changes are pushed to GitHub as a commit, and the queue empties.

Reading the status bar

What it saysWhat it means
All changes savedLocal and GitHub agree. Nothing is pending.
Saved locally · 2 to pushTwo notes are safely on this device but have not reached GitHub yet. Click to push now.
Saving to GitHub…A push is in flight.
Offline · 3 changes queuedNo network. Everything is on this device and will go up automatically when you reconnect.
A sentence saying what went wrong — click to retryThe push failed. The message says what happened and what to do about it; nothing was lost, and your work is on this device either way.
2 conflicts — click to resolveThe same note changed here and on GitHub. See Conflicts.
Saved on this deviceYou are in the local workspace, which never pushes.

What the commits look like

One commit per sync, containing every change in that batch. Multi-file operations — a rename is a delete plus a create — go through GitHub’s tree API as a single atomic commit, so the repository can never be left half-updated.

git log --oneline
a3f9c21 forkleaf: update architecture/sync-engine.md
7b21e08 forkleaf: update 3 notes
1c94ffa forkleaf: rename reading.md to reading-list.md

Commit squashing

Typing produces a lot of small saves, and a commit per keystroke-batch would bury your history. So when the branch head is a commit ForkLeaf made recently, the next push amends it rather than stacking a new one.

The guard rails on that are strict, because rewriting history is dangerous:

  • Only if the head commit carries ForkLeaf’s own marker in its message.
  • Only within a short time window.
  • Only if the author matches.
  • Never if anyone else has pushed in the meantime.
A way to make ForkLeaf rewrite or destroy a commit it did not create is a security bug. Please report it — see the security model.

Offline

Everything works: opening notes, writing, switching views, inserting diagrams, exporting. The queue accumulates and the status bar says how much is waiting. On reconnect it drains automatically.

If you try to close the tab with unpushed changes, the browser asks you to confirm.

Across devices

Sign in with the same GitHub account elsewhere and ForkLeaf pulls the repository down. Both devices commit to the same branch, and each pulls the other’s commits on the next sync. If they both changed the same note, you get a conflict rather than a silent overwrite.

Deleting

Deleting a note commits the deletion. The content remains in your git history, so it is recoverable:

terminal
# find the commit that deleted it
git log --diff-filter=D --name-only -- meetings/2026-08-14.md

# restore it from the commit before that
git checkout <commit>^ -- meetings/2026-08-14.md

Rate limits

Authenticated GitHub requests are capped at 5,000 per hour per user. ForkLeaf stays well under that by batching and by squashing, but if you do hit it, pushes fail with a rate-limit error and resume automatically once the window resets. Nothing is lost in the meantime.