Profile
Back to NewsBack
GitHub Trending 12 min
Reader Mode
gapmiss/obsidian-plugin-skill: Agent SKILL for Obsidian.md plugin development

gapmiss/obsidian-plugin-skill: Agent SKILL for Obsidian.md plugin development

6 hours ago

Obsidian Plugin Development - Agent Skill

A comprehensive agent skill for developing high-quality Obsidian plugins that follow best practices, pass code review, and adhere to official submission guidelines.

Overview

This skill provides your coding agent with deep knowledge of Obsidian plugin development standards, including:

  • ESLint rules from eslint-plugin-obsidianmd v0.4.1
  • Declarative settings (getSettingDefinitions()), the Obsidian 1.13 settings API
  • Official Plugin Guidelines from Obsidian documentation
  • Submission via community.obsidian.md and Scorecard optimization
  • Memory management and lifecycle best practices
  • Security guidelines and XSS prevention
  • Platform compatibility (including iOS considerations)
  • Network request best practices (requestUrl vs fetch)

Prerequisites

  • A coding agent supporting the Agent Skills standard (Claude Code, OpenAI Codex, or Windsurf)
  • An Obsidian plugin project (or starting a new one)

Installation

Quick Install

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

Setup

Option 1: Installer Script (Recommended)

  1. Clone this repository:
git clone https://github.com/gapmiss/obsidian-plugin-skill.git
   cd obsidian-plugin-skill
  1. Run the installer:
./install-skill.sh
  1. Select your provider(s):
- All providers — installs to both .agents/skills/ and .claude/skills/ - Claude Code — installs to .claude/skills/ with slash commands - Codex (OpenAI) — installs to .agents/skills/ - Windsurf — installs to .agents/skills/
  1. Choose installation target (current directory or custom path)

Option 2: Manual Install

Claude Code

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

Copy skill

