diff --git a/setup.py b/setup.py
index 44589992a232e573bcab31a1cb21b1010a873fdd..524eaa73a2561ae48383f9ce7945bcc748635121 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,7 @@
 import setuptools
 
+from sticker.get_version import git_tag, git_revision, version, linkified_version
+
 with open("requirements.txt") as reqs:
     install_requires = reqs.read().splitlines()
 
@@ -8,9 +10,18 @@ try:
 except IOError:
     long_desc = "Failed to read README.md"
 
+with open("sticker/version.py", "w") as version_file:
+    version_file.write(f"""# Generated in setup.py
+
+git_tag = {git_tag!r}
+git_revision = {git_revision!r}
+version = {version!r}
+linkified_version = {linkified_version!r}
+""")
+
 setuptools.setup(
     name="maunium-stickerpicker",
-    version="0.1.0",
+    version=version,
     url="https://github.com/maunium/stickerpicker",
 
     author="Tulir Asokan",
diff --git a/sticker/__init__.py b/sticker/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..86e4dc22dfc4fbd574c536c01026bf99ecb189fc 100644
--- a/sticker/__init__.py
+++ b/sticker/__init__.py
@@ -0,0 +1,2 @@
+__version__ = "0.1.0+dev"
+__author__ = "Tulir Asokan <tulir@maunium.net>"
diff --git a/sticker/get_version.py b/sticker/get_version.py
new file mode 100644
index 0000000000000000000000000000000000000000..3149eb04fad430d05943113099988dbf1157bd41
--- /dev/null
+++ b/sticker/get_version.py
@@ -0,0 +1,50 @@
+import subprocess
+import shutil
+import os
+
+from . import __version__
+
+cmd_env = {
+    "PATH": os.environ["PATH"],
+    "HOME": os.environ["HOME"],
+    "LANG": "C",
+    "LC_ALL": "C",
+}
+
+
+def run(cmd):
+    return subprocess.check_output(cmd, stderr=subprocess.DEVNULL, env=cmd_env)
+
+
+if (os.path.exists("../.git") or os.path.exists(".git")) and shutil.which("git"):
+    try:
+        git_revision = run(["git", "rev-parse", "HEAD"]).strip().decode("ascii")
+        git_revision_url = f"https://github.com/maunium/stickerpicker/commit/{git_revision}"
+        git_revision = git_revision[:8]
+    except (subprocess.SubprocessError, OSError):
+        git_revision = "unknown"
+        git_revision_url = None
+
+    try:
+        git_tag = run(["git", "describe", "--exact-match", "--tags"]).strip().decode("ascii")
+    except (subprocess.SubprocessError, OSError):
+        git_tag = None
+else:
+    git_revision = "unknown"
+    git_revision_url = None
+    git_tag = None
+
+git_tag_url = (f"https://github.com/maunium/stickerpicker/releases/tag/{git_tag}"
+               if git_tag else None)
+
+if git_tag and __version__ == git_tag[1:].replace("-", ""):
+    version = __version__
+    linkified_version = f"[{version}]({git_tag_url})"
+else:
+    if not __version__.endswith("+dev"):
+        __version__ += "+dev"
+    version = f"{__version__}.{git_revision}"
+    if git_revision_url:
+        linkified_version = f"{__version__}.[{git_revision}]({git_revision_url})"
+    else:
+        linkified_version = version
diff --git a/sticker/version.py b/sticker/version.py
new file mode 100644
index 0000000000000000000000000000000000000000..47f7fff6eb0e5056575fe006927f785dca2fea60
--- /dev/null
+++ b/sticker/version.py
@@ -0,0 +1 @@
+from .get_version import git_tag, git_revision, version, linkified_version