Bullet Journaling with Drafts

Out of curiosity, what happens when you use the “Go to Today’s Journal” action with our modified ds variable, var ds = draft.processTemplate("[[date|%A, %e %B %Y]]");? Does it return an error message or create a new journal page?

It brings up the Monthly Journal. Let’s see if these guys can help us

Amazing set of actions! Whilst I am so tempted to add yet another app to my list I’m going to try and stay away. Do you know where I’d start trying to get this sending tasks to Todoist rather than Goodtasks?

I also use Obsidian for my journalling and general note taking but they don’t have the means to connect to Drafts so I suspect that bit of it may still need to be manual


Thanks for your reply! I looked into ToDoist for some integration options, and it looks like their API relies more on Python than a URL scheme. I’m afraid Python is a bit over my head, but I’ll see if there’s a way to make it work for you.

As far as Obsidian goes, that looks like a really cool tool! You’re the first person to mention it to me, but a cursory glance makes it seem that it relies on markdown files stored in a Finder directory. I believe Drafts has a Finder directory, so maybe there would be a way to send the journal entries there instead of Day One. I’ll look into that possibility, too!

I’ll thank you for your patience as I look for solutions. Nearly all my scripting experience is confined to Drafts and specifically to making these actions work, but I like to learn new things and I’ll see what I can do to help.

Drafts has extensive Todoist support and has wrapper classes for their whole API. There are many examples in the directory of todoist scripting as well, that might be starting points.

As far as Obsidian, you can make an Obsidian vault in the /iCloud Drive/Drafts folder, and Drafts can write files directly to that directory, and they will appear in Obsidian, no problem. There’s been some discussion of this on the forums as well if you search Obsidian.


Okay, let’s see if there’s anything I can add to this that’s of use 🤷🏻

Bullet Journalling Script in Drafts

Let’s try a slightly reworked version with a few tweaks in some of the logic, messages, and title matching.

// This is the same as "Go to Today's Journal", but I don't know how to define them in one place and share that information
let bjTitle = draft.processTemplate("# Journal for [[date|%A, %e %B %Y]]");
const tagsJournal = ["journal"];
const tags = draft.tags;
let draftJournal;

// If the current draft doesn't start with "-", "*", or "@", then add a "- " to the front of it, give it a second-level header 
// "##" and add a horizontal rule "---" beneath this section to visually distinguish each entry.
let currentContent = draft.content;
let strSeparator = "\n"
if ("-*@".indexOf(currentContent[0]) == -1) strSeparator = "\n\n- ";
currentContent = `- ## ${draft.processTemplate("[[created|%H:%M]]") + strSeparator + currentContent}\n\n---`;
// If the current draft doesn't end with a newline, then add one.
if (currentContent.slice(-1) != "\n") currentContent += "\n";

// Find matching drafts
let draftsMatching = Draft.queryByTitle(bjTitle, "all", tagsJournal);

// No match, create new journal
if (draftsMatching.length == 0)
	// Create the base journal
	draftJournal = Draft.create();
	draftJournal.content = bjTitle + "\n\n";
	// Add the bullet journal tags
	// Update and confirm
	app.displayInfoMessage("Created a new journal: " + bjTitle);

// Unique match, add to journal
if (draftsMatching.length == 1)
	// Abort if the draft we're trying to bullet journal is the day's bullet journal draft
	if (draft.uuid == draftsMatching[0].uuid) app.displayErrorMessage("Cannot self-bullet");
	// Not self-bulleting, so continue
		//Grab the matching draft and content
		draftJournal = draftsMatching[0];

// Multiple matches, cannot proceed
if (draftsMatching.length > 1) app.displayErrorMessage(`Non-Unique Match: ${draftsMatching.length} drafts titled '${bjTitle}'`);
// We have a journal, let's populate with new content
	// Enforce end with a newline
	let contentWorking = draftJournal.content;
	if (contentWorking.slice(-1) != "\n") contentWorking += "\n";

	// Check each line for special characters, "-*@". 
	//If they are missing, prepend "- " to the line so it gets journaled.
	let newContent = "";
	let lines = currentContent.split("\n");
		if (line.length > 0)
			if ("-*@".indexOf(line[0]) == -1)
				line = "- " + line;
				newContent += line + "\n";
			else newContent += line + "\n";
		else newContent += line + "\n";

	// Append the original draft content to the journal
	draftJournal.content = contentWorking + newContent;

	// Add the bullet journal tags
	app.displayInfoMessage(`Journaled draft ${draft.uuid}`);

My suspicion is that your monthly journal might contain the daily journal title somewhere in the body. but without having the data to check against it’s just guesswork.

Certainly I didn’t experience any particular issue with the first script, but the reworking might resolve it or perhaps help with narrowing down what is occurring.

Drafts to Obsidian

