Full-featured library for writing Alfred workflows
Failed to load latest commit information.
bin Add new utility functions & refactor Dec 17, 2017
docs Document persisting workflow variables Jun 29, 2018
extras Change docs theme to deanishe/alabaster fork Dec 3, 2017
tests Ensure util.appinfo() handles multiple apps with the same bundle ID Jul 22, 2018
workflow Ensure util.appinfo() handles multiple apps with the same bundle ID Jul 22, 2018
.coveragerc Add .coveragerc Feb 28, 2016
.gitignore Use new Alfred 3.4.1 variable-setting mechanism Jul 16, 2017
.gitmodules Use HTTP URL for alabaster submodule Dec 3, 2017
.travis.yml Turn off Python 2.6 on Travis (it doesn't work any more) Sep 19, 2017
Alfred-Workflow 2.0.ft Add todo for V2 Nov 6, 2014
LICENCE.txt Add setup.py Aug 17, 2014
MANIFEST.in Add required setup file to manifest Mar 22, 2016
README.md Document persisting workflow variables Jun 29, 2018
README_PYPI.rst Remove any mentions of (no longer supported) importing of AW from a zip Dec 4, 2017
TODO Update TODOs Mar 22, 2016
alfred-workflow-1.36.zip Ensure util.appinfo() handles multiple apps with the same bundle ID Jul 22, 2018
icon.png Add logo Jul 5, 2015
modd.conf Change docs theme to deanishe/alabaster fork Dec 3, 2017
requirements-docs.txt Change docs theme to deanishe/alabaster fork Dec 3, 2017
requirements-test.txt Change docs theme to deanishe/alabaster fork Dec 3, 2017
run-tests.sh Add new utility functions & refactor Dec 17, 2017
setup.cfg Add notifications Feb 23, 2016
setup.py Document persisting workflow variables Jun 29, 2018
tox.ini Change docs theme to deanishe/alabaster fork Dec 3, 2017


Alfred-Workflow logo


A helper library in Python for authors of workflows for Alfred 2 and 3.

Build Status Coverage Status Latest Version Development Status Supported Python Versions

Supports OS X 10.6+ and Python 2.6 and 2.7 (Alfred 3 is 10.9+/2.7 only).

Alfred-Workflow takes the grunt work out of writing a workflow by giving you the tools to create a fast and featureful Alfred workflow from an API, application or library in minutes.

The only library, in any language, that always supports all current Alfred features.


  • Auto-saved settings API for your workflow
  • Super-simple data caching
  • Fuzzy filtering (with smart diacritic folding)
  • Keychain support for secure storage of passwords, API keys etc.
  • Simple generation of Alfred feedback (JSON/XML output)
  • Input/output decoding for handling non-ASCII text
  • Lightweight web API with Requests-like interface
  • Catches and logs workflow errors for easier development and support
  • "Magic" arguments to help development/debugging
  • Pre-configured logging
  • Easily launch background tasks (daemons) to keep your workflow responsive
  • Automatically check for workflow updates via GitHub releases
  • Post notifications via Notification Center
  • Painlessly add directories to sys.path

Alfred 3-only features

  • Set workflow variables from code
  • Advanced modifiers
  • Alfred 3-only updates (won't break Alfred 2 installs)
  • Re-running of Script Filters



Note: If you're new to Alfred workflows, check out the tutorial in the docs.

With pip

You can install Alfred-Workflow directly into your workflow with:

# from your workflow directory
pip install --target=. Alfred-Workflow

You can install any other library available on the Cheese Shop the same way. See the pip documentation for more information.

It is highly advisable to bundle all your workflow's dependencies with your workflow in this way. That way, it will "just work".

From source

  1. Download the alfred-workflow-X.X.X.zip from the GitHub releases page.
  2. Extract the ZIP archive and place the workflow directory in the root folder of your workflow (where info.plist is).

Your workflow should look something like this:

Your Workflow/

Alternatively, you can clone/download the Alfred-Workflow repository and copy the workflow subdirectory to your workflow's root directory.


A few examples of how to use Alfred-Workflow.

Workflow script skeleton

Set up your workflow scripts as follows (if you wish to use the built-in error handling or sys.path modification):

# encoding: utf-8

import sys

# Workflow3 supports Alfred 3's new features. The `Workflow` class
# is also compatible with Alfred 2.
from workflow import Workflow3

def main(wf):
    # The Workflow3 instance will be passed to the function
    # you call from `Workflow3.run`.
    # Not super useful, as the `wf` object created in
    # the `if __name__ ...` clause below is global...
    # Your imports go here if you want to catch import errors, which
    # is not a bad idea, or if the modules/packages are in a directory
    # added via `Workflow3(libraries=...)`
    import somemodule
    import anothermodule

    # Get args from Workflow3, already in normalized Unicode.
    # This is also necessary for "magic" arguments to work.
    args = wf.args

    # Do stuff here ...

    # Add an item to Alfred feedback
    wf.add_item(u'Item title', u'Item subtitle')

    # Send output to Alfred. You can only call this once.
    # Well, you *can* call it multiple times, but subsequent calls
    # are ignored (otherwise the JSON sent to Alfred would be invalid).

if __name__ == '__main__':
    # Create a global `Workflow3` object
    wf = Workflow3()
    # Call your entry function via `Workflow3.run()` to enable its
    # helper functions, like exception catching, ARGV normalization,
    # magic arguments etc.


Cache data for 30 seconds:

def get_web_data():
    return web.get('http://www.example.com').json()

def main(wf):
    # Save data from `get_web_data` for 30 seconds under
    # the key ``example``
    data = wf.cached_data('example', get_web_data, max_age=30)
    for datum in data:
        wf.add_item(datum['title'], datum['author'])



Grab data from a JSON web API:

data = web.get('http://www.example.com/api/1/stuff').json()

Post a form:

r = web.post('http://www.example.com/',
             data={'artist': 'Tom Jones', 'song': "It's not unusual"})

Upload a file:

files = {'fieldname' : {'filename': "It's not unusual.mp3",
                        'content': open("It's not unusual.mp3", 'rb').read()}
r = web.post('http://www.example.com/upload/', files=files)

WARNING: As this module is based on Python 2's standard HTTP libraries, on older versions of OS X/Python, it does not validate SSL certificates when making HTTPS connections. If your workflow uses sensitive passwords/API keys, you should strongly consider using the requests library upon which the web.py API is based.

Keychain access

Save password:

wf = Workflow()
wf.save_password('name of account', 'password1lolz')

Retrieve password:

wf = Workflow()
wf.get_password('name of account')


The full documentation, including API docs and a tutorial, can be found at deanishe.net.

Dash docset

The documentation is also available as a Dash docset.

Licensing, thanks

The code and the documentation are released under the MIT and Creative Commons Attribution-NonCommercial licences respectively. See LICENCE.txt for details.

The documentation was generated using Sphinx and a modified version of the Alabaster theme by bitprophet.

Many of the cooler ideas in Alfred-Workflow were inspired by Alfred2-Ruby-Template by Zhaocai.

The Keychain parser was based on Python-Keyring by Jason R. Coombs.


Adding a workflow to the list

If you want to add a workflow to the list of workflows using Alfred-Workflow, don't add it to the docs! The list is machine-generated from Packal.org and the library_workflows.tsv file. If your workflow is available on Packal, it will be added on the next update. If not, please add it to library_workflows.tsv, and submit a corresponding pull request.

The list is not auto-updated, so if you've released a workflow and are keen to see it in this list, please open an issue asking me to update the list.

Bug reports, pull requests

Please see the documentation.


Workflows using Alfred-Workflow

Here is a list of some of the many workflows based on Alfred-Workflow.