diff --git a/cmd/root.go b/cmd/root.go
index ca20065bb3a48590dda2bb2e9c0b8f83a72778cc..7b8c20364a576eb80ba05e29ef2ebe08b32f9989 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -311,8 +311,8 @@ func expandEnvCmdObjs(cmd *cobra.Command, args []string) ([]*unstructured.Unstru
 			return nil, err
 		}
 
-		libPath, vendorLibPath := manager.LibPaths()
-		expander.FlagJpath = append([]string{string(libPath), string(vendorLibPath)}, expander.FlagJpath...)
+		libPath, envLibPath := manager.LibPaths(*env)
+		expander.FlagJpath = append([]string{string(libPath), string(envLibPath)}, expander.FlagJpath...)
 
 		fileNames, err = manager.ComponentPaths()
 		if err != nil {
diff --git a/metadata/interface.go b/metadata/interface.go
index 5c81943b69a4432399f4241d8698f09344b84778..f18e1d5a5f0a83e7a0400cf670eaf7ce0c741a2a 100644
--- a/metadata/interface.go
+++ b/metadata/interface.go
@@ -20,7 +20,7 @@ type AbsPaths []string
 type Manager interface {
 	Root() AbsPath
 	ComponentPaths() (AbsPaths, error)
-	LibPaths() (libPath, vendorLibPath AbsPath)
+	LibPaths(envName string) (libPath, envLibPath AbsPath)
 	//
 	// TODO: Fill in methods as we need them.
 	//
diff --git a/metadata/manager.go b/metadata/manager.go
index 5da4157709e3ce4ec0f2024d0424c0acf4f89f15..b0809b4d7d00c6b02570158ceb6ee05d812fbfd0 100644
--- a/metadata/manager.go
+++ b/metadata/manager.go
@@ -18,29 +18,29 @@ func appendToAbsPath(originalPath AbsPath, toAppend ...string) AbsPath {
 }
 
 const (
-	defaultEnvName = "dev"
+	ksonnetDir      = ".ksonnet"
+	libDir          = "lib"
+	componentsDir   = "components"
+	environmentsDir = "environments"
+	vendorDir       = "vendor"
 
-	ksonnetDir    = ".ksonnet"
-	libDir        = "lib"
-	componentsDir = "components"
-	vendorDir     = "vendor"
-	schemaDir     = "vendor/schema"
-	vendorLibDir  = "vendor/lib"
+	defaultEnvName = "default"
 
+	// Environment-specific files
 	schemaFilename         = "swagger.json"
 	ksonnetLibCoreFilename = "k8s.libsonnet"
+	specFilename           = "spec.json"
 )
 
 type manager struct {
 	appFS afero.Fs
 
-	rootPath       AbsPath
-	ksonnetPath    AbsPath
-	libPath        AbsPath
-	componentsPath AbsPath
-	vendorDir      AbsPath
-	schemaDir      AbsPath
-	vendorLibDir   AbsPath
+	rootPath        AbsPath
+	ksonnetPath     AbsPath
+	libPath         AbsPath
+	componentsPath  AbsPath
+	environmentsDir AbsPath
+	vendorDir       AbsPath
 }
 
 func findManager(abs AbsPath, appFS afero.Fs) (*manager, error) {
@@ -66,13 +66,6 @@ func findManager(abs AbsPath, appFS afero.Fs) (*manager, error) {
 }
 
 func initManager(rootPath AbsPath, spec ClusterSpec, appFS afero.Fs) (*manager, error) {
-	//
-	// IMPLEMENTATION NOTE: We get the cluster specification and generate
-	// ksonnet-lib before initializing the directory structure so that failure of
-	// either (e.g., GET'ing the spec from a live cluster returns 404) does not
-	// result in a partially-initialized directory structure.
-	//
-
 	// Get cluster specification data, possibly from the network.
 	specData, err := spec.data()
 	if err != nil {
@@ -82,7 +75,13 @@ func initManager(rootPath AbsPath, spec ClusterSpec, appFS afero.Fs) (*manager,
 	m := newManager(rootPath, appFS)
 
 	// Generate the program text for ksonnet-lib.
-	ksonnetLibDir := appendToAbsPath(m.schemaDir, defaultEnvName)
+	//
+	// IMPLEMENTATION NOTE: We get the cluster specification and generate
+	// ksonnet-lib before initializing the directory structure so that failure of
+	// either (e.g., GET'ing the spec from a live cluster returns 404) does not
+	// result in a partially-initialized directory structure.
+	//
+	ksonnetLibDir := appendToAbsPath(m.environmentsDir, defaultEnvName)
 	ksonnetLibData, err := generateKsonnetLibData(ksonnetLibDir, specData)
 	if err != nil {
 		return nil, err
@@ -94,13 +93,7 @@ func initManager(rootPath AbsPath, spec ClusterSpec, appFS afero.Fs) (*manager,
 	}
 
 	// Cache specification data.
-	if err = m.cacheClusterSpecData(defaultEnvName, specData); err != nil {
-		return nil, err
-	}
-
-	ksonnetLibPath := appendToAbsPath(ksonnetLibDir, ksonnetLibCoreFilename)
-	err = afero.WriteFile(appFS, string(ksonnetLibPath), ksonnetLibData, 0644)
-	if err != nil {
+	if err = m.createEnvironment(defaultEnvName, specData, ksonnetLibData); err != nil {
 		return nil, err
 	}
 
@@ -111,13 +104,12 @@ func newManager(rootPath AbsPath, appFS afero.Fs) *manager {
 	return &manager{
 		appFS: appFS,
 
-		rootPath:       rootPath,
-		ksonnetPath:    appendToAbsPath(rootPath, ksonnetDir),
-		libPath:        appendToAbsPath(rootPath, libDir),
-		componentsPath: appendToAbsPath(rootPath, componentsDir),
-		vendorDir:      appendToAbsPath(rootPath, vendorDir),
-		schemaDir:      appendToAbsPath(rootPath, schemaDir),
-		vendorLibDir:   appendToAbsPath(rootPath, vendorLibDir),
+		rootPath:        rootPath,
+		ksonnetPath:     appendToAbsPath(rootPath, ksonnetDir),
+		libPath:         appendToAbsPath(rootPath, libDir),
+		componentsPath:  appendToAbsPath(rootPath, componentsDir),
+		environmentsDir: appendToAbsPath(rootPath, environmentsDir),
+		vendorDir:       appendToAbsPath(rootPath, vendorDir),
 	}
 }
 
@@ -144,19 +136,26 @@ func (m *manager) ComponentPaths() (AbsPaths, error) {
 	return paths, nil
 }
 
-func (m *manager) LibPaths() (libPath, vendorLibPath AbsPath) {
-	return m.libPath, m.vendorLibDir
+func (m *manager) LibPaths(envName string) (libPath, envLibPath AbsPath) {
+	return m.libPath, appendToAbsPath(m.environmentsDir, envName)
 }
 
-func (m *manager) cacheClusterSpecData(name string, specData []byte) error {
-	envPath := string(appendToAbsPath(m.schemaDir, name))
-	err := m.appFS.MkdirAll(envPath, os.ModePerm)
+func (m *manager) createEnvironment(name string, specData, ksonnetLibData []byte) error {
+	envPath := appendToAbsPath(m.environmentsDir, name)
+	err := m.appFS.MkdirAll(string(envPath), os.ModePerm)
+	if err != nil {
+		return err
+	}
+
+	// Generate the schema file.
+	schemaPath := appendToAbsPath(envPath, schemaFilename)
+	err = afero.WriteFile(m.appFS, string(schemaPath), specData, os.ModePerm)
 	if err != nil {
 		return err
 	}
 
-	schemaPath := string(filepath.Join(envPath, schemaFilename))
-	err = afero.WriteFile(m.appFS, schemaPath, specData, os.ModePerm)
+	ksonnetLibPath := appendToAbsPath(envPath, ksonnetLibCoreFilename)
+	err = afero.WriteFile(m.appFS, string(ksonnetLibPath), ksonnetLibData, 0644)
 	return err
 }
 
@@ -174,8 +173,6 @@ func (m *manager) createAppDirTree() error {
 		m.libPath,
 		m.componentsPath,
 		m.vendorDir,
-		m.schemaDir,
-		m.vendorLibDir,
 	}
 
 	for _, p := range paths {
diff --git a/metadata/manager_test.go b/metadata/manager_test.go
index 1e591ac85ce206ee7ad320c63868d20986e56c14..d88ed7e4150c8fdcf9b61dfc076b1ac670b2955e 100644
--- a/metadata/manager_test.go
+++ b/metadata/manager_test.go
@@ -50,14 +50,13 @@ func TestInitSuccess(t *testing.T) {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
 
-	defaultEnvDir := appendToAbsPath(schemaDir, defaultEnvName)
+	defaultEnvDir := appendToAbsPath(environmentsDir, defaultEnvName)
 	paths := []AbsPath{
 		ksonnetDir,
 		libDir,
 		componentsDir,
+		environmentsDir,
 		vendorDir,
-		schemaDir,
-		vendorLibDir,
 		defaultEnvDir,
 	}