diff --git a/libtaskotron.spec b/libtaskotron.spec
--- a/libtaskotron.spec
+++ b/libtaskotron.spec
@@ -3,7 +3,7 @@
 %{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
 
 Name:           libtaskotron
-Version:        0.3.17
+Version:        0.3.18
 Release:        1%{?dist}
 Summary:        Taskotron Support Library
 
diff --git a/libtaskotron/directives/exitcode_directive.py b/libtaskotron/directives/exitcode_directive.py
new file mode 100644
--- /dev/null
+++ b/libtaskotron/directives/exitcode_directive.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+# Copyright 2009-2014, Red Hat, Inc.
+# License: GPL-2.0+ <http://spdx.org/licenses/GPL-2.0+>
+# See the LICENSE file for more details on Licensing
+
+from libtaskotron.directives import BaseDirective
+from libtaskotron.exceptions import TaskotronDirectiveError
+from libtaskotron.logger import log
+from libtaskotron import check
+
+
+DOCUMENTATION = """
+module: exitcode_directive
+short_description: set runtask exit code based on last or worst TAP outcome
+description: |
+  This directives takes TAP specified by key ``tap_last`` or ``tap_worst`` (keys are mutually
+  exclusive), and generates returncode based on last or worst TAP outcome. If TAP is empty,
+  exitcode is set to SUCCESS.
+
+  If task formula contains multiple usages of exitcode directive, worst exitcode is returned by
+  runtask.
+
+  Input for directive is supposed to be in a `TAP13 format`_. The easiest way to create it is to
+  use :class:`.CheckDetail` objects to construct your result (or results), and then generate
+  the TAP output with :func:`~.check.export_TAP`. Read more in :ref:`writing-tasks-for-taskotron`.
+
+  .. _TAP13 format: http://testanything.org/tap-version-13-specification.html
+parameters:
+  tap_last:
+    required: true
+    description: TAP output, last outcome is used. ``tap_worst`` cannot be specified together with
+      this one.
+    type: str
+  tap_worst:
+    required: true
+    description: TAP output, worst outcome is used. ``tap_last`` cannot be specified together with
+      this one.
+    type: str
+returns: |
+  :int: Returncode based on TAP last or worst outcome. Success is ``0``, failure is ``100``.
+raises: |
+  * :class:`.TaskotronDirectiveError`: when there's not exactly one of parameters ``tap_last`` or
+    ``tap_last`` present
+  * :class:`.TaskotronValueError`: when TAP input cannot be parsed
+version_added: 0.3.18
+"""
+
+EXAMPLES = """
+Run a check returning multiple results and make ``runtask`` fail if any of the results is failed::
+
+  - name: run my check and return TAP
+    python:
+        file: my_check.py
+        callable: run
+    export: tap
+
+  - name: set runtask exit code according to the worst result in TAP
+    exitcode:
+        tap_worst: ${tap}
+
+Run a check that returns multiple results and one "overall" result (at the end) which is computed
+according check's internal logic. Then make ``runtask`` fail if the overall result failed::
+
+  - name: run my check and return TAP
+    python:
+        file: my_check.py
+        callable: run
+    export: tap
+
+  - name: set runtask exit code according to the last (overall) result in TAP
+    exitcode:
+        tap_last: ${tap}
+"""
+
+# exitcode for PASSED and INFO outcome
+SUCCESS = 0
+
+# exitcode for other outcomes
+FAILURE = 100
+
+directive_class = 'ExitcodeDirective'
+
+
+class ExitcodeDirective(BaseDirective):
+    def process(self, input_data, env_data):
+        """Process this directive.
+        :param dict input_data: dictionary of all kwargs from yaml declaration
+        :param dict env_data: information on the environment in which we're running
+        :returns: returncode based on TAP last or worst outcome
+        :raise TaskotronDirectiveError: ``input data`` doesn't contain exactly one of keys
+                                        ``tap_last`` or ``tap_last``
+        :raise TaskotronValueError: when TAP input cannot be parsed
+        """
+
+        # keys 'tap_worst' and 'tap_last' must be mutually exclusive
+        if ('tap_worst' in input_data) == ('tap_last' in input_data):
+            raise TaskotronDirectiveError("The exitcode directive requires exactly one of keys "
+                                          "'tap_worst' or 'tap_last'.")
+
+        if 'tap_worst' in input_data:
+            details = check.import_TAP(input_data['tap_worst'])
+            code = SUCCESS
+            for detail in details:
+                if detail.outcome not in ['PASSED', 'INFO']:
+                    code = FAILURE
+
+            log.debug("Returning exitcode %d" % code)
+            return code
+
+        elif 'tap_last' in input_data:
+            details = check.import_TAP(input_data['tap_last'])
+            if details and details[-1].outcome not in ['PASSED', 'INFO']:
+
+                log.debug("Returning exitcode %d" % FAILURE)
+                return FAILURE
+            else:
+                log.debug("Returning exitcode %d" % SUCCESS)
+                return SUCCESS
+
+        else:
+            assert False, "This should never occur"
diff --git a/libtaskotron/runner.py b/libtaskotron/runner.py
--- a/libtaskotron/runner.py
+++ b/libtaskotron/runner.py
@@ -12,6 +12,7 @@
 import copy
 import collections
 import datetime
+import sys
 
 import libtaskotron
 from libtaskotron import taskformula
@@ -21,6 +22,7 @@
 from libtaskotron import config
 from libtaskotron.logger import log
 from libtaskotron.exceptions import TaskotronYamlError, TaskotronError
+from libtaskotron.directives import exitcode_directive
 
 
 # The list of accepted item types on the command line (--type option)
@@ -34,6 +36,8 @@
         self.working_data = {}
         self.directives = {}
         self.workdir = workdir
+        #: int exitcode set by exitcode directive, is None if exitcode directive was not used
+        self.exitcode = None
 
     def run(self):
         self._validate_input()
@@ -127,6 +131,13 @@
             log.debug("Variable ${%s} was exported with value:\n%s" %
                       (action['export'], output))
 
+        # unable to use isinstance() due to dynamically loaded directives
+        if directive_classname == exitcode_directive.directive_class:
+            # set exitcode if was None or overwrite previous SUCCESS with FAILURE (not vice versa)
+            if not self.exitcode or output != exitcode_directive.SUCCESS:
+                log.info("Setting exitcode to %s" % output)
+                self.exitcode = output
+
     def do_actions(self):
         '''Sequentially run all actions for a task. An 'action' is a single step
         under the ``actions:`` key. An example action looks like::
@@ -263,3 +274,8 @@
     # finalization
     log.info('Execution finished at: %s',
              datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC'))
+
+    if task_runner.exitcode:
+        log.info("Exiting with exit status %d (this behavior was requested by exitcode directive)"
+                 % task_runner.exitcode)
+        sys.exit(task_runner.exitcode)
diff --git a/testing/test_exitcode_directive.py b/testing/test_exitcode_directive.py
new file mode 100644
--- /dev/null
+++ b/testing/test_exitcode_directive.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+# Copyright 2009-2014, Red Hat, Inc.
+# License: GPL-2.0+ <http://spdx.org/licenses/GPL-2.0+>
+# See the LICENSE file for more details on Licensing
+
+from libtaskotron.directives import exitcode_directive
+from libtaskotron.exceptions import TaskotronDirectiveError, TaskotronValueError
+import pytest
+
+
+@pytest.mark.usefixtures("setup")
+class TestReturncode(object):
+
+    @pytest.fixture
+    def setup(self):
+        self.test_env_data = {}
+        self.test_input_data = {}
+        self.test_tap = """
+TAP version 13
+1..4
+ok - $CHECKNAME for Hello World P
+  ---
+  item: Hello World P
+  outcome: PASSED
+  ...
+ok - $CHECKNAME for Hello World I
+  ---
+  item: Hello World I
+  outcome: INFO
+  ...
+not ok - $CHECKNAME for Hello World F	# FAIL
+  ---
+  item: Hello World F
+  outcome: FAILED
+  ...
+ok - $CHECKNAME for Hello World P
+  ---
+  item: Hello World P
+  outcome: PASSED
+  ...
+"""
+
+    def test_tap_last(self):
+        self.test_input_data['tap_last'] = self.test_tap
+        exitcode = exitcode_directive.ExitcodeDirective().process(self.test_input_data,
+                                                                  self.test_env_data)
+        assert exitcode == exitcode_directive.SUCCESS
+
+    def test_tap_worst(self):
+        self.test_input_data['tap_worst'] = self.test_tap
+        exitcode = exitcode_directive.ExitcodeDirective().process(self.test_input_data,
+                                                                  self.test_env_data)
+        assert exitcode == exitcode_directive.FAILURE
+
+    def test_bad_input(self):
+        with pytest.raises(TaskotronDirectiveError):
+            exitcode_directive.ExitcodeDirective().process(self.test_input_data,
+                                                           self.test_env_data)
+
+    def test_bad_tap(self):
+        self.test_tap = "noworky"
+        self.test_input_data['tap_worst'] = self.test_tap
+        with pytest.raises(TaskotronValueError):
+            exitcode_directive.ExitcodeDirective().process(self.test_input_data,
+                                                           self.test_env_data)
+
+    def test_empty_tap_worst(self):
+        self.test_tap = """
+TAP version 13
+1..0
+"""
+        self.test_input_data['tap_worst'] = self.test_tap
+        exitcode = exitcode_directive.ExitcodeDirective().process(self.test_input_data,
+                                                                  self.test_env_data)
+        assert exitcode == exitcode_directive.SUCCESS
+
+    def test_empty_tap_last(self):
+        self.test_tap = """
+TAP version 13
+1..0
+"""
+        self.test_input_data['tap_last'] = self.test_tap
+        exitcode = exitcode_directive.ExitcodeDirective().process(self.test_input_data,
+                                                                  self.test_env_data)
+        assert exitcode == exitcode_directive.SUCCESS
diff --git a/testing/test_runner.py b/testing/test_runner.py
--- a/testing/test_runner.py
+++ b/testing/test_runner.py
@@ -10,6 +10,7 @@
 from dingus import Dingus
 
 from libtaskotron import runner
+from libtaskotron.directives import exitcode_directive
 from libtaskotron import exceptions as exc
 
 
@@ -155,6 +156,27 @@
         self.ref_taskdata = {}
         self.ref_inputdata = {}
 
+        self.ref_tap_passed = """
+TAP version 13
+1..1
+ok - foo for Hello World P
+  ---
+  item: Hello World P
+  outcome: PASSED
+  ...
+"""
+        self.ref_tap_failed = """
+TAP version 13
+1..1
+not ok - foo for Hello World P	# FAIL
+  ---
+  item: Hello World P
+  outcome: FAILED
+  ...
+
+"""
+
+
     def test_runner_extract_directive_name(self):
         ref_directivename = 'dummy'
         ref_action = {'name': 'test action',
@@ -216,6 +238,51 @@
 
         assert test_runner.working_data[ref_exportname] == ref_message
 
+    def test_runner_do_single_dummy_action_exitcode_None(self):
+        ref_action = {'name': 'Return exitcode', 'exitcode': {'tap_last': self.ref_tap_passed}}
+
+        test_runner = runner.Runner(self.ref_taskdata, self.ref_inputdata)
+
+        test_runner.do_single_action(ref_action)
+
+        assert test_runner.exitcode == exitcode_directive.SUCCESS
+
+    def test_runner_do_single_dummy_action_exitcode_success(self):
+        ref_action = {'name': 'Return exitcode', 'exitcode': {'tap_last': self.ref_tap_passed}}
+
+        test_runner = runner.Runner(self.ref_taskdata, self.ref_inputdata)
+
+        test_runner.do_single_action(ref_action)
+
+        assert test_runner.exitcode == exitcode_directive.SUCCESS
+
+    def test_runner_do_single_dummy_action_exitcode_failure(self):
+        ref_action = {'name': 'Return exitcode', 'exitcode': {'tap_last': self.ref_tap_failed}}
+
+        test_runner = runner.Runner(self.ref_taskdata, self.ref_inputdata)
+
+        test_runner.do_single_action(ref_action)
+
+        assert test_runner.exitcode == exitcode_directive.FAILURE
+
+    def test_runner_do_single_dummy_action_exitcode_failure_overwrite_success(self):
+        ref_action = {'name': 'Return exitcode', 'exitcode': {'tap_last': self.ref_tap_failed}}
+
+        test_runner = runner.Runner(self.ref_taskdata, self.ref_inputdata)
+        test_runner.exitcode = exitcode_directive.SUCCESS
+        test_runner.do_single_action(ref_action)
+
+        assert test_runner.exitcode == exitcode_directive.FAILURE
+
+    def test_runner_do_single_dummy_action_exitcode_success_not_overwrite_failure(self):
+        ref_action = {'name': 'Return exitcode', 'exitcode': {'tap_last': self.ref_tap_passed}}
+
+        test_runner = runner.Runner(self.ref_taskdata, self.ref_inputdata)
+        test_runner.exitcode = exitcode_directive.FAILURE
+        test_runner.do_single_action(ref_action)
+
+        assert test_runner.exitcode == exitcode_directive.FAILURE
+
 
 class TestRunnerDoActions():
 

