diff --git a/.gitignore b/.gitignore
index 31ee437c59f4e9c2af827cf41719ad1e1d6f33d9..d1a8368eb6b8fd4fcaea67c6cc2e6d213d6df898 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
 *.py[cod]
 .DS_Store
 __pycache__/
+__pypackages__/
 .vagrant/
 vendor/
 Thumbs.db
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f92da7b142f506a53baa2e4028ac3e501c5919d9
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,4 @@
+---
+include:
+  - project: shore/ci-templates
+    file: templates/pre-commit.yml
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4c644211c85213268ba9d6e5ab58c4a9fae7fa97
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,108 @@
+---
+repos:
+  - repo: https://github.com/pre-commit/pre-commit-hooks.git
+    rev: v4.0.1
+    hooks:
+      - id: check-added-large-files
+      - id: check-json
+      - id: check-merge-conflict
+      - id: check-shebang-scripts-are-executable
+      - id: check-symlinks
+      - id: check-toml
+      - id: check-xml
+      - id: check-yaml
+      - id: detect-private-key
+      - id: end-of-file-fixer
+      - id: trailing-whitespace
+        exclude: \.diff$
+
+  - repo: https://github.com/codespell-project/codespell.git
+    rev: v2.1.0
+    hooks:
+      - id: codespell
+
+  - repo: https://github.com/Yelp/detect-secrets.git
+    rev: v1.1.0
+    hooks:
+      - id: detect-secrets
+
+  - repo: https://gitlab.com/devopshq/gitlab-ci-linter.git
+    rev: v1.0.4
+    hooks:
+      - id: gitlab-ci-linter
+        args:
+          - "--server"
+          - https://git.shore.co.il
+
+  - repo: https://github.com/amperser/proselint.git
+    rev: 0.10.2
+    hooks:
+      - id: proselint
+        types: [plain-text]
+        exclude: LICENSE
+
+  - repo: https://github.com/adrienverge/yamllint.git
+    rev: v1.26.3
+    hooks:
+      - id: yamllint
+
+  - repo: https://github.com/ambv/black.git
+    rev: 21.9b0
+    hooks:
+      - id: black
+        args:
+          - |
+              --line-length=79
+
+  - repo: https://github.com/Lucas-C/pre-commit-hooks-markup.git
+    rev: v1.0.1
+    hooks:
+      - id: rst-linter
+
+  - repo: https://github.com/myint/rstcheck.git
+    rev: master
+    hooks:
+      - id: rstcheck
+
+  - repo: https://github.com/PyCQA/prospector.git
+    rev: 1.5.1
+    hooks:
+      - id: prospector
+        args:
+          - |-
+            --max-line-length=79
+          - |-
+            --with-tool=pyroma
+          - |-
+            --with-tool=bandit
+          - |-
+            --without-tool=pep257
+          - |-
+            --doc-warnings
+          - |-
+            --test-warnings
+          - |-
+            --full-pep8
+          - |-
+            --strictness=high
+          - |-
+            --no-autodetect
+        additional_dependencies:
+          - bandit
+          - pyroma
+
+  - repo: https://gitlab.com/pycqa/flake8.git
+    rev: 3.9.2
+    hooks:
+      - id: flake8
+        args:
+          - |-
+            --doctests
+        additional_dependencies:
+          - flake8-bugbear
+
+  - repo: https://github.com/asottile/pyupgrade
+    rev: v2.23.2
+    hooks:
+      - id: pyupgrade
+        args: [--py36-plus]
diff --git a/README.rst b/README.rst
index f24b3d7ffb1d35fc4092b545b45ad185872d42ce..8bc54a7f4aef86c4227a90fc507b02ff5c009953 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,12 @@
 Transmission feeder
 ###################
 
+.. image:: https://git.shore.co.il/nimrod/transmission-feeder/badges/master/pipeline.svg
+    :target: https://git.shore.co.il/nimrod/transmission-feeder/-/commits/master
+    :alt: pipeline status
+
+Add torrent to Transmission from RSS or Atom feeds.
+
 License
 -------
 
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000000000000000000000000000000000000..ed38c4a7f68885a41f207784b1b80bd889ab32cb
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,36 @@
+[build-system]
+requires = ["setuptools", "wheel"]
+build-backend = "setuptools:build_meta"
+
+[project]
+name = "transmission_feeder"
+authors = [{name = "Nimrod Adar", email = "nimrod@shore.co.il"}]
+readme = "README.rst"
+dynamic = ["version", "description"]
+license = {"file" = "LICENSE.txt"}
+requires-python = ">=3.6"
+keywords = ["torrent", "rss", "atom", "transmission"]
+dependencies = [
+    "feedparser>=6.0.0",
+    "transmission-rpc>=3.2.0",
+    "ruamel.yaml>=0.17.0",
+]
+classifiers = [
+    "Development Status :: 3 - Alpha",
+    "Environment :: Console",
+    "Intended Audience :: End Users/Desktop",
+    "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
+    "Programming Language :: Python :: 3.6",
+    "Programming Language :: Python :: 3.7",
+    "Programming Language :: Python :: 3.8",
+    "Programming Language :: Python :: 3.9",
+    "Topic :: Communications :: File Sharing",
+    "Topic :: Internet",
+    "Topic :: Utilities",
+]
+
+[project.urls]
+Home = "https://git.shore.co.il/nimrod/transmission-feeder"
+
+[project.scripts]
+transmission-feeder = "transmission_feeder:main"
diff --git a/transmission_feeder/__init__.py b/transmission_feeder/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..6f8856dd8728baa04c90dcf80ba00041dbe06ac2
--- /dev/null
+++ b/transmission_feeder/__init__.py
@@ -0,0 +1,12 @@
+"Add torrent to Transmission from RSS or Atom feeds."
+import sys
+
+__version__ = "0.0.1"
+
+
+def main():
+    """Main entrypoint."""
+
+
+if __name__ == "__main__":
+    sys.exit(main())