Local web app for Windows and Linux that watches folders, converts Office documents to Markdown, stores them inside a target workspace subdirectory, and optionally tracks the generated Markdown in Git.
Latest container image: ghcr.io/flier268/office-docs-to-md-sync:latest
- Multiple sync tasks managed from a local web UI
- Office conversion via
markitdown - Direct Markdown output for text files such as
txt,md,csv,tsv, and custom extensions - Full mirror behavior for deletes and renames
- File event watching with periodic hash-based scans to catch missed changes
- Optional Git init, commit, and delayed push per task
- SQLite-backed config and event history
- Windows service and systemd install scripts
python -m venv .venv
source .venv/bin/activate
pip install -e .[dev]
office-docs-to-md-syncOpen http://127.0.0.1:8080.
- Set the task
target_rootas the repository root and output workspace. - Set
output_subdirto choose where generated Markdown lives under the target root. - Each target repo keeps
.office-docs-sync-state.jsonat the repo root with per-task source file hashes and output mappings. - The app still uses filesystem events for low-latency sync, but every task also runs a periodic hash scan to catch missed updates and deletes.
- Auto push uses the system git credential or SSH setup already present on the machine by default.
- For HTTPS remotes in containers, set a task-scoped PAT environment variable named from the task name plus
_key. Non-word characters in the task name become_; for example taskDocs SyncreadsDocs_Sync_key(uppercaseDOCS_SYNC_KEYis also accepted). The token is injected only for the git push process throughGIT_ASKPASS.
Linux:
./scripts/install-systemd.sh /path/to/project office-docs-to-md-syncWindows PowerShell:
.\scripts\install-windows-service.ps1 -AppDir C:\path\to\projectpytestpython -m pip install pyinstaller
pyinstaller --noconfirm office-docs-to-md-sync.specThe generated binary bundle is written to dist/office-docs-to-md-sync/ and includes the web UI static assets.
The packaged dependency set is intentionally limited to the markitdown extras this app targets: docx, pptx, xlsx, and pdf.
docker build -t office-docs-to-md-sync .
docker run --rm -p 8080:8080 -v "$(pwd)/.localdata:/data" office-docs-to-md-synccp docker-compose.example.yml docker-compose.yml
docker compose up -dThe included example mounts ./data to /data for the app database and runtime state.
- Pushing a tag like
v0.1.0runs.github/workflows/release.ymland publishes both the PyInstaller Linux bundle and Windows bundle to GitHub Releases. - You can also run the same workflow manually from the GitHub Actions UI by selecting a branch, then providing a full
v*tag such asv0.1.0. The workflow creates and pushes that tag from the selected branch before publishing the release, and it fails if that release tag already exists unless you explicitly enableallow_move_release_tag. - Manual runs now treat the release tag and
latestseparately. Setmark_as_latestonly when that release should become the current latest release. - Set
allow_move_release_tagonly when you intentionally want to force-move an existingv*release tag to the selected commit. - When a release is marked as latest, the workflow force-moves the Git tag
latestto that release commit and also publishes the containerlatesttag. - The same workflow always publishes multi-arch Docker images to
ghcr.io/<owner>/<repo>with tagsvX.Y.ZandX.Y.Z, and only publisheslatestwhen that release is marked as latest. - If the release for that tag already exists, the workflow updates the release and replaces old assets. Re-pushing the same image tag to GHCR also replaces the previous image manifest for that tag.
.github/workflows/monthly-image.ymlalso publishes the container image automatically at00:00 UTCon the first day of every month from the Git taglatest, tagging it asedgeandmonthly-YYYY-MM.- You can run the monthly image workflow manually from the GitHub Actions UI if you want to refresh the container image outside the normal schedule.
- Pushing commits or opening a pull request runs
.github/workflows/ci.yml. - The CI workflow installs the project with
.[dev]extras on Python 3.12 and runspytest.