CLI tool
obsidianmd/obsidian-sample-plugin avatar
obsidianmd/obsidian-sample-plugin

obsidian-sample-plugin: the TypeScript starting point for an Obsidian plugin

Template for Obsidian community plugins with build configuration and development best practices.

4,542 stars1,784 forksTypeScript0BSD

At a glance

What is it?
The official Obsidian plugin template ships a working ribbon icon, command, modal, settings tab and event registration, plus esbuild watch mode and a preconfigured ESLint setup. It is a scaffold for developers, not a plugin you install to use.
Who is it for?
Adopt this template if you are writing your first Obsidian plugin in TypeScript and want the API surface demonstrated in one file rather than assembled from scratch. Do not adopt it if you need a plugin that does something useful on day one, or if your build pipeline is not Node-based: the repository is a scaffold, and the README's manual install step still assumes you copy main.js, styles.css and manifest.json into VaultFolder/.obsidian/plugins/your-plugin-id/.
Can I use it commercially?
Yes. 0BSD is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 59 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the Obsidian sample plugin actually is, and who it is for

This repository is a template, not a distributed plugin. Its README opens by calling it "a sample plugin for Obsidian," and the repository description calls it a template for community plugins with build configuration and development best practices. The audience is narrow and specific: developers who want to write an Obsidian plugin in TypeScript and would rather start from a working skeleton than from an empty directory.

The README lists exactly what the skeleton demonstrates. A ribbon icon that shows a Notice when clicked. A command named "Open modal (simple)" that opens a Modal. A plugin setting tab on the settings page. A global click event that outputs a Notice. A global interval that logs 'setInterval' to the console. Those five items are the entire functional surface. Nothing here reads a note, queries the vault, or touches the file system, so anyone looking for a plugin to install has the wrong repository.

The README also gives a piece of advice that is easy to skip and worth following: check whether someone already developed a plugin for what you want, because an existing plugin might be close enough to partner on rather than duplicate. That is a real constraint on the decision to start from this template at all.

How the build pipeline works: esbuild watch mode and the TypeScript API types

The mechanism is a single entry point compiled to a single bundle. Source lives in src/, and the README states that running the dev script compiles your plugin from src/main.ts to main.js. The watch mode keeps that going: the README says changes to src/main.ts, or new .ts files you create, should be automatically compiled into main.js.

The type checking is separate from the bundling. The build script runs tsc with -noEmit and -skipLibCheck before invoking esbuild in production mode, so type errors surface as a gate while esbuild does the transform. The repo depends on the latest plugin API in obsidian.d.ts, a TypeScript Definition file with TSDoc comments describing what the API does. That file is the documentation surface for the API, which is why the README points to docs.obsidian.md rather than reproducing signatures.

The dependency list is deliberately small and build-only: esbuild, typescript, eslint, typescript-eslint, the obsidian types package, and eslint-plugin-obsidianmd for Obsidian-specific code guidelines. There are no runtime dependencies declared, which matches the shape of an Obsidian plugin: the host application provides the API, and your bundle supplies the rest.

One consequence is worth stating plainly. Because the type package is pinned as "obsidian": "latest" and the README tells you to run npm update for API updates, the types can move under you between installs. A plugin that compiles today can produce new type errors after an update, and there is no compatibility matrix in the repository beyond versions.json, which maps plugin versions to minimum Obsidian versions rather than to API versions.

Installing the template and getting a first build running

The README's How to use section is the install path. Start by making a copy of the repository as a template with the "Use this template" button, then clone your copy locally. The README notes that for convenience you can place the folder inside your vault at .obsidian/plugins/your-plugin-name. Before running anything, confirm your Node version, because the README requires at least v18.

bash
node --version
npm i
npm run dev

The first command prints your Node version and should show v18 or higher. npm i installs the dev dependencies listed in package.json. npm run dev starts compilation in watch mode, which the README describes as compiling src/main.ts to main.js.

Once that is running, reload Obsidian to load the new version of your plugin, then enable the plugin in the settings window. You should see the ribbon icon described in the README, and clicking it should produce a Notice. The command palette should list "Open modal (simple)".

If you would rather not keep the repo inside the vault, the README documents a manual install: copy main.js, styles.css and manifest.json into VaultFolder/.obsidian/plugins/your-plugin-id/. Those three files are exactly what a release attaches, which is why the build output is a single main.js rather than a directory of modules.

The lint check is preconfigured and runs against the whole repository.

bash
eslint .

The README notes that a GitHub action is preconfigured to lint every commit on all branches, so the same command runs in CI whether or not you run it locally.

Releasing, version bumping and the manifest.json duplication rule

The release procedure has a sharp edge that the README states explicitly: the manifest.json file must be in two places, first the root path of your repository and also in the release. A release that attaches manifest.json, main.js and styles.css but forgets the root copy is incomplete by the README's own checklist.

The version bump has three moving parts. You update manifest.json with the new version number and the minimum Obsidian version required. You update versions.json with a "new-plugin-version": "minimum-obsidian-version" pair so older versions of Obsidian can download an older compatible plugin. Then you create a GitHub release using the new version number as the tag, with no v prefix, and upload the three files as binary attachments.

The README offers a shortcut for the mechanical part: after updating minAppVersion manually in manifest.json, run npm version patch, npm version minor or npm version major. The version script in package.json runs version-bump.mjs and then git add manifest.json versions.json, which the README says bumps the version in manifest.json and package.json and adds the entry for the new version to versions.json. That is a meaningful difference from a hand-edited release: the script keeps three files consistent, but it does not touch minAppVersion, so the manual edit stays manual.

