diff --git a/.gitignore b/.gitignore
index 415827699a816be282558e67a59ea2bb4764ca56..2d48bdff473f5b0fa7a30d13ac759dc5b9477f79 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
 custom/*
+plugins/*
+themes/*
 
 .DS_Store
 *.pyc
diff --git a/README.md b/README.md
index f1b8c8a2b332766b00e4e284855fcb41aff49608..a840e344dde4fa067763797fcadd922e040d137a 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
 |
 <b><a href="#usage">Usage</a></b>
 |
-<b><a href="#send-us-your-theme">Contribute</a></b>
+<b><a href="#contributing">Contributing</a></b>
 |
 <b><a href="#uninstall">Uninstall</a></b>
 |
@@ -52,9 +52,7 @@ If you want to install it manually, [keep reading](#manual-installation).
 
 ## Usage
 
-Enabling a new plugin or theme is as easy as it should be. Open your fish configuration file `~/.config/fish/config.fish` and specify the theme and the plugins you want to use.
-
-As an example, to enable rails and git-flow plugins add this line `set fish_plugins git-flow rails` to your configuration file.
+Open your fish configuration file `~/.config/fish/config.fish` and specify the theme and the plugins you want to use. And then run `fish install` on your terminal to install them.
 
 Before setting down on a theme, you might want to have a go with all themes using our quick [theme switcher](https://github.com/bpinto/oh-my-fish/blob/master/plugins/theme/README.md) by typing `theme --help` on your shell.
 
@@ -63,21 +61,15 @@ Before setting down on a theme, you might want to have a go with all themes usin
 If you have many functions which go well together, you can create custom plugin in the `custom/plugins/PLUGIN_NAME`
 directory and add to it as many functions as you want.
 
-If you would like to override the functionality of a plugin distributed with oh-my-fish,
-create a plugin of the same name in the `custom/plugins/` directory and it will be loaded
-instead of the one shipped with oh-my-fish.
-
 If you would like to use your custom theme, move it with the same name in the `custom/themes/` directory
 and it will override the original theme in `themes/`.
 
 If you just want to override any of the default behavior or add some environment variables,
 just add a new file (ending in .load) into the `custom/` directory.
 
-## Send us your theme!
-
-We are hoping to collect a bunch of themes for our command prompts. You can see existing ones in the [themes](themes/) directory.
+## Contributing
 
-> __Note__: Theme authors, make sure to include a screenshot in your pull request.
+Create an [issue](https://github.com/bpinto/oh-my-fish/issues) linking to your repository and we will move it to the [oh-my-fish](https://github.com/oh-my-fish) organization.
 
 ### Manual installation
 
diff --git a/functions/Plugin.fish b/functions/Plugin.fish
new file mode 100644
index 0000000000000000000000000000000000000000..fcd0513ec2f86525c5d974242a268054cc9e78f4
--- /dev/null
+++ b/functions/Plugin.fish
@@ -0,0 +1,11 @@
+function Plugin --argument-names name
+  set -g fish_plugins $fish_plugins $name
+
+  if [ -e $fish_path/plugins/$name -o -e $fish_custom/plugins/$name ]
+    import plugins/$name
+  else
+    set_color red
+    echo "Plugin '$name' is not installed. Run 'fish install' to download and install it."
+    set_color normal
+  end
+end
diff --git a/functions/Theme.fish b/functions/Theme.fish
new file mode 100644
index 0000000000000000000000000000000000000000..546ea5b0cad5c32b8cc2dfacf0b36d97c127490b
--- /dev/null
+++ b/functions/Theme.fish
@@ -0,0 +1,11 @@
+function Theme --argument-names name
+  set -g fish_theme $name
+
+  if [ -e $fish_path/themes/$name -o -e $fish_custom/themes/$name ]
+    import themes/$name
+  else
+    set_color red
+    echo "Theme '$name' is not installed. Run 'fish install' to download and install it."
+    set_color normal
+  end
+end
diff --git a/functions/_append_path.fish b/functions/_append_path.fish
deleted file mode 100644
index d37e6f3220cfda78a141cc70be1f9f51b9a96fde..0000000000000000000000000000000000000000
--- a/functions/_append_path.fish
+++ /dev/null
@@ -1,19 +0,0 @@
-# Appends the path to the specified path list. If no list specified,
-#  defaults to $PATH
-function _append_path
-  set_color red
-  echo '_append_path function deprecated. Rename to _prepend_path.' >&2
-  set_color normal
-
-  set -l path PATH
-
-  if test (echo $argv | wc -w) -eq 2
-    set path $argv[2]
-  end
-
-  if test -d $argv[1]
-    if not contains $argv[1] $$path
-      set $path $argv[1] $$path
-    end
-  end
-end
diff --git a/functions/fish.fish b/functions/fish.fish
new file mode 100644
index 0000000000000000000000000000000000000000..51791abdfb7464a86311ae0d6e12479d8ef3aca9
--- /dev/null
+++ b/functions/fish.fish
@@ -0,0 +1,20 @@
+# NAME
+#   fish - Extend default fish binary
+#
+# DESCRIPTION
+#   Extend fish binary to support plugins and themes installation
+#
+function fish -d "Extend fish binary"
+  if test (count $argv) -gt 0
+    switch $argv[1]
+      case 'install'
+        fish.packages --install
+      case 'update'
+        fish.packages --update
+      case '*'
+        command fish $argv
+    end
+  else
+    command fish
+  end
+end
diff --git a/functions/fish.log.fish b/functions/fish.log.fish
new file mode 100644
index 0000000000000000000000000000000000000000..55eb3a8892004865c07acf324ff773bc878c5243
--- /dev/null
+++ b/functions/fish.log.fish
@@ -0,0 +1,17 @@
+# NAME
+#   fish.log - simple log with color
+#
+# SYNOPSIS
+#   <string> [<string>...]
+#
+# DESCRIPTION
+#   Simply log a message with a specified color.
+#
+function fish.log -d "Simple log with color"
+  switch $argv[1]
+    case '-*'
+      echo $argv[1] (set_color $argv[2])$argv[3..-1](set_color normal)
+    case '*'
+      echo -e (set_color $argv[1])$argv[2..-1](set_color normal)
+  end
+end
diff --git a/functions/fish.packages.fish b/functions/fish.packages.fish
new file mode 100644
index 0000000000000000000000000000000000000000..857e438961fafb1f0e2e57fc453ed8f23caada81
--- /dev/null
+++ b/functions/fish.packages.fish
@@ -0,0 +1,28 @@
+# NAME
+#   fish.packages - Manage all plugins and themes
+#
+# SYNOPSIS
+#   fish.packages [OPTIONS]
+#
+# OPTIONS
+#   --install
+#     Install all packages
+#   --update
+#     Update all packages
+#
+# DESCRIPTION
+#   Manage all plugins and themes specified on the $fish_plugins
+#   and $fish_theme variables
+#
+function fish.packages --argument-names options -d 'Manage all plugins and themes'
+  set -l modified_packages 0
+
+  switch $options
+    case "--install"
+      fish.packages.install
+    case "--update"
+      fish.packages.update
+    case "*"
+      fish.log red 'Unknown option'
+  end
+end
diff --git a/functions/fish.packages.install.fish b/functions/fish.packages.install.fish
new file mode 100644
index 0000000000000000000000000000000000000000..57830d330100d1a3b8a2e80771895333aa07fc7e
--- /dev/null
+++ b/functions/fish.packages.install.fish
@@ -0,0 +1,36 @@
+# NAME
+#   fish.packages.install - Install all plugins and themes
+#
+# DESCRIPTION
+#   Install all plugins and themes specified on the $fish_plugins
+#   and $fish_theme variables
+#
+function fish.packages.install -d "Install all plugins and themes"
+  set -l installed_packages 0
+
+  # Plugins
+  for plugin in $fish_plugins
+    if [ -e $fish_path/plugins/$plugin -o -e $fish_custom/plugins/$plugin ]
+      #echo "$plugin is already installed. Skipping."
+    else
+      fish.log -n white "Installing $plugin... "
+      git clone "https://github.com/oh-my-fish/plugins-$plugin" $fish_path/plugins/$plugin ^ /dev/null
+      fish.log green  "√"
+      set -l installed_packages 1
+    end
+  end
+
+  # Theme
+  if [ -e $fish_path/themes/$fish_theme -o -e $fish_custom/themes/$fish_theme ]
+    #echo "$fish_theme is already installed. Skipping."
+  else
+    fish.log -n white "Installing $fish_theme... "
+    git clone "https://github.com/oh-my-fish/themes-$fish_theme" $fish_path/themes/$fish_theme ^ /dev/null
+    fish.log green  "√"
+    set -l installed_packages 1
+  end
+
+  if [ $installed_packages -eq 0 ]
+    fish.log green 'All plugins were already installed.'
+  end
+end
diff --git a/functions/fish.packages.update.fish b/functions/fish.packages.update.fish
new file mode 100644
index 0000000000000000000000000000000000000000..513ce465e38bb6baf6487fe22e03c9082efaaf61
--- /dev/null
+++ b/functions/fish.packages.update.fish
@@ -0,0 +1,53 @@
+# NAME
+#   fish.packages.update - Update all plugins and themes
+#
+# DESCRIPTION
+#   Update all plugins and themes specified on the $fish_plugins
+#   and $fish_theme variables
+#
+function fish.packages.update -d "Update all plugins and themes"
+  set -l installed_packages 0
+  pushd
+
+  # Plugins
+  for plugin in $fish_plugins
+    if [ -e $fish_path/plugins/$plugin -a -e $fish_path/plugins/$plugin/.git ]
+      fish.log -n white "Updating $plugin... "
+      echo (cd $fish_path/plugins/$plugin; and git pull --rebase > /dev/null) >/dev/null
+      fish.log green  "√"
+      set -l installed_packages 1
+    else
+      if [ -e $fish_custom/plugins/$plugin -a -e $fish_custom/plugins/$plugin/.git ]
+        fish.log -n white "Updating $plugin... "
+        echo (cd $fish_custom/plugins/$plugin; and git pull --rebase > /dev/null) >/dev/null
+        fish.log green  "√"
+        set -l installed_packages 1
+      else
+        #echo "$plugin is not installed or not a git repo. Skipping."
+      end
+    end
+  end
+
+  # Theme
+  if [ -e $fish_path/themes/$fish_theme -a -e $fish_path/themes/$fish_theme/.git ]
+    fish.log -n white "Updating $fish_theme... "
+    echo (cd $fish_path/themes/$fish_theme; and git pull --rebase > /dev/null) >/dev/null
+    fish.log green  "√"
+    set -l installed_packages 1
+  else
+    if [ -e $fish_custom/themes/$fish_theme -a -e $fish_custom/themes/$fish_theme/.git ]
+      fish.log -n white "Updating $fish_theme... "
+      echo (cd $fish_custom/themes/$fish_theme; and git pull --rebase > /dev/null) >/dev/null
+      fish.log green  "√"
+      set -l installed_packages 1
+    else
+      #echo "$fish_theme is not installed or not a git repo. Skipping."
+    end
+  end
+
+  if [ $installed_packages -eq 0 ]
+    fish.log green 'No plugins to update.'
+  end
+
+  popd
+end
diff --git a/oh-my-fish.fish b/oh-my-fish.fish
index 71058fd040f433964a24ef671ade38b7c818dac9..18f7b9e82a34105495e9f06b3e09e79791952bdf 100644
--- a/oh-my-fish.fish
+++ b/oh-my-fish.fish
@@ -4,17 +4,22 @@ if not set -q fish_custom
   set -g fish_custom $fish_path/custom
 end
 
-# Extract user defined functions from path and prepend later to
-# avoid collisions with oh-my-fish internal functions and allow
-# users to override/customize plugins, themes, etc.
-set user_function_path $fish_function_path[1]
-set -e fish_function_path[1]
-
 # Add functions defined in oh-my-fish/functions to the path.
 if not contains $fish_path/functions/ $fish_function_path
   set fish_function_path $fish_path/functions/ $fish_function_path
 end
 
+if set -q fish_plugins
+  set_color red
+  echo '$fish_plugins usage has been deprecated. Please see https://asciinema.org/a/20802.'
+  set_color normal
+end
+
+if set -q fish_theme
+  set_color red
+  echo '$fish_theme usage has been deprecated. Please see https://asciinema.org/a/20802.'
+  set_color normal
+end
 
 # Add imported plugins, completions and themes. Customize imported
 # commands via the $fish_path/custom directory, for example create
@@ -28,8 +33,5 @@ for load in $fish_custom/*.load
   . $load
 end
 
-# Prepend extracted user functions so they have the highest priority.
-set fish_function_path $user_function_path $fish_function_path
-
 # Make sure to exit with $status of 1 when reloading the framework.
 or true
diff --git a/templates/config.fish b/templates/config.fish
index cf3ac0bea8060a9045fbc136ae333c46e74081a5..9020cb0618a2f57915687144936e432841e92d30 100644
--- a/templates/config.fish
+++ b/templates/config.fish
@@ -1,16 +1,13 @@
 # Path to your oh-my-fish.
 set fish_path $HOME/.oh-my-fish
 
-# Theme
-set fish_theme robbyrussell
-
-# All built-in plugins can be found at ~/.oh-my-fish/plugins/
-# Custom plugins may be added to ~/.oh-my-fish/custom/plugins/
-# Enable plugins by adding their name separated by a space to the line below.
-set fish_plugins theme
-
 # Path to your custom folder (default path is ~/.oh-my-fish/custom)
 #set fish_custom $HOME/dotfiles/oh-my-fish
 
 # Load oh-my-fish configuration.
 . $fish_path/oh-my-fish.fish
+
+# Custom plugins and themes may be added to ~/.oh-my-fish/custom
+# Plugins and themes can be found at https://github.com/oh-my-fish/
+Theme 'robbyrussell'
+Plugin 'theme'