diff --git a/notebooks/tests/render.ipynb b/notebooks/tests/render.ipynb
index 283f29a3532d72c08be07a84010ff58d90ba8176..308e8d3aef019469c9164264289a3216951c56da 100644
--- a/notebooks/tests/render.ipynb
+++ b/notebooks/tests/render.ipynb
@@ -203,10 +203,10 @@
    "outputs": [
     {
      "ename": "CommandExecutionException",
-     "evalue": "::render: Missing content (the content cannot be placed on the same line as the command)",
+     "evalue": "::render: Missing required body content",
      "output_type": "error",
      "traceback": [
-      "\u001b[1m\u001b[31m::render: Missing content (the content cannot be placed on the same line as the command)\u001b[0m"
+      "\u001b[1m\u001b[31m::render: Missing required body content\u001b[0m"
      ]
     }
    ],
@@ -228,10 +228,10 @@
    "outputs": [
     {
      "ename": "CommandExecutionException",
-     "evalue": "::render: Missing MIME type",
+     "evalue": "::render: Missing required parameter mimeType",
      "output_type": "error",
      "traceback": [
-      "\u001b[1m\u001b[31m::render: Missing MIME type\u001b[0m"
+      "\u001b[1m\u001b[31m::render: Missing required parameter mimeType\u001b[0m"
      ]
     }
    ],
