diff --git a/src/plugins/wp/Cache.ml b/src/plugins/wp/Cache.ml
index 65da7ca4b528daae67654b0f7d37fdcc9eb24103..74e6c3b7ea8a2dfa30c8537266425371c8b77926 100644
--- a/src/plugins/wp/Cache.ml
+++ b/src/plugins/wp/Cache.ml
@@ -141,22 +141,6 @@ let is_updating () =
   | NoCache | Replay | Offline -> false
   | Update | Rebuild | Cleanup -> true
 
-let task_hash wpo drv prover task =
-  lazy
-    begin
-      let file = Wpo.DISK.file_goal
-          ~pid:wpo.Wpo.po_pid
-          ~model:wpo.Wpo.po_model
-          ~prover:(VCS.Why3 prover) in
-      let _ = Command.print_file file
-          begin fun fmt ->
-            Format.fprintf fmt "(* WP Task for Prover %s *)@\n"
-              (Why3Provers.print_why3 prover) ;
-            Why3.Driver.print_task_prepared drv fmt task ;
-          end
-      in Digest.file file |> Digest.to_hex
-    end
-
 let time_fits time = function
   | None | Some 0 -> true
   | Some limit -> time <= float limit
@@ -256,23 +240,24 @@ let cleanup_cache () =
         Wp_parameters.warning ~current:false
           "Cannot cleanup cache"
 
-type runner =
-  timeout:int option -> steplimit:int option ->
-  Why3.Driver.driver -> Why3Provers.t -> Why3.Task.task ->
+type 'a digest =
+  Why3Provers.t -> 'a -> string
+
+type 'a runner =
+  timeout:int option -> steplimit:int option -> Why3Provers.t -> 'a ->
   VCS.result Task.task
 
-let get_result wpo runner ~timeout ~steplimit drv prover task =
+let get_result ~digest ~runner ~timeout ~steplimit prover goal =
   let mode = get_mode () in
   match mode with
-  | NoCache ->
-      runner ~timeout ~steplimit drv prover task
+  | NoCache -> runner ~timeout ~steplimit prover goal
   | Offline ->
-      let hash = task_hash wpo drv prover task in
+      let hash = lazy (digest prover goal) in
       let result = get_cache_result ~mode hash |> VCS.cached in
       if VCS.is_verdict result then incr hits else incr miss ;
       Task.return result
   | Update | Replay | Rebuild | Cleanup ->
-      let hash = task_hash wpo drv prover task in
+      let hash = lazy (digest prover goal) in
       let result =
         get_cache_result ~mode hash
         |> promote ~timeout ~steplimit |> VCS.cached in
@@ -284,10 +269,12 @@ let get_result wpo runner ~timeout ~steplimit drv prover task =
         end
       else
         Task.finally
-          (runner ~timeout ~steplimit drv prover task)
+          (runner ~timeout ~steplimit prover goal)
           begin function
             | Task.Result result when VCS.is_verdict result ->
                 incr miss ;
                 set_cache_result ~mode hash prover result
             | _ -> ()
           end
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/Cache.mli b/src/plugins/wp/Cache.mli
index 85130ef5bbf06c648b9bd4bd09b4dd50ed1735c9..7197a8dc22207aa1aec096a1a61735d3e43b4bc8 100644
--- a/src/plugins/wp/Cache.mli
+++ b/src/plugins/wp/Cache.mli
@@ -34,9 +34,12 @@ val is_updating : unit -> bool
 
 val cleanup_cache : unit -> unit
 
-type runner =
-  timeout:int option -> steplimit:int option ->
-  Why3.Driver.driver -> Why3Provers.t -> Why3.Task.task ->
+type 'a digest = Why3Provers.t -> 'a -> string
+
+type 'a runner =
+  timeout:int option -> steplimit:int option -> Why3Provers.t -> 'a ->
   VCS.result Task.task
 
-val get_result: Wpo.t -> runner -> runner
+val get_result: digest:('a digest) -> runner:('a runner) -> 'a runner
+
+(**************************************************************************)
diff --git a/src/plugins/wp/Changelog b/src/plugins/wp/Changelog
index 389007c7c917ae9519016a256dd51c427af755ff..51c3938458848eda30cd366caa3eb5ef6a144261 100644
--- a/src/plugins/wp/Changelog
+++ b/src/plugins/wp/Changelog
@@ -24,6 +24,9 @@
 Plugin WP <next-release>
 #########################
 
+- WP          [2020-09-21] Added support for Why3 Coq interactive prover
+- WP          [2020-09-21] New option -wp-interactive <mode>
+- WP          [2020-09-21] New option -wp-interactive-timeout <seconds>
 - WP          [2020-09-17] New experimental option: -wp-check-model-hypotheses
                            Generates requires in contracts for model hypotheses
 - WP          [2020-09-17] Hypotheses: assigned memory locations
diff --git a/src/plugins/wp/GuiNavigator.ml b/src/plugins/wp/GuiNavigator.ml
index a6bfe8c5311134b3378d4ff6fe49ca9145052b34..48b88111f836a747b202dd51c871d2e29484da20 100644
--- a/src/plugins/wp/GuiNavigator.ml
+++ b/src/plugins/wp/GuiNavigator.ml
@@ -263,7 +263,7 @@ class behavior
                 | Some m , _ -> m
                 | None , VCS.NativeCoq -> VCS.EditMode
                 | None , VCS.NativeAltErgo -> VCS.FixMode
-                | _ -> VCS.BatchMode in
+                | _ -> if VCS.is_auto prover then VCS.BatchMode else VCS.FixMode in
               schedule (Prover.prove w ~mode ~result prover) ;
               refresh w
       end
@@ -291,7 +291,8 @@ class behavior
     val popup_tip  = new Widget.popup ()
     val popup_ergo = new Widget.popup ()
     val popup_coq  = new Widget.popup ()
