diff --git a/Cargo.lock b/Cargo.lock
index 6a39a6d1c86121372b4537bce9646a8359c119ba..dae3c0336561fc5f0e10c72d6d4dc81cdb1b937a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -68,6 +68,12 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "anyhow"
+version = "1.0.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
+
 [[package]]
 name = "arg_parser"
 version = "0.1.0"
@@ -1213,6 +1219,7 @@ dependencies = [
 name = "redox_cookbook"
 version = "0.1.0"
 dependencies = [
+ "anyhow",
  "blake3 1.5.0",
  "pbr",
  "pkgar",
diff --git a/clean.sh b/clean.sh
index d0b85abc22b9656cd310575426f4ee77ea52e734..7aba7ca853cfde37cb36134d2e610ae09b014d22 100755
--- a/clean.sh
+++ b/clean.sh
@@ -10,7 +10,7 @@ else
     recipes="$@"
 fi
 
-for recipe in $recipes
+for recipe_path in $recipes
 do
-    ./cook.sh "$recipe" distclean
+    ./cook.sh "$recipe_path" distclean
 done
diff --git a/cook.sh b/cook.sh
index de9bb1194350d2c8cfd4663e8ed0308e3b2c8f2f..22445a048cf4b88ab673a70abd007f20c1252dfc 100755
--- a/cook.sh
+++ b/cook.sh
@@ -365,7 +365,14 @@ function op {
 
 if [ -n "$1" ]
 then
-    recipe_path=`target/release/find_recipe $1`
+    if (echo "$1" | grep '.*/.*' >/dev/null); then
+        recipe_name=$(basename "$1")
+        recipe_path="recipes/$1"
+    else
+        recipe_name="$1"
+        recipe_path=`target/release/find_recipe $recipe_name`
+    fi
+
     if [ -d "$ROOT/$recipe_path" ]
     then
         export COOKBOOK_RECIPE="${ROOT}/$recipe_path"
@@ -402,10 +409,10 @@ then
 
         for i in "${ops[@]}"
         do
-            op "$1" "$i"
+            op "$recipe_name" "$i"
         done
     else
-        echo "cook.sh: recipe '$1' not found" >&2
+        echo "cook.sh: recipe '$recipe_name' at not found" >&2
         exit 1
     fi
 else
diff --git a/fetch.sh b/fetch.sh
index 1c5c57a8d82e5a9cfbbf75364a9143ce7c54676a..b83caa6e964cdffc3ddb8aa51ce27f3801fcccb0 100755
--- a/fetch.sh
+++ b/fetch.sh
@@ -10,14 +10,12 @@ else
     recipes="$@"
 fi
 
-for recipe in $recipes
+for recipe_path in $recipes
 do
-    recipe_path=`target/release/find_recipe $recipe`
     if [ -e "$recipe_path/recipe.toml" ]
     then
-        target/release/cook --fetch-only "$recipe"
-        continue
+        target/release/cook --fetch-only "$recipe_path"
+    else
+        ./cook.sh "$recipe_path" fetch
     fi
-
-    ./cook.sh "$recipe" fetch
 done
diff --git a/src/bin/list_recipes.rs b/src/bin/list_recipes.rs
index 759dbc9ec3b992064fbd472dc95ac2e18f044876..95264c9dc45d9e44c12fc0f2bb4521e6e297bc22 100644
--- a/src/bin/list_recipes.rs
+++ b/src/bin/list_recipes.rs
@@ -4,7 +4,9 @@ use std::process::exit;
 // use clap::Parser;
 
 fn main() {
-    let result = list_recipes( Path::new("recipes"));
+    let print_short = std::env::args().nth(1).map_or(false, |a| a == "-s" || a == "--short");
+
+    let result = list_recipes( Path::new("recipes"), Default::default());
 
     match result {
         Ok(result) => {
@@ -12,7 +14,17 @@ fn main() {
                 eprintln!("recipes not found");
                 exit(1);
             } else {
-                result.iter().for_each(|recipe| println!("{recipe}"));
+                for path in result {
+                    let Some(file_name) = path.file_name() else {
+                        continue;
+                    };
+
+                    if print_short {
+                        println!("{}", file_name.to_string_lossy());
+                    } else {
+                        println!("{}", path.to_string_lossy());
+                    }
+                }
                 exit(0);
             }
         }
diff --git a/src/recipe_find.rs b/src/recipe_find.rs
index 1cb551696acbcb03318e2022b185dd8a96df61dc..8354264e096e6c1d40a7322fb61d3c751220bec0 100644
--- a/src/recipe_find.rs
+++ b/src/recipe_find.rs
@@ -45,8 +45,8 @@ pub fn recipe_find(recipe: &str, dir: &Path) -> Result<Option<PathBuf>, String>
     Ok(recipe_path)
 }
 
-pub fn list_recipes(dir: &Path) -> Result<Vec<String>, String> {
-    let mut recipes = Vec::<String>::new();
+pub fn list_recipes(dir: &Path, prefix: PathBuf) -> Result<Vec<PathBuf>, String> {
+    let mut recipes = Vec::<PathBuf>::new();
     if !dir.is_dir() {
         return Ok(recipes);
     }
@@ -55,7 +55,7 @@ pub fn list_recipes(dir: &Path) -> Result<Vec<String>, String> {
         if entry.file_name() == OsStr::new("recipe.sh")
             || entry.file_name() == OsStr::new("recipe.toml")
         {
-            recipes.push(dir.file_name().ok_or(format!("could not unwrap the filename for {:?}", dir))?.to_string_lossy().to_string());
+            recipes.push(prefix);
             return Ok(recipes);
         }
     }
@@ -65,7 +65,12 @@ pub fn list_recipes(dir: &Path) -> Result<Vec<String>, String> {
         if !entry.file_type().map_err(|e| e.to_string())?.is_dir() {
             continue;
         }
-        let mut found = list_recipes(entry.path().as_path())?;
+        let name = entry.file_name();
+        let Some(name) = name.to_str() else {
+            eprintln!("invalid UTF-8 for entry {entry:?}");
+            continue;
+        };
+        let mut found = list_recipes(entry.path().as_path(), prefix.join(name))?;
         recipes.append(&mut found);
     }
     recipes.sort();
diff --git a/unfetch.sh b/unfetch.sh
index b6877cc3084510925f7d96a2e1da7b80113692d0..eb73178c371f0d9dc7da75d6e43f5d4fede697a4 100755
--- a/unfetch.sh
+++ b/unfetch.sh
@@ -10,7 +10,7 @@ else
     recipes="$@"
 fi
 
-for recipe in $recipes
+for recipe_path in $recipes
 do
-    ./cook.sh "$recipe" unfetch
+    ./cook.sh "$recipe_path" unfetch
 done