diff --git a/src/main/java/de/prob2/jupyter/CommandUtils.java b/src/main/java/de/prob2/jupyter/CommandUtils.java
index 3c83d96eb6a868411d65c2ff03b0d2141f36c78c..f5694b7dd4f97f771e6fe199e6079e280de5c05e 100644
--- a/src/main/java/de/prob2/jupyter/CommandUtils.java
+++ b/src/main/java/de/prob2/jupyter/CommandUtils.java
@@ -120,7 +120,19 @@ public final class CommandUtils {
 	
 	public static @NotNull ParsedArguments parseArgs(final @NotNull Parameters parameters, final @NotNull String argString) {
 		final ParsedArguments parsed = new ParsedArguments(Collections.emptyMap());
-		String remainingArgs = argString;
+		String remainingArgs;
+		if (parameters.getBodyParam().isPresent()) {
+			final String[] split = argString.split("\n", 2);
+			final PositionalParameter.RequiredRemainder bodyParam = parameters.getBodyParam().get();
+			if (split.length < 2) {
+				throw new UserErrorException("Missing required body " + bodyParam.getIdentifier());
+			}
+			remainingArgs = split[0];
+			parsed.put(bodyParam, split[1]);
+		} else {
+			remainingArgs = argString;
+		}
+		
 		for (final PositionalParameter<?> param : parameters.getPositionalParameters()) {
 			if (remainingArgs.isEmpty()) {
 				break;
diff --git a/src/main/java/de/prob2/jupyter/Parameters.java b/src/main/java/de/prob2/jupyter/Parameters.java
index 0ef54274217db75f79a4a4970ddf06e02b439223..d004b3583388e36e27357505724bdb7c7455fa26 100644
--- a/src/main/java/de/prob2/jupyter/Parameters.java
+++ b/src/main/java/de/prob2/jupyter/Parameters.java
@@ -2,15 +2,18 @@ package de.prob2.jupyter;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public final class Parameters {
 	public static final @NotNull Parameters NONE = new Parameters(Collections.emptyList());
 	
 	private final @NotNull List<PositionalParameter<?>> positionalParameters;
+	private final @Nullable PositionalParameter.RequiredRemainder bodyParam;
 	
-	public Parameters(final @NotNull List<PositionalParameter<?>> positionalParameters) {
+	public Parameters(final @NotNull List<PositionalParameter<?>> positionalParameters, final @Nullable PositionalParameter.RequiredRemainder bodyParam) {
 		super();
 		
 		this.positionalParameters = positionalParameters;
@@ -29,9 +32,19 @@ public final class Parameters {
 			seenOptional |= isOptional;
 			seenOnlyLast |= isOnlyLast;
 		}
+		
+		this.bodyParam = bodyParam;
+	}
+	
+	public Parameters(final @NotNull List<PositionalParameter<?>> positionalParameters) {
+		this(positionalParameters, null);
 	}
 	
 	public @NotNull List<PositionalParameter<?>> getPositionalParameters() {
 		return this.positionalParameters;
 	}
+	
+	public @NotNull Optional<PositionalParameter.RequiredRemainder> getBodyParam() {
+		return Optional.ofNullable(this.bodyParam);
+	}
 }
diff --git a/src/main/java/de/prob2/jupyter/commands/LoadCellCommand.java b/src/main/java/de/prob2/jupyter/commands/LoadCellCommand.java
index 3f115cb5de179fae11f89ac8c5b2384a9a71a8fd..ac346823e1caa7dede37158de6ad746a0fcb878e 100644
--- a/src/main/java/de/prob2/jupyter/commands/LoadCellCommand.java
+++ b/src/main/java/de/prob2/jupyter/commands/LoadCellCommand.java
@@ -17,7 +17,6 @@ import de.prob2.jupyter.Parameters;
 import de.prob2.jupyter.ParsedArguments;
 import de.prob2.jupyter.PositionalParameter;
 import de.prob2.jupyter.ProBKernel;
-import de.prob2.jupyter.UserErrorException;
 
 import io.github.spencerpark.jupyter.kernel.ReplacementOptions;
 import io.github.spencerpark.jupyter.kernel.display.DisplayData;
@@ -26,7 +25,8 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public final class LoadCellCommand implements Command {
-	private static final @NotNull PositionalParameter.RequiredRemainder PREFS_AND_CODE_PARAM = new PositionalParameter.RequiredRemainder("prefsAndCode");
+	private static final @NotNull PositionalParameter.OptionalRemainder PREFS_PARAM = new PositionalParameter.OptionalRemainder("prefs");
+	private static final @NotNull PositionalParameter.RequiredRemainder CODE_PARAM = new PositionalParameter.RequiredRemainder("code");
 	
 	private final @NotNull ClassicalBFactory classicalBFactory;
 	private final @NotNull AnimationSelector animationSelector;
@@ -52,7 +52,7 @@ public final class LoadCellCommand implements Command {
 	
 	@Override
 	public @NotNull Parameters getParameters() {
-		return new Parameters(Collections.singletonList(PREFS_AND_CODE_PARAM));
+		return new Parameters(Collections.singletonList(PREFS_PARAM), CODE_PARAM);
 	}
 	
 	@Override
@@ -74,13 +74,8 @@ public final class LoadCellCommand implements Command {
 	
 	@Override
 	public @NotNull DisplayData run(final @NotNull ParsedArguments args) {
-		final String[] split = args.get(PREFS_AND_CODE_PARAM).split("\n", 2);
-		if (split.length != 2) {
-			throw new UserErrorException("Missing command body");
-		}
-		final String prefsString = split[0];
-		final String body = split[1];
-		final List<String> prefsSplit = CommandUtils.splitArgs(prefsString);
+		final String body = args.get(CODE_PARAM);
+		final List<String> prefsSplit = args.get(PREFS_PARAM).map(CommandUtils::splitArgs).orElse(Collections.emptyList());
 		final Map<String, String> preferences = CommandUtils.parsePreferences(prefsSplit);
 		
 		this.animationSelector.changeCurrentAnimation(new Trace(CommandUtils.withSourceCode(body, () ->
diff --git a/src/main/java/de/prob2/jupyter/commands/RenderCommand.java b/src/main/java/de/prob2/jupyter/commands/RenderCommand.java
index 4e3785592479efbe57ba51d6fcc805452ce26887..22e4d2bae5e29ca65e3e985bb4e8afad387d19c0 100644
--- a/src/main/java/de/prob2/jupyter/commands/RenderCommand.java
+++ b/src/main/java/de/prob2/jupyter/commands/RenderCommand.java
@@ -8,7 +8,6 @@ import de.prob2.jupyter.Command;
 import de.prob2.jupyter.Parameters;
 import de.prob2.jupyter.ParsedArguments;
 import de.prob2.jupyter.PositionalParameter;
-import de.prob2.jupyter.UserErrorException;
 
 import io.github.spencerpark.jupyter.kernel.ReplacementOptions;
 import io.github.spencerpark.jupyter.kernel.display.DisplayData;
@@ -17,7 +16,8 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public final class RenderCommand implements Command {
-	private static final @NotNull PositionalParameter.RequiredRemainder MIME_TYPE_AND_CONTENT_PARAM = new PositionalParameter.RequiredRemainder("mimeTypeAndContent");
+	private static final @NotNull PositionalParameter.RequiredSingle MIME_TYPE_PARAM = new PositionalParameter.RequiredSingle("mimeType");
+	private static final @NotNull PositionalParameter.RequiredRemainder CONTENT_PARAM = new PositionalParameter.RequiredRemainder("content");
 	
 	@Inject
 	private RenderCommand() {
@@ -31,7 +31,7 @@ public final class RenderCommand implements Command {
 	
 	@Override
 	public @NotNull Parameters getParameters() {
-		return new Parameters(Collections.singletonList(MIME_TYPE_AND_CONTENT_PARAM));
+		return new Parameters(Collections.singletonList(MIME_TYPE_PARAM), CONTENT_PARAM);
 	}
 	
 	@Override
@@ -52,15 +52,8 @@ public final class RenderCommand implements Command {
 	
 	@Override
 	public @NotNull DisplayData run(final @NotNull ParsedArguments args) {
-		final String[] split = args.get(MIME_TYPE_AND_CONTENT_PARAM).split("\n", 2);
-		if (split.length != 2) {
-			throw new UserErrorException("Missing content (the content cannot be placed on the same line as the command)");
-		}
-		final String mimeType = split[0];
-		final String code = split[1];
-		if (mimeType.isEmpty()) {
-			throw new UserErrorException("Missing MIME type");
-		}
+		final String mimeType = args.get(MIME_TYPE_PARAM);
+		final String code = args.get(CONTENT_PARAM);
 		final DisplayData data = new DisplayData(mimeType + ":\n" + code);
 		data.putData(mimeType, code);
 		return data;