Make the remote features optional
diff --git a/README.md b/README.md
index 16d017b..76e1071 100644
--- a/README.md
+++ b/README.md
@@ -201,6 +201,11 @@
 
 
 ### Remote Key/Value Store Support
+
+To enable remote support in Viper, do a blank import of the `viper/remote` package:
+
+`import _ github.com/spf13/viper/remote`
+
 Viper will read a config string (as JSON, TOML, or YAML) retrieved from a
 path in a Key/Value store such as Etcd or Consul.  These values take precedence
 over default values, but are overriden by configuration values retrieved from disk,
diff --git a/remote/remote.go b/remote/remote.go
new file mode 100644
index 0000000..faaf3b3
--- /dev/null
+++ b/remote/remote.go
@@ -0,0 +1,77 @@
+// Copyright © 2015 Steve Francia <spf@spf13.com>.
+//
+// Use of this source code is governed by an MIT-style
+// license that can be found in the LICENSE file.
+
+// Package remote integrates the remote features of Viper.
+package remote
+
+import (
+	"bytes"
+	"github.com/spf13/viper"
+	crypt "github.com/xordataexchange/crypt/config"
+	"io"
+	"os"
+)
+
+type remoteConfigProvider struct{}
+
+func (rc remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
+	cm, err := getConfigManager(rp)
+	if err != nil {
+		return nil, err
+	}
+	b, err := cm.Get(rp.Path())
+	if err != nil {
+		return nil, err
+	}
+	return bytes.NewReader(b), nil
+}
+
+func (rc remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
+	cm, err := getConfigManager(rp)
+	if err != nil {
+		return nil, err
+	}
+	resp := <-cm.Watch(rp.Path(), nil)
+	err = resp.Error
+	if err != nil {
+		return nil, err
+	}
+
+	return bytes.NewReader(resp.Value), nil
+}
+
+func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
+
+	var cm crypt.ConfigManager
+	var err error
+
+	if rp.SecretKeyring() != "" {
+		kr, err := os.Open(rp.SecretKeyring())
+		defer kr.Close()
+		if err != nil {
+			return nil, err
+		}
+		if rp.Provider() == "etcd" {
+			cm, err = crypt.NewEtcdConfigManager([]string{rp.Endpoint()}, kr)
+		} else {
+			cm, err = crypt.NewConsulConfigManager([]string{rp.Endpoint()}, kr)
+		}
+	} else {
+		if rp.Provider() == "etcd" {
+			cm, err = crypt.NewStandardEtcdConfigManager([]string{rp.Endpoint()})
+		} else {
+			cm, err = crypt.NewStandardConsulConfigManager([]string{rp.Endpoint()})
+		}
+	}
+	if err != nil {
+		return nil, err
+	}
+	return cm, nil
+
+}
+
+func init() {
+	viper.RemoteConfig = &remoteConfigProvider{}
+}
diff --git a/viper.go b/viper.go
index 11f3a77..799983f 100644
--- a/viper.go
+++ b/viper.go
@@ -35,7 +35,6 @@
 	"github.com/spf13/cast"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/pflag"
-	crypt "github.com/xordataexchange/crypt/config"
 )
 
 var v *Viper
@@ -44,6 +43,14 @@
 	v = New()
 }
 
+type remoteConfigFactory interface {
+	Get(rp RemoteProvider) (io.Reader, error)
+	Watch(rp RemoteProvider) (io.Reader, error)
+}
+
+// RemoteConfig is optional, see the remote package
+var RemoteConfig remoteConfigFactory
+
 // Denotes encountering an unsupported
 // configuration filetype.
 type UnsupportedConfigError string
@@ -115,7 +122,7 @@
 	configPaths []string
 
 	// A set of remote providers to search for the configuration
-	remoteProviders []*remoteProvider
+	remoteProviders []*defaultRemoteProvider
 
 	// Name of file to look for inside the path
 	configName string
@@ -160,17 +167,40 @@
 	SupportedRemoteProviders = []string{"etcd", "consul"}
 }
 
