A bidirectional file synchronization system using Automerge CRDTs for conflict-free collaborative editing.
Pushwork enables real-time collaboration on directories and files using Conflict-free Replicated Data Types (CRDTs). Unlike traditional sync tools that require manual conflict resolution, Pushwork automatically merges changes from multiple users while preserving everyone's work.
- 🔄 Bidirectional Sync: Keep local directories synchronized with remote Automerge repositories
- 🚫 Conflict-Free: Automatic conflict resolution using Automerge CRDTs - no merge conflicts ever
- 📱 Real-time Collaboration: Multiple users can edit the same files simultaneously
- 🧠 Intelligent Move Detection: Detects file renames and moves based on content similarity
- ⚡ Incremental Sync: Only synchronizes changed files for maximum efficiency
- 🌐 Network Resilient: Works offline and gracefully handles network interruptions
- 🖥️ Cross-Platform: Runs on Windows, macOS, and Linux
- 🛠️ Rich CLI: Full-featured command-line interface with comprehensive tooling
Currently, install from source:
pnpm install
pnpm run build
pnpm link --global
Note: you
- Initialize a new repository:
pushwork init ./my-project
- Clone an existing repository:
pushwork clone <automerge-url> ./cloned-project
- Sync changes:
pushwork sync
- Check status:
pushwork status
Initialize sync in a directory, creating a new Automerge repository.
# Initialize with default sync server
pushwork init ./my-project
# Initialize with custom sync server
pushwork init ./my-project \
--sync-server ws://localhost:3030 \
--sync-server-storage-id your-storage-id
Options:
--sync-server <url>
: Custom sync server URL (requires storage-id)--sync-server-storage-id <id>
: Custom sync server storage ID (requires server)
Clone an existing synced directory from an Automerge URL.
# Clone from default sync server
pushwork clone automerge:abc123... ./cloned-project
# Clone with custom sync server
pushwork clone automerge:abc123... ./cloned-project \
--sync-server ws://localhost:3030 \
--sync-server-storage-id your-storage-id
# Force overwrite existing directory
pushwork clone automerge:abc123... ./existing-dir --force
Options:
--force
: Overwrite existing directory--sync-server <url>
: Custom sync server URL--sync-server-storage-id <id>
: Custom sync server storage ID
Run bidirectional synchronization between local files and remote repository.
# Preview changes without applying them
pushwork sync --dry-run
# Apply all changes
pushwork sync
# Verbose output
pushwork sync --verbose
Options:
--dry-run
: Preview changes without applying them--verbose
: Show detailed progress information
Show differences between local and remote state.
# Show all changes
pushwork diff
# Show changes for specific path
pushwork diff src/
# Show only changed file names
pushwork diff --name-only
# Use external diff tool
pushwork diff --tool meld
Options:
--tool <tool>
: Use external diff tool (meld, vimdiff, etc.)--name-only
: Show only changed file names
Show current sync status and repository information.
pushwork status
Show sync history for the repository or specific files.
# Show repository history
pushwork log
# Compact one-line format
pushwork log --oneline
# History for specific path
pushwork log src/important-file.txt
Options:
--oneline
: Compact one-line per sync format--since <date>
: Show syncs since date--limit <n>
: Limit number of syncs shown (default: 10)
Show the Automerge root URL for sharing with others.
# Get URL for current directory
pushwork url
# Get URL for specific directory
pushwork url ./my-project
Commit local changes without network sync (useful for offline work).
# Commit all changes
pushwork commit
# Preview what would be committed
pushwork commit --dry-run
# Commit specific directory
pushwork commit ./src
Options:
--dry-run
: Show what would be committed without applying changes
Restore directory to state from previous sync (not yet implemented).
# Restore entire directory
pushwork checkout sync-123
# Force checkout even with uncommitted changes
pushwork checkout sync-123 --force
Pushwork uses sensible defaults:
- Sync Server:
wss://sync3.automerge.org
- Storage ID:
3760df37-a4c6-4f66-9ecd-732039a9385d
- Excluded Patterns:
.git
,node_modules
,*.tmp
,.pushwork
- Large File Threshold: 100MB
- Move Detection Threshold: 80% similarity
Configuration is stored in .pushwork/config.json
:
{
"sync_server": "wss://sync3.automerge.org",
"sync_server_storage_id": "3760df37-a4c6-4f66-9ecd-732039a9385d",
"sync_enabled": true,
"defaults": {
"exclude_patterns": [".git", "node_modules", "*.tmp", ".pushwork"],
"large_file_threshold": "100MB"
},
"diff": {
"show_binary": false
},
"sync": {
"move_detection_threshold": 0.8,
"prompt_threshold": 0.5,
"auto_sync": false,
"parallel_operations": 4
}
}
Pushwork uses Automerge CRDTs to automatically resolve conflicts:
- Text Files: Character-level merging preserves all changes
- Binary Files: Last-writer-wins with automatic convergence
- Directory Structure: Additive merging supports simultaneous file creation
- File Moves: Intelligent detection prevents data loss during renames
- Push Phase: Apply local changes to Automerge documents
- Pull Phase: Apply remote changes to local filesystem
- Convergence: All repositories eventually reach identical state
- Content-Based: Uses Automerge document heads, not timestamps
- Efficient: Only processes actually changed files
- Reliable: Works across time zones and file system differences
- Resumable: Interrupted syncs can be safely resumed
- Compares content similarity between deleted and created files
- Auto-apply: Moves with >80% similarity (configurable)
- User prompt: Moves with 50-80% similarity (configurable)
- Ignore: Moves with <50% similarity
File Document:
{
"@patchwork": { type: "file" };
name: string;
extension: string;
mimeType: string;
content: Text | Uint8Array;
}
Directory Document:
{
"@patchwork": { type: "folder" };
docs: Array<{
name: string;
type: "file" | "folder";
url: AutomergeUrl;
}>;
}
- Snapshot File:
.pushwork/snapshot.json
tracks sync state - Path Mapping: Links filesystem paths to Automerge document URLs
- Head Tracking: Enables efficient change detection
- Configuration:
.pushwork/config.json
stores sync settings
- Sync Server: Handles real-time synchronization between clients
- Storage ID: Isolates different collaboration groups
- WebSocket Connection: Provides real-time updates
- Graceful Degradation: Works offline with manual sync
# Build the project
npm run build
# Run unit tests
npm test
# Run integration tests
./test/run-tests.sh
# Test conflict resolution
./test/integration/conflict-resolution-test.sh
# Test clone functionality
./test/integration/clone-test.sh
- Unit Tests: Core functionality and utilities
- Integration Tests: End-to-end sync scenarios
- Conflict Resolution: CRDT merging behavior
- Clone Operations: Repository sharing workflows
- Node.js 18+
- TypeScript 5+
- pnpm (recommended) or npm
git clone <repository-url>
cd pushwork
npm install
npm run build
# Development mode
npm run dev
# Watch mode for testing
npm run test:watch
src/
├── cli/ # Command-line interface
├── core/ # Core sync engine
├── config/ # Configuration management
├── types/ # TypeScript type definitions
└── utils/ # Shared utilities
test/
├── unit/ # Unit tests
└── integration/ # Integration tests
# Alice initializes a project
alice$ pushwork init ./shared-docs
alice$ echo "Hello World" > shared-docs/readme.txt
alice$ pushwork sync
alice$ pushwork url
# automerge:2V4w7zv8zkJYJxJsKaYhZ5NPjxA1
# Bob clones Alice's project
bob$ pushwork clone automerge:2V4w7zv8zkJYJxJsKaYhZ5NPjxA1 ./bobs-copy
# Both edit the same file simultaneously
alice$ echo "Alice's changes" >> shared-docs/readme.txt
bob$ echo "Bob's changes" >> bobs-copy/readme.txt
# Both sync - no conflicts!
alice$ pushwork sync
bob$ pushwork sync
alice$ pushwork sync # Gets Bob's changes
# Final result contains both changes merged automatically
alice$ cat shared-docs/readme.txt
Hello World
Alice's changes
Bob's changes
WebSocket Connection Errors: Usually safe to ignore during shutdown
"Directory not initialized": Run pushwork init .
first
Network Sync Timeout: Check internet connection and sync server status
File Permission Errors: Ensure write access to target directory
# Enable verbose logging
pushwork sync --verbose
# Preview changes without applying
pushwork sync --dry-run
# Check repository status
pushwork status
MIT License - see LICENSE file for details.
- Issues: Report bugs and request features
- Documentation: Additional guides and tutorials
- Automerge: Learn more about CRDT technology
🚀 Ready to collaborate conflict-free? Get started with pushwork init
!