Documentation
¶
Overview ¶
Package kit stages a docker-agent kit on the host before launching a sandbox.
A kit is a self-contained directory that bundles every host resource an agent will need at runtime — local skills, AGENTS.md/CLAUDE.md prompt files, sub-agent YAMLs — laid out under a fixed schema:
<kit>/skills/<skill-name>/ # local skills, recursively <kit>/prompt_files/<name> # collected add_prompt_files inputs <kit>/manifest.json # debug + cache key
The host stages the kit, redacts secrets via portcullis.Redact in every text file, and bind-mounts the kit read-only inside the sandbox. At runtime, the in-sandbox resolvers (skills.Load, promptfiles.Paths) consult skills.KitDirEnv to read from the kit instead of the user's $HOME — which doesn't exist inside the sandbox.
The kit solves four constraints inherent to the docker sandbox CLI:
- the user's $HOME inside the sandbox is unrelated to the host's;
- sandbox mounts target directories, not individual files;
- host files may contain secrets that must not leak;
- other host-only state (e.g. .agents/skills under a parent dir) is unreachable from the sandbox.
Index ¶
Constants ¶
const MountPath = "/agent-kit"
MountPath is the path at which the kit is bind-mounted inside the sandbox.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Entry ¶
type Entry struct {
// Source is the original host path. Omitted from the on-disk
// manifest so the sandbox cannot learn the host layout.
Source string `json:"-"`
// Target is the path relative to the kit root. Empty when the
// file isn't staged into the kit because it's already reachable
// inside the sandbox via the live workspace mount.
Target string `json:"target,omitempty"`
}
Entry records one staged file or directory.
type Manifest ¶
type Manifest struct {
AgentRef string `json:"agent_ref"`
BuiltAt time.Time `json:"built_at"`
Skills []Entry `json:"skills,omitempty"`
PromptFiles []Entry `json:"prompt_files,omitempty"`
Redactions []Redaction `json:"redactions,omitempty"`
}
Manifest is the kit's table of contents.
type Options ¶
type Options struct {
// AgentRef is the user-facing reference to the agent (a YAML path,
// an OCI ref, a URL or a builtin name). Used for cache keying and
// for loading the team config so the kit knows which prompt files
// and skills to ship.
AgentRef string
// EnvProvider is forwarded to [config.Resolve] so URL-sourced
// agents can pick up GITHUB_TOKEN. May be nil.
EnvProvider environment.Provider
// HostCwd is the host's working directory. Prompt-file lookups
// walk up from it the same way the in-sandbox runtime would.
HostCwd string
// HostHome overrides the host's $HOME for prompt-file lookups.
// Empty means "use os.UserHomeDir".
HostHome string
// Workspace is the absolute host path that the sandbox mounts as
// the agent's live working directory. Files under it are not
// staged into the kit because the sandbox sees them through the
// live mount; staging them would duplicate content and ship a
// stale, redacted copy alongside the live one.
Workspace string
// CacheDir is the parent directory under which the kit will be
// staged. Empty means "use [paths.GetCacheDir]/sandbox-kits".
CacheDir string
}
Options describes a kit build.
type Redaction ¶
type Redaction struct {
// Source is the host path of the original file. Omitted from the
// on-disk manifest for the same reason as [Entry.Source].
Source string `json:"-"`
// Target is the path relative to the kit root.
Target string `json:"target"`
}
Redaction records that portcullis added at least one portcullis.Marker to the staged copy of a file.
type Result ¶
type Result struct {
// HostDir is the absolute host path of the staged kit. Mount it
// read-only at [MountPath] inside the sandbox and forward
// `-e DOCKER_AGENT_KIT_DIR=<MountPath>` so the in-sandbox
// resolvers find it.
HostDir string
// Manifest describes what was staged. It contains absolute host
// source paths and is meant for caller-side inspection only — the
// on-disk copy under <HostDir>/manifest.json is sanitised so the
// sandbox cannot learn the host filesystem layout.
Manifest Manifest
// NeedsToolInstall reports whether the agent has at least one
// MCP / LSP toolset that the in-sandbox runtime might auto-install
// (the toolset has a Command set and Version isn't "false"/"off").
// Callers use this to decide whether to allowlist the package
// hosts the auto-installer reaches — we keep that gated so we
// don't open holes in the sandbox proxy when no agent could
// possibly need them.
NeedsToolInstall bool
}
Result is what Build returns.
func Build ¶
Build stages the kit and returns its location.
Each Build creates a temporary directory under CacheDir, populates it, then atomically replaces the final per-agent directory. Concurrent Builds for the same agent therefore never see a half-populated kit; the last one to finish wins. The kit directory itself is reused across runs (deterministic path keyed by AgentRef) so the sandbox VM can be reused as long as nothing else in the workspace mount set changed.
func (*Result) PrintSummary ¶
PrintSummary writes a human-readable description of what was staged to w. The output groups files by skill (one block per skill, listing every file inside), then lists prompt files. Files whose host content was scrubbed are tagged "(redacted)". A trailing summary line counts skills, prompt files, and redactions.
PrintSummary is silent when the kit shipped nothing — the caller is expected to print its own "no kit needed" hint in that case.