diff --git a/.gitignore b/.gitignore
index 70309cf2bcbaab22bda94e658b8cb46d6082d83c..10c407378bac4de0815304ebfcedfd7afff87b15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 *.json
 *.zip
 *.swp
-__pychache__/
+__pycache__/
 
+*.egg-info/
diff --git a/bin/hektor b/bin/hektor
new file mode 100644
index 0000000000000000000000000000000000000000..8d684457d9556570dfd867fcf8f1421fd0f31707
--- /dev/null
+++ b/bin/hektor
@@ -0,0 +1,9 @@
+#!/usr/bin/env python3
+
+import hektor
+import sys
+
+if __name__ == '__main__':
+    if sys.version_info < (3, 4):
+        sys.exit("At least Python 3.4 is required.")
+    hektor.main()
diff --git a/hektor.py b/hektor.py
index 63d8a295da3e32bf595bb1864c44d6bd79062f3e..209b1f2ce6fc3bf47a1cf469c687c96064fdc5b1 100644
--- a/hektor.py
+++ b/hektor.py
@@ -16,7 +16,8 @@ tasks_path = ('./assessment/section')
 users = './tst_active/row'
 solutions = './tst_solutions/row[@question_fi="%s"]'
 
-lecturer_xpath = './MetaData/Lifecycle/Contribute[@Role="Author"]/Entity/text()'
+lecturer_xpath = ('./MetaData/Lifecycle/Contribute'
+                  '[@Role="Author"]/Entity/text()')
 
 
 def eat_qti(tree, only_of_type=('assSourceCode',), **kwargs):
@@ -132,8 +133,8 @@ def eat_zipfile(input_file, output):
 
     structured_data = give_me_structure(data)
 
-    with open(output, 'w', encoding='utf-8') as out:
-        json.dump(structured_data, out, indent=2)
+    with open(output, 'w') as out:
+        json.dump(structured_data, out, indent=2, sort_keys=True)
 
 
 def parseme():
@@ -151,6 +152,10 @@ def parseme():
     return parser.parse_args()
 
 
-if __name__ == '__main__':
+def main():
     args = parseme()
     eat_zipfile(args.input, args.output)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..60009f2d208f134bea2481720bcb5210fd954b1d
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from setuptools import setup
+
+setup(
+    name='hektor',
+    version='0.1',
+    description='A QTI-XML to JSON converter for humans',
+    author='Jan Maximilian Michal',
+    author_email='mail@janmax.org',
+    url='https://gitlab.gwdg.de/j.michal/hektor',
+    license='MIT',
+    scripts=['bin/hektor'],
+    install_requires=['lxml'],
+    py_modules=['hektor']
+)