diff --git a/Makefile b/Makefile
index 7ee58e582b68323035707fa6c46fd61118ce71d2..e3c7d9694c41101ecc397e2d9b06d701954a931c 100644
--- a/Makefile
+++ b/Makefile
@@ -6,10 +6,10 @@ help: # Print help on Makefile
 	expand -t20
 
 open_all: # Open all projects files
-	${EDITOR} ${VIRTUAL_ENV}/bin/activate
+	test -n ${VIRTUAL_ENV} && ${EDITOR} ${VIRTUAL_ENV}/bin/activate
 	${EDITOR} .gitignore .gitlab-ci.yml Makefile README.md requirements.txt requirements-dev.txt setup.cfg
 	${EDITOR} .git/hooks/p*-commit
-	${EDITOR} cli/run.py
+	${EDITOR} cli/*.py
 
 pre_commit: # Run the pre-commit hook
 	.git/hooks/pre-commit
diff --git a/README.md b/README.md
index bd2d6dc4f9574f0dda5ebc57e240f479091a85af..0fc4b47c8771ebb2253187000956574a9748625b 100644
--- a/README.md
+++ b/README.md
@@ -12,19 +12,19 @@ A python CLI to share data related to physical activities over an API (geo-local
 1. Respect python scripting guidelines proposed by _Vincent Bernat_ ( [🇫🇷](https://vincent.bernat.ch/fr/blog/2019-script-python-durable) | [🇬🇧](https://vincent.bernat.ch/en/blog/2019-sustainable-python-script) ).
 
 
-✨ (planed) Features
---------------------
+✨ Features
+------------
 
 These are imagined with _[Strava](https://developers.strava.com/docs/reference/) in mind_, but any other service will be nice too :
 
-* [Create manual activity](https://lab.frogg.it/fcode/geostrapy/-/issues/1)
-* From a GPX track: [get characteristics](https://lab.frogg.it/fcode/geostrapy/-/issues/2)
-    * and [create an activity](https://lab.frogg.it/fcode/geostrapy/-/issues/3)
-* Sanitise a GPX track:
-    * [crop start, end & stop points](https://lab.frogg.it/fcode/geostrapy/-/issues/4)
-    * [change start-time](https://lab.frogg.it/fcode/geostrapy/-/issues/5)
-* [Post GPX file as activity](https://lab.frogg.it/fcode/geostrapy/-/issues/6)
-* [Process GPX multi-track file](https://lab.frogg.it/fcode/geostrapy/-/issues/7)
+* [x] [Create activity](https://lab.frogg.it/fcode/geostrapy/-/issues/1)
+* [ ] From a GPX track: [get characteristics](https://lab.frogg.it/fcode/geostrapy/-/issues/2)
+    * [ ] and [create an activity](https://lab.frogg.it/fcode/geostrapy/-/issues/3)
+* Sanitize a GPX track:
+    * [ ] [crop start, end & stop points](https://lab.frogg.it/fcode/geostrapy/-/issues/4)
+    * [ ] [change start-time](https://lab.frogg.it/fcode/geostrapy/-/issues/5)
+* [ ] [Post modified GPX file as activity](https://lab.frogg.it/fcode/geostrapy/-/issues/6)
+* [ ] [Process GPX multi-track file](https://lab.frogg.it/fcode/geostrapy/-/issues/7)
 * and [maybe more](https://lab.frogg.it/fcode/geostrapy/-/boards)…
 
 
diff --git a/cli/api.py b/cli/api.py
new file mode 100644
index 0000000000000000000000000000000000000000..036123e34fc85e018d453cbf798d92fc5e97d582
--- /dev/null
+++ b/cli/api.py
@@ -0,0 +1,18 @@
+"""
+API utilities
+"""
+
+from strava.api._helpers import client, url, json
+
+
+def post_activity(xargs):
+    """API call to create an activity"""
+
+    response = client.post(url=url("/activities"), data=xargs)
+
+    if response.ok:
+        result = json(response)
+    else:
+        result = response.json()
+
+    return result
diff --git a/cli/commands.py b/cli/commands.py
new file mode 100644
index 0000000000000000000000000000000000000000..b4451e9266fb5838e236875648dfb8e8fdafbc0f
--- /dev/null
+++ b/cli/commands.py
@@ -0,0 +1,131 @@
+"""
+CLI commands
+"""
+
+import datetime
+
+import click
+from strava.decorators import (
+    output_option,
+    login_required,
+    format_result,
+    TableFormat,
+    OutputType,
+)
+from strava.formatters import (
+    humanize,
+    apply_formatters,
+)
+
+from api import post_activity
+
+_ACTIVITY_COLUMNS = ("key", "value")
+
+
+@click.option(
+    "-n",
+    "--name",
+    prompt=True,
+    type=str,
+    required=True,
+    default="Activity",
+    help="The name of the activity",
+)
+@click.option(
+    "-a",
+    "--activity_type",
+    prompt=True,
+    type=str,
+    required=True,
+    default="run",
+    help="Type of activity",
+)
+@click.option(
+    "-s",
+    "--start",
+    prompt=True,
+    type=str,
+    required=True,
+    default=datetime.datetime.now().isoformat(),
+    help="ISO 8601 formatted date time",
+)
+@click.option("-t", "--time", prompt=True, type=int, required=True, help="In seconds")
+@click.option("-d", "--desc", prompt=True, type=str, help="Description of the activity")
+@click.option("-D", "--dist", prompt=True, type=int, help="In meters")
+@click.option(
+    "-c",
+    "--commute",
+    prompt=True,
+    type=int,
+    default="0",
+    prompt_required=False,
+    help="Set to 1 to mark as commute",
+)
+@click.option(
+    "-T",
+    "--trainer",
+    prompt=True,
+    type=int,
+    default="0",
+    prompt_required=False,
+    help="Set to 1 to mark as a trainer activity",
+)
+@click.option(
+    "-h",
+    "--hide",
+    prompt=True,
+    type=int,
+    default="0",
+    prompt_required=False,
+    help="Set to true to mute activity",
+)
+@click.command("create")
+@output_option()
+@login_required
+def post_create(**kwargs):
+    """Create an activity"""
+    xargs = {
+        "name": kwargs["name"],
+        "type": kwargs["activity_type"],
+        "trainer": kwargs["trainer"],
+        "commute": kwargs["commute"],
+        "distance": kwargs["dist"],
+        "description": kwargs["desc"],
+        "elapsed_time": kwargs["time"],
+        "hide_from_home": kwargs["hide"],
+        "start_date_local": kwargs["start"],
+    }
+    result = post_activity(xargs)
+    _format_upload(result, output=kwargs["output"])
+
+
+@format_result(
+    table_columns=_ACTIVITY_COLUMNS,
+    show_table_headers=False,
+    table_format=TableFormat.PLAIN,
+)
+def _format_upload(result, output=None):
+    return result if output == OutputType.JSON.value else _as_table(result)
+
+
+def _as_table(upload_result):
+    def format_id(upload_id):
+        return f"{upload_id}"
+
+    def format_error(upload_error):
+        return f"{upload_error}"
+
+    def format_property(name):
+        return click.style(f"{humanize(name)}:", bold=True)
+
+    formatters = {
+        "id": format_id,
+        "errors": format_error,
+    }
+
+    basic_data = [
+        {"key": format_property(k), "value": v}
+        for k, v in apply_formatters(upload_result, formatters).items()
+    ]
+
+    return [*basic_data]
diff --git a/cli/run.py b/cli/main.py
similarity index 89%
rename from cli/run.py
rename to cli/main.py
index 60778ff3500aa5c7aae40fca36c6419d52339c8b..9a98d1d0d888109d15459c90e3e626dd25388964 100644
--- a/cli/run.py
+++ b/cli/main.py
@@ -15,6 +15,8 @@ from strava.commands import (
     set_config,
 )
 
+from commands import post_create
+
 
 @click.group()
 def cli():
@@ -26,6 +28,7 @@ def cli():
 
 cli.add_command(login)
 cli.add_command(logout)
+cli.add_command(post_create)
 cli.add_command(set_config)
 
 if __name__ == "__main__":