Set up Obsidian plugin development environment with Node.js and TypeScript.
Use when starting a new plugin project, configuring the dev environment,
or initializing Obsidian plugin development.
Trigger with phrases like "obsidian setup", "obsidian plugin dev",
"create obsidian plugin", "obsidian development environment".
Set up a complete Obsidian plugin development environment: clone the official sample plugin, install TypeScript + esbuild, configure a dev vault with symlink, verify the build pipeline, and establish the manifest.json / versions.json contract.
set -euo pipefail
# Clone the maintained template — includes esbuild, tsconfig, and a working main.ts
git clone https://github.com/obsidianmd/obsidian-sample-plugin.git my-obsidian-plugin
cd my-obsidian-plugin
# Start fresh git history
rm -rf .git
git init
git add -A
git commit -m "initial scaffold from obsidian-sample-plugin"
The sample plugin includes these key files:
esbuild.config.mjs — bundler with watch mode and external handling
tsconfig.json — TypeScript config targeting ES2018 with strict null checks
manifest.json — plugin metadata Obsidian reads at load time
src/main.ts — Plugin subclass with commands, settings, modal
Step 2: Install Dependencies
set -euo pipefail
npm install
# What gets installed:
# - obsidian (type definitions only — the runtime is provided by the Obsidian app)
# - typescript
# - esbuild (fast bundler, <50ms builds)
# - @types/node
# - tslib (TypeScript helper library)
Step 3: Configure manifest.json
Every Obsidian plugin requires a manifest.json at the project root:
{
"id": "my-obsidian-plugin",
"name": "My Obsidian Plugin",
"version": "1.0.0",
"minAppVersion": "1.5.0",
"description": "What your plugin does in one sentence.",
"author": "Your Name",
"authorUrl": "https://github.com/yourname",
"isDesktopOnly": false
}
id must be lowercase kebab-case, match the folder name under .obsidian/plugins/
minAppVersion should be 1.5.0 or higher (supports modern APIs like processFrontMatter)
isDesktopOnly: false unless you use Electron-only APIs (child_process, fs, shell)
Step 4: Create versions.json
Maps each plugin version to the minimum Obsidian version it requires:
{
"1.0.0": "1.5.0"
}
Obsidian uses this to warn users on older versions that they cannot install your plugin. Update it every time you bump version in manifest.json.
Step 5: Create a Development Vault
set -euo pipefail
DEV_VAULT="$HOME/ObsidianDev"
mkdir -p "$DEV_VAULT/.obsidian/plugins"
mkdir -p "$DEV_VAULT/Test Notes"
# Create a sample note for testing
cat > "$DEV_VAULT/Test Notes/Sample.md" << 'EOF'
---
tags: [test, sample]
status: draft
---
# Sample Note
Test note for plugin development. Has [[wikilinks]], #tags, and frontmatter.
## Section A
Some content with **bold** and `inline code`.
## Section B
- [ ] Task one
- [x] Task two
- [ ] Task three
EOF
echo "Dev vault created at $DEV_VAULT"
Open this vault in Obsidian: File > Open vault > select ~/ObsidianDev.
Step 6: Symlink Plugin into Dev Vault
set -euo pipefail
DEV_VAULT="$HOME/ObsidianDev"
PLUGIN_DIR="$(pwd)"
PLUGIN_ID=$(node -e "console.log(require('./manifest.json').id)")
# Symlink project root into vault plugins folder
ln -sfn "$PLUGIN_DIR" "$DEV_VAULT/.obsidian/plugins/$PLUGIN_ID"
# Verify
ls -la "$DEV_VAULT/.obsidian/plugins/$PLUGIN_ID/manifest.json"
echo "Symlinked $PLUGIN_ID into dev vault"
set -euo pipefail
# Production build
npm run build
ls -la main.js manifest.json
echo "Build output: $(wc -c < main.js) bytes"
# Start dev mode with file watching
npm run dev
# esbuild watches src/ and rebuilds main.js on every save (~30ms)
In Obsidian:
Settings > Community plugins > Enable community plugins
Find your plugin in the list, toggle it on
Open Developer Console (Ctrl+Shift+I) — look for your plugin's load message