As Greg’s already noted, you can put your vault in the Drafts iCloud folder. But you’ll find that if you are using other apps to manage Obsidian on the go (e.g. 1Writer is probably the most popular choice), you may find that this limits this option.

If that is the case, you can utilise Shortcuts and Toolbox Pro or Scriptable to work around this. Toolbox Pro and Scriptable both support folder bookmarks, so you can export data from Drafts via these tools to other directories. On the Mac, you can utilise the TADpoLe draft function TA_exportOutsideMacSandbox() to save files outside of the Drafts folders.

Should you happen to be syncing to GitHub using the Obsidian Git plugin or equivalent, I recently released some functionality for working with GitHub in TADpoLe. There’s an accompanying blog post that explains how I have set it up, as I want to be able to capture in Drafts and push it off to Obsidian via GitHub for processing.

Hopefully some of the above will help.


Cannot self-bullet.

I love it. Thanks, Stephen! I’m definitely going to look into Obsidian more. Right now, I’m using DEVONThink for all my long-term storage, but it would be nice to have something a little lighter and speedier to work with just my .txt and .md docs.

Any idea how you can do this with Roam Research?

Roam Research isn’t based on local files, so writing to files isn’t possible. It also does not have a web API (yet), so an approach like the one I’ve used for GitHub also isn’t possible. Roam Research simply isn’t particularly automation friendly right now.

But there are actions in the action directory intended to help Drafts use with Roam Research, but they aren’t geared towards getting the content in through automation.

However, there is a helper tool which effectively creates a local interface that you should be able to run on a Mac (not i*OS) and use (via Puppeteer) to control Chrome to work with Roam Research.

You should then be able to interface with that locally hosted tool from Drafts to interact with your cloud hosted Roam Research instance directly via a Chrome browser.

But this will leave you a bit stuck on mobile devices, unless you say have an always on Mac that you can trigger from the mobile device to carry out your automated interactions on the mobile device’s behalf.

This seems to work, just that I want to test it for a few more days. If there are any mire issues, I’ll be back with more questions! Thanks a ton for the help.

Last point, when I migrate to Day One the header gets stripped off. How can I correct that part?

That was for @sylumer

There are some big gaps around that question!

  1. How are you ‘migrating’ to Day One?
  2. Can you show us an example of the original content, the migrated content and, if it varies to the original, what you expect the final content to look like.

The action Bullet Journal has a sub action - Migrate. So, I just invoke that

Okay, so there’s a bullet journal action group above, which looks to contain a “Migrate Journal Items” action. Presumably this is what you mean.

Looking at its description only…

Process each line of the draft. By the default settings file:

  • Lines starting with “-“ are collected and sent to Day One as a journal entry.
  • Lines starting with “- [ ]” are sent to Things’s Inbox.
  • Lines starting with “@“ are sent to Fantastical.

Everything else is ignored.

Based on the works of Kirk Strauser and inspired by his craftsmanship.

That indicates that the action is only designed to pick up lines starting with a hyphen for Day One. Markdown headings start with an octothorpe.

That would be why you don’t get a heading copied across.

Thanks a ton, you’ve been very helpful as always.

@ianlhayes ianlhayes

Is there some way I can get entries in specific Journals inside the Day One app?

I dont understand if one has to be sticked to the chosen apps (dayOne, Things, Fantastical); for instance could I send both Events and Tasks to Fantastical? and notes to Aoole Notes or nvAlt?


Destinations can be anything supported, but you have to create the action functionality to do it. The action discussed above is processing content, but the “Migrate Journal Items” is specifically configured as per its description.

Yes, but you would have to build an action to take in the content and process them in the correct way.

You could also look in the action directory and across the forum for actions that might suit your specific needs. There have been a number of similar actions for processing individual lines in notes over the last few years.

If you wish to generally process lines in a draft, I might also recommend the TA_processLinesFunctionRetain() function in TADpoLe. It can simplify some of the processing.


Apple notes is a bit special, and if you search the forum, you can find all sorts of information about the limitations of generating Apple Notes from Drafts.

nvAlt is working with files in a folder. Drafts can export to file, but you may need to work around sandboxing.

You could use something like this on a Mac:

On iOS, I would suggest using a call out to Scriptable, or to Shortcuts utilising Toolbox Pro, as both Scriptable and Toolbox Pro support folder bookmarking which can allow you to punch through the sandboxing restrictions.

In summary, you can do all the things you want, but the actions as they stand do not do what you want, you would need to modify them to suit your own purposes.

very clear, thanks!
…but AFAIK I can change the embedded actions to send my text snippet to another app; for instance how can I change the Task script (I still refer to Bullett Journal Group) to send my text to Fantastical instead of Things…?


How are your JavaScripting skills?

As noted above, you need to tailor the actions if you want to do something different. These rely on scripting. There are lots of examples of working with Fantastical in the Action directory and this forum.