Agent skill

Obsidian SDK Patterns

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

Production-ready Obsidian plugin patterns: typed settings with migration, safe vault operations, event auto-cleanup, workspace layout, metadata cache, and debounced file handlers.

MITAuto-check passedDevelopment

Install Obsidian SDK Patterns

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

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

GitHub CLI
$ gh skill install jeremylongshore/tons-of-skills-marketplace obsidian-sdk-patterns --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-sdk-patterns .claude/skills/obsidian-sdk-patterns && 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-sdk-patterns
GitHub stars
2.8k
Token cost
~4k tokens
SKILL.md length
449 words
Files
3 (incl. references)
Skills in repo
3,342
Repo updated
First seen
Licence
MIT

At a glance

Production-ready Obsidian plugin patterns: typed settings with migration, safe vault operations, event auto-cleanup, workspace layout, metadata cache, and debounced file handlers.

  • Works in 6 steps: Typed settings with versioned migration → Safe vault operations (check-before-act) → Event management with automatic cleanup → …
  • Hardening a plugin for release
  • 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 SDK Patterns is an agent skill from jeremylongshore/tons-of-skills-marketplace. Production-ready Obsidian plugin patterns: typed settings with migration, safe vault operations, event auto-cleanup, workspace layout, metadata cache, and debounced file handlers. Use when hardening a plugin for release, refactoring for reliability, or learning idiomatic Obsidian TypeScript. Trigger with "obsidian patterns", "obsidian best practices", "obsidian production code", "idiomatic obsidian plugin".

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

It sits in Development, covering Refactoring. It works with Obsidian and TypeScript. 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

  • Hardening a plugin for release
  • Refactoring for reliability
  • Learning idiomatic Obsidian TypeScript
  • With obsidian patterns

Example prompts

  • “obsidian patterns”
  • “obsidian best practices”
  • “obsidian production code”
  • “/obsidian-sdk-patterns”

Requirements

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

Workflow steps

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

  1. Typed settings with versioned migration
  2. Safe vault operations (check-before-act)
  3. Event management with automatic cleanup
  4. Workspace layout manipulation
  5. Metadata cache for fast queries
  6. Debounced file modification handlers

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
    • Grep

    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

    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 SDK Patterns loads about 4k tokens when it runs, and up to ~6.9k if it reads all its reference files. Until then it costs about 108 tokens; SKILL.md has 449 words of instructions outside code blocks.

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

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). 449 words, ~4,000 tokens.

Download SKILL.mdSave it as .claude/skills/obsidian-sdk-patterns/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
obsidian-sdk-patterns
description
Production-ready Obsidian plugin patterns: typed settings with migration, safe vault operations, event auto-cleanup, workspace layout, metadata cache, and debounced file handlers. Use when hardening a plugin for release, refactoring for reliability, or learning idiomatic Obsidian TypeScript. Trigger with "obsidian patterns", "obsidian best practices", "obsidian production code", "idiomatic obsidian plugin".
allowed-tools
Read, Write, Edit, Grep
compatibility
Designed for Claude Code
version
1.13.0
license
MIT
author
Jeremy Longshore <jeremy@intentsolutions.io>
tags
obsidian, patterns, production, typescript, best-practices

Obsidian SDK Patterns

Overview

Six production patterns that prevent the most common Obsidian plugin bugs: lost settings on upgrade, null-reference crashes on deleted files, memory leaks from unregistered events, stale metadata, and UI jank from rapid file changes. Each pattern is self-contained and copy-pasteable.

Prerequisites

  • A working Obsidian plugin (see obsidian-core-workflow-a)
  • TypeScript strict mode enabled ("strictNullChecks": true in tsconfig)
  • Familiarity with Plugin.onload() / onunload() lifecycle

Instructions

Step 1: Typed settings with versioned migration

Settings break when you add or rename fields between releases. Version the settings object and migrate on load so existing users keep their data.

typescript
// src/settings.ts
interface PluginSettingsV1 {
  apiKey: string;
  interval: number;
}

interface PluginSettingsV2 {
  version: 2;
  apiKey: string;
  syncInterval: number;      // renamed from "interval"
  excludedFolders: string[]; // new field
  theme: "default" | "minimal";
}

// Current version is always the latest
type PluginSettings = PluginSettingsV2;

const DEFAULTS: PluginSettings = {
  version: 2,
  apiKey: "",
  syncInterval: 300,
  excludedFolders: [],
  theme: "default",
};

