Skip to content

Commit f5ae9b0

Browse files
authored
Update README for dotfilesync v3.0
Refactor README to update project name and features
1 parent b5abb2d commit f5ae9b0

1 file changed

Lines changed: 88 additions & 155 deletions

File tree

README.md

Lines changed: 88 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -1,191 +1,124 @@
1-
Sync dotfiles with Gist
2-
=======================
1+
#  dotfilesync (v3.0)
32

4-
What is dotfilesync?
5-
--------------------
3+
[![Bash Shell](https://img.shields.io/badge/shell-bash-4eaa25.svg)](https://www.gnu.org/software/bash/)
4+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
65

7-
dotfilesync is a bash script that syncs a list of local files that _you_ define, into a secret gist, that _you_ own.
6+
**dotfilesync** is a high-performance, security-focused Bash utility designed to synchronize your local configuration files into a single, private GitHub Gist.
87

9-
dotfilesync is very easy to use as it stores your gist credentials into an encrypted Keychain, so you don't have to provide it each time.
8+
Unlike traditional dotfile managers that require complex Git repo management, `dfsync` treats your Gist as an atomic key-value store. It is lightweight, configuration-driven, and utilizes your system's native encrypted Keychain for credential storage.
109

11-
You are not limited to syncing only dotfiles. Although this tool is meant for you to sync local dotfiles, it can also be used to sync any file that can be synced with gist.
10+
---
1211

13-
This script is inspired by [this](https://hassansin.github.io/syncing-my-dotfiles-using-gist) post on how the author syncs zshrc to their gist.
12+
## 🚀 Key Features (Refactored v3.0)
1413

15-
Features
16-
--------
14+
### ⚡️ Atomic Batch Updates
15+
Version 3.0 introduces a massive performance leap. Instead of N-number of HTTP requests for N-files, `dfsync` now:
16+
1. Aggregates all selected local files into a single JSON object.
17+
2. Performs **ONE** single `PATCH` request to the GitHub API.
18+
3. Ensures atomicity: either all files update, or none do.
1719

18-
### Config driven
20+
### 🤖 Automation Friendly (`-y` flag)
21+
Full support for non-interactive environments (CRON jobs, LaunchAgents). Use the `-y` or `--yes` flag to bypass all confirmation prompts.
1922

20-
dotfilesync uses a JSON config using a hardcoded path - `${HOME}/.dotfilesync/config.json` - to retrieve metadata needed to sync local files to gist.
23+
### 🔐 Secure Keychain Integration
24+
Your GitHub Personal Access Token (PAT) is never stored in plain text.
25+
* **macOS:** Uses the native **macOS Keychain** (`security` utility).
26+
* **Linux:** Uses **Gnome Keyring** (`secret-tool`).
2127

22-
A sample config shape can look like this:
28+
---
2329

24-
```js
25-
{
26-
"githubUser": "snvishna",
27-
"gistId": "8f1bd18cf47f9d3efb8dc0a88a4e57aa",
28-
"dotFilePaths": [
29-
"~/.dotfilesync/config.json",
30-
"~/.zshrc",
31-
"~/.bash_profile",
32-
"~/.ssh/config",
33-
"~/.scripts/a.sh",
34-
"~/.scripts/b.sh"
35-
]
36-
}
37-
```
38-
39-
### Tools used as Keychain
40-
41-
This tool stores and manage your GitHub Personal Access Token within into an encrypted Keychain. This way your token is safe and encrypted by the Keychain, and you don't have to provide it each time you run the command to sync files.
42-
43-
For OS X based operating systems, the [OSX security](https://ss64.com/osx/security.html) command is used.
44-
45-
For Linux based operating systems, the [secret-tools](http://www.linuxfromscratch.org/blfs/view/svn/gnome/libsecret.html) command is used to interact with [GnomeKeyring](https://wiki.gnome.org/Projects/GnomeKeyring). For more info about keyrings used on Linux systems [read this article](https://rtfm.co.ua/en/what-is-linux-keyring-gnome-keyring-secret-service-and-d-bus/#Linux_keyring_vs_gnome-keyring).
46-
47-
### Sync multiple files into a single secret gist
48-
49-
All local files that are listed in the `config.json` file are synced into a single gist. As long as you have a valid `config.json` file in the `${HOME}/.dotfilesync` directory
50-
51-
### Auto-generate gist filenames
52-
53-
The file names in gist are automatically created. This script is opinionated on the file names being created. The characters "/" and "~" are replaced with periods (.). Duplicate consecutive periods in the name are also removed.
54-
55-
### Prompts before syncing each file
56-
57-
Every file listed in the `config.json`, whether being pushed to or pulled from gist, is synced only after a confirmation prompt. A sync is performed __only__ after you enter a "y" or a "yes" (case-insensitive). Any other input is ignored from sync.
58-
59-
### Creates a backup of the local file contents before overriding
60-
61-
During a fetch operation (syncing local files from gist), a sync is performed, only after creating a backup of the local file. The backup file name is auto-generated based on the current timestamp.
62-
63-
Prerequisites
64-
-------------
65-
66-
This script uses [jq](https://stedolan.github.io/jq/download/) to parse the `config.json` on the local filesystem.
67-
68-
## OS X
69-
You can run the following command on OS X, if you have [Homebrew](https://brew.sh/) installed:
70-
71-
brew install jq
72-
73-
## Linux
74-
You can install the required packages on a Debian based distro running the following command:
75-
76-
apt-get install jq libsecret-tools
77-
78-
Installation
79-
------------
80-
81-
Ensure the [prerequisite](#prerequisites) tools are setup. Installing dotfilesync is easy and a one-time effort:
82-
83-
1. Start a Zsh shell:
84-
85-
zsh
86-
87-
2. Fetch the script locally:
30+
## 🛠 Prerequisites
8831

89-
* With curl:
32+
Requires `jq` for JSON processing and `curl` for API interaction.
9033

91-
mkdir -p ${HOME}/.dotfilesync \
92-
&& curl -fsSL https://raw.githubusercontent.com/snvishna/dotfilesync/master/src/dfsync.sh \
93-
>| ${HOME}/.dotfilesync/dfsync.sh
94-
95-
* With wget:
96-
97-
mkdir -p ${HOME}/.dotfilesync \
98-
&& wget -nv -O - https://raw.githubusercontent.com/snvishna/dotfilesync/master/src/dfsync.sh \
99-
>| ${HOME}/.dotfilesync/dfsync.sh
100-
101-
3. Add an entry in zshrc:
102-
103-
You'll find the zshrc file in your $HOME directory. Open it with your favorite text editor and add the following alias in there:
104-
105-
alias dfsync='bash ${HOME}/.dotfilesync/dfsync.sh'
106-
107-
You can now use the `dfsync` command after you restart the terminal, or source your zsh config.
108-
109-
4. Create Person Access Token on GitHub:
110-
111-
You can create a new [person access tokens page](https://github.com/settings/tokens/new) for running the script on the command line. Follow [these instructions](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) on how to create one. Make sure you have the __gist__ scope selected to grant permission on this token.
112-
113-
Once you generate the personal access token, either copy it on your clipboard, or save it somewhere, since the script will need this to store within the Keychain, before syncing your files in gist.
114-
115-
![](./resources/generate_personal_access_token.gif)
116-
117-
5. Run setup:
118-
119-
Run the command `dfsync setup` from your terminal. It prompts for your GitHub username and the personal access token. Refer to the [Commands](#commands) section for more details on this command.
120-
121-
![](./resources/dfsync-setup.gif)
122-
123-
6. You're done! Enjoy dotfilesync!
124-
125-
Usage
126-
-----
127-
128-
* Update the `config.json` file with a list of local file paths that you'd like to sync with gist. You can now run `dfsync push` to upload these files in the gist.
129-
130-
![](./resources/dfsync-push.gif)
131-
132-
Commands
133-
--------
134-
135-
* __dfsync setup__
136-
137-
It is run only __once__ as part of the installation instructions. This command does the following:
138-
139-
* Prompts for your GitHub username and the personal access token. It then stores this information securely in the Keychain.
34+
### macOS
35+
```bash
36+
brew install jq
37+
```
14038

141-
* Creates a new secret gist in your account with the description - "Generated by dotfilesync utility".
39+
### Linux (Debian/Ubuntu)
40+
```bash
41+
sudo apt-get install jq libsecret-tools
42+
```
14243

143-
* It then creates a new `config.json` file, and auto-populates your Github username and the gistId fields.
44+
---
14445

145-
* Saves this file in the `${HOME}/.dotfilesync` directory.
46+
## 📦 Installation
14647

147-
* It also syncs this config file to this gist.
48+
1. **Fetch the script:**
49+
```bash
50+
mkdir -p ${HOME}/.dotfilesync \
51+
&& curl -fsSL https://raw.githubusercontent.com/snvishna/dotfilesync/master/src/dfsync.sh \
52+
>| ${HOME}/.dotfilesync/dfsync.sh \
53+
&& chmod +x ${HOME}/.dotfilesync/dfsync.sh
54+
```
14855

149-
> It is a good practice to leave the `config.json` file to sync with your gist, so you can recover or download these files with the `dfsync pull` command when you need them.
56+
2. **Add the alias to your shell config:**
57+
```bash
58+
alias dfsync='bash ${HOME}/.dotfilesync/dfsync.sh'
59+
```
15060

151-
* __dfsync push__
61+
3. **Run Setup:**
62+
```bash
63+
dfsync setup
64+
```
65+
66+
![](./resources/dfsync-setup.gif)
15267

153-
Use this command to push all local file contents into the secret gist defined in the `config.json` file. This command will prompt you before syncing each file. You can type "Y" or "y" for the file contents to be pushed. You can type any other character, or just hit enter to skip syncing this file. This command will work only after the `dfsync password save` is run once, so the personal access token is saved.
68+
---
15469

155-
* __dfsync pull__
70+
## 📖 Usage & Commands
15671

157-
Use this command to fetch all local file contents into the secret gist defined in the `config.json` file. This command will prompt you before syncing each file. You can type "Y" or "y" for the file contents to be fetched. You can type any other character, or just hit enter to skip syncing this file.
72+
### Pushing to Gist
73+
```bash
74+
# Interactive Mode (Prompt for each file, then batch upload)
75+
dfsync push
15876

159-
To be safe and not corrupt your local file contents, the command will initiate a backup of the local files (using a timestamp), and only then overwrites the contents of the file. Use can use these backup files to recover to the previous state.
77+
# Automated Mode (Bypass prompts, sync everything instantly)
78+
dfsync push -y
79+
```
16080

161-
This command will work only after the `dfsync password save` is run once, so the personal access token is saved.
81+
### Pulling from Gist
82+
```bash
83+
# Interactive Mode (Prompt before overwriting local files)
84+
dfsync pull
16285

163-
* __dfsync cleanup__
86+
# Automated Mode (Sync all files, creating local backups automatically)
87+
dfsync pull -y
88+
```
16489

165-
This command will do the following:
90+
### Command Reference
16691

167-
* Delete the saved GitHub gist credentials from the Keychain.
168-
* Delete `config.json` file from the `${HOME}/.dotfilesync` directory.
169-
* It does not automatically delete the saved gist from your GitHub account. Rather, it prints out the HTTP link to your gist, so you can choose to delete it.
170-
* It provides a link to the uninstall instructions in this README, so you can run the commands to delete the script and update the zsh config.
92+
| Command | Flag | Description |
93+
| :--- | :--- | :--- |
94+
| `setup` | N/A | Initial config, keychain storage, and Gist creation. |
95+
| `push` | `-y`, `--yes` | **Local → Gist.** Batch uploads local changes. |
96+
| `pull` | `-y`, `--yes` | **Gist → Local.** Syncs remote changes and creates backups. |
97+
| `cleanup` | N/A | Safely removes Keychain credentials and local config. |
17198

172-
Uninstall
173-
---------
99+
---
174100

175-
You can cleanup the script and all resources created by it, using the following instructions:
101+
## 🔍 Technical Implementation
176102

177-
* __Run__ `dfsync cleanup`
103+
### Filename Mapping
104+
`dfsync` maps nested local paths to a flat Gist structure by replacing `/` and `~` with periods.
105+
* `~/.zshrc``.zshrc`
106+
* `~/.config/wezterm/wezterm.lua``.config.wezterm.wezterm.lua`
178107

179-
You can run the command to 1) Delete the saved GitHub gist credentials from the Keychain 2) Delete `config.json` file from the `${HOME}/.dotfilesync` directory.
108+
### Resilience
109+
The script uses `set -o pipefail` and `set -o errexit`. If the GitHub API returns an error during the batch upload, the script terminates immediately to protect the integrity of your local configuration.
180110

181-
* __Delete the gist__
111+
### Stdin Handling
112+
To support interactive prompts inside loops, `dfsync` explicitly reads from `/dev/tty`. This ensures that `read` commands don't consume the file-list stream, allowing for stable `y/n` confirmation.
182113

183-
To be safe, the clean up command __does not automatically__ delete your gist from your account. You can choose to do this manually. The URL to your gist will be printed on the terminal when you run `dfsync cleanup`.
114+
---
184115

185-
* __Delete the local file__
116+
## 🧹 Uninstallation
186117

187-
You can now delete the dotfilesync directory from your machine. Run the following command: `rm -rf ${HOME}/.dotfilesync`
118+
1. **Run Cleanup:** `dfsync cleanup`
119+
2. **Delete Gist:** Delete the Gist manually via the URL provided by the cleanup command.
120+
3. **Remove Files:** `rm -rf ${HOME}/.dotfilesync`
188121

189-
* __Remove alias from zsh config__
122+
---
190123

191-
You should now remove the `dfsync` alias from the zsh config. Otherwise this command will fail on the missing file path.
124+
*Inspired by [Hassan Sani's post](https://hassansin.github.io/syncing-my-dotfiles-using-gist).*

0 commit comments

Comments
 (0)