plugins/obsidian-development/skills/obsidian-scaffold/SKILL.md
Scaffolds project structure, manifest, tsconfig, esbuild config, and a minimal plugin class that passes Obsidian's automated plugin review. TRIGGER WHEN: the user asks to start, create, bootstrap, or initialize a new Obsidian community plugin DO NOT TRIGGER WHEN: the task is outside the specific scope of this component.
npx skillsauth add acaprino/alfio-claude-plugins obsidian-scaffoldInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Scaffold a new Obsidian community plugin project that is review-compliant from day one.
/obsidian-scaffold -- then answer the prompts for plugin ID, name, author, and description.
my-plugin/
src/
main.ts # Plugin class with onload/onunload
styles.css # Empty, scoped styles
manifest.json # Valid manifest (review-compliant)
package.json # Dependencies: obsidian, typescript, esbuild, @types/node
tsconfig.json # strict: true, target ES2018, moduleResolution node
esbuild.config.mjs # CJS bundle, externalizes obsidian + electron
eslint.config.mjs # eslint-plugin-obsidianmd + eslint-comments flat config
LICENSE # MIT with current year
README.md # Minimal description
.gitignore # node_modules, main.js, data.json
Ask the user for:
. ? ! ), under 250 chars)Validate inputs against Obsidian automated review rules:
/^[a-z0-9-]+$/, not containing "obsidian", not ending with "plugin".?!)Create all files using the templates below.
Run npm install to install dependencies.
Verify npx tsc --noEmit passes with zero errors.
{
"id": "{{ID}}",
"name": "{{NAME}}",
"version": "1.0.0",
"minAppVersion": "1.0.0",
"description": "{{DESCRIPTION}}",
"author": "{{AUTHOR}}",
"authorUrl": "{{AUTHOR_URL}}",
"isDesktopOnly": {{IS_DESKTOP_ONLY}}
}
{
"name": "{{ID}}",
"version": "1.0.0",
"description": "{{DESCRIPTION}}",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"lint": "eslint src/ package.json"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "^4.0.0",
"@eslint/js": "^9.0.0",
"@types/node": "^22.0.0",
"esbuild": "^0.24.0",
"eslint": "^9.0.0",
"eslint-plugin-obsidianmd": "latest",
"obsidian": "latest",
"typescript": "^5.5.0",
"typescript-eslint": "^8.0.0"
}
}
{
"compilerOptions": {
"baseUrl": ".",
"inlineSourceMap": true,
"inlineSources": true,
"module": "ESNext",
"target": "ES2018",
"allowJs": true,
"noImplicitAny": true,
"moduleResolution": "node",
"importHelpers": true,
"isolatedModules": true,
"strictNullChecks": true,
"strict": true,
"lib": ["DOM", "ES2018", "ES2021.String"]
},
"include": ["src/**/*.ts"]
}
import esbuild from "esbuild";
import process from "process";
import { builtinModules as builtins } from "node:module";
const prod = process.argv[2] === "production";
esbuild.build({
entryPoints: ["src/main.ts"],
bundle: true,
external: [
"obsidian",
"electron",
"@codemirror/autocomplete",
"@codemirror/collab",
"@codemirror/commands",
"@codemirror/language",
"@codemirror/lint",
"@codemirror/search",
"@codemirror/state",
"@codemirror/view",
"@lezer/common",
"@lezer/highlight",
"@lezer/lr",
...builtins,
],
format: "cjs",
target: "es2018",
logLevel: "info",
sourcemap: prod ? false : "inline",
treeShaking: true,
outfile: "main.js",
minify: prod,
}).catch(() => process.exit(1));
import { Plugin } from 'obsidian';
export default class {{CLASS_NAME}} extends Plugin {
onload(): void {
// Plugin initialization here
}
onunload(): void {
// Cleanup here (Obsidian handles leaf detachment automatically)
}
}
node_modules/
main.js
data.json
The eslint-comments block mirrors checks that Obsidian's review platform adds on top of the obsidianmd recommended config.
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import obsidianmd from 'eslint-plugin-obsidianmd';
import comments from '@eslint-community/eslint-plugin-eslint-comments/configs';
export default [
js.configs.recommended,
...tseslint.configs.recommended,
...obsidianmd.configs.recommended,
comments.recommended,
{
rules: {
'@eslint-community/eslint-comments/require-description': 'error',
'@eslint-community/eslint-comments/no-restricted-disable': [
'error',
'obsidianmd/no-static-styles-assignment',
'obsidianmd/ui/sentence-case',
],
},
},
{
languageOptions: {
parserOptions: {
project: './tsconfig.json',
},
},
},
];
After creation, remind the user:
npm run dev for watch mode during developmentnpm run build for production buildnpm run lint to check against the automated review rules locallymain.js, manifest.json, and styles.css as individual assetsv prefix)obsidianmd/obsidian-releases was retired in May 2026tools
Master memory forensics techniques including memory acquisition, process analysis, and artifact extraction using Volatility and related tools. Use when analyzing memory dumps, investigating incidents, or performing malware analysis from RAM captures.
development
Master binary analysis patterns including disassembly, decompilation, control flow analysis, and code pattern recognition. Use when analyzing executables, understanding compiled code, or performing static analysis on binaries.
development
Idiomatic Kotlin implementation patterns: coroutines and structured concurrency, Flow / StateFlow / SharedFlow, Kotlin Multiplatform (KMP) shared-code architecture, Jetpack Compose UI, Ktor server with JWT auth and Exposed, and type-safe DSL design (lambdas with receivers, delegated properties, inline reified, value classes). TRIGGER WHEN: building, writing, or reviewing Kotlin code using coroutines / Flow / suspend functions, expect/actual, Compose composables / ViewModels, Ktor routing, sealed-class state modeling, scope functions, or DSL builders. DO NOT TRIGGER WHEN: libGDX game work (use libgdx-development), Android Java without Kotlin, or pure JVM tuning unrelated to Kotlin language features.
tools
Strategic website planning skill that conducts structured client discovery, produces professional deliverables (website brief, sitemap, design direction, content strategy), and orchestrates frontend-design, frontend-layout, seo-specialist, and content-marketer agents automatically. TRIGGER WHEN: planning a new website or redesign before any code is written. DO NOT TRIGGER WHEN: the task is outside the specific scope of this component.