Loading...
Loading...
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.
npx skill4agent add akillness/oh-my-skills obsidian-pluginKeyword:·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
eslint-plugin-obsidianmdregisterEventas TFileany# 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-pluginsrc/main.tssrc/settings.tsmanifest.jsonstyles.csstsconfig.jsonpackage.jsonesbuild.config.mjsversion-bump.mjsversions.jsonLICENSEnpm install --save-dev eslint eslint-plugin-obsidianmd// eslint.config.mjs
import pluginObsidianmd from "eslint-plugin-obsidianmd";
export default [
pluginObsidianmd.configs.recommended,
// For locale string checking:
// pluginObsidianmd.configs.recommendedWithLocalesEn,
];npx eslint src/
npx eslint src/ --fix # auto-fix where possiblebash scripts/install.sh| 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 |
# Validate your manifest.json
node scripts/create-plugin.js --validate-only| 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 |
| Rule | Auto-fix | Description |
|---|---|---|
| No | Use |
| No | Never store direct view references (causes memory leaks) |
| Rule | Auto-fix | Description |
|---|---|---|
| No | Avoid |
| 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 |
| Rule | Auto-fix | Description |
|---|---|---|
| No | Use |
| No | Use |
| No | Remove |
| No | Use |
| 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 |
| Rule | Auto-fix | Description |
|---|---|---|
| No | Icon buttons must have |
| No | All interactions must be keyboard accessible |
| No | Use |
// ✅ 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));// ✅ 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;// ✅ 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');/* ✅ 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;
}| Task | Command |
|---|---|
| Generate boilerplate | |
| Install ESLint | |
| Run ESLint | |
| Auto-fix ESLint | |
| Build plugin | |
| Dev watch mode | |
| Bump version | |
any