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.
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.
approx rulesNon‑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.
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.
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.
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.
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.
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.
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 🚀
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.
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.
Table · Terminal · HTML · Markdown · JSON · YAML · TOML — all with a 0-100 score and grade.
Override rule severity per-project. Skip whole accuracy levels (e.g. approximate) to dial down noise.
Drop a tree-sitter query into .oplint.yaml and you have a new rule. match or not-match.
Mobile rules auto-skip when isDesktopOnly: true. No false positives for desktop-only plugins.
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.
Check out the roadmap for upcoming features — rule generators for ESLint, Biome, Oxlint, and more.
View roadmap$ 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.
$ cargo install oplint
$ oplint --help
Requires Rust 1.74+. Binary lands in ~/.cargo/bin.
$ 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.
All platforms (Linux, macOS, Windows) on the latest release page.
# pretty table in your terminal
$ oplint lint . -f table
# render an HTML report
$ oplint lint . -f html > oplint-report.html
# render any reports you need
$ cargo run lint -f html,md,tom,yaml,json,table -o ./reporting
# show help
$ oplint --help
# Initialize the configuration file
$ oplint init # default yaml
$ oplint init -f json # json format
$ oplint init -f toml # toml format
# list rules as is
$ oplint rules
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/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/
Markdown report rendered in the run summary, with severity counts and category bars.
Sticky comment with the score delta vs main, top offenders, and a link to the full HTML artifact.
Auto-published shields.io endpoint with score, grade and color. oplintB+ · 78
The full interactive report (the same one you saw in the hero) attached to every run.
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.
.oplint.yamlexactWorking on an Obsidian plugin and finding oplint useful?
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.
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.
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.
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.
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.
Both.
tree-sitter parses TypeScript natively, including JSX/TSX. JSON rules run against manifest.json.
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.