There is no documented rollback procedure. The README does not describe how to retract a published version, and versions.json only helps users stay on an older compatible release; it does not remove a bad one.

Where the template stops helping

The sample covers the plugin lifecycle and stops there. Anything involving persistence, vault queries, file watching or workspace manipulation is absent from the demonstrated functionality, and the README does not walk through those APIs. You will be reading obsidian.d.ts and docs.obsidian.md rather than the repository.

The global interval registered by the sample is a case worth thinking about before you copy it. The README says it logs 'setInterval' to the console. In a plugin that runs for hours inside a desktop application, an interval that is registered and never cleared is a leak, and the sample does not demonstrate the unload path that would clear it. Treat that block as an API demonstration, not as a pattern to keep.

Publishing is also gated outside the repository. The README requires an initial published version, a README.md in the root of your repo, and a pull request against the obsidian-releases repository, after checking the plugin guidelines. Nothing in this template performs or validates that submission, so the last mile is manual and reviewed by someone else.

Finally, the release history is thin: the only listed release is 1.0.0 from 2020-10-28. That is the template's own versioning, and it does not tell you anything about how current the API types are, because those come from the obsidian package rather than from a tagged template release.

Alternatives: starting from scratch or forking an existing plugin

The two realistic alternatives differ in where the boilerplate comes from.

The first is an empty repository with the obsidian types package installed and an esbuild config written by hand. That gives you full control over the bundle, the TypeScript configuration and the lint rules, and it avoids inheriting a sample whose interval and click handlers you will delete anyway. The cost is that you reimplement the manifest, the versions.json bookkeeping and the version-bump script, all of which this template already wires together and the README already documents.

The second is forking an existing community plugin that does something close to what you want. The README itself suggests this direction when it tells you to check whether someone already developed a plugin for what you want, and to consider partnering rather than starting over. The difference in approach is substantial: a fork gives you working domain logic but also someone else's architecture, settings schema and release cadence to maintain, while the sample template gives you almost no domain logic and no inherited design decisions. Pick based on whether the hard part of your plugin is the Obsidian integration or the thing the plugin actually does.

If the hard part is the integration, the sample is the shorter path. If the hard part is the domain logic, a fork is.

Licence and maintenance cost

The repository is licensed 0BSD, and package.json records the same terms as "0-BSD". That is a permissive licence with no attribution requirement, which matters for a template specifically: you can take the scaffold, rename it, and ship it under your own terms without carrying a notice file. The repository does include a LICENSE file at the top level. This is a description of what the repository states, not legal advice; read the licence text itself before relying on it.

On maintenance, the facts are narrow. The repository is not archived, and the last push was on 2026-08-02. The dependency list is current-looking: eslint 9, typescript 5.8, esbuild 0.25.5, eslint-plugin-obsidianmd 0.4.0. But the obsidian types are pinned to "latest", so the upgrade cost is not a version bump you schedule; it is whatever the API does next, discovered when you run the build. The README's instruction to run npm update is the whole upgrade story it offers.

Your recurring cost is therefore the release ritual, not the template: update manifest.json twice over, update versions.json, tag without a v prefix, attach three files. The npm version shortcut removes part of that, and nothing removes the rest.

Editorial conclusion

Adopt this template if you are writing your first Obsidian plugin in TypeScript and want the API surface demonstrated in one file rather than assembled from scratch. Do not adopt it if you need a plugin that does something useful on day one, or if your build pipeline is not Node-based: the repository is a scaffold, and the README's manual install step still assumes you copy main.js, styles.css and manifest.json into VaultFolder/.obsidian/plugins/your-plugin-id/. Verify two things before you commit to it: that your Node version satisfies the README's stated minimum of v18, and that manifest.json carries both your plugin id and your minAppVersion, because the release checklist requires that file to exist in the repository root and in the GitHub release attachment at the same time.

Frequently asked questions

Is obsidian-sample-plugin a plugin I can install in my vault?

No. It is a sample plugin and a template for developers, and its README describes it as a sample plugin for Obsidian. The functionality it demonstrates is a ribbon icon, a command that opens a modal, a settings tab, a global click handler and an interval that logs to the console.

What Node version does obsidian-sample-plugin require?

The README states that your NodeJS must be at least v18, and it suggests checking with node --version before running npm i. The dev script then runs node esbuild.config.mjs to compile src/main.ts to main.js in watch mode.

How do I release a plugin built from obsidian-sample-plugin?

Update manifest.json with the new version and minimum Obsidian version, add the version pair to versions.json, create a GitHub release tagged with the exact version number with no v prefix, and attach manifest.json, main.js and styles.css. The README notes that manifest.json must exist both at the repository root and in the release.

Does obsidian-sample-plugin include linting?

Yes. The README says ESLint is preconfigured and can be invoked with npm run lint, together with a custom eslint plugin for Obsidian-specific code guidelines. A GitHub action is preconfigured to lint every commit on all branches.

What licence does obsidian-sample-plugin use?

The repository is licensed 0BSD, and package.json records the licence field as "0-BSD". That is a permissive licence with no attribution requirement, which matters when the code is used as a starting template.

Official sources

  1. License: 0BSD
  2. obsidianmd/obsidian-sample-plugin on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/obsidianmd-obsidian-sample-plugin.svg)](https://hysenlabs.com/projects/obsidianmd-obsidian-sample-plugin)