Apr 8, 2026 7.2 KB markdown of v23

obsidian plugin

Obsidian community plugin for sublimated. reads file metadata directly from xattrs set by FileProvider. no signup required for core features.

consistency rule: VS Code plugin (src/vscode-sublimated/) is the reference implementation. both plugins must show the same information in the same format, adapted to each platform's UI.

macOS only for now. iOS later. no Windows/Linux — sublimated itself is macOS/iOS only.


xattrs

FileProvider writes these on every synced file (all implemented and working):

  • com.sublimated.version#PS — version number (integer)

  • com.sublimated.commit#PS — last commit hash

  • com.sublimated.url#PS — web link (sublimated.com/anton/blog/readme_md)

  • com.sublimated.content-hash#PS — BLAKE3 hash

  • com.sublimated.id#PS — item ID (stable across renames)

  • com.sublimated.created-by#PS — original author name

  • com.sublimated.modified-by#PS — last author name

  • com.sublimated.modified-by-type#PS — person/ai_agent/bot

  • com.sublimated.sync-status#PS — synced/uploading/downloading/error

  • com.sublimated.space#PS — space slug

  • com.sublimated.branch#PS — current branch name

  • com.sublimated.modified-at#PS — server-side timestamp of last change

plugin reads these directly from filesystem. no API calls, no token, no signup for core features.

official Obsidian APIs only

this plugin only uses official, stable Obsidian APIs:

  • addStatusBarItem() — status bar text at the bottom

  • addRibbonIcon() — ribbon icon in the left sidebar

  • registerView() — custom sidebar panel (version history)

  • addCommand() — command palette entries

  • registerObsidianProtocolHandler() — URI handler

  • addSettingTab() — settings page

Obsidian has no official API for file explorer badges, editor hover tooltips, or inline decorations. VS Code has FileDecorationProvider, HoverProvider, CodeLens etc — Obsidian doesn't. plugins that add file tree badges do it via DOM manipulation (finding internal fileItems, appending <span> elements, watching with MutationObserver). this is fragile — Obsidian can change its internal DOM structure in any update and badges break silently. not worth the maintenance cost.

we deliberately skip these VS Code features that have no stable Obsidian equivalent:

  • file explorer sync badges (requires DOM hacking)

  • hover tooltips on wikilinks (no HoverProvider API)

  • CodeLens-style section attribution above headings (no CodeLens API)

  • inline editor decorations (no stable decoration API)

done

  • status bar: version, sync status icons (✓↑↓!⚠), author (AI prefix), branch, visibility (🌐👥🔒). click to open on web. updates on file change

  • version history sidebar: version list with number/author/timestamp, "view on web" link

  • ribbon icon: history button opens version sidebar

  • view on web: command palette + status bar click opens sublimated.com URL from xattr

  • copy web link: command to copy sublimated.com URL to clipboard

  • open in Obsidian: URI handler (obsidian://sublimated?action=open&file=path), OAuth token flow (action=auth)

  • welcome modal: first-run with setup steps, links, hasSeenWelcome flag

  • settings page: API token input, test connection, workspace detection (.sbl/ folder), links

  • all 13 xattr fields read: version, commit, url, contentHash, id, createdBy, modifiedBy, modifiedByType, syncStatus, space, branch, modifiedAt, visibility

todo

cache layer

Obsidian re-reads all xattrs on every file switch (shells out xattr 13 times per tab switch).

  • add TTL-based in-memory cache for xattr reads

  • cache API responses (folder context, file context)

  • invalidate on file save events

workspace detection

done: checks for .sbl/ folder missing:

  • CloudStorage mount path detection: ~/Library/CloudStorage/Sublimated-{space}/ (prod) and ~/Library/CloudStorage/sublimated-dev-{space}/ (dev)

  • .sbl/config or .sbl/config.yml parsing for space slug

  • detection result: space slug, folder path, root path, detection mode

version history improvements

phase 1 (easy, no new API):

  • group versions by day: "Today", "Yesterday", "3 days ago", "Mon DD"

  • commit messages already render — improve visual layout

  • add "view on web" link per version using /:path/~versions/v{number} URL pattern

phase 2 (diff viewer, needs API):

  • click version to see content at that point (read-only tab)

  • API: GET /v1/spaces/:slug/items/:id/diff?v1=X&v2=Y already exists

  • API: GET /v1/spaces/:slug/content/:hash for fetching old version content

  • Obsidian Sync does NOT show diffs natively. community plugin (obsidian-version-history-diff) does but uses private APIs

  • our approach: open old version content in a read-only leaf, let user compare visually. no private APIs

phase 3 (restore):

  • "restore this version" button per version

  • API: POST /v1/spaces/:slug/items/:id/restore with { from_version: number } already exists

OAuth sign-in

add one-click sign-in instead of pasting API tokens:

  1. user clicks "Sign in with sublimated" in settings

  2. browser opens id.sublimated.com/auth/obsidian

  3. user signs in, server redirects to obsidian://sublimated?action=auth&token={token}

  4. plugin stores token, API calls use Authorization: Bearer {token}

plugin-side: main.ts already handles the URI. settings.ts needs a "Sign in" button. server-side: add GET /auth/obsidian route to id.sublimated.com. bearer plugin already set up. keep manual API token input as fallback. token should be long-lived.

comments sidebar

VS Code has full CommentController (513 lines) with gutter "+", threading, resolve, reactions. Obsidian has no comment API — use a sidebar view (official registerView() API).

  • sidebar view: list comments anchored to specific text

  • author, timestamp, quoted text, resolved/unresolved status

  • threaded replies

  • clicking a comment scrolls to anchored text

  • "resolve" button (API call)

  • new comment creation on sublimated.com (link to web UI)

  • API: GET /v1/spaces/{slug}/items/{id}/context

API endpoints

plugin uses these (shared with VS Code extension and language server):

  • GET /v1/spaces/:slug/items/:folderId/context — folder context (items, links, users)

  • GET /v1/spaces/:slug/items/:id/context — file context (comments, versions, sections, blocks, attribution, reactions)

  • POST /v1/spaces/:slug/items/:id/events — editor events

  • POST /v1/spaces/:slug/messages — comment resolve

submission

setup GitHub mirror

  • create repo at https://github.com/sublimates/obsidian

  • push current code (excluding node_modules)

  • set up a workflow to mirror from sublimated.com to GitHub (manual push or automated)

  • add GitHub release workflow for Obsidian plugin submission (main.js, manifest.json, styles.css as release assets)

promotion

  • r/ObsidianMD

  • Obsidian Forum "Share & showcase"

  • Obsidian Discord #updates

  • twitter #ObsidianMD

  • blog post: "how to use Obsidian with sublimated"