diff --git a/Cargo.lock b/Cargo.lock
index 2e5e2805d673f699a7c251d7ae4ff7a1e115c542..57ccc529c8ed14d10171fb7a36b86756246b20c1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -270,6 +270,11 @@ dependencies = [
  "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "doc-comment"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "either"
 version = "1.5.2"
@@ -355,6 +360,7 @@ dependencies = [
  "auto_enums 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "calculate 0.7.0 (git+https://gitlab.redox-os.org/redox-os/calc)",
  "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1127,6 +1133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65"
 "checksum decimal 2.0.4 (git+https://github.com/alkis/decimal.git)" = "<none>"
 "checksum derive_utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8051728ec2caf87b15d051687024572810187693f9d8f4ec561714d7a3fa7d9c"
+"checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97"
 "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
 "checksum err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3d8ff65eb6c2fc68e76557239d16f5698fd56603925b89856d3f0f7105fd4543"
 "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
diff --git a/Cargo.toml b/Cargo.toml
index 74ee1f61d0c24105efe731520af40fd8e5d7ced7..8e63447a1aecbc3253529774f3f28b145c70a30e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -74,6 +74,7 @@ itertools = "0.8"
 lexical = "2.0"
 object-pool = "0.3.1"
 auto_enums = "0.5.5"
+doc-comment = "0.3"
 
 [lib]
 path = "src/lib/lib.rs"
@@ -86,4 +87,4 @@ panic = "abort"
 [patch.crates-io]
 termion = { git = "https://gitlab.redox-os.org/redox-os/termion" }
 liner = { git = "https://gitlab.redox-os.org/redox-os/liner" }
-redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" }
\ No newline at end of file
+redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" }
diff --git a/src/lib/description.md b/src/lib/description.md
new file mode 100644
index 0000000000000000000000000000000000000000..55783e339e526b278acd089b7053b9ffa3f9c518
--- /dev/null
+++ b/src/lib/description.md
@@ -0,0 +1,57 @@
+# Ion - the pipe-oriented embedded language
+
+Ion is an embeddable shell for rust. This means your users can benefit from a fully-fledged programming language to configure your application, rather than predefined layouts like yaml. This also means the configuration can be completely responsive and react to events in any way the user sees fit.
+
+## Getting started
+
+```toml
+[dependencies]
+ion_shell = "1.0"
+```
+
+## Demo
+
+```rust
+use ion_shell::{BuiltinMap, BuiltinFunction, Shell, status::Status};
+use std::{thread, time, cell::RefCell, rc::Rc};
+
+enum Layout {
+  Simple,
+  Complex(String),
+}
+
+fn main() {
+  let mut i = 0;
+  let layout = RefCell::new(Layout::Simple); // A state for your application
+
+  // Create a custom callback to update your state when called by a script
+  let set_layout: BuiltinFunction = &move |args: &[small::String], shell: &mut Shell| {
+    *layout.borrow_mut() = if let Some(text) = args.get(0) {
+      Layout::Complex(text.to_string())
+    } else {
+      Layout::Simple
+    };
+    Status::SUCCESS
+  };
+
+  // Create a shell
+  let mut shell = Shell::library();
+
+  // Register the builtins
+  shell.builtins_mut().add("layout", set_layout, "Set the application layout");
+
+  // Read a file and execute it
+  shell.execute_file("./bob");
+
+  for _ in 0..255 {
+    i += 1;
+    // call a user-defined callback function named on_update
+    let _ = shell.execute_function("on_update", &["ion", &i.to_string()]);
+
+    thread::sleep(time::Duration::from_millis(5));
+  }
+}
+```
+
+## Documentation
+ - [Ion programming language manual](https://doc.redox-os.org/ion-manual/)
diff --git a/src/lib/lib.rs b/src/lib/lib.rs
index 3063d8491649a8089e3193175914be85a67d46df..a0d5413b3faea3b09576ddc3e53f1eb05f395b61 100644
--- a/src/lib/lib.rs
+++ b/src/lib/lib.rs
@@ -1,5 +1,7 @@
 #![allow(unknown_lints)]
 
+#[macro_use]
+extern crate doc_comment;
 #[macro_use]
 extern crate err_derive;
 extern crate ion_braces as braces;
@@ -15,6 +17,8 @@ pub mod builtins;
 mod memory;
 mod shell;
 
+doctest!("./description.md");
+
 pub(crate) use self::memory::IonPool;
 pub use crate::{
     builtins::{BuiltinFunction, BuiltinMap},