diff --git a/config.sh b/config.sh
new file mode 100755
index 0000000000000000000000000000000000000000..bab886f90be43a99d5d649ebb8b8e9ff6856e48d
--- /dev/null
+++ b/config.sh
@@ -0,0 +1,9 @@
+#!/bin/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 ddc4fbaae17274faf7b317607abeb962e6120e32..f6d5f80bfe54df72551a421e573227c50fa84c41 100755
--- a/cook.sh
+++ b/cook.sh
@@ -1,19 +1,11 @@
-#!/bin/bash
+#!/bin/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
@@ -222,24 +214,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/repo.sh b/repo.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0c94fd7b026496165517e25f39dffc5e9d9c0ef4
--- /dev/null
+++ b/repo.sh
@@ -0,0 +1,57 @@
+#!/bin/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 and updating $recipe\033[0m" >&2
+        ./cook.sh "$recipe" fetch
+    fi
+
+    if [ ! -f "recipes/$recipe/stage.tar" ]
+    then
+        echo -e "\033[01;38;5;215mrepo - building $recipe\033[0m" >&2
+        ./cook.sh $recipe update build stage tar
+    else
+        TIME_SOURCE="$(find recipes/$recipe/source -printf "%Ts\n" | sort -nr | head -n 1)"
+        TIME_STAGE="$(stat -c "%Y" recipes/$recipe/stage.tar)"
+        if [ "$TIME_SOURCE" -ge "$TIME_STAGE" ]
+        then
+            echo -e "\033[01;38;5;215mrepo - rebuilding $recipe\033[0m" >&2
+            ./cook.sh "$recipe" untar unstage update build stage tar
+        else
+            echo -e "\033[01;38;5;215mrepo - $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;215mrepo - publishing $recipe\033[0m" >&2
+        ./cook.sh $recipe publish
+    fi
+done
+
+echo -e "\033[01;38;5;215mrepo - 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 0109dd2343d3757a2ae42cc62d8b9bf8925d28d4..0000000000000000000000000000000000000000
--- a/update-packages.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/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