Skip to main content 首页 创作者 tobi thymer-importer thymer-plugin
thymer-plugin Build Thymer plugins - use when the user asks to create, modify, or debug Thymer plugins for the note-taking/project management app
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tobi/thymer-importer --skill thymer-plugin命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中...
name thymer-plugin description Build Thymer plugins - use when the user asks to create, modify, or debug Thymer plugins for the note-taking/project management app
Thymer Plugin Development
References
Use this skill when building plugins for the Thymer app (thymer.com). Thymer plugins extend the application with custom functionality like status bar items, custom views, formulas, and more.
Plugin Types
AppPlugin (Global)
Extends the entire Thymer application:
Status bar items
Sidebar items
Command palette commands
Custom panels
Toaster notifications
CollectionPlugin
Extends a specific note Collection:
Custom views (table, board, gallery, calendar, custom)
Custom properties with formulas
Navigation buttons
Render hooks for existing views
Custom sorting
File Structure
plugin.js # Plugin code (extends AppPlugin or CollectionPlugin)
plugin.json # Configuration (name, icon, fields, views)
Quick Reference
AppPlugin Example
export class Plugin extends AppPlugin {
onLoad ( ) {
this . = . . ({
: ,
: ,
: ,
: . ()
});
. . ({
: ,
: ,
: . ()
});
. . ({
: ,
: ,
: ,
:
});
}
( ) {
}
}
statusItem
this
ui
addStatusBarItem
label
"My Plugin"
icon
"star"
tooltip
"Click me"
onClick
() =>
this
handleClick
this
ui
addCommandPaletteCommand
label
"My Command"
icon
"wand"
onSelected
() =>
this
doSomething
this
ui
addToaster
title
"Hello"
message
"Plugin loaded!"
dismissible
true
autoDestroyTime
3000
onUnload
CollectionPlugin Example export class Plugin extends CollectionPlugin {
onLoad ( ) {
this .properties .formula ("Total" , ({record} ) => {
const qty = record.number ("Quantity" );
const price = record.number ("Price" );
if (qty == null || price == null ) return null ;
return qty * price;
});
this .properties .render ("Status" , ({record, prop} ) => {
const el = document .createElement ('span' );
el.textContent = prop.text () || 'N/A' ;
el.style .fontWeight = 'bold' ;
return el;
});
this .views .register ("My View" , (viewContext ) => {
return {
onLoad : () => {
viewContext.getElement ().style .padding = "20px" ;
},
onRefresh : ({records} ) => {
const el = viewContext.getElement ();
el.innerHTML = records.map (r =>
`<div>${r.getName()} </div>`
).join ('' );
},
onDestroy : () => {},
onFocus : () => {},
onBlur : () => {},
onKeyboardNavigation : ({e} ) => {},
onPanelResize : () => {}
};
});
this .views .afterRenderBoardCard (null , ({record, element} ) => {
element.style .border = '2px solid blue' ;
});
this .addCollectionNavigationButton ({
label : "Export" ,
icon : "download" ,
onClick : ({panel} ) => this .exportData (panel)
});
}
}
Key APIs
UIAPI (this.ui)
addStatusBarItem({label, icon, tooltip, onClick}) - Status bar
addSidebarItem({label, icon, tooltip, onClick}) - Sidebar
addCommandPaletteCommand({label, icon, onSelected}) - Commands
addToaster({title, message, dismissible, autoDestroyTime}) - Notifications
createButton({icon, label, onClick}) - Create button element
createDropdown({attachedTo, options}) - Dropdown menu
injectCSS(cssString) - Add global styles
getActivePanel() - Get focused panel
getPanels() - Get all panels
createPanel() - Create new panel
registerCustomPanelType(id, callback) - Custom panel types
DataAPI (this.data)
getAllRecords() - Get all workspace records
getRecord(guid) - Get record by GUID
createNewRecord(title) - Create record
getAllCollections() - Get all collections
getActiveUsers() - Get workspace users
PropertiesAPI (this.properties) - CollectionPlugin only
formula(name, fn) - Computed property
render(name, fn) - Custom property rendering
customSort(name, fn) - Custom sorting
ViewsAPI (this.views) - CollectionPlugin only
register(viewName, createHooksFn) - Custom view type
afterRenderBoardCard(viewName, fn) - Board card hook
afterRenderBoardColumn(viewName, fn) - Board column hook
afterRenderGalleryCard(viewName, fn) - Gallery card hook
afterRenderTableCell(viewName, fn) - Table cell hook
afterRenderCalendarEvent(viewName, fn) - Calendar event hook
PluginRecord
getName() - Record title
guid - Record GUID
prop(name) - Get property by name
number(name) - Get numeric property
text(name) - Get text property
date(name) - Get date property
getProperties(viewName) - Get visible properties
getLineItems() - Get document content
PluginProperty
number() - Get as number
text() - Get as text
date() - Get as Date
choice() - Get choice ID
set(value) - Set value
setChoice(choiceName) - Set by choice name
plugin.json Configuration {
"name" : "My Collection" ,
"icon" : "tools" ,
"description" : "Collection description" ,
"item_name" : "Item" ,
"ver" : 1 ,
"show_sidebar_items" : true ,
"show_cmdpal_items" : true ,
"fields" : [
{
"id" : "status" ,
"label" : "Status" ,
"type" : "choice" ,
"icon" : "circle" ,
"active" : true ,
"many" : false ,
"read_only" : false ,
"choices" : [
{ "id" : "todo" , "label" : "To Do" , "color" : "0" , "active" : true } ,
{ "id" : "done" , "label" : "Done" , "color" : "2" , "active" : true }
]
} ,
{
"id" : "amount" ,
"label" : "Amount" ,
"type" : "number" ,
"icon" : "currency-dollar" ,
"number_format" : "USD" ,
"active" : true
}
] ,
"views" : [
{
"id" : "main" ,
"label" : "All Items" ,
"type" : "table" ,
"icon" : "table" ,
"shown" : true ,
"field_ids" : [ "status" , "amount" ] ,
"sort_field_id" : "status" ,
"sort_dir" : "asc"
}
] ,
"page_field_ids" : [ "status" , "amount" ]
}
Property Types
text - Plain text
number - Numeric (formats: plain, formatted, USD, EUR, etc.)
choice - Enum/status with choices
datetime - Date/time
user - User reference
record - Record reference
url - URL link
file - File attachment
image - Image
dynamic - Formula-computed
View Types
table - Table view
board - Kanban board
gallery - Card gallery
calendar - Calendar view
custom - Fully custom view
record - Single record view
Icons Common icons: star, clock, tools, settings, search, home, user, calendar, bell, check, bug, rocket, wand, heart, file-text, folder, download, chart-bar, database
See types.d.ts for full icon list.
Development Workflow
Edit plugin.js and plugin.json
Run npm run dev for hot reload
Build with npm run build
Copy dist/plugin.js to Thymer's Edit Code dialog
Important Notes
Always clean up in onUnload() (intervals, listeners)
Use CSS variables for theming (--bg-default, --text-muted, etc.)
Check viewContext.isDestroyed() after async operations
Use viewContext.isViewingOldVersion() before allowing edits
Property formulas should return null for invalid inputs
Working with Records
Getting Records from a Collection const collections = await this .data .getAllCollections ();
const collection = collections[0 ];
const records = await collection.getAllRecords ();
for (const record of records) {
const title = record.getName ();
const status = record.prop ("Status" )?.text ();
console .log (title, status);
}
Setting Properties const record = this .data .getRecord (guid);
record.prop ("Status" ).set ("Done" );
record.prop ("Amount" ).set (42 );
record.prop ("Priority" ).setChoice ("high" );
Creating Records const collection = (await this .data .getAllCollections ())[0 ];
const newGuid = collection.createRecord ("New Item Title" );
const newRecord = this .data .getRecord (newGuid);
newRecord.prop ("Status" ).set ("Todo" );