-// remoteProvider stores the configuration necessary
-// to connect to a remote key/value store.
-// Optional secretKeyring to unencrypt encrypted values
-// can be provided.
-type remoteProvider struct {
+type defaultRemoteProvider struct {
 	provider      string
 	endpoint      string
 	path          string
 	secretKeyring string
 }
 
+func (rp defaultRemoteProvider) Provider() string {
+	return rp.provider
+}
+
+func (rp defaultRemoteProvider) Endpoint() string {
+	return rp.endpoint
+}
+
+func (rp defaultRemoteProvider) Path() string {
+	return rp.path
+}
+
+func (rp defaultRemoteProvider) SecretKeyring() string {
+	return rp.secretKeyring
+}
+
+// RemoteProvider stores the configuration necessary
+// to connect to a remote key/value store.
+// Optional secretKeyring to unencrypt encrypted values
+// can be provided.
+type RemoteProvider interface {
+	Provider() string
+	Endpoint() string
+	Path() string
+	SecretKeyring() string
+}
+
 // Universally supported extensions.
 var SupportedExts []string = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop"}
 
@@ -252,7 +282,7 @@
 	}
 	if provider != "" && endpoint != "" {
 		jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
-		rp := &remoteProvider{
+		rp := &defaultRemoteProvider{
 			endpoint: endpoint,
 			provider: provider,
 			path:     path,
@@ -284,7 +314,7 @@
 	}
 	if provider != "" && endpoint != "" {
 		jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
-		rp := &remoteProvider{
+		rp := &defaultRemoteProvider{
 			endpoint: endpoint,
 			provider: provider,
 			path:     path,
@@ -296,7 +326,7 @@
 	return nil
 }
 
-func (v *Viper) providerPathExists(p *remoteProvider) bool {
+func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
 	for _, y := range v.remoteProviders {
 		if reflect.DeepEqual(y, p) {
 			return true
@@ -759,6 +789,10 @@
 
 // retrieve the first found remote configuration
 func (v *Viper) getKeyValueConfig() error {
+	if RemoteConfig == nil {
+		return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
+	}
+
 	for _, rp := range v.remoteProviders {
 		val, err := v.getRemoteConfig(rp)
 		if err != nil {
@@ -770,36 +804,12 @@
 	return RemoteConfigError("No Files Found")
 }
 
-func (v *Viper) getRemoteConfig(provider *remoteProvider) (map[string]interface{}, error) {
-	var cm crypt.ConfigManager
-	var err error
+func (v *Viper) getRemoteConfig(provider *defaultRemoteProvider) (map[string]interface{}, error) {
 
-	if provider.secretKeyring != "" {
-		kr, err := os.Open(provider.secretKeyring)
-		defer kr.Close()
-		if err != nil {
-			return nil, err
-		}
-		if provider.provider == "etcd" {
-			cm, err = crypt.NewEtcdConfigManager([]string{provider.endpoint}, kr)
-		} else {
-			cm, err = crypt.NewConsulConfigManager([]string{provider.endpoint}, kr)
-		}
-	} else {
-		if provider.provider == "etcd" {
-			cm, err = crypt.NewStandardEtcdConfigManager([]string{provider.endpoint})
-		} else {
-			cm, err = crypt.NewStandardConsulConfigManager([]string{provider.endpoint})
-		}
-	}
+	reader, err := RemoteConfig.Get(provider)
 	if err != nil {
 		return nil, err
 	}
-	b, err := cm.Get(provider.path)
-	if err != nil {
-		return nil, err
-	}
-	reader := bytes.NewReader(b)
 	v.marshalReader(reader, v.kvstore)
 	return v.kvstore, err
 }
@@ -817,39 +827,11 @@
 	return RemoteConfigError("No Files Found")
 }
 
-func (v *Viper) watchRemoteConfig(provider *remoteProvider) (map[string]interface{}, error) {
-	var cm crypt.ConfigManager
-	var err error
-
-	if provider.secretKeyring != "" {
-		kr, err := os.Open(provider.secretKeyring)
-		defer kr.Close()
-		if err != nil {
-			return nil, err
-		}
-		if provider.provider == "etcd" {
-			cm, err = crypt.NewEtcdConfigManager([]string{provider.endpoint}, kr)
-		} else {
-			cm, err = crypt.NewConsulConfigManager([]string{provider.endpoint}, kr)
-		}
-	} else {
-		if provider.provider == "etcd" {
-			cm, err = crypt.NewStandardEtcdConfigManager([]string{provider.endpoint})
-		} else {
-			cm, err = crypt.NewStandardConsulConfigManager([]string{provider.endpoint})
-		}
-	}
+func (v *Viper) watchRemoteConfig(provider *defaultRemoteProvider) (map[string]interface{}, error) {
+	reader, err := RemoteConfig.Watch(provider)
 	if err != nil {
 		return nil, err
 	}
-	resp := <-cm.Watch(provider.path, nil)
-	// b, err := cm.Watch(provider.path, nil)
-	err = resp.Error
-	if err != nil {
-		return nil, err
-	}
-
-	reader := bytes.NewReader(resp.Value)
 	v.marshalReader(reader, v.kvstore)
 	return v.kvstore, err
 }