# Libtmux_unix.Workspace.await

**Workspace Manager concept example** A working example of the core library. It can change without notice.

- **Module:** Libtmux_unix
- **Package:** libtmux-unix
- **Language:** OCaml
- **Kind:** function
- **Source:** https://github.com/libtmux/libtmux-ocaml/blob/205dfda49742592b479247049d186956e4a4cfe9/unix/libtmux_unix.mli#L790
- **Public owner:** Libtmux_unix
- **Page:** https://libtmux.org/en/ocaml/latest/workspace/reference/libtmux_unix-workspace-await/

```
val await :
  ?cancel:Cancellation.t ->
  ?compensate_on_failure:bool ->
  t -> (Libtmux_workspace.Execution.receipt, Libtmux.Error.t) result
```

Apply steps at most once per execution handle. Expected failures return retained receipts. On initial application, `compensate_on_failure` defaults to `true`, attempting removal of proven newly created panes after failure or cancellation. Passing `false` skips that compensation. Cancellation propagates after recording progress and at most 500 ms of protected compensation; use [`inspect`](/en/ocaml/latest/workspace/reference/libtmux_unix-workspace-inspect/) afterward.

## Examples

Start a private server and capture its first session. This complete program creates a private daemon, checks its result and closes its clients. Use OCaml 5.5.2 on Linux with tmux 3.3a through 3.8. Run it from the source checkout after following the installation guide.

