← Back to What's New

"sessioncast-go v0.1.0 — Go SDK for SessionCast Relay"

We're releasing sessioncast-go, a Go client library for interacting with the SessionCast relay server. It's the same library that powers the SessionCast provider in OpenCode.

Install

go get github.com/sessioncast/sessioncast-go

What It Does

sessioncast-go connects to the SessionCast relay via WebSocket and lets you call your local CLI agent's capabilities from any Go program:

  • LLM Chat — Send prompts, get completions from whatever LLM your agent is running
  • LLM Streaming — Stream responses chunk by chunk via channels
  • Remote Exec — Run shell commands on the agent machine
  • SendKeys — Send keystrokes to tmux sessions
  • List Sessions — Query active tmux sessions
  • Capability Negotiation — Discover what the connected agent supports

Quick Start

package main

import (
    "context"
    "fmt"
    "log"

    sessioncast "github.com/sessioncast/sessioncast-go"
)

func main() {
    client := sessioncast.NewClient(
        sessioncast.WithRelayURL("wss://relay.sessioncast.io/ws"),
        sessioncast.WithToken("agt_YOUR_TOKEN"),
        sessioncast.WithMachineID("my-machine"),
    )

    ctx := context.Background()
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }
    defer client.Disconnect()

    // Chat completion
    resp, err := client.LlmChat(ctx, &sessioncast.LlmChatRequest{
        Model: "claude-code",
        Messages: []sessioncast.ChatMessage{
            {Role: "user", Content: "What is Docker? Answer in 2 sentences."},
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(resp.Choices[0].Message.Content)
}

Streaming

stream, err := client.LlmChatStream(ctx, &sessioncast.LlmChatRequest{
    Model:    "claude-code",
    Messages: []sessioncast.ChatMessage{
        {Role: "user", Content: "Write a hello world HTTP server in Go."},
    },
})
if err != nil {
    log.Fatal(err)
}

for event := range stream {
    if event.Error != nil {
        log.Fatal(event.Error)
    }
    if event.Chunk != nil {
        fmt.Print(event.Chunk.Content)
    }
    if event.Response != nil {
        fmt.Printf("\n\nTokens used: %d\n", event.Response.Usage.TotalTokens)
    }
}

Remote Exec

result, err := client.Exec(ctx, &sessioncast.ExecRequest{
    Command: "ls -la /tmp",
    Cwd:     "/home/user",
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Exit code: %d\nStdout:\n%s\n", result.ExitCode, result.Stdout)

Auto-Reconnect

For long-running services, use ConnectWithReconnect — it handles disconnections with exponential backoff (1s → 2s → 4s → ... → 30s max):

client.ConnectWithReconnect(ctx, func() {
    fmt.Println("Connected!")
})

Architecture

Your Go App
  → sessioncast-go (this library)
    → WebSocket → SessionCast Relay
      → CLI Agent (target machine)
        → LLM / Shell / tmux

The library handles connection lifecycle, ping/pong keepalive (30s interval), request-response correlation via UUID, capability negotiation, and timeout management.

Package Structure

  • client.go — WebSocket client, connect/disconnect, message routing
  • llm.goLlmChat() and LlmChatStream()
  • exec.goExec(), SendKeys(), ListSessions()
  • protocol.go — Message types, request/response structs
  • correlator.go — UUID-based request-response matching
  • capability.go — Capability negotiation handshake
  • reconnect.go — Auto-reconnect with exponential backoff

Dependencies

Only two:

  • github.com/gorilla/websocket — WebSocket client
  • github.com/google/uuid — Request ID generation

Configuration

All options use the functional options pattern:

sessioncast.NewClient(
    sessioncast.WithRelayURL("wss://relay.sessioncast.io/ws"),
    sessioncast.WithToken("agt_YOUR_TOKEN"),
    sessioncast.WithMachineID("my-machine"),
    sessioncast.WithAgentID("my-agent"),
    sessioncast.WithLabel("My App"),
    sessioncast.WithRequestTimeout(120 * time.Second),
    sessioncast.WithPingInterval(30 * time.Second),
    sessioncast.WithLogger(slog.Default()),
)

Links

Loading...