export async function loadSettings(plugin: Plugin): Promise<PluginSettings> {
  const raw = (await plugin.loadData()) as any;
  if (!raw) return { ...DEFAULTS };

  // Migrate v1 -> v2
  if (!raw.version || raw.version < 2) {
    raw.version = 2;
    if (raw.interval !== undefined) {
      raw.syncInterval = raw.interval;
      delete raw.interval;
    }
    raw.excludedFolders = raw.excludedFolders ?? [];
    raw.theme = raw.theme ?? "default";
    await plugin.saveData(raw);
  }

  // Merge with defaults to pick up any newly added fields
  return { ...DEFAULTS, ...raw };
}

Why: Object.assign({}, DEFAULTS, raw) handles new fields added in patch releases. The explicit migration block handles renames and type changes between major versions.

Step 2: Safe vault operations (check-before-act)

The Vault API throws if you create a file that exists or read one that was deleted between your check and your call. Wrap every operation.

typescript
// src/vault-helpers.ts
import { App, TFile, TFolder, TAbstractFile, normalizePath } from "obsidian";

export class VaultHelper {
  constructor(private app: App) {}

  /** Read file content, return null if file doesn't exist */
  async safeRead(path: string): Promise<string | null> {
    const file = this.app.vault.getAbstractFileByPath(normalizePath(path));
    if (!(file instanceof TFile)) return null;
    return this.app.vault.read(file);
  }

  /** Create or overwrite a file. Creates parent folders as needed. */
  async safeWrite(path: string, content: string): Promise<TFile> {
    const normalized = normalizePath(path);
    await this.ensureParentFolder(normalized);

    const existing = this.app.vault.getAbstractFileByPath(normalized);
    if (existing instanceof TFile) {
      await this.app.vault.modify(existing, content);
      return existing;
    }
    return this.app.vault.create(normalized, content);
  }

  /** Append content to a file. Creates the file if it doesn't exist. */
  async safeAppend(path: string, content: string): Promise<void> {
    const normalized = normalizePath(path);
    const existing = this.app.vault.getAbstractFileByPath(normalized);
    if (existing instanceof TFile) {
      const current = await this.app.vault.read(existing);
      await this.app.vault.modify(existing, current + content);
    } else {
      await this.ensureParentFolder(normalized);
      await this.app.vault.create(normalized, content);
    }
  }

  /** Delete a file if it exists, moving to trash by default. */
  async safeDelete(path: string, useTrash = true): Promise<boolean> {
    const file = this.app.vault.getAbstractFileByPath(normalizePath(path));
    if (!(file instanceof TFile)) return false;
    if (useTrash) {
      await this.app.vault.trash(file, false);
    } else {
      await this.app.vault.delete(file);
    }
    return true;
  }

  /** Ensure a folder (and all parents) exist. */
  private async ensureParentFolder(filePath: string): Promise<void> {
    const parts = filePath.split("/");
    parts.pop(); // remove filename
    let current = "";
    for (const part of parts) {
      current = current ? `${current}/${part}` : part;
      const existing = this.app.vault.getAbstractFileByPath(current);
      if (!existing) {
        await this.app.vault.createFolder(current);
      }
    }
  }
}
Step 3: Event management with automatic cleanup

Every this.registerEvent(...) call in onload() is automatically cleaned up when the plugin unloads. Never use raw addEventListener or app.vault.on() without registering -- those leak.

typescript
export default class MyPlugin extends Plugin {
  async onload() {
    // File events -- auto-cleaned on unload
    this.registerEvent(
      this.app.vault.on("create", (file) => {
        if (file instanceof TFile) this.onFileCreated(file);
      })
    );

    this.registerEvent(
      this.app.vault.on("delete", (file) => {
        if (file instanceof TFile) this.onFileDeleted(file);
      })
    );

    this.registerEvent(
      this.app.vault.on("rename", (file, oldPath) => {
        if (file instanceof TFile) this.onFileRenamed(file, oldPath);
      })
    );

    // Workspace events
    this.registerEvent(
      this.app.workspace.on("active-leaf-change", (leaf) => {
        this.onActiveLeafChange(leaf);
      })
    );

    this.registerEvent(
      this.app.workspace.on("layout-change", () => {
        this.onLayoutChange();
      })
    );

    // Periodic tasks -- also auto-cleaned
    this.registerInterval(
      window.setInterval(() => this.periodicSync(), 60_000)
    );

    // DOM events -- use registerDomEvent for auto-cleanup
    this.registerDomEvent(document, "keydown", (evt: KeyboardEvent) => {
      if (evt.key === "F5") this.refreshData();
    });
  }

