obsidian-plugin
Original:🇺🇸 English
Translated
2 scripts
Build, validate, and publish Obsidian plugins following official community submission standards. Use when developing an Obsidian plugin from scratch, reviewing existing plugin code, fixing ESLint violations from eslint-plugin-obsidianmd, preparing a plugin for community directory submission, or applying Obsidian-specific best practices (memory management, type safety, accessibility, CSS variables, vault API). Triggers on: obsidian plugin, obsidian development, obsidian-plugin, create obsidian plugin, obsidian eslint, obsidian submission, obsidian community plugin, obsidian API, plugin boilerplate, obsidian typescript, obsidian vault, obsidian settings, obsidian commands.
3installs
Sourceakillness/oh-my-skills
Added on
NPX Install
npx skill4agent add akillness/oh-my-skills obsidian-pluginTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →obsidian-plugin — Obsidian Plugin Development Skill
Keyword:·obsidian plugin·create obsidian plugin·obsidian eslintobsidian submissionBuild high-quality Obsidian plugins that pass community review on first attempt. Covers all 27 rules fromv0.1.9, boilerplate generation, vault API patterns, accessibility requirements, and submission validation.eslint-plugin-obsidianmd
When to use this skill
- Generate a new Obsidian plugin project with clean boilerplate (no sample code bloat)
- Review and fix ESLint violations from
eslint-plugin-obsidianmd - Prepare a plugin for Obsidian community directory submission
- Apply memory-safe lifecycle patterns (, no view reference storage)
registerEvent - Implement proper type safety (no unsafe casts, no
as TFile)any - Enforce accessibility requirements (keyboard navigation, ARIA labels, focus management)
- Apply Obsidian CSS variables for theme-compatible styling
- Validate plugin metadata (manifest.json, plugin ID/name/description rules)
Instructions
Step 1: Generate a new plugin project
bash
# Interactive boilerplate generator — validates metadata against submission rules
node scripts/create-plugin.js
# Or use npx directly from the source repo
npx github:gapmiss/obsidian-plugin-skill create-pluginThe generator produces:
- — Plugin class with settings integration
src/main.ts - — Settings interface and PluginSettingTab
src/settings.ts - — Validated plugin metadata
manifest.json - — CSS scaffold with Obsidian variables comment
styles.css - ,
tsconfig.json,package.json— Build toolchainesbuild.config.mjs - ,
version-bump.mjs— Version managementversions.json - — MIT with auto-populated year/author
LICENSE
Step 2: Install ESLint validation
bash
npm install --save-dev eslint eslint-plugin-obsidianmdjson
// eslint.config.mjs
import pluginObsidianmd from "eslint-plugin-obsidianmd";
export default [
pluginObsidianmd.configs.recommended,
// For locale string checking:
// pluginObsidianmd.configs.recommendedWithLocalesEn,
];Run validation:
bash
npx eslint src/
npx eslint src/ --fix # auto-fix where possibleStep 3: Follow the submission validation workflow
- Run to set up the development environment
bash scripts/install.sh - Validate plugin ID and name against naming rules (see below)
- Run ESLint — all 27 rules must pass
- Complete the Code Review Checklist (see References)
- Submit PR to obsidianmd/obsidian-releases
Plugin Naming Rules
| Field | Rule |
|---|---|
| Plugin ID | Lowercase, alphanumeric + dashes/underscores; no "obsidian"; no "plugin" suffix |
| Plugin Name | No "Obsidian" word; no "Plugin" suffix; no "Obsi" prefix or "dian" suffix |
| Description | No "Obsidian" word; no "This plugin"; must end with |
bash
# Validate your manifest.json
node scripts/create-plugin.js --validate-onlyESLint Rules Summary (27 rules)
Submission & Naming
| Rule | Auto-fix | Description |
|---|---|---|
| No | Plugin ID must not contain "obsidian" |
| No | Plugin ID must not end with "-plugin" |
| No | Plugin name must not contain "Obsidian" |
| No | Plugin name must not end with "Plugin" |
| No | Description format validation |
Memory & Lifecycle
| Rule | Auto-fix | Description |
|---|---|---|
| No | Use |
| No | Never store direct view references (causes memory leaks) |
Type Safety
| Rule | Auto-fix | Description |
|---|---|---|
| No | Avoid |
UI/UX (sentence-case rules — mostly auto-fixable)
| Rule | Auto-fix | Description |
|---|---|---|
| Yes | All UI text in sentence case |
| No | Commands must not repeat plugin name |
| No | Commands must not include the word "command" |
| No | Do not define default hotkeys |
| No | Settings UI: use |
API Best Practices
| Rule | Auto-fix | Description |
|---|---|---|
| No | Use |
| No | Use |
| No | Remove |
| No | Use |
Styling
| Rule | Auto-fix | Description |
|---|---|---|
| No | Use CSS classes; no inline |
| No | Use Obsidian CSS variables, not hardcoded colors |
| No | Scope all CSS to plugin ID selector |
Accessibility (MANDATORY)
| Rule | Auto-fix | Description |
|---|---|---|
| No | Icon buttons must have |
| No | All interactions must be keyboard accessible |
| No | Use |
Key Code Patterns
Memory-safe event registration
typescript
// ✅ Correct — auto-cleaned on plugin unload
this.registerEvent(
this.app.vault.on('create', (file) => this.handleCreate(file))
);
// ❌ Wrong — leaks memory
this.app.vault.on('create', (file) => this.handleCreate(file));Type-safe file access
typescript
// ✅ Correct — instanceof narrowing
const file = this.app.workspace.getActiveFile();
if (file instanceof TFile) {
await this.app.vault.read(file);
}
// ❌ Wrong — unsafe cast
const file = this.app.workspace.getActiveFile() as TFile;Accessibility — ARIA on icon buttons
typescript
// ✅ Correct
const btn = containerEl.createEl('button', { cls: 'clickable-icon' });
btn.setAttribute('aria-label', 'Delete note');
setIcon(btn, 'trash');
// ❌ Wrong — no aria-label
const btn = containerEl.createEl('button', { cls: 'clickable-icon' });
setIcon(btn, 'trash');CSS with Obsidian variables
css
/* ✅ Correct — theme-compatible */
.my-plugin-button {
background-color: var(--interactive-accent);
color: var(--text-on-accent);
border-radius: var(--radius-m);
}
/* ❌ Wrong — hardcoded colors */
.my-plugin-button {
background-color: #7c3aed;
color: white;
}Quick Reference
| Task | Command |
|---|---|
| Generate boilerplate | |
| Install ESLint | |
| Run ESLint | |
| Auto-fix ESLint | |
| Build plugin | |
| Dev watch mode | |
| Bump version | |
References
- Accessibility Guide — Keyboard nav, ARIA, focus management (MANDATORY)
- Code Quality Guide — Security, platform compat, API usage
- CSS Styling Guide — Obsidian variables, scoped styles, dark/light mode
- File Operations Guide — Vault API, editor vs vault, atomic ops
- Memory Management Guide — registerEvent, lifecycle patterns
- Submission Guide — Repository structure, naming, submission process
- Type Safety Guide — instanceof narrowing, no , const/let
any - UI/UX Guide — Sentence case, commands, settings structure
- eslint-plugin-obsidianmd — Official ESLint rules
- Obsidian Plugin Developer Docs
- Source Skill Repository — MIT License