Milkscript to delete all unused tags
![](/img/avatar_default.png?1522022400)
I tried using ChatGPT to write a script for me but it got syntax errors when I tried to run it. Can anyone show me where the errors are?:
# Find all tags that are not used and delete them
# Step 1: Get all tasks
tasks = getTasks()
# Step 2: Create a set to store all used tags
used_tags = set()
# Step 3: Iterate through tasks to extract tags
for task in tasks:
if task.tags:
for tag in task.tags:
used_tags.add(tag)
# Step 4: Get all tags
all_tags = getTags()
# Step 5: Iterate through all tags to find unused tags and delete them
for tag in all_tags:
if tag not in used_tags:
deleteTag(tag)
# Find all tags that are not used and delete them
# Step 1: Get all tasks
tasks = getTasks()
# Step 2: Create a set to store all used tags
used_tags = set()
# Step 3: Iterate through tasks to extract tags
for task in tasks:
if task.tags:
for tag in task.tags:
used_tags.add(tag)
# Step 4: Get all tags
all_tags = getTags()
# Step 5: Iterate through all tags to find unused tags and delete them
for tag in all_tags:
if tag not in used_tags:
deleteTag(tag)
![](/img/avatar/7/h/7h20wffvtarhuv7p8l41ufced/1647980691807/avatar_48.png?1647980640)
andrewski (Remember The Milk) says:
Hi jstaso,
Thanks for your patience in responding! Depending on your definition of "unused" you'll want to use either of the following scripts, and then the last script will take the tags you list and actually delete them.
I don't suggest putting these together just because MilkScript can be powerful and it would be possible to delete something unexpected.
To that end, I would also suggest keeping a regular and right-before-using-a-new-script backup of your tasks. 😌
I'll share the scripts below separated by bold text and end my personal message here! I hope this helps and feel free to reply with any questions or contact us for a follow-up by email. 💙
Script 1: delete all tasks with no incomplete tasks
// Find tags without incomplete tasks
const tags = rtm.getTags().filter(tag => tag.getTasks("status:incomplete").length === 0);
const title =
tags.length === 0 ? "You don't have unused tags" :
tags.length === 1 ? "You have 1 unused tag" :
`You have ${tags.length} unused tags`;
const text = tags.length === 0 ?
"How 'bout that." :
`${tags.map(tag => tag.getName()).join("\n")}`;
rtm.newMessage(title, text);
Script 2: delete all tags with no tasks at all
// Find tags without tasks
const tags = rtm.getTags().filter(tag => tag.getTasks().length === 0);
const title =
tags.length === 0 ? "You don't have unused tags" :
tags.length === 1 ? "You have 1 unused tag" :
`You have ${tags.length} unused tags`;
const text = tags.length === 0 ?
"How 'bout that." :
`${tags.map(tag => tag.getName()).join("\n")}`;
rtm.newMessage(title, text);
Script 3: actually delete tags (will request input of tags separated by a space)
// Bulk remove tags
const tagNames = new Set(rtm.args["Tags to remove"].split(' ').map(tagName => tagName.trim()));
const tags = rtm.getTags().filter(tag => tagNames.has(tag.getName()));
tags.forEach(tag => tag.delete());
const title = tags.length === 1 ? "Removed 1 tag" : `Removed ${tags.length} tags`;
const text = tags.map(tag => tag.getName()).join("\n")
rtm.newMessage(title, text);
Thanks for your patience in responding! Depending on your definition of "unused" you'll want to use either of the following scripts, and then the last script will take the tags you list and actually delete them.
I don't suggest putting these together just because MilkScript can be powerful and it would be possible to delete something unexpected.
To that end, I would also suggest keeping a regular and right-before-using-a-new-script backup of your tasks. 😌
I'll share the scripts below separated by bold text and end my personal message here! I hope this helps and feel free to reply with any questions or contact us for a follow-up by email. 💙
Script 1: delete all tasks with no incomplete tasks
// Find tags without incomplete tasks
const tags = rtm.getTags().filter(tag => tag.getTasks("status:incomplete").length === 0);
const title =
tags.length === 0 ? "You don't have unused tags" :
tags.length === 1 ? "You have 1 unused tag" :
`You have ${tags.length} unused tags`;
const text = tags.length === 0 ?
"How 'bout that." :
`${tags.map(tag => tag.getName()).join("\n")}`;
rtm.newMessage(title, text);
Script 2: delete all tags with no tasks at all
// Find tags without tasks
const tags = rtm.getTags().filter(tag => tag.getTasks().length === 0);
const title =
tags.length === 0 ? "You don't have unused tags" :
tags.length === 1 ? "You have 1 unused tag" :
`You have ${tags.length} unused tags`;
const text = tags.length === 0 ?
"How 'bout that." :
`${tags.map(tag => tag.getName()).join("\n")}`;
rtm.newMessage(title, text);
Script 3: actually delete tags (will request input of tags separated by a space)
// Bulk remove tags
const tagNames = new Set(rtm.args["Tags to remove"].split(' ').map(tagName => tagName.trim()));
const tags = rtm.getTags().filter(tag => tagNames.has(tag.getName()));
tags.forEach(tag => tag.delete());
const title = tags.length === 1 ? "Removed 1 tag" : `Removed ${tags.length} tags`;
const text = tags.map(tag => tag.getName()).join("\n")
rtm.newMessage(title, text);