diff --git a/cmd/build.go b/cmd/build.go
index 7aaac70e0eaecf45e4d01e5bea97732698f6f062..07bc520f046a3c5a14077b4beaabd983bcf1c4aa 100644
--- a/cmd/build.go
+++ b/cmd/build.go
@@ -16,7 +16,9 @@ package cmd
 
 import (
 	"errors"
+	"fmt"
 	"os"
+	"strings"
 
 	"git.psu.edu/k8s/devtool/config"
 	"git.psu.edu/k8s/devtool/environment"
@@ -44,7 +46,7 @@ var buildCmd = &cobra.Command{
 
 		conf, err := config.New(configFile)
 		if err != nil {
-			color.New(color.FgRed).PrintFunc()("Error reading configuration file: %s", configFile)
+			color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile)
 			return
 		}
 
@@ -100,7 +102,7 @@ func build(config config.Config) error {
 	case "go":
 		environment.RunRequired(true, "make", "build")
 	default:
-		color.New(color.FgRed).PrintFunc()("devtool doesn't support the '%s' language yet.", lang)
+		color.New(color.FgRed).Printf("devtool doesn't support the '%s' language yet.\n", lang)
 		return errors.New("Language not supported")
 	}
 	return nil
@@ -120,8 +122,14 @@ func buildDockerAndDeploy(config config.Config) error {
 
 		dockerTag := image + ":" + tag.String()
 
-		color.New(color.FgGreen).PrintFunc()("Building ", dockerTag)
-		err = environment.Run(true, "docker", "build", "-t", dockerTag, "-f", dockerfile, ".")
+		dockerRootDir := "."
+		if idx := strings.LastIndex(dockerfile, "/"); idx != -1 {
+			dockerRootDir = dockerfile[:idx]
+			fmt.Println(dockerRootDir)
+		}
+
+		color.New(color.FgGreen).Printf("Building: %s\n", dockerTag)
+		err = environment.Run(true, "docker", "build", "-t", dockerTag, "-f", dockerfile, dockerRootDir)
 		if err != nil {
 			return err
 		}
@@ -146,12 +154,15 @@ func buildDockerAndDeploy(config config.Config) error {
 
 		err = environment.Run(true, "helm", args...)
 		if err != nil {
-			color.New(color.FgRed).PrintFunc()("helm error. try running 'helm del --purge %s'", releaseName)
+			color.New(color.FgRed).Printf("helm error. try running 'helm del --purge %s'\n", releaseName)
 			return err
 		}
 
 		if openServices {
-			environment.Run(true, "minikube", "service", releaseName)
+			err = environment.Run(true, "minikube", "service", releaseName)
+			if err != nil {
+				return err
+			}
 		}
 	}
 	return nil
diff --git a/cmd/ci.go b/cmd/ci.go
index 833b01bcba66ac3b4cd0c4c512c2fa98c105262c..26a561d139ce4294a2e88795d766ce6d67a8496e 100644
--- a/cmd/ci.go
+++ b/cmd/ci.go
@@ -41,7 +41,10 @@ func init() {
 	ciCmd.PersistentFlags().StringVarP(&imageTag, "image-tag", "i", "", "image tag for docker")
 	ciCmd.PersistentFlags().StringVarP(&environmentSuffix, "environment", "e", "", "environment suffix to append to helm release name")
 
-	ciCmd.MarkPersistentFlagRequired("image-tag")
+	err := ciCmd.MarkPersistentFlagRequired("image-tag")
+	if err != nil {
+		panic("invalid arg")
+	}
 
 	// Cobra supports local flags which will only run when this command
 	// is called directly, e.g.:
diff --git a/cmd/ci_build.go b/cmd/ci_build.go
index 3e09c9182f3fc005b5447473a5d994e3ad9aeeac..2b710495c40947a956f2122cca9fcb4484ec3f06 100644
--- a/cmd/ci_build.go
+++ b/cmd/ci_build.go
@@ -31,7 +31,7 @@ var ciBuildCmd = &cobra.Command{
 	RunE: func(cmd *cobra.Command, args []string) error {
 		conf, err := config.New(configFile)
 		if err != nil {
-			color.New(color.FgRed).PrintFunc()("Error reading configuration file: %s", configFile)
+			color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile)
 			return err
 		}
 
@@ -59,8 +59,14 @@ func init() {
 	ciBuildCmd.Flags().StringVarP(&dockerRegistry, "registry", "r", "", "url of the docker registry")
 	ciBuildCmd.Flags().StringVarP(&dockerRegistryNamespace, "registry-namespace", "n", "", "namespace in the docker registry")
 
-	ciBuildCmd.MarkFlagRequired("registry")
-	ciBuildCmd.MarkFlagRequired("registry-namespace")
+	err := ciBuildCmd.MarkFlagRequired("registry")
+	if err != nil {
+		panic("invalid arg")
+	}
+	err = ciBuildCmd.MarkFlagRequired("registry-namespace")
+	if err != nil {
+		panic("invalid arg")
+	}
 }
 
 func buildCiDocker(config config.Config) error {
@@ -73,13 +79,13 @@ func buildCiDocker(config config.Config) error {
 		dockerImage := dockerRegistry + "/" + dockerRegistryNamespace + "/" + image
 		dockerTag := dockerImage + ":" + imageTag
 
-		color.New(color.FgGreen).PrintFunc()("Building: ", dockerTag)
+		color.New(color.FgGreen).Printf("Building: %s\n", dockerTag)
 		err := environment.Run(true, "docker", "build", "-t", dockerTag, "-f", dockerfile, ".")
 		if err != nil {
 			return err
 		}
 
-		color.New(color.FgGreen).PrintFunc()("Pushing Docker image: ", dockerTag)
+		color.New(color.FgGreen).Printf("Pushing Docker image: %s\n", dockerTag)
 		err = environment.Run(true, "docker", "push", dockerImage)
 		if err != nil {
 			return err
diff --git a/cmd/ci_deploy.go b/cmd/ci_deploy.go
index e5bc1cd2fcde397fbfcbe992af9782aabbbeed30..50e52277989577cd1f5d015436bcec801fe60257 100644
--- a/cmd/ci_deploy.go
+++ b/cmd/ci_deploy.go
@@ -30,7 +30,7 @@ var ciDeployCmd = &cobra.Command{
 	RunE: func(cmd *cobra.Command, args []string) error {
 		conf, err := config.New(configFile)
 		if err != nil {
-			color.New(color.FgRed).PrintFunc()("Error reading configuration file: %s", configFile)
+			color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile)
 			return err
 		}
 
@@ -69,14 +69,14 @@ func fluxDeployCi(config config.Config) error {
 		} else {
 			releaseName = deployable.Name + "-" + environmentSuffix
 		}
-		color.Blue("Updating Flux Release:", releaseName)
+		color.New(color.FgBlue).Printf("Updating Flux Release: %s\n", releaseName)
 
 		os.Setenv("KUBE_SERVICE_NAME", releaseName)
 		os.Setenv("CI_PROJECT_NAME", image)
 
 		err := environment.Run(true, "fluxhelmrelease")
 		if err != nil {
-			color.Red("fluxhelmrelease error.")
+			color.Red("fluxhelmrelease error: %s", err)
 			return err
 		}
 	}
diff --git a/cmd/config_init.go b/cmd/config_init.go
index 0de207c2b72bc2b49c8f0545d6fba90969aabfe0..fbc4f65c7ec4c49e615c2b8a160cef70afa3ee38 100644
--- a/cmd/config_init.go
+++ b/cmd/config_init.go
@@ -16,11 +16,14 @@ package cmd
 
 import (
 	"fmt"
+	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
 	"strings"
 
+	"git.psu.edu/k8s/devtool/environment"
+
 	"git.psu.edu/k8s/devtool/config"
 
 	"github.com/fatih/color"
@@ -85,7 +88,7 @@ var initCmd = &cobra.Command{
 
 		dockerfiles := findDockerfiles()
 		for _, file := range dockerfiles {
-			color.Yellow("Found Dockerfile: %s", file)
+			color.New(color.FgYellow).Printf("Found Dockerfile: %s\n", file)
 			prompt := promptui.Prompt{
 				Label:   "Include in config",
 				Default: "Yes",
@@ -121,6 +124,7 @@ var initCmd = &cobra.Command{
 			}
 			deployable.Name = response
 
+			// Ask for Chart
 			selectPrompt := promptui.SelectWithAdd{
 				Label:    "Chart",
 				Items:    []string{"cm/eio-swe-service", "cm/eio-swe-cronjob", "cm/angular-client", "cm/eio-swe-jms-processor"},
@@ -132,31 +136,53 @@ var initCmd = &cobra.Command{
 			}
 			deployable.Chart = response
 
-			prompt = promptui.Prompt{
-				Label: "Chart Version",
+			// Ask for Chart Version
+			availableChartVersions := findChartVersions(response)
+
+			selectPrompt = promptui.SelectWithAdd{
+				Label:    "Chart Version",
+				Items:    availableChartVersions,
+				AddLabel: "Other",
 			}
-			response, err = prompt.Run()
+			_, response, err = selectPrompt.Run()
 			if err != nil {
 				return
 			}
 			deployable.ChartVersion = response
 
-			prompt = promptui.Prompt{
-				Label: "Local Config File",
+			// Ask for Local Config
+			availableLocalConfigFiles := findLocalConfigs()
+
+			selectPrompt = promptui.SelectWithAdd{
+				Label:    "Local Config File",
+				Items:    availableLocalConfigFiles,
+				AddLabel: "Other",
 			}
-			response, err = prompt.Run()
+			_, response, err = selectPrompt.Run()
 			if err != nil {
 				return
 			}
 			deployable.LocalConfig = response
 
+			// Create the file if it doesn't exist already
+			_, err = os.OpenFile(response, os.O_RDONLY|os.O_CREATE, 0666)
+			if err != nil {
+				color.Yellow("Unable to create config file")
+			}
+
 			conf.Deployables = append(conf.Deployables, deployable)
 			color.Green("Adding Deployment")
 		}
 
+		conf.LocalEnvVars = []string{"OAUTH_CLIENT_ID"}
+		conf.LocalEnvVars = []string{"OAUTH_CLIENT_SECRET", "OAUTH_JWK"}
+
 		color.Yellow("Writing configuration")
 
-		conf.Write(configFile)
+		err = conf.Write(configFile)
+		if err != nil {
+			color.New(color.FgRed).Printf("Error writing configuration file: %s\n", configFile)
+		}
 
 	},
 }
@@ -195,3 +221,32 @@ func findDockerfiles() []string {
 	}
 	return dockerfiles
 }
+
+func findChartVersions(chartName string) []string {
+	var versions []string
+	output := environment.RunAndGetOutputRequired("helm", "search", chartName, "--versions")
+	for i, line := range output {
+		if i == 0 {
+			continue
+		}
+		fields := strings.Fields(line)
+		if len(fields) < 4 {
+			continue
+		}
+		versions = append(versions, fields[1])
+	}
+	return versions
+}
+
+func findLocalConfigs() []string {
+	files, err := ioutil.ReadDir("config/")
+	if err != nil {
+		log.Println(err)
+	}
+
+	var filenames []string
+	for _, f := range files {
+		filenames = append(filenames, "config/"+f.Name())
+	}
+	return filenames
+}
diff --git a/cmd/config_list.go b/cmd/config_list.go
index 8df3e96c090335909bd442c5a36d5addf9eece33..a538d9da0f7a8f8ef576c33c8f5979b7493d32a8 100644
--- a/cmd/config_list.go
+++ b/cmd/config_list.go
@@ -29,7 +29,7 @@ var listCmd = &cobra.Command{
 	Run: func(cmd *cobra.Command, args []string) {
 		conf, err := config.New(configFile)
 		if err != nil {
-			color.New(color.FgRed).PrintFunc()("Error reading configuration file: ", configFile, "\n")
+			color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile)
 			return
 		}
 		fmt.Println("Project Configuration")
diff --git a/cmd/run.go b/cmd/run.go
new file mode 100644
index 0000000000000000000000000000000000000000..b9f451945f66b5813930631af358a3a5621619f7
--- /dev/null
+++ b/cmd/run.go
@@ -0,0 +1,90 @@
+// Copyright © 2019 NAME HERE <EMAIL ADDRESS>
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cmd
+
+import (
+	"os"
+	"strings"
+
+	"git.psu.edu/k8s/devtool/environment"
+
+	"git.psu.edu/k8s/devtool/config"
+	"github.com/fatih/color"
+	"github.com/spf13/cobra"
+)
+
+var command string
+
+// runCmd represents the run command
+var runCmd = &cobra.Command{
+	Use:   "run",
+	Short: "run the application",
+	Run: func(cmd *cobra.Command, args []string) {
+		color.Blue("Running your application")
+
+		conf, err := config.New(configFile)
+		if err != nil {
+			color.New(color.FgYellow).Printf("WARNING: no project configuration exists: %s\n", configFile)
+		}
+
+		localConfig := selectLocalConfig(conf.Deployables)
+
+		if localConfig != "" {
+			var helmValues config.HelmValues
+			helmValues, err = config.ReadHelmValues(localConfig)
+			if err != nil {
+				color.New(color.FgRed).Printf("Error reading local config file: %s\n", localConfig)
+			}
+			for k, v := range helmValues.EnvironmentVariables {
+				os.Setenv(k, v)
+			}
+		}
+
+		commandSplit := strings.Fields(command)
+		environment.RunRequired(true, commandSplit[0], commandSplit[1:]...)
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(runCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// runCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	runCmd.Flags().StringVarP(&command, "command", "c", "", "The command to run")
+
+	err := runCmd.MarkFlagRequired("command")
+	if err != nil {
+		panic("invalid arg")
+	}
+}
+
+func selectLocalConfig(deployables []config.Deployable) string {
+	if len(deployables) == 0 {
+		return ""
+	}
+
+	//if len(deployables) == 1 {
+	return deployables[0].LocalConfig
+	//}
+
+	//TODO add support for multiple deployables (prompt user and add arg)
+
+}
diff --git a/cmd/start.go b/cmd/start.go
index 246f367e29691c46db62cbe9303758f8e1b6221b..8edfc381270ea05b1aa19839348f52551abac2d0 100644
--- a/cmd/start.go
+++ b/cmd/start.go
@@ -16,7 +16,6 @@ package cmd
 
 import (
 	"fmt"
-	"os"
 	"os/exec"
 	"strings"
 	"time"
@@ -78,15 +77,9 @@ func start(memory, cpu string) {
 		environment.RunRequired(true, "minikube", "start", "--memory", memory, "--cpus", cpu)
 	}
 
-	checkInstallTiller()
-
-	environment.EvalDockerEnv()
+	fixKubectlContext()
 
-	color.Blue("Environment Variables:")
-
-	for _, e := range os.Environ() {
-		fmt.Println(e)
-	}
+	checkInstallTiller()
 
 }
 
@@ -113,13 +106,31 @@ func checkLocalSetup() bool {
 func checkInstalled(app string) error {
 	path, err := exec.LookPath(app)
 	if err != nil {
-		color.New(color.FgYellow).PrintfFunc()("%s is not installed\n", app)
+		color.New(color.FgYellow).Printf("%s is not installed\n", app)
 	} else {
 		fmt.Printf("%s: %s\n", app, path)
 	}
 	return err
 }
 
+func fixKubectlContext() {
+	color.Blue("setting kubectl context.")
+
+	_, err := exec.LookPath("kubectx")
+	if err != nil {
+		color.New(color.FgYellow).Printf("kubectx is not installed")
+	} else {
+		environment.RunRequired(true, "kubectx", "minikube")
+	}
+
+	_, err = exec.LookPath("kubens")
+	if err != nil {
+		color.New(color.FgYellow).Printf("kubens is not installed")
+	} else {
+		environment.RunRequired(true, "kubens", "default")
+	}
+}
+
 func checkInstallTiller() {
 	color.Blue("Checking if Tiller is installed.")
 
@@ -133,15 +144,18 @@ func checkInstallTiller() {
 		time.Sleep(10 * time.Second)
 
 		serverVersionOutput, err = environment.RunAndGetOutput("helm", "version", "--server", "--short")
+		if err != nil {
+			color.Red("Cannot determin helm server version")
+		}
 	}
 
 	clientVersion := strings.TrimPrefix(clientVersionOutput[0], "Client: ")
 	serverVersion := strings.TrimPrefix(serverVersionOutput[0], "Server: ")
 
 	if clientVersion != serverVersion {
-		warn := color.New(color.FgYellow).PrintFunc()
-		warn("Helm version mismatch between client and server")
-		warn("Client Version: %s\n", clientVersion)
-		warn("Server Version: %s\n", serverVersion)
+		warn := color.New(color.FgYellow).PrintfFunc()
+		warn("Helm version mismatch between client and server\n")
+		warn("  Client Version: %s\n", clientVersion)
+		warn("  Server Version: %s\n", serverVersion)
 	}
 }
diff --git a/config/config.go b/config/config.go
index 5e6423278cf7c2ebea75d008bdb8e9e5fcfb0750..9112c945184f5c4b53fd742e8adaa7253738f72f 100644
--- a/config/config.go
+++ b/config/config.go
@@ -3,6 +3,8 @@ package config
 import (
 	"encoding/json"
 	"io/ioutil"
+
+	"gopkg.in/yaml.v2"
 )
 
 type (
@@ -20,6 +22,9 @@ type (
 		ChartVersion string `json:"chartVersion"`
 		LocalConfig  string `json:"localConfig"`
 	}
+	HelmValues struct {
+		EnvironmentVariables map[string]string `yaml:"environmentVariables"`
+	}
 )
 
 func (config Config) Write(filename string) error {
@@ -40,3 +45,14 @@ func New(filename string) (Config, error) {
 	err = json.Unmarshal(data, &config)
 	return config, err
 }
+
+func ReadHelmValues(filename string) (HelmValues, error) {
+	data, err := ioutil.ReadFile(filename)
+	var helmValues HelmValues
+	if err != nil {
+		return helmValues, err
+	}
+
+	err = yaml.Unmarshal([]byte(data), &helmValues)
+	return helmValues, err
+}
diff --git a/go.mod b/go.mod
index ca513bdab48a0f9a50b3f5d3029aa34ea43bcbb3..88d1010e2edfd9f673bd9562fc34dd2e6c9e862c 100644
--- a/go.mod
+++ b/go.mod
@@ -17,4 +17,5 @@ require (
 	github.com/spf13/viper v1.3.2
 	golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 // indirect
 	gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c // indirect
+	gopkg.in/yaml.v2 v2.2.2
 )