sourcewatch
A file synchronization tool that watches a Windows source directory and syncs changes to a Docker container via Unix socket IPC. Respects .gitignore rules.
Architecture
Windows Host Docker Container
┌─────────────────────┐ ┌─────────────────────────┐
│ sourcewatch.exe │ TCP │ sourcewatch (linux) │
│ watches C:\src │◄────────────►│ - receives manifest │
│ ReadDirectory │ connect │ - syncs changed files │
│ ChangesW │ :5151 │ - listens for events │
└─────────────────────┘ └─────────────────────────┘
- Container starts and listens on TCP port 5151
- Windows binary connects to container, scans source directory (fast native NTFS), sends file metadata
- Container compares with local state, copies only changed files
- Windows binary watches for changes, sends events over TCP
- Container receives events and syncs in real-time
Building
Windows binary (sourcewatch.exe)
# From Windows (Git Bash, PowerShell, or cmd)
go build -o sourcewatch.exe .
# Cross-compile from Linux/Mac
GOOS=windows GOARCH=amd64 go build -o sourcewatch.exe .
Requires Go 1.24+ and github.com/fsnotify/fsnotify (automatically downloaded).
Docker/Podman image (linux container)
# Build image
docker build -t sourcewatch .
# Or with Podman
podman build -t sourcewatch .
Usage
Step 1: Build the Windows binary
GOOS=windows GOARCH=amd64 go build -o sourcewatch.exe .
Step 2: Start the container
docker run -d -p 5151:5151 \
-v C:\myproject:/host:ro \
-v project-data:/data \
sourcewatch
Or with Podman:
podman run -d -p 5151:5151 \
-v C:\myproject:/host:ro \
-v project-data:/data \
sourcewatch
Step 3: Start the Windows watcher
# PowerShell
.\sourcewatch.exe -dir C:\myproject -connect localhost:5151
# Git Bash
./sourcewatch.exe -dir /c/myproject -connect localhost:5151
Standalone mode (no Windows watcher)
If you don't need real-time watching, run with -listen "":
docker run -v /path/to/source:/host:ro -v data:/data sourcewatch -listen ""
Flags
Windows binary (sourcewatch.exe)
-dir string Source directory to watch (required)
-connect string TCP address of the container (default "localhost:5151")
-log-level string Log level: debug, info, warn, error, none (default "info")
-verbose Enable verbose logging (shorthand for -log-level debug)
Container (sourcewatch)
-host string Host source directory (default "/host")
-data string Data destination directory (default "/data")
-listen string TCP address to listen on (default ":5151")
-verbose Enable verbose logging (shorthand for -log-level debug)
-log-level string Log level: debug, info, warn, error, none (default "info")
-dry-run Preview what would be synced without copying
Protocol
Communication uses newline-delimited JSON over TCP:
{"type":"manifest","files":{"path":{"size":1234,"modtime":"2024-01-01T00:00:00Z","mode":"0644"}}}
{"type":"manifest_done"}
{"type":"event_create","path":"new/file.go"}
{"type":"event_write","path":"modified/file.go"}
{"type":"event_remove","path":"deleted/file.go"}
.gitignore support
- Full gitignore spec:
*,**,[],!negation - Nested
.gitignorefiles (child patterns override parents) - Patterns scoped to their directory
.gitdirectory always skipped
Example .gitignore:
*.log
build/
!important.log
Limitations
- One-way sync only (
/host→/data) /hostmust be read-only?single-character wildcard not supported (go-gitignore limitation)- Windows binary requires Go 1.21+ to build
License
MIT
