From onyx
Create dynamic templates using Templater's template syntax and tp.* functions. Use when the user mentions Templater, dynamic templates, tp.date, tp.file, template commands, or automated note creation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/onyx:obsidian-templaterThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill enables Claude Code to create valid Templater templates for dynamic content in Obsidian.
This skill enables Claude Code to create valid Templater templates for dynamic content in Obsidian.
Templater extends Obsidian's template system with:
<% expression %> Output result
<%* statement %> Execute without output (for logic)
<% tp.date.now() %> Outputs: 2024-02-15
<%* await tp.file.rename("New Name") %> Renames file (no output)
Get current date with optional formatting and offset.
<% tp.date.now() %>
<% tp.date.now("YYYY-MM-DD") %>
<% tp.date.now("dddd, MMMM Do YYYY") %>
<% tp.date.now("YYYY-MM-DD", 7) %>
<% tp.date.now("YYYY-MM-DD", -7) %>
<% tp.date.now("YYYY-MM-DD", "P1M") %>
<% tp.date.now("YYYY-MM-DD", "P-1M") %>
<% tp.date.now("YYYY-MM-DD", 1, tp.file.title, "YYYY-MM-DD") %>
Parameters:
format - Date format string (default: "YYYY-MM-DD")offset - Days as number or ISO 8601 duration stringreference - Reference date stringreference_format - Format of reference date<% tp.date.tomorrow() %>
<% tp.date.tomorrow("YYYY-MM-DD") %>
<% tp.date.yesterday() %>
<% tp.date.yesterday("YYYY-MM-DD") %>
Get a specific weekday relative to current/reference date.
<% tp.date.weekday("YYYY-MM-DD", 0) %>
<% tp.date.weekday("YYYY-MM-DD", 7) %>
<% tp.date.weekday("YYYY-MM-DD", -7) %>
<% tp.date.weekday("YYYY-MM-DD", 0, tp.file.title, "YYYY-MM-DD") %>
Parameters:
format - Date format stringweekday - 0 = Monday of current week, 7 = next Monday, -7 = last Mondayreference - Reference date stringreference_format - Format of reference date| Token | Output | Description |
|---|---|---|
YYYY | 2024 | 4-digit year |
YY | 24 | 2-digit year |
MM | 01-12 | Month (padded) |
M | 1-12 | Month |
MMMM | January | Full month name |
MMM | Jan | Short month |
DD | 01-31 | Day (padded) |
D | 1-31 | Day |
Do | 1st-31st | Day with ordinal |
dddd | Monday | Full weekday |
ddd | Mon | Short weekday |
dd | Mo | Min weekday |
HH | 00-23 | Hour 24h (padded) |
H | 0-23 | Hour 24h |
hh | 01-12 | Hour 12h (padded) |
h | 1-12 | Hour 12h |
mm | 00-59 | Minutes (padded) |
ss | 00-59 | Seconds (padded) |
a | am/pm | AM/PM lowercase |
A | AM/PM | AM/PM uppercase |
W | 1-53 | ISO week number |
Q | 1-4 | Quarter |
<% moment(tp.file.title, "YYYY-MM-DD").format("MMMM Do, YYYY") %>
<% moment(tp.file.title, "YYYY-MM-DD").startOf("month").format("YYYY-MM-DD") %>
<% moment(tp.file.title, "YYYY-MM-DD").endOf("month").format("YYYY-MM-DD") %>
<% moment(tp.file.title, "YYYY-MM-DD").add(1, "week").format("YYYY-MM-DD") %>
<% moment(tp.file.title, "YYYY-MM-DD").subtract(1, "month").format("YYYY-MM-DD") %>
<% tp.file.title %> File name without extension
<% tp.file.path(true) %> Relative path from vault root
<% tp.file.path(false) %> Absolute system path
<% tp.file.folder(true) %> Folder path from vault root
<% tp.file.folder(false) %> Folder name only
<% tp.file.tags %> Array of tags in file
<% tp.file.content %> Full file content as string
<% tp.file.creation_date() %>
<% tp.file.creation_date("YYYY-MM-DD HH:mm") %>
<% tp.file.creation_date("dddd, MMMM Do YYYY") %>
<% tp.file.last_modified_date() %>
<% tp.file.last_modified_date("YYYY-MM-DD HH:mm") %>
Place cursor after template insertion.
<% tp.file.cursor() %>
<% tp.file.cursor(1) %>
<% tp.file.cursor(2) %>
Multiple cursors with same number create multi-cursor selection.
Append text at cursor position.
<%* tp.file.cursor_append("Text to append") %>
Get currently selected text.
<% tp.file.selection() %>
Include another file's content.
<% await tp.file.include("[[Template]]") %>
<% await tp.file.include("[[Note#Section]]") %>
<% await tp.file.include("[[Note#^blockid]]") %>
<% await tp.file.include(tp.file.find_tfile("TemplateName")) %>
Check if file exists.
<% await tp.file.exists("folder/file.md") %>
<% await tp.file.exists(tp.file.folder(true) + "/" + tp.file.title + ".md") %>
Get TFile object by name.
<% tp.file.find_tfile("MyFile").basename %>
<% tp.file.find_tfile("MyTemplate") %>
Create a new file.
<%* await tp.file.create_new("File content", "NewFileName") %>
<%* await tp.file.create_new(tp.file.find_tfile("MyTemplate"), "NewFileName") %>
<%* await tp.file.create_new("Content", "Name", true) %>
<%* await tp.file.create_new("Content", "Name", false, "Path/To/Folder") %>
Parameters:
template - Content string or TFile templatefilename - Name for new file (default: "Untitled")open_new - Open file after creation (default: false)folder - Target folder path or TFolderRename current file.
<%* await tp.file.rename("New Name") %>
<%* await tp.file.rename(tp.file.title + " - Copy") %>
Move current file.
<%* await tp.file.move("/New/Path/" + tp.file.title) %>
<%* await tp.file.move("/Archive/" + tp.file.title) %>
Get clipboard content.
<% await tp.system.clipboard() %>
Show input prompt to user.
<% await tp.system.prompt("Enter a value") %>
<% await tp.system.prompt("Enter title", "Default Value") %>
<% await tp.system.prompt("Enter notes", "", false, true) %>
Parameters:
prompt_text - Text shown above inputdefault_value - Default value in inputthrow_on_cancel - Throw error if cancelled (default: false)multiline - Use multiline textarea (default: false)Show selection list to user.
<% await tp.system.suggester(["Option 1", "Option 2", "Option 3"], ["value1", "value2", "value3"]) %>
<% await tp.system.suggester((item) => item, ["Apple", "Banana", "Cherry"]) %>
<% await tp.system.suggester((item) => item.basename, tp.app.vault.getMarkdownFiles()) %>
Parameters:
text_items - Array of display text or mapping functionitems - Array of values to returnthrow_on_cancel - Throw error if cancelled (default: false)placeholder - Placeholder textlimit - Max items to renderSelect multiple items.
<% await tp.system.multi_suggester(["A", "B", "C"], ["A", "B", "C"]) %>
<% (await tp.system.multi_suggester((f) => f.basename, tp.app.vault.getMarkdownFiles())).map(f => `[[${f.basename}]]`) %>
Make HTTP request.
<% await tp.web.request("https://api.example.com/data") %>
<% await tp.web.request("https://jsonplaceholder.typicode.com/todos/1") %>
<% await tp.web.request("https://api.example.com/data", "items.0.name") %>
Parameters:
url - URL to fetchpath - JSON path to extract specific dataGet daily quote.
<% await tp.web.daily_quote() %>
Get random Unsplash image.
<% await tp.web.random_picture() %>
<% await tp.web.random_picture("200x200") %>
<% await tp.web.random_picture("200x200", "nature,water") %>
Access Templater context information.
<% tp.config.template_file %> Template TFile
<% tp.config.target_file %> Target TFile
<% tp.config.run_mode %> How Templater was triggered
<% tp.config.active_file %> Active file when triggered
Access current file's frontmatter.
<% tp.frontmatter.title %>
<% tp.frontmatter.tags %>
<% tp.frontmatter.author %>
<% tp.frontmatter["custom-field"] %>
Execute code after all templates complete.
<%*
tp.hooks.on_all_templates_executed(() => {
// Code to run after template execution
console.log("Template execution complete");
});
%>
Access Obsidian API.
<%* new tp.obsidian.Notice("Hello!") %>
<%* tp.obsidian.moment().format("YYYY-MM-DD") %>
Call custom scripts from configured folder.
<% await tp.user.myFunction() %>
<% await tp.user.myFunction("arg1", "arg2") %>
---
created: <% tp.date.now("YYYY-MM-DD") %>
tags: daily
---
# <% tp.date.now("dddd, MMMM Do YYYY") %>
## Morning Review
- [ ] Review calendar
- [ ] Check email
- [ ] Set top 3 priorities
## Today's Tasks
- [ ] <% tp.file.cursor() %>
## Notes
## Evening Review
### What went well?
### What could improve?
---
[[<% tp.date.yesterday("YYYY-MM-DD") %>|Yesterday]] | [[<% tp.date.tomorrow("YYYY-MM-DD") %>|Tomorrow]]
---
type: meeting
date: <% tp.date.now("YYYY-MM-DD") %>
attendees:
---
# Meeting: <% await tp.system.prompt("Meeting Title") %>
**Date:** <% tp.date.now("MMMM Do YYYY, h:mm A") %>
**Attendees:** <% await tp.system.prompt("Attendees (comma separated)") %>
## Agenda
1. <% tp.file.cursor(1) %>
## Discussion Notes
## Action Items
- [ ]
## Next Steps
---
type: weekly-review
week: <% tp.date.now("YYYY-[W]WW") %>
---
# Weekly Review: <% tp.date.weekday("MMMM Do", 0) %> - <% tp.date.weekday("MMMM Do", 6) %>
## This Week's Accomplishments
## Incomplete Items
## Lessons Learned
## Next Week's Priorities
1.
2.
3.
## Notes
---
type: project
status: <% await tp.system.suggester(["Active", "Planning", "On Hold", "Complete"], ["active", "planning", "on-hold", "complete"]) %>
created: <% tp.date.now("YYYY-MM-DD") %>
due:
tags: project
---
# <% await tp.system.prompt("Project Name") %>
## Overview
<% tp.file.cursor() %>
## Goals
-
## Tasks
- [ ]
## Resources
## Notes
## Log
### <% tp.date.now("YYYY-MM-DD") %>
- Created project note
---
type: literature
title: <% await tp.system.prompt("Title") %>
author: <% await tp.system.prompt("Author") %>
year: <% await tp.system.prompt("Year") %>
status: queue
created: <% tp.date.now("YYYY-MM-DD") %>
---
# <% tp.frontmatter.title %>
**Author:** <% tp.frontmatter.author %>
**Year:** <% tp.frontmatter.year %>
## Summary
## Key Points
-
## Quotes
## My Thoughts
## Connections
-
---
type: capture
created: <% tp.date.now("YYYY-MM-DD HH:mm") %>
---
# Quick Capture
<% await tp.system.clipboard() %>
---
*Captured on <% tp.date.now("MMMM Do YYYY [at] h:mm A") %>*
<%*
const content = await tp.system.clipboard();
const title = await tp.system.prompt("Note title", content.split('\n')[0].substring(0, 50));
await tp.file.rename(title);
%>
# <% tp.file.title %>
<% await tp.system.clipboard() %>
<%*
const type = await tp.system.suggester(
["Meeting", "Project", "Daily"],
["meeting", "project", "daily"]
);
let template;
switch(type) {
case "meeting":
template = tp.file.find_tfile("Meeting Template");
break;
case "project":
template = tp.file.find_tfile("Project Template");
break;
case "daily":
template = tp.file.find_tfile("Daily Template");
break;
}
await tp.file.create_new(template, tp.date.now("YYYY-MM-DD") + " - " + type, true);
%>
<%*
const includeSection = await tp.system.suggester(["Yes", "No"], [true, false]);
%>
<% includeSection ? "## Optional Section\n\nThis section was included." : "" %>
<% tp.date.now("YYYY-MM-DD", 1, tp.file.title, "YYYY-MM-DD") %>
[[<% tp.date.now("YYYY-MM-DD", -1, tp.file.title, "YYYY-MM-DD") %>|Previous]] | [[<% tp.date.now("YYYY-MM-DD", 1, tp.file.title, "YYYY-MM-DD") %>|Next]]
[[<% tp.date.weekday("YYYY-[W]WW", -7, tp.file.title, "YYYY-[W]WW") %>|Previous Week]] | [[<% tp.date.weekday("YYYY-[W]WW", 7, tp.file.title, "YYYY-[W]WW") %>|Next Week]]
Start: <% moment(tp.file.title, "YYYY-MM").startOf("month").format("YYYY-MM-DD") %>
End: <% moment(tp.file.title, "YYYY-MM").endOf("month").format("YYYY-MM-DD") %>
<%*
const projectName = await tp.system.prompt("Project name");
const priority = await tp.system.suggester(["High", "Medium", "Low"], ["high", "medium", "low"]);
-%>
---
project: <% projectName %>
priority: <% priority %>
---
# <% projectName %>
Priority: <% priority %>
<%*
const targetFile = tp.file.find_tfile("Log");
await tp.app.vault.append(targetFile, "\n- " + tp.date.now() + ": " + await tp.system.prompt("Log entry"));
%>
npx claudepluginhub odysseia06/onyx --plugin onyxCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.