Agent skill

Obsidian Data Handling

by jeremylongshore in jeremylongshore/tons-of-skills-marketplace

Implement vault data backup, sync, and recovery strategies. An agent skill from jeremylongshore/tons-of-skills-marketplace.

MITAuto-check passed

Install Obsidian Data Handling

skills CLI
$ npx skills add jeremylongshore/tons-of-skills-marketplace --skill obsidian-data-handling -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install jeremylongshore/tons-of-skills-marketplace obsidian-data-handling --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/jeremylongshore/tons-of-skills-marketplace.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/.curated/obsidian-data-handling .claude/skills/obsidian-data-handling && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
obsidian-data-handling
GitHub stars
2.8k
Token cost
~2.8k tokens
SKILL.md length
443 words
Files
2 (incl. references)
Skills in repo
3,342
Repo updated
First seen
Licence
MIT

At a glance

Implement vault data backup, sync, and recovery strategies. An agent skill from jeremylongshore/tons-of-skills-marketplace.

  • Works in 6 steps: Plugin Config with loadData / saveData → Reading and Writing Vault Files → Working with Frontmatter via MetadataCache → …
  • Building backup features
  • SKILL.md covers Overview, Prerequisites, Instructions and Output, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Obsidian Data Handling is an agent skill from jeremylongshore/tons-of-skills-marketplace. Implement vault data backup, sync, and recovery strategies. Use when building backup features, implementing data export, or handling vault synchronization in your plugin. Trigger with phrases like "obsidian backup", "obsidian sync", "obsidian data export", "vault backup strategy".

