Logo
Command Palette

Search for a command to run...

~/ cd ..

An intelligent, session-based file monitoring system that watches your workspace, groups related changes, and delivers ZIP archives via Telegram with real-time bot control.

SYNC-OG

Sync

An intelligent, session-based file monitoring system that watches your workspace, intelligently groups changes, and delivers ZIP archives via Telegram with real-time control.

About The Project

Sync is a file monitoring daemon that uses session-based bundling to automatically track, package, and deliver workspace changes via Telegram. It's well suited to automatic backups, homework submission, or lightweight collaborative workflows — instead of sending a notification per file edit, it groups related changes into a single session and ships one timestamped ZIP once activity settles down.

Key Features

  • Smart session management that groups related file changes using configurable idle timeouts
  • Debounced file watching to prevent notification spam during rapid edits
  • Automatic ZIP packaging into timestamped archives
  • Full Telegram bot control with admin-only commands
  • Async architecture for non-blocking, concurrent operation
  • Selective monitoring filtering to relevant file types (.md, .pdf, .excalidraw)

Technology Stack

  • Python 3.13+
  • Watchdog (file system observation)
  • Telegram Bot API

Architecture

The system runs two concurrent pieces from a single entry point: a background-threaded file watcher observing the target directory, and a blocking Telegram bot handling commands. File events pass through a type filter, then a debounce buffer, before being handed to a session manager that tracks changed files and resets an idle timer on every new change. Once the idle timeout expires (or a manual /endsession command fires), the session finalizes, the collected files are zipped into a timestamped archive, and the archive is delivered asynchronously over the Telegram Bot API.

Session Lifecycle

The session manager behaves as a small state machine:

StateDescriptionTrigger
IdleNo active sessionSystem start / session complete
ActiveTracking changes, timer resets per activityFile modification detected
ProcessingFinalizing the sessionIdle timeout or manual /endsession
ZippingCreating the archiveSession finalization
SendingUploading to TelegramZIP creation complete

Bot Commands

  • /status — shows pending files in the current session
  • /last — displays the last sent ZIP filename
  • /endsession — forces an immediate session end and send
  • /setIdle <seconds> / /getIdle — admin-only commands to adjust or check the idle timeout

Technical Highlights

Async/Sync Bridge Pattern

The session manager needs to trigger session completion from both a synchronous timer thread and an asynchronous bot context. It does this by attempting to grab the running event loop and scheduling a task if one exists, falling back to asyncio.run() if called from a plain timer thread — letting the same completion logic work correctly from either context.

Debounced File Events

Each file path gets its own cancellable timer: every new event on a path cancels the previous timer and starts a new one, so rapid successive edits to the same file only trigger a single downstream update once edits actually settle.

Smart File Filtering

Hidden files, temp files (trailing ~), and known cache/trash directories (like .obsidian, .trash) are filtered out before they ever reach the debounce or session layer, keeping noise out of delivered archives.

Problems Faced

  1. Bridging Sync and Async Contexts : Python's timer threads are synchronous, but the Telegram bot and file delivery logic are asynchronous — triggering session completion correctly from either context required detecting whether an event loop was already running and branching accordingly.

  2. Avoiding Notification Spam : Without debouncing, a single save could fire multiple file-system events in quick succession; per-path cancellable timers solved this without adding noticeable delay to genuine session updates.

  3. Balancing Idle Timeout Against Usability : Picking a sensible default idle timeout (600 seconds) meant balancing "wait long enough that a real editing session isn't split into multiple ZIPs" against "don't make the user wait too long to get their backup."

Key Learnings

  1. State Machines Simplify Concurrent Systems : Modeling the session lifecycle explicitly as Idle → Active → Processing → Zipping → Sending made it much easier to reason about what should happen when timers, file events, and bot commands all fire in overlapping ways.

  2. Debouncing Is Essential for File-System Events : Raw file-system watcher events are noisy by nature; a debounce layer is effectively mandatory for any system that wants to react to "a user is done editing" rather than "a byte changed on disk."

  3. Small Async Bridges Go a Long Way : A few lines of context-detection code (try get_running_loop(), fall back to asyncio.run()) were enough to let the same business logic be triggered safely from completely different execution contexts.

What's Next

  • A dashboard with session statistics
  • Support for monitoring multiple vaults at once
  • Cloud storage integration (S3, GCS)
  • A web interface for configuration
  • A file-type plugin system
  • Configurable compression levels and optional encryption
  • Scheduled, time-based backups in addition to idle-triggered ones
Command Palette

Search for a command to run...