An Unofficial Go SDK for the OpenAI Codex CLI.
go get github.com/thealish/codex-sdk-go- Go 1.25.5 or later
- OpenAI Codex CLI installed (
codexbinary in PATH or specify path) - OpenAI API key
package main
import (
"context"
"fmt"
"log"
"github.com/thealish/codex-sdk-go"
"github.com/thealish/codex-sdk-go/thread"
)
func main() {
// Create a new Codex instance
client := codex.New()
defer client.Close()
// Start a new thread
t, err := client.StartThread(&thread.ThreadOptions{
Model: "gpt-5.2-codex",
SandboxMode: thread.SandboxModeWorkspaceWrite,
})
if err != nil {
log.Fatal(err)
}
defer t.Close()
// Run a prompt
ctx := context.Background()
response, err := t.Run(ctx, "Diagnose the test failure and propose a fix")
if err != nil {
log.Fatal(err)
}
fmt.Println(response.FinalResponse)
}The SDK uses the OPENAI_API_KEY environment variable by default. You can also set it programmatically:
client := codex.New(codex.WithAPIKey("your-api-key"))If the codex binary is not in your PATH:
client := codex.New(codex.WithBinaryPath("/path/to/codex"))For custom API endpoints:
client := codex.New(codex.WithBaseURL("https://custom-api.example.com"))opts := &thread.ThreadOptions{
Model: "o3", // Model to use
SandboxMode: thread.SandboxModeWorkspaceWrite, // Sandbox permissions
ApprovalPolicy: thread.ApprovalModeOnRequest, // When to ask for approval
ModelReasoningEffort: thread.ModelReasoningEffortMedium, // Reasoning effort level
WorkingDirectory: "/path/to/project", // Working directory
NetworkAccessEnabled: true, // Allow network access
WebSearchMode: thread.WebSearchModeLive, // Web search mode
}SandboxModeReadOnly- Read-only accessSandboxModeWorkspaceWrite- Write access to workspaceSandboxModeDangerFullAccess- Full filesystem access (dangerous)
ApprovalModeNever- Never ask for approvalApprovalModeOnRequest- Ask when agent requestsApprovalModeOnFailure- Ask on failureApprovalModeUntrusted- Ask for untrusted operations
ModelReasoningEffortMinimalModelReasoningEffortLowModelReasoningEffortMediumModelReasoningEffortHighModelReasoningEffortXHigh
events, err := t.Stream(ctx, "Write a hello world program")
if err != nil {
log.Fatal(err)
}
for event := range events {
fmt.Printf("Event: %s\n", event.Type)
if event.Item != nil {
fmt.Printf(" Item Type: %s\n", event.Item.Type)
}
}Threads are persisted in ~/.codex/sessions. You can resume a previous thread:
t, err := client.ResumeThread("thread-id-from-previous-session")
if err != nil {
log.Fatal(err)
}
response, err := t.Run(ctx, "Continue with the fix")Set a custom approval handler:
t.SetApprovalHandler(func(req thread.ApprovalRequest) (bool, string) {
fmt.Printf("Approval requested: %s\n", req.Description)
// Custom logic to approve/deny
if req.Type == thread.ApprovalTypeCommand {
// Auto-approve safe commands
return true, ""
}
// Deny with reason
return false, "Operation not allowed"
})The SDK supports these item types:
ItemTypeUserMessage- User inputItemTypeAgentMessage- Agent responseItemTypeReasoning- Agent reasoningItemTypeCommandExecution- Shell command executionItemTypeFileChange- File modificationsItemTypeMCPToolCall- MCP tool callsItemTypeWebSearch- Web search resultsItemTypeImageView- Image viewing
MIT