A comprehensive agent skill for developing high-quality Obsidian plugins that follow best practices, pass code review, and adhere to official submission guidelines.
Repo: gapmiss/obsidian-plugin-skill
What's inside
A comprehensive agent skill for developing high-quality Obsidian plugins that follow best practices, pass code review, and adhere to official submission guidelines.
This skill provides your coding agent with deep knowledge of Obsidian plugin development standards, including:
eslint-plugin-obsidianmd v0.4.1getSettingDefinitions()), the Obsidian 1.13 settings APInpx skills add https://github.com/gapmiss/obsidian-plugin-skill --skill obsidian
Clone this repository:
git clone https://github.com/gapmiss/obsidian-plugin-skill.git
cd obsidian-plugin-skill
Run the installer:
./install-skill.sh
Select your provider(s):
.agents/skills/ and .claude/skills/.claude/skills/ with slash commands.agents/skills/.agents/skills/Choose installation target (current directory or custom path)
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/
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/
Just open this directory with your coding agent โ no installation needed!
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.
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:
src/ directory structure with main.ts and settings.tsgetSettingDefinitions()), so it's lint-clean and searchable on Obsidian 1.13+. To target older Obsidian, lower minAppVersion and add a display() fallback โ see Path BWhat 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.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 )
| 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.
data-tooltip-positionThe main SKILL.md file highlights the most important rules organized by category:
Submission & Naming:
.?!) punctuationMemory & Lifecycle:
6. Use registerEvent() for automatic cleanup
7. Don't store view references in plugin
8. Don't call detachLeavesOfType() in onunload
Type Safety:
9. Use instanceof instead of type casting for TFile/TFolder
10. Use .instanceOf(T) for cross-window DOM checks
UI/UX:
11. Use sentence case for all UI text (ui/sentence-case, enabled as warn in v0.4.0)
12. Sentence case in locale JSON files
13. Sentence case in TS/JS locale modules
14. No "command" in command names/IDs
15. No plugin ID/name in command IDs/names
16. No default hotkeys
17. Use .setHeading() for settings headings
Declarative Settings (Obsidian 1.13+):
display() while minAppVersion < 1.13.0 (settings-tab/require-display)getSettingDefinitions() so settings appear in global search (settings-tab/prefer-setting-definitions)this.update(), not this.display() (settings-tab/prefer-update-over-display)display() once minAppVersion >= 1.13.0 and definitions exist (settings-tab/no-deprecated-display)API Best Practices:
18. Use Editor API for active file edits
19. Use Vault.process() for background file mods
20. Use FileManager.trashFile() for file deletion
21. Use Vault.getAbstractFileByPath() instead of iterating files
22. Use normalizePath() for user paths
23. Use Platform API for OS detection
24. Use requestUrl() instead of fetch()
25. No console.log in onload/onunload in production
26. Use built-in AbstractInputSuggest
27. Check minAppVersion for API compatibility
Popout Window Compatibility:
28. Use activeDocument/activeWindow instead of globals (prefer-active-doc, still off by default โ enable manually)
29. Use activeWindow.setTimeout() for timers
Event Handling:
30. Check evt.defaultPrevented in editor-drop/paste handlers
Styling:
31. Use Obsidian CSS variables
32. Scope CSS to plugin containers
33. Don't create <link> or <style> elements
Accessibility (MANDATORY): 34. Make all interactive elements keyboard accessible 35. Provide ARIA labels for icon buttons 36. Define clear focus indicators
Security & Compatibility:
innerHTML/outerHTMLCode Quality:
Object.assignregisterEvent(), addCommand(), registerDomEvent(), registerInterval()instanceof instead of type castingany typeconst and let over varAccessibility (A11y) - MANDATORY
:focus-visible)Plugin Submission Requirements
// Multiple issues
class MyPlugin extends Plugin {
view: CustomView;
async onload() {
this.registerView(VIEW_TYPE, (leaf) => {
this.view = new CustomView(leaf); // Memory leak!
return this.view;
});
this.addCommand({
id: 'my-plugin-show-command', // Redundant naming
name: 'Show Command', // Title Case
hotkeys: [{ modifiers: ['Mod'], key: 's' }], // Default hotkey
});
const file = abstractFile as TFile; // Unsafe cast
}
onunload() {
this.app.workspace.detachLeavesOfType(VIEW_TYPE); // Don't do this
}
}
// Following all guidelines
class TodoPlugin extends Plugin {
async onload() {
this.registerView(VIEW_TYPE, (leaf) => {
return new CustomView(leaf); // Create and return directly
});
this.addCommand({
id: 'show', // Clean naming
name: 'Show todo', // Sentence case
// Let users set their own hotkeys
checkCallback: (checking: boolean) => {
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
if (view) {
if (!checking) {
// Perform action
}
return true;
}
return false;
}
});
if (abstractFile instanceof TFile) {
// Safe type narrowing
const file = abstractFile;
}
}
onunload() {
// Let Obsidian handle cleanup
}
}
Use this checklist before submitting your plugin:
Submission Validation (will fail bot checks if incorrect):
Code Quality:
instanceof instead of casts)Accessibility (MANDATORY):
aria-label):focus-visible with proper CSS)data-tooltip-positionRelease Requirements:
For automatic checking, install the official ESLint plugin and typescript-eslint:
npm install --save-dev eslint typescript-eslint @typescript-eslint/parser eslint-plugin-obsidianmd
Important: The community plugin scanner uses both eslint-plugin-obsidianmd AND typescript-eslint type-checked rules. Most submission failures come from missing the typescript-eslint setup.
See the complete ESLint setup guide for:
eslint.config.mjs that matches the community scannerrecommended bundles the type-checked rules (v0.4.0)Quick config example (v0.4.0 โ recommended bundles typescript-eslint recommendedTypeChecked plus the security and import rules):
// eslint.config.mjs
import { defineConfig } from "eslint/config";
import tseslint from "typescript-eslint";
import obsidianmd from "eslint-plugin-obsidianmd";
export default defineConfig([
{ ignores: ["node_modules/**", "main.js", "*.mjs"] },
...obsidianmd.configs.recommended,
// Point the bundled type-checked rules at your tsconfig
{
files: ["**/*.ts"],
languageOptions: {
parser: tseslint.parser,
parserOptions: { project: "./tsconfig.json" },
},
},
]);
Many rules are auto-fixable with:
npx eslint --fix .
Found a missing guideline or rule? Please contribute!
.agents/skills/obsidian/SKILL.md.agents/skills/obsidian/reference/*.mdWhen adding new content:
.claude/skills/If you previously installed this skill to .claude/skills/obsidian/, you can migrate:
# Move skill files to the new location
mv .claude/skills/obsidian .agents/skills/obsidian
# Keep .claude/commands/ as-is (Claude Code only)
The .claude/skills/ path still works for Claude Code, but .agents/skills/ is the standard location recognized by all providers.
MIT License - See LICENSE file for details
This skill is based on:
eslint-plugin-obsidianmd packageThis skill follows Agent Skills standard best practices:
reference/ (no nesting)This structure allows your coding agent to load the essential information quickly while having access to comprehensive details when needed.
Note: Guidelines in this skill are based on eslint-plugin-obsidianmd v0.4.1 and the community.obsidian.md Scorecard system. The plugin and portal are under active development and may evolve.
.agents/
skills/
obsidian/
reference/
accessibility.md
code-quality.md
community-scanner.md
css-styling.md
eslint-setup.md
file-operations.md
memory-management.md
submission.md
type-safety.md
ui-ux.md
SKILL.md
.claude/
commands/
create-plugin.md
obsidian.md
.github/
FUNDING.yml
.gitignore
install-skill.sh
LICENSE
README.md
tools/
create-plugin.jsFAQ
obsidian-plugin-skill is a Claude Code plugin with hand-picked skills for development work, indexed on Flowy. Install it with the command on its page. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.