Its SKILL.md is about 2.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/implementation-guide.md`). Compatibility notes: Designed for Claude Code

It works with Obsidian. The repository describes itself as: Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com. The licence is MIT.

When your agent uses it

  • Building backup features
  • Implementing data export
  • Handling vault synchronization in your plugin
  • With phrases like obsidian backup

Example prompts

  • “obsidian backup”
  • “obsidian sync”
  • “obsidian data export”
  • “/obsidian-data-handling”

Requirements

  • Compatibility (from SKILL.md): Designed for Claude Code
  • Pre-approved tools (allowed-tools): Read, Write, Edit

Workflow steps

6 steps, taken from the step headings in SKILL.md.

  1. Plugin Config with loadData / saveData
  2. Reading and Writing Vault Files
  3. Working with Frontmatter via MetadataCache
  4. Handling File Renames and Deletes
  5. Cross-Device Sync Considerations
  6. IndexedDB Fallback for Large Datasets

What it can do on your machine

Read from SKILL.md and the folder at commit cfae287. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Read
    • Write
    • Edit

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • docs.obsidian.md
    • help.obsidian.md

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

  • Compatibility

    Designed for Claude Code

    From compatibility in the SKILL.md frontmatter.

Context cost

Obsidian Data Handling loads about 2.8k tokens when it runs, and up to ~7k if it reads all its reference files. Until then it costs about 76 tokens; SKILL.md has 443 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~76
When it runs · the whole SKILL.md, loaded when a task matches
~2.8k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from jeremylongshore/tons-of-skills-marketplace at commit cfae287, republished under its MIT licence (© jeremylongshore). 443 words, ~2,846 tokens.

Download SKILL.mdSave it as .claude/skills/obsidian-data-handling/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
obsidian-data-handling
description
Implement vault data backup, sync, and recovery strategies. Use when building backup features, implementing data export, or handling vault synchronization in your plugin. Trigger with phrases like "obsidian backup", "obsidian sync", "obsidian data export", "vault backup strategy".
allowed-tools
Read, Write, Edit
compatibility
Designed for Claude Code
version
1.13.0
license
MIT
author
Jeremy Longshore <jeremy@intentsolutions.io>
tags
saas, obsidian, backup

Obsidian Data Handling

Overview

Data management patterns for Obsidian plugins: plugin config with loadData/saveData, vault file I/O, frontmatter parsing via metadataCache, handling renames and deletes, cross-device sync considerations, and IndexedDB fallback for large datasets.

Prerequisites

  • Working Obsidian plugin (export default class extends Plugin)
  • Understanding of Obsidian's Vault and MetadataCache APIs
  • TypeScript compilation configured

Instructions

Step 1: Plugin Config with loadData / saveData

Obsidian stores plugin data in .obsidian/plugins/<plugin-id>/data.json. Use loadData() and saveData() — never read that file directly.

typescript
interface PluginConfig {
  version: number;
  apiEndpoint: string;
  syncInterval: number;
  excludedFolders: string[];
}

const DEFAULT_CONFIG: PluginConfig = {
  version: 1,
  apiEndpoint: 'https://api.example.com',
  syncInterval: 300,
  excludedFolders: [],
};

export default class DataPlugin extends Plugin {
  config: PluginConfig;

  async onload() {
    await this.loadConfig();
  }

  async loadConfig() {
    const saved = await this.loadData();
    this.config = Object.assign({}, DEFAULT_CONFIG, saved);

    // Migrate from older config versions
    if (this.config.version < 1) {
      this.config.excludedFolders = [];
      this.config.version = 1;
      await this.saveConfig();
    }
  }

  async saveConfig() {
    await this.saveData(this.config);
  }
}

loadData() returns null on first run — Object.assign onto defaults handles this cleanly.

Step 2: Reading and Writing Vault Files
typescript
import { TFile, TFolder, normalizePath } from 'obsidian';

// Read a markdown file
async readNote(path: string): Promise<string | null> {
  const file = this.app.vault.getAbstractFileByPath(normalizePath(path));
  if (file instanceof TFile) {
    return await this.app.vault.read(file);
  }
  return null;
}

// Write or create a markdown file
async writeNote(path: string, content: string): Promise<TFile> {
  const normalized = normalizePath(path);
  const existing = this.app.vault.getAbstractFileByPath(normalized);

  if (existing instanceof TFile) {
    await this.app.vault.modify(existing, content);
    return existing;
  }

  // Ensure parent folder exists
  const dir = normalized.substring(0, normalized.lastIndexOf('/'));
  if (dir && !this.app.vault.getAbstractFileByPath(dir)) {
    await this.app.vault.createFolder(dir);
  }

  return await this.app.vault.create(normalized, content);
}

// Append to a file (e.g., a log or journal)
async appendToNote(path: string, text: string): Promise<void> {
  const file = this.app.vault.getAbstractFileByPath(normalizePath(path));
  if (file instanceof TFile) {
    await this.app.vault.append(file, '\n' + text);
  }
}

Use vault.cachedRead() instead of vault.read() when you don't need the absolute latest content — it avoids hitting disk on every call.

Step 3: Working with Frontmatter via MetadataCache

Never parse YAML frontmatter manually. Obsidian's metadataCache keeps a parsed cache of every file's frontmatter.

typescript
import { TFile, CachedMetadata } from 'obsidian';

// Read frontmatter from a file
getFrontmatter(file: TFile): Record<string, any> | null {
  const cache: CachedMetadata | null = this.app.metadataCache.getFileCache(file);
  return cache?.frontmatter ?? null;
}

// Update frontmatter using processFrontMatter (Obsidian 1.4+)
async setStatus(file: TFile, status: string): Promise<void> {
  await this.app.fileManager.processFrontMatter(file, (fm) => {
    fm.status = status;
    fm.updated = new Date().toISOString();
  });
}

// Bulk query: find all files with a specific tag
getFilesWithTag(tag: string): TFile[] {
  const files: TFile[] = [];
  for (const file of this.app.vault.getMarkdownFiles()) {
    const cache = this.app.metadataCache.getFileCache(file);
    const tags = cache?.tags?.map(t => t.tag) ?? [];
    const fmTags = cache?.frontmatter?.tags ?? [];
    if (tags.includes(tag) || fmTags.includes(tag.replace('#', ''))) {
      files.push(file);
    }
  }
  return files;
}

processFrontMatter handles YAML serialization correctly — it preserves comments and formatting, and is the only safe way to update frontmatter programmatically.

Step 4: Handling File Renames and Deletes

Plugins that index file paths must update their state when files move or disappear.

typescript
async onload() {
  // Track renames to update internal references
  this.registerEvent(
    this.app.vault.on('rename', (file, oldPath) => {
      if (file instanceof TFile) {
        this.onFileRenamed(file, oldPath);
      }
    })
  );

  // Clean up when files are deleted
  this.registerEvent(
    this.app.vault.on('delete', (file) => {
      if (file instanceof TFile) {
        this.onFileDeleted(file.path);
      }
    })
  );
}

private onFileRenamed(file: TFile, oldPath: string) {
  // Update any stored path references
  if (this.config.pinnedFiles?.includes(oldPath)) {
    const idx = this.config.pinnedFiles.indexOf(oldPath);
    this.config.pinnedFiles[idx] = file.path;
    this.saveConfig();
  }
}

private onFileDeleted(path: string) {
  // Remove from any indexes
  if (this.config.pinnedFiles?.includes(path)) {
    this.config.pinnedFiles = this.config.pinnedFiles.filter(p => p !== path);
    this.saveConfig();
  }
}

Always use registerEvent — it automatically cleans up the listener when the plugin unloads.

Step 5: Cross-Device Sync Considerations

Obsidian vaults synced via iCloud, Dropbox, or Obsidian Sync introduce eventual consistency issues.

typescript
// Problem: two devices modify data.json simultaneously
// Solution: merge-friendly data structures

interface SyncSafeConfig {
  // Use a map keyed by unique IDs instead of arrays
  // Maps merge better than arrays across sync conflicts
  items: Record<string, { value: string; updatedAt: number }>;
}

// Timestamp-based last-write-wins merge
mergeConfigs(local: SyncSafeConfig, remote: SyncSafeConfig): SyncSafeConfig {
  const merged: SyncSafeConfig = { items: {} };
  const allKeys = new Set([
    ...Object.keys(local.items),
    ...Object.keys(remote.items),
  ]);

  for (const key of allKeys) {
    const l = local.items[key];
    const r = remote.items[key];
    if (!l) merged.items[key] = r;
    else if (!r) merged.items[key] = l;
    else merged.items[key] = l.updatedAt >= r.updatedAt ? l : r;
  }
  return merged;
}

Guidelines for sync-friendly plugins:

  • Avoid storing file paths in data.json — they differ across devices with different vault locations
  • Use file content hashes or frontmatter IDs for identity instead of paths
  • Keep data.json small — large files cause sync conflicts and slow sync
Show full SKILL.md (193 more words)Show less
Step 6: IndexedDB Fallback for Large Datasets

When plugin data exceeds what's practical for data.json (more than ~1MB), use IndexedDB.

typescript
class PluginDatabase {
  private db: IDBDatabase | null = null;
  private dbName: string;

  constructor(pluginId: string) {
    this.dbName = `obsidian-${pluginId}`;
  }

  async open(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, 1);

      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result;
        if (!db.objectStoreNames.contains('cache')) {
          db.createObjectStore('cache', { keyPath: 'id' });
        }
      };

      request.onsuccess = (event) => {
        this.db = (event.target as IDBOpenDBRequest).result;
        resolve();
      };

      request.onerror = () => reject(request.error);
    });
  }

  async put(id: string, data: any): Promise<void> {
    if (!this.db) throw new Error('Database not open');
    return new Promise((resolve, reject) => {
      const tx = this.db!.transaction('cache', 'readwrite');
      tx.objectStore('cache').put({ id, data, updatedAt: Date.now() });
      tx.oncomplete = () => resolve();
      tx.onerror = () => reject(tx.error);
    });
  }

  async get(id: string): Promise<any | null> {
    if (!this.db) throw new Error('Database not open');
    return new Promise((resolve, reject) => {
      const tx = this.db!.transaction('cache', 'readonly');
      const request = tx.objectStore('cache').get(id);
      request.onsuccess = () => resolve(request.result?.data ?? null);
      request.onerror = () => reject(request.error);
    });
  }

  close() {
    this.db?.close();
    this.db = null;
  }
}

// Usage in plugin
async onload() {
  this.db = new PluginDatabase(this.manifest.id);
  await this.db.open();
}

onunload() {
  this.db?.close();
}

IndexedDB is per-device and does not sync across devices. Use it for caches and derived data that can be rebuilt, not for primary user data.

Output

  • Plugin config loading with version migration
  • Safe vault file read/write/append operations
  • Frontmatter access via metadataCache
  • Rename and delete event handlers
  • Sync-friendly data structures
  • IndexedDB storage for large datasets

Error Handling

IssueCauseSolution
loadData() returns nullFirst run, no data.json yetObject.assign onto defaults
Frontmatter returns undefinedFile not yet indexed by cacheListen for metadataCache.on('resolved')
File write failsParent folder doesn't existCreate folder with vault.createFolder() first
Settings lost after syncConcurrent writes from two devicesUse merge-friendly data structures with timestamps
data.json too large / slowStoring too much dataMove large data to IndexedDB
stale cache after modifycachedRead returns old contentUse vault.read() when freshness matters

Examples

Export All Notes with Tag to JSON
typescript
async exportTaggedNotes(tag: string): Promise<string> {
  const files = this.getFilesWithTag(tag);
  const notes = await Promise.all(
    files.map(async (f) => ({
      path: f.path,
      content: await this.app.vault.read(f),
      frontmatter: this.getFrontmatter(f),
    }))
  );
  return JSON.stringify(notes, null, 2);
}
Atomic Config Update
typescript
async updateConfig<K extends keyof PluginConfig>(
  key: K,
  value: PluginConfig[K]
): Promise<void> {
  this.config[key] = value;
  await this.saveConfig();
}

Resources

Next Steps

For team access control patterns, see obsidian-enterprise-rbac. For performance with large vaults, see obsidian-rate-limits.

© jeremylongshore, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (references) in skills/.curated/obsidian-data-handling of jeremylongshore/tons-of-skills-marketplace.

  • SKILL.md
  • references/implementation-guide.md

Open the folder on GitHubat commit cfae287

Compare with similar skills

Obsidian Data Handling next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Obsidian Data Handling compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Obsidian Data Handling this skilljeremylongshore/tons-of-skills-marketplace2.8k—~2.8kAutomated safety check: PassMIT
Obsidian BasesAtmosphere/atmosphere3.8k22 repos~3.2kAutomated safety check: PassApache-2.0
Knap Markdown Templateskepano/obsidian-skills49k2 repos~986Automated safety check: PassMIT
JSON Canvasheyitsnoah/claudesidian2.6k18 repos~3.5kAutomated safety check: PassMIT
Obsidian MarkdownAtmosphere/atmosphere3.8k20 repos~1.3kAutomated safety check: PassApache-2.0
Obsidian CLIAtmosphere/atmosphere3.8k13 repos~795Automated safety check: PassApache-2.0

Similar skills

  • Obsidian Bases

    Atmosphere/atmosphere

    Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries.

    3.8k GitHub starsUsed in 22 repos~3.2k tokens
    Backend & APIsAuto-check passed
  • Knap Markdown Templates

    kepano/obsidian-skills

    Renders Markdown notes from Knap templates and JSON data on the command line, including notes built from Defuddle web page output.

    49k GitHub starsUsed in 2 repos~986 tokens
    Documents & OfficeAuto-check passed
  • JSON Canvas

    heyitsnoah/claudesidian

    Create and edit JSON Canvas files (.canvas) with nodes, edges, groups, and connections.

    2.6k GitHub starsUsed in 18 repos~3.5k tokens
    DevelopmentAuto-check passed
  • Obsidian Markdown

    Atmosphere/atmosphere

    Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax.

    3.8k GitHub starsUsed in 20 repos~1.3k tokens
    Documents & OfficeAuto-check passed
  • Obsidian CLI

    Atmosphere/atmosphere

    Interact with Obsidian vaults using the Obsidian CLI to read, create, search, and manage notes, tasks, properties, and more.

    3.8k GitHub starsUsed in 13 repos~795 tokens
    Knowledge ManagementAuto-check passed
  • Obsidian Canvas Creator

    axtonliu/axton-obsidian-visual-skills

    Create Obsidian Canvas files from text content, supporting both MindMap and freeform layouts.

    3.6k GitHub stars~1.6k tokensUpdated 3 mo ago
    Auto-check passed

More from jeremylongshore/tons-of-skills-marketplace

All 3,342 skills in this repo
  • Performing Security Code Review

    jeremylongshore/tons-of-skills-marketplace

    Execute this skill enables AI assistant to conduct a security-focused code review using the security-agent plugin.

    2.8k GitHub starsUsed in 2 repos~1.3k tokens
    Auto-check: notes
  • Adapting Transfer Learning Models

    jeremylongshore/tons-of-skills-marketplace

    Build this skill automates the adaptation of pre-trained machine learning models using transfer learning techniques.

    2.8k GitHub stars~1.1k tokensUpdated today
    Auto-check passed
  • Agent Context Loader

    jeremylongshore/tons-of-skills-marketplace

    Execute proactive auto-loading: automatically detects and loads agents.md files.

    2.8k GitHub stars~1.1k tokensUpdated today
    Auto-check passed
  • Aggregating Performance Metrics

    jeremylongshore/tons-of-skills-marketplace

    Aggregate and centralize performance metrics from applications, systems, databases, caches, and services.

    2.8k GitHub stars~1.2k tokensUpdated today
    Auto-check passed
  • Analyzing Capacity Planning

    jeremylongshore/tons-of-skills-marketplace

    Execute this skill enables AI assistant to analyze capacity requirements and plan for future growth.

    2.8k GitHub stars~947 tokensUpdated today
    Auto-check passed
  • Analyzing Database Indexes

    jeremylongshore/tons-of-skills-marketplace

    Process use when you need to work with database indexing. An agent skill from jeremylongshore/tons-of-skills-marketplace.

    2.8k GitHub stars~2k tokensUpdated today
    Auto-check passed

Works with

Questions about Obsidian Data Handling

What does Obsidian Data Handling do?

Implement vault data backup, sync, and recovery strategies. An agent skill from jeremylongshore/tons-of-skills-marketplace. Obsidian Data Handling is an agent skill from jeremylongshore/tons-of-skills-marketplace. Implement vault data backup, sync, and recovery strategies.

When should I use Obsidian Data Handling?

Obsidian Data Handling fits situations like: building backup features; implementing data export; handling vault synchronization in your plugin; with phrases like obsidian backup.

How do I install Obsidian Data Handling in Claude Code?

Run `npx skills add jeremylongshore/tons-of-skills-marketplace --skill obsidian-data-handling -a claude-code`. Or copy the skill folder (skills/.curated/obsidian-data-handling in jeremylongshore/tons-of-skills-marketplace) into .claude/skills/obsidian-data-handling in your project. Claude Code loads it when a task matches its description.

How do I install Obsidian Data Handling in Codex?

Run `npx skills add jeremylongshore/tons-of-skills-marketplace --skill obsidian-data-handling -a codex`. Or copy the skill folder (skills/.curated/obsidian-data-handling in jeremylongshore/tons-of-skills-marketplace) into .agents/skills/obsidian-data-handling in your project. Codex loads it when a task matches its description.

Can I use Obsidian Data Handling in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jeremylongshore/tons-of-skills-marketplace --skill obsidian-data-handling -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/obsidian-data-handling, .gemini/skills/obsidian-data-handling, .github/skills/obsidian-data-handling and .opencode/skills/obsidian-data-handling in your project.

What does Obsidian Data Handling need to run?

SKILL.md names no scripts, command-line tools or credentials: Obsidian Data Handling is instructions for the agent only. Its frontmatter pre-approves these tools: Read, Write, Edit. Compatibility (from SKILL.md): Designed for Claude Code.

Does Obsidian Data Handling access the network?

SKILL.md names 2 domains. As links in the text: docs.obsidian.md and help.obsidian.md. This is read from the text; nothing was executed.

Is Obsidian Data Handling safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Obsidian Data Handling use?

Obsidian Data Handling is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Obsidian Data Handling use?

About 2.8k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 4.2k tokens, read only when the agent opens those files.

What are the alternatives to Obsidian Data Handling?

Skills that share tags, products or a category with Obsidian Data Handling: Obsidian Bases (Atmosphere/atmosphere, 3.8k stars), Knap Markdown Templates (kepano/obsidian-skills, 49k stars), JSON Canvas (heyitsnoah/claudesidian, 2.6k stars) and Obsidian Markdown (Atmosphere/atmosphere, 3.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Obsidian Data Handling?

jeremylongshore (a GitHub user) maintains it in jeremylongshore/tons-of-skills-marketplace, which has 2,827 GitHub stars. The repository holds 3,342 skills in this directory. The repository was last updated on October 10, 2026.

Source: jeremylongshore/tons-of-skills-marketplace on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.