### Skill Installation Script Usage Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Demonstrates how to execute the installation script for skills and follow the interactive prompts for provider and target directory selection. ```bash ./install-skill.sh # Follow interactive prompts ``` -------------------------------- ### Create and Develop an Obsidian Plugin Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/README.md Guides through the process of generating a new plugin, installing dependencies, starting the development server, and performing quality checks. ```bash # 1. Run the interactive generator node /path/to/obsidian-plugin-skill/tools/create-plugin.js # 2. Follow prompts for metadata # 3. Generator creates boilerplate automatically # 4. Install dependencies cd your-plugin-directory npm install # 5. Start development npm run dev # 6. Lint before submission npm run lint # 7. Build for production npm run build # 8. Create GitHub release (tag matches version) git tag v1.0.0 git push origin v1.0.0 # 9. Submit to community.obsidian.md # Sign in → Plugins → New Plugin → Enter repository URL ``` -------------------------------- ### Example Plugin Class Implementation Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md A concrete example of a plugin class implementation, showing initialization of settings, adding a setting tab, and registering a command. ```typescript export default class TodoManagerPlugin extends Plugin { settings: PluginSettings; async onload(): Promise { await this.loadSettings(); this.addSettingTab(new SettingsTab(this.app, this)); this.addCommand({ id: 'run-example', name: 'Run example', callback: () => { console.log('Command executed'); } }); } onunload(): void { // Cleanup handled automatically by Obsidian } async loadSettings(): Promise { this.settings = Object.assign( {}, DEFAULT_SETTINGS, await this.loadData() as Partial ); } async saveSettings(): Promise { await this.saveData(this.settings); } } ``` -------------------------------- ### Clone Repository for Installer Script Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Clones the skill repository to your local machine. This is the first step when using the installer script. ```bash git clone https://github.com/gapmiss/obsidian-plugin-skill.git cd obsidian-plugin-skill ``` -------------------------------- ### Reference File Structure Example Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Shows the recommended structure for reference files, which cover specific domains with an overview, detailed explanations of rules or patterns, and correct/incorrect code examples. ```markdown # [Topic Name] ## Overview [What this covers] ## Rule/Pattern Name [Explanation] ### ✅ Correct [Good code example] ### ❌ Incorrect [Bad code example] ## Related Topics [Cross-references] ``` -------------------------------- ### Example ESLint Configuration (eslint.config.mjs) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md A quick configuration example for ESLint, including type-checked rules from `typescript-eslint` and Obsidian-specific rules from `eslint-plugin-obsidianmd`. Ensure `recommendedTypeChecked` is included. ```javascript // eslint.config.mjs import tsParser from "@typescript-eslint/parser"; import tseslint from "typescript-eslint"; import obsidianmd from "eslint-plugin-obsidianmd"; export default [ { ignores: ["node_modules/**", "main.js"] }, // Type-checked rules — this is what most people miss ...tseslint.configs.recommendedTypeChecked.map(c => ({ ...c, files: ["src/**/*.ts"] })), // Obsidian-specific rules ...obsidianmd.configs.recommended, { files: ["src/**/*.ts"], languageOptions: { parser: tsParser, parserOptions: { project: "./tsconfig.json" }, }, }, ]; ``` -------------------------------- ### Install Skill Script Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/README.md Run the shell script to install the Obsidian skill. ```bash ./install-skill.sh ``` -------------------------------- ### Manual Skill Installation (Development) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Provides instructions for manually cloning the skill repository, which is the recommended method for development purposes. ```bash git clone https://github.com/gapmiss/obsidian-plugin-skill.git ``` -------------------------------- ### Versions JSON Example Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Example of a versions.json file mapping plugin versions to minimum required Obsidian application versions. ```json { "0.1.0": "0.15.0", "1.0.0": "1.0.0" } ``` -------------------------------- ### manifest.json Example Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md An example of a complete `manifest.json` file, demonstrating the correct format and values for plugin metadata. Ensure all required fields are present and adhere to validation rules. ```json { "id": "todo-manager", "name": "Todo Manager", "version": "1.0.0", "minAppVersion": "0.15.0", "description": "Organize and track your tasks with ease.", "author": "Jane Smith", "authorUrl": "https://github.com/janesmith", "isDesktopOnly": false } ``` -------------------------------- ### Install ESLint and TypeScript ESLint for Plugin Linting Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Install the necessary ESLint plugins for Obsidian and TypeScript linting. This setup is crucial for passing automated community plugin checks. ```bash npm install --save-dev eslint typescript-eslint @typescript-eslint/parser eslint-plugin-obsidianmd ``` -------------------------------- ### Manual Install for Codex/Windsurf Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Manually installs the skill for Codex or Windsurf by copying skill files. Ensure you are in the cloned repository directory. ```bash git clone https://github.com/gapmiss/obsidian-plugin-skill.git cd obsidian-plugin-skill # Copy skill mkdir -p your-project/.agents/skills/obsidian cp -r .agents/skills/obsidian/* your-project/.agents/skills/obsidian/ ``` -------------------------------- ### SettingsTab Example Implementation Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Provides an example of how to implement the display() method in SettingsTab to render a text input setting. It demonstrates clearing the container, adding a new setting, and handling value changes. ```typescript display(): void { const { containerEl } = this; containerEl.empty(); new Setting(containerEl) .setName('Example setting') .setDesc('This is an example setting') .addText(text => text .setPlaceholder('Enter value') .setValue(this.plugin.settings.exampleSetting) .onChange(async (value) => { this.plugin.settings.exampleSetting = value; await this.plugin.saveSettings(); })); } ``` -------------------------------- ### Install Obsidian Plugin Skill via NPM Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Use this command to install the Obsidian Plugin Skill using the NPM package installer. ```bash npx skills add https://github.com/gapmiss/obsidian-plugin-skill --skill obsidian ``` -------------------------------- ### ESLint Configuration Example Usage Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Demonstrates how to configure ESLint using an ES module format, including importing necessary plugins and defining rules for TypeScript files. ```javascript import tseslint from "typescript-eslint"; import obsidianmd from "eslint-plugin-obsidianmd"; export default [ { ignores: ["node_modules/**", "main.js"] }, ...tseslint.configs.recommendedTypeChecked.map(config => ({ ...config, files: ["src/**/*.ts"], })), ...obsidianmd.configs.recommended, { files: ["src/**/*.ts"], languageOptions: { parser: tsParser, parserOptions: { project: "./tsconfig.json" }, }, rules: { "no-console": ["error", { allow: ["warn", "error", "debug"] }], }, }, ]; ``` -------------------------------- ### PluginSettings Usage Example Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Demonstrates how to import and use the PluginSettings interface within a plugin class for loading and saving settings. ```typescript import type { PluginSettings } from './settings'; class MyPlugin extends Plugin { settings: PluginSettings; async loadSettings(): Promise { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); } async saveSettings(): Promise { await this.saveData(this.settings); } } ``` -------------------------------- ### Manual Install for Claude Code Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Manually installs the skill for Claude Code by copying skill and command files. Ensure you are in the cloned repository directory. ```bash git clone https://github.com/gapmiss/obsidian-plugin-skill.git cd obsidian-plugin-skill # Copy skill mkdir -p your-project/.claude/skills/obsidian cp -r .agents/skills/obsidian/* your-project/.claude/skills/obsidian/ # Copy slash commands mkdir -p your-project/.claude/commands cp .claude/commands/obsidian.md your-project/.claude/commands/ cp .claude/commands/create-plugin.md your-project/.claude/commands/ ``` -------------------------------- ### Claude Code /create-plugin Command - Automated Setup Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Initiates an interactive boilerplate generator for creating a new Obsidian plugin, recommended for automated setup. ```bash node /path/to/obsidian-plugin-skill/tools/create-plugin.js ``` -------------------------------- ### Metadata Validation Example Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md This JavaScript example demonstrates how to use the validateMetadata function and process its ValidationResult, checking for errors and warnings. ```javascript const result = validateMetadata('my-plugin', 'My Plugin', 'Does something.'); if (result.errors.length > 0) { console.log('❌ Validation Errors:'); result.errors.forEach(err => console.log(` • ${err}`)); } if (result.warnings.length > 0) { console.log('⚠️ Warnings:'); result.warnings.forEach(warn => console.log(` • ${warn}`)); } ``` -------------------------------- ### Obsidian Plugin Structure Example Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md This illustrates the file structure generated by the boilerplate tool, including source files, metadata, build configurations, and licensing. ```tree your-plugin/ ├── src/ │ ├── main.ts # Plugin class with settings integration │ └── settings.ts # Settings interface, defaults, and tab ├── manifest.json # Validated plugin metadata ├── styles.css # CSS with Obsidian variables ├── tsconfig.json # TypeScript configuration ├── package.json # Dependencies ├── esbuild.config.mjs # Build configuration ├── eslint.config.mjs # ESLint configuration ├── version-bump.mjs # Version management script ├── versions.json # Version tracking ├── .gitignore # Git ignore rules └── LICENSE # MIT license ``` -------------------------------- ### Example .gitignore Patterns Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md A standard .gitignore file for Node.js and Obsidian plugin development, excluding dependencies, build outputs, OS-specific files, and IDE configurations. ```ignore # Logs *.log npm-debug.log* # Dependencies node_modules/ # Build output main.js *.js.map # OS files .DS_Store Thumbs.db # IDE .vscode/ .idea/ # TypeScript cache *.tsbuildinfo # Privacy data.json .env # Agent settings .claude/settings.local.json .agents/settings.local.json ``` -------------------------------- ### Skill Content Structure Example Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Illustrates the recommended structure for a skill's main Markdown file, including metadata, sections for guidelines, rules, patterns, and review checklists. ```markdown --- name: obsidian description: ... --- # Obsidian Plugin Development Guidelines ## Getting Started ... ## Rules Reference [Table of all rules organized by category] ## Detailed Guidelines [Links to reference/ files] ## Common Patterns [Before/after code examples] ## When Reviewing/Writing Code [Checklist for code review] ``` -------------------------------- ### Example package.json for Obsidian Plugin Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md This JSON object shows a typical structure for a plugin's package.json file, including metadata, scripts, and dependencies. ```json { "name": "todo-manager", "version": "1.0.0", "description": "Organize and track your tasks with ease.", "main": "main.js", "scripts": { "dev": "node esbuild.config.mjs", "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", "lint": "eslint src/", "version": "node version-bump.mjs && git add manifest.json versions.json" }, "keywords": ["obsidian", "obsidian-plugin"], "author": "Jane Smith", "license": "MIT", "devDependencies": { "@eslint/js": "^9.30.1", "@types/node": "^16.11.6", "@typescript-eslint/parser": "^8.35.1", "builtin-modules": "^5.0.0", "esbuild": "^0.25.5", "eslint": "^9.30.1", "eslint-plugin-no-unsanitized": "^4.1.2", "eslint-plugin-obsidianmd": "^0.3.0", "globals": "^14.0.0", "jiti": "^2.6.1", "tslib": "^2.4.0", "typescript": "^5.8.2", "typescript-eslint": "^8.35.1" }, "dependencies": { "obsidian": "latest" } } ``` -------------------------------- ### Plugin Metadata Validation Example Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Demonstrates the usage of `validateMetadata` with both valid and invalid inputs. The output shows the errors and warnings generated for each case. ```javascript const result = validateMetadata('my-plugin', 'My Plugin', 'Does something.'); console.log(result); // { errors: [], warnings: [] } const bad = validateMetadata('obsidian-plugin', 'Obsidian Plugin', 'A plugin'); console.log(bad); // { // errors: [ // 'Plugin ID cannot contain "obsidian"', // 'Plugin ID cannot end with "plugin"', // 'Plugin name cannot contain "Obsidian"', // 'Plugin name cannot end with "Plugin"', // 'Description must end with punctuation: . ? ! or )' // ], // warnings: [] // } ``` -------------------------------- ### Invoke Obsidian Skill with Windsurf Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Example of how to invoke the Obsidian skill using Windsurf provider. ```text @obsidian ``` -------------------------------- ### Invoke Obsidian Skill with Codex Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Example of how to invoke the Obsidian skill using Codex (OpenAI) provider. ```text $obsidian ``` -------------------------------- ### Interactive Plugin Creation Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md This section demonstrates the interactive CLI process for creating a new Obsidian plugin. The tool guides the user through providing necessary metadata and then generates the project files. ```APIDOC ## Interactive Plugin Creation ### Description This command-line tool scaffolds a new Obsidian plugin project with a best-practice structure. It interactively prompts the user for essential plugin details such as name, ID, version, description, author, and minimum Obsidian version. Existing files are not overwritten. ### Command ```bash $ node tools/create-plugin.js ``` ### Process 1. **Initiation**: Run the script to start the interactive session. 2. **Directory Selection**: Specify the target directory for the plugin (defaults to current directory). 3. **Metadata Input**: Provide plugin name, ID, version, description, author, GitHub username (optional), and minimum Obsidian version. 4. **Validation**: The script validates the provided metadata. 5. **File Generation**: Creates a standard set of plugin files (e.g., `src/main.ts`, `manifest.json`, `package.json`). 6. **Completion**: Reports the number of files created and suggests next steps. ### Next Steps 1. Install dependencies: `npm install` 2. Start development: `npm run dev` 3. Enable the plugin in Obsidian settings. 4. Lint before submission: `npm run lint` ``` -------------------------------- ### Invoke Obsidian Skill with Claude Code Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Example of how to invoke the Obsidian skill using Claude Code provider for creating a plugin. ```text /obsidian /create-plugin ``` -------------------------------- ### Prompting User Input in JavaScript Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Use the `prompt` function to get user input with an optional default value. This is useful for interactive CLI tools. ```javascript const name = await prompt('Plugin name', 'My Helper'); ``` -------------------------------- ### Description Length Validation Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/errors.md This example shows the condition for triggering a warning when a plugin description exceeds 250 characters. Aim for 100-200 characters for clarity. ```javascript "This plugin helps you manage your daily tasks, organize them by priority, track deadlines, and integrate with external calendars to keep everything synchronized across your devices while providing detailed analytics and productivity insights with customizable workflows for different teams." ``` -------------------------------- ### Description Validation: Redundant Phrases Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/errors.md This snippet demonstrates the pattern used to detect and reject redundant phrases in plugin descriptions. Ensure descriptions start with an action verb. ```regex /this plugin|this is a plugin|this plugin allows/i ``` -------------------------------- ### Real-time Plugin Validation Errors Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Examples of validation errors that the interactive prompt system will catch, ensuring compliance with Obsidian's submission bot rules. ```text ❌ Validation Errors: • Plugin ID cannot contain "obsidian" • Plugin name cannot end with "Plugin" • Description must end with punctuation: . ? ! or ) ``` -------------------------------- ### manifest.json Schema Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md Defines the structure for plugin metadata, including ID, name, version, author, and compatibility information. This file is required by Obsidian for plugin listing and installation. ```json { "id": "string", "name": "string", "version": "string", "minAppVersion": "string", "description": "string", "author": "string", "authorUrl": "string", "isDesktopOnly": boolean } ``` -------------------------------- ### File System: Directory Creation and Change Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/errors.md Shows the process of creating a target directory and then changing the current working directory to it. Failure here results in a process exit. ```javascript fs.mkdirSync(targetDir, { recursive: true }); process.chdir(targetDir); ``` -------------------------------- ### Running the Create Plugin CLI Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Execute the create-plugin script to generate a new Obsidian plugin project. The CLI will prompt for necessary details like plugin name, ID, and version. ```bash $ node tools/create-plugin.js 🔮 Obsidian Plugin Boilerplate Generator This tool creates a minimal, best-practice plugin structure. Existing files will NOT be overwritten. Where should the plugin be created? (leave blank for current directory) Target directory: ./my-todo-plugin 📁 Working in: /home/user/my-todo-plugin Plugin name (My Helper): Todo Manager Plugin ID (kebab-case) (todo-manager): todo-manager Initial version (0.1.0): 0.1.0 Description (Enhance your workflow.): Manage your daily tasks efficiently. Author name: Jane Smith GitHub username (optional): janesmith Minimum Obsidian version (0.15.0): 0.15.0 🔍 Validating metadata... ✅ Metadata validation passed! 📝 Generating files... ✅ Created src/ directory ✅ Created src/main.ts ✅ Created src/settings.ts ✅ Created manifest.json ✅ Created styles.css ✅ Created tsconfig.json ✅ Created package.json ✅ Created esbuild.config.mjs ✅ Created eslint.config.mjs ✅ Created version-bump.mjs ✅ Created versions.json ✅ Created LICENSE ✅ Created .gitignore ✨ Done! Created 12 file(s). 📚 Next steps: 1. Run: npm install 2. Run: npm run dev 3. Enable the plugin in Obsidian settings 4. Before submitting: npm run lint 💡 Tip: This boilerplate includes ESLint configured for community scanner compliance. Run "npm run lint" to catch issues before submission! ``` -------------------------------- ### Project Structure Overview Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/INDEX.md This snippet outlines the project structure generated by create-plugin.js, detailing the purpose and location of key files and directories. ```text ✅ tools/ └── create-plugin.js (511 lines of reference) ✅ .agents/skills/obsidian/ ├── SKILL.md (Referenced in overview) └── reference/ (Structure documented) ✅ .claude/commands/ ├── obsidian.md (Documented in skill-integration.md) └── create-plugin.md (Documented in skill-integration.md) ✅ Generated by create-plugin.js: ├── src/main.ts (Type & code documented) ├── src/settings.ts (Type & code documented) ├── manifest.json (Schema documented) ├── package.json (Schema documented) ├── tsconfig.json (Schema documented) ├── eslint.config.mjs (Schema documented) ├── esbuild.config.mjs (Schema documented) ├── styles.css (Purpose documented) ├── versions.json (Schema documented) ├── version-bump.mjs (Purpose documented) ├── LICENSE (Template documented) └── .gitignore (Patterns documented) ``` -------------------------------- ### File System: Skip Existing File Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/errors.md Illustrates the tool's handling of existing files, where it skips writing and provides a message instead of overwriting. ```javascript console.log('⏭️ Skipping {filename} (already exists)'); ``` -------------------------------- ### File System: Recursive Directory Creation Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/errors.md Demonstrates the use of the `recursive: true` flag when creating directories, which is attempted when initial creation fails due to permissions or disk issues. ```javascript fs.mkdirSync('src', { recursive: true }); ``` -------------------------------- ### Create Plugin CLI Tool Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/README.md Execute the command to create a new Obsidian plugin using the provided Node.js script. ```bash node tools/create-plugin.js ``` -------------------------------- ### Creating a Setting Control Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Use the Setting class to build individual controls within your plugin's settings UI. It's chainable and requires importing 'Setting' from 'obsidian'. ```typescript import { Setting } from 'obsidian'; new Setting(containerEl) .setName('My Setting') .setDesc('Description') .addText(text => text .setValue(currentValue) .onChange(newValue => { // Handle change })); ``` -------------------------------- ### Natural Language Plugin Command Request Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Demonstrates how to ask an agent to help implement a new command for an Obsidian plugin, leveraging the Obsidian skill. ```text Help me implement a new command for my Obsidian plugin ``` -------------------------------- ### Settings Tab Implementation Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Implement this class to create a custom settings UI for your plugin. It extends PluginSettingTab and requires importing 'PluginSettingTab' and 'App' from 'obsidian'. ```typescript import { PluginSettingTab, App } from 'obsidian'; export class SettingsTab extends PluginSettingTab { display(): void { // Render UI } } ``` -------------------------------- ### Create Obsidian Plugin Boilerplate Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/README.md Use this script to generate the initial file structure and boilerplate code for a new Obsidian plugin. It interactively prompts for project details. ```bash $ node tools/create-plugin.js Plugin name: Todo Manager Plugin ID: todo-manager Description: Organize and track your tasks with ease. Author: Jane Smith GitHub username: janesmith Min version: 1.0.0 # Generated files: # ✅ src/main.ts # ✅ src/settings.ts # ✅ manifest.json # ✅ ... (9 more files) $ cd your-directory && npm install $ npm run dev ``` -------------------------------- ### Migrate Skill Files Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md Use this command to move skill files from the old location to the new standard location. The `.claude/commands/` path is only relevant for Claude Code. ```bash # Move skill files to the new location mv .claude/skills/obsidian .agents/skills/obsidian # Keep .claude/commands/ as-is (Claude Code only) ``` -------------------------------- ### esbuild Configuration for Bundling Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md Configures esbuild to bundle the TypeScript entry point 'src/main.ts' into a CommonJS module 'main.js'. It includes options for development (inline sourcemaps, watch mode) and production (tree-shaking, no sourcemaps). ```javascript const context = await esbuild.context({ banner: { js: "/* THIS IS A GENERATED/BUNDLED FILE ... */" }, entryPoints: ["src/main.ts"], bundle: true, external: [ /* Obsidian + built-ins + CodeMirror */ ], format: "cjs", target: "es2018", logLevel: "info", sourcemap: prod ? false : "inline", treeShaking: true, outfile: "main.js", }); ``` -------------------------------- ### Corrected Plugin Code Following Best Practices Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/README.md This corrected version addresses the issues found in the previous snippet. It demonstrates proper view registration, clean command naming, safe type checking with `instanceof`, and appropriate cleanup in `onunload`. ```typescript // Following all guidelines class TodoPlugin extends Plugin { async onload() { this.registerView(VIEW_TYPE, (leaf) => { return new CustomView(leaf); // Create and return directly }); this.addCommand({ id: 'show', // Clean naming name: 'Show todo', // Sentence case // Let users set their own hotkeys checkCallback: (checking: boolean) => { const view = this.app.workspace.getActiveViewOfType(MarkdownView); if (view) { if (!checking) { // Perform action } return true; } return false; } }); if (abstractFile instanceof TFile) { // Safe type narrowing const file = abstractFile; } } onunload() { // Let Obsidian handle cleanup } } ``` -------------------------------- ### Basic Plugin Structure Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Use this as a base for your Obsidian plugin. It extends the base Plugin class and requires importing 'Plugin' from 'obsidian'. ```typescript import { Plugin } from 'obsidian'; export default class MyPlugin extends Plugin { // ... } ``` -------------------------------- ### Copy Obsidian Skill Files (Codex/Windsurf) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Use this command to copy the Obsidian skill files into your project's .agents/skills directory for Codex or Windsurf integration. ```bash mkdir -p /path/to/project/.agents/skills/obsidian cp -r .agents/skills/obsidian/* /path/to/project/.agents/skills/obsidian/ ``` -------------------------------- ### prompt(question, defaultValue) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Prompts the user for input with an optional default value. This function is used internally by the CLI to gather information from the user. ```APIDOC ## prompt(question, defaultValue) ### Description Prompts the user for input with an optional default value. This function is used internally by the CLI to gather information from the user. ### Signature ```typescript function prompt(question: string, defaultValue?: string): Promise ``` ### Parameters #### Parameters - **question** (`string`) - Required - The prompt text to display - **defaultValue** (`string`) - Optional - Default value if user presses Enter without input ### Returns - `Promise` - User input or default value (trimmed) ### Example ```javascript const name = await prompt('Plugin name', 'My Helper'); ``` ``` -------------------------------- ### Obsidian Skill Metadata Frontmatter Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md The frontmatter for the SKILL.md file defines the skill's name, description, license, and version. ```yaml --- name: obsidian description: Comprehensive guidelines for Obsidian.md plugin development including ESLint rules, TypeScript best practices, memory management, API usage, UI/UX standards, community submission process, and Scorecard optimization. license: MIT metadata: version: 1.7.0 --- ``` -------------------------------- ### Converting Plugin Name to Class Name Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Use `toClassName` to convert a plugin name into a PascalCase class name. Handles spaces, dashes, and underscores. ```javascript toClassName('my-plugin-name'); // Returns 'MyPluginName' toClassName('hello world'); // Returns 'HelloWorld' ``` -------------------------------- ### Copy Obsidian Skill Files (Claude Code) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Use this command to copy the Obsidian skill files into your project's .claude/skills directory for Claude Code integration. ```bash mkdir -p /path/to/project/.claude/skills/obsidian cp -r .agents/skills/obsidian/* /path/to/project/.claude/skills/obsidian/ cp .claude/commands/obsidian.md /path/to/project/.claude/commands/ cp .claude/commands/create-plugin.md /path/to/project/.claude/commands/ ``` -------------------------------- ### SettingsTab Class Declaration Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Defines the basic structure of the SettingsTab class, extending Obsidian's PluginSettingTab. It includes a constructor and a placeholder for the display method. ```typescript export class SettingsTab extends PluginSettingTab { plugin: MyHelperPlugin; constructor(app: App, plugin: MyHelperPlugin) { super(app, plugin); this.plugin = plugin; } display(): void { // Render settings UI here } } ``` -------------------------------- ### Converting Plugin Name to Plugin ID Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Use `toPluginId` to convert a plugin name into a kebab-case plugin ID. Handles spaces, dashes, and underscores. ```javascript toPluginId('My Plugin Name'); // Returns 'my-plugin-name' toPluginId('HelloWorld'); // Returns 'hello-world' ``` -------------------------------- ### toClassName(name) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Converts a plugin name to a PascalCase class name. This is useful for generating class names for plugin code. ```APIDOC ## toClassName(name) ### Description Converts a plugin name to PascalCase class name. This is useful for generating class names for plugin code. ### Signature ```typescript function toClassName(name: string): string ``` ### Parameters #### Parameters - **name** (`string`) - Required - Plugin name (can contain spaces, dashes, underscores) ### Returns - `string` - PascalCase class name ### Example ```javascript toClassName('my-plugin-name'); // Returns 'MyPluginName' toClassName('hello world'); // Returns 'HelloWorld' ``` ``` -------------------------------- ### PackageJSON Type Definition (Simplified) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Presents a simplified TypeScript interface for the package.json file, highlighting key properties relevant to build scripts and dependencies. ```typescript interface PackageJSON { name: string; version: string; description: string; main: string; scripts: Record; keywords: string[]; author: string; license: string; devDependencies: Record; dependencies: Record; } ``` -------------------------------- ### Accessing Obsidian App Instance Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Reference the global Obsidian application instance using 'this.app' within a Plugin class or via the constructor for SettingsTab. Key properties include 'workspace' and 'vault'. ```typescript import { App } from 'obsidian'; // Available as this.app in Plugin class // Passed to SettingsTab constructor const workspace = this.app.workspace; const vault = this.app.vault; ``` -------------------------------- ### ESLint Flat Configuration Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md ESLint configuration using the flat config format for modern ESLint versions. Includes ignores, TypeScript-specific rules, and Obsidian API best practices. ```javascript export default [ // Ignores { ignores: ["node_modules/**", "main.js", ...] }, // TypeScript ESLint recommended rules (type-checked) ...tseslint.configs.recommendedTypeChecked.map(config => ({ ...config, files: ["src/**/*.ts"], })), // Obsidian-specific rules ...obsidianmd.configs.recommended, // Project-specific rule overrides { files: ["src/**/*.ts"], languageOptions: { parser: tsParser, parserOptions: { project: "./tsconfig.json" } }, rules: { ... } } ]; ``` -------------------------------- ### ESLint Configuration for Obsidian Plugin Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md This ESLint configuration sets up type-aware TypeScript linting, integrates the obsidianmd plugin, and restricts console logging. It's designed for use in the 'src/**/*.ts' files. ```javascript import tsParser from "@typescript-eslint/parser"; import tseslint from "typescript-eslint"; import obsidianmd from "eslint-plugin-obsidianmd"; export default [ { ignores: [ "node_modules/**", "main.js", "*.mjs", "package.json", "package-lock.json", "versions.json", "tsconfig.json" ] }, ...tseslint.configs.recommendedTypeChecked.map(config => ({ ...config, files: ["src/**/*.ts"], })), ...obsidianmd.configs.recommended, { files: ["src/**/*.ts"], languageOptions: { parser: tsParser, parserOptions: { project: "./tsconfig.json", sourceType: "module", }, }, rules: { "no-console": ["error", { allow: ["warn", "error", "debug"] }], "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_", }], }, }, ]; ``` -------------------------------- ### Runtime Error Handling Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/errors.md This snippet shows the main error handler in the tool's execution flow. Unhandled errors are caught, logged, and result in a process exit with code 1. ```javascript main().catch(err => { console.error('Error:', err); process.exit(1); }); ``` -------------------------------- ### PluginSettings Interface Definition Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/types.md Defines the structure for plugin settings. Properties can be any JSON-serializable type and should have default values. ```typescript export interface PluginSettings { exampleSetting: string; } ``` -------------------------------- ### package.json Schema Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md Defines the structure for Node.js package metadata, including project name, version, scripts for development and building, dependencies, and author information. This file is used by build tools and npm. ```json { "name": "string", "version": "string", "description": "string", "main": "string", "scripts": { "dev": "string", "build": "string", "lint": "string", "version": "string" }, "keywords": ["string"], "author": "string", "license": "string", "devDependencies": { "string": "string" }, "dependencies": { "string": "string" } } ``` -------------------------------- ### writeFileIfNotExists(filePath, content) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Writes content to a file only if it doesn't already exist. This prevents accidental overwrites of existing files. ```APIDOC ## writeFileIfNotExists(filePath, content) ### Description Writes content to a file only if it doesn't already exist. This prevents accidental overwrites of existing files. ### Signature ```typescript function writeFileIfNotExists(filePath: string, content: string): boolean ``` ### Parameters #### Parameters - **filePath** (`string`) - Required - Path where file will be written - **content** (`string`) - Required - File content to write ### Returns - `boolean` - `true` if file was created, `false` if it already existed ``` -------------------------------- ### TypeScript Compiler Options and Includes Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/configuration.md Configuration for the TypeScript compiler, specifying module resolution, output targets, and included files. Embeds source maps and source code for debugging. ```json { "compilerOptions": { "baseUrl": ".", "inlineSourceMap": true, "inlineSources": true, "module": "ESNext", "target": "ES6", "allowJs": true, "noImplicitAny": true, "moduleResolution": "node", "importHelpers": true, "isolatedModules": true, "strictNullChecks": true, "lib": ["DOM", "ES5", "ES6", "ES7"] }, "include": ["src/**/*.ts"] } ``` -------------------------------- ### Obsidian Skill Content Structure Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/skill-integration.md Illustrates the progressive disclosure pattern used by the Obsidian skill, with essential knowledge in SKILL.md and detailed references in the reference/ directory. ```treeview .agents/skills/obsidian/ ├── SKILL.md # 285 lines — Essential knowledge │ ├── Quick start (5 lines) │ ├── ESLint rules (100 lines) │ ├── Validation workflow (10 lines) │ ├── Scorecard system (30 lines) │ └── Reference pointers (140 lines) │ └── reference/ # Detailed guides (~100-300 lines each) ├── memory-management.md # Lifecycle patterns ├── type-safety.md # Type narrowing ├── ui-ux.md # Naming, sentence case ├── file-operations.md # Vault API ├── css-styling.md # Theming ├── accessibility.md # MANDATORY A11y ├── code-quality.md # Security, patterns ├── submission.md # Publishing └── eslint-setup.md # Complete config ``` -------------------------------- ### fileExists(filePath) Source: https://github.com/gapmiss/obsidian-plugin-skill/blob/main/_autodocs/api-reference/create-plugin-cli.md Checks if a file exists at the given path. This is a utility function used internally for file operations. ```APIDOC ## fileExists(filePath) ### Description Checks if a file exists at the given path. This is a utility function used internally for file operations. ### Signature ```typescript function fileExists(filePath: string): boolean ``` ### Parameters #### Parameters - **filePath** (`string`) - Required - Absolute or relative path to check ### Returns - `boolean` - `true` if file exists, `false` otherwise ```