Apr 11, 2026 7.6 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: compact format ✓ synced v21 by anton (sync icon + version + author + optional branch/visibility). click to open on web. hidden for non-sublimated files. updates on file change

  • version history sidebar: newest-first, grouped by day (Today / Yesterday / N days ago), with author, timestamp, commit message, per-version "view on web" link (/~versions/v{number})

  • anonymous version history: public files fetch history without an API token. private files show a friendly "add token in settings" message on 401/403

  • 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 stub (action=auth)

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

  • settings page: API token input, test connection, xattr-based workspace detection, links

  • xattr-based workspace detection: per-file, works for subfolder vaults and mixed vaults, no .sbl/ folder required

  • 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: per-file xattr-based detection. any file with com.sublimated.space#PS identifies the workspace. works for subfolder vaults, works without .sbl/, works for mixed vaults.

possible future additions:

  • CloudStorage mount path detection as a fallback for empty vaults: ~/Library/CloudStorage/Sublimated-{space}/ (prod) and ~/Library/CloudStorage/sublimated-dev-{space}/ (dev)

  • cache detected space slug across sessions so settings page shows it before any file is opened

version history improvements

phase 1 (done):

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

  • commit messages render with improved visual layout

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

  • newest version first (reverse server order)

  • anonymous fetch for public files (no token needed)

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)

  • needs new API endpoint — comments are not currently exposed over HTTP

API endpoints

plugin currently uses:

  • GET /v1/spaces/:slug/items/:id/versions — list version history (anonymous for public items, token required for private)

public items work without an API token. the middleware in src/shared/auth/authorize.ts grants anonymous callers { read: true } when folder visibility is public.

submission

  • source of truth: https://sublimated.com/sublimated/code/obsidian

  • GitHub live mirror: https://github.com/sublimates/obsidian — live-synced from sublimated.com

  • todo: PR to obsidianmd/obsidian-releases adding entry to community-plugins.json

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

  • todo: README with screenshots, description, setup instructions

  • automated validation + manual review by Obsidian team

promotion

  • r/ObsidianMD

  • Obsidian Forum "Share & showcase"

  • Obsidian Discord #updates

  • twitter #ObsidianMD

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