diff --git a/goaljobs.ml b/goaljobs.ml
index bb7141abadc9907a1dfd5dd95642505acfcbcaef..6875ca591929eeb2380593110606adac5f17f781 100644
--- a/goaljobs.ml
+++ b/goaljobs.ml
@@ -391,6 +391,11 @@ let goal_file_exists filename =
     let msg = sprintf "file '%s' required but not found" filename in
     goal_failed msg
   )
+let goal_directory_exists path =
+  if not (directory_exists path) then (
+    let msg = sprintf "directory '%s' required but not found" path in
+    goal_failed msg
+  )
 let goal_file_newer_than f1 f2 =
   if not (file_newer_than f1 f2) then (
     let msg = sprintf "file %s is required to be newer than %s" f1 f2 in
diff --git a/goaljobs.mli b/goaljobs.mli
index a265dff35c09accc7e5f750075ccf04fb0be9b10..043782665e608d48ae6cff1f203fc925ee4399c2 100644
--- a/goaljobs.mli
+++ b/goaljobs.mli
@@ -200,6 +200,11 @@ val file_exists : string -> bool
       {v require (file_exists "somefile");}
       will die unless ["somefile"] exists. *)
 
+val directory_exists : string -> bool
+  (** Return true if the named directory exists.
+
+      There is also a goal version of this function. *)
+
 val file_newer_than : string -> string -> bool
   (** [file_newer_than file_a file_b] returns true if [file_a] is
       newer than [file_b].  Note that if [file_a] does not exist, it
@@ -451,6 +456,7 @@ val publish : string -> (string list -> unit) -> unit
  * if the predicate returns false.
  *)
 val goal_file_exists : string -> unit
+val goal_directory_exists : string -> unit
 val goal_file_newer_than : string -> string -> unit
 val goal_more_recent : string list -> string list -> unit
 val goal_url_exists : string -> unit