diff --git a/ci/Dockerfile-android b/ci/Dockerfile-android
index dc85a9cb0a7a0669c77b03f7c2cd4e19cb46e060..5f0a31e9c2fb15ec9f1089e3e43c30b54def2071 100644
--- a/ci/Dockerfile-android
+++ b/ci/Dockerfile-android
@@ -1,3 +1,7 @@
+# This is a Dockerfile for building the image that is used to build Android
+# binaries and run tests within. This will install the NDK, SDK, and set up an
+# emulator to run tests in.
+
 FROM ubuntu:latest
 
 RUN mkdir /build
diff --git a/ci/README.md b/ci/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c05e771da18fc1e386427cfdd86e532dd116798f
--- /dev/null
+++ b/ci/README.md
@@ -0,0 +1,45 @@
+The goal of the libc crate is to have CI running everywhere to have the
+strongest guarantees about the definitions that this library contains, and as a
+result the CI is pretty complicated and also pretty large! Hopefully this can
+serve as a guide through the sea of scripts in this directory and elsewhere in
+this project.
+
+First up, let's talk about the files in this directory:
+
+* `Dockerfile-android`, `android-accept-licenses.sh` -- these two files are
+  used to build the Docker image that the android CI builder uses. The
+  `Dockerfile` just installs the Android SDK, NDK, a Rust nightly, Rust target
+  libraries for Android, and sets up an emulator to run tests in. You can build
+  a new image with this command (from the root of the project):
+
+      docker build -t alexcrichton/rust-libc-test -f ci/Dockerfile-android .
+
+  When building a new image contact @alexcrichton to push it to the docker hub
+  and have libc start using it. This hasn't needed to happen yet, so the process
+  may be a little involved.
+
+  The script here, `android-accept-licenses.sh` is just a helper used to accept
+  the licenses of the SDK of Android while the docker image is being created.
+
+* `msys2.ps1` - a PowerShell script which is used to install MSYS2 on the
+  AppVeyor bots. As of this writing MSYS2 isn't installed by default, and this
+  script will install the right version/arch of msys2 in preparation of using
+  the contained C compiler to compile C shims.
+
+* `run-travis.sh` - a shell script run by all Travis builders, this is
+  responsible for setting up the rest of the environment such as installing new
+  packages, downloading Rust target libraries, etc.
+
+* `run.sh` - the actual script which runs tests for a particular architecture.
+  Called from the `run-travis.sh` script this will run all tests for the target
+  specified.
+
+* `cargo-config` - Cargo configuration of linkers to use copied into place by
+  the `run-travis.sh` script before builds are run.
+
+* `dox.sh` - script called from `run-travis.sh` on only the linux 64-bit nightly
+  Travis bots to build documentation for this crate.
+
+* `landing-page-*.html` - used by `dox.sh` to generate a landing page for all
+  architectures' documentation.
+
diff --git a/ci/cargo-config b/ci/cargo-config
index f8f6cc21da47c3ddc08dcda8cf2166d6b5534ff9..e738f18902dc0ee6d076ae40f6820223ccd760a8 100644
--- a/ci/cargo-config
+++ b/ci/cargo-config
@@ -1,3 +1,5 @@
+# Configuration of which linkers to call on Travis for various architectures
+
 [target.arm-linux-androideabi]
 linker = "arm-linux-androideabi-gcc"
 
diff --git a/ci/dox.sh b/ci/dox.sh
index a003dc389d06c6a425cd45b4035f1103d32233e9..6edcb159ddba64a7c9ae7aff776dbd966d61d09f 100644
--- a/ci/dox.sh
+++ b/ci/dox.sh
@@ -1,14 +1,18 @@
 #!/bin/sh
 
+# Builds documentation for all target triples that we have a registered URL for
+# in liblibc. This scrapes the list of triples to document from `src/lib.rs`
+# which has a bunch of `html_root_url` directives we pick up.
+
 set -e
 
+TARGETS=`grep html_root_url src/lib.rs | sed 's/.*".*\/\(.*\)"/\1/'`
+
 rm -rf target/doc
 mkdir -p target/doc
 
 cp ci/landing-page-head.html target/doc/index.html
 
-TARGETS=`grep html_root_url src/lib.rs | sed 's/.*".*\/\(.*\)"/\1/'`
-
 for target in $TARGETS; do
   echo documenting $target
 
@@ -21,7 +25,8 @@ done
 
 cat ci/landing-page-footer.html >> target/doc/index.html
 
-if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "autotest" ]; then
+# If we're on travis, not a PR, and on the right branch, publish!
+if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then
   pip install ghp-import --user $USER
   $HOME/.local/bin/ghp-import -n target/doc
   git push -qf https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
diff --git a/ci/msys2.ps1 b/ci/msys2.ps1
index f57cc6b4e8555e676cf99c453895b0b3fb0b696f..071e8f4af02949b1c066cdd44c87099d7e108c99 100644
--- a/ci/msys2.ps1
+++ b/ci/msys2.ps1
@@ -1,3 +1,5 @@
+# Installs MSYS2 on AppVeyor builders
+
 If (!${env:MSYS2_ARCH}) {
   Exit 0
 }
diff --git a/ci/run-travis.sh b/ci/run-travis.sh
index f5ddc9dc51f5c9e7e71f7ce418f68cba685de9b3..db01aae2412b84d8dcf1c8fdd2688aae2c3f5cb7 100644
--- a/ci/run-travis.sh
+++ b/ci/run-travis.sh
@@ -1,3 +1,7 @@
+# Entry point for all travis builds, this will set up the Travis environment by
+# downloading any dependencies. It will then execute the `run.sh` script to
+# build and execute all tests.
+
 set -ex
 
 if [ "$TRAVIS_OS_NAME" = "linux" ]; then
diff --git a/ci/run.sh b/ci/run.sh
index 16778a98728d86e76af5115a7d760b2b75ad08ac..f9e0b51e02e645c16ac88f2fadcedc2575e8f358 100644
--- a/ci/run.sh
+++ b/ci/run.sh
@@ -1,5 +1,8 @@
 #!/bin/sh
 
+# Builds and runs tests for a particular target passed as an argument to this
+# script.
+
 set -ex
 
 TARGET=$1