  // No cleanup code needed in onunload() -- all registered events
  // are automatically removed by the Plugin base class.
}

Anti-pattern to avoid:

typescript
// BAD: leaks on plugin unload
this.app.vault.on("modify", handler);
document.addEventListener("click", handler);

// GOOD: auto-cleaned
this.registerEvent(this.app.vault.on("modify", handler));
this.registerDomEvent(document, "click", handler);
Step 4: Workspace layout manipulation

Open files in specific panes, split views, and restore layout state.

typescript
import { MarkdownView, WorkspaceLeaf } from "obsidian";

export class WorkspaceHelper {
  constructor(private app: App) {}

  /** Open a file in a new tab */
  async openInNewTab(path: string): Promise<void> {
    const file = this.app.vault.getAbstractFileByPath(path);
    if (!(file instanceof TFile)) return;
    const leaf = this.app.workspace.getLeaf("tab");
    await leaf.openFile(file);
  }

  /** Open a file in a vertical split to the right */
  async openInSplit(path: string): Promise<void> {
    const file = this.app.vault.getAbstractFileByPath(path);
    if (!(file instanceof TFile)) return;
    const leaf = this.app.workspace.getLeaf("split", "vertical");
    await leaf.openFile(file);
  }

  /** Get the currently active markdown file (or null) */
  getActiveFile(): TFile | null {
    const view = this.app.workspace.getActiveViewOfType(MarkdownView);
    return view?.file ?? null;
  }

  /** Iterate all open markdown leaves */
  forEachOpenNote(callback: (file: TFile, leaf: WorkspaceLeaf) => void): void {
    this.app.workspace.iterateAllLeaves((leaf) => {
      if (leaf.view instanceof MarkdownView && leaf.view.file) {
        callback(leaf.view.file, leaf);
      }
    });
  }

  /** Pin/unpin the active tab */
  togglePin(): void {
    const leaf = this.app.workspace.getLeaf();
    if (leaf) {
      const pinned = (leaf as any).pinned;
      (leaf as any).setPinned(!pinned);
    }
  }
}
Step 5: Metadata cache for fast queries

metadataCache is Obsidian's pre-parsed index of all vault files. It avoids reading file content for frontmatter, tags, links, and headings.

typescript
import { App, TFile, CachedMetadata } from "obsidian";

export class MetadataHelper {
  constructor(private app: App) {}

  /** Get parsed metadata for a file (frontmatter, tags, links, headings) */
  getCache(file: TFile): CachedMetadata | null {
    return this.app.metadataCache.getFileCache(file);
  }

  /** Get frontmatter value, returns undefined if missing */
  getFrontmatterValue(file: TFile, key: string): any | undefined {
    const cache = this.getCache(file);
    return cache?.frontmatter?.[key];
  }

  /** Find all files with a specific tag */
  filesWithTag(tag: string): TFile[] {
    const normalized = tag.startsWith("#") ? tag : `#${tag}`;
    return this.app.vault.getMarkdownFiles().filter((file) => {
      const cache = this.getCache(file);
      // Tags in body
      const bodyTags = cache?.tags?.map((t) => t.tag) ?? [];
      // Tags in frontmatter
      const fmTags = (cache?.frontmatter?.tags ?? []).map((t: string) =>
        t.startsWith("#") ? t : `#${t}`
      );
      return [...bodyTags, ...fmTags].includes(normalized);
    });
  }

  /** Get all outgoing links from a file */
  outgoingLinks(file: TFile): string[] {
    const cache = this.getCache(file);
    const links = cache?.links?.map((l) => l.link) ?? [];
    const embeds = cache?.embeds?.map((e) => e.link) ?? [];
    return [...new Set([...links, ...embeds])];
  }

  /** Get files that link to this file (backlinks) */
  backlinks(file: TFile): TFile[] {
    const resolved = this.app.metadataCache.resolvedLinks;
    const results: TFile[] = [];
    for (const [sourcePath, targets] of Object.entries(resolved)) {
      if (file.path in targets) {
        const source = this.app.vault.getAbstractFileByPath(sourcePath);
        if (source instanceof TFile) results.push(source);
      }
    }
    return results;
  }

  /** Wait for metadata cache to be fully indexed (useful on plugin load) */
  onCacheReady(callback: () => void): void {
    if (this.app.metadataCache.initialized) {
      callback();
    } else {
      this.app.metadataCache.on("initialized", callback);
    }
  }