[Source example](https://github.com/libtmux/libtmux-ocaml/blob/205dfda49742592b479247049d186956e4a4cfe9/examples/showcase_bootstrap.ml).

```ocaml
open Libtmux
module Client = Libtmux_unix.Client
module Workspace = Libtmux_unix.Workspace
module Config = Libtmux_workspace.Config
module Plan = Libtmux_workspace.Plan
module Execution = Libtmux_workspace.Execution

let checked pp = function
  | Ok value -> value
  | Error error -> failwith (Format.asprintf "%a" pp error)

let get result = checked Error.pp result

let protect ~finally use =
  match use () with
  | value ->
      finally ();
      value
  | exception error ->
      let backtrace = Printexc.get_raw_backtrace () in
      (try finally ()
       with cleanup ->
         Format.eprintf "cleanup failed: %s@." (Printexc.to_string cleanup));
      Printexc.raise_with_backtrace error backtrace

(* docs:begin bootstrap *)
let bootstrap ~binary ~version ~directory endpoint =
  let spawn = Spawn.make (Exec { program = "/bin/cat"; args = [ "-u" ] }) in
  let config =
    Config.make ~directory ~session:"bootstrap-demo"
      [ Config.window ~name:"editor" [ Config.pane ~spawn () ] ]
    |> checked Config.pp_error
  in
  let plan =
    Plan.make ~endpoint ~version ~observed:None config |> checked Plan.pp_error
  in
  get (Workspace.submit_bootstrap ~binary plan)
(* docs:end bootstrap *)

let require_success (receipt : Execution.receipt) =
  if receipt.status <> Execution.Succeeded then (
    Format.eprintf "workspace %s did not complete@." receipt.operation_id;
    (match receipt.status with
    | Execution.Rejected error -> Format.eprintf "%a@." Plan.pp_error error
    | Execution.Unavailable error -> Format.eprintf "%a@." Error.pp error
    | _ -> ());
    Iarray.iter
      (fun (step : Execution.step) ->
        match step.status with
        | Execution.Failed error | Execution.Uncertain error ->
            Format.eprintf "step %d: %a@." step.index Error.pp error
        | _ -> ())
      receipt.steps;
    Option.iter
      (fun error -> Format.eprintf "compensation: %a@." Error.pp error)
      receipt.cleanup_error;
    Iarray.iter
      (fun (cleanup : Execution.cleanup) ->
        match cleanup.outcome with
        | Ok () -> ()
        | Error error -> Format.eprintf "cleanup: %a@." Error.pp error)
      receipt.cleanup;
    failwith "bootstrap incomplete; no automatic retry")

let local_version binary =
  let input = Unix.open_process_args_in binary [| binary; "-V" |] in
  let version =
    protect
      ~finally:(fun () ->
        if Unix.close_process_in input <> Unix.WEXITED 0 then
          failwith "tmux version discovery failed")
      (fun () -> String.trim (input_line input))
  in
  if not (String.starts_with ~prefix:"tmux " version) then
    failwith "invalid tmux version";
  String.sub version 5 (String.length version - 5)

let () =
  let binary = if Array.length Sys.argv = 2 then Sys.argv.(1) else "tmux" in
  let directory = Filename.temp_dir "libtmux-ocaml-showcase-" "" in
  protect
    ~finally:(fun () ->
      Sys.readdir directory
      |> Array.iter (fun name -> Sys.remove (Filename.concat directory name));
      Unix.rmdir directory)
    (fun () ->
      let socket = Filename.concat directory "server" in
      let config_file = Filename.concat directory "tmux.conf" in
      Out_channel.with_open_text config_file (fun output ->
          output_string output "set-option -s exit-unattached on\n");
      let wrapper = Filename.concat directory "tmux" in
      Out_channel.with_open_text wrapper (fun output ->
          Printf.fprintf output "#!/bin/sh\nexec %s -f %s \"$@\"\n"
            (Filename.quote binary)
            (Filename.quote config_file));
      Unix.chmod wrapper 0o700;
      let execution =
        bootstrap ~binary:wrapper ~version:(local_version binary) ~directory
          (Endpoint.socket_path socket)
      in
      (* docs:begin await-bootstrap *)
      let snapshot =
        protect
          ~finally:(fun () -> get (Workspace.close execution))
          (fun () ->
            let receipt = get (Workspace.await execution) in
            require_success receipt;
            let client = Option.get (Workspace.client execution) in
            get (Client.capture client))
        (* docs:end await-bootstrap *)
      in
      assert (Iarray.length (Snapshot.sessions snapshot) = 1);
      assert (Iarray.length (Snapshot.windows snapshot) = 1);
      assert (Iarray.length (Snapshot.panes snapshot) = 1);
      assert (
        Session.name (Iarray.get (Snapshot.sessions snapshot) 0)
        = "bootstrap-demo");
      assert (Window.name (Iarray.get (Snapshot.windows snapshot) 0) = "editor");
      Printf.printf "socket=%s\n" socket;
      print_endline "bootstrapped: 1 session, 1 window, 1 pane")
```

Run the recorded entry point:

```console
$ opam exec -- dune exec examples/showcase_bootstrap.exe -- tmux
```

Expected outcome line, after the temporary socket path:

```text
bootstrapped: 1 session, 1 window, 1 pane
```

## Parameters

- `cancel?` (`Cancellation.t`)
- `compensate_on_failure?` (`bool`)
- `arg1` (`t`)

## In other ports

Build a session from a workspace description

| Language | Equivalent |
| --- | --- |
| Python | [`tmuxp.workspace.builder.ClassicWorkspaceBuilder.build`](/en/py/latest/workspace/reference/tmuxp-workspace-builder-classicworkspacebuilder-build/) (method) |
| Ruby | [`LibTmux::Workspace::Plan#apply`](/en/ruby/latest/workspace/reference/libtmux-workspace-plan-apply/) (method) |
| PowerShell | [`LibTmux.Workspace\Invoke-TmuxWorkspace`](/en/powershell/latest/workspace/reference/libtmux-workspace-invoke-tmuxworkspace/) (cmdlet). Applies the exact reviewed [`-Plan`](/en/powershell/latest/workspace/reference/libtmux-workspace-invoke-tmuxworkspace/#LibTmux.Workspace%5CInvoke-TmuxWorkspace.parameter.Plan) after PowerShell confirmation. [`-WhatIf`](/en/powershell/latest/workspace/reference/libtmux-workspace-invoke-tmuxworkspace/#LibTmux.Workspace%5CInvoke-TmuxWorkspace.parameter.WhatIf) previews without applying it; application is detached. |
| Julia | [`LibTmuxWorkspace.apply`](/en/julia/latest/workspace/reference/libtmuxworkspace-apply/) (function). Applies a prepared `WorkspacePlan` on an explicit `Server`, detached and under one deadline. Existing session names fail unless reuse is explicit. |
| Haskell | No public Haskell equivalent is implemented; the current modules expose scalar values and version parsing. |
| Common Lisp | [`libtmux.workspace:apply-workspace`](/en/lisp/latest/workspace/reference/libtmux-workspace-apply-workspace/) (function) |
| TypeScript | [`builder.applyWorkspace`](/en/ts/latest/workspace/reference/builder-applyworkspace/) (function) |
| Rust | [`src.WorkspaceBuilder.build`](/en/rs/latest/workspace/reference/src-workspacebuilder-build/) (method) |
| Go | [`workspace.Build`](/en/go/latest/workspace/reference/workspace-build/) (function) |
| Java | [`io.github.libtmux.workspace.WorkspaceBuilder.build`](/en/java/latest/workspace/reference/io-github-libtmux-workspace-workspacebuilder-workspacebuilder-build/) (method) |
| C# | [`LibTmux.Workspace.WorkspaceBuilder.BuildAsync`](/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuilder-buildasync/) (method) |
| C++ | [`libtmux::workspace::build`](/en/cxx/latest/workspace/reference/libtmux-workspace-build/) (function) |
| Swift | [`WorkspaceBuilder.build(_:on:)`](/en/swift/latest/workspace/reference/workspacebuilder-build(_-on-)/) (method) |
| Perl | [`LibTmux::Workspace::load`](/en/perl/latest/workspace/reference/libtmux-workspace-load/) (method). Loads through installed public core APIs; existing-target policy and known owned rollback effects are explicit. |

No equivalent is recorded in Lua, Erlang, Elixir, Clojure, Kotlin, Scala or F#.
