InSync is a file synchronization tool for a local network, built around a three-snapshot model: base, local, and remote. The project uses three-way merge to compare states, detect conflicts, and apply changes in a predictable order.
InSync is designed for synchronizing file trees over the network in a REPL format. Nodes are discovered through mDNS, data exchange is handled via gRPC, and the connection is protected by certificate-based mutual authentication.
- Three-way synchronization using the base / local / remote scheme
- Bidirectional sync
- Conflict detection when states diverge
- Deterministic change merging
- A contract-based model for paths and tree structure
- Strict normalized path representation
- An extensible command and transport architecture
InSync is built around the concept of three snapshots:
- Base — the previous synchronized state
- Local — the current state on the local node
- Remote — the current state on the remote node
REPL layer
The user interacts with the application through an interactive console and enters commands as needed.
Transport layer
gRPC is used for data exchange between nodes.
Discovery layer
mDNS is used to discover nodes in the local network.
Security layer
The connection is protected by mutual authentication: both client and server present certificates.
Hashing layer
BLAKE3 is used for computing hashes.
The contract-based model makes it possible to traverse the tree in lexicographic order and skip unchanged subtrees. This reduces unnecessary work and makes the system’s behavior more predictable.
Contract first
All paths must be normalized, and the tree structure must be predefined and validated. This simplifies state handling and makes the synchronization algorithm deterministic.
Connection security
Node interaction uses certificate-based mutual authentication. This reduces the risk of connecting to an unverified node.
Determinism
The same input data must always produce the same result.
Simplicity and lightweight design over universality
Some complex cases are intentionally not supported, including symlinks and virtual file systems.
The following are required to build and run the project:
- Go
- certificate support for both client and server nodes
- the ability to run nodes in a local network
- Windows or another environment compatible with the certificate generation scripts provided in the repository
git clone https://github.com/1ight181/InSync
cd InSync
go build -o insync ./cmd/insyncIf you are using the Windows certificate generation script, it is convenient to run it separately from the certsgen directory.
Before starting the nodes, you need to prepare a CA certificate and then issue and sign certificates for the server and client.
If the repository uses the ready-made batch scripts from certsgen, first create the CA, then generate the node certificates based on it.
Procedure:
- Generate the CA certificate
- Generate the server certificate
- Generate the client certificate
- Make sure both nodes use a consistent certificate set
insync
After startup, the user enters interactive mode and can execute commands sequentially.
insync> nodes
This command prints the list of available nodes in the local network.
insync> connect nodeNameExample
After connection, state exchange and synchronization control become available.
A root directory is created on each node, and its contents will be synchronized.
On the local side:
insync> add-root exampleRoot "/path/to/example-root"
On the remote side:
insync> add-root exampleRoot "/path/to/remote-root"
After adding a root, you can initialize the base state:
insync> init exampleRoot
insync> dry-run exampleRoot
This command shows the list of planned changes and possible conflicts without applying any modifications.
insync> sync exampleRoot
This command applies all required changes sequentially. If conflicts are found, they are shown to the user for resolution.
insync> set-alias nodeNameExample aliasExample
The alias is displayed next to the node name and makes working in the REPL easier.
nodes— show available nodesconnect <nodeName>— connect to a nodecurrent-node— show the currently connected nodeadd-root <rootName> <path>— add a root directory for synchronizationremove-root <rootName> [--should_delete_snapshots]— remove a root directory from synchronizationinit <rootName>— create a base snapshot for selected rootdry-run <rootName>— show the synchronization plan without applying itsync <rootName> [--should-use-cache]— apply changesset-alias <nodeName> <alias>— assign an alias to a noderemove-alias <alias>— remove an assigned alias
- Symlinks are not supported
- Virtual file systems are not supported
- Create a custom gRPC resolver for mDNS
- Switch to a CGO-free sqlite driver
- Migrate from zeroconf to mdns
- Add support for selecting a default conflict resolution policy
- Increase the level of parallelism
- Raise test coverage to 90%
- Add daemon mode
- Move to Bubble Tea
- Move to rsync algorithms
├── certsgen
├── cmd
├── config
├── internal
├── proto
├── go.mod
└── go.sum
MIT License - Copyright (c) 2026 1ight181
Found a bug? - GitHub Issues
Email: danil.odinzov181@gmail.com