| name | obsidian-plugin |
| description | ALIAS — merged into the unified `obsidian` skill (v2.0). Use the `obsidian` skill instead. Build, validate, and publish Obsidian plugins. Redirects to obsidian skill for plugin development, ESLint rules, boilerplate generation, accessibility, and submission validation.
|
| allowed-tools | Bash Read Write Edit Glob Grep WebFetch |
| license | MIT |
| metadata | {"tags":"obsidian, plugin-development, eslint, typescript, boilerplate, submission, accessibility","version":"1.1","source":"https://github.com/gapmiss/obsidian-plugin-skill","deprecated":"Merged into obsidian skill v2.0 — use obsidian instead"} |
obsidian-plugin — Obsidian Plugin Development Skill
Keyword: obsidian plugin · create obsidian plugin · obsidian eslint · obsidian submission
Build high-quality Obsidian plugins that pass community review on first attempt.
Covers all 27 rules from eslint-plugin-obsidianmd v0.1.9, boilerplate generation,
vault API patterns, accessibility requirements, and submission validation.
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 (
registerEvent, no view reference storage)
- Implement proper type safety (no unsafe
as TFile casts, no 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
node scripts/create-plugin.js
npx github:gapmiss/obsidian-plugin-skill create-plugin
The generator produces:
src/main.ts — Plugin class with settings integration
src/settings.ts — Settings interface and PluginSettingTab
manifest.json — Validated plugin metadata
styles.css — CSS scaffold with Obsidian variables comment
tsconfig.json, package.json, esbuild.config.mjs — Build toolchain
version-bump.mjs, versions.json — Version management
LICENSE — MIT with auto-populated year/author
Step 2: Install ESLint validation
npm install --save-dev eslint eslint-plugin-obsidianmd
import pluginObsidianmd from "eslint-plugin-obsidianmd";
export default [
pluginObsidianmd.configs.recommended,
];
Run validation:
npx eslint src/
npx eslint src/ --fix
Step 3: Follow the submission validation workflow
- Run
bash scripts/install.sh to set up the development environment
- 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 ., ?, !, or ) |
node scripts/create-plugin.js --validate-only
ESLint Rules Summary (27 rules)
Submission & Naming
| Rule | Auto-fix | Description |
|---|
no-obsidian-in-id | No | Plugin ID must not contain "obsidian" |
no-plugin-suffix-in-id | No | Plugin ID must not end with "-plugin" |
no-obsidian-in-name | No | Plugin name must not contain "Obsidian" |
no-plugin-suffix-in-name | No | Plugin name must not end with "Plugin" |
valid-description | No | Description format validation |
Memory & Lifecycle
| Rule | Auto-fix | Description |
|---|
prefer-register-event | No | Use this.registerEvent() for automatic cleanup |
no-view-reference | No | Never store direct view references (causes memory leaks) |
Type Safety
| Rule | Auto-fix | Description |
|---|
no-tfile-cast | No | Avoid as TFile / as TFolder (use instanceof) |
UI/UX (sentence-case rules — mostly auto-fixable)
| Rule | Auto-fix | Description |
|---|
sentence-case | Yes | All UI text in sentence case |
no-plugin-name-in-command | No | Commands must not repeat plugin name |
no-command-in-command | No | Commands must not include the word "command" |
no-default-hotkey | No | Do not define default hotkeys |
no-manual-headings | No | Settings UI: use setHeading(), not manual HTML |
API Best Practices
| Rule | Auto-fix | Description |
|---|
no-global-app | No | Use this.app, not global app |
prefer-request-url | No | Use requestUrl(), not fetch() |
no-console-log | No | Remove console.log before submission |
prefer-abstract-input-suggest | No | Use AbstractInputSuggest for suggestions |
Styling
| Rule | Auto-fix | Description |
|---|
no-inline-styles | No | Use CSS classes; no inline style attributes |
prefer-css-variables | No | Use Obsidian CSS variables, not hardcoded colors |
scope-plugin-styles | No | Scope all CSS to plugin ID selector |
Accessibility (MANDATORY)
| Rule | Auto-fix | Description |
|---|
require-aria-label | No | Icon buttons must have aria-label |
require-keyboard-nav | No | All interactions must be keyboard accessible |
require-focus-visible | No | Use :focus-visible CSS for focus indicators |
Key Code Patterns
Memory-safe event registration
this.registerEvent(
this.app.vault.on('create', (file) => this.handleCreate(file))
);
this.app.vault.on('create', (file) => this.handleCreate(file));
Type-safe file access
const file = this.app.workspace.getActiveFile();
if (file instanceof TFile) {
await this.app.vault.read(file);
}
const file = this.app.workspace.getActiveFile() as TFile;
Accessibility — ARIA on icon buttons
const btn = containerEl.createEl('button', { cls: 'clickable-icon' });
btn.setAttribute('aria-label', 'Delete note');
setIcon(btn, 'trash');
const btn = containerEl.createEl('button', { cls: 'clickable-icon' });
setIcon(btn, 'trash');
CSS with Obsidian variables
.my-plugin-button {
background-color: var(--interactive-accent);
color: var(--text-on-accent);
border-radius: var(--radius-m);
}
.my-plugin-button {
background-color: #7c3aed;
color: white;
}
Quick Reference
| Task | Command |
|---|
| Generate boilerplate | node scripts/create-plugin.js |
| Install ESLint | npm install --save-dev eslint eslint-plugin-obsidianmd |
| Run ESLint | npx eslint src/ |
| Auto-fix ESLint | npx eslint src/ --fix |
| Build plugin | npm run build |
| Dev watch mode | npm run dev |
| Bump version | npm run 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
any, const/let
- UI/UX Guide — Sentence case, commands, settings structure
- eslint-plugin-obsidianmd — Official ESLint rules
- Obsidian Plugin Developer Docs
- Source Skill Repository — MIT License