- TypeScript 100%
|
|
||
|---|---|---|
| .github/workflows | ||
| src | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| biome.json | ||
| CLAUDE.md | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.build.json | ||
| tsconfig.json | ||
| vitest.config.ts | ||
devsync
devsync is a cross-platform CLI for managing the configuration files in your home directory with git and syncing them across multiple machines.
Instead of treating the repository as the source of truth, devsync treats your actual local config as the truth. You choose files and directories under HOME, devsync mirrors them into a git-backed sync repository, and later restores that repository onto another machine when you need it.
1. Purpose and how it differs
Most dotfiles tools start from the repository and ask you to shape your local machine around it.
devsync takes the opposite approach:
- Your real config under
HOMEis the source of truth. - The git repository is a sync artifact, not the primary authoring location.
pushcaptures your current machine state into the repository.pullapplies the repository back onto another machine.
That makes devsync a good fit when you want to:
- manage existing dotfiles and app configs without reorganizing your home directory,
- keep machine-specific config workflows intact,
- sync plain files and encrypted secrets together,
- use normal git remotes as the transport layer between PCs.
Core capabilities:
- track files and directories under your home directory,
- store synced artifacts in
~/.config/devsync/sync, - mark paths as
normal,secret, orignore, - encrypt secret artifacts with
age, - preview both directions with
status,push --dry-run, andpull --dry-run.
2. Installation
Requirements:
- Node.js 24+
- npm
- git
Install globally:
npm install -g @tinyrack/devsync
devsync --help
Run without installing globally:
npx @tinyrack/devsync --help
Run from this checkout:
npm install
npm run start -- --help
The published package name is @tinyrack/devsync, and the installed command is devsync.
3. Quickstart
Initialize a local sync repository:
devsync init
Track a few configs:
devsync add ~/.gitconfig
devsync add ~/.zshrc
devsync add ~/.config/mytool --secret
Review what would be captured:
devsync status
devsync push --dry-run
Write your current local config into the sync repository:
devsync push
Open the sync repository and publish it with git:
devsync cd
git status
git add .
git commit -m "Update synced config"
git push
On another machine, clone and restore from the same repo:
devsync init https://example.com/my-sync-repo.git
devsync status
devsync pull --dry-run
devsync pull
Notes:
pushupdates the sync repository contents only; it does not create git commits or push to a remote.pullupdates local files only.- Secret paths are stored encrypted in the repository and require the configured
ageidentity to decrypt on restore.
4. Detailed docs
How tracking works
- You add files or directories that live under your home directory.
devsyncmirrors them into~/.config/devsync/sync/default/<repoPath>for the default profile, or~/.config/devsync/sync/<profile>/<repoPath>for a named profile.- Plain artifacts are stored as-is.
- Secret artifacts are stored with the
.devsync.secretsuffix.
Storage layout:
- Sync repo:
~/.config/devsync/sync - Default profile artifacts:
~/.config/devsync/sync/default/<repoPath> - Named profile artifacts:
~/.config/devsync/sync/<profile>/<repoPath> - Default age identity:
$XDG_CONFIG_HOME/devsync/age/keys.txt
Sync modes
Each tracked path can use one of three modes:
normal: store and restore plain contentsecret: encrypt before storing in the repoignore: skip during push and pull
You can apply modes to tracked roots or nested paths inside tracked directories.
Profile-specific behavior inherits the tracked root mode and only changes nested paths inside tracked directories.
Examples:
devsync set secret ~/.config/mytool/token.json
devsync set ignore ~/.config/mytool/cache --recursive
devsync set normal ~/.config/mytool/public.json
devsync set secret ~/.config/mytool/token.json --profile work
Profile-specific overrides
- Track the root once without
--profile. - Use
devsync set --profile <name>only for child paths inside tracked directories. - Profile-specific rules inherit the parent root mode and only override nested paths.
- Named profile artifacts are stored under
<profile>/<repoPath>. defaultis reserved for the base layout and cannot be used as a named profile.- Standalone profiled roots and profiled file entries are not supported.
Example config.json:
{
"version": 1,
"age": {
"identityFile": "$XDG_CONFIG_HOME/devsync/age/keys.txt",
"recipients": ["age1example..."]
},
"entries": [
{
"kind": "directory",
"localPath": "~/.config/mytool",
"mode": "normal",
"overrides": {
"cache/": "ignore"
},
"profiles": {
"work": {
"overrides": {
"token.json": "secret"
}
}
},
"repoPath": ".config/mytool"
}
]
}
Common workflow
Check what changed:
devsync status
Capture local config into the repository:
devsync push
Restore repository state onto the machine:
devsync pull
Use dry runs when you want to review first:
devsync push --dry-run
devsync pull --dry-run
Command reference
init
Create or connect the local sync repository.
devsync init
devsync init https://example.com/my-sync-repo.git
devsync init --identity "$XDG_CONFIG_HOME/devsync/age/keys.txt" --recipient age1...
add
Track a file or directory under your home directory.
devsync add ~/.gitconfig
devsync add ~/.config/mytool
devsync add ~/.config/mytool --secret
add --profile is not supported for tracked roots. Track the root first, then use set --profile for child overrides.
set
Change the sync mode for a tracked root, child path, or subtree.
devsync set secret ~/.config/mytool/token.json
devsync set ignore ~/.config/mytool/cache --recursive
devsync set secret ~/.config/mytool/token.json --profile work
With --profile, the target must be a child path inside a tracked directory, and default cannot be used as the profile name. Profile-specific root mode changes are not supported.
forget
Remove a tracked path or nested override from config.
devsync forget ~/.gitconfig
devsync forget ~/.config/mytool
devsync forget .config/mytool/token.json --profile work
list
Show tracked entries, default modes, root overrides, and profile-specific child overrides.
devsync list
status
Preview planned push and pull changes.
devsync status
doctor
Validate repo state, config, tracked paths, and secret setup.
devsync doctor
push
Write local state into the sync repository.
devsync push
devsync push --dry-run
pull
Apply repository state back onto the local machine.
devsync pull
devsync pull --dry-run
cd
Open the sync repository in your shell, or print its path.
devsync cd
devsync cd --print
For flag-level details, use built-in help:
devsync --help
devsync init --help
devsync add --help
devsync set --help
Development
Run the CLI locally:
npm run start -- --help
Watch mode:
npm run dev
Validation:
npm run typecheck
biome check .
npm run test
Or run everything at once:
npm run check
Release
- CI runs
npm run checkon every push and pull request. - npm publishing runs automatically for Git tags matching
v*.*.*. - The release workflow expects the pushed tag to match
package.jsonversion.
Typical release flow:
npm version patch
git push --follow-tags