Obsidian plugin quality audit

SkillDocs & knowledge

Audit ZettelFlow against the official Obsidian plugin guidelines and the Community-hub automated review / quality score. Use before a release, when preparing a directory submission, or when the user asks to "check plugin quality", "raise the Obsidian score", "run the reviewer", or "prepare for submission". Runs the same rule set Obsidian's automated reviewer uses and reports concrete, file-anchored fixes.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Obsidian plugin quality audit skill

What this skill tells your AI

The instructions your AI receives, as published by rafaelgb/obsidian-zettelflow in .claude/skills/obsidian-plugin-quality/SKILL.md and read by ahel’s review.

Obsidian's Community hub (May 2026) runs an automated review on every plugin version and publishes a 1–100 source-code quality score plus safety scorecards. The score is essentially how clean the code is against eslint-plugin-obsidianmd + the developer policies + the submission requirements. This skill reproduces that audit locally.

Background reference (keep it in sync): docs/development/obsidian-review-and-scoring.md.

When to use

  • Before cutting a release or tagging a version.
  • Before (re-)submitting to the community directory.
  • When the user asks to improve the Obsidian score / pass the automated review.

How to run the audit

Work through the phases in order. Report findings grouped by category, most-severe first, each anchored to file:line with a concrete fix. Do not auto-apply large refactors without confirming scope with the user first.

Phase 1 — Run the official linter (the ground truth)

The project currently lints with oxlint and a legacy .eslintrc.js; neither encodes the Obsidian rules. Add and run the official rule set:

npm i -D eslint eslint-plugin-obsidianmd @typescript-eslint/parser
# with an eslint.config.mjs using obsidianmd.configs.recommended (see the doc)
npx eslint "src/**/*.{ts,tsx}"

If the flat config is not yet present, create eslint.config.mjs as shown in docs/development/obsidian-review-and-scoring.md §5. Treat every eslint-plugin-obsidianmd error as a score deduction.

Phase 2 — Fast static audit (grep the known anti-patterns)

Run these and triage each hit:

CheckCommand (ripgrep)Rule / guideline
HTML injection`rg -n "innerHTMLouterHTML
Inline styles`rg -n ".style.setAttribute(['"]style" src`
Detach leaves on unloadrg -n "detachLeavesOfType" srcdetach-leaves → remove from onunload.
Hardcoded config dirrg -n "\.obsidian/" srchardcoded-config-path → use vault.configDir.
Node/Electron on mobile`rg -n "require(from ['"](fs
Global app`rg -n "window.app\bapp." src`
var / Promise chains`rg -n "\bvar\s.then(" src`
Regex lookbehindrg -n "\(\?<" srcregex-lookbehind → unsupported on some iOS.
Direct activeLeafrg -n "workspace\.activeLeaf" srcUse getActiveViewOfType().
Adapter over Vaultrg -n "\.adapter\." srcPrefer the Vault API.

Phase 3 — Manifest & release hygiene

  • manifest.json: valid id, name, semver version, minAppVersion, description (≤250 chars, action verb, ends with ., not starting "This is a plugin"), author.
  • fundingUrl present only because donations are accepted (ZettelFlow: yes).
  • versions.json exists and maps each version → minAppVersion. ⚠️ Currently missing — see docs/development/obsidian-review-and-scoring.md §6.
  • version-bump.mjs exists (referenced by the version npm script). ⚠️ Currently missing.
  • Release workflow attaches main.js, manifest.json, styles.css under a git tag equal to manifest.version (no v prefix). Cross-check .github/workflows/releases.yml.
  • LICENSE present with a valid copyright notice (validate-license).

Phase 4 — Commands, settings & UI text

  • Command ids/names don't repeat the plugin id/name or the word "command".
  • No default hotkeys shipped.
  • Settings headings use setHeading() (not manual HTML), no "settings" in the heading text.
  • All user-facing strings are Sentence case, not Title Case. (ZettelFlow has an i18n layer at src/architecture/lang/ — audit en/es locale strings too.)

Phase 5 — ZettelFlow-specific risk review

  • Canvas monkey-patching (src/architecture/plugin/canvas/extensions/CanvasPatcher.ts) patches internal Canvas APIs via monkey-around. This is a manual-review flag: keep the patches defensive (they already register uninstallers via plugin.register), guard every patched method behind existence checks, and document the risk. Verify against the current minAppVersion.
  • .js extension registration (CodeView): already wrapped in try/catch — keep it.
  • Logger gating (src/architecture/monitoring/Logger.ts): error is silenced when the logger toggle is off. Consider always allowing error.
  • onunload only clears the action store; confirm no leaked resources (most are covered by Obsidian's register* auto-teardown).

Phase 6 — The transformation gate (constitution §XI)

Beyond the linter, judge the change against the design gate:

  • Transformation. Ask "what knowledge transformation does this enable?" Flag surface that doesn't transform/connect/evaluate/discover/advance knowledge as secondary.
  • No net complexity. The change removes/merges a command, view, setting or path, or hardens a boundary — it doesn't only add. Rising net surface is a finding.
  • Boundaries. The Knowledge layer (architecture/knowledge, future knowledge/) imports no obsidian and makes no network/AI call; derived metrics are queries over the model, not new dashboard features. Existing .zftemplate systems and saved settings still work; no command/view removed without an alias.

Output format

Produce a prioritized report: (1) blocking submission issues (missing versions.json, manifest errors), (2) eslint-plugin-obsidianmd errors, (3) security (HTML injection), (4) styling/inline-style migrations, (5) polish (sentence case, commands). For each: the rule, the file:line, and the exact fix. Offer to apply the low-risk mechanical fixes (innerHTML = "" → .empty(), adding the eslint config) in a follow-up.

Signals

GitHub stars
168
Forks
12
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
obsidian-plugin-quality
Source
github.com/rafaelgb/obsidian-zettelflow