Vault Bridge

approved

by Yi Yang

Open a token-protected port on your computer, then upload and download vault files from your phone over a URL. - This plugin has not been manually reviewed by Obsidian staff.

36 downloadsUpdated 3d agoMIT

Vault Bridge

English · 简体中文

Open a token-protected port on your computer, then upload and download vault files from your phone over a URL.

One codebase plays two roles:

  • On desktop it runs an HTTP server: opens the port, verifies the token, reads and writes your vault.
  • On mobile it is a client only: browse files on the computer and download them, or send files from the phone back to the computer.

No cloud service, no account, no third-party server in the middle. Files travel directly between your own devices.

Sponsor / 赞助

English — Vault Bridge is a spare-time project. If it saves you some hassle moving files between your computer and phone, you can buy me a cup of tea. Entirely optional — every feature stays free.

中文 —— Vault Bridge 是业余时间的作品。如果它让你在手机和电脑之间传文件省了事, 欢迎扫码请我喝杯茶 —— 完全自愿,不影响任何功能

WeChat Pay QR code / 微信支付收款码
WeChat Pay / 微信支付
Alipay QR code / 支付宝收款码
Alipay / 支付宝

Three things that help just as much as money / 不花钱也能帮上忙:

  1. Star this repo / 给仓库点个 Star;
  2. Vote for it in the community directory once it is listed / 等它进入社区目录后点个赞;
  3. Report what broke / 把遇到的问题反馈过来。

Features

One-tap whole-vault syncOn the phone, tap ⬇ 一键同步整个库到手机 right under the tabs: the entire vault comes over in one go, and later taps transfer only the files that changed.
Update the plugin from the computerOn mobile, ⇧ 更新插件 pulls main.js / manifest.json / styles.css from the desktop server and replaces them in place — no file manager, no manual copying.
Actions reachable from SettingsThe 手机端 group starts with a 连接检查与一键同步 row: 测试连接(检查 200) proves the address answers, ⬇ 一键同步整个库 syncs without opening the panel, 打开传输面板 opens the browser view.
Download to phoneBrowse the remote vault and tap a file. Tapping a folder downloads it recursively, keeping the same relative structure so wiki-links and attachments keep working on mobile.
Upload to computerBrowse the phone vault and send files back. The landing folder is configurable.
Works without the pluginThe desktop server also serves a mobile-friendly web page, so any phone browser can transfer files with zero install.
Built-in setup page/setup walks you through installing the mobile plugin and hands out the installation bundle — no cable, no cloud drive.
LAN first, public optionalSame-WiFi transfers go straight over your local network. For 4G/5G there is a one-command HTTPS tunnel.

Requirements

Obsidian 1.13.0 or later. The settings tab uses the declarative settings API introduced in 1.13.0, which is what lets these settings show up in Obsidian's settings search.

Quick start

1. On the computer

npm install
npm run build
node tools/install.mjs --enable    # install into your vault and enable it

Or copy main.js, manifest.json and styles.css into <your vault>/.obsidian/plugins/vault-bridge/ and enable it under Settings → Community plugins.

Reload Obsidian; the server starts automatically on port 8770.

The plugin settings then show:

  • the running status,
  • a LAN address such as http://192.168.1.44:8770/?token=…,
  • the access token.

Click the address to copy it.

2. On the phone

Option A — browser, nothing to install. Open the copied link on your phone. Add it to your home screen and it behaves like an app.

Option B — the mobile plugin. On the phone open http://<computer-ip>:8770/setup, download the bundle, unzip it into <your vault>/.obsidian/plugins/vault-bridge/, then enable Vault Bridge in Obsidian and enter the address and token.

Step-by-step iOS instructions (中文): docs/mobile-setup.md.

Network

SituationAddressWhat to do
Phone and computer on the same WiFihttp://192.168.1.44:8770Nothing — it just works
Phone on 4G/5Ghttps://xxx.trycloudflare.comRun tools/tunnel.sh start on the computer

Public access must be HTTPS: iOS App Transport Security rejects plain HTTP requests from the app, which is why the LAN address stops working outside your home network.

tools/tunnel.sh start     # start the tunnel and print the public URL
tools/tunnel.sh status
tools/tunnel.sh stop

Quick-tunnel hostnames change on every restart. Update the address on your phone when that happens; the token stays the same.

Security

An open port gets probed, so every request is treated as hostile until proven otherwise.

  • The token is the only credential — 32 URL-safe random characters, sent as Authorization: Bearer or ?token=.
  • Constant-time comparison — response timing cannot be used to guess the token character by character.
  • Rate limiting — 8 failures from one IP within a minute triggers a 5-minute block.
  • Path sandbox — every path from the network is normalized first; ../ escapes, absolute paths and drive letters are rejected.
  • The config directory is off-limits.obsidian cannot be read or written over the network, so tokens and plugin data cannot be exfiltrated or overwritten.
  • Writes can be disabled — turn off "allow upload" and the phone becomes read-only.
  • Upload size cap — 32 MB by default, configurable.
  • Access log — see who did what and when in the settings tab.

Regenerating the token in the settings invalidates the old one immediately.

FAQ

The phone cannot connect. Open http://<computer-ip>:8770/api/health in the phone browser. JSON back means the network is fine. A 401 means the network is fine but the token is wrong. Nothing at all means WiFi or firewall.

Port already in use? Change the port in the settings (1024–65535) and press "restart service".

Where do downloaded files go? Into VaultBridge下载/ on the phone, mirroring the computer's relative paths. Configurable in the settings.

How one bundle runs on both platforms

Mobile Obsidian cannot load Node built-in modules. The build therefore:

  • bundles with platform: browser and marks http/os/fs as external,
  • runs server code only when Platform.isDesktopApp is true, resolving Node modules lazily through a single nodeRequire() chokepoint.

tools/verify-bundle.mjs loads the real main.js the same way Obsidian does — injecting module/exports/require through new Function — then starts the server and fires real HTTP requests. It also asserts that on mobile the plugin creates no server instance and binds no port.

Development

npm run build          # bundle to main.js
npm run typecheck
npm run lint
npm test               # 160 unit & integration tests
npm run test:coverage
npm run verify         # 42 bundle-level assertions against the real artifact
npm run bench          # end-to-end latency benchmark

Layout

src/
├── main.ts              plugin entry; dispatches the two roles by platform
├── settings.ts          settings model and the desktop settings tab
├── shared/              used by both sides: types, path safety, token, protocol, transfer paths
├── server/              desktop: HTTP server, router, auth, vault ops, web UI, self-setup page
└── client/              mobile: API client and the transfer panel
tests/                   vitest: attack surface, auth, routing, real-port integration
tools/                   installer, tunnel, bundle verification, Obsidian host double

Verifying a release

Release assets ship with a GitHub build provenance attestation, so you can confirm that main.js was built from this repository by its release workflow:

gh attestation verify main.js --repo YaYII/obsidian-vault-bridge

On older gh versions (below 2.49) verify through the API instead:

D=$(sha256sum main.js | cut -d" " -f1)
gh api "repos/YaYII/obsidian-vault-bridge/attestations/sha256:$D"

The build is also reproducible: it embeds no timestamp or randomness, so rebuilding from the same tag yields a byte-identical main.js.

License

MIT

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.