Script Filter Results and the XML Format


This document is valid for Alfred 2, as of version 2.5 of Alfred and 1.8.5 of Alfred-Workflow.

For Alfred 3, see Alfred’s online docs. The major differences are the handling of modifiers and the addition of Workflow variables and quicklookurl.

If you’re using Alfred 3, it may still be useful to read this description, as the behaviour described still applies to Alfred 3.

Alfred’s Script Filters are its most powerful workflow API and a main focus of Alfred-Workflow. Script Filters work by receiving a {query} from Alfred and returning a list of results as XML.

To build this list of results use the Workflow.add_item() method, and then Workflow.send_feedback() to send the results back to Alfred.

This document is an attempt to explain how the many options available in the XML format and Workflow.add_item()‘s arguments work.


As Script Filters use STDOUT to send their results to Alfred as XML, you must not print() or log any output to STDOUT or it will break the XML, and Alfred will show no results.

XML format / available parameters


If you’re not using Alfred-Workflow to generate your Script Filter’s output, you should use a real XML library to do so. XML is a lot more finicky that it looks, and it’s fairly easy to create invalid XML. Unless your XML is hard-coded (i.e. never changes), it’s much safer and more reliable to use a proper XML library than to generate your own XML.

This is a valid and complete XML result list containing just one result with all possible options. Workflow.send_feedback() will print something much like this to STDOUT when called (though it won’t be as pretty as it will all be on one line).

<?xml version="1.0" encoding="UTF-8"?>
    <item uid="home" valid="YES" autocomplete="Home Folder" type="file">
        <title>Home Folder</title>
        <subtitle>Home folder ~/</subtitle>
        <subtitle mod="shift">Subtext when shift is pressed</subtitle>
        <subtitle mod="fn">Subtext when fn is pressed</subtitle>
        <subtitle mod="ctrl">Subtext when ctrl is pressed</subtitle>
        <subtitle mod="alt">Subtext when alt is pressed</subtitle>
        <subtitle mod="cmd">Subtext when cmd is pressed</subtitle>
        <text type="copy">Text when copying</text>
        <text type="largetype">Text for LargeType</text>
        <icon type="fileicon">~/</icon>

The first line is the standard XML declaration. If you’re generating your own XML, you should probably use a declaration exactly as shown here and ensure your XML is encoded as UTF-8 text. If you’re using Alfred-Workflow, the XML declaration will be generated for you and it will ensure that the XML output is UTF-8-encoded.

The root element must be <items> (lines 2 and 16).

The <items> element contains one or more <item> elements.

To generate the above XML with Alfred-Workflow you would use:

from workflow import Workflow

wf = Workflow()

wf.add_item(u'Home Folder',     # title
            u'Home folder ~/',  # subtitle
                u'shift': u'Subtext when shift is pressed',
                u'fn': u'Subtext when fn is pressed',
                u'ctrl': u'Subtext when ctrl is pressed',
                u'alt': u'Subtext when alt is pressed',
                u'cmd': u'Subtext when cmd is pressed'
            autocomplete=u'Home Folder',
            largetext=u'Text for LargeType',
            copytext=u'Text when copying')

# Print XML to STDOUT

Basic example

A minimal, valid result looks like this:

    <title>My super title</title>

Generated with:

wf.add_item(u'My super title')

This will show a result in Alfred with Alfred’s blank workflow icon and “My super title” as its text.

Everything else is optional, but some parameters don’t make much sense without other complementary parameters. Let’s have a look.

Item parameters


This is the large text shown for each result in Alfred’s results list.

Pass to Workflow.add_item() as the title argument or the first unnamed argument. This is the only required argument and must be unicode:

wf.add_item(u'My title'[, ...])


wf.add_item(title=u'My title'[, ...])


This is the smaller text shown under each result in Alfred’s results list.


Remember that users can turn off subtitles in Alfred’s settings. If you don’t want to confuse minimalists, don’t relegate essential information to the subtitle. On the other hand, you could argue that users who think turning off subtitles is okay deserve what they get…

