diff --git a/Makefile b/Makefile
index a142a10..7d39415 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ BIN = dive
 all: clean build
 
 run: build
-	docker image ls | grep "dive-test" >/dev/null || docker build -t dive-test:latest .
+	docker image ls | grep "dive-test" >/dev/null || docker build -t dive-test:latest -f data/Dockerfile .
 	./build/$(BIN) dive-test
 
 build:
diff --git a/README.md b/README.md
index 0e8baff..aff38a2 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,7 @@
 # dive
 [![Go Report Card](https://goreportcard.com/badge/github.com/wagoodman/dive)](https://goreportcard.com/report/github.com/wagoodman/dive)
 
-A tool for interrogating docker images. 
-
+**A tool for interrogating docker images.**
 
 To analyze a Docker image simply run dive with an image tag/id/digest:
 ```bash
diff --git a/cmd/build.go b/cmd/build.go
index 485534c..d6fe2fd 100644
--- a/cmd/build.go
+++ b/cmd/build.go
@@ -7,15 +7,13 @@ import (
 	"github.com/wagoodman/dive/ui"
 	"io/ioutil"
 	"os"
-	"os/exec"
-	"strings"
+	"github.com/wagoodman/dive/utils"
 )
 
 // buildCmd represents the build command
 var buildCmd = &cobra.Command{
-	Use:                "build",
-	Short:              "Build and analyze a docker image",
-	Long:               `Build and analyze a docker image`,
+	Use:                "build [any valid `docker build` arguments]",
+	Short:              "Builds and analyzes a docker image from a Dockerfile (this is a thin wrapper for the `docker build` command).",
 	DisableFlagParsing: true,
 	Run:                doBuild,
 }
@@ -33,7 +31,7 @@ func doBuild(cmd *cobra.Command, args []string) {
 	defer os.Remove(iidfile.Name())
 
 	allArgs := append([]string{"--iidfile", iidfile.Name()}, args...)
-	err = runDockerCmd("build", allArgs...)
+	err = utils.RunDockerCmd("build", allArgs...)
 	if err != nil {
 		log.Fatal(err)
 	}
@@ -46,28 +44,3 @@ func doBuild(cmd *cobra.Command, args []string) {
 	manifest, refTrees := image.InitializeData(string(imageId))
 	ui.Run(manifest, refTrees)
 }
-
-// runDockerCmd runs a given Docker command in the current tty
-func runDockerCmd(cmdStr string, args ...string) error {
-
-	allArgs := cleanArgs(append([]string{cmdStr}, args...))
-
-	cmd := exec.Command("docker", allArgs...)
-
-	cmd.Stdout = os.Stdout
-	cmd.Stderr = os.Stderr
-	cmd.Stdin = os.Stdin
-
-	return cmd.Run()
-}
-
-// cleanArgs trims the whitespace from the given set of strings.
-func cleanArgs(s []string) []string {
-	var r []string
-	for _, str := range s {
-		if str != "" {
-			r = append(r, strings.Trim(str, " "))
-		}
-	}
-	return r
-}
diff --git a/cmd/root.go b/cmd/root.go
index 1e85094..c78421f 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -7,15 +7,18 @@ import (
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 	"os"
+	"github.com/tebeka/atexit"
+	"github.com/k0kubun/go-ansi"
 )
 
 var cfgFile string
 
 // rootCmd represents the base command when called without any subcommands
 var rootCmd = &cobra.Command{
-	Use:   "dive",
+	Use:   "dive [IMAGE]",
 	Short: "Docker Image Visualizer & Explorer",
-	Long:  `Docker Image Visualizer & Explorer`,
+	Long:  `This tool provides a way to discover and explore the contents of a docker image. Additionally the tool estimates
+the amount of wasted space and identifies the offending files from the image.`,
 	Args:  cobra.ExactArgs(1),
 	Run:   analyze,
 }
@@ -28,18 +31,19 @@ func Execute() {
 	}
 }
 
+func exitHandler() {
+	ansi.CursorShow()
+}
+
 func init() {
+	ansi.CursorHide()
+	atexit.Register(exitHandler)
+
 	cobra.OnInitialize(initConfig)
 	cobra.OnInitialize(initLogging)
 
-	// Here you will define your flags and configuration settings.
-	// Cobra supports persistent flags, which, if defined here,
-	// will be global for your application.
-	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.dive.yaml)")
-
-	// Cobra also supports local flags, which will only run
-	// when this action is called directly.
-	rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+	// TODO: add config options
+	// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.dive.yaml)")
 }
 
 // initConfig reads in config file and ENV variables if set.
diff --git a/Dockerfile b/data/Dockerfile
similarity index 89%
rename from Dockerfile
rename to data/Dockerfile
index 358f252..c3b6e8a 100644
--- a/Dockerfile
+++ b/data/Dockerfile
@@ -1,5 +1,5 @@
 FROM alpine:latest
-ADD README.md /somefile.txt
+ADD ../README.md /somefile.txt
 RUN mkdir /root/example
 RUN cp /somefile.txt /root/example/somefile1.txt
 RUN cp /somefile.txt /root/example/somefile2.txt
diff --git a/image/image.go b/image/image.go
index ccdec04..a33fa06 100644
--- a/image/image.go
+++ b/image/image.go
@@ -13,10 +13,10 @@ import (
 	"strings"
 
 	"github.com/docker/docker/client"
-	"github.com/k0kubun/go-ansi"
 	"github.com/wagoodman/dive/filetree"
 	"github.com/wagoodman/jotframe"
 	"golang.org/x/net/context"
+	"github.com/wagoodman/dive/utils"
 )
 
 // TODO: this file should be rethought... but since it's only for preprocessing it'll be tech debt for now.
@@ -57,11 +57,14 @@ func (pb *ProgressBar) Update(currentValue int64) (hasChanged bool) {
 func (pb *ProgressBar) String() string {
 	width := 40
 	done := int((pb.percent * width) / 100.0)
+	if done > width {
+		done = width
+	}
 	todo := width - done
+	if todo < 0 {
+		todo = 0
+	}
 	head := 1
-	// if pb.percent >= 100 {
-	// 	head = 0
-	// }
 
 	return "[" + strings.Repeat("=", done) + strings.Repeat(">", head) + strings.Repeat(" ", todo) + "]" + fmt.Sprintf(" %d %% (%d/%d)", pb.percent, pb.rawCurrent, pb.rawTotal)
 }
@@ -194,13 +197,21 @@ func InitializeData(imageID string) ([]*Layer, []*filetree.FileTree) {
 	var layerMap = make(map[string]*filetree.FileTree)
 	var trees = make([]*filetree.FileTree, 0)
 
-	ansi.CursorHide()
+	// pull the image if it does not exist
+	ctx := context.Background()
+	dockerClient, err := client.NewClientWithOpts()
+	if err != nil {
+		fmt.Println("Could not connect to the Docker daemon:"+err.Error())
+		os.Exit(1)
+	}
+	_, _, err = dockerClient.ImageInspectWithRaw(ctx, imageID)
+	if err != nil {
+		// don't use the API, the CLI has more informative output
+		utils.RunDockerCmd("pull", imageID)
+	}
 
 	// save this image to disk temporarily to get the content info
 	imageTarPath, tmpDir := saveImage(imageID)
-	// imageTarPath := "/tmp/dive516670682/image.tar"
-	// tmpDir := "/tmp/dive516670682"
-	// fmt.Println(tmpDir)
 	defer os.RemoveAll(tmpDir)
 
 	// read through the image contents and build a tree
@@ -313,8 +324,6 @@ func InitializeData(imageID string) ([]*Layer, []*filetree.FileTree) {
 		layerIdx--
 	}
 
-	ansi.CursorShow()
-
 	return layers, trees
 }
 
@@ -322,7 +331,8 @@ func saveImage(imageID string) (string, string) {
 	ctx := context.Background()
 	dockerClient, err := client.NewClientWithOpts()
 	if err != nil {
-		panic(err)
+		fmt.Println("Could not connect to the Docker daemon:"+err.Error())
+		os.Exit(1)
 	}
 
 	frame := jotframe.NewFixedFrame(0, false, false, true)
@@ -331,7 +341,6 @@ func saveImage(imageID string) (string, string) {
 	io.WriteString(line, "  Fetching metadata...")
 
 	result, _, err := dockerClient.ImageInspectWithRaw(ctx, imageID)
-	check(err)
 	totalSize := result.Size
 
 	frame.Remove(line)
diff --git a/utils/docker.go b/utils/docker.go
new file mode 100644
index 0000000..339b0a9
--- /dev/null
+++ b/utils/docker.go
@@ -0,0 +1,33 @@
+package utils
+
+import (
+	"os/exec"
+	"os"
+	"strings"
+)
+
+// RunDockerCmd runs a given Docker command in the current tty
+func RunDockerCmd(cmdStr string, args ...string) error {
+
+	allArgs := cleanArgs(append([]string{cmdStr}, args...))
+
+	cmd := exec.Command("docker", allArgs...)
+
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	cmd.Stdin = os.Stdin
+
+	return cmd.Run()
+}
+
+// cleanArgs trims the whitespace from the given set of strings.
+func cleanArgs(s []string) []string {
+	var r []string
+	for _, str := range s {
+		if str != "" {
+			r = append(r, strings.Trim(str, " "))
+		}
+	}
+	return r
+}
+