diff --git a/init.fish b/init.fish
index 8e61a00d867103af8b001ad3d7cbc8cd6babaa5b..abb5568da4123bfd412efc3860bcc07d7f746b76 100644
--- a/init.fish
+++ b/init.fish
@@ -7,17 +7,11 @@ end
 # Source custom before.init.fish file
 source $OMF_CONFIG/before.init.fish ^/dev/null
 
-# Autoload framework structure, keeping user function path as first
-set fish_function_path $fish_function_path[1] \
-                       $OMF_CONFIG/functions  \
-                       $OMF_PATH/{lib,git}    \
-                       $fish_function_path[2..-1]
-
 # Read current theme
 read -l theme < $OMF_CONFIG/theme
 
 # Prepare Oh My Fish paths
-set -l omf_function_path {$OMF_CONFIG,$OMF_PATH}/{themes*/$theme/{,functions},pkg/*/{,functions}}
+set -l omf_function_path {$OMF_CONFIG,$OMF_PATH}/{themes*/$theme/{,functions},pkg/*/{,functions},functions,lib,lib/git}
 set -l omf_complete_path {$OMF_CONFIG,$OMF_PATH}/{themes*/$theme/completions,pkg/*/completions}
 
 # Autoload functions
@@ -30,16 +24,7 @@ set fish_complete_path $fish_complete_path[1] \
                        $omf_complete_path     \
                        $fish_complete_path[2..-1]
 
-for init in {$OMF_CONFIG,$OMF_PATH}/{pkg/*/init.fish}
-  begin
-    source $init >/dev/null ^&1
-
-    set -l IFS '/'
-    echo $init | read -la components
-
-    emit init_$components[-2] (printf '/%s' $components[1..-2])
-  end
-end
+initialize {$OMF_CONFIG,$OMF_PATH}/pkg/*/init.fish
 
 # Source custom init.fish file
 source $OMF_CONFIG/init.fish ^/dev/null
diff --git a/lib/autoload.fish b/lib/autoload.fish
new file mode 100644
index 0000000000000000000000000000000000000000..3432e2da0e95b97dfea14f6990f7c89a5347e81b
--- /dev/null
+++ b/lib/autoload.fish
@@ -0,0 +1,65 @@
+function __autoload_insert
+  set -l function_path
+  set -l complete_path
+
+  for path in $argv
+    not test -d "$path"; and continue
+
+    set -l IFS '/'
+    echo $path | read -la components
+
+    if test "$components[-1]" = completions
+      contains -- $path $fish_complete_path
+        or set complete_path $complete_path $path
+    else
+      contains -- $path $fish_function_path
+        or set function_path $function_path $path
+    end
+  end
+
+  test "$function_path"
+    and set fish_function_path $fish_function_path[1] $function_path $fish_function_path[2..-1]
+  test "$complete_path"
+    and set fish_complete_path $fish_complete_path[1] $complete_path $fish_complete_path[2..-1]
+
+  return 0
+end
+
+function __autoload_erase
+  set -l function_indexes
+  set -l complete_indexes
+
+  for path in $argv
+    set -l IFS '/'
+    echo $path | read -la components
+
+    test "$components[-1]" = completions
+      and set complete_indexes $complete_indexes (contains -i $path $fish_complete_path)
+      or  set function_indexes $function_indexes (contains -i $path $fish_function_path)
+  end
+
+  test -n "$function_indexes"
+    and set -e fish_function_path[$function_indexes]
+  test -n "$complete_indexes"
+    and set -e fish_complete_path[$complete_indexes]
+
+  return 0
+end
+
+function autoload
+  set -l paths $argv
+
+  switch "$argv[1]"
+  case '-e' '--erase'
+    test (count $argv) -ge 2
+      and __autoload_erase $argv[2..-1]
+      or echo "usage: autoload $argv[1] <path>..." 1>&2
+  case "-*" "--*"
+    echo "autoload: invalid option $argv[1]"
+    return 1
+  case '*'
+    test (count $argv) -ge 1
+      and __autoload_insert $argv
+      or echo "usage: autoload <path>..." 1>&2
+  end
+end
diff --git a/lib/available.fish b/lib/available.fish
new file mode 100644
index 0000000000000000000000000000000000000000..191673bfbbb3a43f2566af46f0a4b500db0e2dbb
--- /dev/null
+++ b/lib/available.fish
@@ -0,0 +1,3 @@
+function available -a name -d "Check if argument a function or command"
+  type -q "$name"
+end
diff --git a/lib/initialize.fish b/lib/initialize.fish
new file mode 100644
index 0000000000000000000000000000000000000000..68799ca9742ce92ce737de1375e963d723fb0652
--- /dev/null
+++ b/lib/initialize.fish
@@ -0,0 +1,20 @@
+function initialize -d "Initialize a package"
+  for init in $argv
+    set -l IFS '/'
+    echo $init | read -la components
+
+    set package $components[-2]
+    set path (printf '/%s' $components[1..-2])
+    set bundle $path/bundle
+
+    if test -f $bundle
+      while read -l type dependency
+        test "$type" = package
+          and require "$dependency"
+      end < $bundle
+    end
+
+    source $init $path
+    emit init_$package $path
+  end
+end
diff --git a/lib/reload.fish b/lib/reload.fish
new file mode 100644
index 0000000000000000000000000000000000000000..e229b905b85cfc4c14e62850a45747eb83be1605
--- /dev/null
+++ b/lib/reload.fish
@@ -0,0 +1,10 @@
+function reload -d "Reload fish process via exec"
+  set -q CI; and return 0
+
+  set -gx dirprev $dirprev
+  set -gx dirnext $dirnext
+  set -gx dirstack $dirstack
+  set -gx fish_greeting ''
+  history --save
+  exec fish
+end
diff --git a/lib/require.fish b/lib/require.fish
new file mode 100644
index 0000000000000000000000000000000000000000..21a99e69012d67762d95ff7b3c502d5f2feade6c
--- /dev/null
+++ b/lib/require.fish
@@ -0,0 +1,32 @@
+function require
+  set packages $argv
+
+  # Skip if plugin has already been loaded.
+  for package in $packages
+    if contains -- $package $omf_packages_loaded
+      set index (contains -i -- $package $packages)
+      set -e packages[$index]
+    end
+  end
+
+  set function_path {$OMF_PATH,$OMF_CONFIG}/pkg*/$packages{,/functions}
+  set completion_path {$OMF_PATH,$OMF_CONFIG}/pkg*/$packages/completions
+
+  # Autoload functions
+  test "$function_path"
+    and set fish_function_path $fish_function_path[1] \
+                               $function_path \
+                               $fish_function_path[2..-1]
+
+  # Autoload completions
+  test "$complete_path"
+    and set fish_complete_path $fish_complete_path[1] \
+                               $complete_path \
+                               $fish_complete_path[2..-1]
+
+  initialize {$OMF_CONFIG,$OMF_PATH}/pkg*/$packages/init.fish
+
+  set -g omf_packages_loaded $packages $omf_packages_loaded
+
+  return 0
+end