Go Library
Import Warden as a Go library for single-process deployment. No warden binary needed — your application initializes and controls the engine directly.
Quick start
Section titled “Quick start”import ( "github.com/thesimonho/warden" "github.com/thesimonho/warden/api")
func main() { w, err := warden.New(warden.Options{}) if err != nil { panic(err) } defer w.Close()
ctx := context.Background() result, err := w.Service.CreateContainer(ctx, api.CreateContainerRequest{ ProjectPath: "/path/to/repo", ProjectName: "my-project", }) if err != nil { panic(err) } fmt.Printf("Created project: %s (container: %s)\n", result.ProjectName, result.ContainerID)}Warden initialization
Section titled “Warden initialization”w, err := warden.New(warden.Options{ DBDir: "/path/to/db", // Optional: override default database location Runtime: "docker", // Optional: explicit runtime})if err != nil { return err}defer w.Close() // Idempotent; shuts down all subsystems (including session watchers)warden.New() initializes the engine, database, event bus, agent registry, starts session watchers for active containers, and pre-warms the CLI cache in the background (downloading pinned Claude Code and Codex versions to a shared Docker volume). w.Close() tears down all subsystems including any running session watchers.
Project management
Section titled “Project management”Create a project
Section titled “Create a project”result, err := w.Service.CreateContainer(ctx, api.CreateContainerRequest{ ProjectPath: "/workspace/path", ProjectName: "project-name", AgentType: "claude-code", // "claude-code" (default) or "codex" Image: "ubuntu:24.04", EnvVars: map[string]string{"USER": "alice", "OPENAI_API_KEY": os.Getenv("OPENAI_API_KEY")}, Mounts: []api.Mount{{HostPath: "/data", ContainerPath: "/data"}}, NetworkMode: api.NetworkModeFull, AllowedDomains: []string{"api.example.com"}, EnabledRuntimes: []string{"node", "python", "go"},})List projects
Section titled “List projects”projects, err := w.Service.ListProjects(ctx)for _, proj := range projects { fmt.Printf("%s: %s\n", proj.Name, proj.State)}Stop/Restart
Section titled “Stop/Restart”err := w.Service.StopProject(ctx, "project-id", "claude-code")err := w.Service.RestartProject(ctx, "project-id", "claude-code")Delete a project
Section titled “Delete a project”err := w.Service.DeleteContainer(ctx, "project-id", "claude-code")err := w.Service.RemoveProject("project-id", "claude-code")Reset project cost history
Section titled “Reset project cost history”err := w.Service.ResetProjectCosts("project-id", "claude-code")Purge project audit history
Section titled “Purge project audit history”deleted, err := w.Service.PurgeProjectAudit("project-id", "claude-code")Read a project template
Section titled “Read a project template”// Read a .warden.json from an arbitrary path (for import).tmpl, err := w.Service.ReadProjectTemplate("/path/to/.warden.json")if err != nil { return err}fmt.Printf("Image: %s, Network: %s\n", tmpl.Image, tmpl.NetworkMode)Templates are also automatically read during GetDefaults(projectPath) and written back to .warden.json on CreateContainer and UpdateContainer.
Get project and worktree status
Section titled “Get project and worktree status”projects, err := w.Service.ListProjects(ctx)projectID := projects[0].ProjectIDagentType := projects[0].AgentType
worktrees, err := w.Service.ListWorktrees(ctx, projectID, agentType)for _, wt := range worktrees { fmt.Printf(" - %s (state: %s)\n", wt.ID, wt.State)}Worktree management
Section titled “Worktree management”Create a worktree
Section titled “Create a worktree”result, err := w.Service.CreateWorktree(ctx, "project-id", "claude-code", "feature-branch")The agentType parameter specifies which agent manages the worktree ("claude-code" or "codex"). This must match the agent type used when creating the project.
Connect terminal (start agent)
Section titled “Connect terminal (start agent)”result, err := w.Service.ConnectTerminal(ctx, "project-id", "claude-code", "worktree-id")Disconnect terminal
Section titled “Disconnect terminal”result, err := w.Service.DisconnectTerminal(ctx, "project-id", "claude-code", "worktree-id")Kill worktree process
Section titled “Kill worktree process”result, err := w.Service.KillWorktreeProcess(ctx, "project-id", "claude-code", "worktree-id")Reset worktree
Section titled “Reset worktree”Clear session state (session files, terminal tracking) without removing the worktree:
result, err := w.Service.ResetWorktree(ctx, "project-id", "claude-code", "worktree-id")Remove worktree
Section titled “Remove worktree”result, err := w.Service.RemoveWorktree(ctx, "project-id", "claude-code", "worktree-id")Restart a worktree
Section titled “Restart a worktree”// Kill and reconnecterr := w.Service.KillWorktreeProcess(ctx, "project-id", "claude-code", "worktree-id")result, err := w.Service.ConnectTerminal(ctx, "project-id", "claude-code", "worktree-id")List worktrees
Section titled “List worktrees”worktrees, err := w.Service.ListWorktrees(ctx, "project-id", "claude-code")for _, wt := range worktrees { fmt.Printf("%s: state=%s, branch=%s\n", wt.ID, wt.State, wt.Branch)}Audit and event logging
Section titled “Audit and event logging”Enable event logging via settings and query audit events through the service:
// Enable detailed logging (off/standard/detailed)mode := api.AuditLogDetailedw.Service.UpdateSettings(ctx, api.UpdateSettingsRequest{ AuditLogMode: &mode,})Query audit events:
entries, err := w.Service.GetAuditLog(api.AuditFilters{ Category: api.AuditCategoryAgent, Container: "my-project", Limit: 100,})
summary, err := w.Service.GetAuditSummary(ctx, api.AuditFilters{})fmt.Printf("Sessions: %d, Tools: %d\n", summary.TotalSessions, summary.TotalToolUses)Export as CSV:
var buf bytes.Buffererr := w.Service.WriteAuditCSV(&buf, api.AuditFilters{ Container: "my-project",})Event subscription (real-time)
Section titled “Event subscription (real-time)”events, unsubscribe := w.Broker.Subscribe()defer unsubscribe()
for event := range events { switch event.Event { case eventbus.SSEWorktreeState: fmt.Printf("Worktree state: %s\n", string(event.Data)) case eventbus.SSEProjectState: fmt.Printf("Project state: %s\n", string(event.Data)) case eventbus.SSEBudgetExceeded: fmt.Printf("Budget exceeded: %s\n", string(event.Data)) case eventbus.SSEBudgetContainerStopped: // Includes containerId for matching against project views fmt.Printf("Container stopped by budget: %s\n", string(event.Data)) }}Lower-level API access
Section titled “Lower-level API access”For advanced operations, access the service layer or engine directly:
// Service methodserr := w.Service.ValidateContainer(ctx, "container-id")containers, err := w.Service.ListContainers(ctx)settings := w.Service.GetSettings()
// Engine client (advanced use only)config, err := w.Engine.InspectContainer(ctx, "container-id")Error handling
Section titled “Error handling”Service methods return error. Check for sentinel errors:
import "github.com/thesimonho/warden/service"
_, err := w.Service.RemoveProject("project-id", "claude-code")if errors.Is(err, service.ErrNotFound) { fmt.Println("Project not found")}if errors.Is(err, service.ErrInvalidInput) { fmt.Println("Invalid input")}Complete example
Section titled “Complete example”package main
import ( "context" "fmt" "log"
"github.com/thesimonho/warden" "github.com/thesimonho/warden/api")
func main() { ctx := context.Background()
// 1. Initialize Warden w, err := warden.New(warden.Options{}) if err != nil { log.Fatal(err) } defer w.Close()
// 2. Create container for a project containerResult, err := w.Service.CreateContainer(ctx, api.CreateContainerRequest{ ProjectPath: "/home/user/projects/my-app", ProjectName: "my-app", Image: "ubuntu:24.04", Mounts: []api.Mount{{HostPath: "/data", ContainerPath: "/data"}}, NetworkMode: api.NetworkModeFull, }) if err != nil { log.Fatal(err) } projectID := containerResult.ProjectID fmt.Printf("Created: %s (ID: %s)\n", containerResult.ProjectName, containerResult.ContainerID)
// 3. Create worktree wtResult, err := w.Service.CreateWorktree(ctx, projectID, "claude-code", "feature-branch") if err != nil { log.Fatal(err) }
// 4. Connect terminal (start agent) _, err = w.Service.ConnectTerminal(ctx, projectID, "claude-code", wtResult.WorktreeID) if err != nil { log.Fatal(err) }
// 5. Get worktree status worktrees, err := w.Service.ListWorktrees(ctx, projectID, "claude-code") if err != nil { log.Fatal(err) } fmt.Printf("Project status: %d worktrees\n", len(worktrees))
// 6. Clean up _, _ = w.Service.DisconnectTerminal(ctx, projectID, "claude-code", wtResult.WorktreeID) _ = w.Service.DeleteContainer(ctx, projectID, "claude-code") _ = w.Service.RemoveProject(projectID, "claude-code")}Reference
Section titled “Reference”- Entry point:
warden.New(Options) (*Warden, error) - Primary interface:
w.Service— all operations (containers, worktrees, settings, audit, access items) - Event bus:
w.Broker— subscribe to real-time events - Advanced access:
w.Engine— container runtime client,w.DB— SQLite store,w.Watcher— file-based event watcher - Go Packages: See the Go Packages reference for API documentation