-    val popup_why3 = new Widget.popup ()
+    val popup_why3_auto = new Widget.popup ()
+    val popup_why3_inter = new Widget.popup ()
     val mutable popup_target = None
 
     method private popup_delete () =
@@ -327,8 +328,10 @@ class behavior
         popup_tip#add_item ~label:"Run Script" ~callback:(self#popup_run BatchMode) ;
         popup_tip#add_item ~label:"Edit Proof" ~callback:(self#popup_run EditMode) ;
         popup_tip#add_item ~label:"Delete Script" ~callback:(self#popup_delete_script) ;
-        self#add_popup_proofmodes popup_why3
-          [ "Run",BatchMode ] ;
+        popup_why3_auto#add_item ~label:"Run Prover" ~callback:(self#popup_run VCS.BatchMode) ;
+        popup_why3_inter#add_item ~label:"Check Script" ~callback:(self#popup_run VCS.BatchMode) ;
+        popup_why3_inter#add_item ~label:"Edit Script" ~callback:(self#popup_run VCS.EditMode) ;
+        popup_why3_inter#add_item ~label:"Fixup Script" ~callback:(self#popup_run VCS.FixMode) ;
         self#add_popup_proofmodes popup_ergo
           [ "Run",BatchMode ; "Open Altgr-Ergo on Fail",EditMode ; "Open Altgr-Ergo",EditMode ] ;
         self#add_popup_proofmodes popup_coq
@@ -344,7 +347,10 @@ class behavior
         | Some Qed -> popup_qed#run ()
         | Some NativeCoq -> popup_coq#run ()
         | Some NativeAltErgo -> popup_ergo#run ()
-        | Some (Why3 _) -> popup_why3#run ()
+        | Some (Why3 _ as p) ->
+            if VCS.is_auto p
+            then popup_why3_auto#run ()
+            else popup_why3_inter#run ()
       end
 
     method private action w p =
