Documentation
¶
Overview ¶
Package devcontainer manages devcontainer lifecycle: parsing devcontainer.json, building images, creating/starting/stopping containers, and executing commands.
Index ¶
- Constants
- Variables
- func ConfigHash(data []byte) string
- func ContainerName(projectDir string) string
- func DeleteMeta(name string) error
- func DevcontainersDir() string
- func FindConfig(projectDir string) (string, error)
- func ImageName(projectDir, configHash string) string
- func InstallFeatures(ctx context.Context, docker DockerClient, puller FeaturePuller, ...) (map[string]string, error)
- func ManagedLabels(projectDir, name, configHash string) map[string]string
- func MetaPath(name string) string
- func ParseRunArgs(args []string, opts *ContainerCreateOptions, logger zerolog.Logger)
- func RunHook(ctx context.Context, docker DockerClient, containerID, user string, ...) error
- func RunLifecycleHooks(ctx context.Context, docker DockerClient, containerID, user string, ...) error
- func SanitizeName(name string) string
- func StripJSONC(data []byte) []byte
- func WriteMeta(m Meta) error
- type BuildConfig
- type ContainerConfigInfo
- type ContainerCreateOptions
- type ContainerInspectResponse
- type ContainerListOptions
- type ContainerRemoveOptions
- type ContainerState
- type ContainerSummary
- type DevcontainerConfig
- type DockerClient
- type ExecAttachResponse
- type ExecInspectResponse
- type ExecOptions
- type FeatureMeta
- type FeatureOption
- type FeaturePuller
- type HumanConfig
- type ImageBuildOptions
- type ImageBuilder
- type ImageInspectResponse
- type ImageListOptions
- type ImagePullOptions
- type ImageSummary
- type LogsOptions
- type Manager
- func (m *Manager) Down(ctx context.Context, name string, removeVolumes bool) error
- func (m *Manager) Exec(ctx context.Context, containerID string, cmd []string, user string, ...) (int, error)
- func (m *Manager) List(ctx context.Context) ([]Meta, error)
- func (m *Manager) Status(ctx context.Context, name string) (*Meta, error)
- func (m *Manager) Stop(ctx context.Context, name string) error
- func (m *Manager) Up(ctx context.Context, opts UpOptions) (*Meta, error)
- type Meta
- type OCIFeaturePuller
- type Status
- type UpOptions
Constants ¶
const ( LabelManaged = "dev.human.managed" // "true" LabelProject = "dev.human.project" // absolute path to project dir LabelConfigHash = "dev.human.config-hash" // SHA256 of devcontainer.json LabelName = "dev.human.name" // human-friendly name )
Docker labels for identifying human-managed devcontainers.
Variables ¶
var StdCopy = stdcopy.StdCopy
StdCopy re-exports stdcopy.StdCopy so callers within the devcontainer package can demux exec output without importing the Docker SDK directly.
Functions ¶
func ConfigHash ¶
ConfigHash returns a hex-encoded SHA256 hash of devcontainer.json content.
func ContainerName ¶
ContainerName returns the Docker container name for a devcontainer. Format: human-dc-<project>
func DeleteMeta ¶
DeleteMeta removes the devcontainer metadata file from disk.
func DevcontainersDir ¶
func DevcontainersDir() string
DevcontainersDir returns the directory where devcontainer metadata is stored.
func FindConfig ¶
FindConfig locates the devcontainer.json file for a project directory. Search order: .devcontainer/devcontainer.json, then .devcontainer.json.
func ImageName ¶
ImageName returns the Docker image tag for a devcontainer build. Format: human-dc-<project>:<hash12>
func InstallFeatures ¶
func InstallFeatures(ctx context.Context, docker DockerClient, puller FeaturePuller, containerID string, features map[string]interface{}, remoteUser string, logger zerolog.Logger, out io.Writer) (map[string]string, error)
InstallFeatures downloads and installs devcontainer features into a running container using exec. Each feature's install.sh is copied in via base64 encoding, then executed with the appropriate option environment variables. InstallFeatures installs each feature into the container and returns the accumulated containerEnv contributed by the features. A feature's containerEnv (e.g. the node feature putting node/npm on PATH) must reach both the features installed after it and the committed image — otherwise a dependent feature like claude-code can't find node and fails. The returned map is baked into the image by the caller via ContainerCommit.
func ManagedLabels ¶
ManagedLabels returns the standard set of labels for a human-managed container.
func ParseRunArgs ¶
func ParseRunArgs(args []string, opts *ContainerCreateOptions, logger zerolog.Logger)
ParseRunArgs translates devcontainer.json runArgs (Docker CLI flags) into ContainerCreateOptions fields. Unknown flags are logged as warnings.
func RunHook ¶
func RunHook(ctx context.Context, docker DockerClient, containerID, user string, cmd interface{}, logger zerolog.Logger) error
RunHook executes a lifecycle command inside a container. The cmd parameter follows the devcontainer.json spec:
- string: run via /bin/sh -c "<string>"
- []interface{}: run as a direct command (each element is a string arg)
- map[string]interface{}: run each value in parallel (keys are labels)
Returns nil if cmd is nil (hook not defined).
func RunLifecycleHooks ¶
func RunLifecycleHooks(ctx context.Context, docker DockerClient, containerID, user string, cfg *DevcontainerConfig, logger zerolog.Logger, out io.Writer) error
RunLifecycleHooks executes the devcontainer lifecycle hooks in order inside a container. Sequence: onCreateCommand -> updateContentCommand -> postCreateCommand -> postStartCommand
func SanitizeName ¶
SanitizeName converts a project directory basename into a Docker-safe name. Lowercased, non-alphanumeric chars replaced with hyphens, trimmed.
func StripJSONC ¶
StripJSONC removes // line comments and /* */ block comments from JSONC input, preserving content inside JSON string literals.
Types ¶
type BuildConfig ¶
type BuildConfig struct {
Dockerfile string `json:"dockerfile,omitempty"`
Context string `json:"context,omitempty"`
Args map[string]string `json:"args,omitempty"`
Target string `json:"target,omitempty"`
CacheFrom []string `json:"cacheFrom,omitempty"`
}
BuildConfig holds Dockerfile build configuration.
type ContainerConfigInfo ¶
ContainerConfigInfo holds container configuration from inspection.
type ContainerCreateOptions ¶
type ContainerCreateOptions struct {
Name string
Image string
Cmd []string
Env []string // KEY=VALUE pairs
Labels map[string]string
WorkingDir string
User string
ExtraHosts []string // "host:ip" entries for /etc/hosts
Binds []string // "src:dst[:opts]" bind mounts
CapAdd []string // added capabilities
SecurityOpt []string // security options
Privileged bool
NetworkMode string
ShmSize int64
}
ContainerCreateOptions bundles all parameters for creating a container. The implementation maps these to separate Docker SDK parameters.
type ContainerInspectResponse ¶
type ContainerInspectResponse struct {
ID string
Name string
State ContainerState
Image string
Config ContainerConfigInfo
}
ContainerInspectResponse holds container inspection results.
type ContainerListOptions ¶
type ContainerListOptions struct {
All bool // include stopped containers
LabelFilters map[string]string // label key=value pairs
NameFilter string // filter by container name (Docker regex match)
}
ContainerListOptions filters container listing.
type ContainerRemoveOptions ¶
ContainerRemoveOptions configures container removal.
type ContainerState ¶
type ContainerState struct {
Status string // "running", "exited", "created", etc.
Running bool
ExitCode int
}
ContainerState represents the container's runtime state.
type ContainerSummary ¶
type ContainerSummary struct {
ID string
Names []string
Image string
State string // "running", "exited", etc.
Labels map[string]string
}
ContainerSummary holds basic container metadata from listing.
type DevcontainerConfig ¶
type DevcontainerConfig struct {
Name string `json:"name,omitempty"`
Image string `json:"image,omitempty"`
Build *BuildConfig `json:"build,omitempty"`
DockerFile string `json:"dockerFile,omitempty"`
Features map[string]interface{} `json:"features,omitempty"`
Mounts []interface{} `json:"mounts,omitempty"`
RunArgs []string `json:"runArgs,omitempty"`
ForwardPorts []interface{} `json:"forwardPorts,omitempty"`
RemoteEnv map[string]string `json:"remoteEnv,omitempty"`
ContainerEnv map[string]string `json:"containerEnv,omitempty"`
RemoteUser string `json:"remoteUser,omitempty"`
ContainerUser string `json:"containerUser,omitempty"`
WorkspaceFolder string `json:"workspaceFolder,omitempty"`
CapAdd []string `json:"capAdd,omitempty"`
SecurityOpt []string `json:"securityOpt,omitempty"`
Privileged bool `json:"privileged,omitempty"`
OverrideCommand *bool `json:"overrideCommand,omitempty"`
InitializeCommand interface{} `json:"initializeCommand,omitempty"`
OnCreateCommand interface{} `json:"onCreateCommand,omitempty"`
UpdateContentCommand interface{} `json:"updateContentCommand,omitempty"`
PostCreateCommand interface{} `json:"postCreateCommand,omitempty"`
PostStartCommand interface{} `json:"postStartCommand,omitempty"`
PostAttachCommand interface{} `json:"postAttachCommand,omitempty"`
}
DevcontainerConfig represents a parsed devcontainer.json. Supports the subset of the spec needed for image-based and Dockerfile-based configs.
func ParseConfig ¶
func ParseConfig(data []byte) (*DevcontainerConfig, error)
ParseConfig parses a devcontainer.json file, handling JSONC (comments).
func ReadConfig ¶
func ReadConfig(projectDir string) (*DevcontainerConfig, error)
ReadConfig finds and parses the devcontainer.json for a project directory.
func ResolveVariables ¶
func ResolveVariables(cfg *DevcontainerConfig, projectDir string) *DevcontainerConfig
ResolveVariables replaces devcontainer.json variable placeholders in string fields. Supported: ${localEnv:VAR}, ${localWorkspaceFolder}, ${localWorkspaceFolderBasename}.
type DockerClient ¶
type DockerClient interface {
// Image operations
ImageBuild(ctx context.Context, buildContext io.Reader, opts ImageBuildOptions) (io.ReadCloser, error)
ImagePull(ctx context.Context, ref string, opts ImagePullOptions) (io.ReadCloser, error)
ImageInspect(ctx context.Context, imageRef string) (ImageInspectResponse, error)
ImageList(ctx context.Context, opts ImageListOptions) ([]ImageSummary, error)
// Container lifecycle
ContainerCreate(ctx context.Context, opts ContainerCreateOptions) (string, error)
ContainerStart(ctx context.Context, containerID string) error
ContainerStop(ctx context.Context, containerID string, timeout *int) error
ContainerRemove(ctx context.Context, containerID string, opts ContainerRemoveOptions) error
ContainerInspect(ctx context.Context, containerID string) (ContainerInspectResponse, error)
ContainerList(ctx context.Context, opts ContainerListOptions) ([]ContainerSummary, error)
ContainerLogs(ctx context.Context, containerID string, opts LogsOptions) (io.ReadCloser, error)
// ContainerCommit commits the container as an image. env entries are baked
// into the image as ENV so feature-contributed variables (e.g. the node and
// go features' PATH additions) persist into containers created from the image.
ContainerCommit(ctx context.Context, containerID string, ref string, env map[string]string) (string, error)
// File transfer
CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader) error
// Exec for lifecycle hooks and user commands.
ExecCreate(ctx context.Context, containerID string, cmd []string, opts ExecOptions) (string, error)
ExecAttach(ctx context.Context, execID string) (ExecAttachResponse, error)
ExecInspect(ctx context.Context, execID string) (ExecInspectResponse, error)
Close() error
}
DockerClient abstracts Docker Engine operations for devcontainer management. The interface is intentionally simplified compared to the raw Docker SDK; the implementation in docker_engine.go handles the SDK-specific details.
func NewDockerClient ¶
func NewDockerClient() (DockerClient, error)
NewDockerClient creates a DockerClient backed by the Docker Engine API.
When DOCKER_HOST is unset, it resolves the active docker CLI context's endpoint (colima/OrbStack/Rancher/Docker-Desktop/Podman) so human reaches the engine out-of-the-box, mirroring what the docker CLI does. Explicit DOCKER_HOST / DOCKER_CONTEXT always win. The resolution is shared with claude.NewEngineDockerClient via internal/dockerhost so the two never diverge.
type ExecAttachResponse ¶
ExecAttachResponse wraps the exec attachment, providing access to stdout/stderr.
func (ExecAttachResponse) Close ¶
func (r ExecAttachResponse) Close() error
Close releases the underlying connection.
type ExecInspectResponse ¶
ExecInspectResponse holds exec process inspection results.
type ExecOptions ¶
type ExecOptions struct {
User string
WorkingDir string
Env []string // KEY=VALUE pairs
AttachStdout bool
AttachStderr bool
AttachStdin bool
Tty bool
}
ExecOptions configures command execution inside a container.
type FeatureMeta ¶
type FeatureMeta struct {
ID string `json:"id"`
Version string `json:"version"`
Name string `json:"name"`
Options map[string]FeatureOption `json:"options"`
InstallsAfter []string `json:"installsAfter"`
ContainerEnv map[string]string `json:"containerEnv"`
}
FeatureMeta is the parsed devcontainer-feature.json from a feature tarball.
type FeatureOption ¶
type FeatureOption struct {
Type string `json:"type"`
Default interface{} `json:"default"`
}
FeatureOption describes a single feature option.
type FeaturePuller ¶
type FeaturePuller interface {
Pull(ctx context.Context, ref string) (installSh []byte, meta *FeatureMeta, err error)
}
FeaturePuller abstracts OCI feature download for testability.
type HumanConfig ¶
type HumanConfig struct {
ConfigDir string `yaml:"configdir"`
}
HumanConfig holds devcontainer settings from .humanconfig.
func LoadHumanConfig ¶
func LoadHumanConfig(dir string) (*HumanConfig, error)
LoadHumanConfig reads the devcontainer section from .humanconfig.
type ImageBuildOptions ¶
type ImageBuildOptions struct {
Dockerfile string
Tags []string
BuildArgs map[string]*string
Target string
CacheFrom []string
Remove bool // remove intermediate containers
}
ImageBuildOptions configures an image build.
type ImageBuilder ¶
type ImageBuilder struct {
Docker DockerClient
Logger zerolog.Logger
// Puller fetches devcontainer features; defaults to an OCI registry puller
// when nil. Injectable so feature installation can be tested without a registry.
Puller FeaturePuller
}
ImageBuilder handles building or pulling devcontainer images.
func (*ImageBuilder) EnsureImage ¶
func (b *ImageBuilder) EnsureImage(ctx context.Context, cfg *DevcontainerConfig, projectDir, configHash string, rebuild bool, out io.Writer) (string, string, error)
EnsureImage ensures a devcontainer image exists. If not cached (or rebuild requested), it builds/pulls the image per the devcontainer config. Returns the image ID.
type ImageInspectResponse ¶
ImageInspectResponse holds image inspection results.
type ImageListOptions ¶
ImageListOptions filters image listing.
type ImagePullOptions ¶
type ImagePullOptions struct {
RegistryAuth string // base64-encoded auth for private registries
}
ImagePullOptions configures an image pull.
type ImageSummary ¶
ImageSummary holds basic image metadata.
type LogsOptions ¶
type LogsOptions struct {
Follow bool
Tail string // number of lines, e.g. "100"
ShowStdout bool
ShowStderr bool
}
LogsOptions configures container log retrieval.
type Manager ¶
type Manager struct {
Docker DockerClient
Logger zerolog.Logger
}
Manager orchestrates devcontainer lifecycle operations.
func (*Manager) Exec ¶
func (m *Manager) Exec(ctx context.Context, containerID string, cmd []string, user string, stdin io.Reader, stdout, stderr io.Writer) (int, error)
Exec runs a command inside a running devcontainer.
func (*Manager) List ¶
List returns metadata for all managed devcontainers, refreshing status from Docker.
type Meta ¶
type Meta struct {
Name string `json:"name"`
ProjectDir string `json:"project_dir"`
ContainerID string `json:"container_id"`
ContainerName string `json:"container_name"`
ImageID string `json:"image_id"`
ImageName string `json:"image_name"`
Status Status `json:"status"`
CreatedAt time.Time `json:"created_at"`
StartedAt time.Time `json:"started_at,omitempty"`
StoppedAt time.Time `json:"stopped_at,omitempty"`
WorkspaceDir string `json:"workspace_dir"`
RemoteUser string `json:"remote_user"`
DaemonAddr string `json:"daemon_addr,omitempty"`
ConfigHash string `json:"config_hash"`
}
Meta holds persisted metadata for a managed devcontainer.
type OCIFeaturePuller ¶
type OCIFeaturePuller struct{}
OCIFeaturePuller downloads devcontainer features from OCI registries.
func (*OCIFeaturePuller) Pull ¶
func (p *OCIFeaturePuller) Pull(_ context.Context, featureRef string) ([]byte, *FeatureMeta, error)
Pull downloads a devcontainer feature OCI artifact and returns the raw tarball bytes and parsed metadata.
type UpOptions ¶
type UpOptions struct {
ProjectDir string
Rebuild bool
DaemonInfo *daemon.DaemonInfo // nil = no daemon injection
Out io.Writer
ContainerName string // override container name (default: derived from project dir)
SourceDir string // override mount source (default: same as ProjectDir)
}
UpOptions configures the devcontainer up operation.