Pass to Workflow.add_item() as the subtitle argument or the second unnamed argument (the first, title, is required and must therefore be present.

It’s also possible to specify custom subtitles to be shown when a result is selected and the user presses one of the modifier keys (cmd, opt, ctrl, shift, fn).

These are specified in the XML file as additional <subtitle> elements with mod="<key>" attributes (see lines 6–10 in the example XML).

In Alfred-Workflow, you can set modifier-specific subtitles with the modifier_subtitles argument to Workflow.add_item(), which must be a dictionary with some or all of the keys alt, cmd, ctrl, fn, shift and the corresponding values set to the unicode subtitles to be shown when the modifiers are pressed (see lines 7–13 of the example code).


If the user presses TAB on a result, the query currently shown in Alfred’s query box will be expanded to the autocomplete value of the selected result.

If the user presses ENTER on a result with valid set to no, Alfred will expand the query as if the user had pressed TAB.

Pass to Workflow.add_item() as the autocomplete argument. Must be unicode.

When a user autocompletes a result with TAB, Alfred will run the Script Filter again with the new query.

If no autocomplete parameter is specified, using TAB on a result will have no effect.


Pass to Workflow.add_item() as the arg argument. Must be unicode.

This is the “value” of the result that will be passed by Alfred as {query} to the Action(s) or Output(s) your Script Filter is connected to when the result is “actioned” (i.e. by selecting it and hitting ENTER or using CMD+NUM).

Additionally, if you press CMD+C on a result in Alfred, arg will be copied to the pasteboard (unless you have set copy text for the item).

Other than being copyable, setting arg doesn’t make great deal of sense unless the item is also valid. An exception is if the item’s type is file. In this case, a user can still use File Actions on an item, even if it is not valid.


arg may also be specified as an attribute of the <item> element, but specifying it as a child element of <item> is more flexible: you can include newlines within an element, but not within an attribute.

Alfred’s behaviour is a little complicated when arg and valid are not specified. By default, Alfred will set arg to an empty string and valid to True. This may or may not make the item actionable depending on your Script Filter settings.

Alfred-Workflow, on the other hand, will set valid to False if arg and valid are not set, making the item unactionable. This is done to provide more predictable behaviour.


Passed to Workflow.add_item() as the valid argument. Must be True or False (the default).

In the XML file, valid is an attribute on the <item> element and must have the value of either YES or NO:

<item valid="YES">
<item valid="NO">

valid determines whether a user can action a result (i.e with ENTER or CMD+NUM) in Alfred’s results list or not ("YES"/True meaning they can). If a result has the type file, users can still perform File Actions on it (if arg is set to a valid filepath).

Specifying valid=True/valid="YES" has no effect if arg isn’t set.


Pass to Workflow.add_item() as the uid argument. Must be unicode.

Alfred uses the uid to uniquely identify a result and apply its “knowledge” to it. That is to say, if (and only if) a user hits ENTER on a result with a uid, Alfred will associate that result (well, its uid) with its current query and prioritise that result for the same query in the future.

As a result, in most situations you should ensure that a particular item always has the same uid. In practice, setting uid to the same value as arg is often a good choice.

If you omit the uid, Alfred will show results in the order in which they appear in the XML file (the order in which you add them with Workflow.add_item()).


The type of the result. Currently, only file and file:skipcheck are supported.

Pass to Workflow.add_item() as the type argument. Should be unicode. Currently, the only allowed value is file.

If the type of a result is set to file (the only value currently supported by Alfred), it will enable users to “action” the item, as in Alfred’s file browser, and show Alfred’s File Actions (Open, Open with…, Reveal in Finder etc.) using the default keyboard shortcut set in Alfred Preferences > File Search > Actions > Show Actions.

If type is set to file:skipcheck, Alfred won’t test to see if the file specified as arg actually exists. This will save a tiny bit of time if you’re sure the file exists.

For File Actions to work, arg must be set to a valid filepath, but it is not necessary for the item to be valid.

copy text

Text that will be copied to the pasteboard if a user presses CMD+C on a result.

Pass to Workflow.add_item() as the copytext argument. Must be unicode.

Set using <text type="copy">Copy text goes here</text> in XML.

If copytext is set, when the user presses CMD+C, this will be copied to the pasteboard and Alfred’s window will close. If copytext is not set, the selected result’s arg value will be copied to the pasteboard and Alfred’s window will close. If neither is set, nothing will be copied to the pasteboard and Alfred’s window will close.

large text

Text that will be displayed in Alfred’s Large Type pop-up if a user presses CMD+L on a result.

Pass to Workflow.add_item() as the largetext argument. Must be unicode.

Set using <text type="largetype">Large text goes here</text> in XML.

If largetext is not set, when the user presses CMD+L on a result, Alfred will display the current query in its Large Type pop-up.


There are three different kinds of icon you can tell Alfred to use. Use the type attribute of the <icon> XML element or the icontype argument to Alfred.add_item() to define which type of icon you want.

Image files

This is the default. Simply pass the filename or filepath of an image file:



Workflow.add_item(..., icon=u'icon.png')

Relative paths will be interpreted by Alfred as relative to the root of your workflow directory, so icon.png will be your workflow’s own icon, icons/github.png is the file github.png in the icons subdirectory of your workflow etc.

You can pass paths to PNG or ICNS files. If you’re using PNG, you should try to make them square and ideally 256 px wide/high. Anything bigger and Alfred will have to resize the icon; smaller and it won’t look so good on a Retina screen.

File icons

Alternatively, you can tell Alfred to use the icon of a file:

<icon type="fileicon">/path/to/some/file.pdf</icon>


Workflow.add_item(..., icon=u'/path/to/some/file.pdf',

This is great if your workflow lists the user’s own files, and makes your Script Filter work like Alfred’s File Browser or File Filters in that by passing the file’s path as the icon, Alfred will show the appropriate icon for that file.

If you have set a custom icon for, e.g., your Downloads folder, this custom icon will be shown. In the case of media files that have cover art, e.g. audio files, movies, ebooks, comics etc., any cover art will not be shown, but rather the standard icon for the appropriate filetype.

Filetype icons

Finally, you can tell Alfred to use the icon for a specific filetype by specifying a UTI as the value to icon and filetype as the type:

<icon type="filetype">public.html</icon>


Workflow.add_item(..., icon=u'public.html', icontype=u'filetype')

This will show the icon for HTML pages, which will be different depending on which browser you have set as the default.

filetype icons are useful if your Script Filter deals with files and filetypes but you don’t have a specific filepath to use as a fileicon.


If you need to find the UTI for a filetype, Alfred can help you.

Add a File Filter to a workflow, and drag a file of the type you’re interested in into the File Types list in the Basic Setup tab. Alfred will show the corresponding UTI in the list (in this screenshot, I dragged a .py file into the list):


You can also find the UTI of a file (along with much of its other metadata) by running mdls /path/to/the/file in Terminal.