diff --git a/src/plugins/wp/ProofScript.ml b/src/plugins/wp/ProofScript.ml
index 73c77b5b71d37ffa4fbb17639893672e2e17a7e6..4ad9bd70305c577c20e833482bf6419f7a3cb5b3 100644
--- a/src/plugins/wp/ProofScript.ml
+++ b/src/plugins/wp/ProofScript.ml
@@ -342,7 +342,7 @@ let json_of_result (p : VCS.prover) (r : VCS.result) =
   `Assoc (name :: verdict :: (time @ steps))
 
 let prover_of_json js =
-  try VCS.prover_of_name (js >? "prover" |> Json.string)
+  try VCS.parse_prover (js >? "prover" |> Json.string)
   with Not_found -> None
 
 let result_of_json js =
diff --git a/src/plugins/wp/ProverWhy3.ml b/src/plugins/wp/ProverWhy3.ml
index d19bacb5bd4c9800a65005833298362e9fdc30fd..a4e27a63283ac7f3ed795a1ffe75325fdaf953bd 100644
--- a/src/plugins/wp/ProverWhy3.ml
+++ b/src/plugins/wp/ProverWhy3.ml
@@ -1153,18 +1153,21 @@ let ping_prover_call p =
   match Why3.Call_provers.query_call p.call with
   | NoUpdates
   | ProverStarted ->
-      let () = match p.timeover with
-        | None ->
-            let started = Unix.time () in
-            p.timeover <- Some (started +. 2.0 +. float p.timeout)
-        | Some timeout ->
-            let time = Unix.time () in
-            if time > timeout then
-              begin
-                Wp_parameters.debug ~dkey "Hard Kill (late why3server timeout)" ;
-                p.interrupted <- true ;
-                Why3.Call_provers.interrupt_call p.call ;
-              end
+      let () =
+        if p.timeout > 0 then
+          match p.timeover with
+          | None ->
+              let started = Unix.time () in
+              p.timeover <- Some (started +. 2.0 +. float p.timeout)
+          | Some timeout ->
+              let time = Unix.time () in
+              if time > timeout then
+                begin
+                  Wp_parameters.debug ~dkey
+                    "Hard Kill (late why3server timeout)" ;
+                  p.interrupted <- true ;
+                  Why3.Call_provers.interrupt_call p.call ;
+                end
       in Task.Wait 100
   | InternalFailure exn ->
       let msg = Format.asprintf "@[<hov 2>%a@]"
@@ -1198,34 +1201,11 @@ let ping_prover_call p =
         VCS.pp_result r;
       Task.Return (Task.Result r)
 
-let call_prover prover_config ~timeout ~steplimit drv prover task =
-  let steps = match steplimit with Some 0 -> None | _ -> steplimit in
-  let limit =
-    let def = Why3.Call_provers.empty_limit in
-    { def with
-      Why3.Call_provers.limit_time = Why3.Opt.get_def def.limit_time timeout;
-      Why3.Call_provers.limit_steps = Why3.Opt.get_def def.limit_time steps;
-    } in
-  let with_steps = match steps, prover_config.Why3.Whyconf.command_steps with
-    | None, _ -> false
-    | Some _, Some _ -> true
-    | Some _, None ->
-        Wp_parameters.warning ~once:true ~current:false
-          "%a does not support steps limit (ignored option)"
-          Why3.Whyconf.print_prover prover ;
-        false
-  in
-  let command = Why3.Whyconf.get_complete_command prover_config ~with_steps in
-  let call =
-    Why3.Driver.prove_task_prepared ~command ~limit drv task in
-  let pp_steps fmt s =
-    if with_steps then Format.fprintf fmt "%i steps" (Why3.Opt.get_def (-1) s)
-    else Format.fprintf fmt ""
-  in
-  Wp_parameters.debug ~dkey "Why3 run prover %a with %i timeout %a@."
+let call_prover_task ~timeout ~steps prover call =
+  Wp_parameters.debug ~dkey "Why3 run prover %a with timeout %d, steps %d@."
     Why3.Whyconf.print_prover prover
     (Why3.Opt.get_def (-1) timeout)
-    pp_steps steps ;
+    (Why3.Opt.get_def (-1) steps) ;
   let timeout = match timeout with None -> 0 | Some tlimit -> tlimit in
   let pcall = {
     call ; prover ;
@@ -1242,15 +1222,110 @@ let call_prover prover_config ~timeout ~steplimit drv prover task =
   in
   Task.async ping
 
-let is_trivial (t : Why3.Task.task) =
-  let goal = Why3.Task.task_goal_fmla t in
-  Why3.Term.t_equal goal Why3.Term.t_true
+(* -------------------------------------------------------------------------- *)
+(* --- Batch Prover                                                       --- *)
+(* -------------------------------------------------------------------------- *)
+
+let digest wpo drv prover task =
+  let file = Wpo.DISK.file_goal
+      ~pid:wpo.Wpo.po_pid
+      ~model:wpo.Wpo.po_model
+      ~prover:(VCS.Why3 prover) in
+  let _ = Command.print_file file
+      begin fun fmt ->
+        Format.fprintf fmt "(* WP Task for Prover %s *)@\n"
+          (Why3Provers.print_why3 prover) ;
+        Why3.Driver.print_task_prepared drv fmt task ;
+      end
+  in Digest.file file |> Digest.to_hex
+
+let batch pconf driver ?script ~timeout ~steplimit prover task =
+  let steps = match steplimit with Some 0 -> None | _ -> steplimit in
+  let limit =
+    let def = Why3.Call_provers.empty_limit in
+    { def with
+      Why3.Call_provers.limit_time = Why3.Opt.get_def def.limit_time timeout;
+      Why3.Call_provers.limit_steps = Why3.Opt.get_def def.limit_time steps;
+    } in
+  let with_steps = match steps, pconf.Why3.Whyconf.command_steps with
+    | None, _ -> false
+    | Some _, Some _ -> true
+    | Some _, None -> false
+  in
+  let command = Why3.Whyconf.get_complete_command pconf ~with_steps in
+  let inplace = if script <> None then Some true else None in
+  let call = Why3.Driver.prove_task_prepared ?old:script ?inplace
+      ~command ~limit driver task in
+  call_prover_task ~timeout ~steps prover call
+
+(* -------------------------------------------------------------------------- *)
+(* --- Interactive Prover (Coq)                                           --- *)
+(* -------------------------------------------------------------------------- *)
+
+let editor pconf =
+  let config = Why3Provers.config () in
+  try
+    let ed = Why3.Whyconf.editor_by_id config pconf.Why3.Whyconf.editor in
+    String.concat " " (ed.editor_command :: ed.editor_options)
+  with Not_found ->
+    Why3.Whyconf.(default_editor (get_main config))
+
+let scriptfile ~force ~ext wpo =
+  let dir = Wp_parameters.get_session_dir ~force "interactive" in
+  Format.sprintf "%s/%s%s" (dir :> string) wpo.Wpo.po_sid ext
+
+let call_editor ~script pconf =
+  Wp_parameters.feedback ~ontty:`Transient "Editing %S..." script ;
+  let call = Why3.Call_provers.call_editor ~command:(editor pconf) script in
+  call_prover_task ~timeout:None ~steps:None pconf.prover call
+
+let compile ~script ~timeout pconf driver prover task =
+  let digest _prover _task = Digest.file script |> Digest.to_hex in
+  let runner = batch pconf driver ~script in
+  Cache.get_result ~digest ~runner ~timeout ~steplimit:None prover task
+
+let prepare ~mode wpo driver task =
+  let force = match mode with VCS.BatchMode -> false | _ -> true in
+  let ext = Filename.extension (Why3.Driver.file_of_task driver "S" "T" task) in
+  let script = scriptfile ~force wpo ~ext in
+  if Sys.file_exists script then Some script
+  else if force then
+    begin
+      Command.pp_to_file script (fun fmt ->
+          ignore (Why3.Driver.print_task_prepared driver fmt task)
+        ) ; Some script
+    end
+  else None
+
+let interactive ~mode wpo pconf driver prover task =
+  let time = Wp_parameters.InteractiveTimeout.get () in
+  let timeout = if time <= 0 then None else Some time in
+  match prepare ~mode wpo driver task with
+  | None -> Task.return VCS.unknown
+  | Some script ->
+      match mode with
+      | VCS.BatchMode ->
+          compile ~script ~timeout pconf driver prover task
+      | VCS.EditMode ->
+          let open Task in
+          call_editor ~script pconf >>= fun _ ->
+          compile ~script ~timeout pconf driver prover task
+      | VCS.FixMode ->
+          let open Task in
+          compile ~script ~timeout pconf driver prover task >>= fun r ->
+          if VCS.is_valid r then return r else
+            call_editor ~script pconf >>= fun _ ->
+            compile ~script ~timeout pconf driver prover task
 
 (* -------------------------------------------------------------------------- *)
 (* --- Prove WPO                                                          --- *)
 (* -------------------------------------------------------------------------- *)
 
-let build_proof_task ?timeout ?steplimit ~prover wpo () =
+let is_trivial (t : Why3.Task.task) =
+  let goal = Why3.Task.task_goal_fmla t in
+  Why3.Term.t_equal goal Why3.Term.t_true
+
+let build_proof_task ?(mode=VCS.BatchMode) ?timeout ?steplimit ~prover wpo () =
   try
     (* Always generate common task *)
     let context = Wpo.get_context wpo in
@@ -1259,12 +1334,17 @@ let build_proof_task ?timeout ?steplimit ~prover wpo () =
     then Task.return VCS.no_result (* Only generate *)
     else
       let env = WpContext.on_context context get_why3_env () in
