diff --git a/cmd/init.go b/cmd/init.go
index 4a7ef31ebf2c4a5a35eb6a1f847f47c30ab7c316..3320522c6636ba88914ba30c653d51708a9c6182 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -16,9 +16,10 @@
 package cmd
 
 import (
+	"errors"
 	"fmt"
 	"os"
-	"path"
+	"path/filepath"
 
 	"github.com/ksonnet/ksonnet/metadata"
 	"github.com/ksonnet/ksonnet/pkg/kubecfg"
@@ -26,6 +27,10 @@ import (
 	"github.com/spf13/cobra"
 )
 
+const (
+	flagInitDir = "dir"
+)
+
 func init() {
 	RootCmd.AddCommand(initCmd)
 	// TODO: We need to make this default to checking the `kubeconfig` file.
@@ -33,6 +38,7 @@ func init() {
 		"Manually specify API version from OpenAPI schema, cluster, or Kubernetes version")
 
 	bindClientGoFlags(initCmd)
+	initCmd.Flags().String(flagInitDir, "", "Ksonnet application directory")
 }
 
 var initCmd = &cobra.Command{
@@ -45,11 +51,22 @@ var initCmd = &cobra.Command{
 		}
 
 		appName := args[0]
-		appDir, err := os.Getwd()
+		wd, err := os.Getwd()
+		if err != nil {
+			return err
+		}
+
+		initDir, err := flags.GetString(flagInitDir)
+		if err != nil {
+			return err
+		}
+
+		path, err := genKsRoot(appName, wd, initDir)
 		if err != nil {
 			return err
 		}
-		appRoot := metadata.AbsPath(path.Join(appDir, appName))
+
+		appRoot := metadata.AbsPath(path)
 
 		specFlag, err := flags.GetString(flagAPISpec)
 		if err != nil {
@@ -120,5 +137,29 @@ ks init app-name --api-spec=version:v1.7.1
 
 # Initialize a ksonnet application, using the OpenAPI spec generated by a
 # specific build of Kubernetes to generate 'ksonnet-lib'.
-ks init app-name --api-spec=file:swagger.json`,
+ks init app-name --api-spec=file:swagger.json
+
+# Initialize a ksonnet application, using a custom location for the application
+# directory.
+ks init app-name --dir=custom-location`,
+}
+
+func genKsRoot(appName, ksDir, wd string) (string, error) {
+	if ksDir == "" {
+		return "", errors.New("invalid working directory")
+	}
+
+	if appName == "" && wd == "" {
+		return "", errors.New("invalid application name")
+	}
+
+	if wd != "" {
+		if filepath.IsAbs(wd) {
+			return wd, nil
+		}
+
+		return filepath.Abs(filepath.Join(ksDir, wd))
+	}
+
+	return filepath.Join(ksDir, appName), nil
 }
diff --git a/cmd/init_test.go b/cmd/init_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..228e6b69672c9aefa25e5bb7d23da50db0a8ae8e
--- /dev/null
+++ b/cmd/init_test.go
@@ -0,0 +1,37 @@
+package cmd
+
+import "testing"
+
+func Test_genKsRoot(t *testing.T) {
+	cases := []struct {
+		name     string
+		appName  string
+		ksDir    string
+		wd       string
+		expected string
+		isErr    bool
+	}{
+		{name: "no wd", appName: "app", ksDir: "/root", expected: "/root/app"},
+		{name: "with abs wd", appName: "app", ksDir: "/root", wd: "/custom", expected: "/custom"},
+		{name: "with rel wd #1", appName: "app", ksDir: "/root", wd: "./custom", expected: "/root/custom"},
+		{name: "with rel wd #2", appName: "app", ksDir: "/root", wd: "custom", expected: "/root/custom"},
+		{name: "with rel wd #2", appName: "app", ksDir: "/root", wd: "../custom", expected: "/custom"},
+		{name: "missing ksDir", appName: "app", wd: "./custom", isErr: true},
+		{name: "missing appName and wd", ksDir: "/root", isErr: true},
+	}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			got, err := genKsRoot(tc.appName, tc.ksDir, tc.wd)
+			if tc.isErr {
+				if err == nil {
+					t.Errorf("genKsRoot expected error, but none was received")
+				}
+			} else {
+				if got != tc.expected {
+					t.Errorf("genKsRoot got %q; expected %q", got, tc.expected)
+				}
+			}
+		})
+	}
+}
diff --git a/docs/cli-reference/ks_init.md b/docs/cli-reference/ks_init.md
index 9be0796d5838b89aed7434c12c9f6e500344ae9d..3f1a2597b6f7e9404dc8fdc72ba947300c354a81 100644
--- a/docs/cli-reference/ks_init.md
+++ b/docs/cli-reference/ks_init.md
@@ -36,7 +36,7 @@ of the current context specified in `$KUBECONFIG`.
 
 
 ```
-ks init <app-name>
+ks init <app-name> [flags]
 ```
 
 ### Examples
@@ -65,6 +65,10 @@ ks init app-name --api-spec=version:v1.7.1
 # Initialize a ksonnet application, using the OpenAPI spec generated by a
 # specific build of Kubernetes to generate 'ksonnet-lib'.
 ks init app-name --api-spec=file:swagger.json
+
+# Initialize a ksonnet application, using a custom location for the application
+# directory.
+ks init app-name --dir=custom-location
 ```
 
 ### Options
@@ -77,6 +81,7 @@ ks init app-name --api-spec=file:swagger.json
       --client-key string              Path to a client key file for TLS
       --cluster string                 The name of the kubeconfig cluster to use
       --context string                 The name of the kubeconfig context to use
+      --dir string                     Ksonnet application directory
       --insecure-skip-tls-verify       If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
       --kubeconfig string              Path to a kube config. Only required if out-of-cluster
   -n, --namespace string               If present, the namespace scope for this CLI request