diff --git a/doc/misc.rst b/doc/misc.rst
index 8acd53e1710ec846ce42033fb114cb3dd717b608..950e27da8412d84cec520687ae9d65e0aa58d819 100644
--- a/doc/misc.rst
+++ b/doc/misc.rst
@@ -39,6 +39,8 @@ and then use the ``%%cl_kernel`` 'cell-magic' command. See `this notebook
 
 You can pass build options to be used for building the program executable by using the ``-o`` flag on the first line of the cell (next to the ``%%cl_kernel`` directive). For example: `%%cl_kernel -o "-cl-fast-relaxed-math"``.
 
+There are also line magics: ``cl_load_edit_kernel`` which will load a file into the next cell (adding ``cl_kernel`` to the first line) and ``cl_kernel_from_file`` which will compile kernels from a file (as if you copy-and-pasted the contents of the file to a cell with ``cl_kernel``). Boths of these magics take options ``-f`` to specify the file and optionally ``-o`` for build options.
+
 .. versionadded:: 2014.1
 
 Guidelines
diff --git a/pyopencl/ipython_ext.py b/pyopencl/ipython_ext.py
index 2d7d42d7c78106490d556bbd5bfb67b8d80decdf..0ceb04f82e3c3b7215901f09519603799628a98d 100644
--- a/pyopencl/ipython_ext.py
+++ b/pyopencl/ipython_ext.py
@@ -1,6 +1,6 @@
 from __future__ import division
 
-from IPython.core.magic import (magics_class, Magics, cell_magic)
+from IPython.core.magic import (magics_class, Magics, cell_magic, line_magic)
 
 import pyopencl as cl
 
@@ -13,8 +13,9 @@ def _try_to_utf8(text):
 
 @magics_class
 class PyOpenCLMagics(Magics):
-    @cell_magic
-    def cl_kernel(self, line, cell):
+    def _run_kernel(self, kernel, options):
+        kernel = _try_to_utf8(kernel)
+        options = _try_to_utf8(options).strip()
         try:
             ctx = self.shell.user_ns["cl_ctx"]
         except KeyError:
@@ -33,13 +34,49 @@ class PyOpenCLMagics(Magics):
             raise RuntimeError("unable to locate cl context, which must be "
                     "present in namespace as 'cl_ctx' or 'ctx'")
 
-        opts, args = self.parse_options(line,'o:')
-        build_options = opts.get('o', '')
-        prg = cl.Program(ctx, _try_to_utf8(cell)).build(options=_try_to_utf8(build_options).strip())
+        prg = cl.Program(ctx, kernel).build(options=options)
 
         for knl in prg.all_kernels():
             self.shell.user_ns[knl.function_name] = knl
 
 
+    @cell_magic
+    def cl_kernel(self, line, cell):
+        kernel = cell
+
+        opts, args = self.parse_options(line,'o:')
+        build_options = opts.get('o', '')
+
+        self._run_kernel(kernel, build_options)
+
+
+    def _load_kernel_and_options(self, line):
+        opts, args = self.parse_options(line,'o:f:')
+
+        build_options = opts.get('o')
+        kernel = self.shell.find_user_code(opts.get('f') or args)
+
+        return kernel, build_options
+
+
+    @line_magic
+    def cl_kernel_from_file(self, line):
+        kernel, build_options = self._load_kernel_and_options(line)
+        self._run_kernel(kernel, build_options)
+
+
+    @line_magic
+    def cl_load_edit_kernel(self, line):
+        kernel, build_options = self._load_kernel_and_options(line)
+        header = "%%cl_kernel"
+
+        if build_options:
+            header = "%s %s" % (header, build_options)
+
+        content = "%s\n\n%s" % (header, kernel)
+
+        self.shell.set_next_input(content)
+
+
 def load_ipython_extension(ip):
     ip.register_magics(PyOpenCLMagics)