🚀 Live Demo

Ship Obsidian plugins that actually pass review. delight users. earn five stars. run everywhere. feel polished. are linter standalone.

oplint is a standalone static-analysis CLI for the Obsidian plugin guidelines. 50+ tree-sitter rules across security, manifest, mobile, API and UI — with HTML, JSON, Markdown reports and a one-line GitHub Action. Linter-aware — works standalone whatever linter you use in your JS/TS toolchain.

🛡️ 0
Rules
🧩 0
Categories
📦 0
Output
formats
0
Guidelines covered≈ 100% with approx rules
~/my-plugin · zsh
report.html
Plugin Compliance Report
my-plugin v1.0.2 · 42 files · 4 318 LOC
78
B+ · Good
▲ +6 vs last run
3Errors
11Warnings
6Info
68Passing
Security
API Usage
Mobile
UX & Styling
Manifest
View on GitHub
Why oplint

The Obsidian guidelines are strong 💪.
Your workflow should be secure 🔒!

01 IMPACT
Most critical

Bad plugins breakuser experience

Non‑compliant plugins cause slowdowns, weird UI behavior, or silent mobile crashes. Following the guidelines is the best way to avoid these real issues before users ever notice them.

02 EFFICIENCY

Plugin reviews areslow

Verifying code on a loop flags the same dozen issues over and over — innerHTML, missing onunload, hardcoded styles, sample-plugin leftovers. Catch them locally before you open the PR.

03 PANIC

Mobile breakssilently

Lookbehind regex, navigator.userAgent, raw window.setTimeout — none of it errors at compile time. oplint flags every mobile-incompatible API unless your manifest sets isDesktopOnly.

04 SCHEMA

Manifests arefiddly

Twelve required-field, ID-format and description rules. Validated against the same schema Obsidian's reviewers use, with copyright-notice and sample-ID checks built in.

05 STANDARD

Style guidelines aresubtle

Sentence case, no top-level settings headings, setHeading() over h1, no inline style= attributes. The kind of thing a reviewer notices and a linter should catch.

06 TOKENS
Stay Clever

AI loops are costly

Every loop verifying you stick to guidelines means another AI prompt to fix the same issues. oplint automates this — keeping your plugin performant and your users' Obsidian stable, so your agent spends tokens on interesting work, not the same 12 checklist items.

Features

Built for plugin authors 👩🏽‍💻,
not for linter authors 🥋.

Standalone

Linter-aware & standalone

ESLint needs plugins; Biome/Oxlint don't cover Obsidian guidelines. oplint runs standalone — no other linter required, works outside your existing JS/TS toolchain.

Rule generator for top linters on the roadmap 🚀

tree-sitter AST, not regex

Real syntax trees mean fewer false positives on strings, comments and template literals. Each rule is tagged exact or approximate so you know what you're trusting.

Fast by default

Written in Rust. Lints a typical plugin between 500ms and 5s ⚡️ on cold cache.

Now with built‑in concurrency — processes files in parallel so multi‑file projects stay just as snappy.

7 output formats

Table · Terminal · HTML · Markdown · JSON · YAML · TOML — all with a 0-100 score and grade.

Configurable severity

Override rule severity per-project. Skip whole accuracy levels (e.g. approximate) to dial down noise.

Custom rules

Drop a tree-sitter query into .oplint.yaml and you have a new rule. match or not-match.

Mobile-aware

Mobile rules auto-skip when isDesktopOnly: true. No false positives for desktop-only plugins.

GitHub Action, ready to drop in

Lint on push, post a Markdown summary on the PR, attach the HTML report as an artifact, and stamp a compliance badge on your README. One YAML, zero plumbing.

Want to see what's next?

Check out the roadmap for upcoming features — rule generators for ESLint, Biome, Oxlint, and more.

View roadmap
Install

Four ways in 🎟️.

Recommended

One-liner

$ curl -fsSL https://raw.githubusercontent.com/kodaskills/oplint/main/install.sh | sh

macOS & Linux. Detects your OS and arch, installs to /usr/local/bin. No Rust required.

From crates.io

Via cargo

$ cargo install oplint
$ oplint --help

Requires Rust 1.74+. Binary lands in ~/.cargo/bin.

From source

Build it yourself

$ git clone https://github.com/kodaskills/oplint
$ cd oplint
$ cargo build --release
$ ./target/release/oplint --help

Useful if you want to contribute custom rules upstream.

Pre-built binary

Download from GitHub

All platforms (Linux, macOS, Windows) on the latest release page.

How it works

Easy as a breeze ✨.

  1. A

    Lint and report in your terminal

    # pretty table in your terminal
    $ oplint lint . -f table
  2. B

    Clear readable report

    # render an HTML report
    $ oplint lint . -f html > oplint-report.html
  3. C

    Won't choose?

    # render any reports you need
    $ cargo run lint -f html,md,tom,yaml,json,table -o ./reporting
  4. D

    Need help?

    # show help
    $ oplint --help
  5. E

    Need to configure?

    # Initialize the configuration file
    $ oplint init # default yaml
    $ oplint init -f json # json format
    $ oplint init -f toml # toml format
  6. F

    Or Just want list rules?

    # list rules as is
    $ oplint rules
Rule catalog

50+ rules, 11 categories, all transparent ⭐.

Every rule has an ID, severity and accuracy tag. Approximate rules say so — you can disable them globally in one line of config.

You have encountered a rule that doesn't fit your use case? You want to add a new guideline rule for the good of the community?

GitHub Action

Drop it in. Get a badge 🛡️.

# .github/workflows/lint.yml
name: Plugin compliance
on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run OPLint
        id: oplint
        uses: kodaskills/oplint-action@v1
        with:
          path: .
          summary: true
          comment: true
          badge_enabled: true
          badge_endpoint: true
          badge_endpoint_output: .oplint-badge.json
          badge_style: for-the-badge
          reporting_enabled: true
          reporting_formats: md,html
          reporting_output_dir: reports/

GitHub Summary

Markdown report rendered in the run summary, with severity counts and category bars.

PR comment

Sticky comment with the score delta vs main, top offenders, and a link to the full HTML artifact.

Compliance badge

Auto-published shields.io endpoint with score, grade and color. oplintB+ · 78

HTML artifact

The full interactive report (the same one you saw in the hero) attached to every run.

Roadmap

Where we're aiming 📅.

oplint is a starter project from the Kodaskills team. It already covers ~99% (💯 if we include approximate rules) of the published Obsidian plugin guidelines. If the Obsidian team and community find it useful, here's what's next.

Shipped
  • 50+ rules across 11 categories
  • including 15+ custom semantic rules (in Rust)
  • tree-sitter syntax queries
  • HTML / JSON / Markdown / YAML / TOML reports
  • Custom rules via .oplint.yaml
  • GitHub Action — lint, summary, PR comment, badge
  • Compliance score, grade and per-file performance
If there's interest
  • Full AST semantic analysis — bring approximate rules to exact
  • Auto-fix for the safe subset (innerHTML → setText, var → const, sentence-case, …)
  • VS Code / Obsidian editor extension with inline diagnostics
  • Community-contributed rule packs
  • Watch mode for local dev
  • Rule generator & exports for top linters (ESLint, Biome, Oxlint, …) — replicate oplint ruleset everywhere

Working on an Obsidian plugin and finding oplint useful?

FAQ

Quick answers 🙋‍♀️.

Is oplint affiliated with Obsidian?

No.

oplint is a community project from the Kodaskills team that encodes the publicly documented Obsidian plugin guidelines.

It is not endorsed by or affiliated with the Obsidian team.

Will it replace the official plugin review?

No — and it's not trying to.

oplint catches the mechanical issues so reviewers can focus on the substantive ones (UX, scope, naming, originality).

plugins that pass oplint cleanly still need a human review.

Why not use the official Obsidian ESLint plugin?

oplint is standalone. It runs independently — no ESLint plugin to install, no toolchain lock-in. Whatever linter you use (or none), oplint just works.

Other linters don't cover Obsidian guidelines. Biome and Oxlint are faster than ESLint, but they lack Obsidian-specific rules entirely. ESLint plugins only work inside ESLint.

oplint is linter-aware. The roadmap includes rule generators to export oplint's ruleset to ESLint, Biome, Oxlint, and other top linters — so you can enforce the same Obsidian rules everywhere you lint.

It complements, doesn't replace. Keep your code-quality linting in ESLint if you use it, and let oplint handle Obsidian plugin compliance.

What's the difference between exact and approximate rules?

Exact rules are semantically precise — no false positives or negatives.

Approximate rules are best-effort and may misfire on edge cases.

You can skip a whole accuracy level in config.

Can I disable a rule for one file?

Yes — per-rule except_in globs in .oplint.yaml, or override severity for a specific rule ID.

There's no inline-comment ignore yet; it's on the roadmap.

Does it work on TypeScript or just JavaScript?

Both.

tree-sitter parses TypeScript natively, including JSX/TSX. JSON rules run against manifest.json.

How do I write a custom rule?

Add a custom_rules: entry with a tree-sitter query, severity, accuracy and message.

The README has a full example with expect: match / not-match semantics.

Any other questions?

Please feel free to discuss!

Open a discussion