| title | Foreign Folder Watcher |
|---|---|
| stage | development |
An Obsidian plugin for automatic synchronization of files between external folders and your vault.
- Real-time Watching: Monitors external folders for file changes using chokidar
- Bidirectional Sync: Sync in both directions (source → vault, vault → source, or both)
- Bulk Reconcile: Full synchronization on startup or on-demand
- Incremental Reconcile: Only sync files changed since last reconcile (much faster for large folders)
- Cloud Sync Compatibility: Special handling for OneDrive, Dropbox & Co. (stability checks, temp file filtering)
- Exclusion Patterns: Exclude files and folders using glob patterns
- Conflict Resolution: Multiple strategies (overwrite, rename, skip, keep newer)
- Dashboard: Visual interface for monitoring and control with health indicators
- Export / Import Mappings: Share your folder mapping configuration as JSON — others can import it to set up their vault
- Performance: Parallel processing, intelligent caching, skip-unchanged optimization
- Download
main.js,styles.css, andmanifest.jsonfrom the latest release - Create the folder
.obsidian/plugins/foreign-folder-watcher/in your vault - Copy the downloaded files into this folder
- Enable the plugin in Obsidian under Settings → Community Plugins
- Open Settings → Foreign Folder Watcher
- Click "Add Folder Mapping"
- Select a Source Folder (external folder, e.g.,
C:\Users\Name\OneDrive\Notes) - Select a Target Folder (folder in vault, e.g.,
imported/onedrive) - Click Save
The plugin now monitors the external folder and automatically copies new/changed files to your vault.
Each mapping defines a source-target relationship:
| Setting | Description |
|---|---|
| Description | A name for this mapping (e.g., "OneDrive Notes") |
| Source Folder | Absolute path to the external folder (e.g., C:\Users\Name\OneDrive\Notes) |
| Target Folder | Relative path in vault (e.g., imported/onedrive) |
| Watch Subfolders | Include subdirectories |
| File Extensions | Filter for file types (empty = all) |
| Exclude Patterns | Patterns to exclude (see below) |
| Sync Direction | Direction of synchronization |
| Conflict Resolution | How to handle existing files |
| Reconcile on Start | Synchronize when plugin starts |
| Enabled | Enable/disable this mapping |
The plugin supports three sync modes:
| Mode | Description | Use Case |
|---|---|---|
| Source → Vault | Import from external folder to vault only | Consume files (default) |
| Vault → Source | Export from vault to external folder only | Publish files |
| Bidirectional | Sync in both directions | Full synchronization |
Note: Deletion sync is opt-in. Set Deletion Handling to "Trash" per mapping to propagate deletes (files go to system trash or
.sync-trash/).
When a file exists in both source and target:
| Strategy | Behavior |
|---|---|
| Keep Newer | The newer file (by modification date) wins |
| Overwrite | Source file always overwrites target |
| Rename | Conflict files are renamed (e.g., file (conflict 2025-02-07).md) |
| Skip | Existing files are never overwritten |
With bidirectional sync, you can set a separate conflict strategy for each direction.
Under "Exclude Patterns" you can specify files and folders to exclude from sync:
node_modules
*.log
temp/**
.git
build/*
Supported Wildcards:
| Pattern | Meaning |
|---|---|
* |
Any characters (except /) |
** |
Any characters including path separators (recursive) |
? |
Single character |
Examples:
| Pattern | Excluded |
|---|---|
node_modules |
All node_modules folders at any depth |
*.log |
All .log files |
temp/** |
Everything in the temp folder |
*.tmp |
All temporary files |
build/* |
Direct contents of build, but not subfolders |
.git |
Git directory |
For OneDrive, Dropbox, and similar services:
| Setting | Description | Default |
|---|---|---|
| Ignore OneDrive Temp Files | Ignore temporary files (~$, .tmp, etc.) |
On |
| Verify File Stability | Wait until file is fully synchronized | On |
| Stability Checks | Number of stability checks | 3 |
| Stability Interval | Time between checks (ms) | 500 |
| Use Polling | Use polling instead of native file watching | Off |
| Polling Interval | Polling interval (ms) | 300 |
Recommended for cloud folders:
- Enable
Use Pollingwith 300-1000ms interval - Enable
Verify File Stability - Enable
Ignore OneDrive Temp Files
| Setting | Description | Default |
|---|---|---|
| Sync on Start | Global setting for reconcile on startup | On |
| Incremental Reconcile | Only sync files changed since last reconcile | On |
| Parallelism | Number of parallel workers (1-64) | 8 |
| Fast Skip Unchanged | Skip unchanged files (size + mtime) | On |
| Progress Throttle | UI update interval (ms) | 250 |
| Notify on Mapping Done | Show notification after each mapping completes | On |
| Show Notifications | Display plugin notifications (sync, error, status notices) | On |
Available via Command Palette (Ctrl/Cmd + P):
| Command | Description |
|---|---|
| File Watcher: Open Dashboard | Open the dashboard |
| File Watcher: Restart all watchers | Restart all watchers |
| File Watcher: Export folder mappings | Export all mappings to a JSON file |
| File Watcher: Import folder mappings | Import mappings from a JSON file |
Open the dashboard via:
- Command palette: "File Watcher: Open Dashboard"
- Click on status bar element
The dashboard shows:
- Overview: Global statistics, reconcile status, recent activity
- Watchers: Status and health of each mapping with start/stop/reconcile controls
- Logs: Filtered logs with search
Each watcher displays a health status:
- Healthy (green): Running with recent activity
- Idle (gray): Running but no activity for 5+ minutes
- Warning (yellow): Queue backpressure (dropped jobs or high queue)
- Error (red): Error state
The status bar shows:
- Number of active watchers
- Processed/Skipped/Error counters
- Reconcile progress (when active)
Click on the status bar to open the dashboard.
Description: OneDrive Notes
Source: C:\Users\Name\OneDrive\Notes
Target: imported/onedrive
Sync Direction: Source → Vault
File Extensions: .md, .txt
Conflict: Keep Newer
Watch Subfolders: Yes
Use Polling: Yes
Description: Publish to Dropbox
Source: C:\Users\Name\Dropbox\Public\Notes
Target: published
Sync Direction: Vault → Source
File Extensions: .md
Conflict: Overwrite
Description: Work Notes (Bidirectional)
Source: C:\Users\Name\OneDrive\Work
Target: work
Sync Direction: Bidirectional
Conflict (→Vault): Keep Newer
Conflict (→Source): Keep Newer
Exclude: node_modules, .git, *.log
You can share your folder mapping configuration with others so they can set up their vault with the same sync structure.
- Open Settings → Foreign Folder Watcher
- Click "Export" (or use Command Palette: "File Watcher: Export folder mappings")
- Choose a save location — can be anywhere on your machine, including outside the vault
- A
.jsonfile is saved with all your mappings
What gets exported:
- Target folders, descriptions, sync direction, conflict resolution, file extensions, exclude patterns, and all other sync settings
- Source folders are cleared (paths are machine-specific and meaningless to others)
- All mappings are set to disabled in the export
- Open Settings → Foreign Folder Watcher
- Click "Import" (or use Command Palette: "File Watcher: Import folder mappings")
- Select a
.jsonmapping file — can be from anywhere on your machine - Imported mappings appear in your settings, disabled by default
After importing:
- Configure the Source Folder for each imported mapping (point to your local folders)
- Enable the mappings you want to activate
- Mappings with overlapping target folders are skipped automatically
{
"version": 1,
"exportedAt": "2026-02-10T12:00:00.000Z",
"pluginVersion": "1.0.0",
"mappings": [
{
"targetFolder": "imported/onedrive",
"description": "OneDrive Notes",
"sourceFolder": "",
"enabled": false,
"syncDirection": "source-only",
"fileExtensions": [".md", ".txt"],
"conflictResolution": "keepNewer",
...
}
]
}- Check if the mapping is enabled
- Check if the file extension is allowed
- Check the Exclude Patterns
- Open the Sync Logs for details
The plugin has loop detection with a 5-second cooldown. With very slow cloud services, you may still see notifications - but the file will not be synced again.
- Reduce the number of monitored folders
- Enable
Use Pollingwith a higher interval (1000+ ms) - Use
Exclude Patternsto exclude large folders
- Check the Conflict Resolution setting
- With
Skip, existing files are never overwritten - Open the Sync Logs to see which files were skipped
- Open the developer console (
Ctrl/Cmd + Shift + I) - Look for error messages
- Try Restart all watchers command
The following file types are automatically ignored when "Ignore OneDrive Temp Files" is enabled:
~$document.docx(Office lock files)*.tmp,*.temp*.partial,*.crdownload*.swp(Vim swap files)thumbs.db,.DS_Store,desktop.ini
src/
├── main.ts # Main plugin class
├── types.ts # Core type definitions
├── utils.ts # Utility functions (glob matching, etc.)
├── services/
│ ├── FileSyncService.ts # Core synchronization logic
│ ├── ReconcileService.ts # Bulk reconcile orchestration
│ ├── SyncStateService.ts # Sync state persistence (incremental reconcile)
│ ├── StatsService.ts # Statistics tracking
│ ├── StatusBarService.ts # Status bar display
│ ├── LogService.ts # Logging with subscriptions
│ ├── NoticeService.ts # User notifications
│ ├── FolderPickerService.ts # Native folder/file picker (Electron)
│ ├── MappingExportService.ts # Export/import mapping configurations
│ └── AsyncMutex.ts # Thread safety (locks)
├── watcher/
│ ├── WatcherManager.ts # Watcher lifecycle & health tracking
│ ├── MappingWatcher.ts # Source → Vault watcher (external folder)
│ └── VaultWatcher.ts # Vault → Source watcher (vault folder)
├── modals/
│ ├── DashboardModal.ts # Main dashboard UI
│ ├── FolderMappingModal.ts # Mapping editor
│ └── ConfirmModal.ts # Confirmation dialogs
├── settings/
│ ├── FileWatcherSettingTab.ts # Settings tab
│ └── types.ts # Settings types
└── interfaces/
└── IPluginContext.ts # Service interfaces
- Node.js >= 16
- npm
npm installnpm run dev # Watch mode
npm run build # Production build
npm test # Run tests
npm run docs # Generate TypeDocThe project uses Vitest for unit tests:
npm test # Run tests once
npm run test:watch # Watch mode
npm run test:ui # Vitest UI
npm run test:coverage # With coverage reportGenerate TypeDoc documentation:
npm run docsDocumentation is generated in docs/codebase/.
- Desktop-only: The plugin only works on desktop (not mobile)
MIT
Luis Mendez - luis-mendez.de