Prerequisites
Node.js 18 or higher
A text editor
Basic TypeScript knowledge
Step 1: Create Plugin Directory
Create a new directory for your plugin:
mkdir my-inkdown-plugin
cd my-inkdown-plugin
npm init -y
Step 2: Install Dependencies
Install the Inkdown plugin API:
npm install @inkdown/api
npm install -D typescript esbuild
Step 3: Create Manifest
Create manifest.json in your plugin directory:
{
"id" : "my-first-plugin" ,
"name" : "My First Plugin" ,
"version" : "1.0.0" ,
"minAppVersion" : "1.0.0" ,
"description" : "My first Inkdown plugin" ,
"author" : "Your Name"
}
The id must be unique and use kebab-case (lowercase with hyphens).
Step 4: Create Plugin Class
Create src/index.ts:
import { Plugin } from '@inkdown/api' ;
export default class MyFirstPlugin extends Plugin {
async onload () {
console . log ( 'My First Plugin loaded!' );
// Add a command
this . addCommand ({
id: 'hello-world' ,
name: 'Say Hello' ,
callback : () => {
this . showNotice ( 'Hello from My First Plugin!' );
},
});
// Add a status bar item
const statusBar = this . addStatusBarItem ();
statusBar . setText ( 'My Plugin' );
statusBar . setTitle ( 'Click me!' );
statusBar . setOnClick (() => {
this . showNotice ( 'Status bar clicked!' );
});
}
async onunload () {
console . log ( 'My First Plugin unloaded' );
}
}
Create tsconfig.json:
{
"compilerOptions" : {
"target" : "ES2020" ,
"module" : "ESNext" ,
"moduleResolution" : "node" ,
"strict" : true ,
"skipLibCheck" : true ,
"outDir" : "dist" ,
"declaration" : true
},
"include" : [ "src/**/*" ]
}
Step 6: Add Build Scripts
Update package.json:
{
"scripts" : {
"build" : "esbuild src/index.ts --bundle --outfile=dist/main.js --format=cjs --external:@inkdown/api" ,
"dev" : "npm run build -- --watch"
}
}
Step 7: Build Your Plugin
This creates dist/main.js - your compiled plugin.
Step 8: Install Plugin in Inkdown
Copy your plugin directory to Inkdown’s plugins folder:
Linux : ~/.config/inkdown/plugins/
macOS : ~/Library/Application Support/inkdown/plugins/
Windows : %APPDATA%\inkdown\plugins\
Restart Inkdown or reload plugins
Enable your plugin in Settings → Plugins
Step 9: Test Your Plugin
Open the command palette (Ctrl/Cmd + P)
Search for “Say Hello”
Run the command to see your notification
Check the status bar for your plugin item
Next Steps
Add Settings
Create a settings tab for user configuration:
import { PluginSettingTab , Setting } from '@inkdown/api' ;
interface MyPluginSettings {
greeting : string ;
}
const DEFAULT_SETTINGS : MyPluginSettings = {
greeting: 'Hello' ,
};
export default class MyFirstPlugin extends Plugin {
settings : MyPluginSettings = DEFAULT_SETTINGS ;
async onload () {
await this . loadSettings ();
this . addSettingTab ( new MySettingTab ( this . app , this ));
this . addCommand ({
id: 'custom-greeting' ,
name: 'Custom Greeting' ,
callback : () => {
this . showNotice ( ` ${ this . settings . greeting } from My Plugin!` );
},
});
}
async loadSettings () {
const data = await this . loadData < MyPluginSettings >();
this . settings = { ... DEFAULT_SETTINGS , ... data };
}
async saveSettings () {
await this . saveData ( this . settings );
}
}
class MySettingTab extends PluginSettingTab {
plugin : MyFirstPlugin ;
constructor ( app : App , plugin : MyFirstPlugin ) {
super ( app , plugin );
this . plugin = plugin ;
}
display () {
const { containerEl } = this ;
new Setting ( containerEl )
. setName ( 'Greeting Text' )
. setDesc ( 'Customize your greeting message' )
. addText ( text => text
. setValue ( this . plugin . settings . greeting )
. onChange ( async ( value ) => {
this . plugin . settings . greeting = value ;
await this . plugin . saveSettings ();
})
);
}
}
Add Editor Commands
Create commands that work with the active editor:
this . addCommand ({
id: 'insert-timestamp' ,
name: 'Insert Timestamp' ,
editorCallback : ( editor ) => {
const timestamp = new Date (). toISOString ();
editor . replaceSelection ( timestamp );
},
});
Listen to Events
React to file system changes:
async onload () {
this . registerEvent (
this . app . workspace . onFileCreate (( file ) => {
console . log ( 'File created:' , file . path );
})
);
}
Learn More
Plugin Class Lifecycle methods and base functionality
Commands Register commands and shortcuts
Settings Create settings UI
Best Practices Guidelines for plugin development