mkdir -p your-project/.claude/skills/obsidian cp -r .agents/skills/obsidian/* your-project/.claude/skills/obsidian/

Copy slash commands

mkdir -p your-project/.claude/commands cp .claude/commands/obsidian.md your-project/.claude/commands/ cp .claude/commands/create-plugin.md your-project/.claude/commands/

Codex (OpenAI) / Windsurf

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

Copy skill

mkdir -p your-project/.agents/skills/obsidian cp -r .agents/skills/obsidian/* your-project/.agents/skills/obsidian/

Option 3: Use as Standalone

Just open this directory with your coding agent — no installation needed!

Skill Structure

The skill uses progressive disclosure for optimal performance:

.agents/skills/obsidian/
├── SKILL.md                          # Main overview (~325 lines)
└── reference/                        # Detailed documentation
    ├── memory-management.md          # Lifecycle & cleanup patterns
    ├── type-safety.md                # Type narrowing & safety
    ├── ui-ux.md                      # UI standards & commands
    ├── file-operations.md            # Vault & file API
    ├── css-styling.md                # Theming & styling
    ├── accessibility.md              # A11y requirements (MANDATORY)
    ├── code-quality.md               # Best practices & security
    ├── submission.md                 # Publishing guidelines
    ├── community-scanner.md          # Scanner behavior & Scorecard (version-stamped)
    └── eslint-setup.md               # Complete ESLint config guide

SKILL.md provides a concise overview with ESLint rules and Scorecard guidance, while reference files contain comprehensive details on specific topics.

Quick Start: Creating a New Plugin

Interactive Boilerplate Generator

The fastest way to start a new Obsidian plugin with all best practices built-in:

node /path/to/obsidian-plugin-skill/tools/create-plugin.js

Features:

  • Generates clean TypeScript boilerplate with no sample code
  • Creates src/ directory structure with main.ts and settings.ts
  • Settings tab uses the declarative API (getSettingDefinitions()), so it's lint-clean and searchable on Obsidian 1.13+. To target older Obsidian, lower minAppVersion and add a display() fallback — see Path B
  • Validates plugin metadata in real-time against Obsidian's submission bot rules
  • Prompts for target directory to avoid overwriting existing files
  • Detects existing projects and only adds missing files
  • All generated code follows the skill's best practices automatically
What it creates:
your-plugin/
├── src/
│   ├── main.ts           # Plugin class with settings integration
│   └── settings.ts       # Settings interface, defaults, and declarative tab
├── manifest.json         # Validated plugin metadata
├── styles.css           # CSS with Obsidian variables
├── tsconfig.json        # TypeScript configuration
├── package.json         # Dependencies
├── esbuild.config.mjs   # Build configuration
├── eslint.config.mjs    # ESLint configuration
├── version-bump.mjs     # Version management script
├── versions.json        # Version tracking
├── .gitignore          # Git ignore rules
└── LICENSE             # MIT license

Interactive prompts:

  1. Target directory (default: current directory)
  2. Plugin name (validates: no "Obsidian", can't end with "Plugin")
  3. Plugin ID (validates: no "obsidian", can't end with "plugin", lowercase only)
  4. Description (validates: no "Obsidian"/"This plugin", must end with punctuation)
  5. Author name
  6. GitHub username (optional, auto-generates authorUrl)
  7. Minimum Obsidian version (default 1.13.0)
Real-time validation catches common mistakes:
❌ Validation Errors:
   • Plugin ID cannot contain "obsidian"
   • Plugin name cannot end with "Plugin"
   • Description must end with punctuation: . ? ! or )


Usage

Invoking the Skill

| Provider | Load skill | Create plugin | |----------|-----------|---------------| | Claude Code | /obsidian | /create-plugin | | Codex (OpenAI) | $obsidian | — | | Windsurf | @obsidian | — |

Skills are automatically discovered by your agent when present in the project directory. You can also invoke them explicitly using the commands above.

Just ask your agent naturally:

Help me implement a new command for my Obsidian plugin

Your agent will automatically use the Obsidian skill guidelines while helping you write code.

What the Skill Helps With

Code Quality

  • Prevents common memory leaks
  • Enforces type safety (no unsafe casts)
  • Ensures proper resource cleanup
  • Follows Obsidian's API patterns

UI/UX Standards

  • Enforces sentence case for all UI text
  • Prevents redundant naming patterns
  • Ensures consistent settings UI

Accessibility (A11y)

  • MANDATORY keyboard navigation for all interactive elements
  • MANDATORY ARIA labels for icon buttons and controls
  • MANDATORY focus indicators with proper CSS styling
  • Touch target size requirements (44×44px minimum)
  • Screen reader support and announcements
  • Tooltip positioning with data-tooltip-position

Security

  • Prevents XSS vulnerabilities (no innerHTML/outerHTML)
  • Validates manifest structure
  • Ensures proper path handling

Platform Compatibility

  • iOS compatibility checks (no regex lookbehind)
  • Cross-platform path handling
  • Mobile-friendly API usage

Submission Ready

  • Removes template/sample code
  • Validates manifest.json
  • Ensures LICENSE compliance
  • Follows submission requirements

What's Covered

Most Critical Rules (eslint-plugin-obsidianmd v0.4.1)

The main SKILL.md file highlights the most important rules organized by category:

Submission & Naming:

  1. Plugin ID: no "obsidian", can't end with "plugin"
  2. Plugin name: no "Obsidian", can't end with "Plugin"
  3. Plugin name: can't start with "Obsi" or end with "dian"
  4. Description: no "Obsidian", "This plugin", etc.
  5. Description must end with .?!) punctuation
Memory & Lifecycle:
  1. Use registerEvent() for automatic cleanup
  2. Don't store view references in plugin
  3. Don't call detachLeavesOfType() in onunload
Type Safety:
  1. Use instanceof instead of type casting for TFile/TFolder
  2. Use .instanceOf(T) for cross-window DOM checks
UI/UX:
  1. Use sentence case for all UI text (ui/sentence-case, enabled as warn in v0.4.0)
  2. Sentence case in locale JSON files
  3. Sentence case in TS/JS locale modules
  4. No "command" in command names/IDs
  5. No plugin ID/name in command IDs/names
  6. No default hotkeys
  7. Use .setHeading() for settings headings
Declarative Settings (Obsidian 1.13+):

  • Keep display() while minAppVersion < 1.13.0 (settings-tab/require-display)
  • Implement getSettingDefinitions() so settings appear in global search (settings-tab/prefer-setting-definitions)
  • Refresh with this.update(), not this.display() (settings-tab/prefer-update-over-display)
  • Drop display() once minAppVersion >= 1.13.0 and definitions exist (settings-tab/no-deprecated-display)
API Best Practices:
  1. Use Editor API for active file edits
  2. Use Vault.process() for background file mods
  3. Use FileManager.trashFile() for file deletion
  4. Use Vault.getAbstractFileByPath() instead of iterating files
  5. Use normalizePath() for user paths
  6. Use Platform API for OS detection
  7. Use requestUrl() instead of fetch()
  8. No console.log in onload/onunload in production
  9. Use built-in AbstractInputSuggest
  10. Check minAppVersion for API compatibility
Popout Window Compatibility:
  1. Use activeDocument/activeWindow instead of globals (prefer-active-doc, still off by default — enable manually)
  2. Use activeWindow.setTimeout() for timers
Event Handling:
  1. Check evt.defaultPrevented in editor-drop/paste handlers
Styling:
  1. Use Obsidian CSS variables
  2. Scope CSS to plugin containers
  3. Don't create or