diff --git a/guix/channels.scm b/guix/channels.scm
index aca8302ba0d0048a9e30922ebe338742f94de701..f0174de7674e89e146a8a0e9fc4e93cba3ca99bb 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -347,6 +347,21 @@ (define* (guile-for-source source #:optional (quirks %quirks))
       (((predicate . guile) rest ...)
        (if (predicate source) (guile) (loop rest))))))
 
+(define (call-with-guile guile thunk)
+  (lambda (store)
+    (values (parameterize ((%guile-for-build
+                            (if guile
+                                (package-derivation store guile)
+                                (%guile-for-build))))
+              (run-with-store store (thunk)))
+            store)))
+
+(define-syntax-rule (with-guile guile exp ...)
+  "Set GUILE as the '%guile-for-build' parameter for the dynamic extent of
+EXP, a series of monadic expressions."
+  (call-with-guile guile (lambda ()
+                           (mbegin %store-monad exp ...))))
+
 (define (with-trivial-build-handler mvalue)
   "Run MVALUE, a monadic value, with a \"trivial\" build handler installed
 that unconditionally resumes the continuation."
@@ -385,10 +400,7 @@ (define script
         ;; Note: BUILD can return #f if it does not support %PULL-VERSION.  In
         ;; the future we'll fall back to a previous version of the protocol
         ;; when that happens.
-        (mbegin %store-monad
-          (mwhen guile
-            (set-guile-for-build guile))
-
+        (with-guile guile
           ;; BUILD is usually quite costly.  Install a "trivial" build handler
           ;; so we don't bounce an outer build-accumulator handler that could
           ;; cause us to redo half of the BUILD computation several times just
@@ -750,3 +762,7 @@ (define* (channel-news-for-commit channel new #:optional old)
       (if (= GIT_ENOTFOUND (git-error-code error))
           '()
           (apply throw key error rest)))))
+
+;;; Local Variables:
+;;; eval: (put 'with-guile 'scheme-indent-function 1)
+;;; End: