plugins/obsidian-development/skills/obsidian-check/SKILL.md
Reviews code against all Obsidian automated plugin review rules and reports violations with fixes. Use PROACTIVELY before any git push on an Obsidian plugin project. TRIGGER WHEN: preparing an Obsidian plugin for submission or before pushing code DO NOT TRIGGER WHEN: the task is outside the specific scope of this component.
npx skillsauth add acaprino/anvil-toolset obsidian-checkInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Review code against all Obsidian automated plugin review rules before pushing. Since May 2026 the review runs on the Community hub (community.obsidian.md) and scans every GitHub release; a failing version is removed from directory search within 24 hours. Reports violations grouped by severity with exact file locations and fixes.
/obsidian-check -- scans the current Obsidian plugin project for all automated review violations.
Check that manifest.json, package.json, and src/ exist. If not, abort with message.
Check if eslint-plugin-obsidianmd and @eslint-community/eslint-plugin-eslint-comments are in package.json devDependencies. If NOT installed:
npm install --save-dev eslint eslint-plugin-obsidianmd @eslint-community/eslint-plugin-eslint-comments @typescript-eslint/parser typescript-eslint @eslint/js
eslint.config.mjs, .eslintrc.*), create eslint.config.mjs. The eslint-comments block mirrors checks that Obsidian's review platform adds on top of the obsidianmd recommended config:import tsparser from "@typescript-eslint/parser";
import { defineConfig } from "eslint/config";
import obsidianmd from "eslint-plugin-obsidianmd";
import comments from "@eslint-community/eslint-plugin-eslint-comments/configs";
export default defineConfig([
...obsidianmd.configs.recommended,
comments.recommended,
{
rules: {
"@eslint-community/eslint-comments/require-description": "error",
"@eslint-community/eslint-comments/no-restricted-disable": [
"error",
"obsidianmd/no-static-styles-assignment",
"obsidianmd/ui/sentence-case",
],
},
},
{
files: ["**/*.ts"],
languageOptions: {
parser: tsparser,
parserOptions: { project: "./tsconfig.json" },
},
},
]);
npx tsc --noEmit
Report any type errors.
npx eslint src/ package.json 2>&1
Lint package.json too, not just src/: the recommended config runs depend/ban-dependencies on it (flags deprecated packages like builtin-modules, replaced by node:module's builtinModules).
This covers sentence case (ui/sentence-case), inline styles, command rules, manifest validation, TFile/TFolder casts, forbidden elements, popout-window compatibility (prefer-active-doc, prefer-window-timers, no-global-this), API availability vs minAppVersion (no-unsupported-api), undescribed or forbidden eslint-disable directives, and more. Report all ESLint errors and warnings.
These checks catch issues NOT covered by eslint-plugin-obsidianmd. Run by reading the source code:
| # | Check | How to detect |
|---|-------|---------------|
| 1 | No unnecessary type assertions | Search for as Type where ?? fallback makes it redundant |
| 2 | Promises handled | Search for async function calls without await, void, .catch(), or .then() with rejection |
| 3 | No async without await | Search for async methods with no await inside |
| 4 | No promise where void expected | Search for async callbacks in event handlers that expect void |
| 5 | No object stringification | Search for template literals with ?? where left side could be an object |
| 6 | Setting.setHeading() | Search for createEl('h1'), createEl('h2'), createEl('h3') in settings/modals |
| # | Check | How to detect |
|---|-------|---------------|
| 1 | Unused imports | TypeScript check catches these |
| 2 | Unused variables | TypeScript check catches these |
| 3 | console.log in lifecycle | Search for console.log in onload()/onunload() |
| 4 | createEl helpers | Search for document.createElement(, document.createDocumentFragment(, createEl('span', createEl('div' -- replace with createEl(), createFragment(), createSpan(), createDiv(). Covers obsidianmd/prefer-create-el: the review platform enforces it, but the rule is not yet in the npm release, so local ESLint misses it |
| 5 | Local storage | Search for localStorage and sessionStorage -- persist plugin data with Plugin.loadData()/saveData(); for device-specific per-vault values use App.loadLocalStorage()/App.saveLocalStorage(). Raw localStorage is shared across all vaults on the device and sessionStorage does not survive a restart |
id: alphanumeric + dashes, no "obsidian", no "plugin" suffixname: no "Obsidian", no "Plugin" suffixdescription: no "Obsidian", no "This plugin", must end with . ? ! ), under 250 charsid, name, version, minAppVersion, description, authorversion matches latest git tag (if any)minAppVersion covers every API the code calls (obsidianmd/no-unsupported-api flags APIs newer than it, e.g. Workspace.revealLeaf needs 1.7.2)Output a structured report:
## Obsidian Lint Report
### TypeScript: [PASS/FAIL]
[errors if any]
### ESLint: [PASS/FAIL]
[errors if any]
### Required Violations: [count]
[grouped by rule, with file:line and suggested fix]
### Optional Warnings: [count]
[grouped by rule]
### Manifest: [PASS/FAIL]
[issues if any]
### License: [PASS/FAIL]
[issues if any]
---
**Result: [READY TO PUSH / FIX REQUIRED ISSUES FIRST]**
[count] required issues, [count] warnings
If violations are found, ask:
For auto-fix, apply changes following the obsidian-plugin-development skill rules (move styles to CSS classes, fix sentence case, remove unnecessary assertions, void unhandled promises, etc.).
development
Quality gates for multi-reviewer code review pipelines: adversarial verification panel, completeness critic, reviewer pipeline conventions, and the context sharing pattern for parallel reviewers. TRIGGER WHEN: running /senior-review:team-review quality gates; running /senior-review:code-review Steps 4b/4c (adversarial verification and completeness check); consolidating or deduplicating findings from multiple parallel reviewers. DO NOT TRIGGER WHEN: single-reviewer style review without a consolidation phase, or generic team coordination (the upstream agent-teams skills cover that).
development
Knowledge base for pure-architecture decisions on when to unify duplicated logic into a shared abstraction versus leave it duplicated. Covers the canonical theory (Rule of Three, DRY/WET/AHA, Wrong Abstraction, Locality of Behaviour, Bounded Contexts, Tidy First options framing, CUPID vs SOLID), 12 essential-duplication patterns that justify unification, 12 wrong-abstraction patterns that justify inlining or decomposition, an operational decision frame, and a verified reading list. TRIGGER WHEN: the user is making an architectural decision about whether to centralize, extract, or remove a layer; reviewing an abstraction for premature generality; auditing scattered cross-cutting concerns; spawned by the abstraction-architect agent during /abstraction-architect:audit or as the Abstraction dimension of /senior-review:team-review or /senior-review:code-review; the user asks "should I extract this into a service" / "is this DRY enough" / "is this wrong abstraction". DO NOT TRIGGER WHEN: the task is code formatting and readability cleanup (use clean-code:clean-code), Python-specific refactoring with metrics (use python-development:python-refactor), generic dead-code removal (use senior-review:cleanup-dead-code), security review (use senior-review:security-auditor), or pure pattern-consistency review without an architecture lens (use senior-review:code-auditor).
development
Unified web frontend knowledge base covering CSS architecture, UX psychology, UI components, distinctive aesthetics, and interface design generation. TRIGGER WHEN: working on web styling, design systems, component decisions, responsive strategy, distinctive frontend aesthetics, or exploring multiple interface designs. DO NOT TRIGGER WHEN: the task is purely backend or unrelated to web frontend.
development
Stripe payments knowledge base - API patterns, checkout optimization, subscription lifecycle, pricing strategies, webhook reliability, Firebase integration, cost analysis, and revenue modeling. Loaded by stripe-integrator and revenue-optimizer agents; also consumable directly when the user asks for Stripe-specific patterns without needing an agent. TRIGGER WHEN: working with Stripe API (Payment Intents, Customers, Subscriptions, Checkout Sessions, Connect, webhooks, tax, usage-based billing), pricing strategy, or revenue modeling. DO NOT TRIGGER WHEN: payment work is non-Stripe (PayPal, Square, crypto) or the task is generic e-commerce unrelated to payments.