# Relay Docs — full content > Relay is an Obsidian plugin for real-time multiplayer collaboration on notes and Canvases. ## Canvas multiplayer URL: https://docs.relay.md/features/canvas-multiplayer/ Canvas multiplayer On this page With Relay, you can collaborate with your team in real time on Obsidian's core Canvas tool. Great for mind maps, white boarding, process flows, etc. Note: This feature is in beta It's open to all, but special steps are required to enable it. Join the canvas-beta channel on the Relay Discord server to get setup instructions. What is Canvas? Canvas is a core Obsidian plugin that allows you to visualize your notes and their connections. It uses an open file format developed by the Obsidian team called JSON Canvas . Canvas showcase from danlandrum on the Obsidian Forum Canvas multiplayer While .canvas files can be synced as binary (atomic units) like any other file, real-time multiplayer requires a specialized CRDT implementation within Relay. The reason is that markdown files — the first format we built support for at Relay — are backed by a single text CRDT, but Canvas files have multiple block types, inline text nodes, and even embedded markdown files. Canvas multiplayer is out now in beta. Try it out to see your collaborators actions in real time. Join the Relay Discord server and visit the #canvas-beta channel to get started. Tell us about your use case If Canvas multiplayer is important for your workflow: Join our Discord - and get into the #canvas-beta channel Describe your specific use case . This helps us steer design and development Follow our roadmap at relay.md/relay/roadmap for updates (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Hosting options URL: https://docs.relay.md/features/hosting-options/ Hosting options On this page Relay offers flexible hosting options to meet a variety of security, compliance, and operational requirements. You can think of Relay as comprising three components: the Relay Server, the Control Plane, and storage. Each of these can be hosted on our infrastructure or yours. Self-hosting a Relay Server is free on every Relay plan. See Self-hosting Relay is free and We don't charge for privacy for the reasoning behind that policy. Why is hosting required to use Relay? The beautiful thing about Obsidian is that your files are local first: the canonical source of truth is the .md files on your local disk. Relay maintains that commitment and meets the challenge of making those local files collaborative. Relay accomplishes this with the help the open source CRDT Yjs . When you run Relay, the plugin watches your shared notes, converts your changes to commutative update operations, and relays those operations through hosted infrastructure to your collaborators, where they can be processed to recreate the changes on the other side. In principle this could be accomplished entirely through peer-to-peer communication without the use of any central intermediary. However, we have chosen not to architect Relay as peer-to-peer because in that case, collaboration is only possible between two peers who are online at the same time. An always-on server is like a 'market maker' that allows you to relay your updates between collaborators even if you're not online at the same time. For example, suppose Abigail is in the United States and John is in Europe: Abigail makes a change to a note while John in sleeping. Her machine sends those changes up to the hosted Relay Server. Abigail shuts down her computer and goes to bed. A few hours later, John wakes up in Amsterdam, opens his machine, and starts his day. John's machine downloads Abigail's updates from the hosted Relay Server, bringing him up to date with the most recent work from Abigail. To make this possible, somewhere in the world there has to be a machine that's always online, ready to receive and transmit changes. Relay architecture Relay consists of two primary components. The Relay Server is responsible for: Real-time collaboration and file storage APIs Data is persisted to S3-compatible storage The Control Plane is responsible for: User authentication and SSO integration User management and permissions Server and folder metadata Hosting models offered Self-hosting a Relay Server provides total document privacy. Obsidian users are granted document-scoped access tokens by the control plane which are valid for 1 hour. The Relay Server does not need to access the public internet. If you need a full air-gapped or on-premise deployment, including the Control Plane, that is an Enterprise-positioned waitlist offering. Contact us if you need that level of isolation so we can understand your requirements and plan support. Note: Self-hosting is free You can self-host a Relay Server on any Relay plan. See our relay-server-template on GitHub for deployment guides and configuration examples. When you self-host a Relay Server you have unmetered storage, but the seat limit still applies. Relay Cloud: Host on Relay's infrastructure. The easiest and most cost-effective option. Relay Cloud (dedicated) We run a dedicated host for your Relay Server(s) to add an additional layer of security and isolation. Supports BYO AWS S3-compatible storage. Self-hosted Relay Server: Host Relay Servers on your own infrastructure. Full air-gapped or on-premise deployment: Enterprise waitlist offering for running the full stack, including the Control Plane, on your infrastructure. Here's what's available at each tier: Relay Server (document collaboration) Control Plane (login & permissions) Free Relay Cloud OR self-host Relay Cloud Team Relay Cloud OR self-host Relay Cloud Pro Relay Cloud (dedicated) OR self-host Relay Cloud Enterprise Relay Cloud (dedicated) OR self-host; full air-gapped/on-premise by waitlist Relay Cloud; full air-gapped/on-premise by waitlist Privacy implications We don't look at your data and we don't sell it. Like all cloud services, we could be compelled by law enforcement to provide access (this has never happened). BYO hosting options provide technical guarantees beyond promises. What Relay staff can technically access depends on which components you host: All components on Relay Cloud : Standard SaaS model - we could access your data if legally compelled, though we don't under normal operations. See our security page for details. Storage + Relay Server on your infrastructure, Control Plane on Relay Cloud : We can only see metadata (server names, user emails, document IDs) but no document content Full air-gapped or on-premise deployment, including the Control Plane : Enterprise-positioned waitlist offering. If deployed, we see nothing unless you grant specific access for support Choosing the right option Choose Team tier if: Standard security requirements Cost is primary concern No specific compliance mandates Choose Pro tier if: Need dedicated infrastructure Want BYO storage while we host dedicated Relay infrastructure Need cross-org collaboration Choose Enterprise tier if: Need complete data sovereignty Need a full air-gapped or on-premise deployment and want to join the waitlist Require full audit control Tip: Need help deciding? Contact us to discuss your specific requirements. We can help you understand which hosting model best fits your security, compliance, and operational needs. (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Backing up your Obsidian vault URL: https://docs.relay.md/guides/backing-up-your-obsidian-vault/ Backing up your Obsidian vault On this page Relay syncs your Shared Folders. It is not designed as a backup tool. You'll want remote backups if your computer is lost or destroyed; local backups are fine for recovering from data loss or corruption (e.g. if a coding agent makes unwelcome changes to your files). If you're serious about your notes, set up git. It's the right answer for any Obsidian user, Relay or not. Set up git with Obsidian Git The Obsidian Git plugin commits your vault to a git repository on a schedule. Set it to auto-commit every 5 minutes. Git retains full file history. You can restore any file to any prior state: git log to find the commit, git checkout <hash> -- path/to/file.md to restore. Should you push to a remote? Pushing to GitHub, GitLab, or a self-hosted server gives you an offsite copy — protection if your machine is lost or destroyed. The trade-off: your vault content lives on another server. If your vault contains sensitive notes or client work, use a private repository, a self-hosted server, or skip remote push and keep history local. Local-only git still gives you full version history. You lose the offsite copy but keep the recovery path. If you've already lost data If you don't have git set up, these are your options: Obsidian file recovery (Settings → Core plugins → File recovery) — saves snapshots on a schedule, can restore a note to a recent prior state .trash folder ( <vault>/.trash/ ) — check here for recently deleted files These are better than nothing. Git is better than these. Compatibility with other sync services Do not run another sync service (iCloud, Dropbox, Obsidian Sync) on the same Shared Folders as Relay. See Using Relay with other sync services for details. If you use Obsidian Sync for cross-device sync alongside Relay, configure it to exclude your Relay Shared Folders. The Obsidian Sync Local REST API (headless mode) makes managing those exclusions easier. Need help? Join the Relay Discord for support. (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Configure attachments for sharing URL: https://docs.relay.md/guides/configure-attachments-for-sharing/ Configure attachments for sharing On this page When you paste images or attach files in Obsidian, they need to be saved inside your Shared Folder for Relay to sync them. By default, Obsidian may save attachments to a centralized location outside your Shared Folders, which means they won't sync. This guide shows you how to configure Obsidian so attachments are automatically placed where Relay can sync them. Info: Attachment sync requires a paid plan Attachment sync is only available on Relay for Teams. See Upgrade to Relay for Teams or visit the pricing page for details. The issue Relay sharing is folder-based. Relay will never look outside a Shared Folder into other parts of your vault. If an attachment is saved outside the Shared Folder, it won't sync, even if the note that references it is inside the Shared Folder. This is a common issue when: You have a vault-wide attachments folder (like "Attachments/" at the root of your vault) You're adding Relay to an existing vault with attachment settings you configured before using Relay Recommended solution: attachments in subfolders Configure Obsidian to save attachments in a subfolder within the current folder. This ensures attachments stay inside your Shared Folders and sync automatically. How to configure this Open Obsidian settings (gear icon in the lower left) Navigate to Files and links Under Default location for new attachments , select: In subfolder under current folder Under Subfolder name , enter: Attachments (or whatever name you prefer) With this configuration: If your note is in Projects/Website/meeting-notes.md Pasted images will be saved to Projects/Website/Attachments/ If Projects or Website is a Shared Folder, the attachments will sync automatically Alternative solutions Same folder as current file If you don't want a separate attachments subfolder, you can save attachments directly alongside your notes: Open Obsidian settings Navigate to Files and Links Under Default location for new attachments , select: Same folder as current file With this configuration, attachments are saved directly in the same folder as the note you're working in. Manually move attachments in If you prefer to keep your attachments centralized in your vault root, you can always manually move new (and old) attachments into your Shared Folder when you want to share. You can also use Obsidian's file move hotkey to make this faster (set in Settings → Hotkeys → "Move file to another folder"). Need help? Join the Relay Discord for support. (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Install the latest Relay beta URL: https://docs.relay.md/guides/install-relay-beta/ Install the latest Relay beta On this page Relay beta releases are prerelease builds for testing new Relay features before they reach the standard Obsidian community plugin release. There are two ways to install the latest Relay beta. If you run a local coding agent, use it — that is the smoothest path. If you don't, install it yourself with BRAT. Automatic install: use a local agent . Recommended if you have Claude Code, Codex, Cursor, or another local shell-capable agent on the same computer as your vault. It selects the latest beta, verifies GitHub release digests, backs up replaced files, preserves your Relay settings, and restarts Relay. Copy the self-contained instructions and paste them in: Copy agent instructions as Markdown Manual install: use BRAT . Use this if you do not run a local agent, or are on mobile. Install from inside Obsidian yourself. Manual install: use BRAT BRAT (Beta Reviewer's Auto-update Tool) is an Obsidian plugin that can side-load other plugins. Use BRAT if you want to install the beta yourself from inside Obsidian. In Obsidian, open Settings -> Community plugins. Browse for BRAT and install it. Enable BRAT. Open the command palette. On macOS, press Command-P . On Windows or Linux, use your command palette shortcut. Run BRAT: Plugins: Add a beta plugin with frozen version based on a release tag . Enter: Repository: No-Instructions/Relay Release version tag: checking latest beta... Enable after installing: checked Click Add Plugin . Reload Obsidian, or disable and re-enable Relay in Community plugins. The release tag is pinned. To move to a newer Relay beta later, repeat these steps with the newer release tag. If the latest tag does not load here, open Relay releases and choose the most recently published non-draft prerelease that has main.js , styles.css , and a manifest asset, such as 0.8.4 . The tag may or may not end in -rcN . Automatic install: use a local agent Have your agent install the beta if it can read and write files inside your Obsidian vault. It can select the latest beta release, verify GitHub release digests, back up replaced files, preserve Relay settings, and restart Relay in Obsidian when possible. If your agent can read web pages, have it use this page. Otherwise copy the full self-contained instructions: Copy agent instructions as Markdown # Install the latest Relay beta You are a local coding agent running on the same computer as the user's Obsidian vault. Install the newest Relay beta release for the Obsidian community plugin id `system3-relay`. ### Before you start Relay beta releases are published at [No-Instructions/Relay releases](https://github.com/No-Instructions/Relay/releases). This install copies verified release files into the user's vault at ` /.obsidian/plugins/system3-relay`. Only modify: - ` /.obsidian/plugins/system3-relay` - ` /.obsidian/.relay-beta-backups` ### Procedure 1. Get the absolute path to the user's Obsidian vault. If the user does not provide it, inspect Obsidian's local vault registry and then ask the user to confirm the selected vault before writing. Common registry locations: - macOS: `~/Library/Application Support/obsidian/obsidian.json` - Windows: `%APPDATA%\Obsidian\obsidian.json` - Linux: `~/.config/obsidian/obsidian.json` If multiple registry entries exist, prefer the one marked `open: true`, then confirm the selected vault with the user. Reason: the install target is inside that vault, and users may have more than one vault. 2. Verify ` /.obsidian` exists. Stop if it does not. Reason: this prevents writing plugin files into the wrong directory. 3. Query `https://api.github.com/repos/No-Instructions/Relay/releases?per_page=50`. Reason: the GitHub Releases API contains the release metadata, asset URLs, and SHA-256 digests. 4. Among releases where `draft` is false and `prerelease` is true and assets include `main.js`, `styles.css`, and a manifest (`manifest.json` or `manifest-beta.json`), select the one with the newest `published_at`. Do not filter on the tag name. Reason: Relay betas have shipped under more than one tag convention — release candidates like `0.8.0-rc11`, and plain versions built from `main` like `0.8.4`. Selecting by the prerelease flag, the required assets, and publish date finds the true latest beta no matter how the tag is named, so this does not go stale when the convention changes again. 5. Choose the manifest asset: prefer `manifest.json` if the release has it, otherwise use `manifest-beta.json`. Read the `digest` field for `main.js`, `styles.css`, and the chosen manifest asset. Reason: GitHub's digest is the source of truth for verifying each downloaded file, and different beta releases ship the manifest under different asset names. 6. Prepare `PLUGIN_DIR`, `BACKUP_ROOT`, `BACKUP_DIR`, and `STAGING`. Reason: explicit paths make the install auditable and keep writes within the allowed locations. 7. Check whether the official Obsidian CLI is available with `command -v obsidian`. Reason: Obsidian must restart plugin code after the file install, and checking for the CLI now prevents defaulting to a manual restart later. 8. Show the user the selected release, publish date, vault path, plugin path, backup path, expected SHA-256 digests, file list, and whether Obsidian CLI restart is available. If the CLI is available, say the install will use the CLI to disable Relay, wait briefly for teardown, then enable Relay after the files are written. If the CLI is not available, say manual reload will be needed. Do not write anything until the user explicitly approves. Reason: this is a prerelease install that modifies files in the user's vault. 9. Download `main.js`, `styles.css`, and the chosen manifest asset into a temporary directory. Reason: failed downloads must not leave the installed plugin half-updated. 10. Verify each downloaded asset's SHA-256 against the expected digest from the API. Stop on any mismatch. Reason: a mismatch means the downloaded file is not the expected release asset. 11. Verify the downloaded manifest asset has `id` set to `system3-relay`. Reason: this prevents installing the wrong plugin manifest. 12. Set the manifest's `version` field to the selected release tag, then save it as `manifest.json`. Do this regardless of the version the downloaded manifest already declares. Reason: the `version` field in Relay's beta manifests is not reliable — release candidates have carried an old stable version (for example `0.7.4`), and within a single release the `manifest.json` and `manifest-beta.json` assets can declare different versions. The release tag is the one authoritative version, and Obsidian reads the local plugin folder's `manifest.json` to report what is installed. 13. If `PLUGIN_DIR` already exists, create `BACKUP_DIR` and copy `main.js`, `styles.css`, `manifest.json`, and `data.json` into it, skipping any that are not present. Reason: rollback only needs the files being replaced plus settings, and `data.json` must be preserved. 14. Create `STAGING` inside `PLUGIN_DIR`. Copy verified `main.js`, verified `styles.css`, and rewritten `manifest.json` into `STAGING`. Reason: staging keeps the final write step small and avoids a plugin folder with a mix of downloaded and missing files. 15. Move `main.js`, `styles.css`, and `manifest.json` from `STAGING` into `PLUGIN_DIR`. Reason: this completes the direct plugin install. 16. Confirm `data.json`, if present, was not replaced. Reason: `data.json` contains existing Relay settings. 17. Restart Relay in Obsidian. If step 7 found the official Obsidian CLI, first try a full disable/enable cycle: `obsidian plugin:disable id=system3-relay`, wait at least 2 seconds, then `obsidian plugin:enable id=system3-relay`. Do not assume a running Obsidian app is enough; the user may need to enable the CLI in Obsidian settings first. Use the `id=` prefix; command forms like `obsidian plugin:disable system3-relay` are not valid. If the CLI is unavailable or the disable/enable cycle fails, tell the user to disable then re-enable Relay in Community plugins, or run `Reload app without saving` from the command palette. Reason: Obsidian must unload old plugin code before the new beta is active. A disable/enable cycle gives Relay time to tear down sockets, listeners, and timers before loading the replacement code. ## Reference implementation This shell script is not required. The agent may use other tooling as long as it follows the contract above. If using the script, run it first with `RELAY_DRY_RUN=1` to preview the selected release, expected writes, and digest verification. After the user approves, run with `RELAY_CONFIRM=INSTALL` to skip the interactive prompt. ```bash # Agents: set VAULT to the absolute path of the target Obsidian vault before running. VAULT="/absolute/path/to/your/vault" REPO="No-Instructions/Relay" set -euo pipefail if [ "$VAULT" = "/absolute/path/to/your/vault" ]; then echo "Set VAULT to the absolute path of the Obsidian vault before running." >&2 exit 1 fi if [ ! -d "$VAULT/.obsidian" ]; then echo "Refusing to continue: $VAULT does not contain a .obsidian folder" >&2 exit 1 fi for tool in curl jq; do if ! command -v "$tool" >/dev/null 2>&1; then echo "Missing required tool: $tool" >&2 exit 1 fi done if command -v sha256sum >/dev/null 2>&1; then SHA256_CMD="sha256sum" elif command -v shasum >/dev/null 2>&1; then SHA256_CMD="shasum -a 256" else echo "Missing SHA-256 utility: need sha256sum or shasum" >&2 exit 1 fi sha256_of() { $SHA256_CMD "$1" | awk '{print $1}' } PLUGIN_DIR="$VAULT/.obsidian/plugins/system3-relay" BACKUP_ROOT="$VAULT/.obsidian/.relay-beta-backups" STAMP="$(date +%Y%m%d-%H%M%S)" BACKUP_DIR="$BACKUP_ROOT/system3-relay-$STAMP" TMPDIR="$(mktemp -d)" STAGING="" cleanup() { [ -n "${TMPDIR:-}" ] && rm -rf "$TMPDIR" [ -n "${STAGING:-}" ] && [ -d "$STAGING" ] && rm -rf "$STAGING" return 0 } trap cleanup EXIT DRY_RUN="${RELAY_DRY_RUN:-0}" RELEASES_JSON="$TMPDIR/releases.json" curl -fsSL "https://api.github.com/repos/$REPO/releases?per_page=50" -o "$RELEASES_JSON" VERSION="$(jq -r ' map(select(.draft == false and .prerelease == true)) | map(select( ([.assets[].name] | contains(["main.js"])) and ([.assets[].name] | contains(["styles.css"])) and ([.assets[].name] | (contains(["manifest.json"]) or contains(["manifest-beta.json"]))) )) | sort_by(.published_at) | reverse | .[0].tag_name // empty ' "$RELEASES_JSON")" if [ -z "$VERSION" ]; then echo "No prerelease found with required Relay beta assets" >&2 exit 1 fi PUBLISHED_AT="$(jq -r --arg version "$VERSION" ' (.[] | select(.tag_name == $version) | .published_at) // "unknown" ' "$RELEASES_JSON")" asset_digest() { local asset_name="$1" jq -r --arg version "$VERSION" --arg asset "$asset_name" ' (.[] | select(.tag_name == $version) | .assets[] | select(.name == $asset) | .digest) // empty ' "$RELEASES_JSON" } # Prefer the modern manifest.json asset; fall back to the older manifest-beta.json. MANIFEST_ASSET="manifest.json" if [ -z "$(asset_digest "$MANIFEST_ASSET")" ]; then MANIFEST_ASSET="manifest-beta.json" fi EXPECTED_DIGEST_MAIN="$(asset_digest main.js)" EXPECTED_DIGEST_STYLES="$(asset_digest styles.css)" EXPECTED_DIGEST_MANIFEST="$(asset_digest "$MANIFEST_ASSET")" for pair in "main.js:$EXPECTED_DIGEST_MAIN" "styles.css:$EXPECTED_DIGEST_STYLES" "$MANIFEST_ASSET:$EXPECTED_DIGEST_MANIFEST"; do digest="${pair#*:}" asset="${pair%%:*}" if [ -z "$digest" ] || [ "${digest#sha256:}" = "$digest" ]; then echo "Missing or non-sha256 digest for $asset: '$digest'" >&2 exit 1 fi done echo "Relay beta release: $VERSION" echo "Published: $PUBLISHED_AT" echo "Vault: $VAULT" echo "Plugin folder: $PLUGIN_DIR" echo "Backup folder: $BACKUP_DIR" echo "Expected digests:" printf " %-18s %s\n" "main.js" "$EXPECTED_DIGEST_MAIN" printf " %-18s %s\n" "styles.css" "$EXPECTED_DIGEST_STYLES" printf " %-18s %s\n" "$MANIFEST_ASSET" "$EXPECTED_DIGEST_MANIFEST" echo "Will write: main.js, styles.css, manifest.json" echo "Will preserve: data.json" if [ -d "$PLUGIN_DIR" ]; then echo "Will back up (selective, only these files if present):" for f in main.js styles.css manifest.json data.json; do [ -f "$PLUGIN_DIR/$f" ] && echo " $PLUGIN_DIR/$f" done else echo "Will back up: nothing (fresh install)" fi if [ "$DRY_RUN" = "1" ]; then echo "RELAY_DRY_RUN=1; downloading and verifying without writing to the plugin folder." elif [ "${RELAY_CONFIRM:-}" = "INSTALL" ]; then echo "RELAY_CONFIRM=INSTALL detected; proceeding without interactive prompt." else printf "Type INSTALL to continue: " read -r CONFIRM if [ "$CONFIRM" != "INSTALL" ]; then echo "Cancelled." exit 1 fi fi BASE="https://github.com/$REPO/releases/download/$VERSION" curl -fsSL "$BASE/main.js" -o "$TMPDIR/main.js" curl -fsSL "$BASE/styles.css" -o "$TMPDIR/styles.css" curl -fsSL "$BASE/$MANIFEST_ASSET" -o "$TMPDIR/$MANIFEST_ASSET" verify_digest() { local file="$1" local expected="$2" local expected_hex="${expected#sha256:}" local actual actual="$(sha256_of "$file")" if [ "$actual" != "$expected_hex" ]; then echo "SHA-256 mismatch for $(basename "$file"):" >&2 echo " expected $expected_hex" >&2 echo " actual $actual" >&2 exit 1 fi echo "Verified $(basename "$file") $actual" } verify_digest "$TMPDIR/main.js" "$EXPECTED_DIGEST_MAIN" verify_digest "$TMPDIR/styles.css" "$EXPECTED_DIGEST_STYLES" verify_digest "$TMPDIR/$MANIFEST_ASSET" "$EXPECTED_DIGEST_MANIFEST" jq --arg expected "$VERSION" ' if .id == "system3-relay" then .version = $expected else error("Unexpected plugin id: \(.id)") end ' "$TMPDIR/$MANIFEST_ASSET" > "$TMPDIR/manifest.staged.json" mv -f "$TMPDIR/manifest.staged.json" "$TMPDIR/manifest.json" echo "Verified id=system3-relay; wrote manifest.json with version $VERSION (from $MANIFEST_ASSET)" if [ "$DRY_RUN" = "1" ]; then echo "DRY RUN: all assets downloaded and verified. Would have installed:" echo " $PLUGIN_DIR/main.js" echo " $PLUGIN_DIR/styles.css" echo " $PLUGIN_DIR/manifest.json" echo "Plugin folder was not modified. No backup was taken. Exiting." exit 0 fi if [ -d "$PLUGIN_DIR" ]; then mkdir -p "$BACKUP_DIR" echo "Backing up to $BACKUP_DIR:" for f in main.js styles.css manifest.json data.json; do if [ -f "$PLUGIN_DIR/$f" ]; then cp "$PLUGIN_DIR/$f" "$BACKUP_DIR/$f" echo " $f" fi done else echo "Fresh install: no existing plugin folder, no backup taken." fi STAGING="$PLUGIN_DIR/.relay-install-staging-$STAMP" mkdir -p "$STAGING" cp "$TMPDIR/main.js" "$STAGING/main.js" cp "$TMPDIR/styles.css" "$STAGING/styles.css" cp "$TMPDIR/manifest.json" "$STAGING/manifest.json" mv -f "$STAGING/main.js" "$PLUGIN_DIR/main.js" mv -f "$STAGING/styles.css" "$PLUGIN_DIR/styles.css" mv -f "$STAGING/manifest.json" "$PLUGIN_DIR/manifest.json" rmdir "$STAGING" STAGING="" echo "Installed Relay $VERSION in $PLUGIN_DIR" if [ -d "$BACKUP_DIR" ]; then echo "Backup of replaced files is in $BACKUP_DIR" fi echo "This did not replace Relay settings stored in data.json." if command -v obsidian >/dev/null 2>&1; then ( cd "$VAULT" RELAY_ENABLED="$(obsidian plugin id=system3-relay 2>/dev/null | awk -F '\t' '$1 == "enabled" { print $2 }' || true)" if [ "$RELAY_ENABLED" = "true" ]; then obsidian plugin:disable id=system3-relay sleep 2 else echo "Relay was not enabled before install; enabling it now." fi obsidian plugin:enable id=system3-relay ) && echo "Restarted Relay via Obsidian CLI." && exit 0 echo "Obsidian CLI exists, but the plugin disable/enable cycle failed. Obsidian may not be running with this vault open, the CLI may not be enabled, or Relay may need manual activation." >&2 fi echo "In Obsidian, disable then re-enable Relay in Community plugins (or run 'Reload app without saving' from the command palette)." ``` ## Roll back an agent install If the direct agent install is not usable, restore the files from ` /.obsidian/.relay-beta-backups/system3-relay- /` back into ` /.obsidian/plugins/system3-relay/`. Run the commands below for the timestamp you want to restore, skipping any file the backup directory does not contain: ```bash BACKUP_DIR=" /.obsidian/.relay-beta-backups/system3-relay- " PLUGIN_DIR=" /.obsidian/plugins/system3-relay" [ -f "$BACKUP_DIR/main.js" ] && cp "$BACKUP_DIR/main.js" "$PLUGIN_DIR/main.js" [ -f "$BACKUP_DIR/styles.css" ] && cp "$BACKUP_DIR/styles.css" "$PLUGIN_DIR/styles.css" [ -f "$BACKUP_DIR/manifest.json" ] && cp "$BACKUP_DIR/manifest.json" "$PLUGIN_DIR/manifest.json" [ -f "$BACKUP_DIR/data.json" ] && cp "$BACKUP_DIR/data.json" "$PLUGIN_DIR/data.json" ``` After restoring, disable then re-enable Relay in Community plugins, or run `Reload app without saving`, so Obsidian picks up the previous code. ## Report problems Use the Obsidian command `Relay: Send bug report` when available. If that does not work, post in the `new-sync-beta` channel in the [Relay Discord](https://discord.relay.md). Agent install instructions You are a local coding agent running on the same computer as the user's Obsidian vault. Install the newest Relay beta release for the Obsidian community plugin id system3-relay . Before you start Relay beta releases are published at No-Instructions/Relay releases . This install copies verified release files into the user's vault at <vault>/.obsidian/plugins/system3-relay . Only modify: <vault>/.obsidian/plugins/system3-relay <vault>/.obsidian/.relay-beta-backups Procedure Get the absolute path to the user's Obsidian vault. If the user does not provide it, inspect Obsidian's local vault registry and then ask the user to confirm the selected vault before writing. Common registry locations: macOS: ~/Library/Application Support/obsidian/obsidian.json Windows: %APPDATA%\Obsidian\obsidian.json Linux: ~/.config/obsidian/obsidian.json If multiple registry entries exist, prefer the one marked open: true , then confirm the selected vault with the user. Reason: the install target is inside that vault, and users may have more than one vault. Verify <vault>/.obsidian exists. Stop if it does not. Reason: this prevents writing plugin files into the wrong directory. Query https://api.github.com/repos/No-Instructions/Relay/releases?per_page=50 . Reason: the GitHub Releases API contains the release metadata, asset URLs, and SHA-256 digests. Among releases where draft is false and prerelease is true and assets include main.js , styles.css , and a manifest ( manifest.json or manifest-beta.json ), select the one with the newest published_at . Do not filter on the tag name. Reason: Relay betas have shipped under more than one tag convention — release candidates like 0.8.0-rc11 , and plain versions built from main like 0.8.4 . Selecting by the prerelease flag, the required assets, and publish date finds the true latest beta no matter how the tag is named, so this does not go stale when the convention changes again. Choose the manifest asset: prefer manifest.json if the release has it, otherwise use manifest-beta.json . Read the digest field for main.js , styles.css , and the chosen manifest asset. Reason: GitHub's digest is the source of truth for verifying each downloaded file, and different beta releases ship the manifest under different asset names. Prepare PLUGIN_DIR , BACKUP_ROOT , BACKUP_DIR , and STAGING . Reason: explicit paths make the install auditable and keep writes within the allowed locations. Check whether the official Obsidian CLI is available with command -v obsidian . Reason: Obsidian must restart plugin code after the file install, and checking for the CLI now prevents defaulting to a manual restart later. Show the user the selected release, publish date, vault path, plugin path, backup path, expected SHA-256 digests, file list, and whether Obsidian CLI restart is available. If the CLI is available, say the install will use the CLI to disable Relay, wait briefly for teardown, then enable Relay after the files are written. If the CLI is not available, say manual reload will be needed. Do not write anything until the user explicitly approves. Reason: this is a prerelease install that modifies files in the user's vault. Download main.js , styles.css , and the chosen manifest asset into a temporary directory. Reason: failed downloads must not leave the installed plugin half-updated. Verify each downloaded asset's SHA-256 against the expected digest from the API. Stop on any mismatch. Reason: a mismatch means the downloaded file is not the expected release asset. Verify the downloaded manifest asset has id set to system3-relay . Reason: this prevents installing the wrong plugin manifest. Set the manifest's version field to the selected release tag, then save it as manifest.json . Do this regardless of the version the downloaded manifest already declares. Reason: the version field in Relay's beta manifests is not reliable — release candidates have carried an old stable version (for example 0.7.4 ), and within a single release the manifest.json and manifest-beta.json assets can declare different versions. The release tag is the one authoritative version, and Obsidian reads the local plugin folder's manifest.json to report what is installed. If PLUGIN_DIR already exists, create BACKUP_DIR and copy main.js , styles.css , manifest.json , and data.json into it, skipping any that are not present. Reason: rollback only needs the files being replaced plus settings, and data.json must be preserved. Create STAGING inside PLUGIN_DIR . Copy verified main.js , verified styles.css , and rewritten manifest.json into STAGING . Reason: staging keeps the final write step small and avoids a plugin folder with a mix of downloaded and missing files. Move main.js , styles.css , and manifest.json from STAGING into PLUGIN_DIR . Reason: this completes the direct plugin install. Confirm data.json , if present, was not replaced. Reason: data.json contains existing Relay settings. Restart Relay in Obsidian. If step 7 found the official Obsidian CLI, first try a full disable/enable cycle: obsidian plugin:disable id=system3-relay , wait at least 2 seconds, then obsidian plugin:enable id=system3-relay . Do not assume a running Obsidian app is enough; the user may need to enable the CLI in Obsidian settings first. Use the id= prefix; command forms like obsidian plugin:disable system3-relay are not valid. If the CLI is unavailable or the disable/enable cycle fails, tell the user to disable then re-enable Relay in Community plugins, or run Reload app without saving from the command palette. Reason: Obsidian must unload old plugin code before the new beta is active. A disable/enable cycle gives Relay time to tear down sockets, listeners, and timers before loading the replacement code. Reference implementation This shell script is not required. The agent may use other tooling as long as it follows the contract above. If using the script, run it first with RELAY_DRY_RUN=1 to preview the selected release, expected writes, and digest verification. After the user approves, run with RELAY_CONFIRM=INSTALL to skip the interactive prompt. # Agents: set VAULT to the absolute path of the target Obsidian vault before running. VAULT="/absolute/path/to/your/vault" REPO="No-Instructions/Relay" set -euo pipefail if [ "$VAULT" = "/absolute/path/to/your/vault" ]; then echo "Set VAULT to the absolute path of the Obsidian vault before running." >&2 exit 1 fi if [ ! -d "$VAULT/.obsidian" ]; then echo "Refusing to continue: $VAULT does not contain a .obsidian folder" >&2 exit 1 fi for tool in curl jq; do if ! command -v "$tool" >/dev/null 2>&1; then echo "Missing required tool: $tool" >&2 exit 1 fi done if command -v sha256sum >/dev/null 2>&1; then SHA256_CMD="sha256sum" elif command -v shasum >/dev/null 2>&1; then SHA256_CMD="shasum -a 256" else echo "Missing SHA-256 utility: need sha256sum or shasum" >&2 exit 1 fi sha256_of() { $SHA256_CMD "$1" | awk '{print $1}' } PLUGIN_DIR="$VAULT/.obsidian/plugins/system3-relay" BACKUP_ROOT="$VAULT/.obsidian/.relay-beta-backups" STAMP="$(date +%Y%m%d-%H%M%S)" BACKUP_DIR="$BACKUP_ROOT/system3-relay-$STAMP" TMPDIR="$(mktemp -d)" STAGING="" cleanup() { [ -n "${TMPDIR:-}" ] && rm -rf "$TMPDIR" [ -n "${STAGING:-}" ] && [ -d "$STAGING" ] && rm -rf "$STAGING" return 0 } trap cleanup EXIT DRY_RUN="${RELAY_DRY_RUN:-0}" RELEASES_JSON="$TMPDIR/releases.json" curl -fsSL "https://api.github.com/repos/$REPO/releases?per_page=50" -o "$RELEASES_JSON" VERSION="$(jq -r ' map(select(.draft == false and .prerelease == true)) | map(select( ([.assets[].name] | contains(["main.js"])) and ([.assets[].name] | contains(["styles.css"])) and ([.assets[].name] | (contains(["manifest.json"]) or contains(["manifest-beta.json"]))) )) | sort_by(.published_at) | reverse | .[0].tag_name // empty ' "$RELEASES_JSON")" if [ -z "$VERSION" ]; then echo "No prerelease found with required Relay beta assets" >&2 exit 1 fi PUBLISHED_AT="$(jq -r --arg version "$VERSION" ' (.[] | select(.tag_name == $version) | .published_at) // "unknown" ' "$RELEASES_JSON")" asset_digest() { local asset_name="$1" jq -r --arg version "$VERSION" --arg asset "$asset_name" ' (.[] | select(.tag_name == $version) | .assets[] | select(.name == $asset) | .digest) // empty ' "$RELEASES_JSON" } # Prefer the modern manifest.json asset; fall back to the older manifest-beta.json. MANIFEST_ASSET="manifest.json" if [ -z "$(asset_digest "$MANIFEST_ASSET")" ]; then MANIFEST_ASSET="manifest-beta.json" fi EXPECTED_DIGEST_MAIN="$(asset_digest main.js)" EXPECTED_DIGEST_STYLES="$(asset_digest styles.css)" EXPECTED_DIGEST_MANIFEST="$(asset_digest "$MANIFEST_ASSET")" for pair in "main.js:$EXPECTED_DIGEST_MAIN" "styles.css:$EXPECTED_DIGEST_STYLES" "$MANIFEST_ASSET:$EXPECTED_DIGEST_MANIFEST"; do digest="${pair#*:}" asset="${pair%%:*}" if [ -z "$digest" ] || [ "${digest#sha256:}" = "$digest" ]; then echo "Missing or non-sha256 digest for $asset: '$digest'" >&2 exit 1 fi done echo "Relay beta release: $VERSION" echo "Published: $PUBLISHED_AT" echo "Vault: $VAULT" echo "Plugin folder: $PLUGIN_DIR" echo "Backup folder: $BACKUP_DIR" echo "Expected digests:" printf " %-18s %s\n" "main.js" "$EXPECTED_DIGEST_MAIN" printf " %-18s %s\n" "styles.css" "$EXPECTED_DIGEST_STYLES" printf " %-18s %s\n" "$MANIFEST_ASSET" "$EXPECTED_DIGEST_MANIFEST" echo "Will write: main.js, styles.css, manifest.json" echo "Will preserve: data.json" if [ -d "$PLUGIN_DIR" ]; then echo "Will back up (selective, only these files if present):" for f in main.js styles.css manifest.json data.json; do [ -f "$PLUGIN_DIR/$f" ] && echo " $PLUGIN_DIR/$f" done else echo "Will back up: nothing (fresh install)" fi if [ "$DRY_RUN" = "1" ]; then echo "RELAY_DRY_RUN=1; downloading and verifying without writing to the plugin folder." elif [ "${RELAY_CONFIRM:-}" = "INSTALL" ]; then echo "RELAY_CONFIRM=INSTALL detected; proceeding without interactive prompt." else printf "Type INSTALL to continue: " read -r CONFIRM if [ "$CONFIRM" != "INSTALL" ]; then echo "Cancelled." exit 1 fi fi BASE="https://github.com/$REPO/releases/download/$VERSION" curl -fsSL "$BASE/main.js" -o "$TMPDIR/main.js" curl -fsSL "$BASE/styles.css" -o "$TMPDIR/styles.css" curl -fsSL "$BASE/$MANIFEST_ASSET" -o "$TMPDIR/$MANIFEST_ASSET" verify_digest() { local file="$1" local expected="$2" local expected_hex="${expected#sha256:}" local actual actual="$(sha256_of "$file")" if [ "$actual" != "$expected_hex" ]; then echo "SHA-256 mismatch for $(basename "$file"):" >&2 echo " expected $expected_hex" >&2 echo " actual $actual" >&2 exit 1 fi echo "Verified $(basename "$file") $actual" } verify_digest "$TMPDIR/main.js" "$EXPECTED_DIGEST_MAIN" verify_digest "$TMPDIR/styles.css" "$EXPECTED_DIGEST_STYLES" verify_digest "$TMPDIR/$MANIFEST_ASSET" "$EXPECTED_DIGEST_MANIFEST" jq --arg expected "$VERSION" ' if .id == "system3-relay" then .version = $expected else error("Unexpected plugin id: \(.id)") end ' "$TMPDIR/$MANIFEST_ASSET" > "$TMPDIR/manifest.staged.json" mv -f "$TMPDIR/manifest.staged.json" "$TMPDIR/manifest.json" echo "Verified id=system3-relay; wrote manifest.json with version $VERSION (from $MANIFEST_ASSET)" if [ "$DRY_RUN" = "1" ]; then echo "DRY RUN: all assets downloaded and verified. Would have installed:" echo " $PLUGIN_DIR/main.js" echo " $PLUGIN_DIR/styles.css" echo " $PLUGIN_DIR/manifest.json" echo "Plugin folder was not modified. No backup was taken. Exiting." exit 0 fi if [ -d "$PLUGIN_DIR" ]; then mkdir -p "$BACKUP_DIR" echo "Backing up to $BACKUP_DIR:" for f in main.js styles.css manifest.json data.json; do if [ -f "$PLUGIN_DIR/$f" ]; then cp "$PLUGIN_DIR/$f" "$BACKUP_DIR/$f" echo " $f" fi done else echo "Fresh install: no existing plugin folder, no backup taken." fi STAGING="$PLUGIN_DIR/.relay-install-staging-$STAMP" mkdir -p "$STAGING" cp "$TMPDIR/main.js" "$STAGING/main.js" cp "$TMPDIR/styles.css" "$STAGING/styles.css" cp "$TMPDIR/manifest.json" "$STAGING/manifest.json" mv -f "$STAGING/main.js" "$PLUGIN_DIR/main.js" mv -f "$STAGING/styles.css" "$PLUGIN_DIR/styles.css" mv -f "$STAGING/manifest.json" "$PLUGIN_DIR/manifest.json" rmdir "$STAGING" STAGING="" echo "Installed Relay $VERSION in $PLUGIN_DIR" if [ -d "$BACKUP_DIR" ]; then echo "Backup of replaced files is in $BACKUP_DIR" fi echo "This did not replace Relay settings stored in data.json." if command -v obsidian >/dev/null 2>&1; then ( cd "$VAULT" RELAY_ENABLED="$(obsidian plugin id=system3-relay 2>/dev/null | awk -F '\t' '$1 == "enabled" { print $2 }' || true)" if [ "$RELAY_ENABLED" = "true" ]; then obsidian plugin:disable id=system3-relay sleep 2 else echo "Relay was not enabled before install; enabling it now." fi obsidian plugin:enable id=system3-relay ) && echo "Restarted Relay via Obsidian CLI." && exit 0 echo "Obsidian CLI exists, but the plugin disable/enable cycle failed. Obsidian may not be running with this vault open, the CLI may not be enabled, or Relay may need manual activation." >&2 fi echo "In Obsidian, disable then re-enable Relay in Community plugins (or run 'Reload app without saving' from the command palette)." Roll back an agent install If the direct agent install is not usable, restore the files from <vault>/.obsidian/.relay-beta-backups/system3-relay-<timestamp>/ back into <vault>/.obsidian/plugins/system3-relay/ . Run the commands below for the timestamp you want to restore, skipping any file the backup directory does not contain: BACKUP_DIR="<vault>/.obsidian/.relay-beta-backups/system3-relay-<timestamp>" PLUGIN_DIR="<vault>/.obsidian/plugins/system3-relay" [ -f "$BACKUP_DIR/main.js" ] && cp "$BACKUP_DIR/main.js" "$PLUGIN_DIR/main.js" [ -f "$BACKUP_DIR/styles.css" ] && cp "$BACKUP_DIR/styles.css" "$PLUGIN_DIR/styles.css" [ -f "$BACKUP_DIR/manifest.json" ] && cp "$BACKUP_DIR/manifest.json" "$PLUGIN_DIR/manifest.json" [ -f "$BACKUP_DIR/data.json" ] && cp "$BACKUP_DIR/data.json" "$PLUGIN_DIR/data.json" After restoring, disable then re-enable Relay in Community plugins, or run Reload app without saving , so Obsidian picks up the previous code. Report problems Use the Obsidian command Relay: Send bug report when available. If that does not work, post in the new-sync-beta channel in the Relay Discord . (() => { const payload = document.getElementById('relay-agent-instructions'); const buttons = Array.from(document.querySelectorAll('[data-copy-relay-agent-instructions]')); const latestTag = document.getElementById('latest-relay-beta-tag'); const releasesUrl = 'https://api.github.com/repos/No-Instructions/Relay/releases?per_page=50'; const requiredAssets = ['main.js', 'styles.css']; function chooseLatestBeta(releases) { return releases .filter((release) => { if (release.draft || !release.prerelease) return false; const assetNames = new Set((release.assets || []).map((asset) => asset.name)); if (!requiredAssets.every((name) => assetNames.has(name))) return false; return assetNames.has('manifest.json') || assetNames.has('manifest-beta.json'); }) .sort((a, b) => new Date(b.published_at) - new Date(a.published_at))[0]; } if (latestTag) { fetch(releasesUrl, { headers: { Accept: 'application/vnd.github+json' } }) .then((response) => { if (!response.ok) throw new Error(`GitHub returned ${response.status}`); return response.json(); }) .then((releases) => { const latest = chooseLatestBeta(releases); if (!latest) throw new Error('No valid beta release found'); latestTag.textContent = latest.tag_name; }) .catch(() => { const fallback = document.createElement('span'); fallback.textContent = 'open Relay releases and choose the newest prerelease'; latestTag.replaceWith(fallback); }); } if (!payload || buttons.length === 0) return; async function copyText(text) { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(text); return; } const temp = document.createElement('textarea'); temp.value = text; temp.setAttribute('readonly', ''); temp.style.position = 'fixed'; temp.style.left = '-9999px'; document.body.appendChild(temp); temp.select(); document.execCommand('copy'); document.body.removeChild(temp); } buttons.forEach((button) => { button.addEventListener('click', async () => { const status = button.parentElement.querySelector('.copy-agent-status'); try { await copyText(payload.value.trim() + '\n'); if (status) status.textContent = 'Copied.'; } catch { if (status) status.textContent = 'Copy failed. Select the agent instructions below instead.'; } }); }); })(); (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Invite someone to collaborate URL: https://docs.relay.md/guides/invite-a-collaborator/ Invite someone to collaborate On this page To collaborate with someone in Relay, you put your work in a Shared Folder on a Relay Server, then invite them to that Relay Server with a Share Key . They paste the key into Relay to join, add the Shared Folder to their vault, and your edits sync in real time. You do not need Discord, a separate account system, or an email invite. Everything happens inside Relay's settings. Watch the flow This video shows the whole flow: an owner copies the Share Key, and a collaborator joins and adds the Shared Folder. Download the video . Before you start You and your collaborator each need Obsidian with the Relay plugin installed. New to Relay? Start with the Introduction . You need a Relay Server with at least one Shared Folder. If you have not made one yet, see Create a Shared Folder with private access . Relay's free tier supports up to 3 users per Relay Server. For larger teams, or to sync images, PDFs, and other file types, see Upgrade to Relay for teams . Put your work in a Shared Folder Anything inside a Shared Folder on your Relay Server is shared with the people on that server — unless the folder uses private access , which limits it to selected people. Drag the notes or Canvas you want to collaborate on into a Shared Folder. Because real-time collaboration is powerful, keep a backup copy of anything important before you share it, especially when you are trying a beta feature like Canvas multiplayer . Invite your collaborator 1. Open your Relay Server Open Relay settings with the Relay ribbon icon in Obsidian's far-left sidebar. Under Relay Servers , click the gear icon for the server you want to share. Click the gear icon next to your Relay Server. 2. Copy the Share Key On the server's settings page, scroll to the Sharing section and make sure Enable key sharing is on. Then click the eye icon next to the Share Key to reveal it, and copy it. Click the eye icon to reveal the Share Key , then copy it. Treat it like a password — anyone who has it can join your Relay Server. Turn Enable key sharing off once everyone has joined, or use Rotate key to replace it. 3. Send the Share Key to your collaborator Send the key to your collaborator any way you like — a message, an email, however you normally reach them. They do not need Discord or any other account to join your Relay Server. Your collaborator joins Your collaborator does these steps on their own device. 1. Install Obsidian and Relay If they are new to Relay, they install Obsidian and the Relay plugin first. See the Introduction for the full setup. 2. Enter the Share Key In Relay settings, under Join a Relay Server , they paste the key into the Enter share key field and click Join . The Join a Relay Server section is at the top of Relay settings. Paste the Share Key and click Join . 3. Add the Shared Folder to the vault After joining, your collaborator opens the Relay Server from their Relay Servers list. The Shared Folder is listed there — they click the Download button next to it to add it to their vault. Relay syncs the folder locally, and you are collaborating in real time. Click the Download button next to the Shared Folder to add it to your vault. Both people now appear under Users on the Relay Server. Troubleshooting My collaborator joined, but our edits aren't showing up First, make sure each person has actually added the Shared Folder to their own vault — joining the Relay Server is not enough on its own. On the Relay Server's settings page, the Shared Folder has a Download button to add it locally. If the folder is added on both sides and edits still aren't syncing, a few things can jog it into action: Both people reload Obsidian: open the command palette and run Reload app without saving . Right-click the Shared Folder in your file list and choose Relay: Sync . Make a fresh copy of the file from your vault and drag the copy into the Shared Folder. Do we need Discord to collaborate? No. The Relay Discord is our community and support server, and it is a great place to ask questions, but it has nothing to do with joining a Relay Server. Your collaborator joins entirely inside Relay using the Share Key. We're collaborating on a Canvas Real-time Canvas collaboration is currently a beta feature and needs to be enabled. See Canvas multiplayer for how to turn it on and what to expect. I want to control who can see each folder By default, everyone on a Relay Server can access its Shared Folders. To limit a folder to specific people, use a Shared Folder with private access — see Create a Shared Folder with private access . Related guides Create a Shared Folder with private access Upgrade to Relay for teams Canvas multiplayer Introduction (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Obsidian for work URL: https://docs.relay.md/guides/obsidian-for-work/ Obsidian for work On this page Can I use Obsidian at work? Yes, you can use Obsidian for work with your teammates. Many advanced teams are already doing so with Relay. There are significant advantages to using Obsidian+Relay over traditional tools like Google Docs and Notion. There are also drawbacks. You get the tool you love, but your team needs to learn it (vs everyone knows Google Docs) You get the power and flexibility of local files, but you make more decisions You can get total privacy with self-hosting, but that requires setup (vs cloud is instant) This guide explains what you need to know. Why use Obsidian at work? Knowledge workers want to use Obsidian at work for the same reasons they use it personally: Local files (file over app: longevity and capabilities) Graph structure Extensibility (plugins, editors like VS Code, terminal scripts, language models, etc) They want the best knowledge tools at work where the stakes are high. The challenge: Obsidian is single-player What's missing from Obsidian is multiplayer. You can use Obsidian Sync or Google Drive, but you'll risk collisions and lost data if two people edit offline or at the same time. You can use Git, but you'll deal with merges. In either case, you won't get live presence and real-time cursors. The ideal would be a Google Docs-like collaboration UX, inside Obsidian. That's what Relay does. Using CRDT technology (Yjs), it lets everyone work on local files simultaneously while guaranteeing they'll converge to the same document. Is it real-time? Yes, it's real-time, and our users frequently report being surprised at how fast it is. If you and your collaborators are online and editing at the same time, you can watch one another's cursors move with each keystroke. Each user works with a local file (the Obsidian way), which means you don't need to receive anything from a remote location in order to work. Relay streams your updates in the background. The result is you never have to wait for a connection to make edits, and you have live presence with your collaborators as long as you're both online. What about offline? Relay has excellent support for offline editing. Whether you're offline or not, Relay tracks every change as an operation and stores them in a local database. When you're back online, operations stream up to the server and then are relayed on to collaborators. CRDT operations are commutative (any order) and idempotent (duplicates are fine). So you can work offline as much as you like, and the CRDT ensures that when you come back online and sync your operations, everyone will converge to the same document. What about conflicts and merges? CRDTs are 'conflict-free' in the technical sense — they make all merges automatically — but they can't resolve social disagreements. For example: suppose you and your partner have a shopping list containing "milk". While offline, you specify "oat" while your partner specifies "almond". When you come back online you'll get something like "oatalmond milk." Changes merged automatically and you're guaranteed to see the same document — but you'll have to resolve the milk decision socially. One other conflict type: if you edit files on disk while Relay isn't running, Relay will ask what to do when it notices the difference. What about version history? These are local files. We recommend you use Git for version history. The Git plugin for Obsidian is excellent and can be set to commit every five minutes. In addition, Obsidian has a core File Recovery plugin that can be used to recover past versions of a file. Is it private? Is it secure? Can I self-host? Obsidian alone is private — like a house with no windows or doors. Add collaboration and you need a server to coordinate edits. That server introduces questions: who controls it? Are they trustworthy? What can they see if trust isn't enough? Relay offers three deployment options with different privacy guarantees: Cloud (we host) Fastest setup Our company could see your data if compelled to by a court. This has never happened. We do not read, sell, or train on your data. Hybrid (you host relay server, we host identity) Document content never touches our servers — we can't see it even if we wanted to We see limited metadata Good for teams wanting privacy guarantees Air-gapped (you host everything) We can't see any data, not even metadata Total control, requires most setup Tradeoff: closed collaboration network — can only share with people on your deployment Good for the most security-sensitive organizations All options encrypt data in transit and at rest. We do not offer end-to-end encryption. See Hosting options and Pricing for details. Comments and notifications? Obsidian doesn't have native comments or notifications. This is part of the flexibility tradeoff — you get more power but need to figure out your own solutions. You can use plugins, write custom scripts, or simply develop team social protocols that work for you. For comments: Because files are markdown, you can create whatever system works for you. Internally at System 3, we use hotkeys to insert tags with highlighting: ==@Matt at 2025-10-15 Wed 05:15pm: This is a comment== For notifications: We handle this socially. If someone updates a doc and wants it seen, they ping in Slack or add a line to the next day's standup agenda. It works well for us and minimizes notification spam. Teams can also create custom file watchers and Slack or Discord bots. Task and project management? With plugins like TaskNotes, Dataview, and Bases, some teams manage projects entirely in Obsidian. But if task management is your primary need, you might still use a dedicated tool like Asana or Linear. Obsidian's strength is networked thinking and knowledge management. Task workflows are quickly improving, but still require considerable attention to set up. Cost Relay has a free plan, but most business users will want to use the product on one of our paid tiers. See our pricing page for details on our plans. Try Relay Install from Obsidian community plugins. You can start with our free plan to check it out, and invite your team when you're ready. If you have questions about deployment, security, or enterprise features, contact us . (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Create a Shared Folder with private access URL: https://docs.relay.md/guides/private-shared-folders/ Create a Shared Folder with private access On this page A Shared Folder lets you share a folder and everything inside it with people on a Relay Server. A Shared Folder with private access is shared only with selected Relay Server users. The Private toggle appears only on Relay Servers whose subscription includes private access for Shared Folders. If you upgraded Relay but do not see the toggle, make sure you are sharing from the Relay Server that has the subscription. Plans apply to Relay Servers, not to your user account. Watch the flow This video shows how to create a Shared Folder with private access in Relay settings. Download the video . Before you start The Relay Server must be on a paid plan that includes private access for Shared Folders. If needed, see our pricing plans . You must be a Member or Owner on that Relay Server. Relay Server Members can create Shared Folders with private access; you do not need to be the Relay Server owner. Use a current version of the Relay Obsidian plugin. See Update Relay , or for the adventurous, Get the latest Relay beta . Create the Shared Folder with private access 1. Open the paid Relay Server Open Relay settings in Obsidian and select a Relay Server that has a plan with private access. Private access for Shared Folders is enabled per paid Relay Server, not globally on your account. 2. Click Share local folder In the Relay Server settings, click Share local folder . Relay opens the folder selector first. The private access controls are behind this selector, and they may be hidden if your folder list is long. Choose or create the folder you want to share before looking for the Private toggle. The folder selector appears in front of the share dialog. Select the folder first. 3. Turn on Private After selecting the folder, turn on Private . When Private is on, only selected Relay Server users can access this Shared Folder. The Private toggle appears after the folder is selected. 4. Add the users who should have access Click Add Users , then select the users who should be able to access the Shared Folder. Relay adds you automatically as the Shared Folder owner. Select the other Relay Server users who should have access. Select the Relay Server users who should have access to the folder. 5. Click Share Click Share to create the Shared Folder. The folder appears under Shared Folders on this Relay Server . The Shared Folder appears on the Relay Server after sharing. Troubleshooting I do not see the Private toggle Select a folder first. Relay opens the folder selector in front of the share dialog, and a long folder list can hide the Private toggle behind it. Choose or create the local folder you want to share, then check the share dialog again. Check that you selected a Relay Server with a plan that includes private access. A paid subscription applies to one Relay Server, not to every Relay Server connected to your user account. If you upgraded a different server, switch to that server or upgrade this Relay Server . If you are on the right server and still do not see the toggle, update the Relay plugin . Do I need to be the Relay Server owner? No. Relay Server Members can create Shared Folders with private access on a Relay Server that supports private access. The creator is added automatically as the Shared Folder owner. I do not see the person I want to add Private access is selected from the users already on that Relay Server. Add the person to the Relay Server first, then create or edit the Shared Folder access list. Can I set per-folder view and edit roles? Not yet. Private access currently controls whether a Relay Server user has access to the Shared Folder. A selected user can read and write files in that Shared Folder; a user who is not selected has no access. Relay does not currently support read-only access for Shared Folders. Use the Relay Server Users section for server-level user management. For private access to a Shared Folder, use the Private toggle and selected-user list. Related guides Upgrade to Relay for teams Update Relay Configure attachments for sharing (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Update Relay URL: https://docs.relay.md/guides/update-relay/ Update Relay On this page Keeping Relay updated ensures you have the latest features, bug fixes, and compatibility improvements. This guide covers how to check your current version and update to the latest release. Check latest version You can always find the latest Relay version at https://relay.md/relay/releases Update the Relay plugin Open Obsidian settings by clicking the settings icon (gear icon) at the bottom of the left panel. Navigate to Community plugins . Here you can see all your installed plugins with their current version numbers. Click Check for updates . This scans for available updates but doesn't install them automatically. If an update is available for Relay, click Update next to the Relay plugin to install it. After installing an update, reload Obsidian by opening the command palette ( Cmd+P on Mac, Ctrl+P on Windows/Linux) and selecting Reload app without saving . Tip: Obsidian saves your work automatically every few seconds, so using "Reload app without saving" is generally safe and faster than fully restarting. ![](/assets/CleanShot 2025-06-25 at 13.18.04.png) Why updates matter Staying current with Relay updates is important because: Bug fixes: Resolves sync issues, authentication problems, and other stability improvements Compatibility: Ensures Relay works properly with the latest Obsidian versions New features: Access to the latest collaboration and productivity enhancements Performance: Optimizations that make Relay faster and more reliable Troubleshooting update issues If you have trouble updating or the update doesn't seem to work: Restart Obsidian completely: Close Obsidian entirely and reopen it Check your internet connection: Updates require downloading new files Disable and re-enable: Try disabling Relay in Community plugins, then re-enabling it Manual reinstall: Uninstall and reinstall Relay from the Community plugins directory See also Install the latest Relay beta - Test the latest prerelease version with BRAT or a local agent Gray stack icon - Fix common issues after updates (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Upgrade to Relay for teams URL: https://docs.relay.md/guides/upgrade-to-relay-for-teams/ Upgrade to Relay for teams On this page Relay is entirely funded by subscriptions from our users. We don't sell your data or show you advertisements. If you like what we're doing and you want to see us continue, we'd love to have your support. Relay's free tier supports up to 3 users per server. When your team grows beyond that, or when you need to sync images, PDFs, and other file types, upgrading to Relay for Teams unlocks these capabilities. Follow these steps to upgrade your server to a paid subscription. Before you start You must be the Owner of the Relay Server to upgrade Have a payment method ready (credit/debit card) Current pricing available at relay.md/pricing Remember that the subscription applies to a single server, not to your vault or all servers associated with your account. Step-by-step upgrade process 1. Access Relay settings Access the Relay settings screen by clicking the Relay ribbon icon in the far-left sidebar. 2. Select your Relay Server In the Relay settings, you'll see a list of your servers. Click on the gear icon for the server you want to upgrade. 3. Hit the Upgrade button Scroll down to the Plan section, find the Upgrade button, and hit it. 4. Enter payment info and subscribe You'll be taken to a web page in your browser, where you can complete payment with Stripe. Enter your info and hit Subscribe to complete the upgrade. 5. Success screen and back to Obsidian If your purchase was successful, you'll see the success screen. You can now return to Obsidian and enjoy your paid tier access. We appreciate your support! What happens after upgrade Your Relay Server will immediately have all the features of the Team plan. Universal File Sync - Sync images, PDFs, videos, and other file types (not just markdown) Increased seats 10GB attachment storage - Binary files are stored on Relay servers and synced to all team members See https://relay.md/pricing for full list You can cancel your subscription at any time from your server settings. Troubleshooting Don't see the upgrade option? Make sure you're the server Owner, not just a Member Still need help? Join the Relay Discord for support. (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Using Relay with other sync services URL: https://docs.relay.md/guides/using-relay-with-other-sync-services/ Using Relay with other sync services On this page You cannot use Relay on the same content as other sync services like Obsidian Sync, iCloud, Dropbox, or Google Drive. If these services compete over the same content, you are likely to get conflicts and data loss. You can use multiple sync services in the same vault as long as they are working in different parts of the vault. This is the same requirement imposed by any sync service, including Obsidian Sync. The rule: no double coverage Safe setup: Use Relay for the shared project folders where you need true multiplayer For everything else that you want to sync between devices, use whatever sync service you want, including Relay (just set up a separate Relay Server), Obsidian Sync, or iCloud, etc. If using something other than Relay, make sure to exclude the Relay-covered folders from this service Double-check to make sure no folder or file is handled by both services Dangerous setup: Running a file sync service like Obsidian Sync on your entire vault, and running Relay on a folder within that vault ❌ (double coverage) How to set this up safely If you're adding Relay to a vault already synced by a device sync service like Obsidian Sync Choose which folders will use Relay - typically project or team folders Add those folders to your Relay Server as Shared Folders Exclude those folders from your existing sync service : Obsidian Sync exclusions If you use iCloud Drive, keep Relay Shared Folders outside iCloud-synced locations like Desktop, Documents, and iCloud Drive. Apple does not currently document a supported per-folder exclusion control for iCloud Drive; Apple's current guidance is to keep separate cloud services in separate locations on your Mac. Check your sync service's documentation for folder exclusion steps iCloud and .nosync Some macOS users append .nosync to a folder name to keep that folder out of iCloud Drive. Apple mentions .nosync in an archived iCloud developer guide , and Howard Oakley has a useful current explanation of iCloud Drive exclusions . Relay does not recommend .nosync as the default setup: it is not exposed as a normal iCloud Drive setting, and renaming a folder can break paths you already use in Obsidian or other apps. If you choose to use it anyway, treat it as an iCloud-specific workaround you need to verify yourself on every device. The safer Relay setup is to put Relay Shared Folders somewhere iCloud is not syncing. If you're not already using a device sync service Consider using Relay for your entire vault If you prefer two services, make sure to set up exclusions to abide by the 'no double coverage' rule: Exclude your Relay Shared Folders from the new sync service before enabling it Signs you have a sync service collision The most common symptom is missing contributions : You open a note that should have content, but it's blank A note has reverted to an old version, losing recent changes Content you or collaborators added has disappeared You may also see Relay's conflict resolution banner asking you to resolve merge conflicts. What to do if you're already in conflict Stop the conflict immediately : Exclude your Relay folders from the other sync service Check your files : Open shared documents and look for missing content or unexpected changes If you see conflicts : Use conflict resolution and version history tools: Use Relay's diff resolution tool, if presented. Use Obsidian's built-in File recovery tool (independent of Obsidian Sync. See docs: https://help.obsidian.md/plugins/file-recovery) Use your other sync service's version history tool (eg, here's documentation for Obsidian Sync's ) If content is missing : Check if you have recent backups from before the conflict started. Use Obsidian's built-in File recovery tool (https://help.obsidian.md/plugins/file-recovery). Why this happens Different sync services use different approaches to handle simultaneous changes. When two services try to sync the same files, they can get overwrite each other's changes or create race conditions that result in data loss. Each sync service assumes it's the authoritative source for your files. Running multiple services on the same content violates this assumption and creates unpredictable behavior. Need help? Join the Relay Discord for support. (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Real-time multiplayer vs repurposed file sync URL: https://docs.relay.md/how-relay-works/real-time-multiplayer-vs-repurposed-file-sync/ Real-time multiplayer vs repurposed file sync On this page In the Obsidian world, collaboration tools fall into three categories: File sync repurposed : Tools like Obsidian Sync, designed for one person across multiple devices, now used by teams Real-time multiplayer : Tools like Relay, built specifically for simultaneous collaborative editing Git-based : Version control systems designed for asynchronous collaboration through branching and merging The fundamental difference is how each handles conflicts arising from concurrent edits. Different philosophies about conflicts File sync tools were designed assuming conflicts are rare — a single person won't edit the same file on two devices simultaneously. This assumption breaks when these tools are used by teams. When conflicts do happen between team members, these tools use simple resolution like "last write wins" — silently dropping one collaborator's contributions — because they weren't built for this scenario. Real-time multiplayer tools assume conflicts are normal and frequent. They use specialized technology (like CRDTs) to merge concurrent edits automatically without data loss. Git-based systems assume work is mostly asynchronous — people work separately and merge intentionally. When conflicts arise during merging, the system preserves both versions and requires explicit human resolution. When it matters File sync repurposed Real-time multiplayer Git-based Two people edit same paragraph One person's work gets overwritten Both contributions preserved Merge conflict flagged for manual resolution See collaborator's changes After the entire file is synced Instantly as they type After they commit and push See where others are editing No Live cursors No How Relay solves this Relay uses CRDTs (Conflict-free Replicated Data Types) — a data structure designed specifically for merging concurrent edits. When two people type in the same paragraph: Each keystroke is captured as an update operation with metadata (position, timestamp, user) Operations are sent up instantly to the central Relay servers, then relayed on to collaborators the next time they are online On the collaborators' side, Relay processes the operations and from them replicates the document locally Everyone sees the same final result This happens seamlessly in the background. You just see live cursors and instant updates. Offline work is fully supported. CRDTs are designed such that the update operations are commutative — they can be processed in any order — and idempotent — duplicates of the same operation will be ignored. If you'd like to learn more, we recommend checking out Yjs , the open source CRDT that Relay uses, and a presentation by Cambridge researcher Martin Kleppmann called " CRDTs: the Hard Parts ". The complete collaboration stack For knowledge work teams, a great setup uses all three: Obsidian for thinking and editing Relay for Real-time multiplayer and active collaboration Git for version history and backup Relay offers a Git sync feature so that your Relay Server can automatically update eg a GitHub repo every time someone makes an edit. This is a paid feature. (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Introduction URL: https://docs.relay.md/introduction/ Introduction On this page Relay is an Obsidian plugin that enables real-time multiplayer collaboration on notes and Canvases. It's used by: knowledge workers in companies students and researchers in universities and labs tabletop gamers at home It is the most popular multiplayer solution in the Obsidian world. How is Relay different? Relay differs from other popular Obsidian collaboration tools like Obsidian Sync in that it uses a purpose-built, open-source collaboration system called a CRDT to support true real-time multiplayer. It's not just multiparty file sync . With Relay you can: Share specific folders from your vault while keeping the rest private Sync keystrokes instantly and see collaborators' cursors as they type Work offline and smoothly converge when you come back on Relay lets you keep what's great about Obsidian — markdown files in a local-first architecture — and add modern team collaboration. Is Relay free? Relay has a free tier and paid tiers. We believe, with Obsidian, that quality software deserves your hard-earned cash . By paying for Relay you're funding our small team to continue developing and maintaining what we endorse as a high-quality service. We do not sell your data and we do not look at it. See our privacy policy . We do not sell advertising. We are self-funded. Our revenue comes entirely from subscriptions from our customers. The paid tiers enable us to maintain a free tier, which makes the service accessible to students, hobbyists, and people just trying it out. Quick start Relay works on all major platforms, both desktop and mobile. In order to use Relay you need Obsidian. Download Obsidian here . Startup: Install Relay. Within Obsidian, (1) enable Community Plugins, (2) then browse for the Relay plugin, (3) Install it, (4) Enable it, and then (5) go to Options . For help, see Obsidian's guide to installing plugins . Create a Relay Server. First navigate to the Relay settings screen. Then click Create to create a new server, or enter a Share Key from your teammate to join an existing server. Add folders. From your Relay Server's settings screen, click Share local folder to select a folder from your vault and add it to the Relay Server. Add team members. Give collaborators your Relay Server's Share Key to invite them to the server. Key features Multiplayer markdown: Real-time collaboration on .md files with live cursors Shared folders: Choose folders from your vault and share them, including all of their subfolders Universal File Sync (paid feature): Sync images, pdfs, and arbitrary file types in addition to markdown files Canvas multiplayer (beta): Real-time collaboration on Obsidian Canvas files On-premise/self-hosted deployment (beta): Deploy Relay on your own infrastructure for complete control See our Pricing page for a more comprehensive list of features, and our Roadmap for a preview of what's to come. Need help? Join the Relay Discord community to chat with Relay users and staff (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Stack icon is gray URL: https://docs.relay.md/troubleshooting/stack-icon-gray/ Stack icon is gray On this page If your stack icon is gray, Relay cannot track changes properly. This means your edits won't sync to collaborators and you won't receive their updates. If you continue editing while the stack icon is gray, you'll likely see merge conflicts when Relay reconnects because it will detect mismatches between your editor and the local database. What the gray stack icon means The stack icon shows whether Relay is successfully tracking changes to the current note as CRDT updates. When it's gray, something has gone wrong with the local change tracking system. Relay works by keeping three things in sync: The content in your Obsidian editor The content stored on your hard disk The content in your local CRDT update database When these fall out of sync, the stack icon turns gray to alert you. Common causes Outdated software versions (Relay, Obsidian, or Obsidian installer) File sync conflicts between different services Other plugins interfering with file operations Solutions to try Work through these steps in order. Most problems resolve with the earlier steps. 1. Check for updates (try this first) Outdated software is the most common cause and best-bet way to resolve tracking issues. Update all three components: Update Relay: Go to Obsidian Settings → Community plugins Find Relay and check if there's an update available If so, click Update Latest version always listed at https://relay.md/relay/releases Update Obsidian app: Go to Settings → General Select "Check for updates" If updates are available, select "Relaunch" to apply them See Obsidian's update guide for detailed instructions Update Obsidian installer (Electron): Go to Settings → General Select "Check for updates" If updates are available for the Installer, you will need to download and install outside of Obsidian. To update the installer: Navigate to obsidian.md/download Select the "Download" button Close Obsidian if it's currently open Run the installer (you don't need to uninstall first) This updates the Electron framework and may be required for newer plugins or features After updating, restart Obsidian completely and check if the stack icon is now colored. 2. Check sync service conflicts If you're using other sync services (Obsidian Sync, iCloud, Dropbox, etc.), make sure they're not syncing the same folders as Relay. This can cause file conflicts that break tracking. See our guide on Using Relay with other sync services for setup instructions. 3. Check for conflicting plugins Some plugins can interfere with Relay's tracking. This includes plugins that have a special view, like Kanban, and plugins (or custom functions) that update note content automatically — such as if you have a plugin that updates frontmatter with the note's last updated date. Identify any such plugins Try disabling them Check if the stack icon becomes colored If not, try disabling ALL other plugins Check if the stack icon becomes colored 4. Reload Obsidian Open the command palette ( Cmd+P on Mac, Ctrl+P on Windows/Linux) Run Reload app without saving (Obsidian saves automatically many times per minute) Check if the stack icon becomes colored 5. Check authentication Click the Relay ribbon icon to open Relay settings If not signed in, log in If you have multiple accounts, make sure you're using the right one Even if auth looks fine, sometimes logging out and logging back in can resolve a silent authentication issue Check if the stack icon becomes colored 6. Toggle syncing For the individual note: Click the satellite icon in the note (top right) It should toggle from colored to gray Click it again to toggle back to colored For the folder: Right-click the Shared Folder in the left panel Select Disconnect Right-click again and select Connect 7. Restart Obsidian completely Quit Obsidian entirely (not just close the window) Restart Obsidian Check if the stack icon becomes colored 8. Disable and re-enable Relay Go to Obsidian Settings → Community plugins Find Relay and toggle it off Wait a few seconds, then toggle it back on Check if the stack icon becomes colored 9. Restart your machine Sometimes system-level issues can affect file tracking. Restart your computer and try again. If you still need help If none of these steps resolve the issue: Use the command palette to run Relay: Send bug report Join the Relay Discord for hands-on support When reporting the issue, include: Your versions of Relay, Obsidian, and operating system Screenshots of the gray stack icon What you were doing when the problem started Whether it affects all notes or just specific ones Any error messages you've seen (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })(); ## Understanding Relay's UI icons URL: https://docs.relay.md/user-interface/icons/ Understanding Relay's UI icons On this page Relay adds several icons to your Obsidian interface to give you important status information and quick access to controls. Stack icons (1, 3) The stack icons tell you whether or not Relay is successfully tracking changes to your files. On your local machine, Relay works by making sure three things stay in sync: the content you see in your Obsidian editor the content stored on your hard disk the content in your database of CRDT updates When Relay is successfully tracking updates in the editor and storing them in the CRDT database, the stack icon will be colored to indicate that Relay is tracking. This is the foundation of Relay's true multiplayer system. If these three things fall out of sync, a problem has occurred, and the stack icons will turn gray. Colored stack icon = Good. Relay is tracking your changes at the keystroke level and maintaining them in your local CRDT update database. Gray stack icon = Problem. Relay is not able to track your changes properly. See Gray stack icon troubleshooting . No stack icon = This note is not in a Shared Folder, or it's a file type that Relay doesn't support for CRDT tracking, or there's a problem. The icon in the note (3, in the diagram above) gives you status about the current note, and the icon in the folder tree (1 above) gives you status of the Shared Folder as a whole. Satellite icons (2, 4) The satellite icons tell you whether or not Relay is syncing with remote servers. Colored satellite icon = Connected. Your changes are being synced to the server, and from there they will be relayed on to any connected collaborators. You'll also receive updates from collaborators. Gray or missing satellite icon = Not connected. This could mean you're not signed in, have connection issues, or there's an authentication problem. The icon in the note (4 above) pertains to that specific note. You can click the icon to intentionally toggle syncing on or off. For example, you might like to turn syncing off to have a bit of privacy while you're writing, and turn it back on when you're done. The icon in the file tree (2 above) pertains to the entire Shared Folder. You can right-click the folder and toggle connect/disconnect in the menu. External file icon (5) When your note contains a link to another note that is not within the same Shared Folder, Relay shows a small file icon with an exclamation point next to the link (see 5 in the image above). This warns you that your collaborators may not be able to access the linked file (unless they have access to it via a different Shared Folder). If a collaborator clicks the link, it will create a new empty note in their vault. To make the icon go away, move the linked-to file into the same Shared Folder, or move the link to a file in the same Shared Folder as the target file. Ribbon icon (6) The Relay ribbon icon provides quick access the Relay settings screens. Troubleshooting For help with icon-related issues, see our Gray stack icon troubleshooting guide, or join the discord server at https://discord.relay.md. (function () { var btn = document.getElementById('theme-toggle'); if (!btn) return; function syncLabel() { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; btn.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode'); } btn.addEventListener('click', function () { var dark = document.documentElement.getAttribute('data-theme') === 'dark'; if (dark) { document.documentElement.removeAttribute('data-theme'); localStorage.setItem('relay-docs-theme', 'light'); } else { document.documentElement.setAttribute('data-theme', 'dark'); localStorage.setItem('relay-docs-theme', 'dark'); } syncLabel(); }); syncLabel(); })();