diff --git a/IPython/core/magics/execution.py b/IPython/core/magics/execution.py
index ccc1a2b..2ea9ab1 100644
--- a/IPython/core/magics/execution.py
+++ b/IPython/core/magics/execution.py
@@ -293,8 +293,21 @@ python-profiler package from non-free.""")
         self.shell.call_pdb = new_pdb
         print 'Automatic pdb calling has been turned',on_off(new_pdb)
 
-    @line_magic
-    def debug(self, parameter_s=''):
+    @skip_doctest
+    @magic_arguments.magic_arguments()
+    @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
+        help="""
+        Set break point at LINE in FILE.
+        """
+    )
+    @magic_arguments.argument('statement', nargs='*',
+        help="""
+        Code to run in debugger.
+        You can omit this in cell magic mode.
+        """
+    )
+    @line_cell_magic
+    def debug(self, line='', cell=None):
         """Activate the interactive debugger in post-mortem mode.
 
         If an exception has just occurred, this lets you inspect its stack
@@ -306,8 +319,27 @@ python-profiler package from non-free.""")
         If you want IPython to automatically do this on every exception, see
         the %pdb magic for more details.
         """
+        args = magic_arguments.parse_argstring(self.debug, line)
+
+        if not (args.breakpoint or args.statement or cell):
+            self._debug_post_mortem()
+        else:
+            code = "\n".join(args.statement)
+            if cell:
+                code += "\n" + cell
+            self._debug_exec(code, args.breakpoint)
+
+    def _debug_post_mortem(self):
         self.shell.debugger(force=True)
 
+    def _debug_exec(self, code, breakpoint):
+        if breakpoint:
+            (filename, bp_line) = breakpoint.split(':', 1)
+            bp_line = int(bp_line)
+        else:
+            (filename, bp_line) = (None, None)
+        self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
+
     @line_magic
     def tb(self, s):
         """Print the last traceback with the currently active exception mode.
@@ -560,8 +592,10 @@ python-profiler package from non-free.""")
                     stats = self._run_with_profiler(code, opts, code_ns)
                 else:
                     if 'd' in opts:
+                        bp_file, bp_line = parse_breakpoint(
+                            opts.get('b', ['1'])[0], filename)
                         self._run_with_debugger(
-                            code, code_ns, opts.get('b', ['1'])[0], filename)
+                            code, code_ns, filename, bp_line, bp_file)
                     else:
                         if 'm' in opts:
                             def run():
@@ -629,7 +663,8 @@ python-profiler package from non-free.""")
 
         return stats
 
-    def _run_with_debugger(self, code, code_ns, break_point, filename):
+    def _run_with_debugger(self, code, code_ns, filename=None,
+                           bp_line=None, bp_file=None):
         """
         Run `code` in debugger with a break point.
 
@@ -639,19 +674,18 @@ python-profiler package from non-free.""")
             Code to execute.
         code_ns : dict
             A namespace in which `code` is executed.
-        break_point : str
-            Line number in the file specified by `filename` argument
-            or a string in the format ``file:line``.  In the latter
-            case, `filename` is ignored.
-            See also :func:`.parse_breakpoint`.
         filename : str
+            `code` is ran as if it is in `filename`.
+        bp_line : int, optional
+            Line number of the break point.
+        bp_file : str, optional
             Path to the file in which break point is specified.
+            `filename` is used if not given.
 
         Raises
         ------
         UsageError
-            If no meaningful break point is given by `break_point` and
-            `filename`.
+            If the break point given by `bp_line` is not valid.
 
         """
         deb = debugger.Pdb(self.shell.colors)
@@ -660,34 +694,37 @@ python-profiler package from non-free.""")
         bdb.Breakpoint.next = 1
         bdb.Breakpoint.bplist = {}
         bdb.Breakpoint.bpbynumber = [None]
-        # Set an initial breakpoint to stop execution
-        maxtries = 10
-        bp_file, bp_line = parse_breakpoint(break_point, filename)
-        checkline = deb.checkline(bp_file, bp_line)
-        if not checkline:
-            for bp in range(bp_line + 1, bp_line + maxtries + 1):
-                if deb.checkline(bp_file, bp):
-                    break
-            else:
-                msg = ("\nI failed to find a valid line to set "
-                       "a breakpoint\n"
-                       "after trying up to line: %s.\n"
-                       "Please set a valid breakpoint manually "
-                       "with the -b option." % bp)
-                raise UsageError(msg)
-        # if we find a good linenumber, set the breakpoint
-        deb.do_break('%s:%s' % (bp_file, bp_line))
-
-        # Mimic Pdb._runscript(...)
-        deb._wait_for_mainpyfile = True
-        deb.mainpyfile = deb.canonic(filename)
+        if bp_line is not None:
+            # Set an initial breakpoint to stop execution
+            maxtries = 10
+            bp_file = bp_file or filename
+            checkline = deb.checkline(bp_file, bp_line)
+            if not checkline:
+                for bp in range(bp_line + 1, bp_line + maxtries + 1):
+                    if deb.checkline(bp_file, bp):
+                        break
+                else:
+                    msg = ("\nI failed to find a valid line to set "
+                           "a breakpoint\n"
+                           "after trying up to line: %s.\n"
+                           "Please set a valid breakpoint manually "
+                           "with the -b option." % bp)
+                    raise UsageError(msg)
+            # if we find a good linenumber, set the breakpoint
+            deb.do_break('%s:%s' % (bp_file, bp_line))
+
+        if filename:
+            # Mimic Pdb._runscript(...)
+            deb._wait_for_mainpyfile = True
+            deb.mainpyfile = deb.canonic(filename)
 
         # Start file run
         print "NOTE: Enter 'c' at the",
         print "%s prompt to start your script." % deb.prompt
         try:
-            #save filename so it can be used by methods on the deb object
-            deb._exec_filename = filename
+            if filename:
+                # save filename so it can be used by methods on the deb object
+                deb._exec_filename = filename
             deb.run(code, code_ns)
 
         except: