environment

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2025 License: Apache-2.0 Imports: 14 Imported by: 0

README

Environments

An environment is an isolated, containerized development workspace that combines Docker containers with Git branches to provide agents with safe, persistent workspaces.

What is an Environment?

Each environment consists of:

  • Git Branch: Dedicated branch tracking all changes and history
  • Container: Dagger container with your code and dependencies
  • History: Versioned snapshots of container state changes appended to the branch as notes
  • Configuration: Base image, setup commands, secrets, and instructions that can be checked into the source repo.

Key Features

  • Branch-Based: Each environment is a Git branch that syncs into the container-use/ remote
  • Isolation: Each environment runs in its own container and branch
  • Persistence: All changes automatically committed with full history
  • Standard Git:
    • Use git log to view source code history
    • Use git log --notes=container-use to view container operation history
    • Use git checkout env-branch to inspect any environment's work - each env branch tracks the upstream container-use/
  • State Recovery: Container states stored in Git notes for reconstruction

How It Works

When you create an environment, container-use:

  1. Creates a new Git branch in your source repo (e.g., env-name/adverb-animal)
  2. Sets up a container-use remote branch inside ~/.config/container-use/repos/project/
  3. Sets up a worktree copy of the branch in ~/.config/container-use/worktrees/project/
  4. Spins up a Dagger container with that worktree copied into /workdir

When an agent runs commands:

  1. Commands execute inside the isolated container
  2. File changes get written back to the container filesystem
  3. Container state is preserved in the Dagger container's LLB definition
  4. Everything gets committed to the environment's Git branch automatically
  5. Container state snapshots are stored as Git notes using container-use-state ref
  6. Operation logs are stored as Git notes using container-use ref

Each environment is just a Git branch that your source repo tracks on the container-use/ remote. You can inspect any environment's work using standard Git commands, and the container state can always be reconstructed from an environment branch's Git history and notes.

Architecture

projectName/ Source Repo                container-use/ Remote
├── feature-branch ←──── cu merge/apply ────────┐
├── main (current) ── environment_create ──→ adverb-animal
└── cu-adverb-animal ←──── cu checkout ───────────┘
                                       │
                                       │ (host filesystem implementation)
                                       ▼
                    ~/.config/container-use/
                    ├── repos/projectName/ (bare)
                    └── worktrees/adverb-animal (only env branches become worktrees)
                        ├── .git -> ../../repos/projectName/worktrees/adverb-animal
                        └── (your code)
                            │
                            ▼
                        Container
                        └── /workdir

The diagram shows how environment branches sync between your source repo and the container-use remote. When you create an environment, the current branch content gets pushed to the container-use remote as adverb-animal. When you checkout an environment, it creates a local tracking branch cu-adverb-animal that tracks the remote environment branch. Regular branches like main and feature-branch stay only in your source repo.

You can accept the environment's work into your current branch using either:

  • cu merge - Preserves the agent's commit history
  • cu apply - Stages changes for you to commit with your own message

Below the branch level, the system creates a bare Git repository and worktree in ~/.config/container-use/ - this is plumbing to make the Git operations work with minimal modifications to your source repository. The worktree contains a copy of your code that gets mounted into the Docker container at /workdir.

So the flow is: Branch (the logical environment) → Worktree (filesystem implementation) → Container (where code actually runs).

Files

  • environment.go - Core environment management and container operations
  • config.go - Configuration management and persistence
  • state.go - Container state serialization and legacy migration
  • service.go - Service management for multi-container environments
  • note.go - Git notes management for operation logging
  • filesystem.go - File operations within containers
  • ../repository/git.go - Worktree and Git integration
  • ../repository/repository.go - High-level repository operations

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type EndpointMapping

type EndpointMapping struct {
	EnvironmentInternal string `json:"environment_internal"`
	HostExternal        string `json:"host_external"`
}

type EndpointMappings

type EndpointMappings map[int]*EndpointMapping

type Environment

type Environment struct {
	*EnvironmentInfo

	Services []*Service
	Notes    Notes
	// contains filtered or unexported fields
}

func Load added in v0.1.0

func Load(ctx context.Context, dag *dagger.Client, id string, state []byte, worktree string) (*Environment, error)

func New added in v0.1.0

func New(ctx context.Context, dag *dagger.Client, id, title string, config *EnvironmentConfig, initialSourceDir *dagger.Directory) (*Environment, error)

func (*Environment) AddService added in v0.0.3

func (env *Environment) AddService(ctx context.Context, explanation string, cfg *ServiceConfig) (*Service, error)

func (*Environment) Checkpoint

func (env *Environment) Checkpoint(ctx context.Context, target string) (string, error)

func (*Environment) FileDelete

func (env *Environment) FileDelete(ctx context.Context, explanation, targetFile string) error

func (*Environment) FileEdit added in v0.4.1

func (env *Environment) FileEdit(ctx context.Context, explanation, targetFile, search, replace, matchID string) error

func (*Environment) FileList

func (env *Environment) FileList(ctx context.Context, path string) (string, error)

func (*Environment) FileRead

func (env *Environment) FileRead(ctx context.Context, targetFile string, shouldReadEntireFile bool, startLineOneIndexedInclusive int, endLineOneIndexedInclusive int) (string, error)

func (*Environment) FileWrite

func (env *Environment) FileWrite(ctx context.Context, explanation, targetFile, contents string) error

func (*Environment) Run

func (env *Environment) Run(ctx context.Context, command, shell string, useEntrypoint bool) (string, error)

func (*Environment) RunBackground

func (env *Environment) RunBackground(ctx context.Context, command, shell string, ports []int, useEntrypoint bool) (EndpointMappings, error)

func (*Environment) Terminal

func (env *Environment) Terminal(ctx context.Context) error

func (*Environment) UpdateConfig added in v0.0.3

func (env *Environment) UpdateConfig(ctx context.Context, newConfig *EnvironmentConfig) error

func (*Environment) Workdir

func (env *Environment) Workdir() *dagger.Directory

type EnvironmentConfig added in v0.0.3

type EnvironmentConfig struct {
	Workdir         string         `json:"workdir,omitempty"`
	BaseImage       string         `json:"base_image,omitempty"`
	SetupCommands   []string       `json:"setup_commands,omitempty"`
	InstallCommands []string       `json:"install_commands,omitempty"`
	Env             KVList         `json:"env,omitempty"`
	Secrets         KVList         `json:"secrets,omitempty"`
	Services        ServiceConfigs `json:"services,omitempty"`
}

func DefaultConfig added in v0.0.3

func DefaultConfig() *EnvironmentConfig

func (*EnvironmentConfig) Copy added in v0.0.3

func (config *EnvironmentConfig) Copy() *EnvironmentConfig

func (*EnvironmentConfig) Load added in v0.0.3

func (config *EnvironmentConfig) Load(baseDir string) error

func (*EnvironmentConfig) Save added in v0.0.3

func (config *EnvironmentConfig) Save(baseDir string) error

type EnvironmentInfo added in v0.1.0

type EnvironmentInfo struct {
	State *State `json:"state,omitempty"`

	ID string `json:"id,omitempty"`
}

EnvironmentInfo contains basic metadata about an environment without requiring dagger operations

func LoadInfo added in v0.1.0

func LoadInfo(ctx context.Context, id string, state []byte, worktree string) (*EnvironmentInfo, error)

LoadInfo loads basic environment metadata without requiring dagger operations. This is useful for operations that only need access to configuration and state information without the overhead of initializing container operations.

type KVList added in v0.3.0

type KVList []string

KVList represents a list of key-value pairs in the format KEY=VALUE

func (*KVList) Clear added in v0.3.0

func (kv *KVList) Clear()

Clear removes all key-value pairs

func (KVList) Get added in v0.3.0

func (kv KVList) Get(key string) string

Get returns the value for a given key, or empty string if not found

func (KVList) Keys added in v0.3.0

func (kv KVList) Keys() []string

Keys returns all keys in the list

func (*KVList) Set added in v0.3.0

func (kv *KVList) Set(key, value string)

Set adds or updates a key-value pair

func (*KVList) Unset added in v0.3.0

func (kv *KVList) Unset(key string) bool

Unset removes a key-value pair by key and returns true if the key was found

type Notes added in v0.1.0

type Notes struct {
	// contains filtered or unexported fields
}

func (*Notes) Add added in v0.1.0

func (n *Notes) Add(format string, a ...any)

func (*Notes) AddCommand added in v0.2.0

func (n *Notes) AddCommand(command string, exitCode int, stdout, stderr string)

func (*Notes) Clear added in v0.1.0

func (n *Notes) Clear()

func (*Notes) Pop added in v0.1.0

func (n *Notes) Pop() string

func (*Notes) String added in v0.1.0

func (n *Notes) String() string

type Service added in v0.0.3

type Service struct {
	Config    *ServiceConfig   `json:"config"`
	Endpoints EndpointMappings `json:"endpoints"`
	// contains filtered or unexported fields
}

type ServiceConfig added in v0.0.3

type ServiceConfig struct {
	Name         string   `json:"name,omitempty"`
	Image        string   `json:"image,omitempty"`
	Command      string   `json:"command,omitempty"`
	ExposedPorts []int    `json:"exposed_ports,omitempty"`
	Env          []string `json:"env,omitempty"`
}

type ServiceConfigs added in v0.0.3

type ServiceConfigs []*ServiceConfig

func (ServiceConfigs) Get added in v0.0.3

func (sc ServiceConfigs) Get(name string) *ServiceConfig

type State added in v0.1.0

type State struct {
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	Config    *EnvironmentConfig `json:"config,omitempty"`
	Container string             `json:"container,omitempty"`
	Title     string             `json:"title,omitempty"`
}

func (*State) Marshal added in v0.1.0

func (s *State) Marshal() ([]byte, error)

func (*State) Unmarshal added in v0.1.0

func (s *State) Unmarshal(data []byte) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL