Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

R2 Media Sync

Chiang Shun FanChiang Shun Fan134 downloads

Upload local Obsidian media to Cloudflare R2 and rewrite note links automatically.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates21

R2 Media Sync is an Obsidian plugin that automatically uploads local media assets referenced in Markdown notes to Cloudflare R2, rewrites the Markdown links to public R2 URLs, and optionally deletes the local files.

It is designed for workflows where other tools create local image files inside your vault, such as PDF-to-Markdown converters, document importers, AI assistants, or batch import tools.

User Guide

  • English user guide
  • 繁體中文使用手冊

Recent Updates (v0.4.1)

  • Community review compatibility: Removed newer settings APIs while keeping minAppVersion at v1.12.7+.
  • Standalone uploader flow: R2 Media Sync can upload pasted images, dropped images, selected image files, and existing local image links without requiring EzImage.
  • Selected file upload command: Added a command to choose image files from your device and insert R2 Markdown image links into the active note.
  • Configurable selected-file insertion: Selected-file uploads can insert a Markdown image, Markdown link, or plain URL.
  • Delayed rewrite verification: Added a verification pass for paste/drop workflows so Obsidian editor timing does not overwrite the rewritten R2 URL.
  • Safer local cleanup controls: Cleanup mode and review-folder settings remain visible when local cleanup is enabled, including on older Obsidian versions used for BRAT testing.

How It Differs From Other Image Upload Plugins

R2 Media Sync is a standalone Cloudflare R2 media uploader for Obsidian.

It can handle the common image-entry moments directly:

  • pasted images
  • dropped images
  • selected image files
  • local image links that already exist in Markdown

It also handles the next problem: other tools may create image files directly inside your vault and insert local image links into Markdown. Common examples include:

  • PDF-to-Markdown converters that extract page images into the note folder.
  • Document importers that generate local assets.
  • AI assistants or automation tools that write Markdown and image files directly.
  • Batch migration workflows that leave notes full of local image references.

In those cases, paste/drag upload hooks never run. R2 Media Sync watches the resulting Markdown files, uploads the referenced local images to Cloudflare R2, rewrites the links in-place, and can remove the local image files after a successful upload.

In short:

  • Use R2 Media Sync by itself for pasted, dropped, selected, generated, or imported local images.
  • EzImage is optional. R2 Media Sync can import or reuse EzImage's R2 settings, but does not require EzImage to upload images.
  • Companion plugins such as Geo Capture can optionally use R2 Media Sync's local metadata cache, but R2 Media Sync does not depend on them.