  /** Listen for metadata changes on a specific file */
  onFileMetadataChange(
    plugin: Plugin,
    filePath: string,
    callback: (cache: CachedMetadata) => void
  ): void {
    plugin.registerEvent(
      this.app.metadataCache.on("changed", (file, _data, cache) => {
        if (file.path === filePath) callback(cache);
      })
    );
  }
}
Step 6: Debounced file modification handlers

Plugins that react to file changes (auto-save, indexing, sync) fire too often without debouncing. Obsidian's vault modify event fires on every keystroke when live preview is active.

typescript
import { Plugin, TFile, debounce } from "obsidian";

export default class IndexerPlugin extends Plugin {
  // Debounce: wait 2s after last modification before processing
  private processFile = debounce(
    async (file: TFile) => {
      console.log(`[Indexer] Processing ${file.path}`);
      const content = await this.app.vault.read(file);
      await this.updateIndex(file, content);
    },
    2000,
    true  // true = reset timer on each call (trailing edge)
  );

  async onload() {
    this.registerEvent(
      this.app.vault.on("modify", (file) => {
        if (file instanceof TFile && file.extension === "md") {
          this.processFile(file);
        }
      })
    );
  }

  private async updateIndex(file: TFile, content: string): Promise<void> {
    // Your indexing logic here -- runs at most once per 2s per file
  }
}

For per-file debouncing (different timers for different files):

typescript
private fileTimers = new Map<string, ReturnType<typeof setTimeout>>();

private debouncedProcess(file: TFile, delayMs = 2000): void {
  const existing = this.fileTimers.get(file.path);
  if (existing) clearTimeout(existing);

  this.fileTimers.set(
    file.path,
    setTimeout(async () => {
      this.fileTimers.delete(file.path);
      const content = await this.app.vault.read(file);
      await this.updateIndex(file, content);
    }, delayMs)
  );
}

// Clean up all timers on unload
onunload() {
  for (const timer of this.fileTimers.values()) {
    clearTimeout(timer);
  }
  this.fileTimers.clear();
}
Show full SKILL.md (181 more words)Show less

Output

After applying these patterns:

  • Settings survive across plugin updates with automatic migration
  • File operations never crash on missing files or duplicate paths
  • All events auto-clean on plugin unload (zero memory leaks)
  • Workspace manipulation opens files in tabs, splits, or sidebar
  • Metadata cache provides instant tag/link/frontmatter queries without reading files
  • File modification handlers are debounced to prevent UI jank and redundant work

Error Handling

ErrorCauseFix
Settings lost after updateNo version field / no migrationAdd version to settings interface, migrate in loadSettings
null file referenceFile deleted between check and useAlways re-fetch with getAbstractFileByPath immediately before use
Memory leak warningEvents registered without registerEventWrap every .on() with this.registerEvent()
Stale metadataCache not yet updated after vault.modifyListen to metadataCache.on('changed') instead of reading immediately
Plugin slows ObsidianProcessing every keystrokeDebounce modify handlers (2s+ delay)
createFolder throwsFolder already existsCheck getAbstractFileByPath first
normalizePath undefinedForgot importImport from "obsidian"

Examples

Complete plugin using all patterns together:

typescript
import { Plugin, TFile, debounce, normalizePath } from "obsidian";
import { loadSettings, PluginSettings } from "./settings";
import { VaultHelper } from "./vault-helpers";
import { MetadataHelper } from "./metadata-helpers";

export default class MyPlugin extends Plugin {
  settings: PluginSettings;
  vault: VaultHelper;
  meta: MetadataHelper;

  async onload() {
    this.settings = await loadSettings(this);
    this.vault = new VaultHelper(this.app);
    this.meta = new MetadataHelper(this.app);

    // Debounced auto-index
    const reindex = debounce(
      (file: TFile) => this.indexFile(file), 2000, true
    );
    this.registerEvent(
      this.app.vault.on("modify", (f) => {
        if (f instanceof TFile) reindex(f);
      })
    );
  }

  private async indexFile(file: TFile) {
    const content = await this.vault.safeRead(file.path);
    if (!content) return;
    const tags = this.meta.filesWithTag("index");
    // ... indexing logic
  }
}

Resources

Next Steps

Debug and test: obsidian-local-dev-loop. Common errors: obsidian-common-errors. Release: obsidian-prod-checklist.

© 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 2 other files (references) in skills/.curated/obsidian-sdk-patterns of jeremylongshore/tons-of-skills-marketplace.

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

