mcpField
O
obsidian-dev-rules

obsidian-dev-rules

github.com/agents365-aiDevelopment97271 installsUpdated 2w ago
Repository

About obsidian-dev-rules

obsidian-dev-rules is a skill for building and reviewing Obsidian plugins, themes, and snippets. It organizes official development guidance into topic-based references covering APIs, resource cleanup, safe DOM practices, and release requirements.

Key features

  1. 01Guide plugin lifecycle and resource cleanup
  2. 02Cover Vault, Editor, and event APIs
  3. 03Organize commands, settings, views, and UI
  4. 04Explain theme and snippet development
  5. 05Describe community directory submission requirements

Use cases

  1. 01Build or debug Obsidian plugins
  2. 02Review note access and editor integrations
  3. 03Create themes or CSS snippets and prepare releases

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/agents365-ai/365-skills --skill obsidian-dev-rules

After installing, type/obsidian-dev-rulesin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
plugin-basics.md
themes-and-release.md
ui.md
vault-and-editor.md

Details

From the project README

Obsidian Dev Rules

Obsidian is extended two ways: plugins (TypeScript against the Obsidian API) and themes/snippets (CSS). This skill mirrors the official developer docs at https://docs.obsidian.md so you can build and review Obsidian plugins/themes without re-fetching. The API ships as the obsidian npm package; the canonical starting point is the obsidian-sample-plugin.

When to use this skill

  • Building, debugging, or reviewing an Obsidian plugin (lifecycle, commands, settings, UI, views).
  • Reading/writing notes via the Vault API; manipulating the active note via the Editor API.
  • Subscribing to events, registering Markdown post-processors / code-block processors, or CodeMirror 6 editor extensions.
  • Building a theme (CSS variables, theme.css, manifest) or snippets.
  • Releasing/submitting a plugin or theme to the community directory.

Reference index — load the file you need

FileCovers
references/plugin-basics.mdProject setup, manifest.json, Plugin lifecycle (onload/onunload), resource registration & cleanup, events, dev workflow / hot reload, debugging
references/vault-and-editor.mdVault API (read/cachedRead/create/modify/process/delete, TFile/TFolder, adapter, normalizePath), Editor API, Markdown post-processing & code-block processors, CodeMirror 6 editor extensions
references/ui.mdCommands (callback variants, hotkeys), Settings (PluginSettingTab, load/saveData, Setting controls), Modals (Modal/SuggestModal/FuzzySuggestModal), Views (ItemView, registerView, workspace leaves), ribbon/status bar
references/themes-and-release.mdThemes (CSS variables, theme.css/manifest, body classes, snippets), submitting plugins & themes, developer policies & guidelines

Cheat sheet

import { Plugin, Notice, MarkdownView, TFile, normalizePath } from 'obsidian';

export default class MyPlugin extends Plugin {
  async onload() {
    await this.loadSettings();
    this.addRibbonIcon('dice', 'Greet', () => new Notice('Hello!'));
    this.addCommand({ id: 'do-x', name: 'Do X', callback: () => {/* ... */} });
    this.addSettingTab(new MySettingTab(this.app, this));
    // Auto-cleaned on unload — always register through these:
    this.registerEvent(this.app.vault.on('modify', (f) => {/* ... */}));
    this.registerInterval(window.setInterval(() => {/* ... */}, 1000));
    this.registerDomEvent(document, 'click', () => {/* ... */});
  }
  onunload() { /* release anything NOT registered via register*/ }
}
// Vault: prefer process() over read()+modify(); use cachedRead() for display only.
const file = this.app.vault.getFileByPath('Notes/x.md');
await this.app.vault.process(file, (data) => data.replace('foo', 'bar'));
// Editor of the active note (preserves cursor/selection):
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
view?.editor.replaceSelection(view.editor.getSelection().toUpperCase());

Plugin files: manifest.json + main.js (+ optional styles.css) in <vault>/.obsidian/plugins/<id>/. Theme files: manifest.json + theme.css in <vault>/.obsidian/themes/<name>/.

Hard rules

  • Use this.app, never the global app (global exists for debugging only and may be removed).
  • Register everything that needs teardown via registerEvent / registerInterval / registerDomEvent / addCommand / registerView / registerMarkdownPostProcessor — Obsidian auto-cleans those on unload. Manually release anything else in onunload(). Leaked listeners/ intervals degrade Obsidian after the plugin is disabled.
  • Never use innerHTML / outerHTML / insertAdjacentHTML with dynamic content — build DOM with createEl() / createDiv() / createSpan().
  • Prefer the Vault API over the Adapter API; use getFileByPath() (not iterate-all); always normalizePath() user-supplied paths. Use process() (atomic) instead of sequential read()+modify() to avoid data loss; cachedRead() only when you won't write it back.
  • For the active note, edit via the Editor interface, not Vault.modify — it preserves the cursor and selection.
  • Don't store references to view instances; Obsidian may recreate them — fetch with getLeavesOfType() / getActiveViewOfType().
  • Don't set default hotkeys for distributed plugins (OS-dependent, conflict-prone). UI text is sentence case. Use CSS classes + Obsidian CSS variables, not hardcoded inline styles.
  • manifest.json required fields: id, name, version (semver x.y.z), minAppVersion, description, author, isDesktopOnly. id must not contain "obsidian"; name is Basic-Latin, no emoji/punctuation except hyphens.
  • Release: GitHub release whose tag equals the manifest version, with main.js, manifest.json, and optional styles.css attached as individual binary assets (not zipped).
  • Use async/await (not Promise chains); const/let (not var).

Comments

Markdown supported