What It Does

  • Watches newly created or modified Markdown files.
  • Uploads pasted images after Obsidian inserts them into the current note.
  • Uploads dropped images after Obsidian inserts them into the current note.
  • Uploads selected image files from the command palette and inserts R2 Markdown image links.
  • Lets selected-file uploads insert a Markdown image, Markdown link, or plain URL.
  • Detects local image links:
    • ![](https://raw.githubusercontent.com/fab34/cloudflare-media-sync/HEAD/image.png)
    • ![[image.png]]
  • Uploads referenced image files to Cloudflare R2.
  • Rewrites the note to use a public R2 URL.
  • Optionally deletes the local image file after successful upload.
  • Can read Cloudflare R2 settings from the EzImage plugin or use its own manual R2 settings.

Current Mobile Behavior

R2 Media Sync fully supports Obsidian mobile.

  • Background Auto-monitoring: Automatically detects newly inserted local images on mobile, uploads them to R2, and rewrites links to public URLs.
  • Local Image Handling: Supports Handle local image after upload on mobile. After upload and link rewrite, the original local file can be moved to a review folder or Obsidian trash.
  • iCloud Sync Staging: Recommended when using iCloud sync. Setting the handling mode to "Move to review folder" (e.g. _r2_media_review) keeps files in a safety staging area. Files there are not deleted automatically; clear them from the dashboard after confirming other devices render the R2 URLs correctly. "Move to Obsidian trash" removes the image from the vault through Obsidian's trash handling.
  • UI Constraints: The plugin does not create the desktop status bar on mobile. Scan on startup is always disabled at runtime on mobile to ensure fast app startup.

Why

Plugins such as EzImage handle pasted or dragged images very well, but some Obsidian workflows create files directly in the vault and write local links into Markdown. For example, a PDF conversion plugin may create files like _page_3_Picture_2.jpeg and insert:

![](https://raw.githubusercontent.com/fab34/cloudflare-media-sync/HEAD/_page_3_Picture_2.jpeg)

Those files can clutter the vault and consume sync storage. R2 Media Sync cleans up that class of generated assets automatically.

Features

  • Configurable local cleanup after upload:
    • move to Obsidian trash
    • move to a review folder before manual cleanup
  • Configurable scan scope:
    • whole vault
    • selected folders only
  • Configurable excluded folders, such as .obsidian, .git, Templates, or attachment folders.
  • Toggle support for Markdown image links and wiki image embeds separately.
  • Use existing EzImage R2 settings or enter R2 credentials directly.
  • Reuse previous uploads by file hash to avoid uploading identical image content again.
  • Retry failed uploads before recording them as failed.
  • Keep a local failed upload log for troubleshooting.
  • View recent failed upload details in a modal.
  • Open a sync dashboard with recent status, scope count, upload history count, failure count, review folder size, and maintenance actions.
  • Repair broken local image links from upload history when the attachment file is already missing.
  • Preserve JPEG GPS coordinates in a local metadata cache before rewriting images to R2 URLs, so companion tools such as Geo Capture can still use photo location data later.
  • Show the latest sync state in the Obsidian status bar.
  • Choose the plugin interface language: Auto, English, or Traditional Chinese.
  • Manual command to upload selected image files and insert R2 Markdown links.
  • Manual command to scan the current note.
  • Manual command to scan the configured scope.
  • Manual command to import EzImage settings.

Safety Defaults

R2 Media Sync uses conservative defaults for first-time installs:

  • It does not scan on startup by default.
  • It does not delete local images by default.
  • You can run a manual scan on the current note before enabling broader automation.
  • If local cleanup is enabled, review folder mode is the safer option for multi-device sync.
  • Local cleanup is skipped automatically when the note still contains local image links after rewrite.
  • Failed uploads are recorded locally so you can inspect and retry later instead of losing track of partial failures.
  • On mobile, startup scans are forced off at runtime for performance and safety.

After confirming your R2 settings, public URL, and scan scope, you can opt in to startup scans or local deletion from the plugin settings.

Privacy and Security

  • No telemetry.
  • No analytics.
  • No remote service other than the Cloudflare R2 endpoint you configure.
  • Credentials are stored locally in Obsidian plugin data when using manual mode.
  • When using EzImage mode, this plugin reads the EzImage data.json file from your vault config folder locally and does not modify it.
  • Public Markdown links will contain your configured public R2 URL.
  • Upload history and failed upload logs are stored locally in this plugin's data folder.
  • When JPEG GPS metadata is available, only the extracted coordinates are stored in the local image metadata cache. Full EXIF data and image files are not copied into that cache.

Image Metadata Cache

Before uploading a JPEG image, R2 Media Sync reads local EXIF GPS coordinates when available and stores a small local record in:

.obsidian/plugins/cloudflare-media-sync/image_metadata.json

Each record is keyed by file hash and includes the original vault path, file name, R2 object key, public URL, related Markdown paths, upload time, and optional GPS coordinates.

This helps multi-plugin workflows. For example, after a photo is rewritten to an R2 URL or the local attachment is no longer available on another device, Geo Capture can still look up the saved GPS point and suggest nearby places.

This cache is local to your vault and is intended for recovery and interoperability. It does not upload location data anywhere by itself.

Vault Access

R2 Media Sync scans Markdown files so it can find local media references that were created by PDF converters, importers, AI tools, or other automation.

You can limit this behavior by:

  • Choosing Only included folders instead of Whole vault.
  • Setting included folders such as AI 工作區 or a specific project folder.
  • Excluding folders such as .obsidian, .git, .trash, Templates, or attachment folders.

The plugin only uploads image files that are referenced by Markdown notes and are inside the configured scan scope.

Requirements

  • Obsidian desktop or mobile.
  • A Cloudflare R2 bucket.
  • A public R2 URL or custom public domain.
  • R2 API credentials with permission to upload objects to the target bucket.

Installation

This plugin is not yet published to the Obsidian community plugin registry.

BRAT Installation

If you use the BRAT plugin:

  1. Install and enable BRAT.
  2. Run BRAT: Add a beta plugin for testing.
  3. Enter:
fab34/cloudflare-media-sync
  1. Enable R2 Media Sync in Community plugins.

Manual Installation

Manual installation:

  1. Download or build the plugin files:
    • manifest.json
    • main.js
    • styles.css
  2. Create this folder in your vault:
.obsidian/plugins/cloudflare-media-sync/
  1. Copy the three files into that folder.
  2. Restart Obsidian.
  3. Open Settings -> Community plugins.
  4. Enable R2 Media Sync.

Configuration

Open Settings -> R2 Media Sync.

Language

Choose one:

  • Auto: follow your system/browser language when it is Traditional Chinese, otherwise English.
  • English
  • Traditional Chinese

R2 Settings Source

Choose one:

  • Read from EzImage: reuse EzImage's R2 settings.
  • Manual: enter Cloudflare R2 settings directly in this plugin.

Manual fields:

  • Cloudflare account ID
  • Access key ID
  • Secret access key
  • Bucket name
  • Public URL
  • Path template

Reliability

  • Reuse uploads by file hash: avoids uploading identical image content more than once by storing a local hash-to-URL history.
  • Upload retry attempts: retries each R2 upload before the image is recorded in the failed upload log.

Selected File Uploads

The Upload selected image files command can insert one of three formats:

  • Markdown image: ![image](https://example.com/image.png)
  • Markdown link: [image](https://example.com/image.png)
  • Plain URL: https://example.com/image.png

Local Cleanup

Local cleanup is disabled by default.

When enabled, choose one cleanup mode:

  • Move to Obsidian trash: removes the image from the vault through Obsidian's trash handling.
  • Move to review folder: moves uploaded local files into a vault folder such as _r2_media_review, preserving the original path under that folder so you can inspect before deleting.

The review folder is not cleared automatically. Use Clear local review folder from the command palette or dashboard when you are ready to move review-folder files to Obsidian trash.

Path Template

Default:

{yyyy}/{MM}/{timestamp}-{random}.{ext}

Supported tokens:

  • {yyyy}
  • {MM}
  • {dd}
  • {hh}
  • {mm}
  • {ss}
  • {timestamp}
  • {random}
  • {name}
  • {ext}

Scan Scope

Use the whole vault, or limit processing to included folders.

Recommended exclusions:

.obsidian, .git, .trash, Templates

Recommended First Run

  1. Keep Handle local image after upload disabled.
  2. Keep Scan on startup disabled.
  3. Open a note with one or two local test images.
  4. Run R2 Media Sync: Upload local images in current note.
  5. Confirm the note was rewritten to public R2 URLs.
  6. Enable local cleanup or startup scans only after the manual test behaves as expected.

Recommended Mobile Run

  1. Keep Handle local image after upload disabled.
  2. Keep Scan on startup disabled.
  3. Insert one test image into a note on mobile.
  4. Wait for the local link to be rewritten to an R2 URL.
  5. Confirm the same note renders correctly on desktop before relying on the workflow for important captures.

EzImage is not required for this workflow. If you also use EzImage, note that EzImage's own local-save behavior may affect whether a local file remains in the vault after upload.

Commands

Open the command palette and search for R2 Media Sync.

  • Upload local images in current note
  • Upload selected image files
  • Scan configured scope now
  • Import settings from EzImage
  • Show failed upload summary
  • Clear failed upload log
  • Clear local review folder
  • Repair missing local image links
  • Open sync dashboard

Example

Before:

![](https://raw.githubusercontent.com/fab34/cloudflare-media-sync/HEAD/_page_3_Picture_2.jpeg)
![[diagram.png]]

After:

![image](https://example.r2.dev/2026/06/1710000000000-a1b2c3d4.jpeg)
![image](https://example.r2.dev/2026/06/1710000001000-e5f6g7h8.png)

Development

Install dependencies:

npm install

Build:

npm run build

Development watch:

npm run dev

Release Files

For a manual release, include:

  • manifest.json
  • main.js
  • styles.css

Community Plugin Submission

This repository is structured for eventual submission to the Obsidian community plugin directory.

Before submitting:

  • Publish a GitHub release whose tag exactly matches the version in manifest.json, for example 0.1.2.
  • Attach manifest.json, main.js, and styles.css to that release.
  • Open a pull request to obsidianmd/obsidian-releases.

See COMMUNITY_SUBMISSION.md for the suggested entry and checklist.

Notes

This plugin intentionally only processes image files that are referenced by Markdown notes. It does not upload unreferenced orphan images, because doing so could remove files that are still being staged or reviewed.

For multi-device setups, the safest pattern is:

  1. Upload and rewrite first.
  2. Confirm the rewritten note renders on the other device.
  3. Only then consider removing local files or emptying the review folder.

License

MIT — Feel free to use, modify, and distribute. Issues and PRs are welcome.

HealthExcellent
ReviewPassed
About
Automatically detect local image links in Markdown notes, upload the referenced files to Cloudflare R2, and replace them with public URLs. Designed for workflows where tools like PDF converters, importers, or AI assistants generate local media files inside your vault. Supports Markdown image links and wiki embeds, configurable scan scope, optional cleanup of local files after upload, and importing R2 settings from EzImage.
AttachmentsSyncingAutomation
Details
Current version
0.4.1
Last updated
Last month
Created
2 months ago
Updates
21 releases
Downloads
134
Compatible with
Obsidian 1.12.7+
Platforms
Desktop, Mobile
License
MIT
Report bugRequest featureReport plugin
Sponsor
Buy Me a Coffee
Author
Chiang Shun FanChiang Shun Fanfab34
GitHubfab34
GitHubfab34
  1. Community
  2. Plugins
  3. Attachments
  4. R2 Media Sync

Related plugins

Attachment Management

Customize attachment path, auto-rename attachments, etc.

YAOS

Simple real-time sync powered by your own Cloudflare Worker.

Paste image rename

Rename image after pasting, support name pattern and auto renaming.

Homepage

Open a note, base, or workspace on startup, or set it for quick access later.

BRAT

Easily install a beta version of a plugin for testing.

Advanced URI

Control everything with URI.

Fast Note Sync

Real-time sync of your vaults across server, mobile, and web; shareable with anyone; supports REST and MCP integrations to build your personal AI knowledge base.

Share Note

Instantly share/publish a note, with the full theme and content exactly like you see in Obsidian. Data is shared encrypted by default, and only you and the person you send it to have the key.

Lazy Loader

Load plugins with a delay on startup, so that you can get your app startup down into the sub-second loading time.

Hot Reload

Automatically reload in-development plugins when their files are changed