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".
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
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
version
1.13.0
license
MIT
author
Jeremy Longshore <jeremy@intentsolutions.io>
tags
["saas","obsidian","backup"]
compatibility
Designed for Claude Code, also compatible with Codex and OpenClaw
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.
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.
asynconload() {
// Track renames to update internal referencesthis.registerEvent(
this.app.vault.on('rename', (file, oldPath) => {
if (file instanceofTFile) {
this.onFileRenamed(file, oldPath);
}
})
);
// Clean up when files are deletedthis.registerEvent(
this.app.vault.on('delete', (file) => {
if (file instanceofTFile) {
this.onFileDeleted(file.path);
}
})
);
}
privateonFileRenamed(file: TFile, oldPath: string) {
// Update any stored path referencesif (this.config.pinnedFiles?.includes(oldPath)) {
const idx = this.config.pinnedFiles.indexOf(oldPath);
this.config.pinnedFiles[idx] = file.path;
this.saveConfig();
}
}
privateonFileDeleted(path: string) {
// Remove from any indexesif (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.
// Problem: two devices modify data.json simultaneously// Solution: merge-friendly data structuresinterfaceSyncSafeConfig {
// Use a map keyed by unique IDs instead of arrays// Maps merge better than arrays across sync conflictsitems: Record<string, { value: string; updatedAt: number }>;
}
// Timestamp-based last-write-wins mergemergeConfigs(local: SyncSafeConfig, remote: SyncSafeConfig): SyncSafeConfig {
constmerged: SyncSafeConfig = { items: {} };
const allKeys = newSet([
...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;
elseif (!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
Step 6: IndexedDB Fallback for Large Datasets
When plugin data exceeds what's practical for data.json (more than ~1MB), use IndexedDB.