Sync hand-picked single files — .vimrc, .gitconfig, a shell profile — between your
machines, using one secret GitHub Gist per file. Transfers are explicit: you say push or
pull, one file at a time, and the tool tells you when the two sides have diverged instead
of guessing.
What it is not: not a folder sync, not a background daemon, not a merge tool. It never watches files, never syncs on its own, never merges, and never deletes a gist.
The GitHub CLI is the only route to GitHub — gistsync holds no
token of its own. Install gh, then:
gh auth loginThe gist scope is required.
go build -o gistsync .Cross-compile for the other machine (no CGO, single static binary):
GOOS=windows GOARCH=amd64 go build -o gistsync.exe .GOOS=darwin GOARCH=arm64 go build -o gistsync .Put the binary anywhere on your PATH.
gistsync initgistsync add ~/.vimrcThe logical name comes from the basename with leading dots stripped, so ~/.vimrc is
tracked as vimrc. Pass --name to choose your own; you will need it if two files share a
basename.
gistsync push vimrcThat creates the secret gist and prints its URL. The gist's description is gistsync:vimrc
— that string, not the ID, is what the other machine looks for.
The name is the bridge; the path differs on every machine, so you give it once to link.
gistsync initgistsync list --remoteThat shows every gistsync gist on your account and which are tracked here — useful when you have forgotten what you named things.
gistsync link vimrc C:/Users/me/_vimrclink finds the gist by its description, writes the [[file]] entry into this device's
config.toml, and records the gist ID. No gist ID is ever copied between machines by hand.
The path may point at a file that does not exist yet — that is the usual case.
gistsync pull vimrcpull writes the file, creating parent directories if needed. link never touches your
files.
If the name is already in config.toml, the path is optional: gistsync link vimrc just
records the gist ID.
link compares the two copies and tells you where you stand:
- identical — it records the sync markers and you are
cleanimmediately, no transfer. - different — it links anyway and prints both locations. Nothing has been overwritten,
and the state is
conflict: the two copies have no version in common, sopushandpullboth refuse until you pick a winner with--force.
gistsync status| state | meaning | what to do |
|---|---|---|
clean |
both sides match the last sync | nothing |
ahead |
you edited locally | push |
behind |
the other machine pushed | pull |
conflict |
both changed since the last sync, or the two copies never shared one | compare, then force one way |
never pushed |
no gist yet for this name | push or link |
missing locally |
the configured path does not exist | pull |
The state column is colour-coded when stdout is a terminal — green clean, yellow ahead,
cyan behind, red conflict/missing locally, magenta never pushed. Set NO_COLOR or pipe
the output to get plain text.
Offline, status still works: it prints remote unknown per file and tells you whether the
local copy changed. push, pull, link, and add need the network and fail loudly
without it, changing nothing.
push refuses when you are behind or in conflict; pull refuses when you are ahead or
in conflict. There is no merge — you pick a winner:
gistsync push --force vimrcgistsync pull --force vimrcThe first overwrites the gist with the local file, the second overwrites the local file with the gist. Look at both copies before you run either.
To stop tracking a file here:
gistsync rm vimrcThat untracks it locally and leaves both the file on disk and the gist on GitHub alone — delete the gist yourself on github.com if you want it gone.
Both files sit in ~/.gistsync/ (%USERPROFILE%\.gistsync\ on Windows):
config.toml— one[[file]]block per tracked file, with the name and this machine's absolute path.addandlinkwrite it for you; editing it by hand is supported but never required.state.json— the tool's. Gist IDs and last-sync fingerprints, per device. Editing it by hand is how you get a wrong answer fromstatus.
Content moves byte-exact in both directions: CRLF stays CRLF, a missing trailing newline stays missing. Text only — binary and non-UTF-8 files are refused rather than mangled.