anchor.diff:          |> Option.map (fun e -> e.extensionPath)
   
   
  +module CrossSpawn = 
  +    open Node.ChildProcess
  +    type [<AllowNullLiteral>] IExports = 
  +        abstract spawn: command: string * options: ExecOptions -> ChildProcess
  +        abstract spawn: command: string * args: ResizeArray<string>  * ?options: ExecOptions -> ChildProcess
  +
  +    let crossSpawn: IExports = Fable.Core.JsInterop.importAll "cross-spawn"
  +
   //---------------------------------------------------
   //Process Helpers
   //---------------------------------------------------
   module Process =
  -    let splitArgs cmd =
  -        if cmd = "" then
  -            [||]
  -        else
  -            cmd.Split(' ')
  -            |> Array.toList
  -            |> List.fold (fun (quoted : string option,acc) e ->
  -                if quoted.IsSome then
  -                    if e.EndsWith "\"" then None, (quoted.Value + " " + e).Replace("\"", "")::acc
  -                    else Some (quoted.Value + " " + e), acc
  -                else
  -                    if e.StartsWith "\"" &&  e.EndsWith "\"" then None, e.Replace("\"", "")::acc
  -                    elif e.StartsWith "\"" then Some e, acc
  -                    elif String.IsNullOrEmpty e then None, acc
  -                    else None, e::acc
  -            ) (None,[])
  -            |> snd
  -            |> List.rev
  -            |> List.toArray
   
       open Node
       open Node.ChildProcess
       open Fable.Import.VSCode.Vscode
       open Fable.Core.JsInterop
  +    open CrossSpawn
   
       module node = Node.Api
   
  
positive.code:         proc?on $ ("error", f |> unbox) |> ignore
          proc
  
      let spawn location linuxCmd (cmd : string) =
          let cmd' = splitArgs cmd |> ResizeArray
  
          let options =
              createObj [
                  "cwd" ==> workspace.rootPath
              ]
          if isWin () || linuxCmd = "" then
              node.childProcess.spawn(location, cmd', options)
          else
              let prms = seq { yield location; yield! cmd'} |> ResizeArray
              node.childProcess.spawn(linuxCmd, prms, options)
  
      let spawnInDir location linuxCmd (cmd : string) =
          let cmd' = splitArgs cmd |> ResizeArray
  
          let options =
              createObj [
                  "cwd" ==> (node.path.dirname location)
              ]
          if isWin () || linuxCmd = "" then
  
              node.childProcess.spawn(location, cmd', options)
          else
              let prms = seq { yield location; yield! cmd'} |> ResizeArray
              node.childProcess.spawn(linuxCmd, prms, options)
  
      let spawnWithShell location linuxCmd (cmd : string) =
          let cmd' =
              if isWin() then
                  splitArgs cmd
                  |> Seq.map (fun c -> if c.Contains " " then sprintf "\"%s\"" c else c )
                  |> ResizeArray
              else
                  splitArgs cmd
                  |> Seq.toArray
                  |> ResizeArray
  
          if isWin () || linuxCmd = "" then
              window.createTerminal("F# Application", location, U2.Case1 cmd')
          else
              let prms = seq { yield location; yield! cmd'} |> ResizeArray |> U2.Case1
              window.createTerminal("F# Application", linuxCmd, prms)
  
  
      let spawnWithNotification location linuxCmd (cmd : string) (outputChannel : OutputChannel) =
          spawn location linuxCmd cmd
          |> onOutput(fun e -> e.toString () |> outputChannel.append)
          |> onError (fun e -> e.ToString () |> outputChannel.append)
          |> onErrorOutput(fun e -> e.toString () |> outputChannel.append)
  
      let spawnWithNotificationInDir location linuxCmd (cmd : string) (outputChannel : OutputChannel) =
          spawnInDir location linuxCmd cmd
          |> onOutput(fun e -> e.toString () |> outputChannel.append)
          |> onError (fun e -> e.ToString () |> outputChannel.append)
          |> onErrorOutput(fun e -> e.toString () |> outputChannel.append)
  
negative.code:             |> ignore
          )
  
      /// <summary>
      /// fire off a command and gather the error, if any, and the stdout and stderr streams
      /// </summary>
      /// <param name="command">the 'base' command to execute</param>
      /// <param name="args">an array of additional CLI args</param>
      /// <returns></returns>
      let exec command args : JS.Promise<ExecError option * string * string> =
          let options = createEmpty<ExecOptions>
          options.cwd <- workspace.rootPath
          Promise.create (fun resolve reject ->
              let stdout = ResizeArray()
              let stderr = ResizeArray()
              let mutable error = None
              
              crossSpawn.spawn(command, args)
              |> onOutput (fun e -> stdout.Add(string e))
              |> onError (fun e -> error <- Some e)
              |> onErrorOutput (fun e -> stderr.Add(string e))
              |> onExit (fun code signal ->
                  resolve (unbox error, String.concat "\n" stdout, String.concat "\n" stderr)
              )
              |> ignore
          )
  
  
  