diff --git a/config.sh b/config.sh
new file mode 100755
index 0000000000000000000000000000000000000000..1f3bf1fc05b4346515ac641ccb92a4ab2eae4125
--- /dev/null
+++ b/config.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash -e
+
+# Configuration
+export TARGET=x86_64-unknown-redox
+
+# Automatic variables
+ROOT="$(cd `dirname "$0"` && pwd)"
+REPO="$ROOT/repo/$TARGET"
+export CC="$ROOT/libc-artifacts/gcc.sh"
diff --git a/cook.sh b/cook.sh
index 646ae2d61e8e2344843ccd440f1ae413f6cfbe6b..1cc2e47af13b570f77f6f3387eba277e7e6ec297 100755
--- a/cook.sh
+++ b/cook.sh
@@ -1,19 +1,11 @@
-#!/usr/bin/env bash
+#!/usr/bin/env bash -e
 
-# Configuration
-export TARGET=x86_64-unknown-redox
-
-# Automatic variables
-ROOT="$(cd `dirname "$0"` && pwd)"
-REPO="$ROOT/repo/$TARGET"
-export CC="$ROOT/libc-artifacts/gcc.sh"
+source config.sh
 
 # Variables to be overriden by recipes
 export BINDIR=bin
 export CARGOFLAGS=
 
-set -e
-
 function usage {
     echo "cook.sh $1 <op>" >&2
     echo "  dist" >&2
@@ -22,6 +14,8 @@ function usage {
     echo "  clean" >&2
     echo "  fetch" >&2
     echo "  unfetch" >&2
+    echo "  prepare" >&2
+    echo "  unprepare" >&2
     echo "  publish" >&2
     echo "  unpublish" >&2
     echo "  stage" >&2
@@ -40,7 +34,7 @@ function op {
 
     case "$2" in
         dist)
-            op $1 fetch
+            op $1 prepare
             op $1 update
             op $1 build
             op $1 stage
@@ -49,7 +43,7 @@ function op {
         distclean)
             op $1 untar
             op $1 unstage
-            op $1 unfetch
+            op $1 unprepare
             ;;
         fetch)
             if [ -n "$TAR" ]
@@ -64,9 +58,6 @@ function op {
                     mkdir source
                     tar xvf source.tar -C source --strip-components 1
                 fi
-
-                rm -rf build
-                cp -r source build
             elif [ -n "$GIT" ]
             then
                 if [ ! -d source ]
@@ -79,19 +70,22 @@ function op {
                 git submodule sync
                 git submodule update --init --recursive
                 popd > /dev/null
-
-                rm -rf build
-                cp -r source build
             fi
-
             ;;
         unfetch)
-            rm -rfv build source
+            rm -rfv source
             if [ -n "$TAR" ]
             then
                 rm -f source.tar
             fi
             ;;
+        prepare)
+            rm -rf build
+            cp -r source build
+            ;;
+        unprepare)
+            rm -rf build
+            ;;
         version)
             pushd build > /dev/null
             skip="0"
