Obsidian Plugin Development Skill

repository·main·Indexed 41 days ago

https://github.com/gapmiss/obsidian-plugin-skill

An agentic skill for coding agents like Claude Code, Windsurf, and Codex to develop high-quality Obsidian plugins. It includes an interactive boilerplate generator for TypeScript, real-time validation for community submission standards, and comprehensive reference guides on memory management, type-safe file operations, and mandatory A11y requirements. Provides integration with eslint-plugin-obsidianmd to ensure code quality and security.

Tokens
2.2K
Snippets
5
Records
11
Agent score
2%

What's inside Obsidian Plugin Skill

  1. Use Best Practices for Memory and Lifecycle Management

    main

    To prevent memory leaks and ensure stability, follow these lifecycle rules:

    • Automatic Cleanup: Use this.registerEvent(), this.addCommand(), this.registerDomEvent(), or this.registerInterval() so Obsidian can manage cleanup automatically.
    • View Management: Do not store view references directly in your plugin class. Instead, create and return the view directly within registerView.
    • Leaf Cleanup: Do not manually call this.app.workspace.detachLeavesOfType() in onunload; let Obsidian handle the cleanup of registered leaves.
    // CORRECT: Create and return directly to avoid memory leaks
    this.registerView(VIEW_TYPE, (leaf) => {
      return new CustomView(leaf);
    });
    
    // INCORRECT: Storing view reference in plugin
    this.registerView(VIEW_TYPE, (leaf) => {
      this.view = new CustomView(leaf);
      return this.view;
    });
  2. Understand the Obsidian Plugin Skill structure

    main

    The skill uses progressive disclosure to optimize performance. It consists of a main overview file and a set of detailed reference files:

    • SKILL.md: The main entry point providing a concise overview, ESLint rules, and Scorecard guidance.
    • reference/: A directory containing deep-dive documentation on specific topics:
      • memory-management.md: Lifecycle and cleanup patterns.
      • type-safety.md: Type narrowing and safety.
      • ui-ux.md: UI standards and commands.
      • file-operations.md: Vault and file API usage.
      • css-styling.md: Theming and styling.
      • accessibility.md: Mandatory A11y requirements.
      • code-quality.md: Security and best practices.
      • submission.md: Publishing guidelines.
      • community-scanner.md: Scanner behavior and Scorecard optimization.
      • eslint-setup.md: ESLint configuration guide.
  3. Create a new Obsidian plugin with the Interactive Boilerplate Generator

    main

    The skill includes a tool to generate a production-ready TypeScript boilerplate that adheres to Obsidian's best practices and submission guidelines. It creates a complete directory structure including main.ts, settings.ts (using the declarative API), manifest.json, and build configurations.

    Key Features:

    • Real-time Validation: Validates plugin name, ID, and description against Obsidian's submission rules (e.g., prevents using "Obsidian" in the ID).
    • Declarative Settings: Automatically sets up the settings tab using getSettingDefinitions() for Obsidian 1.13+ compatibility.
    • Clean Slate: Generates code without sample/template logic to ensure a clean starting point.

    To run the generator, point to the create-plugin.js file in your local installation of the skill repository.

    node /path/to/obsidian-plugin-skill/tools/create-plugin.js
  4. Follow Obsidian Plugin Naming and Description Rules

    main

    To pass automated community reviews, your plugin must adhere to strict naming and description constraints. Failure to follow these will result in submission rejection.

    Plugin ID & Name:

    • ID: Must be lowercase only. Do not include the word "obsidian". Do not end with "plugin".
    • Name: Do not include "Obsidian". Do not end with "Plugin". Do not start with "Obsi" or end with "dian".

    Description:

    • Do not use phrases like "Obsidian" or "This plugin".
    • The description must end with punctuation: ., ?, !, or ).
    • Keep descriptions under 250 characters for best results.
  5. Invoke the Obsidian skill in your coding agent

    main

    Once installed, the skill is automatically discovered by your agent. You can invoke it using provider-specific syntax:

    ProviderLoad SkillCreate Plugin
    Claude Code/obsidian/create-plugin
    Codex (OpenAI)$obsidian—
    Windsurf@obsidian—

    You can also use natural language to trigger the skill's knowledge, for example: Help me implement a new command for my Obsidian plugin.

  6. Implement Mandatory Accessibility (A11y) Standards

    main

    Accessibility is mandatory for Obsidian plugins. Ensure your plugin meets the following requirements:

    • Keyboard Navigation: All interactive elements must be accessible via Tab, Enter, and Space.
    • ARIA Labels: Provide aria-label attributes for all icon buttons.
    • Focus Indicators: Define clear focus styles using the :focus-visible CSS pseudo-class.
    • Touch Targets: Ensure mobile/touch targets are at least 44×44px.
    • Tooltips: Position tooltips using the data-tooltip-position attribute.
  7. Follow UI/UX and Styling Standards

    main

    To ensure your plugin feels native to Obsidian:

    • Text Casing: Use sentence case for all UI text, including command names, settings, and locale files.
    • Command Naming: Do not include the word "command" in command names or IDs. Do not include your plugin's ID or name in command IDs/names.
    • Styling: Use Obsidian's built-in CSS variables. Scope all CSS to your plugin's container to avoid leaking styles. Do not create <link> or <style> elements manually.
    • Settings: For Obsidian 1.13+, implement getSettingDefinitions() so settings appear in global search. Use this.update() to refresh settings instead of this.display().
  8. Configure eslint-plugin-obsidianmd for Development

    main

    Install the official ESLint plugin to automatically check your code against Obsidian's community standards and security rules.

    Installation:

    npm install --save-dev eslint eslint-plugin-obsidianmd

    Configuration (eslint.config.mjs): The recommended config includes typescript-eslint (type-checked), security plugins, and Obsidian-specific rules. You do not need a separate typescript-eslint setup.

    import { defineConfig } from "eslint/config";
    import obsidianmd from "eslint-plugin-obsidianmd";
    
    export default defineConfig([
      { ignores: ["main.js", "*.mjs"] },
      ...obsidianmd.configs.recommended,
      {
        languageOptions: {
          parserOptions: {
            projectService: true,
          },
        },
      },
    ]);

    Auto-fixing: Many rule violations can be fixed automatically using:

    npx eslint --fix .
  9. Install the Obsidian Plugin Development Skill

    main

    You can install this skill using one of three methods depending on your workflow:

    Use npx to add the skill directly to your environment:

    npx skills add https://github.com/gapmiss/obsidian-plugin-skill --skill obsidian

    2. Installer Script (Best for local setup)

    Clone the repository and run the provided shell script to install to specific provider directories (.agents/skills/ or .claude/skills/):

    git clone https://github.com/gapmiss/gapmiss/obsidian-plugin-skill.git
    cd obsidian-plugin-skill
    ./install-skill.sh

    3. Manual Install

    For Claude Code: Copy the skill files to .claude/skills/obsidian and the slash commands to .claude/commands/.

    For Codex (OpenAI) or Windsurf: Copy the skill files to .agents/skills/obsidian/.

    npx skills add https://github.com/gapmiss/gapmiss/obsidian-plugin-skill --skill obsidian
  10. Use Type-Safe File Operations

    main

    Avoid unsafe type casting when working with Obsidian's file system. Use instanceof to narrow types for TFile or TFolder.

    Recommended APIs:

    • Active Edits: Use the Editor API for editing the currently active file.
    • Background Mods: Use Vault.process() or processFrontMatter() for non-interactive file modifications.
    • File Deletion: Use FileManager.trashFile().
    • Path Handling: Use normalizePath() for user-provided paths.
    • File Retrieval: Use Vault.getAbstractFileByPath() instead of iterating through all files.
    // CORRECT: Safe type narrowing
    if (abstractFile instanceof TFile) {
      const file = abstractFile;
    }
    
    // INCORRECT: Unsafe cast
    const file = abstractFile as TFile;
  11. Reference: Mandatory Accessibility (A11y) requirements

    main

    When developing UI for Obsidian plugins, the following accessibility standards are strictly enforced by this skill:

    • Keyboard Navigation: Mandatory for all interactive elements.
    • ARIA Labels: Mandatory for icon buttons and controls.
    • Focus Indicators: Mandatory CSS styling for focus states.
    • Touch Targets: Minimum size of 44×44px.
    • Screen Readers: Must support screen reader announcements.
    • Tooltips: Use data-tooltip-position for positioning.