Script: Apple watch shopping capture: automate draft actions based on keyword in text/tags coming from watch?

Hi all

So I use drafts for everything (no surprises here :)) and one thing that takes a lot of manual work is dealing with shopping items.

I cant use drafts for shopping lists (since i need to share them with wife and kids) and thus i use apple reminders. The actions List in reminders is perfect for that.

the “problem” (1st world problems… :slight_smile: ) is that i use quick capture for shopping items from the drafts app on my watch each time i remember an item so i end up with 5-6 separate drafts with single/multiple shopping items like this:

now i have to remember to go each day one by one and click the send to reminders action to get them to the family shopping list…

so after this long intro im wondering, can i automate this somehow? I thought of a few things but don’t know how to proceed.

  1. add a keyword (like buy) to each line/draft which will trigger a drafts automation and send to reminder? (can you even automate that in drafts?)

  2. apply a tag somehow (ie shopping) when i capture on the watch (in new watch os7 i understand there can be multiple complications, perhaps a separate capture to shopping complication)? and then automate based on the tag

  3. other idea?

any help or directions would ne super appreciate :slight_smile:



I think it should be possible to write a small script in an action that guesses if it is a shopping list.

So an approach would be to loop (for) through all items with (only?) the watch tag on it and find those with 1-3 lines and not too long sentences.

Then add a new tag when sure or ask the user about it.

A fun idea would be to build a dictionary (JSON) for all the items you found and then use this to improve the guessing.

I would suspect that after some weeks the guessing gets quite sofisticated.

Would you have the skills to start fit a simple script? (look into TADpole for basic actions and examples if you not had already)

Keep in mind I haven’t tested this, but you might be able to use a Shortcut for this. Search for Drafts with a specific tag then use the add to reminders action for each one found. You might even be able to to automate that to run at a specific time each day without prompting you, now that Shortcuts allows for it in iOS 14. Just another thought for research.

thx guys for the input!

haha i really wish but my skills of programming are zero ;D

@yvonnezed, thx for the suggestions im looking more for a mac based solution TBH, but will explore shortcuts

gott say i thought this would are relatively straight forward and that more people would use such things.
I wonder @agiletortoise, will it be possible with watchOS 7 to define a complication with a custom tag so every capture from that gets the custom tag?



Hi guys

Stil struggling with this, would appreciate any suggestions that could fit a non technical user :slight_smile:


Hi @zeltak

it is weekend and time for my good deed in the forum

Is the code readable? Do you need an explanation?

Please feel free to ask


Wow this is amazing, thx so much @Andreas_Haberle!! Cant thank you enough :smiley:

I have zero coding language but managed to modify it a bit ( I assume there re much more intelligent ways to do so :slight_smile: … ) :

  • i don’t need Markdown list so took out the syntax here
match_list += " "+ content_lines[line_index] + "\n";
  • also i export my items to a shopping list with my wife named Shopping so changed that as well
  title_master : "# Shopping",

I have 2 questions if you don’t mind!

  1. is there a way to have the original watch tagged shopping items auto archive (currently they stay in the inbox alongside the non shopping items with watch which are not processed)

  2. can the little window which pops up (saying dismiss) either be removed or if not have a cancel button?

thx against much i learned a lot from this!



Actions have an option to do this on success. Just change the action to archive on a successful run rather than default.

Prefix line 67 with two forward slashed like this:


That should stop it appearing.

Your really welcome. I love the idea. It was fun!

Thanks Stephen! You totally rock!

I updated the action

It now includes all your changes

thx @sylumer

the commenting of line 67 was perfect!

as for the archive after success part i had that already yet this only works on the draft this is launched from. But the script merges 2…n scripts and they don’t get archived. I wonder if the script can archive them or is that impossible technically?

Also i think related i tried to add a Draft action to run immediately after the completion of the script but again this runs only on the note the action is launched from and not the merged note:

any clue how to male the second draft action RM::Q>Shopping run on the merged note and not the note the first action was started from?

thx a lot guys appreciate the help a lot and learning much about drafts!!



OK, got it. I’d read this at first as being a manual multi-select and process, but I see it is now filtering automatically. But the good news is that yes, this is possible.

Keeping with the approach Andreas has used, you can do this by adding two lines.

I added the first after the remove _watch_tag setting, but you could place it in any number of places in the constraint definition. It is a setting to tell the script to archive drafts it is merging.

  remove_watch_tag : true,
  archive: true,
  max_lines : 5,

Next we want to use that setting. I’ve added this in after the merge tag is added.

        draft_candidate.isArchived = p_constraints.archive;

Here we’re telling the script to update the current draft to set the archival attribute to whatever was set in the constraints.

With the changes above, a little bit of reformatting, switching vars to lets (functionally no change, but some good practice to help avoid coding issues), applying your updates, and correcting a variable typo, the revised code might look a bit like this:

// shopping list: finding and merging shopping lists
//TODO: remove watch tag
// ignore processed notes 

const constraints =
	tag_master: "shopping_master",
	title_master: "# Shopping",
	tag_watch: "watch",
	merged_tag: "shopping_merged",
	dismissed_tag: "shopping_dismissed",
	remove_watch_tag: true,
	archive: true,
	max_lines: 5,
	max_line_length: 42,
	look_in: "inbox" // archive, flagged, trash, all

function get_items(p_constraints)
	let match_list = "";
	let data_list = Draft.query("", p_constraints.look_in, [p_constraints.tag_watch], [p_constraints.merged_tag, p_constraints.dismissed_tag]);

	for (let index in data_list)
		let draft_candidate = data_list[index];
		let content_lines = draft_candidate.lines
		let max_line_length = 0;
		for (let line_index in content_lines)
			let active_length = content_lines[line_index].length;
			if (max_line_length < active_length) max_line_length = active_length;

		if (content_lines.length < p_constraints.max_lines && max_line_length < p_constraints.max_line_length)
			draft_candidate.isArchived = p_constraints.archive;

			for (let line_index in content_lines)
				let active_item = content_lines[line_index];
				if (active_item.length > 0) match_list += content_lines[line_index] + "\n";
	return match_list;

let items = get_items(constraints);

// put this into the shopping list draft
let shopping_list = Draft.query("", "all", [constraints.tag_master])[0];

if (shopping_list == null)
	shopping_list = new Draft();
	shopping_list.content = constraints.title_master;

1 Like

I agree.

I did not know about the let and var difference.
I will use let in future

might not be necessary cause it is the only useful behaviour

I did not get that draft.isArchived is a writable property.
Hmm it is not really documented in the script interface. So good to know.

You might even want to trash the merged drafts with

    draft_candidate.isTrashed = true;

Instead of archiving them.

Wow guys wow, this is amazing (and so fun to follow as a non coder and begin to understand :))

thx! I added this to the code (and commented the archive option (was that needed)?:

if (content_lines.length < p_constraints.max_lines && max_line_length < p_constraints.max_line_length)
			// draft_candidate.isArchived = p_constraints.archive;
			draft_candidate.isTrashed = true;

but it seems only the other notes are sent to the trash and the original note to archive?

Also only the first note is being sent to the reminders with my send to reminder action, and not the shopping list merged note.

TBH this is leaps and bounds beyond what i imagined so if you guys had enough of me i can live with the current state :smiley:

@Andreas_Haberle, since all credit goes to you (With the kind help of @sylumer ofc!) , will you want to UL it as a proper script so other users can enjoy it? If you cant. be bothered i will gladly do it myself

best and thx again


Read only properties should have the read only label on them.

1 Like