@@ -135,7 +129,7 @@ function op {
             fi
             if [ "$skip" -eq "0" ]
             then
-                cp -r "$ROOT/Xargo.toml" "$ROOT/.cargo" "$ROOT/libc-artifacts" .
+                cp -r "$ROOT/Xargo.toml" .
                 xargo build --target "$TARGET" --release $CARGOFLAGS
             fi
             popd > /dev/null
@@ -149,7 +143,7 @@ function op {
             fi
             if [ "$skip" -eq "0" ]
             then
-                cp -r "$ROOT/Xargo.toml" "$ROOT/.cargo" "$ROOT/libc-artifacts" .
+                cp -r "$ROOT/Xargo.toml" .
                 xargo test --no-run --target "$TARGET" --release $CARGOFLAGS
             fi
             popd > /dev/null
@@ -222,24 +216,7 @@ function op {
 
 if [ -n "$1" ]
 then
-    if [ "$1" = "repo" ]
-    then
-        if [ ! "$COOK_QUIET" = "1" ]
-        then
-            echo -e "\033[01;38;5;215mcook - repo\033[0m" >&2
-        fi
-
-        echo "[packages]" > "$REPO/repo.toml"
-        for toml in "$REPO/"*".toml"
-        do
-            package="$(basename "$toml" .toml)"
-            if [ "$package" != "repo" ]
-            then
-                version="$(grep version "$toml" | cut -d '=' -f2-)"
-                echo "$package =$version" >> "$REPO/repo.toml"
-            fi
-        done
-    elif [ -d "$ROOT/recipes/$1" ]
+    if [ -d "$ROOT/recipes/$1" ]
     then
         cd "$ROOT/recipes/$1"
         source recipe.sh
diff --git a/fetch.sh b/fetch.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b73edf9fc4eb18f1386623b5b4f3f28286ec9c52
--- /dev/null
+++ b/fetch.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash -e
+
+source config.sh
+
+if [ $# = 0 ]
+then
+    recipes="$(ls -1 recipes)"
+else
+    recipes="$@"
+fi
+
+for recipe in $recipes
+do
+    ./cook.sh "$recipe" fetch
+done
diff --git a/recipes/contain/recipe.sh b/recipes/contain/recipe.sh
new file mode 100644
index 0000000000000000000000000000000000000000..60d7e75dfc3af5cbcec20f38b07c44fbdd0458e0
--- /dev/null
+++ b/recipes/contain/recipe.sh
@@ -0,0 +1 @@
+GIT=https://github.com/redox-os/contain.git
diff --git a/recipes/drivers/Cargo.toml b/recipes/drivers/Cargo.toml
deleted file mode 100644
index 4b13eaf7863f2b145077173f6c0c8e5897691804..0000000000000000000000000000000000000000
--- a/recipes/drivers/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[workspace]
-members = [
-    "ahcid",
-    "alxd",
-    "bgad",
-    "e1000d",
-    "nvmed",
-    "pcid",
-    "ps2d",
-    "rtl8168d",
-    "vboxd",
-    "vesad",
-    "xhcid"
-]
diff --git a/recipes/drivers/recipe.sh b/recipes/drivers/recipe.sh
index c4648ebadef0605a8547f8b6478861e993358f15..cdbba51c31a0520517c663b11a8d8ce1fc99eed1 100644
--- a/recipes/drivers/recipe.sh
+++ b/recipes/drivers/recipe.sh
@@ -1,7 +1,12 @@
-GIT=https://github.com/redox-os/drivers
+GIT=https://github.com/redox-os/drivers.git
 CARGOFLAGS=--all
-BINDIR="/sbin"
 
-function recipe_update {
-    cp ../Cargo.toml ./
+function recipe_version {
+    echo "0.1.1"
+    return 1
+}
+
+function recipe_stage {
+    mkdir -pv "$1/etc"
+    cp -v pcid.toml "$1/etc/pcid.toml"
 }
diff --git a/recipes/installer/recipe.sh b/recipes/installer/recipe.sh
new file mode 100644
index 0000000000000000000000000000000000000000..398e4f022dadea7c6867ba7397caff1a883fd45d
--- /dev/null
+++ b/recipes/installer/recipe.sh
@@ -0,0 +1 @@
+GIT=https://github.com/redox-os/installer.git
diff --git a/recipes/netstack/recipe.sh b/recipes/netstack/recipe.sh
new file mode 100644
index 0000000000000000000000000000000000000000..190f9487c6ab8b987f80841e7f5326367d5bffbb
--- /dev/null
+++ b/recipes/netstack/recipe.sh
@@ -0,0 +1 @@
+GIT=https://github.com/redox-os/netstack.git
diff --git a/recipes/orbital/recipe.sh b/recipes/orbital/recipe.sh
index d823bef79c70c19cd97e11d1af8b3d239d3ee897..be4992a37e6512db0527083e4245000110181bb6 100644
--- a/recipes/orbital/recipe.sh
+++ b/recipes/orbital/recipe.sh
@@ -1,2 +1 @@
 GIT=https://github.com/redox-os/orbital.git
-BINDIR="/sbin"
diff --git a/recipes/ptyd/recipe.sh b/recipes/ptyd/recipe.sh
new file mode 100644
index 0000000000000000000000000000000000000000..a3c336ef1b37464c347f6c7b088026bfd0f90369
--- /dev/null
+++ b/recipes/ptyd/recipe.sh
@@ -0,0 +1 @@
+GIT=https://github.com/redox-os/ptyd.git
diff --git a/recipes/randd/recipe.sh b/recipes/randd/recipe.sh
new file mode 100644
index 0000000000000000000000000000000000000000..29f1ef75bcac94cdeedc84b4682f8e93cb30bedf
--- /dev/null
+++ b/recipes/randd/recipe.sh
@@ -0,0 +1 @@
+GIT=https://github.com/redox-os/randd.git
diff --git a/recipes/redoxfs/recipe.sh b/recipes/redoxfs/recipe.sh
new file mode 100644
index 0000000000000000000000000000000000000000..9b8b0406e82973ad67f101035d049a69f5d3412d
--- /dev/null
+++ b/recipes/redoxfs/recipe.sh
@@ -0,0 +1 @@
+GIT=https://github.com/redox-os/redoxfs.git
diff --git a/repo.sh b/repo.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f5bc33fe8213c3fe80a1248d330833a524a3ab09
--- /dev/null
+++ b/repo.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash -e
+
+source config.sh
+
+if [ $# = 0 ]
+then
+    recipes="$(ls -1 recipes)"
+else
+    recipes="$@"
+fi
+
+for recipe in $recipes
+do
+    if [ ! -d "recipes/$recipe/source" ]
+    then
+        echo -e "\033[01;38;5;215mrepo - fetching $recipe\033[0m" >&2
+        ./cook.sh "$recipe" fetch
+    fi
+
+    if [ ! -d "recipes/$recipe/build" ]
+    then
+        echo -e "\033[01;38;5;155mrepo - preparing $recipe\033[0m" >&2
+        ./cook.sh "$recipe" prepare
+    else
+        TIME_SOURCE="$(find recipes/$recipe/source -type f -not -path '*/.git*' -printf "%Ts\n" | sort -nr | head -n 1)"
+        TIME_BUILD="$(find recipes/$recipe/build -type f -not -path '*/.git*' -printf "%Ts\n" | sort -nr | head -n 1)"
+        if [ "$TIME_SOURCE" -gt "$TIME_BUILD" ]
+        then
+            echo -e "\033[01;38;5;155mrepo - repreparing $recipe\033[0m" >&2
+            ./cook.sh "$recipe" unprepare prepare
+        fi
+    fi
+
+    if [ ! -f "recipes/$recipe/stage.tar" ]
+    then
+        echo -e "\033[01;38;5;155mrepo - building $recipe\033[0m" >&2
+        ./cook.sh "$recipe" update build stage tar
+    else
+        TIME_BUILD="$(find recipes/$recipe/build -type f -not -path '*/.git*' -printf "%Ts\n" | sort -nr | head -n 1)"
+        TIME_STAGE="$(stat -c "%Y" recipes/$recipe/stage.tar)"
+        if [ "$TIME_BUILD" -gt "$TIME_STAGE" ]
+        then
+            echo -e "\033[01;38;5;155mrepo - rebuilding $recipe\033[0m" >&2
+            ./cook.sh "$recipe" untar unstage update build stage tar
+        else
+            echo -e "\033[01;38;5;155mrepo - $recipe up to date\033[0m" >&2
+        fi
+    fi
+done
+
+for recipe in $recipes
+do
+    if [ "recipes/$recipe/stage.tar" -nt "$REPO/$recipe.tar" ]
+    then
+        echo -e "\033[01;38;5;155mrepo - publishing $recipe\033[0m" >&2
+        ./cook.sh $recipe publish
+    fi
+done
+
+echo -e "\033[01;38;5;155mrepo - generating repo.toml\033[0m" >&2
+
+echo "[packages]" > "$REPO/repo.toml"
+for toml in "$REPO/"*".toml"
+do
+    package="$(basename "$toml" .toml)"
+    if [ "$package" != "repo" ]
+    then
+        version="$(grep version "$toml" | cut -d '=' -f2-)"
+        echo "$package =$version" >> "$REPO/repo.toml"
+    fi
+done
diff --git a/update-packages.sh b/update-packages.sh
deleted file mode 100755
index 2374038dbb8b81e1d79cfbd4e591a17194e2f479..0000000000000000000000000000000000000000
--- a/update-packages.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-if [ $# = 0 ]
-then
-    recipes=$(ls -1 recipes)
-else
-    recipes=$@
-fi
-
-publish=""
-for recipe in $recipes
-do
-    if [ ! -f "recipes/$recipe/stage.tar" ]
-    then
-        echo "$recipe: building..."
-        ./cook.sh $recipe dist
-        publish="${publish} $recipe"
-    else
-        oldver=$(COOK_QUIET=1 ./cook.sh $recipe gitversion)
-        ./cook.sh $recipe fetch
-        newver=$(COOK_QUIET=1 ./cook.sh $recipe gitversion)
-        if [ "$oldver" = "$newver" ]
-        then
-            echo "$recipe: up to date (version $newver)."
-        else
-            echo "$recipe: updating $oldver -> $newver..."
-            ./cook.sh $recipe unstage untar dist
-            publish="${publish} $recipe"
-        fi
-    fi
-done
-
-for recipe in $publish
-do
-    ./cook.sh $recipe publish
-done
-
-./cook.sh repo