Open the folder on GitHubat commit cfae287

Compare with similar skills

Obsidian SDK Patterns 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 SDK Patterns compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Obsidian SDK Patterns this skilljeremylongshore/tons-of-skills-marketplace2.8k—~4kAutomated safety check: PassMIT
Svelte5 Best PracticesSikandarJODD/cnblocks4311 repos~810Automated safety check: PassMIT
Dinero Best Practicesdinerojs/dinero.js6.8k—~756Automated safety check: PassMIT
Code Guidelinesgetsentry/sentry-react-native1.8k—~3.2kAutomated safety check: PassMIT
AST Visitor Pattern for Unionsprisma/orm48k—~830Automated safety check: PassApache-2.0
ast-grep Codemod Referencewarp-drive-data/warp-drive3.2k—~2.6kAutomated safety check: PassMIT

Similar skills

  • Svelte5 Best Practices

    SikandarJODD/cnblocks

    Svelte 5 runes, snippets, SvelteKit patterns, and modern best practices for TypeScript and component development.

    431 GitHub starsUsed in 1 repo~810 tokens
    DevelopmentAuto-check passed
  • Dinero Best Practices

    dinerojs/dinero.js

    Core best practices for the Dinero.js money library. An agent skill from dinerojs/dinero.js.

    6.8k GitHub stars~756 tokensUpdated 4 days ago
    DevelopmentAuto-check passed
  • Code Guidelines

    getsentry/sentry-react-native

    Official

    Enforce Sentry React Native SDK code guidelines for implementation, refactoring, and review.

    1.8k GitHub stars~3.2k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Official

    Replaces a plain TypeScript union plus switch statements with frozen subclasses and a visitor interface when several places dispatch on the same variants.

    48k GitHub stars~830 tokensUpdated today
    DevelopmentAuto-check passed
  • ast-grep Codemod Reference

    warp-drive-data/warp-drive

    Reference for writing and debugging TypeScript and JavaScript codemods with @ast-grep/napi: parsing, node queries, meta-variables, rule objects and editing.

    3.2k GitHub stars~2.6k tokensUpdated today
    DevelopmentAuto-check passed
  • Deep Refactor Audit

    AlmanacCode/codealmanac

    A skill your agent uses when a user asks for a major architecture/refactor audit, codebase smell investigation, boundary critique, feature simplification review, vibe-coded or AI-generated code…

    997 GitHub stars~3.5k tokensUpdated 2 mo ago
    DevelopmentAuto-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

Categories

Questions about Obsidian SDK Patterns

What does Obsidian SDK Patterns do?

Production-ready Obsidian plugin patterns: typed settings with migration, safe vault operations, event auto-cleanup, workspace layout, metadata cache, and debounced file handlers. Obsidian SDK Patterns is an agent skill from jeremylongshore/tons-of-skills-marketplace. Production-ready Obsidian plugin patterns: typed settings with migration, safe vault operations, event auto-cleanup, workspace layout, metadata cache, and debounced file handlers.

When should I use Obsidian SDK Patterns?

Obsidian SDK Patterns fits situations like: hardening a plugin for release; refactoring for reliability; learning idiomatic Obsidian TypeScript; with obsidian patterns.

How do I install Obsidian SDK Patterns in Claude Code?

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

How do I install Obsidian SDK Patterns in Codex?

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

Can I use Obsidian SDK Patterns 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-sdk-patterns -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-sdk-patterns, .gemini/skills/obsidian-sdk-patterns, .github/skills/obsidian-sdk-patterns and .opencode/skills/obsidian-sdk-patterns in your project.

What does Obsidian SDK Patterns need to run?

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

Does Obsidian SDK Patterns access the network?

SKILL.md names 1 domain. As links in the text: docs.obsidian.md. This is read from the text; nothing was executed.

Is Obsidian SDK Patterns 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 SDK Patterns use?

Obsidian SDK Patterns 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 SDK Patterns use?

About 4k tokens (SKILL.md is roughly 16k 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 2.9k tokens, read only when the agent opens those files.

What are the alternatives to Obsidian SDK Patterns?

Skills that share tags, products or a category with Obsidian SDK Patterns: Svelte5 Best Practices (SikandarJODD/cnblocks, 431 stars), Dinero Best Practices (dinerojs/dinero.js, 6.8k stars), Code Guidelines (getsentry/sentry-react-native, 1.8k stars) and AST Visitor Pattern for Unions (prisma/orm, 48k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Obsidian SDK Patterns?

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.