diff --git a/README.md b/README.md
index 7ac61627a03f34e68bef066ed085d38362667dc8..e097ee59cbcf82099cad7940d4e6a908e660291b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,38 @@
 # exec
 A [maubot](https://github.com/maubot/maubot) that executes code.
+
+# This does not work yet
+
+## Usage
+The bot is triggered by a specific message prefix (defaults to `!exec`) and
+executes the code in the first code block.
+
+<pre>
+!exec
+```python
+print("Hello, World!")
+```
+</pre>
+
+Standard input can be added with another code block that has `stdin` as the
+language:
+
+<pre>
+!exec
+```python
+print(f"Hello, {input()}")
+```
+
+```stdin
+maubot
+```
+</pre>
+
+When the bot executes the code, it'll reply immediately and then update the
+output using edits until the command finishes. After it finishes, the reply
+will be edited to contain the return values.
+
+If running in userbot mode, the bot will edit your original message instead of
+making a new reply message.
+
+Currently, the bot supports `python` and `shell` as languages.
diff --git a/base-config.yaml b/base-config.yaml
index b62ac94c68181fc6e4ecdf7261291320d2d109c6..a91e6184cf4c86cf48cb072a1ff7093c930e8f89 100644
--- a/base-config.yaml
+++ b/base-config.yaml
@@ -8,3 +8,5 @@ userbot: false
 # sandboxing in maubot or this plugin, keep this list small.
 whitelist:
 - '@user:example.com'
+# Number of seconds to wait between output update edits.
+output_interval: 5
diff --git a/exec/bot.py b/exec/bot.py
index 68d0530235302241b774dc90e76004e814cf5ce9..eb10c64c20be986a05cc61a60dc09e1eeb4e9b41 100644
--- a/exec/bot.py
+++ b/exec/bot.py
@@ -35,12 +35,14 @@ class Config(BaseProxyConfig):
         helper.copy("prefix")
         helper.copy("userbot")
         helper.copy("whitelist")
+        helper.copy("output_interval")
 
 
 class ExecBot(Plugin):
     whitelist: Set[UserID]
     userbot: bool
     prefix: str
+    output_interval: int
 
     @classmethod
     def get_config_class(cls) -> Type[BaseProxyConfig]:
@@ -54,6 +56,7 @@ class ExecBot(Plugin):
         self.whitelist = set(self.config["whitelist"])
         self.userbot = self.config["userbot"]
         self.prefix = self.config["prefix"]
+        self.output_interval = self.config["output_interval"]
 
     @event.on(EventType.ROOM_MESSAGE)
     async def exec(self, evt: MessageEvent) -> None:
@@ -72,12 +75,12 @@ class ExecBot(Plugin):
         for entity in command.entities:
             if entity.type != EntityType.PREFORMATTED:
                 continue
-            current_lang = entity.extra_info["language"]
+            current_lang = entity.extra_info["language"].lower()
             value = command.text[entity.offset:entity.offset+entity.length]
             if not code:
                 code = value
                 lang = current_lang
-            elif lang == "stdin":
+            elif lang == "stdin" or lang == "input":
                 stdin += value
         if not code or not lang:
             return