This project implements a server-coordinated directory synchronization system.
Detailed design decisions are documented in system_design.md.
- Go >= 1.22
- Rust >= 1.75
- Node.js >= 22.21.x Optional build tool:
- Bun: required only for Node single-executable builds (see Node client build notes below)
cd server-go
go run ./cmd/server --listen :9000 --keys ../keys.txtKeys file (keys.txt) is one API key per line. --keys is required unless you pass --insecure-allow-any-key.
Use --help to see all options and examples.
Example: example.keys.txt (one key per line).
cd client-rust
cargo run -- --server 127.0.0.1:9000 --key <api_key> --dir ./sync --poll 2Use --help to see all options and examples.
cd client-node
node index.ts --server 127.0.0.1:9000 --key <api_key> --dir ./sync --poll 2Use --help to see all options and examples.
Root Makefile:
make build-all
make test-unit
make test-e2e
make test-all
make cleanPer-project Makefiles:
cd server-go && make build
cd server-go && make clean
cd client-rust && make test
cd client-rust && make clean
cd client-node && make lint
cd client-node && make cleanRoot Taskfile (go-task):
task build:all
task build:node
task test:unit
task test:all
task typecheck:node
task cleanGo server:
cd server-go
make build-linux
make build-windowsRust client:
cd client-rust
make build-linux
make build-windowsNode client (bun executable):
cd client-node
make build-linux
make build-windowsNotes:
- The Node client can be built into a single executable via bun. Bun is only required for these build targets; running the client with Node.js does not require bun(https://bun.com/).
- The bun-built binary name is
directory_sync_client(Linux) /directory_sync_client.exe(Windows). - Node.js has a newer single-executable app flow (SEA) in v25.6.0+, but this project standardizes on bun for repeatable builds without extra tooling.
Per-project docs:
server-go/README.mdclient-rust/README.mdclient-node/README.md
Reconnect behavior: not implemented (clients exit on disconnect). See per-project docs.
Auth failure: clients log auth failed: invalid api_key and exit.
Concurrency: server uses per-connection reader/writer loops and buffered send queues (64 frames) to handle 32+ clients; no explicit hard limit.
Build:
docker build -t directory-sync-server -f server-go/Dockerfile .Run (daemon):
docker run -d --name directory-sync-server -p 9000:9000 -v $(pwd)/keys.txt:/app/keys.txt directory-sync-server --listen :9000 --keys /app/keys.txtSee:
client-rust/README.mdclient-node/README.md
- Start server.
- Start Rust client with
--dir ./sync-rust. - Start Node client with
--dir ./sync-node. - Create a file in
./sync-rustand confirm it appears in./sync-node. - Create a file in
./sync-nodeand confirm it appears in./sync-rust. - Modify the same path in both directories; the server picks by
mtime, tie-breaker byclient_id. - Delete a file on one side; the other side should not delete it.
Go:
cd server-go
go test ./internal/proto
go test ./internal/coordinator/...Rust:
cd client-rust
cargo testNode:
cd client-node
node --testMake (root):
make test-unit
make test-e2e
make test-allTaskfile (root):
task test:unit
task test:e2e
task test:allE2E (spawns server + clients):
./scripts/e2e_smoke.shAll tests (unit + e2e):
./scripts/run_all_tests.sh- Deletions do not propagate, by design.
- Clients use polling and will send deltas for added/modified files.
- Transfers are mediated by the server; binary chunks are forwarded to downloaders.