Expert in creating devcontainer configurations using DuploCloud features. Use when setting up development environments, configuring devcontainer.json, or adding DuploCloud tooling to a workspace. Knows feature detection, cloud CLI setup, Kubernetes access, AI tools, and 1Password SSH integration.
Create devcontainer configurations using duplocloud/devcontainers features.
The devcontainer name should be descriptive and creative. Use imagination to create a good name:
Sources for naming:
terraform-duplocloud-components → "DuploCloud Components Devspace")Format: "<Project Name> Devspace"
Examples:
"DuploCloud IaC Devspace" - for infrastructure repos"Brook AI Development" - from README nickname"Playlab Platform Devspace" - from org/project name"Customer Portal Dev" - descriptive of purposeIf no clear name: Use repo directory name, title-cased, with "Devspace" suffix.
Always start by reading the project's README.md to understand:
Read: README.md (or README.rst, readme.md)
Search the workspace for indicators to determine which features to include.
| Feature | Search For | Indicators |
|---------|------------|------------|
| terraform | *.tf, modules/, terraform/ | Terraform files present |
| aws-cli | aws, s3://, AWS_, us-east, us-west | AWS references in code/config |
| gcloud-cli | gcloud, gs://, GOOGLE_, gcp, GCP | GCP references in code/config |
| kubernetes | kubectl, k8s, kubernetes, helm, Chart.yaml | K8s manifests or Helm charts |
| github | .github/, github.com | GitHub workflows or references |
| git | Commit signing needed, version tags | Team uses signed commits |
| ai-claude | Team uses Claude | Anthropic AI preference |
| ai-codex | Team uses ChatGPT/OpenAI | OpenAI preference |
| ai-gemini | Team uses Gemini | Google AI preference |
| onepassword-cli | Team uses 1Password | SSH key management needed |
| direnv | .envrc files, per-dir env vars | direnv usage |
| openvpn | VPN access needed | Private network access |
# Cloud detection
grep -r "aws\|s3://" --include="*.tf" --include="*.py" --include="*.yaml" .
grep -r "gcloud\|gs://" --include="*.tf" --include="*.py" --include="*.yaml" .
# Kubernetes detection
find . -name "*.yaml" -exec grep -l "kind:\|apiVersion:" {} \;
ls -la terraform/ modules/ 2>/dev/null
# Git provider
grep -r "github.com\|gitlab.com\|bitbucket.org" .
Always include duploctl - it's required for all other DuploCloud features:
"ghcr.io/duplocloud/devcontainers/duploctl:latest": {}
| Feature | Purpose | When to Use |
|---------|---------|-------------|
| duploctl | DuploCloud CLI | Always required |
| aws-cli | AWS CLI + JIT creds | AWS cloud projects |
| gcloud-cli | Google Cloud CLI | GCP cloud projects |
| terraform | Terraform + tf wrapper | Infrastructure as code |
| kubernetes | kubectl + JIT kubeconfig | K8s workloads |
| github | GitHub CLI + Copilot | GitHub repos |
| git | Git config + signing + plugins | Commit signing, version bumping |
| ai-claude | Anthropic Claude Code CLI | Claude AI assistance |
| ai-codex | OpenAI Codex CLI | OpenAI/ChatGPT assistance |
| ai-gemini | Google Gemini CLI | Gemini AI assistance |
| onepassword-cli | 1Password + SSH keys | Team SSH management |
| direnv | direnv + DuploCloud direnvrc | Per-directory env vars |
| openvpn | OpenVPN client | VPN access to private networks |
Detailed options: See references/features.md
Important: All CLI configurations should be isolated to a workspace directory. This keeps state across container restarts and rebuilds.
Default folder: config/ (can also be .config, .secrets, .tmp, .dev - ask user if unclear)
"containerEnv": {
"AWS_CONFIG_FILE": "${containerWorkspaceFolder}/config/aws",
"KUBECONFIG": "${containerWorkspaceFolder}/config/kubeconfig.yaml",
"CLOUDSDK_CONFIG": "${containerWorkspaceFolder}/config/gcloud",
"GOOGLE_APPLICATION_CREDENTIALS": "${containerWorkspaceFolder}/config/gcloud/application_default_credentials.json",
"DUPLO_CONFIG": "${containerWorkspaceFolder}/config/duplo.yaml",
"CODEX_HOME": "${containerWorkspaceFolder}/config/.codex",
"XDG_CONFIG_HOME": "${containerWorkspaceFolder}/config"
}
config/
├── aws # AWS CLI config
├── kubeconfig.yaml # kubectl config
├── gcloud/ # gcloud SDK config
├── duplo.yaml # duploctl config
├── op/ # 1Password CLI (via XDG_CONFIG_HOME)
└── .codex/ # Codex skills and config
config/
!config/.gitkeep
mkdir -p "${VSCODE_CWD}/config"
Use ${localEnv:VAR_NAME} to pull values from the host machine into feature configuration. This allows team members to customize their devcontainer without modifying the shared config.
These must be set on the host machine (in shell profile or .env):
| Variable | Purpose | Required |
|----------|---------|----------|
| DUPLO_HOST | DuploCloud portal URL | Yes |
| DUPLO_TOKEN | DuploCloud API token | Yes |
| GIT_USERNAME | Git commit author name | Recommended |
| GIT_EMAIL | Git commit author email | Recommended |
| OP_SSH_SECRET | 1Password SSH key name | If using 1Password |
| OP_ACCOUNT | 1Password account domain | If using 1Password |
| OP_VAULT_NAME | 1Password vault name | If using 1Password |
Secrets are passed via .env file (never committed to git). The runArgs mounts this file:
"runArgs": [
"--env-file=${localWorkspaceFolder}/.env"
]
Minimum .env contents:
DUPLO_HOST=https://yourportal.duplocloud.net
DUPLO_TOKEN=your-duplo-token
Add to .gitignore:
.env
Create .devcontainer/init.sh to bootstrap required files:
#!/usr/bin/env bash
set -e
echo "Init Devcontainer"
VSCODE_CWD=${VSCODE_CWD:-$PWD}
mkdir -p "${VSCODE_CWD}/config"
# Create .env file if it doesn't exist
if [ ! -f "${VSCODE_CWD}/.env" ]; then
echo "Creating .env file with DUPLO credentials..."
cat > "${VSCODE_CWD}/.env" << EOF
DUPLO_HOST=${DUPLO_HOST}
DUPLO_TOKEN=${DUPLO_TOKEN}
EOF
echo ".env file created"
else
echo ".env file already exists"
fi
Create .devcontainer/post-start.sh for commands after container starts:
#!/usr/bin/env bash
set -e
echo "Post start running"
# Add custom post-start commands here
"initializeCommand": ".devcontainer/init.sh",
"postStartCommand": ".devcontainer/post-start.sh"
Default image: Python base (unless user specifies otherwise)
{
"name": "<Project> Devspace",
"image": "mcr.microsoft.com/vscode/devcontainers/python:3.12",
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
"moby": "false"
},
"ghcr.io/duplocloud/devcontainers/duploctl:latest": {}
},
"runArgs": [
"--env-file=${localWorkspaceFolder}/.env"
],
"initializeCommand": ".devcontainer/init.sh",
"postStartCommand": ".devcontainer/post-start.sh",
"containerEnv": {
"WORKSPACE_FOLDER": "${containerWorkspaceFolder}",
"DUPLO_CONFIG": "${containerWorkspaceFolder}/config/duplo.yaml",
"EDITOR": "code --wait"
},
"customizations": {
"vscode": {
"extensions": [],
"settings": {}
}
}
}
"features": {
"ghcr.io/duplocloud/devcontainers/duploctl:latest": {},
"ghcr.io/duplocloud/devcontainers/aws-cli:latest": {
"jit": true,
"jitAdmin": true
}
},
"containerEnv": {
"AWS_CONFIG_FILE": "${containerWorkspaceFolder}/config/aws",
"AWS_DEFAULT_REGION": "us-east-1",
"AWS_REGION": "us-east-1"
}
"features": {
"ghcr.io/duplocloud/devcontainers/duploctl:latest": {},
"ghcr.io/duplocloud/devcontainers/gcloud-cli:1": {}
},
"containerEnv": {
"CLOUDSDK_CONFIG": "${containerWorkspaceFolder}/config/gcloud",
"CLOUDSDK_PYTHON": "/usr/local/bin/python",
"GOOGLE_APPLICATION_CREDENTIALS": "${containerWorkspaceFolder}/config/gcloud/application_default_credentials.json"
}
"ghcr.io/duplocloud/devcontainers/kubernetes:1": {
"jit": true,
"jitAdmin": true,
"plan": "nonprod01"
},
"containerEnv": {
"KUBECONFIG": "${containerWorkspaceFolder}/config/kubeconfig.yaml"
}
Options:
jit: Enable automatic JIT authenticationjitAdmin: Use admin privileges (requires admin token)plan: DuploCloud infrastructure nameChoose based on team's AI provider preference:
"ghcr.io/duplocloud/devcontainers/ai-claude:1": {
"skills": "tf-module"
}
Skills installed to: ~/.claude/skills/
"ghcr.io/duplocloud/devcontainers/ai-codex:1": {
"skills": "tf-module"
},
"containerEnv": {
"CODEX_HOME": "${containerWorkspaceFolder}/.codex"
}
Skills installed to: $CODEX_HOME/skills/
"ghcr.io/duplocloud/devcontainers/ai-gemini:1": {
"skills": "tf-module"
}
Skills installed to: ~/.gemini/skills/
"ghcr.io/duplocloud/devcontainers/github:latest": {
"installCopilot": true,
"skills": "tf-module"
}
These must be set on the host machine for 1Password to work:
| Variable | Purpose | Example |
|----------|---------|--------|
| OP_ACCOUNT | 1Password account domain | my.1password.com |
| OP_VAULT_NAME | Vault containing SSH keys | Employee |
| OP_SSH_SECRET | SSH key secret name in 1Password | GitHub SSH Key |
| OP_AUTO_SSH | Enable auto SSH config | true |
| USER_EMAIL | Email for 1Password account | you@company.com |
"ghcr.io/duplocloud/devcontainers/onepassword-cli:1": {
"autoSsh": "${localEnv:OP_AUTO_SSH}",
"sshSecretNames": "${localEnv:OP_SSH_SECRET}",
"vault": "${localEnv:OP_VAULT_NAME}",
"account": "${localEnv:OP_ACCOUNT}",
"userEmail": "${localEnv:USER_EMAIL}"
}
Critical: For auto SSH config to work, your 1Password SSH secret needs custom fields:
| Field | Required | Description | Example |
|-------|----------|-------------|--------|
| host | Yes | Hostname for SSH | github.com |
| username | Recommended | SSH username | git |
| port | Optional | SSH port | 22 |
Without the host field, keys download but SSH config isn't created.
Important for macOS users: You need to configure a Launch Agent to expose the 1Password SSH agent socket to devcontainers.
Follow: 1Password SSH Agent Compatibility
Verify SSH agent is working:
ssh-add -l
Common problems:
"No vault specified" error
OP_VAULT_NAME or vault option is setSSH keys not configured
host custom field in 1PasswordautoSsh is true (not string "true")Repeated account setup on rebuild
XDG_CONFIG_HOME to workspace config folder$XDG_CONFIG_HOME/op/macOS SSH agent not forwarding
SSH_AUTH_SOCK is set in containerInteractive login required every time
userEmail to skip email promptXDG_CONFIG_HOME for persistenceFor detailed troubleshooting: Read the full feature README:
https://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/onepassword-cli/README.md
OP_CONNECT_HOST + OP_CONNECT_TOKEN)OP_SERVICE_ACCOUNT_TOKEN)~/.1password/agent.sock)"ghcr.io/duplocloud/devcontainers/git:1": {
"userName": "${localEnv:GIT_USERNAME}",
"userEmail": "${localEnv:GIT_EMAIL}",
"signingKey": "${localEnv:GIT_SIGNING_KEY}"
}
Options:
userName: Git user.name (fallback: GIT_USER env)userEmail: Git user.email (fallback: GIT_EMAIL env)signingKey: Path to signing key relative to ~/.sshinstallGitKraken: Install GitKraken CLIIncluded plugins:
git-bump - Semantic version bumping (git bump -v patch)git-setenv - Export CI env vars (eval $(git setenv bitbucket))Integration with 1Password for signed commits:
{
"ghcr.io/duplocloud/devcontainers/onepassword-cli:1": {
"autoSsh": true,
"sshSecretNames": "GitHub SSH Key"
},
"ghcr.io/duplocloud/devcontainers/git:1": {
"signingKey": "GitHub_SSH_Key.pub"
}
}
Note: Primarily useful for GitHub Codespaces. Can be disabled for local devcontainers.
"ghcr.io/duplocloud/devcontainers/openvpn:1": {
"enabled": "${localEnv:DEVCONTAINER_VPN_ENABLED:-false}",
"autoConnect": true
},
"runArgs": ["--device=/dev/net/tun"]
Options:
enabled: Enable/disable feature (use localEnv to toggle)autoConnect: Auto-connect on container start (default: true)configDir: Custom config directoryRequired: Must add --device=/dev/net/tun to runArgs.
"ghcr.io/duplocloud/devcontainers/direnv:1": {}
Installs direnv with DuploCloud-specific direnvrc at $HOME/direnv/direnvrc.
"ghcr.io/duplocloud/devcontainers/terraform:1": {},
"customizations": {
"vscode": {
"extensions": ["hashicorp.terraform"],
"settings": {
"[terraform]": {
"editor.defaultFormatter": "hashicorp.terraform",
"editor.formatOnSave": true
}
}
}
}
1. Read README.md for project context
2. Search workspace for cloud indicators (AWS/GCP)
3. Check for Terraform files
4. Check for Kubernetes references
5. Determine git provider
6. Add AI tools based on project complexity
7. Add 1Password if team uses it
| Stack | Extensions |
|-------|------------|
| Python | ms-python.python |
| Terraform | hashicorp.terraform |
| Kubernetes | ms-kubernetes-tools.vscode-kubernetes-tools |
| YAML | redhat.vscode-yaml |
| GitHub | github.vscode-github-actions, GitHub.copilot-chat |
| Database | cweijan.vscode-database-client2 |
| Git | eamodio.gitlens |
| AWS | amazonwebservices.aws-toolkit-vscode |
| Feature | Extension |
|---------|----------|
| github | github.vscode-pull-request-github |
| git | eamodio.gitlens |
| ai-claude | anthropic.claude-code |
| ai-codex | openai.chatgpt |
| ai-gemini | Google.geminicodeassist |
| aws-cli | amazonwebservices.aws-toolkit-vscode |
| kubernetes | ms-kubernetes-tools.vscode-kubernetes-tools |
To learn about a specific feature's options, use web search to read its README:
https://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/<feature-name>/README.md
All feature README URLs:
https://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/duploctl/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/aws-cli/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/gcloud-cli/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/terraform/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/kubernetes/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/github/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/git/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/ai-claude/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/ai-codex/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/ai-gemini/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/onepassword-cli/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/direnv/README.mdhttps://raw.githubusercontent.com/duplocloud/devcontainers/refs/heads/main/src/openvpn/README.md| Resource | Contents |
|----------|----------|
| references/features.md | Detailed feature options and configuration |
| references/detection.md | Workspace search patterns for feature selection |
| assets/templates/ | Ready-to-use template files |
Use these templates as starting points - copy and customize:
| Template | Use Case |
|----------|----------|
| devcontainer.json.template | Minimal base template |
| devcontainer-aws.json.template | AWS projects with JIT |
| devcontainer-terraform.json.template | Terraform/IaC projects |
| devcontainer-full.json.template | Full-featured with all tools |
| init.sh | Initialize script (creates .env) |
| post-start.sh | Post-start script placeholder |
Template placeholder: {{PROJECT_NAME}} - replace with devcontainer name
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer