diff --git a/src/Cargo.lock b/src/Cargo.lock
index 219ed5d6bc2..51d45c06fcb 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -6,6 +6,14 @@ dependencies = [
  "libc 0.0.0",
 ]
 
+[[package]]
+name = "aho-corasick"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "alloc"
 version = "0.0.0"
@@ -31,10 +39,25 @@ dependencies = [
  "libc 0.0.0",
 ]
 
+[[package]]
+name = "ansi_term"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "arena"
 version = "0.0.0"
 
+[[package]]
+name = "bitflags"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "bootstrap"
 version = "0.0.0"
@@ -69,6 +92,21 @@ dependencies = [
 name = "cargotest"
 version = "0.1.0"
 
+[[package]]
+name = "clap"
+version = "2.19.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "cmake"
 version = "0.1.18"
@@ -114,6 +152,7 @@ version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -158,6 +197,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "graphviz"
 version = "0.0.0"
 
+[[package]]
+name = "handlebars"
+version = "0.20.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "libc"
 version = "0.0.0"
@@ -183,6 +249,27 @@ name = "log"
 version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "mdbook"
+version = "0.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "handlebars 0.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "memchr"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "num_cpus"
 version = "0.2.13"
@@ -209,6 +296,11 @@ dependencies = [
  "unwind 0.0.0",
 ]
 
+[[package]]
+name = "pest"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "proc_macro"
 version = "0.0.0"
@@ -225,6 +317,15 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "pulldown-cmark"
+version = "0.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "qemu-test-client"
 version = "0.1.0"
@@ -233,6 +334,11 @@ version = "0.1.0"
 name = "qemu-test-server"
 version = "0.1.0"
 
+[[package]]
+name = "quick-error"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "rand"
 version = "0.0.0"
@@ -240,9 +346,30 @@ dependencies = [
  "core 0.0.0",
 ]
 
+[[package]]
+name = "regex"
+version = "0.1.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "rustbook"
-version = "0.0.0"
+version = "0.1.0"
+dependencies = [
+ "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "rustc"
@@ -650,6 +777,11 @@ dependencies = [
  "core 0.0.0",
 ]
 
+[[package]]
+name = "strsim"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "syntax"
 version = "0.0.0"
@@ -685,6 +817,16 @@ dependencies = [
 name = "term"
 version = "0.0.0"
 
+[[package]]
+name = "term_size"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "test"
 version = "0.0.0"
@@ -700,6 +842,23 @@ dependencies = [
  "test 0.0.0",
 ]
 
+[[package]]
+name = "thread-id"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "tidy"
 version = "0.1.0"
@@ -712,14 +871,69 @@ dependencies = [
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "unicode-segmentation"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "utf8-ranges"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "vec_map"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [metadata]
+"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
+"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
+"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
+"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
+"checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374"
 "checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
 "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
 "checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
+"checksum handlebars 0.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "07f9c1d28bcfb97143c95ed0667141677b2b5675c7ba3d5b81459ad43b1073bd"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
 "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
 "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
+"checksum mdbook 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a629cd0194bbd0340a70db83a94b27cf9881fac8c55e6a2db983addcb7114ee4"
+"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
+"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
+"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
+"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
+"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
+"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
+"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c"
+"checksum term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7f5f3f71b0040cecc71af239414c23fd3c73570f5ff54cf50e03cef637f2a0"
+"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
+"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
 "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
+"checksum unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3bc443ded17b11305ffffe6b37e2076f328a5a8cb6aa877b1b98f77699e98b5"
+"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
+"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
+"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 3dc9b837555..74b13144f2f 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -47,6 +47,7 @@ pub fn rustbook(build: &Build, target: &str, name: &str) {
     build.run(build.tool_cmd(&compiler, "rustbook")
                    .arg("build")
                    .arg(&src)
+                   .arg("-d")
                    .arg(out));
 }
 
diff --git a/src/doc/book/src/SUMMARY.md b/src/doc/book/src/SUMMARY.md
new file mode 100644
index 00000000000..7390c82896e
--- /dev/null
+++ b/src/doc/book/src/SUMMARY.md
@@ -0,0 +1,3 @@
+# Summary
+
+- [Chapter 1](./chapter_1.md)
diff --git a/src/doc/book/src/chapter_1.md b/src/doc/book/src/chapter_1.md
new file mode 100644
index 00000000000..b743fda3546
--- /dev/null
+++ b/src/doc/book/src/chapter_1.md
@@ -0,0 +1 @@
+# Chapter 1
diff --git a/src/doc/nomicon/src/SUMMARY.md b/src/doc/nomicon/src/SUMMARY.md
new file mode 100644
index 00000000000..7390c82896e
--- /dev/null
+++ b/src/doc/nomicon/src/SUMMARY.md
@@ -0,0 +1,3 @@
+# Summary
+
+- [Chapter 1](./chapter_1.md)
diff --git a/src/doc/nomicon/src/chapter_1.md b/src/doc/nomicon/src/chapter_1.md
new file mode 100644
index 00000000000..b743fda3546
--- /dev/null
+++ b/src/doc/nomicon/src/chapter_1.md
@@ -0,0 +1 @@
+# Chapter 1
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index e7690c03de5..25c310aa877 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -1,9 +1,12 @@
 [package]
 authors = ["The Rust Project Developers"]
 name = "rustbook"
-version = "0.0.0"
-build = false
+version = "0.1.0"
+license = "MIT/Apache-2.0"
 
-[[bin]]
-name = "rustbook"
-path = "main.rs"
+[dependencies]
+clap = "2.19.3"
+
+[dependencies.mdbook]
+version = "0.0.14"
+default-features = false
diff --git a/src/tools/rustbook/book.rs b/src/tools/rustbook/book.rs
deleted file mode 100644
index c5f72127a9c..00000000000
--- a/src/tools/rustbook/book.rs
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Basic data structures for representing a book.
-
-use std::io::prelude::*;
-use std::io::BufReader;
-use std::iter;
-use std::path::{Path, PathBuf};
-
-pub struct BookItem {
-    pub title: String,
-    pub path: PathBuf,
-    pub path_to_root: PathBuf,
-    pub children: Vec<BookItem>,
-}
-
-pub struct Book {
-    pub chapters: Vec<BookItem>,
-}
-
-/// A depth-first iterator over a book.
-pub struct BookItems<'a> {
-    cur_items: &'a [BookItem],
-    cur_idx: usize,
-    stack: Vec<(&'a [BookItem], usize)>,
-}
-
-impl<'a> Iterator for BookItems<'a> {
-    type Item = (String, &'a BookItem);
-
-    fn next(&mut self) -> Option<(String, &'a BookItem)> {
-        loop {
-            if self.cur_idx >= self.cur_items.len() {
-                match self.stack.pop() {
-                    None => return None,
-                    Some((parent_items, parent_idx)) => {
-                        self.cur_items = parent_items;
-                        self.cur_idx = parent_idx + 1;
-                    }
-                }
-            } else {
-                let cur = self.cur_items.get(self.cur_idx).unwrap();
-
-                let mut section = "".to_string();
-                for &(_, idx) in &self.stack {
-                    section.push_str(&(idx + 1).to_string()[..]);
-                    section.push('.');
-                }
-                section.push_str(&(self.cur_idx + 1).to_string()[..]);
-                section.push('.');
-
-                self.stack.push((self.cur_items, self.cur_idx));
-                self.cur_items = &cur.children[..];
-                self.cur_idx = 0;
-                return Some((section, cur))
-            }
-        }
-    }
-}
-
-impl Book {
-    pub fn iter(&self) -> BookItems {
-        BookItems {
-            cur_items: &self.chapters[..],
-            cur_idx: 0,
-            stack: Vec::new(),
-        }
-    }
-}
-
-/// Construct a book by parsing a summary (markdown table of contents).
-pub fn parse_summary(input: &mut Read, src: &Path) -> Result<Book, Vec<String>> {
-    fn collapse(stack: &mut Vec<BookItem>,
-                top_items: &mut Vec<BookItem>,
-                to_level: usize) {
-        loop {
-            if stack.len() < to_level { return }
-            if stack.len() == 1 {
-                top_items.push(stack.pop().unwrap());
-                return;
-            }
-
-            let tip = stack.pop().unwrap();
-            let last = stack.len() - 1;
-            stack[last].children.push(tip);
-        }
-    }
-
-    let mut top_items = vec![];
-    let mut stack = vec![];
-    let mut errors = vec![];
-
-    // always include the introduction
-    top_items.push(BookItem {
-        title: "Introduction".to_string(),
-        path: PathBuf::from("README.md"),
-        path_to_root: PathBuf::from(""),
-        children: vec![],
-    });
-
-    for line_result in BufReader::new(input).lines() {
-        let line = match line_result {
-            Ok(line) => line,
-            Err(err) => {
-                errors.push(err.to_string());
-                return Err(errors);
-            }
-        };
-
-        let star_idx = match line.find("*") { Some(i) => i, None => continue };
-
-        let start_bracket = star_idx + line[star_idx..].find("[").unwrap();
-        let end_bracket = start_bracket + line[start_bracket..].find("](").unwrap();
-        let start_paren = end_bracket + 1;
-        let end_paren = start_paren + line[start_paren..].find(")").unwrap();
-
-        let given_path = &line[start_paren + 1 .. end_paren];
-        let title = line[start_bracket + 1..end_bracket].to_string();
-        let indent = &line[..star_idx];
-
-        let path_from_root = match src.join(given_path).strip_prefix(src) {
-            Ok(p) => p.to_path_buf(),
-            Err(..) => {
-                errors.push(format!("paths in SUMMARY.md must be relative, \
-                                     but path '{}' for section '{}' is not.",
-                                     given_path, title));
-                PathBuf::new()
-            }
-        };
-        let path_to_root = PathBuf::from(&iter::repeat("../")
-                                         .take(path_from_root.components().count() - 1)
-                                         .collect::<String>());
-        let item = BookItem {
-            title: title,
-            path: path_from_root,
-            path_to_root: path_to_root,
-            children: vec![],
-        };
-        let level = indent.chars().map(|c| -> usize {
-            match c {
-                ' ' => 1,
-                '\t' => 4,
-                _ => unreachable!()
-            }
-        }).sum::<usize>() / 4 + 1;
-
-        if level > stack.len() + 1 {
-            errors.push(format!("section '{}' is indented too deeply; \
-                                 found {}, expected {} or less",
-                                item.title, level, stack.len() + 1));
-        } else if level <= stack.len() {
-            collapse(&mut stack, &mut top_items, level);
-        }
-        stack.push(item)
-    }
-
-    if errors.is_empty() {
-        collapse(&mut stack, &mut top_items, 1);
-        Ok(Book { chapters: top_items })
-    } else {
-        Err(errors)
-    }
-}
diff --git a/src/tools/rustbook/build.rs b/src/tools/rustbook/build.rs
deleted file mode 100644
index d88ff48843a..00000000000
--- a/src/tools/rustbook/build.rs
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation of the `build` subcommand, used to compile a book.
-
-use std::env;
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::io::{self, BufWriter};
-use std::path::{Path, PathBuf};
-use rustc_back::tempdir::TempDir;
-
-use subcommand::Subcommand;
-use term::Term;
-use error::{err, CliResult, CommandResult};
-use book;
-use book::{Book, BookItem};
-
-use rustdoc;
-
-struct Build;
-
-pub fn parse_cmd(name: &str) -> Option<Box<Subcommand>> {
-    if name == "build" {
-        Some(Box::new(Build))
-    } else {
-        None
-    }
-}
-
-fn write_toc(book: &Book, current_page: &BookItem, out: &mut Write) -> io::Result<()> {
-    fn walk_items(items: &[BookItem],
-                  section: &str,
-                  current_page: &BookItem,
-                  out: &mut Write) -> io::Result<()> {
-        for (i, item) in items.iter().enumerate() {
-            walk_item(item, &format!("{}{}.", section, i + 1)[..], current_page, out)?;
-        }
-        Ok(())
-    }
-    fn walk_item(item: &BookItem,
-                 section: &str,
-                 current_page: &BookItem,
-                 out: &mut Write) -> io::Result<()> {
-        let class_string = if item.path == current_page.path {
-            "class='active'"
-        } else {
-            ""
-        };
-
-        writeln!(out, "<li><a {} href='{}'><b>{}</b> {}</a>",
-                 class_string,
-                 current_page.path_to_root.join(&item.path).with_extension("html").display(),
-                 section,
-                 item.title)?;
-        if !item.children.is_empty() {
-            writeln!(out, "<ol class='section'>")?;
-            let _ = walk_items(&item.children[..], section, current_page, out);
-            writeln!(out, "</ol>")?;
-        }
-        writeln!(out, "</li>")?;
-
-        Ok(())
-    }
-
-    writeln!(out, "<div id='toc' class='mobile-hidden'>")?;
-    writeln!(out, "<ol class='chapter'>")?;
-    walk_items(&book.chapters[..], "", &current_page, out)?;
-    writeln!(out, "</ol>")?;
-    writeln!(out, "</div>")?;
-
-    Ok(())
-}
-
-fn render(book: &Book, tgt: &Path) -> CliResult<()> {
-    let tmp = TempDir::new("rustbook")?;
-
-    for (_section, item) in book.iter() {
-        let out_path = match item.path.parent() {
-            Some(p) => tgt.join(p),
-            None => tgt.to_path_buf(),
-        };
-
-        let src;
-        if env::args().len() < 3 {
-            src = env::current_dir().unwrap().clone();
-        } else {
-            src = PathBuf::from(&env::args().nth(2).unwrap());
-        }
-        // preprocess the markdown, rerouting markdown references to html
-        // references
-        let mut markdown_data = String::new();
-        File::open(&src.join(&item.path)).and_then(|mut f| {
-            f.read_to_string(&mut markdown_data)
-        })?;
-        let preprocessed_path = tmp.path().join(item.path.file_name().unwrap());
-        {
-            let urls = markdown_data.replace(".md)", ".html)");
-            File::create(&preprocessed_path).and_then(|mut f| {
-                f.write_all(urls.as_bytes())
-            })?;
-        }
-
-        // write the prelude to a temporary HTML file for rustdoc inclusion
-        let prelude = tmp.path().join("prelude.html");
-        {
-            let mut buffer = BufWriter::new(File::create(&prelude)?);
-            writeln!(&mut buffer, r#"
-                <div id="nav">
-                    <button id="toggle-nav">
-                        <span class="sr-only">Toggle navigation</span>
-                        <span class="bar"></span>
-                        <span class="bar"></span>
-                        <span class="bar"></span>
-                    </button>
-                </div>"#)?;
-            let _ = write_toc(book, &item, &mut buffer);
-            writeln!(&mut buffer, "<div id='page-wrapper'>")?;
-            writeln!(&mut buffer, "<div id='page'>")?;
-        }
-
-        // write the postlude to a temporary HTML file for rustdoc inclusion
-        let postlude = tmp.path().join("postlude.html");
-        {
-            let mut buffer = BufWriter::new(File::create(&postlude)?);
-            writeln!(&mut buffer, "<script src='rustbook.js'></script>")?;
-            writeln!(&mut buffer, "</div></div>")?;
-        }
-
-        fs::create_dir_all(&out_path)?;
-
-        let rustdoc_args: &[String] = &[
-            "".to_string(),
-            preprocessed_path.display().to_string(),
-            format!("-o{}", out_path.display()),
-            format!("--html-before-content={}", prelude.display()),
-            format!("--html-after-content={}", postlude.display()),
-            format!("--markdown-playground-url=https://play.rust-lang.org/"),
-            format!("--markdown-css={}", item.path_to_root.join("rustbook.css").display()),
-            "--markdown-no-toc".to_string(),
-        ];
-        let output_result = rustdoc::main_args(rustdoc_args);
-        if output_result != 0 {
-            let message = format!("Could not execute `rustdoc` with {:?}: {}",
-                                  rustdoc_args, output_result);
-            return Err(err(&message));
-        }
-    }
-
-    // create index.html from the root README
-    fs::copy(&tgt.join("README.html"), &tgt.join("index.html"))?;
-
-    Ok(())
-}
-
-impl Subcommand for Build {
-    fn parse_args(&mut self, _: &[String]) -> CliResult<()> {
-        Ok(())
-    }
-    fn usage(&self) {}
-    fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
-        let cwd = env::current_dir().unwrap();
-        let src;
-        let tgt;
-
-        if env::args().len() < 3 {
-            src = cwd.clone();
-        } else {
-            src = PathBuf::from(&env::args().nth(2).unwrap());
-        }
-
-        if env::args().len() < 4 {
-            tgt = cwd.join("_book");
-        } else {
-            tgt = PathBuf::from(&env::args().nth(3).unwrap());
-        }
-
-        // `_book` directory may already exist from previous runs. Check and
-        // delete it if it exists.
-        for entry in fs::read_dir(&cwd)? {
-            let path = entry?.path();
-            if path == tgt { fs::remove_dir_all(&tgt)? }
-        }
-        fs::create_dir(&tgt)?;
-
-        // Copy static files
-        let css = include_bytes!("static/rustbook.css");
-        let js = include_bytes!("static/rustbook.js");
-
-        let mut css_file = File::create(tgt.join("rustbook.css"))?;
-        css_file.write_all(css)?;
-
-        let mut js_file = File::create(tgt.join("rustbook.js"))?;
-        js_file.write_all(js)?;
-
-
-        let mut summary = File::open(&src.join("SUMMARY.md"))?;
-        match book::parse_summary(&mut summary, &src) {
-            Ok(book) => {
-                // execute rustdoc on the whole book
-                render(&book, &tgt)
-            }
-            Err(errors) => {
-                let n = errors.len();
-                for err in errors {
-                    term.err(&format!("error: {}", err)[..]);
-                }
-
-                Err(err(&format!("{} errors occurred", n)))
-            }
-        }
-    }
-}
diff --git a/src/tools/rustbook/error.rs b/src/tools/rustbook/error.rs
deleted file mode 100644
index e896dee2791..00000000000
--- a/src/tools/rustbook/error.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Error handling utilities. WIP.
-
-use std::error::Error;
-use std::fmt;
-
-pub type CliError = Box<Error + 'static>;
-pub type CliResult<T> = Result<T, CliError>;
-
-pub type CommandError = Box<Error + 'static>;
-pub type CommandResult<T> = Result<T, CommandError>;
-
-pub fn err(s: &str) -> CliError {
-    #[derive(Debug)]
-    struct E(String);
-
-    impl Error for E {
-        fn description(&self) -> &str { &self.0 }
-    }
-    impl fmt::Display for E {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            self.0.fmt(f)
-        }
-    }
-
-    Box::new(E(s.to_string()))
-}
diff --git a/src/tools/rustbook/help.rs b/src/tools/rustbook/help.rs
deleted file mode 100644
index c90c2b93609..00000000000
--- a/src/tools/rustbook/help.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation of the `help` subcommand. Currently just prints basic usage info.
-
-use subcommand::Subcommand;
-use error::CliResult;
-use error::CommandResult;
-use term::Term;
-
-struct Help;
-
-pub fn parse_cmd(name: &str) -> Option<Box<Subcommand>> {
-    match name {
-        "help" | "--help" | "-h" | "-?" => Some(Box::new(Help)),
-        _ => None
-    }
-}
-
-impl Subcommand for Help {
-    fn parse_args(&mut self, _: &[String]) -> CliResult<()> {
-        Ok(())
-    }
-    fn usage(&self) {}
-    fn execute(&mut self, _: &mut Term) -> CommandResult<()> {
-        usage();
-        Ok(())
-    }
-}
-
-pub fn usage() {
-    println!("Usage: rustbook <command> [<args>]");
-    println!("");
-    println!("The <command> must be one of:");
-    println!("  help    Print this message.");
-    println!("  build   Build the book in subdirectory _book");
-    println!("  serve   --NOT YET IMPLEMENTED--");
-    println!("  test    --NOT YET IMPLEMENTED--");
-}
diff --git a/src/tools/rustbook/main.rs b/src/tools/rustbook/main.rs
deleted file mode 100644
index 906251db1c2..00000000000
--- a/src/tools/rustbook/main.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![deny(warnings)]
-
-#![feature(rustc_private)]
-#![feature(rustdoc)]
-
-extern crate rustdoc;
-extern crate rustc_back;
-
-use std::env;
-use std::process;
-use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
-use term::Term;
-
-mod term;
-mod error;
-mod book;
-
-mod subcommand;
-mod help;
-mod build;
-mod serve;
-mod test;
-
-static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
-
-pub fn main() {
-    let mut term = Term::new();
-    let cmd: Vec<_> = env::args().collect();
-
-    if cmd.len() <= 1 {
-        help::usage()
-    } else {
-        match subcommand::parse_name(&cmd[1][..]) {
-            Some(mut subcmd) => {
-                match subcmd.parse_args(&cmd[..cmd.len()-1]) {
-                    Ok(_) => {
-                        match subcmd.execute(&mut term) {
-                            Ok(_) => (),
-                            Err(err) => {
-                                term.err(&format!("error: {}", err));
-                            }
-                        }
-                    }
-                    Err(err) => {
-                        println!("{}", err.description());
-                        println!("");
-                        subcmd.usage();
-                    }
-                }
-            }
-            None => {
-                println!("Unrecognized command '{}'.", cmd[1]);
-                println!("");
-                help::usage();
-            }
-        }
-    }
-    process::exit(EXIT_STATUS.load(Ordering::SeqCst) as i32);
-}
diff --git a/src/tools/rustbook/serve.rs b/src/tools/rustbook/serve.rs
deleted file mode 100644
index 2fa7b7eed7b..00000000000
--- a/src/tools/rustbook/serve.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation of the `serve` subcommand. Just a stub for now.
-
-use subcommand::Subcommand;
-use error::CliResult;
-use error::CommandResult;
-use term::Term;
-
-struct Serve;
-
-pub fn parse_cmd(name: &str) -> Option<Box<Subcommand>> {
-    if name == "serve" {
-        Some(Box::new(Serve))
-    } else {
-        None
-    }
-}
-
-impl Subcommand for Serve {
-    fn parse_args(&mut self, _: &[String]) -> CliResult<()> {
-        Ok(())
-    }
-    fn usage(&self) {}
-    fn execute(&mut self, _: &mut Term) -> CommandResult<()> {
-        Ok(())
-    }
-}
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
new file mode 100644
index 00000000000..837c934934a
--- /dev/null
+++ b/src/tools/rustbook/src/main.rs
@@ -0,0 +1,79 @@
+extern crate mdbook;
+#[macro_use]
+extern crate clap;
+
+use std::env;
+use std::error::Error;
+use std::io::{self, Write};
+use std::path::{Path, PathBuf};
+
+use clap::{App, ArgMatches, SubCommand, AppSettings};
+
+use mdbook::MDBook;
+
+const NAME: &'static str = "rustbook";
+
+fn main() {
+    // Create a list of valid arguments and sub-commands
+    let matches = App::new(NAME)
+                    .about("Build a book with mdBook")
+                    .author("Steve Klabnik <steve@steveklabnik.com>")
+                    .version(&*format!("v{}", crate_version!()))
+                    .setting(AppSettings::SubcommandRequired)
+                    .subcommand(SubCommand::with_name("build")
+                        .about("Build the book from the markdown files")
+                        .arg_from_usage("-d, --dest-dir=[dest-dir] 'The output directory for your book{n}(Defaults to ./book when omitted)'")
+                        .arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'"))
+                    .get_matches();
+
+    // Check which subcomamnd the user ran...
+    let res = match matches.subcommand() {
+        ("build", Some(sub_matches)) => build(sub_matches),
+        ("test", Some(sub_matches)) => test(sub_matches),
+        (_, _) => unreachable!(),
+    };
+
+    if let Err(e) = res {
+        writeln!(&mut io::stderr(), "An error occured:\n{}", e).ok();
+        ::std::process::exit(101);
+    }
+}
+
+// Build command implementation
+fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
+    let book_dir = get_book_dir(args);
+    let book = MDBook::new(&book_dir).read_config();
+
+    let mut book = match args.value_of("dest-dir") {
+        Some(dest_dir) => book.set_dest(Path::new(dest_dir)),
+        None => book
+    };
+
+    try!(book.build());
+
+    Ok(())
+}
+
+fn test(args: &ArgMatches) -> Result<(), Box<Error>> {
+    let book_dir = get_book_dir(args);
+    let mut book = MDBook::new(&book_dir).read_config();
+
+    try!(book.test());
+
+    Ok(())
+}
+
+fn get_book_dir(args: &ArgMatches) -> PathBuf {
+    if let Some(dir) = args.value_of("dir") {
+        // Check if path is relative from current dir, or absolute...
+        let p = Path::new(dir);
+        if p.is_relative() {
+            env::current_dir().unwrap().join(dir)
+        } else {
+            p.to_path_buf()
+        }
+    } else {
+        env::current_dir().unwrap()
+    }
+}
+
diff --git a/src/tools/rustbook/static/rustbook.css b/src/tools/rustbook/static/rustbook.css
deleted file mode 100644
index ba0151fa2ed..00000000000
--- a/src/tools/rustbook/static/rustbook.css
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
- * file at the top-level directory of this distribution and at
- * http://rust-lang.org/COPYRIGHT.
- *
- * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
- * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
- * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
- * option. This file may not be copied, modified, or distributed
- * except according to those terms.
- */
-
-@import url('../rust.css');
-
-body {
-    max-width: none;
-    font: 16px/1.6 'Source Serif Pro', Georgia, Times, 'Times New Roman', serif;
-    color: #333;
-}
-
-h1, h2, h3, h4, h5, h6 {
-    font-family: 'Open Sans', 'Fira Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
-    font-weight: bold;
-    color: #333;
-}
-
-@media only screen {
-    #toc {
-        position: fixed;
-        top: 0;
-        left: 0;
-        bottom: 0;
-        width: 300px;
-        overflow-y: auto;
-        border-right: 1px solid #e8e8e8;
-        padding: 0 15px;
-        font-size: 14px;
-        background-color: #fafafa;
-        -webkit-overflow-scrolling: touch;
-    }
-
-    #page-wrapper {
-        position: absolute;
-        top: 0;
-        left: 300px;
-        right: 0;
-        padding: 0 15px;
-        -webkit-overflow-scrolling: touch;
-    }
-}
-
-@media only print {
-    #toc, #nav {
-        display: none;
-    }
-}
-
-@media only screen and (max-width: 1023px) {
-    #toc {
-        width: 100%;
-        top: 40px;
-    }
-
-    #page-wrapper {
-        top: 40px;
-        left: 0;
-    }
-
-    .mobile-hidden {
-        display: none;
-    }
-}
-
-#page {
-    margin: 0 auto;
-    max-width: 750px;
-    padding-bottom: 50px;
-}
-
-.chapter {
-    list-style: none;
-    padding-left: 0;
-    line-height: 30px;
-}
-
-.section {
-    list-style: none;
-    padding-left: 20px;
-    line-height: 40px;
-}
-
-.section li {
-    text-overflow: ellipsis;
-    overflow: hidden;
-    white-space: nowrap;
-}
-
-.chapter li a {
-    color: #333;
-    padding: 5px 0;
-}
-
-.chapter li a.active,
-.chapter li a:hover {
-    color: #008cff;
-    text-decoration: none;
-}
-
-#toggle-nav {
-    cursor: pointer;
-    margin-top: 5px;
-    width: 30px;
-    height: 30px;
-    background-color: #fff;
-    border: 1px solid #666;
-    border-radius: 3px;
-    padding: 3px 3px 0 3px;
-}
-
-.sr-only {
-    position: absolute;
-    width: 1px;
-    height: 1px;
-    margin: -1px;
-    padding: 0;
-    overflow: hidden;
-    clip: rect(0, 0, 0, 0);
-    border: 0;
-}
-
-.bar {
-    display: block;
-    background-color: #000;
-    border-radius: 2px;
-    width: 100%;
-    height: 2px;
-    margin: 2px 0 3px;
-    padding: 0;
-}
-
-pre {
-    padding: 11px;
-    overflow: auto;
-    font-size: 85%;
-    line-height: 1.45;
-    background-color: #f7f7f7;
-    border: 0;
-    border-radius: 3px;
-}
-
-.left {
-    float: left;
-}
-
-.right {
-    float: right;
-}
diff --git a/src/tools/rustbook/static/rustbook.js b/src/tools/rustbook/static/rustbook.js
deleted file mode 100644
index d8ab15260ed..00000000000
--- a/src/tools/rustbook/static/rustbook.js
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*jslint browser: true, es5: true */
-/*globals $: true, rootPath: true */
-
-document.addEventListener('DOMContentLoaded', function() {
-    'use strict';
-
-    document.getElementById('toggle-nav').onclick = function(e) {
-        var toc = document.getElementById('toc');
-        var pagewrapper = document.getElementById('page-wrapper');
-        toggleClass(toc, 'mobile-hidden');
-        toggleClass(pagewrapper, 'mobile-hidden');
-    };
-
-    function toggleClass(el, className) {
-        // from http://youmightnotneedjquery.com/
-        if (el.classList) {
-            el.classList.toggle(className);
-        } else {
-            var classes = el.className.split(' ');
-            var existingIndex = classes.indexOf(className);
-
-            if (existingIndex >= 0) {
-                classes.splice(existingIndex, 1);
-            } else {
-                classes.push(className);
-            }
-
-            el.className = classes.join(' ');
-        }
-    }
-
-    // The below code is used to add prev and next navigation links to the
-    // bottom of each of the sections.
-    // It works by extracting the current page based on the url and iterates
-    // over the menu links until it finds the menu item for the current page. We
-    // then create a copy of the preceding and following menu links and add the
-    // correct css class and insert them into the bottom of the page.
-    var toc = document.getElementById('toc').getElementsByTagName('a');
-    var href = document.location.pathname.split('/').pop();
-
-    if (href === 'index.html' || href === '') {
-        href = 'README.html';
-    }
-
-    for (var i = 0; i < toc.length; i++) {
-        if (toc[i].attributes.href.value.split('/').pop() === href) {
-            var nav = document.createElement('p');
-
-            if (i > 0) {
-                var prevNode = toc[i-1].cloneNode(true);
-                prevNode.className = 'left';
-                prevNode.setAttribute('rel', 'prev');
-                nav.appendChild(prevNode);
-            }
-
-            if (i < toc.length - 1) {
-                var nextNode = toc[i+1].cloneNode(true);
-                nextNode.className = 'right';
-                nextNode.setAttribute('rel', 'next');
-                nav.appendChild(nextNode);
-            }
-
-            document.getElementById('page').appendChild(nav);
-
-            break;
-        }
-    }
-});
diff --git a/src/tools/rustbook/subcommand.rs b/src/tools/rustbook/subcommand.rs
deleted file mode 100644
index a66c2b4f302..00000000000
--- a/src/tools/rustbook/subcommand.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Common API for all rustbook subcommands.
-
-use error::CliResult;
-use error::CommandResult;
-use term::Term;
-
-use help;
-use build;
-use serve;
-use test;
-
-pub trait Subcommand {
-    /// Mutate the subcommand by parsing its arguments.
-    ///
-    /// Returns `Err` on a parsing error.
-    fn parse_args(&mut self, args: &[String]) -> CliResult<()>;
-    /// Print the CLI usage information.
-    fn usage(&self);
-    /// Actually execute the subcommand.
-    fn execute(&mut self, term: &mut Term) -> CommandResult<()>;
-}
-
-/// Create a Subcommand object based on its name.
-pub fn parse_name(name: &str) -> Option<Box<Subcommand>> {
-    let cmds: [fn(&str) -> Option<Box<Subcommand>>; 4] = [help::parse_cmd,
-                                                          build::parse_cmd,
-                                                          serve::parse_cmd,
-                                                          test::parse_cmd];
-    for parser in &cmds {
-        let parsed = (*parser)(name);
-        if parsed.is_some() { return parsed }
-    }
-    None
-}
diff --git a/src/tools/rustbook/term.rs b/src/tools/rustbook/term.rs
deleted file mode 100644
index cdd25e67c8f..00000000000
--- a/src/tools/rustbook/term.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! An abstraction of the terminal. Eventually, provide color and
-//! verbosity support. For now, just a wrapper around stdout/stderr.
-
-use std::io;
-use std::io::prelude::*;
-use std::sync::atomic::Ordering;
-
-pub struct Term {
-    err: Box<Write + 'static>
-}
-
-impl Term {
-    pub fn new() -> Term {
-        Term {
-            err: Box::new(io::stderr())
-        }
-    }
-
-    pub fn err(&mut self, msg: &str) {
-        // swallow any errors
-        let _ = writeln!(&mut self.err, "{}", msg);
-        ::EXIT_STATUS.store(101, Ordering::SeqCst);
-    }
-}
diff --git a/src/tools/rustbook/test.rs b/src/tools/rustbook/test.rs
deleted file mode 100644
index 002c46a7af4..00000000000
--- a/src/tools/rustbook/test.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation of the `test` subcommand. Just a stub for now.
-
-use subcommand::Subcommand;
-use error::{err, CliResult, CommandResult};
-use term::Term;
-use book;
-
-use std::fs::File;
-use std::env;
-use std::process::Command;
-
-struct Test;
-
-pub fn parse_cmd(name: &str) -> Option<Box<Subcommand>> {
-    if name == "test" {
-        Some(Box::new(Test))
-    } else {
-        None
-    }
-}
-
-impl Subcommand for Test {
-    fn parse_args(&mut self, _: &[String]) -> CliResult<()> {
-        Ok(())
-    }
-    fn usage(&self) {}
-    fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
-        let cwd = env::current_dir().unwrap();
-        let src = cwd.clone();
-
-        let mut summary = File::open(&src.join("SUMMARY.md"))?;
-        match book::parse_summary(&mut summary, &src) {
-            Ok(book) => {
-                for (_, item) in book.iter() {
-                    let output_result = Command::new("rustdoc")
-                        .arg(&item.path)
-                        .arg("--test")
-                        .output();
-                    match output_result {
-                        Ok(output) => {
-                            if !output.status.success() {
-                                term.err(&format!("{}\n{}",
-                                         String::from_utf8_lossy(&output.stdout),
-                                         String::from_utf8_lossy(&output.stderr)));
-                                return Err(err("some tests failed"));
-                            }
-
-                        }
-                        Err(e) => {
-                            let message = format!("could not execute `rustdoc`: {}", e);
-                            return Err(err(&message))
-                        }
-                    }
-                }
-            }
-            Err(errors) => {
-                for err in errors {
-                    term.err(&err[..]);
-                }
-                return Err(err("there was an error"))
-            }
-        }
-        Ok(()) // lol
-    }
-}