Skip to content

zidane/contexts/docker

An execution context that runs commands and file operations inside a local Docker container.

import { … } from 'zidane/contexts/docker'src/contexts/docker.ts

Use createDockerContext when you want a disposable environment on your machine. Each spawn starts a container through dockerode, an optional peer dependency, and destroy removes it. The helpers here build bind mounts and pack files into tar archives for container transfers.

TypeScript
import { createDockerContext } from 'zidane/contexts/docker'

const context = createDockerContext({ image: 'node:22', cwd: '/workspace', limits: { memory: 512, cpu: '1.0' } })
const handle = await context.spawn()
const result = await context.exec(handle, 'node --version')
console.log(result.stdout)
await context.destroy(handle)

Functions#

buildBindSpecsFunction#

Assemble dockerode HostConfig.Binds from the context's mounts.

TypeScript
function buildBindSpecs(mounts: ContextMount[]): string[]
Parameters
NameTypeDescription
mountsContextMount[]

Mounts to convert. Throws when a source or target is missing or a mount is both read-only and shared.

string[]

src/contexts/docker-spawn.ts:28

createDockerContextFunction#

Creates an execution context that runs commands and file operations inside a Docker container. Each spawn starts a container through dockerode, an optional peer dependency, and destroy removes it. Resource limits, mounts and hardening come from the spawn config.

TypeScript
function createDockerContext(config?: SpawnConfig): ExecutionContext
Parameters
NameTypeDescription
config?SpawnConfig

Default spawn settings, such as image, cwd, mounts and limits.

Example
import { createAgent } from 'zidane'
import { createDockerContext } from 'zidane/contexts/docker'
import { basic } from 'zidane/presets'
import { anthropic } from 'zidane/providers/anthropic'

const agent = createAgent({
  ...basic,
  provider: anthropic(),
  execution: createDockerContext({ image: 'node:22', cwd: '/workspace' }),
})

src/contexts/docker.ts:54

hostWorkspaceMountsFunction#

Path-equal bind mounts that make a HOST working directory usable inside a container: the enclosing git worktree (or cwd itself outside git) at the same absolute path, plus the git common dir when it lives outside that tree (a linked worktree's .git file points there — without it, git fails in the container). Path-equal keeps host-side features (diffs, artifacts, @-paths) valid for the same absolute paths the agent sees.

The git dir's hooks/ and config (plus config.worktree when present or enabled) are overlaid read-only — created empty first if absent: host-side git (zidane's own diff/workspace calls included) would otherwise run hooks or core.fsmonitor / core.hooksPath planted from inside the container. Deliberate cost: git commands that WRITE config fail inside the container — git push -u / --set-upstream, git branch --set-upstream-to, git remote add, git config …. Commits, fetches and a plain git push <remote> <branch> work; environments that publish a branch must push without recording an upstream.

Returns [] when cwd is not an existing host directory, so a container-only path (--cwd /workspace) stays a path inside the container, and when the tree to mount is /, $HOME, or an ancestor of $HOME (too broad to hand a container read-write). A git root that is too broad falls back to cwd alone (no git dir), so a dotfiles repo at $HOME doesn't blank every project under it.

TypeScript
function hostWorkspaceMounts(cwd: string): ContextMount[]
Parameters
NameTypeDescription
cwdstring

Absolute host directory the agent works in.

src/contexts/docker.ts:169

packTarFileFunction#

Pack a single file into an in-memory tar archive for putArchive, via tar-stream (the same battle-tested packer the dockerode ecosystem uses for build contexts). Optional peer dependency, loaded lazily like dockerode itself so the module graph stays lean for non-docker users.

TypeScript
function packTarFile(name: string, data: Buffer): Promise<Buffer<ArrayBufferLike>>
Parameters
NameTypeDescription
namestring

Entry name inside the archive.

dataBuffer

File contents.

Promise<Buffer<ArrayBufferLike>>

src/contexts/docker-files.ts:151

Constants#

READ_FILE_MAX_BUFFERConstant#

readFile transport cap: headroom above the whole-read tool ceiling (256MB in tools/whole-read-guard.ts) so tool policy — not the docker transport — decides read limits, keeping refusal behavior consistent across contexts. Still bounded: a probe-failure path can't buffer more than this into host memory.

TypeScript
const READ_FILE_MAX_BUFFER: number

src/contexts/docker-files.ts:23