-      let drv , config , task = prover_task env prover task in
+      let drv , pconf , task = prover_task env prover task in
       if is_trivial task then
         Task.return VCS.valid
       else
-        Cache.get_result wpo (call_prover config)
-          ~timeout ~steplimit drv prover task
+      if pconf.interactive then
+        interactive ~mode wpo pconf drv prover task
+      else
+        Cache.get_result
+          ~digest:(digest wpo drv)
+          ~runner:(batch pconf drv ?script:None)
+          ~timeout ~steplimit prover task
   with exn ->
     if Wp_parameters.has_dkey dkey_api then
       Wp_parameters.fatal "[Why3 Error] %a@\n%s"
@@ -1273,7 +1353,7 @@ let build_proof_task ?timeout ?steplimit ~prover wpo () =
     else
       Task.failed "[Why3 Error] %a" Why3.Exn_printer.exn_printer exn
 
-let prove ?timeout ?steplimit ~prover wpo =
-  Task.later (build_proof_task ?timeout ?steplimit ~prover wpo) ()
+let prove ?mode ?timeout ?steplimit ~prover wpo =
+  Task.later (build_proof_task ?mode ?timeout ?steplimit ~prover wpo) ()
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/ProverWhy3.mli b/src/plugins/wp/ProverWhy3.mli
index ea029e0804bc7aba4a8f25d66b18a043dd0804ea..e29b681ff4412f662db152da2af6b14bb9a9d19a 100644
--- a/src/plugins/wp/ProverWhy3.mli
+++ b/src/plugins/wp/ProverWhy3.mli
@@ -26,8 +26,8 @@ val add_specific_equality:
   unit
 (** Equality used in the goal, simpler to prove than polymorphic equality *)
 
-val prove : ?timeout:int -> ?steplimit:int -> prover:Why3Provers.t ->
-  Wpo.t -> VCS.result Task.task
+val prove : ?mode:VCS.mode -> ?timeout:int -> ?steplimit:int ->
+  prover:Why3Provers.t -> Wpo.t -> VCS.result Task.task
 (** Return NoResult if it is already proved by Qed *)
 
 (**************************************************************************)
diff --git a/src/plugins/wp/VCS.ml b/src/plugins/wp/VCS.ml
index 50507c33c3974e967750caf41b168e317e152ccb..2b7862a000d14da1f3699f8021af17af9babe1c9 100644
--- a/src/plugins/wp/VCS.ml
+++ b/src/plugins/wp/VCS.ml
@@ -38,7 +38,7 @@ type mode =
   | EditMode  (* Edit then check scripts *)
   | FixMode   (* Try check script, then edit script on non-success *)
 
-let prover_of_name = function
+let parse_prover = function
   | "" | "none" -> None
   | "qed" | "Qed" -> Some Qed
   | "native-alt-ergo" (* for wp-reports *)
@@ -70,13 +70,19 @@ let prover_of_name = function
             (String.concat ":" prv) (Why3Provers.print_wp p) ;
           Some (Why3 p)
       | NotFound ->
-          Wp_parameters.error "Prover '%s' not found in why3.conf" name ;
+          Wp_parameters.error ~once:true
+            "Prover '%s' not found in why3.conf" name ;
           None
 
-let mode_of_prover_name = function
-  | "native:coqedit" -> EditMode
-  | "native:coqide" | "native:altgr-ergo" -> FixMode
-  | _ -> BatchMode
+let parse_mode m =
+  match String.lowercase_ascii m with
+  | "fix" -> FixMode
+  | "edit" -> EditMode
+  | "batch" -> BatchMode
+  | _ ->
+      Wp_parameters.error ~once:true
+        "Unrecognized mode %S (use 'batch' instead)" m ;
+      BatchMode
 
 let name_of_prover = function
   | Why3 s -> Why3Provers.print_wp s
@@ -122,8 +128,18 @@ let filename_for_prover = function
   | Tactical -> "Tactical"
 
 let is_auto = function
-  | Qed | NativeAltErgo | Why3 _ -> true
+  | Qed | NativeAltErgo -> true
   | Tactical | NativeCoq -> false
+  | Why3 p ->
+      match p.prover_name with
+      | "Alt-Ergo" | "CVC4" | "Z3" -> true
+      | "Coq" -> false
+      | _ ->
+          let config = Why3Provers.config () in
+          try
+            let prover_config = Why3.Whyconf.get_prover_config config p in
+            not prover_config.interactive
+          with Not_found -> true
 
 let cmp_prover p q =
   match p,q with
diff --git a/src/plugins/wp/VCS.mli b/src/plugins/wp/VCS.mli
index 54b34f23ef850f4e974c4a2e18034c035d510ec4..e43bb52617772920bbe7fb93760c1a79ed832273 100644
--- a/src/plugins/wp/VCS.mli
+++ b/src/plugins/wp/VCS.mli
@@ -44,10 +44,11 @@ module Pmap : Map.S with type key = prover
 val name_of_prover : prover -> string
 val title_of_prover : prover -> string
 val filename_for_prover : prover -> string
-val prover_of_name : string -> prover option
-val mode_of_prover_name : string -> mode
 val title_of_mode : mode -> string
 
+val parse_mode : string -> mode
+val parse_prover : string -> prover option
+
 val pp_prover : Format.formatter -> prover -> unit
 val pp_mode : Format.formatter -> mode -> unit
 
diff --git a/src/plugins/wp/Why3Provers.ml b/src/plugins/wp/Why3Provers.ml
index ab50c9858b2de0a3fec9d8adc147994a3e0db981..46a1f714ab5902d7b9356ede7a3a0f879af75a54 100644
--- a/src/plugins/wp/Why3Provers.ml
+++ b/src/plugins/wp/Why3Provers.ml
@@ -109,3 +109,5 @@ let has_shortcut p s =
           (Why3.Whyconf.get_prover_shortcuts (config ())) with
   | None -> false
   | Some p' -> Why3.Whyconf.Prover.equal p p'
