Personalization
Add your own tools, setup steps and dotfiles to every devcontainer without committing them to the repository.
Your team's .devcontainer holds what everyone needs. Personalization adds what only you use, such as a git workflow tool, a shell or your dotfiles. It is kept in opendevhub's config.json on your machine and never written to the repository.
Open Settings → Personalization to set it for every project. To add to it or turn it off for one project, open the project's settings (the gear in the project header) and go to Personalization.
What you can add
- Features: dev container Features built into the image on top of the repository's own, passed to the dev container CLI as
--additional-features. Only published features work (ghcr.io/owner/repo/feature:1, or anhttps://tarball). Local./featurefolders don't, because they would have to be in the repository. Options are JSON, the same as in devcontainer.json. - Setup command: a shell script run as the container's user once the container starts. It runs with
bash -lwhen bash is installed andsh -lotherwise. It runs once per container and again after you change it. A marker in~/.cache/opendevhubrecords that it ran, and the marker is only written when the script succeeds, so a failed script runs again on the next start. A failure never stops the container. The output goes to the environment's log, prefixed withpersonalize:. - Mounts: folders or Docker volumes mounted into the container, the same as
mountsin devcontainer.json, passed to the dev container CLI as--mount.- A folder is an absolute path or one under
~. It comes from the machine the container runs on. That is your machine for local containers, and the node itself for containers on a remote node, where~means the node's home folder. - A folder that doesn't exist on your machine is skipped and logged rather than failing the container. Folders on a remote node aren't checked, so a missing one fails the container's start.
- Mounts are read and write:
--mounttakes noreadonlyoption. Agents and everything else in the container can change and delete what is in them. - Targets under
/opendevhub, and the targets opendevhub uses itself for worktrees and opencode's sessions, are skipped. - A volume suits a cache you want to keep across rebuilds, for example
go-mod-cachemounted at/go/pkg/mod.
- A folder is an absolute path or one under
- Dotfiles: a repository the dev container CLI clones into each new container before it runs the repository's install script (
install.sh,setup.shand so on). This is the same mechanism that VS Code and Codespaces use. You can enterowner/repofor GitHub, or any git URL.
How project settings combine
A project uses your global personalization and adds its own:
- For a feature that both list, the project's options win.
- Both setup commands run, the global one first.
- The project's dotfiles replace the global ones.
- For a mount target that both use, the project's mount wins.
Turn off Use your global personalization for a project to give it only its own settings. The project page shows what its containers end up with.
When changes apply
Features, dotfiles and mounts are part of how a container is created:
- Project container: rebuild it. Its Personalization settings say when it was created with other settings and offer a Rebuild button.
- Task containers: they are built from a base image. Your features are part of that image's key, so a new task container gets a fresh image. Rebuild an existing one to update it.
A changed setup command runs on the container's next start, with no rebuild.
Example: Git Town for yourself only
Your team doesn't use Git Town, but you want it in every container. Add an install step as the global setup command. Follow Git Town's installation guide for the current release, for example:
# Example: check git-town.com/install for the current command
go install github.com/git-town/git-town/v21@latestIf a published dev container Feature for the tool exists, add it under Features instead. It is then built into the image once and cached, rather than installed on every new container.
The settings are stored like this:
{
"personalization": {
"features": { "ghcr.io/devcontainers/features/github-cli:1": {} },
"setupCommand": "go install github.com/git-town/git-town/v21@latest",
"dotfiles": { "repository": "you/dotfiles" },
"mounts": [
{ "type": "bind", "source": "~/notes", "target": "/home/node/notes" },
{ "type": "volume", "source": "go-mod-cache", "target": "/go/pkg/mod" }
]
},
"projects": {
"/src/app": {
"personalization": { "inheritGlobal": false }
}
}
}It runs in the container
Setup commands and dotfiles install scripts run inside the project's
container, with the container user's access to the workspace and to the
ssh-agent opendevhub forwards. Mounted folders are writable from the container
too. Only add scripts and repositories you trust, and don't mount folders that
hold secrets you don't want agents to read, such as ~/.ssh or ~/.aws.