Documentation
¶
Overview ¶
Package clauderelay provides a WebSocket relay server for Claude Code CLI with isolated, portable installation support.
This package enables you to programmatically create and manage multiple isolated Claude instances, each with its own configuration and authentication, without requiring system-wide installation.
Features ¶
• Isolated Installation: Each instance has its own Bun and Claude installation • Multiple Instances: Run multiple Claude relays on different ports • Auto-Setup: Automatically downloads and installs dependencies • Authentication Management: Handle Claude authentication programmatically • WebSocket Interface: Connect to Claude via WebSocket protocol • Conversation State: Maintains context across messages • Undo/Restore: Support for undoing and restoring conversations
Basic Usage ¶
Create a simple relay server:
import "github.com/rizrmd/claude-relay"
func main() {
// Create relay with automatic setup
relay, err := clauderelay.New(clauderelay.Options{
Port: "8081",
BaseDir: "./claude-instance",
AutoSetup: true,
EnableLogging: true,
})
if err != nil {
log.Fatal(err)
}
defer relay.Close()
// Check authentication
if authenticated, _ := relay.IsAuthenticated(); !authenticated {
if err := relay.Authenticate(); err != nil {
log.Fatal(err)
}
}
// Start the server
if err := relay.Start(); err != nil {
log.Fatal(err)
}
// Wait for shutdown
select {}
}
Multiple Instances ¶
Run multiple isolated Claude instances:
// Create instance 1
relay1, _ := clauderelay.New(clauderelay.Options{
Port: "8081",
BaseDir: "./claude-1",
})
relay1.Start()
// Create instance 2
relay2, _ := clauderelay.New(clauderelay.Options{
Port: "8082",
BaseDir: "./claude-2",
})
relay2.Start()
Embedding in Existing Server ¶
Integrate Claude relay into your existing HTTP server:
relay, _ := clauderelay.New(clauderelay.Options{
Port: "8081",
})
relay.Start()
// Use relay.GetWebSocketURL() to get the WebSocket endpoint
// Integrate with your existing routes
WebSocket Protocol ¶
The relay server exposes a WebSocket endpoint at /ws that accepts text messages and returns Claude's responses.
Client to Server: • Plain text messages to send to Claude • /undo-from:N - Undo from message index N • /restore - Restore last undone conversation
Server to Client: • Claude's responses as plain text • Progress indicators during processing • Error messages prefixed with ❌
Directory Structure ¶
Each Claude instance creates the following structure in its BaseDir:
BaseDir/ ├── .bun/ // Portable Bun installation │ └── bin/ │ ├── bun // Bun executable │ └── claude // Claude CLI ├── .claude-home/ // Claude configuration │ └── .config/ │ └── claude/ │ └── auth.json // Authentication token └── claude-relay-*/ // Temporary workspaces (runtime)
Authentication ¶
Claude requires authentication on first use. The library provides multiple authentication methods to suit different deployment scenarios:
## Authentication Methods
### 1. SetAuthToken() - Non-Interactive/Programmatic
Use when you already have an API key. Perfect for servers, containers, and headless environments.
apiKey := os.Getenv("CLAUDE_API_KEY")
err := relay.SetAuthToken(apiKey)
### 2. Authenticate() - Interactive/Terminal-Based
Use when running in a terminal with user interaction. Launches Claude's interactive login.
err := relay.Authenticate() // User will see Claude interface, choose theme, type /login
### 3. Options.APIKey - Automatic Authentication
Provide API key during initialization for automatic setup.
relay, _ := clauderelay.New(clauderelay.Options{
APIKey: "sk-ant-...", // Automatically authenticates
})
### 4. Options.AuthCallback - Custom Authentication Flow
Implement your own authentication UI/flow.
relay, _ := clauderelay.New(clauderelay.Options{
AuthCallback: func(authURL string) (string, error) {
// Show authURL to user in your UI
// Return API key from your source
return getUserAPIKey(authURL), nil
},
})
## When to Use Each Method
SetAuthToken() - Use when: • Running as a web service or API • Deploying in Docker containers • Running in CI/CD pipelines • Serverless functions (AWS Lambda, etc.) • Background jobs or workers • Any environment without terminal access
Authenticate() - Use when: • Building CLI tools • Local development with terminal • One-time setup scripts • User manages their own authentication
## Checking Authentication Status
// Simple check authenticated, err := relay.IsAuthenticated() // Detailed status authenticated, message, err := relay.GetAuthStatus() // Returns: (true, "Authenticated", nil) or (false, "No authentication file found", nil)
## Getting the Auth URL
For custom authentication flows:
url, _ := relay.GetAuthURL() // Returns: "https://console.anthropic.com/settings/keys"
Thread Safety ¶
The Relay type is thread-safe and can be safely accessed from multiple goroutines. Multiple relay instances can run concurrently without interference.
Package clauderelay provides a WebSocket relay server for Claude Code CLI with isolated, portable installation support.
This package allows you to create multiple isolated Claude instances, each with its own configuration and authentication, without requiring system-wide installation.
Basic usage:
import "github.com/yourusername/claude-relay"
// Create a new relay server
relay, err := clauderelay.New(clauderelay.Options{
Port: "8081",
BaseDir: "./claude-instance-1",
AutoSetup: true,
})
if err != nil {
log.Fatal(err)
}
defer relay.Close()
// Start the server
if err := relay.Start(); err != nil {
log.Fatal(err)
}
Package clauderelay provides isolated Claude Code CLI instances.
Index ¶
- func PromptUser(prompt string) string
- type ClaudeProcess
- func (p *ClaudeProcess) CanRestore() bool
- func (p *ClaudeProcess) CanUndo() bool
- func (p *ClaudeProcess) Cleanup() error
- func (p *ClaudeProcess) GetLastExchange() (string, string, error)
- func (p *ClaudeProcess) GetRestoredMessagesForClient() []map[string]string
- func (p *ClaudeProcess) GetWorkingDirectory() string
- func (p *ClaudeProcess) IsRunning() bool
- func (p *ClaudeProcess) Kill() error
- func (p *ClaudeProcess) ReadFile(filename string) ([]byte, error)
- func (p *ClaudeProcess) RestoreLastUndo() ([]string, error)
- func (p *ClaudeProcess) SaveFile(filename string, content []byte) error
- func (p *ClaudeProcess) SaveState()
- func (p *ClaudeProcess) SendMessage(message string) (string, error)
- func (p *ClaudeProcess) SendMessageWithProgress(message string, progressChan chan<- []byte, doneChan <-chan bool) (string, error)
- func (p *ClaudeProcess) UndoLastExchange() error
- func (p *ClaudeProcess) UndoToIndex(messageIndex int) error
- type ClaudeProcessV2
- func (p *ClaudeProcessV2) Cleanup() error
- func (p *ClaudeProcessV2) GetWorkingDirectory() string
- func (p *ClaudeProcessV2) ReadFile(filename string) ([]byte, error)
- func (p *ClaudeProcessV2) SaveFile(filename string, content []byte) error
- func (p *ClaudeProcessV2) SendMessage(message string) (string, error)
- type ClaudeSetup
- func (cs *ClaudeSetup) CheckAuthentication() (bool, error)
- func (cs *ClaudeSetup) GetAuthStatus() (bool, string, error)
- func (cs *ClaudeSetup) GetAuthURL() (string, error)
- func (cs *ClaudeSetup) GetClaudeEnv() []string
- func (cs *ClaudeSetup) GetClaudeHome() string
- func (cs *ClaudeSetup) GetClaudePath() string
- func (cs *ClaudeSetup) HandleAuthenticationPrompt(process *ClaudeProcess) error
- func (cs *ClaudeSetup) InstallBun() error
- func (cs *ClaudeSetup) InstallClaude() error
- func (cs *ClaudeSetup) IsAuthenticationNeeded(output string) bool
- func (cs *ClaudeSetup) IsInstalled() bool
- func (cs *ClaudeSetup) RunClaudeLogin() error
- func (cs *ClaudeSetup) SetAuthToken(apiKey string) error
- func (cs *ClaudeSetup) Setup() error
- func (cs *ClaudeSetup) SetupClaudeHome() error
- func (cs *ClaudeSetup) StartNonInteractiveAuth() (string, chan error)
- func (cs *ClaudeSetup) WaitForAuth(timeout time.Duration) error
- type Config
- type Connection
- type ConnectionV2
- type ConversationState
- type Options
- type Relay
- func (r *Relay) Authenticate() error
- func (r *Relay) AuthenticateWithCallback(callback func(authURL string) (string, error)) error
- func (r *Relay) Close() error
- func (r *Relay) GetAuthStatus() (bool, string, error)
- func (r *Relay) GetAuthURL() (string, error)
- func (r *Relay) GetBaseDir() string
- func (r *Relay) GetPort() string
- func (r *Relay) GetServer() *Server
- func (r *Relay) GetSetup() *ClaudeSetup
- func (r *Relay) GetWebSocketURL() string
- func (r *Relay) IsAuthenticated() (bool, error)
- func (r *Relay) IsInstalled() bool
- func (r *Relay) IsRunning() bool
- func (r *Relay) SetAuthToken(apiKey string) error
- func (r *Relay) Setup() error
- func (r *Relay) Start() error
- func (r *Relay) Stop() error
- func (r *Relay) Wait()
- type Server
- type ServerV2
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func PromptUser ¶
Types ¶
type ClaudeProcess ¶
type ClaudeProcess struct {
// contains filtered or unexported fields
}
func NewClaudeProcess ¶
func NewClaudeProcess(setup *ClaudeSetup) (*ClaudeProcess, error)
func (*ClaudeProcess) CanRestore ¶
func (p *ClaudeProcess) CanRestore() bool
func (*ClaudeProcess) CanUndo ¶
func (p *ClaudeProcess) CanUndo() bool
func (*ClaudeProcess) Cleanup ¶
func (p *ClaudeProcess) Cleanup() error
func (*ClaudeProcess) GetLastExchange ¶
func (p *ClaudeProcess) GetLastExchange() (string, string, error)
func (*ClaudeProcess) GetRestoredMessagesForClient ¶
func (p *ClaudeProcess) GetRestoredMessagesForClient() []map[string]string
func (*ClaudeProcess) GetWorkingDirectory ¶
func (p *ClaudeProcess) GetWorkingDirectory() string
func (*ClaudeProcess) IsRunning ¶
func (p *ClaudeProcess) IsRunning() bool
func (*ClaudeProcess) Kill ¶
func (p *ClaudeProcess) Kill() error
func (*ClaudeProcess) RestoreLastUndo ¶
func (p *ClaudeProcess) RestoreLastUndo() ([]string, error)
func (*ClaudeProcess) SaveFile ¶
func (p *ClaudeProcess) SaveFile(filename string, content []byte) error
func (*ClaudeProcess) SaveState ¶
func (p *ClaudeProcess) SaveState()
func (*ClaudeProcess) SendMessage ¶
func (p *ClaudeProcess) SendMessage(message string) (string, error)
func (*ClaudeProcess) SendMessageWithProgress ¶
func (*ClaudeProcess) UndoLastExchange ¶
func (p *ClaudeProcess) UndoLastExchange() error
func (*ClaudeProcess) UndoToIndex ¶
func (p *ClaudeProcess) UndoToIndex(messageIndex int) error
type ClaudeProcessV2 ¶
type ClaudeProcessV2 struct {
// contains filtered or unexported fields
}
func NewClaudeProcessV2 ¶
func NewClaudeProcessV2() (*ClaudeProcessV2, error)
func (*ClaudeProcessV2) Cleanup ¶
func (p *ClaudeProcessV2) Cleanup() error
func (*ClaudeProcessV2) GetWorkingDirectory ¶
func (p *ClaudeProcessV2) GetWorkingDirectory() string
func (*ClaudeProcessV2) ReadFile ¶
func (p *ClaudeProcessV2) ReadFile(filename string) ([]byte, error)
func (*ClaudeProcessV2) SaveFile ¶
func (p *ClaudeProcessV2) SaveFile(filename string, content []byte) error
func (*ClaudeProcessV2) SendMessage ¶
func (p *ClaudeProcessV2) SendMessage(message string) (string, error)
type ClaudeSetup ¶
type ClaudeSetup struct {
// contains filtered or unexported fields
}
func NewClaudeSetup ¶
func NewClaudeSetup() (*ClaudeSetup, error)
func NewClaudeSetupWithBaseDir ¶
func NewClaudeSetupWithBaseDir(baseDir string) (*ClaudeSetup, error)
NewClaudeSetupWithBaseDir creates a ClaudeSetup with a custom base directory. This allows multiple isolated Claude instances.
func (*ClaudeSetup) CheckAuthentication ¶
func (cs *ClaudeSetup) CheckAuthentication() (bool, error)
func (*ClaudeSetup) GetAuthStatus ¶
func (cs *ClaudeSetup) GetAuthStatus() (bool, string, error)
GetAuthStatus returns detailed authentication status
func (*ClaudeSetup) GetAuthURL ¶
func (cs *ClaudeSetup) GetAuthURL() (string, error)
GetAuthURL returns the Claude authentication URL for non-interactive login
func (*ClaudeSetup) GetClaudeEnv ¶
func (cs *ClaudeSetup) GetClaudeEnv() []string
func (*ClaudeSetup) GetClaudeHome ¶
func (cs *ClaudeSetup) GetClaudeHome() string
func (*ClaudeSetup) GetClaudePath ¶
func (cs *ClaudeSetup) GetClaudePath() string
func (*ClaudeSetup) HandleAuthenticationPrompt ¶
func (cs *ClaudeSetup) HandleAuthenticationPrompt(process *ClaudeProcess) error
func (*ClaudeSetup) InstallBun ¶
func (cs *ClaudeSetup) InstallBun() error
func (*ClaudeSetup) InstallClaude ¶
func (cs *ClaudeSetup) InstallClaude() error
func (*ClaudeSetup) IsAuthenticationNeeded ¶
func (cs *ClaudeSetup) IsAuthenticationNeeded(output string) bool
func (*ClaudeSetup) IsInstalled ¶
func (cs *ClaudeSetup) IsInstalled() bool
func (*ClaudeSetup) RunClaudeLogin ¶
func (cs *ClaudeSetup) RunClaudeLogin() error
func (*ClaudeSetup) SetAuthToken ¶
func (cs *ClaudeSetup) SetAuthToken(apiKey string) error
SetAuthToken sets the authentication token programmatically
func (*ClaudeSetup) Setup ¶
func (cs *ClaudeSetup) Setup() error
func (*ClaudeSetup) SetupClaudeHome ¶
func (cs *ClaudeSetup) SetupClaudeHome() error
func (*ClaudeSetup) StartNonInteractiveAuth ¶
func (cs *ClaudeSetup) StartNonInteractiveAuth() (string, chan error)
StartNonInteractiveAuth initiates non-interactive authentication It returns the auth URL and a channel that will receive the result
func (*ClaudeSetup) WaitForAuth ¶
func (cs *ClaudeSetup) WaitForAuth(timeout time.Duration) error
WaitForAuth waits for authentication to be completed This can be used after SetAuthToken to verify authentication worked
type Config ¶
type Config struct {
Port string `json:"port"`
ClaudePath string `json:"claude_path"`
MaxProcesses int `json:"max_processes"`
Endpoints map[string]string `json:"endpoints,omitempty"`
AllowOrigins []string `json:"allow_origins,omitempty"`
TempDirBase string `json:"temp_dir_base,omitempty"`
}
func DefaultConfig ¶
func DefaultConfig() *Config
func LoadConfig ¶
type Connection ¶
type Connection struct {
// contains filtered or unexported fields
}
type ConnectionV2 ¶
type ConnectionV2 struct {
// contains filtered or unexported fields
}
type ConversationState ¶
type Options ¶
type Options struct {
// Port is the port number for the WebSocket server.
// Default: "8080"
Port string
// BaseDir is the directory where Claude and Bun will be installed.
// Each instance should have a unique BaseDir for isolation.
// Default: current directory
BaseDir string
// AutoSetup automatically installs Claude and Bun if not present.
// Default: true
AutoSetup bool
// MaxProcesses limits the number of concurrent Claude processes.
// Default: 100
MaxProcesses int
// EnableLogging enables detailed logging output.
// Default: true
EnableLogging bool
// CustomClaudePath allows specifying a custom Claude executable path.
// If empty, uses the isolated installation.
CustomClaudePath string
// APIKey provides the Claude API key for non-interactive authentication.
// If provided, the library will automatically authenticate without user interaction.
APIKey string
// AuthCallback is called when authentication is needed.
// If provided, this will be used instead of interactive authentication.
// The callback receives the auth URL and should return the API key.
AuthCallback func(authURL string) (string, error)
}
Options configures the Claude relay server.
type Relay ¶
type Relay struct {
// contains filtered or unexported fields
}
Relay represents a Claude WebSocket relay server instance.
func New ¶
New creates a new Claude relay instance with the given options.
Example:
relay, err := clauderelay.New(clauderelay.Options{
Port: "8081",
BaseDir: "./my-claude",
})
func (*Relay) Authenticate ¶
Authenticate runs the Claude authentication process interactively. This should be called when IsAuthenticated returns false.
Example:
authenticated, _ := relay.IsAuthenticated()
if !authenticated {
fmt.Println("Please complete Claude authentication:")
if err := relay.Authenticate(); err != nil {
log.Fatal(err)
}
}
func (*Relay) AuthenticateWithCallback ¶
AuthenticateWithCallback performs non-interactive authentication using a callback. The callback receives the auth URL and should return the API key.
Example:
err := relay.AuthenticateWithCallback(func(authURL string) (string, error) {
fmt.Printf("Please visit: %s\n", authURL)
fmt.Print("Enter your API key: ")
var apiKey string
fmt.Scanln(&apiKey)
return apiKey, nil
})
func (*Relay) Close ¶
Close stops the server and cleans up resources. It's safe to call Close multiple times.
Example:
defer relay.Close()
func (*Relay) GetAuthStatus ¶
GetAuthStatus returns detailed authentication status. Returns: (isAuthenticated, statusMessage, error)
func (*Relay) GetAuthURL ¶
GetAuthURL returns the URL where users can get their API key. Use this for non-interactive authentication flows.
Example:
url, _ := relay.GetAuthURL()
fmt.Printf("Get your API key at: %s\n", url)
// ... show URL to user ...
relay.SetAuthToken(apiKey)
func (*Relay) GetBaseDir ¶
GetBaseDir returns the base directory for this Claude instance.
func (*Relay) GetSetup ¶
func (r *Relay) GetSetup() *ClaudeSetup
GetSetup returns the underlying ClaudeSetup instance for advanced usage.
func (*Relay) GetWebSocketURL ¶
GetWebSocketURL returns the WebSocket URL for connecting to this relay.
func (*Relay) IsAuthenticated ¶
IsAuthenticated checks if Claude is authenticated.
func (*Relay) IsInstalled ¶
IsInstalled checks if Claude and Bun are installed.
func (*Relay) SetAuthToken ¶
SetAuthToken sets the API key for non-interactive authentication. This method allows programmatic authentication without terminal access.
Example:
// Get API key from environment, database, or user input
apiKey := os.Getenv("CLAUDE_API_KEY")
if err := relay.SetAuthToken(apiKey); err != nil {
log.Fatal(err)
}
func (*Relay) Setup ¶
Setup installs Claude and Bun if not already installed. This is called automatically if AutoSetup is true.
func (*Relay) Start ¶
Start starts the WebSocket relay server. The server runs in the background and returns immediately.
Example:
if err := relay.Start(); err != nil {
log.Fatal(err)
}
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
func NewServer ¶
func NewServer(config *Config, setup *ClaudeSetup) *Server
func (*Server) HandleWebSocket ¶
func (s *Server) HandleWebSocket(w http.ResponseWriter, r *http.Request)
type ServerV2 ¶
type ServerV2 struct {
// contains filtered or unexported fields
}
func NewServerV2 ¶
func (*ServerV2) HandleWebSocketV2 ¶
func (s *ServerV2) HandleWebSocketV2(w http.ResponseWriter, r *http.Request)
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
claude-relay
command
Command claude-relay starts a WebSocket relay server for Claude Code CLI.
|
Command claude-relay starts a WebSocket relay server for Claude Code CLI. |
|
examples
|
|
|
auth-apikey
command
Example of non-interactive authentication using API key.
|
Example of non-interactive authentication using API key. |
|
auth-callback
command
Example of non-interactive authentication using a callback function.
|
Example of non-interactive authentication using a callback function. |
|
basic
command
Basic example of using the clauderelay library.
|
Basic example of using the clauderelay library. |
|
embedded
command
Example of embedding Claude relay in an existing HTTP server.
|
Example of embedding Claude relay in an existing HTTP server. |
|
multiple
command
Example of running multiple isolated Claude instances.
|
Example of running multiple isolated Claude instances. |
|
webservice
command
Example of using Claude relay in a web service with non-interactive authentication.
|
Example of using Claude relay in a web service with non-interactive authentication. |