The Plugin class provides a structured lifecycle for managing your plugin’s initialization, operation, and cleanup. Understanding these lifecycle methods is essential for building reliable Obsidian plugins.
The Plugin Class
All Obsidian plugins extend the Plugin class, which itself extends Component. This inheritance provides automatic lifecycle management and resource cleanup.
export abstract class Plugin extends Component {
app : App ;
manifest : PluginManifest ;
onload () : Promise < void > | void ;
onunload () : void ;
onUserEnable () : void ;
onExternalSettingsChange ? () : any ;
}
Core Lifecycle Methods
onload()
The onload() method is called when your plugin is loaded. This is where you should perform all initialization:
async onload () {
// Load plugin settings
await this . loadData ();
// Register commands
this . addCommand ({
id: 'example-command' ,
name: 'Example Command' ,
callback : () => {
console . log ( 'Command executed' );
}
});
// Register views
this . registerView (
'example-view' ,
( leaf ) => new ExampleView ( leaf )
);
// Register events
this . registerEvent (
this . app . workspace . on ( 'file-open' , ( file ) => {
console . log ( 'File opened:' , file );
})
);
}
The onload() method can be synchronous or asynchronous. Use async if you need to load settings or perform other asynchronous operations during initialization.
onunload()
The onunload() method is called when your plugin is disabled or Obsidian is shut down. The Component system automatically cleans up registered resources, but you can override this method for custom cleanup:
onunload () {
// Custom cleanup logic
console . log ( 'Plugin unloaded' );
}
You typically don’t need to manually unregister events, DOM listeners, or intervals registered through registerEvent(), registerDomEvent(), or registerInterval(). These are automatically cleaned up when the plugin unloads.
onUserEnable()
Called when the user explicitly enables the plugin through the settings. This is useful for opening custom views or performing one-time setup:
onUserEnable () {
// Open a welcome view when user first enables the plugin
this . app . workspace . getRightLeaf ( false ). setViewState ({
type: 'example-view' ,
active: true
});
}
onExternalSettingsChange()
Called when the plugin’s data.json file is modified externally (e.g., by a sync service):
async onExternalSettingsChange () {
// Reload settings from disk
await this . loadData ();
// Update UI or plugin state
this . refreshUI ();
}
Registration Methods
During onload(), use these methods to register plugin features:
Registering Commands
this . addCommand ({
id: 'open-sample-modal' ,
name: 'Open Sample Modal' ,
callback : () => {
new SampleModal ( this . app ). open ();
}
});
Registering Views
this . registerView (
'custom-view' ,
( leaf : WorkspaceLeaf ) => new CustomView ( leaf )
);
Registering Events
this . registerEvent (
this . app . vault . on ( 'modify' , ( file ) => {
console . log ( 'File modified:' , file . path );
})
);
Registering DOM Events
this . registerDomEvent ( document , 'click' , ( evt : MouseEvent ) => {
console . log ( 'Click detected' );
});
Registering Intervals
this . registerInterval (
window . setInterval (() => {
console . log ( 'Periodic check' );
}, 5000 )
);
Always use window.setInterval() instead of setInterval() to avoid TypeScript confusion between Node.js and browser APIs.
Registering Settings Tabs
this . addSettingTab ( new SampleSettingTab ( this . app , this ));
Registering Ribbon Icons
this . addRibbonIcon ( 'dice' , 'Sample Plugin' , ( evt : MouseEvent ) => {
console . log ( 'Ribbon icon clicked' );
});
Registering Status Bar Items
const statusBarItem = this . addStatusBarItem ();
statusBarItem . setText ( 'Status: Active' );
Status bar items are not available on mobile.
Best Practices
Initialize in onload() Perform all plugin initialization in onload(). Never initialize in the constructor.
Use Register Methods Always use registerEvent(), registerDomEvent(), and registerInterval() for automatic cleanup.
Async Operations Make onload() async if you need to load settings or perform other asynchronous initialization.
Minimal onunload() Let the Component system handle cleanup automatically. Only override onunload() for custom cleanup logic.
Complete Example
import { Plugin , TFile } from 'obsidian' ;
export default class ExamplePlugin extends Plugin {
settings : MyPluginSettings ;
async onload () {
// Load settings
await this . loadSettings ();
// Add ribbon icon
this . addRibbonIcon ( 'dice' , 'Example Plugin' , () => {
console . log ( 'Ribbon icon clicked' );
});
// Add status bar
const statusBarItem = this . addStatusBarItem ();
statusBarItem . setText ( 'Status Bar Text' );
// Register command
this . addCommand ({
id: 'open-sample-modal' ,
name: 'Open sample modal' ,
callback : () => {
new SampleModal ( this . app ). open ();
}
});
// Register settings tab
this . addSettingTab ( new SampleSettingTab ( this . app , this ));
// Register event handlers
this . registerEvent (
this . app . workspace . on ( 'file-open' , ( file : TFile ) => {
console . log ( 'File opened:' , file . path );
})
);
// Register DOM event
this . registerDomEvent ( document , 'click' , ( evt : MouseEvent ) => {
console . log ( 'Document clicked' );
});
// Register interval
this . registerInterval (
window . setInterval (() => this . checkStatus (), 5 * 60 * 1000 )
);
}
onunload () {
console . log ( 'Plugin unloaded' );
}
async loadSettings () {
this . settings = Object . assign ({}, DEFAULT_SETTINGS , await this . loadData ());
}
async saveSettings () {
await this . saveData ( this . settings );
}
checkStatus () {
// Periodic status check logic
}
}
App Architecture Learn about the App object and its major modules
Events Deep dive into the event system and event registration