cli_subprocess_core is the provider-facing runtime layer above the lower execution substrate.

Use it when you want normalized provider commands, sessions, payloads, and events instead of working directly with the raw transport substrate.

For the covered runtime slice, provider-aware local one-shot commands route through ExecutionPlane.Process.run/2, while raw sessions and non-local surfaces route through ExecutionPlane.Process.Transport.

Install

def deps do
  [
    {:cli_subprocess_core, "~> 0.2.0"}
  ]
end

Choose The Right API

Use:

One-Shot Commands

{:ok, result} =
  CliSubprocessCore.Command.run(
    provider: :claude,
    prompt: "Summarize the latest changes"
  )

The result type is CliSubprocessCore.Command.RunResult. For surface_kind: :local_subprocess, the core emits ProcessExecutionIntent.v1 and delegates the lower one-shot hop to execution_plane before projecting the outcome back into the core-owned command shape.

Raw Sessions

{:ok, session} =
  CliSubprocessCore.RawSession.start("sh", ["-c", "cat"], stdin?: true)

:ok = CliSubprocessCore.RawSession.send_input(session, "alpha")
:ok = CliSubprocessCore.RawSession.close_input(session)

{:ok, result} = CliSubprocessCore.RawSession.collect(session, 5_000)

RawSession is the lowest public CLI-owned layer. For the covered local session-bearing lane it uses ExecutionPlane.Process.Transport underneath while keeping the public placement seam generic. The same transport seam also handles non-local placement through execution_surface.

Normalized Sessions

ref = make_ref()

{:ok, session, info} =
  CliSubprocessCore.Session.start_session(
    provider: :codex,
    prompt: "Review this change",
    subscriber: {self(), ref}
  )

IO.inspect(info.transport.info.surface_kind)

Execution Surface

Placement stays on one execution_surface contract:

execution_surface = [
  surface_kind: :ssh_exec,
  transport_options: [
    destination: "buildbox.example",
    ssh_user: "deploy"
  ],
  target_id: "buildbox-1",
  boundary_class: :remote
]

Pass that value through Command.run/1, Command.run/2, RawSession.start/2, or Session.start_session/1.

When Command.run/1,2 receives surface_kind: :local_subprocess, the covered minimal one-shot lane runs through execution_plane. RawSession, Channel, and Session now use the Execution Plane-backed local session lane for :local_subprocess as well. Non-local surfaces also resolve through the same Execution Plane-backed transport seam.

Supported landed surface kinds are:

  • :local_subprocess
  • :ssh_exec
  • :guest_bridge