diff --git a/Cargo.toml b/Cargo.toml
index 5ca648ab45..16ee769014 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -148,6 +148,10 @@ path = "examples/3d/texture.rs"
name = "z_sort_debug"
path = "examples/3d/z_sort_debug.rs"
+[[example]]
+name = "custom_loop"
+path = "examples/app/custom_loop.rs"
+
[[example]]
name = "empty_defaults"
path = "examples/app/empty_defaults.rs"
diff --git a/examples/app/custom_loop.rs b/examples/app/custom_loop.rs
new file mode 100644
index 0000000000..4ca46dee35
--- /dev/null
+++ b/examples/app/custom_loop.rs
@@ -0,0 +1,31 @@
+use bevy::prelude::*;
+use std::{io, io::BufRead};
+
+struct Input(String);
+
+/// This example demonstrates you can create a custom runner (to update an app manually). It reads
+/// lines from stdin and prints them from within the ecs.
+fn my_runner(mut app: App) {
+ app.initialize();
+
+ println!("Type stuff into the console");
+ for line in io::stdin().lock().lines() {
+ {
+ let mut input = app.resources.get_mut::().unwrap();
+ input.0 = line.unwrap();
+ }
+ app.update();
+ }
+}
+
+fn print_system(input: Res) {
+ println!("You typed: {}", input.0);
+}
+
+fn main() {
+ App::build()
+ .add_resource(Input(String::new()))
+ .set_runner(my_runner)
+ .add_system(print_system.system())
+ .run();
+}