Skip to content

Instantly share code, notes, and snippets.

@lenalebt
Last active December 2, 2025 15:07
Show Gist options
  • Select an option

  • Save lenalebt/8e58aa21392c388d8c7d65bad3206e35 to your computer and use it in GitHub Desktop.

Select an option

Save lenalebt/8e58aa21392c388d8c7d65bad3206e35 to your computer and use it in GitHub Desktop.
"Rollover Daily Todos" for Obsidian Templater

Rollover Daily Todos for Obsidian, but with the Templater Plugin

Rollver daily todos is a really nice extension for Obsidian.md that takes TODOs from yesterdays daily notes and rolls them over to today's notes. It has support for Obsidians built-in templates, but does - to my understanding - not really work well with the Templater Plugin. At least, I was unable to get it to work :-). Also, I wished it had some way to tell me that TODOs have been rolled over a few times already. Doing it this way is my way of working around these limitations.

I took some of the code of that "rollover daily todos" plugin and made it into a templater user script.

How to use

  • Copy rollover_daily_todos.js into your templater user scripts directory.
  • Include it in your daily notes template, like so:
# Tasks

<% await tp.user.rollover_daily_todos() %>

If your folder id different from "Tasks/Daily", you might need to call it like this:

# Tasks

<% await tp.user.rollover_daily_todos(folder="My/Daily/Notes/Folder") %>
  • Activate templater plugin in the settings. Make sure to tick "Trigger templater on new file creation" (2), enable folder templates (3) and add your daily notes template image

  • Import the user script like this in the settings (1): image

async function getAllUnfinishedTodos(file, tasksHeader) {
const contents = await this.app.vault.read(file);
const contentsForDailyTasks = contents.split(tasksHeader)[1] || contents;
const unfinishedTodosRegex = /\t*- \[ \].*/g
const unfinishedTodos = Array.from(contentsForDailyTasks.matchAll(unfinishedTodosRegex)).map(([todo]) => todo)
return unfinishedTodos;
}
function getLastDailyNote(folder, format) {
const { moment } = window
// get all notes in directory that aren't null
const dailyNoteFiles = this.app.vault.getAllLoadedFiles()
.filter(file => file.path.startsWith(folder))
.filter(file => file.basename != null)
// remove notes that are from the future
const todayMoment = moment()
let dailyNotesTodayOrEarlier = []
dailyNoteFiles.forEach(file => {
if (moment(file.basename, format).isSameOrBefore(todayMoment, 'day')) {
dailyNotesTodayOrEarlier.push(file)
}
})
// sort by date
const sorted = dailyNotesTodayOrEarlier.sort((a, b) => moment(b.basename, format).valueOf() - moment(a.basename, format).valueOf());
return sorted[1];
};
async function rollover_daily_todos(folder = "Tasks/Daily", format = "YYYY-MM-DD", tasksHeader = "# Tasks", rolloverMarkCharacter = "❗") {
return (await getAllUnfinishedTodos(getLastDailyNote(folder, format), tasksHeader)).map(task => `${task}${rolloverMarkCharacter}`).join('\n');
}
module.exports = rollover_daily_todos;
@alirostami1
Copy link

Amazing work, thank you. If anyone is interested in embedding the code inside their daily template to avoid creating user script directory and stuff you can use the templater <%* %> tags and the special tR variable to achieve this:

<%*
async function getAllUnfinishedTodos(file, tasksHeader) {
  const contents = await this.app.vault.read(file);
  const contentsForDailyTasks = contents.split(tasksHeader)[1] || contents;
  const unfinishedTodosRegex = /\t*- \[ \].*/g
  const unfinishedTodos = Array.from(contentsForDailyTasks.matchAll(unfinishedTodosRegex)).map(([todo]) => todo)
  return unfinishedTodos;
}

function getLastDailyNote(folder, format) {
	const { moment } = window

	// get all notes in directory that aren't null
	const dailyNoteFiles = this.app.vault.getAllLoadedFiles()
	  .filter(file => file.path.startsWith(folder))
	  .filter(file => file.basename != null)

	// remove notes that are from the future
	const todayMoment = moment()
	let dailyNotesTodayOrEarlier = []
	dailyNoteFiles.forEach(file => {
	  if (moment(file.basename, format).isSameOrBefore(todayMoment, 'day')) {
		dailyNotesTodayOrEarlier.push(file)
	  }
	})

	// sort by date
	const sorted = dailyNotesTodayOrEarlier.sort((a, b) => moment(b.basename, format).valueOf() - moment(a.basename, format).valueOf());
	return sorted[1];
};

async function rollover_daily_todos(folder = "Tasks/Daily", format = "YYYY-MM-DD", tasksHeader = "# Tasks") {
	const lastDailyNote = getLastDailyNote(folder, format);
	const unfinishedTodos = await getAllUnfinishedTodos(lastDailyNote, tasksHeader);
	return unfinishedTodos;
}

const unfinishedTodos = await rollover_daily_todos(folder="daily");

unfinishedTodos.forEach(task => {
	tR += `${task}\n`;
})
%>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment