cli_subprocess_core is the provider-facing runtime layer above the lower
execution substrate.
This guide targets cli_subprocess_core ~> 0.7.0.
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.7.0"}
]
endChoose The Right API
Use:
CliSubprocessCore.Commandfor provider-aware one-shot executionCliSubprocessCore.RawSessionfor long-lived raw subprocess ownershipCliSubprocessCore.Sessionfor normalized provider eventsCliSubprocessCore.ChannelorCliSubprocessCore.ProtocolSessionfor framed or protocol-driven sessions
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