A Dart toolkit and runtime for building Obsidian plugins without writing TypeScript. Write your plugin in Dart, compile to CommonJS, and drop it into .obsidian/plugins/.
Built as part of Rhyolite Sync — an end-to-end encrypted sync service for Obsidian. Your notes stay yours: encryption keys never leave your devices, and the server only ever sees ciphertext.
dart pub global activate obsidian_dart
Create your entry point at bin/plugin_entry.dart:
import 'package:obsidian_dart/obsidian_dart.dart';
void main() {
bootstrapPlugin(
onLoad: (plugin) async {
plugin.addCommand(
id: 'hello',
name: 'Say hello from Dart',
callback: () => showNotice('Hello from Dart!'),
);
},
onUnload: (plugin) async {},
);
}
Build and copy to your vault:
dart run obsidian_dart:obsidian_build --plugin-id my_plugin
dart run obsidian_dart:obsidian_manifest --plugin-id my_plugin
# copy build/plugin/my_plugin/ → <vault>/.obsidian/plugins/my_plugin/
| Option |
Default |
Description |
--plugin-id |
(required) |
Obsidian plugin ID |
--entry |
bin/plugin_entry.dart |
Dart entry file |
--out |
build/plugin/<id> |
Output directory |
--plugin-class |
DartPlugin |
JS class name |
--release |
false |
Release optimisations |
--fvm |
false |
Use FVM-managed Dart |
| Option |
Default |
Description |
--plugin-id |
(required) |
Obsidian plugin ID |
--out |
build/plugin/<id> |
Output directory |
| Class |
What's covered |
PluginHandle |
addCommand, addRibbonIcon, addStatusBarItem, addSettingTab, registerEvent, saveData, loadData |
AppHandle |
vault, workspace, metadataCache, secretStorage, keymap |
| Class |
What's covered |
VaultHandle |
getRoot, getFileByPath, getFolderByPath, getMarkdownFiles, getFiles, getAllLoadedFiles, read, cachedRead, readBinary, create, createBinary, createFolder, modify, modifyBinary, append, process, delete, trash, rename, copy, on, offref |
AdapterHandle |
read, readBinary, write, writeBinary, append, process, exists, stat, list, mkdir, rmdir, remove, rename, copy, trashSystem, trashLocal, getResourcePath |
TFileHandle / TFolderHandle |
path, name, parent, stat, basename, extension, children, isRoot |
| Class |
What's covered |
WorkspaceHandle |
getActiveFile, openFile, on |
MetadataCacheHandle |
getFileCache, getCache, on |
| Class |
What's covered |
SettingHandle |
setName, setDesc, addText, addToggle, addDropdown, addButton |
TextComponentHandle |
setValue, setPlaceholder, onChange |
ToggleComponentHandle |
setValue, onChange |
DropdownComponentHandle |
addOption, addOptions, setValue, onChange |
ButtonComponentHandle |
setButtonText, setCta, onClick |
| Class |
What's covered |
ModalContext |
createEl, h3, row, column, input, toggle, button, buttonRow, spinner, showError, onEnter, onEscape, close |
| Utilities |
showNotice, showModal, showTextPrompt, showPasswordPrompt, log |
| Class |
What's covered |
SecretStorageHandle |
getSecret, setSecret, deleteSecret, listSecrets |
| Class |
Description |
VaultEvents / WorkspaceEvents |
Stream-based vault and workspace events |
FileHandle |
TFileHandle extended with size, dates, type detection (isMarkdown, isImage, …) |
FileWatcher |
Watch files/folders with path, glob, size, and event-type filters |
SettingsManager<T> |
Type-safe generic settings with Stream-based change notifications |
SettingsBuilder<T> |
Declarative settings UI with automatic persistence |
PluginSettingsTab |
Fluent settings tab builder |
BatchFileOperations |
Transactional bulk file ops with rollback and progress callbacks |
- Dart SDK
>=3.1.0
- Obsidian 1.7.0+
MIT — see LICENSE.