diff --git a/firestarter b/firestarter
index 1f8e634..ba85039 100755
--- a/firestarter
+++ b/firestarter
@@ -187,26 +187,7 @@ step_execute() {
 		fi
 		# Skip our logs directory
 		[ "$_optlogdir" == "$file" ] && continue
-		local filename="$(basename -- "$file")"
-		local logfile="$_optlogdir/$filename.log"
-		if gettarget "$file"; then
-			# It's a defaults file with a selected target
-			target="$_return"
-			log "Found target for $filename: \"$target\""
-			[ -n "$_optdryrun" ] && continue
-			if [ -f "$logfile" ]; then
-				[ -f "$logfile.old" ] && rm "$logfile.old"
-				mv "$logfile" "$logfile.old"
-			fi
-			bash -c "$target" > "$logfile" 2>&1 &
-		elif [ $? = 50 ] && [ -x "$file" ]; then
-			# It's a shell script or executable symlink
-			log "Executing file: \"$filename\""
-			[ -n "$_optdryrun" ] && continue
-			"$file" > "$logfile" 2>&1 &
-		else
-			warn "Could not execute file: \"$filename\""
-		fi
+		fs_exec "$file"
 	done
 }
 step_postexecute() {
@@ -277,13 +258,21 @@ step_logout() {
 
 printhelp() {
 	cat << EOF
-Usage: $_name [OPTION]...
+Usage: $_name [OPTION]... {COMMAND}
 
   -d			Perform a dry run; print what programs would have been
 			executed instead of doing so
   -h			Print this help text
   -v			Print more status messages. Stacks
 
+Commands:
+If no command is specified, firestarter will behave as though init had been
+provided
+
+  init			Start all services and wait
+  start			Start the provided service, fork, and exit
+  status		Show status information
+
 Environment Variables:
 
   FS_DIEONWM		If nonempty, end the session when the WM dies.
@@ -293,6 +282,54 @@ Copyright (c) 2019 rehashedsalt@cock.li
 Licensed under the MIT license
 EOF
 }
+fs_exec() {
+	# Execute an fsdefaults file
+	[ -z "$1" ] && return 1
+	local file="$1"
+	local filename="$(basename -- "$file")"
+	local logfile="$_optlogdir/$filename.log"
+	if gettarget "$file"; then
+		# It's a defaults file with a selected target
+		target="$_return"
+		log "Found target for $filename: \"$target\""
+		[ -n "$_optdryrun" ] && return
+		if [ -f "$logfile" ]; then
+			[ -f "$logfile.old" ] && rm "$logfile.old"
+			mv "$logfile" "$logfile.old"
+		fi
+		bash -c "$target" > "$logfile" 2>&1 &
+	elif [ $? = 50 ] && [ -x "$file" ]; then
+		# It's a shell script or executable symlink
+		log "Executing file: \"$filename\""
+		[ -n "$_optdryrun" ] && return
+		"$file" > "$logfile" 2>&1 &
+	else
+		warn "Could not execute file: \"$filename\""
+	fi
+}
+firestart() {
+	# Really main firestarter function
+	local action="${_args[0]}"
+	[ -z "$action" ] && action=init
+	case "$action" in
+		init)
+			[ -n "$_optdryrun" ] && log "Performing a dry run"
+			step_preexecute
+			step_execute
+			step_wait
+			step_logout
+			;;
+		start)
+			error "NYI" 128
+			;;
+		status)
+			error "NYI" 128
+			;;
+		*)
+			error "Unknown action: $action" 51
+			;;
+	esac
+}
 
 # Main
 main() {
@@ -359,11 +396,7 @@ main() {
 	fi
 
 	# Do the do
-	[ -n "$_optdryrun" ] && log "Performing a dry run"
-	step_preexecute
-	step_execute
-	step_wait
-	step_logout
+	firestart
 	exit 0
 }