Skip to content

Built-in Plugins

crib ships four plugins that run automatically before each container is created. They inject credentials, SSH config, shell history persistence, and shared package caches into every workspace without any devcontainer.json boilerplate.

Plugins run during crib up and crib rebuild. They are fail-open: if a plugin can’t find something it needs (no SSH agent running, no Claude credentials on disk), it skips silently and doesn’t block container creation.


Persists your bash/zsh history across container recreations. Without this, every rebuild starts with an empty history.

What it does:

  • Creates ~/.crib/workspaces/{id}/plugins/shell-history/.shell_history on the host
  • Bind-mounts that directory into the container at ~/.crib_history/
  • Sets HISTFILE=~/.crib_history/.shell_history in the container

Both bash and zsh read HISTFILE, so this works regardless of which shell you use inside the container. The history file is mounted as a directory (not a file directly) so the shell can do atomic renames when saving, which avoids EBUSY errors on Docker and Podman.

No configuration needed. It always runs.


Shares package manager caches across all your workspaces via named Docker volumes. Without this, every rebuild re-downloads all dependencies from scratch.

Configure in .cribrc (in your project root):

cache = npm, pip, go

Comma-separated list of providers. Each one creates a crib-cache-{workspace}-{provider} named volume mounted at the standard cache directory inside the container. Volumes are per-workspace, so different projects don’t share cached data.

ProviderMount targetNotes
npm~/.npm
yarn~/.cache/yarn
pip~/.cache/pip
go~/go/pkg/modAlso sets GOMODCACHE so it works with any GOPATH
cargo~/.cargoAlso sets CARGO_HOME so it works with devcontainer images that use /usr/local/cargo
maven~/.m2/repository
gradle~/.gradle/caches
bundler~/.bundleSets BUNDLE_PATH and BUNDLE_BIN; adds ~/.bundle/bin to PATH via /etc/profile.d/
apt/var/cache/aptSystem path; disables docker-clean so cached .deb files persist
downloads~/.cache/cribGeneral-purpose cache; sets CRIB_CACHE env var for easy access

Unknown provider names produce a warning at startup and are skipped.

The downloads provider is a general-purpose persistent directory for anything that doesn’t have its own provider. Use it for large downloads, compiled tools, or any files you want to survive rebuilds:

Terminal window
curl -L -o "$CRIB_CACHE/some-tool.tar.gz" https://example.com/some-tool.tar.gz
tar -xzf "$CRIB_CACHE/some-tool.tar.gz" -C /usr/local/bin

Use crib cache list to see which cache volumes exist and how much space they use, and crib cache clean to remove them. See Commands for details.

When cache providers are configured, crib also attaches BuildKit cache mounts to the RUN instructions that install DevContainer Features. This speeds up feature installation across rebuilds by reusing cached packages (especially apt packages, which most features install).

Build-time caching applies to the feature-generated Dockerfile only, not to user Dockerfiles or compose service builds. The build cache is managed by BuildKit and is separate from the runtime named volumes.

For apt, crib also disables the docker-clean hook in the generated Dockerfile so that cached .deb files are preserved across builds.


Shares Claude Code credentials with the container so you can run claude without authenticating every time. Two modes are available.

Copies your host’s ~/.claude/.credentials.json into the container on each crib up. If the file doesn’t exist on the host, the plugin is a no-op.

A minimal ~/.claude.json with {"hasCompletedOnboarding":true} is also injected to skip the onboarding prompt. It won’t overwrite an existing file in the container.

This mode is transparent — nothing to configure.

For teams using a shared Claude organization account, or when you want to authenticate once inside the container and have those credentials persist across rebuilds.

Configure it in devcontainer.json:

{
"customizations": {
"crib": {
"coding-agents": {
"credentials": "workspace"
}
}
}
}

In workspace mode:

  • Host credentials are not injected
  • ~/.crib/workspaces/{id}/plugins/coding-agents/claude-state/ is bind-mounted to ~/.claude/ inside the container
  • Credentials you create inside the container (by running claude and authenticating) are stored in that directory and survive rebuilds
  • The ~/.claude.json onboarding config is still re-injected via docker exec on each rebuild (with IfNotExists semantics, so your customizations are preserved)

This is the right choice when:

  • Your team shares a Claude organization account that requires SSO or a different login than your personal account
  • You want credentials scoped to a specific project workspace

In both modes, plugin data (including credentials) is stored on the host under ~/.crib/workspaces/{id}/plugins/coding-agents/. Running crib remove deletes the workspace and all plugin data with it.

If you delete the project directory without running crib remove first, the workspace state (including any cached credentials) remains on disk. To clean it up manually, delete the workspace directory listed by crib list, or remove it directly from ~/.crib/workspaces/.


Shares your SSH configuration with the container so that git operations, remote connections, and commit signing work the same way inside the container as they do on your host.

If SSH_AUTH_SOCK is set on your host and the socket exists, the plugin:

  • Bind-mounts the socket into the container at /tmp/ssh-agent.sock
  • Sets SSH_AUTH_SOCK=/tmp/ssh-agent.sock inside the container

This lets git push, ssh, and other tools use your host’s keys without any keys being copied into the container.

Make sure your SSH agent is running on the host before crib up:

Terminal window
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519

Or add ssh-add to your shell startup file so keys are always loaded.

If ~/.ssh/config exists, it’s copied into the container at ~/.ssh/config. Host aliases, ProxyJump rules, and other SSH settings are available inside the container.

*.pub files from ~/.ssh/ are copied into the container. Private keys are never copied. This is enough for git commit signing (see below), since signing uses the forwarded agent rather than the private key directly.

authorized_keys files are skipped.

If your host’s global git config has gpg.format = ssh, the plugin extracts your signing configuration and generates a minimal .gitconfig for the container.

The generated config includes:

SettingSource
user.namegit config --global user.name
user.emailgit config --global user.email
user.signingkeygit config --global user.signingkey (path rewritten to container home)
gpg.formatssh
gpg.ssh.programgit config --global gpg.ssh.program (if set)
commit.gpgsigngit config --global commit.gpgsign (if set)
tag.gpgsigngit config --global tag.gpgsign (if set)

If user.signingkey is a path under ~/.ssh/ (e.g. ~/.ssh/id_ed25519-sign.pub), it’s rewritten to the equivalent path inside the container. The public key file is copied there by the SSH public keys step above.

Signing works via the agent. OpenSSH 8.2+ can sign commits using only the public key file plus the forwarded agent socket — no private key in the container.

Host git config setup:

Terminal window
# Enable SSH signing globally.
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
# Auto-sign all commits and tags.
git config --global commit.gpgsign true
git config --global tag.gpgsign true

If you already sign commits on your host, nothing else is needed. The plugin reads your existing config.

If gpg.format is not ssh, the plugin skips the gitconfig step entirely. Git settings for GPG signing (OpenPGP) are not forwarded.