+
+(* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/doc/manual/wp.bib b/src/plugins/wp/doc/manual/wp.bib
index bcc4524f29d0569c6fa30a52b475ee1966715b73..cbe190e5609458dda0b3b93767fafdf007fdd7c8 100644
--- a/src/plugins/wp/doc/manual/wp.bib
+++ b/src/plugins/wp/doc/manual/wp.bib
@@ -98,6 +98,39 @@
   url = {http://ergo.lri.fr/papers/ergo.ps}
 }
 
+@inproceedings{CVC4,
+  url       = "http://www.cs.stanford.edu/~barrett/pubs/BCD+11.pdf",
+  author    = "Clark Barrett and Christopher L. Conway and Morgan Deters and
+               Liana Hadarean and Dejan Jovanovi{'{c}} and Tim King and
+               Andrew Reynolds and Cesare Tinelli",
+  title     = "{CVC4}",
+  booktitle = "Proceedings of the 23rd International Conference on Computer Aided Verification (CAV '11)",
+  series    = "Lecture Notes in Computer Science",
+  volume    = 6806,
+  publisher = "Springer",
+  editor    = "Ganesh Gopalakrishnan and Shaz Qadeer",
+  pages     = "171--177",
+  month     = jul,
+  year      = 2011,
+  note      = "Snowbird, Utah",
+  category  = "Conference Publications"
+}
+
+@InProceedings{Z3,
+author="de Moura, Leonardo
+and Bj{\o}rner, Nikolaj",
+editor="Ramakrishnan, C. R.
+and Rehof, Jakob",
+title="Z3: An Efficient SMT Solver",
+booktitle="Tools and Algorithms for the Construction and Analysis of Systems",
+year="2008",
+publisher="Springer Berlin Heidelberg",
+address="Berlin, Heidelberg",
+pages="337--340",
+abstract="Satisfiability Modulo Theories (SMT) problem is a decision problem for logical first order formulas with respect to combinations of background theories such as: arithmetic, bit-vectors, arrays, and uninterpreted functions. Z3 is a new and efficient SMT Solver freely available from Microsoft Research. It is used in various software verification and analysis applications.",
+isbn="978-3-540-78800-3"
+}
+
 @inproceedings{qed,
   author    = {Lo{\"{\i}}c Correnson},
   title     = {Qed. Computing What Remains to Be Proved},
diff --git a/src/plugins/wp/doc/manual/wp_plugin.tex b/src/plugins/wp/doc/manual/wp_plugin.tex
index 3e343ef02f74e318d518694174ef46d0af68f881..a690b944e0e6c4bcf93cee5cb064bdff5e15494c 100644
--- a/src/plugins/wp/doc/manual/wp_plugin.tex
+++ b/src/plugins/wp/doc/manual/wp_plugin.tex
@@ -10,51 +10,13 @@ This plug-in computes proof obligations of programs annotated with
 \textsf{ACSL} annotations by \emph{weakest precondition calculus},
 using a parametrized memory model to represent pointers and heap
 values. The proof obligations may then be discharged by external
-decision procedures, which range over automated theorem provers such
-as \textsf{Alt-Ergo}~\cite{AltErgo2006}, interactive proof assistants
-like \textsf{Coq}~\cite{Coq84} and the interactive proof manager
-\textsf{Why3}~\cite{Why3}.
-
-This chapter describes how to use the plug-in, from the
-\textsf{Frama-C} graphical user interface (section~\ref{wp-gui}), from
-the command line (section~\ref{wp-cmdline}), or from another plug-in
-(section~\ref{wp-api}).  Additionally, the combination of the \textsf{WP}
-plug-in with the load and save commands of \textsf{Frama-C} and/or the
-\texttt{-then} command-line option is explained in section~\ref{wp-persistent}.
-
-\clearpage
-%-----------------------------------------------------------------------------
-\section{Installing Provers}
-\label{wp-install-provers}
-%-----------------------------------------------------------------------------
-
-The \textsf{WP} plug-in requires external provers to work.
-The recommended versions for external provers are:
-\begin{center}
-  \begin{tabular}{crlc}
-    Prover & Versions & Download &\\
-    \hline
-    \textsf{Why3} & \verb|1.3.1| &
-    \url{http://why3.lri.fr} & \cite{Why3}\\
-    \textsf{Alt-Ergo} & \verb|2.0.0|  &
-    \url{http://alt-ergo.ocamlpro.com} & \cite{AltErgo2006}\\
-    % \textsf{Coq} & \verb|8.9.0| &
-    % \url{http://coq.inria.fr} & \cite{Coq84}\\
-  \end{tabular}
-\end{center}
-
-Recent \textsf{OPAM}-provided versions should work smoothly.
-Other versions might be supported as well, typically, as far as we know:
-\begin{itemize}
-\item \textsf{Alt-Ergo} \verb+2.2.0+ and \verb+2.3.0+, although distributed under a non-commercial licence.
-% \item \textsf{Coq} \verb+8.7.2+ and \verb+8.8.2+, although proof scripts compatibility can be an issue.
-\item \textsf{Why3} \verb+1.3.1+.
-\end{itemize}
-
-Other provers, like \textsf{Coq}, \textsf{Gappa}, \textsf{Z3}, \textsf{CVC3},
-\textsf{CVC4}, \textsf{PVS}, and many others, are accessible from
-\textsf{WP} through \textsf{Why3}. We refer the user to the manual of
-\textsf{Why3} to handle specific configuration tasks.
+automated theorem provers such as
+\textsf{Alt-Ergo}~\cite{AltErgo2006},
+\textsf{CVC4}~\cite{CVC4} and
+\textsf{Z3}~\cite{Z3}
+or by interactive proof assistants
+like \textsf{Coq}~\cite{Coq84} and more generally, any automated or interactive
+prover supported by \textsf{Why3}~\cite{Why3}.
 
 \clearpage
 %-----------------------------------------------------------------------------
@@ -1018,6 +980,10 @@ all unproved proof obligations are sent to external decision procedures.
 
 Support for \textsf{Why-3 IDE} is no longer provided.
 
+Since \textsf{Frama-C 22.0} (Titanium) support for Coq interactive prover has
+been added and might also work with other interactive provers.
+See \texttt{-wp-interactive <mode>} option for details.
+
 \begin{description}
 \item[\tt -wp-prover <dp,...>] selects the decision procedures used to
   discharge proof obligations. See below for supported provers.  By
@@ -1028,6 +994,13 @@ Support for \textsf{Why-3 IDE} is no longer provided.
   It is possible to ask for several decision procedures to be tried.
   For each goal, the first decision procedure that succeeds cancels the
   other attempts.
+\item[\tt -wp-interactive <mode>] selects the interaction mode with
+  interactive provers such as Coq. Three modes are available:
+  \texttt{"batch"} mode only check existing scripts (the default);
+  \texttt{"edit"} mode opens the default prover editor on each generated goal;
+  \texttt{"fix"} mode only opens
+  editor for non-proved goals. New scripts are created in the \texttt{interactive}
+  directory of \textsf{WP} session (see option \texttt{-wp-session <dir>}).
 \item[\tt -wp-detect] lists the provers available for \textsf{Why-3}.
   This command can only work if \textsf{why3} API was installed before building and
   installing \textsf{Frama-C}.
@@ -1053,6 +1026,8 @@ Support for \textsf{Why-3 IDE} is no longer provided.
   to the decision prover (defaults to 10 seconds).
 \item[\tt -wp-smoke-timeout <n>] sets the timeout (in seconds) for smoke tests
   (see \verb+-wp-smoke-tests+, defaults to 5 seconds).
+\item[\tt -wp-interactive-timeout <n>] sets the timeout (in seconds) for checking
+  edited scripts with interactive provers (defaults to 30 seconds).
 \item[\tt -wp-time-extra <n>] additional time allocated to provers when
   replaying a script. This is used to cope with variable machine load.
   Default is \verb+5s+.
diff --git a/src/plugins/wp/doc/manual/wp_simplifier.tex b/src/plugins/wp/doc/manual/wp_simplifier.tex
index 4dda147545e9ef5766ef6d3e8696a953e6d3443a..2e3e82551aa4e94a1ab36ac54e667b9e3ff97d0c 100644
--- a/src/plugins/wp/doc/manual/wp_simplifier.tex
+++ b/src/plugins/wp/doc/manual/wp_simplifier.tex
@@ -344,13 +344,3 @@ following heuristic:
 
 Inside the same level of priority, alternatives are kept in their original
 order.
-
-
-
-
-
-
-
-
-
-
diff --git a/src/plugins/wp/prover.ml b/src/plugins/wp/prover.ml
index 08291e8aeea9ec4e9fc2fe1b7f5f2b9be9945853..83b432ac6c284ec2826c9f5c99420d525a7bbcc4 100644
--- a/src/plugins/wp/prover.ml
+++ b/src/plugins/wp/prover.ml
@@ -40,7 +40,7 @@ let dispatch ?(config=VCS.default) mode prover wpo =
         ProverWhy3.prove
           ~timeout:(VCS.get_timeout ~smoke config)
           ~steplimit:(VCS.get_stepout config)
-          ~prover wpo
+          ~mode ~prover wpo
   end
 
 let started ?start wpo =
diff --git a/src/plugins/wp/register.ml b/src/plugins/wp/register.ml
index ed3a27c63af70ad7d6bc876c6d3adbb5c88fd0f9..74a692cf28f452a7040299b9129aa4fca50b15f3 100644
--- a/src/plugins/wp/register.ml
+++ b/src/plugins/wp/register.ml
@@ -551,7 +551,7 @@ let do_list_scheduled_result () =
 (* ---  Proving                                                         --- *)
 (* ------------------------------------------------------------------------ *)
 
-type mode = {
+type script = {
   mutable tactical : bool ;
   mutable update : bool ;
   mutable depth : int ;
@@ -561,24 +561,24 @@ type mode = {
   mutable provers : (VCS.mode * VCS.prover) list ;
 }
 
-let spawn_wp_proofs ~mode goals =
-  if mode.tactical || mode.provers<>[] then
+let spawn_wp_proofs ~script goals =
+  if script.tactical || script.provers<>[] then
     begin
       let server = ProverTask.server () in
       ignore (Wp_parameters.Share.get_dir "."); (* To prevent further errors *)
       Bag.iter
         (fun goal ->
-           if  mode.tactical
+           if  script.tactical
             && not (Wpo.is_trivial goal)
-            && (mode.auto <> [] || ProofSession.exists goal)
+            && (script.auto <> [] || ProofSession.exists goal)
            then
              ProverScript.spawn
                ~failed:false
-               ~auto:mode.auto
-               ~depth:mode.depth
-               ~width:mode.width
-               ~backtrack:mode.backtrack
-               ~provers:(List.map snd mode.provers)
+               ~auto:script.auto
+               ~depth:script.depth
+               ~width:script.width
+               ~backtrack:script.backtrack
+               ~provers:(List.map snd script.provers)
                ~start:do_wpo_start
                ~progress:do_progress
                ~result:do_wpo_result
@@ -591,7 +591,7 @@ let spawn_wp_proofs ~mode goals =
                ~progress:do_progress
                ~result:do_wpo_result
                ~success:do_wpo_success
-               mode.provers
+               script.provers
         ) goals ;
       Task.on_server_wait server do_wpo_wait ;
       Task.launch server
@@ -604,19 +604,20 @@ let env_script_update () =
   try Sys.getenv "FRAMAC_WP_SCRIPT" = "update"
   with Not_found -> false
 
-let compute_provers ~mode =
-  mode.provers <- List.fold_right
-      (fun pname prvs ->
-         match VCS.prover_of_name pname with
-         | None -> prvs
-         | Some VCS.Tactical ->
-             mode.tactical <- true ;
-             if pname = "tip" || env_script_update () then
-               mode.update <- true ;
-             prvs
-         | Some prover ->
-             (VCS.mode_of_prover_name pname , prover) :: prvs)
-      (get_prover_names ()) []
+let compute_provers ~mode ~script =
+  script.provers <- List.fold_right
+      begin fun pname prvs ->
+        match VCS.parse_prover pname with
+        | None -> prvs
+        | Some VCS.Tactical ->
+            script.tactical <- true ;
+            if pname = "tip" || env_script_update () then
+              script.update <- true ;
+            prvs
+        | Some prover ->
+            let pmode = if VCS.is_auto prover then VCS.BatchMode else mode in
+            (pmode , prover) :: prvs
+      end (get_prover_names ()) []
 
 let dump_strategies =
   let once = ref true in
@@ -629,18 +630,18 @@ let dump_strategies =
                  Format.fprintf fmt "@\n  '%s': %s" h#id h#title
                )))
 
-let default_mode () = {
+let default_script_mode () = {
   tactical = false ; update=false ; provers = [] ;
   depth=0 ; width = 0 ; auto=[] ; backtrack = 0 ;
 }
 
-let compute_auto ~mode =
-  mode.auto <- [] ;
-  mode.width <- Wp_parameters.AutoWidth.get () ;
-  mode.depth <- Wp_parameters.AutoDepth.get () ;
-  mode.backtrack <- max 0 (Wp_parameters.BackTrack.get ()) ;
+let compute_auto ~script =
+  script.auto <- [] ;
+  script.width <- Wp_parameters.AutoWidth.get () ;
+  script.depth <- Wp_parameters.AutoDepth.get () ;
+  script.backtrack <- max 0 (Wp_parameters.BackTrack.get ()) ;
   let auto = Wp_parameters.Auto.get () in
-  if mode.depth <= 0 || mode.width <= 0 then
+  if script.depth <= 0 || script.width <= 0 then
     ( if auto <> [] then
         Wp_parameters.feedback
           "Auto-search deactivated because of 0-depth or 0-width" )
@@ -650,17 +651,17 @@ let compute_auto ~mode =
         (fun id ->
            if id = "?" then dump_strategies ()
            else
-             try mode.auto <- Strategy.lookup ~id :: mode.auto
+             try script.auto <- Strategy.lookup ~id :: script.auto
              with Not_found ->
                Wp_parameters.error ~current:false
                  "Strategy -wp-auto '%s' unknown (ignored)." id
         ) auto ;
-      mode.auto <- List.rev mode.auto ;
-      if mode.auto <> [] then mode.tactical <- true ;
+      script.auto <- List.rev script.auto ;
+      if script.auto <> [] then script.tactical <- true ;
     end
 
-let do_update_session mode goals =
-  if mode.update then
+let do_update_session ~script goals =
+  if script.update then
     begin
       let removed = ref 0 in
       let updated = ref 0 in
@@ -714,24 +715,25 @@ let do_update_session mode goals =
     end
 
 let do_wp_proofs ?provers ?tip (goals : Wpo.t Bag.t) =
-  let mode = default_mode () in
-  compute_provers ~mode ;
-  compute_auto ~mode ;
+  let script = default_script_mode () in
+  let mode = VCS.parse_mode (Wp_parameters.Interactive.get ()) in
+  compute_provers ~mode ~script ;
+  compute_auto ~script ;
   begin match provers with None -> () | Some prvs ->
-    mode.provers <- List.map (fun dp -> VCS.BatchMode , VCS.Why3 dp) prvs
+    script.provers <- List.map (fun dp -> VCS.BatchMode , VCS.Why3 dp) prvs
   end ;
   begin match tip with None -> () | Some tip ->
-    mode.tactical <- tip ;
-    mode.update <- tip ;
+    script.tactical <- tip ;
+    script.update <- tip ;
   end ;
-  let spawned = mode.tactical || mode.provers <> [] in
+  let spawned = script.tactical || script.provers <> [] in
   begin
     if spawned then do_list_scheduled goals ;
-    spawn_wp_proofs ~mode goals ;
+    spawn_wp_proofs ~script goals ;
     if spawned then
       begin
         do_list_scheduled_result () ;
-        do_update_session mode goals ;
+        do_update_session ~script goals ;
       end
     else if not (Wp_parameters.Print.get ()) then
       Bag.iter do_wpo_display goals
diff --git a/src/plugins/wp/tests/wp/stmtcompiler_test.ml b/src/plugins/wp/tests/wp/stmtcompiler_test.ml
index 07e77bf23093eb5c0ec694eecf32ac30f6317f15..ab8fd28f71adf5fe5a631056ae2ad39533d5a421 100644
--- a/src/plugins/wp/tests/wp/stmtcompiler_test.ml
+++ b/src/plugins/wp/tests/wp/stmtcompiler_test.ml
@@ -19,10 +19,10 @@ let run () =
 
   let provers =
     List.fold_right
-      (fun pname prvs -> match VCS.prover_of_name pname with
+      (fun pname prvs -> match VCS.parse_prover pname with
          | None -> prvs
          | Some VCS.Tactical -> prvs
-         | Some prv -> (VCS.mode_of_prover_name pname, prv) :: prvs)
+         | Some prv -> (VCS.BatchMode, prv) :: prvs)
       ["qed"] []
   in
 
diff --git a/src/plugins/wp/tests/wp/stmtcompiler_test_rela.ml b/src/plugins/wp/tests/wp/stmtcompiler_test_rela.ml
index f38450c4501df76ed0fdbe6cbebbee247a3431d8..ee5548356cc7a0037c3bc2f56dd2c86f7b62b228 100644
--- a/src/plugins/wp/tests/wp/stmtcompiler_test_rela.ml
+++ b/src/plugins/wp/tests/wp/stmtcompiler_test_rela.ml
@@ -18,10 +18,10 @@ let run () =
 
   let provers =
     List.fold_right
-      (fun pname prvs -> match VCS.prover_of_name pname with
+      (fun pname prvs -> match VCS.parse_prover pname with
          | None -> prvs
          | Some VCS.Tactical -> prvs
-         | Some prv -> (VCS.mode_of_prover_name pname, prv) :: prvs)
+         | Some prv -> (VCS.BatchMode, prv) :: prvs)
       ["alt-ergo"] []
   in
 
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle
index 0aeeeccf367612ea83cffeda8d96603923e5c18f..ce12f14d75e508eb5d7d3aaf23c54f7322e71554 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle
@@ -2,7 +2,6 @@
 [kernel] Parsing tests/wp_plugin/no_step_limit.i (no preprocessing)
 [wp] Running WP plugin...
 [wp] 1 goal scheduled
-[wp] Warning: no-steps  does not support steps limit (ignored option)
 [wp] [no-steps] Goal typed_lemma_truc : Unsuccess
 [wp] Proved goals:    0 / 1
   no-steps:        0  (unsuccess: 1)
diff --git a/src/plugins/wp/wpReport.ml b/src/plugins/wp/wpReport.ml
index be5b8151c1363541716bd1ebf093eb147be42926..6bdd9397a04e55018e96370fa42afd2ce900c248 100644
--- a/src/plugins/wp/wpReport.ml
+++ b/src/plugins/wp/wpReport.ml
@@ -609,7 +609,7 @@ let pstats ~config fmt s cmd arg =
   | "wp" | "qed" -> stat ~config fmt (get_prover s VCS.Qed) arg
   | cmd when is_stat_name cmd -> stat ~config fmt s.main cmd
   | prover ->
-      match (VCS.prover_of_name prover) with
+      match (VCS.parse_prover prover) with
       | None -> Wp_parameters.error ~once:true "Unknown prover name %s" prover
       | Some prover -> stat ~config fmt (get_prover s prover) arg
 
diff --git a/src/plugins/wp/wp_parameters.ml b/src/plugins/wp/wp_parameters.ml
index 3fd6bd1b7487f96a33e342eca0758866d53a484c..85a91ef237393229e0aefb1a077ff92e76f8fe13 100644
--- a/src/plugins/wp/wp_parameters.ml
+++ b/src/plugins/wp/wp_parameters.ml
@@ -621,6 +621,20 @@ module Provers = String_list
         "
     end)
 
+let () = Parameter_customize.set_group wp_prover
+module Interactive = String
+    (struct
+      let option_name = "-wp-interactive"
+      let arg_name = "mode"
+      let default = "batch"
+      let help =
+        "WP mode for interactive provers:\n\
+         - 'batch': use script only (default)\n\
+         - 'edit': run editor on every goal\n\
+         - 'fix': run editor for unproved goal\n\
+        "
+    end)
+
 let () = Parameter_customize.set_group wp_prover
 module RunAllProvers =
   False(struct
@@ -732,6 +746,18 @@ module SmokeTimeout =
         "Set the timeout (in seconds) for provers (default: %d)." default
   end)
 
+let () = Parameter_customize.set_group wp_prover
+module InteractiveTimeout =
+  Int(struct
+    let option_name = "-wp-interactive-timeout"
+    let default = 30
+    let arg_name = "n"
+    let help =
+      Printf.sprintf
+        "Set the timeout (in seconds) for checking scripts\n\
+         of interactive provers (default: %d)." default
+  end)
+
 let () = Parameter_customize.set_group wp_prover
 module TimeExtra =
   Int(struct
diff --git a/src/plugins/wp/wp_parameters.mli b/src/plugins/wp/wp_parameters.mli
index 5723c87072a18a4d4a738af17b749727147fb94a..236c418e01883ea1690ca1a4961af637dd808464 100644
--- a/src/plugins/wp/wp_parameters.mli
+++ b/src/plugins/wp/wp_parameters.mli
@@ -108,6 +108,7 @@ module PrecondWeakening : Parameter_sig.Bool
 module Detect: Parameter_sig.Bool
 module Generate:Parameter_sig.Bool
 module Provers: Parameter_sig.String_list
+module Interactive: Parameter_sig.String
 module RunAllProvers: Parameter_sig.Bool
 module Cache: Parameter_sig.String
 module CacheEnv: Parameter_sig.Bool
@@ -118,6 +119,7 @@ module Script: Parameter_sig.String
 module UpdateScript: Parameter_sig.Bool
 module Timeout: Parameter_sig.Int
 module SmokeTimeout: Parameter_sig.Int
+module InteractiveTimeout: Parameter_sig.Int
 module TimeExtra: Parameter_sig.Int
 module TimeMargin: Parameter_sig.Int
 module CoqTimeout: Parameter_sig.Int
diff --git a/src/plugins/wp/wpo.ml b/src/plugins/wp/wpo.ml
index 252264a5f932e20b76b203fb541fc3d744c2b170..a36b16398193812618864a7ab292f6d1d012b751 100644
--- a/src/plugins/wp/wpo.ml
+++ b/src/plugins/wp/wpo.ml
@@ -954,7 +954,7 @@ let goals_of_property =
 let prover_of_name =
   Dynamic.register ~plugin:"Wp" "Wpo.prover_of_name" ~journalize:false
     (Datatype.func Datatype.string (Datatype.option ProverType.ty))
-    VCS.prover_of_name
+    VCS.parse_prover
 
 (* -------------------------------------------------------------------------- *)
 (* --- Prover and Files                                                   --- *)