diff --git a/apps/cli/executables/vulture/README.md b/apps/cli/executables/vulture/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..02bcb3f1e55198abba2af6b08b95b09fe5399d20
--- /dev/null
+++ b/apps/cli/executables/vulture/README.md
@@ -0,0 +1,5 @@
+# Vulture
+
+Vulture is a fake HTCondor. It doesn't submit jobs to a cluster, instead it runs them locally. 
+
+This tool is intended to bypass HTCondor for integration testing purposes.
diff --git a/apps/cli/executables/vulture/setup.py b/apps/cli/executables/vulture/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e28444c9064a0fa53c1cebab10fbe20715b8aba
--- /dev/null
+++ b/apps/cli/executables/vulture/setup.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from pathlib import Path
+from setuptools import setup
+
+VERSION = open('src/vulture/_version.py').readlines()[-1].split()[-1].strip("\"'")
+README = Path('README.md').read_text()
+
+tests_require = [
+    'pytest>=5.4,<6.0'
+]
+setup(
+    name='ssa-' + Path().absolute().name,
+    version=VERSION,
+    description='HTCondor fake executor.',
+    long_description=README,
+    author='NRAO SSA Team',
+    author_email='dms-ssa@nrao.edu',
+    url='TBD',
+    license="GPL",
+    # install_requires=requires,
+    tests_require=tests_require,
+    keywords=[],
+    packages=['vulture'],
+    package_dir={'':'src'},
+    classifiers=[
+        'Programming Language :: Python :: 3.8'
+    ],
+    entry_points={
+        'console_scripts': ['vulture = vulture.execute:main']
+    },
+)
diff --git a/apps/cli/executables/vulture/src/vulture/__init__.py b/apps/cli/executables/vulture/src/vulture/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/apps/cli/executables/vulture/src/vulture/_version.py b/apps/cli/executables/vulture/src/vulture/_version.py
new file mode 100644
index 0000000000000000000000000000000000000000..f27d146a3f39885ce269bacf9ab4510254147c8d
--- /dev/null
+++ b/apps/cli/executables/vulture/src/vulture/_version.py
@@ -0,0 +1,2 @@
+""" Version information for this package, don't put anything else here. """
+___version___ = '4.0.0a1.dev1'
diff --git a/apps/cli/executables/vulture/src/vulture/condorlite.py b/apps/cli/executables/vulture/src/vulture/condorlite.py
new file mode 100644
index 0000000000000000000000000000000000000000..31ba0a553b77d0e23789385da4914d1aac20d5dc
--- /dev/null
+++ b/apps/cli/executables/vulture/src/vulture/condorlite.py
@@ -0,0 +1,22 @@
+class Job:
+    @staticmethod
+    def parse(file):
+        job = Job()
+        # do something here to iterate the file contents and parse it
+        raise NotImplementedError
+
+    def execute(self):
+        raise NotImplementedError
+
+
+class Dag:
+    @staticmethod
+    def parse(file):
+        dag = Dag()
+        # do something here to iterate the file contents and parse it
+        raise NotImplementedError
+
+
+    def execute(self):
+        raise NotImplementedError
+
diff --git a/apps/cli/executables/vulture/src/vulture/execute.py b/apps/cli/executables/vulture/src/vulture/execute.py
new file mode 100644
index 0000000000000000000000000000000000000000..18eb05711d7c9b5042897d90171c594bb3bdbab6
--- /dev/null
+++ b/apps/cli/executables/vulture/src/vulture/execute.py
@@ -0,0 +1,49 @@
+"""
+CLI to our fake dagman executor and fake job executor
+"""
+
+import argparse as ap
+from pathlib import Path
+
+
+def execute_dag(file: Path):
+    """
+    Execute the DAG in the given file.
+    :param file:
+    :return:
+    """
+    dag = Dag.parse(file)
+    dag.execute()
+
+
+def execute_job(file: Path):
+    """
+    Execute the job in the given file.
+    :param file:
+    :return:
+    """
+    job = Job.parse(file)
+    job.execute()
+
+
+def main():
+    parser = ap.ArgumentParser('vulture', description='Tool to run HTCondor job specs and DAG workflows locally')
+    subparsers = parser.add_subparsers()
+    dag = subparsers.add_parser('dag', help='DAG operations')
+    sub2 = dag.add_subparsers()
+    execute = sub2.add_parser('execute', description='Execute an HTCondor DAGMAN DAG')
+    execute.set_defaults(func=execute_dag)
+    execute.add_argument('file', nargs=1, type=Path, help='DAGMAN file to execute')
+
+    job = subparsers.add_parser('job', help='Job operations')
+    sub2 = job.add_subparsers()
+    execute = sub2.add_parser('execute', description='Execute an HTCondor job specification')
+    execute.set_defaults(func=execute_job)
+    execute.add_argument('file', nargs=1, type=Path, help='Job file to execute')
+
+    args = parser.parse_args()
+
+    if 'func' in args and 'file' in args:
+        args.func(args.file)
+    else:
+        parser.print_usage()