Back to Microsandbox

Native Sessions

docs/sandboxes/ssh/native-sessions.mdx

0.5.13.4 KB
Original Source

Native sessions keep the SSH protocol boundary but do not expose a listener. microsandbox creates an in-process SSH client/server pair over an in-memory stream, then forwards SSH channels to the sandbox.

Use this path when you want a quick shell from msb, or when SDK code wants SSH semantics without running an external SSH client.

CLI

bash
msb ssh devbox
msb ssh connect devbox

With no remote command, the CLI opens an interactive shell. With --, the remaining tokens become the SSH command string and run through the sandbox shell.

bash
msb ssh devbox -- uname -a
msb ssh devbox -- sh -lc "cd /app && npm test"

If a sandbox name collides with an SSH subcommand such as serve or authorize, use --name:

bash
msb ssh --name serve
msb ssh --name authorize -- uptime

SDK

<CodeGroup> ```rust Rust let sb = Sandbox::start("devbox").await?; let ssh = sb.ssh().connect().await?;

let output = ssh.exec("uname -a").await?; println!("{}", String::from_utf8_lossy(&output.stdout));

ssh.close().await?;


```typescript TypeScript
const sb = await Sandbox.start("devbox");
const ssh = await sb.ssh().connect();

const output = await ssh.exec("uname -a");
console.log(output.stdout.toString());

await ssh.close();
python
sb = await Sandbox.start("devbox")
ssh = await sb.ssh().connect()

output = await ssh.exec("uname -a")
print(output.stdout_text)

await ssh.close()
go
sb, err := m.StartSandbox(ctx, "devbox")
if err != nil {
    return err
}
defer sb.Close()

ssh, err := sb.SSH().Connect(ctx)
if err != nil {
    return err
}
defer ssh.Close(ctx)

output, err := ssh.Exec(ctx, "uname -a")
if err != nil {
    return err
}
fmt.Print(string(output.Stdout))
</CodeGroup>

Interactive attach

SDK clients can attach the local terminal to an SSH shell. This requires a real terminal.

<CodeGroup> ```rust Rust let code = sb .ssh() .connect_with(|ssh| ssh.term("xterm-256color")) .await? .attach() .await?; ```
typescript
const ssh = await sb.ssh().connect({ term: "xterm-256color" });
const code = await ssh.attach({ detachKeys: "ctrl-]" });
python
ssh = await sb.ssh().connect(term="xterm-256color")
code = await ssh.attach(detach_keys="ctrl-]")
go
ssh, err := sb.SSH().Connect(ctx, m.WithSSHTerm("xterm-256color"))
if err != nil {
    return err
}
code, err := ssh.Attach(ctx, m.WithSSHDetachKeys("ctrl-]"))
</CodeGroup>

SFTP from a native client

The native SSH client can open SFTP over the same SSH connection.

<CodeGroup> ```rust Rust let sftp = ssh.sftp().await?; sftp.write("/tmp/hello.txt", b"hello").await?; let data = sftp.read("/tmp/hello.txt").await?; sftp.close().await?; ```
typescript
const sftp = await ssh.sftp();
await sftp.write("/tmp/hello.txt", Buffer.from("hello"));
const data = await sftp.read("/tmp/hello.txt");
await sftp.close();
python
sftp = await ssh.sftp()
await sftp.write("/tmp/hello.txt", b"hello")
data = await sftp.read("/tmp/hello.txt")
await sftp.close()
go
sftp, err := ssh.SFTP(ctx)
if err != nil {
    return err
}
defer sftp.Close(ctx)

if err := sftp.Write(ctx, "/tmp/hello.txt", []byte("hello")); err != nil {
    return err
}
data, err := sftp.Read(ctx, "/tmp/hello.txt")
</CodeGroup>

For exact SDK signatures, see the SSH reference for Rust, TypeScript, Python, or Go.