Generate devcontainer configurations for Claude Code development environments. Use when setting up development containers with Claude Code and optional Codex CLI. Automatically detects marketplace.json for plugin marketplace configurations.
Generates complete devcontainer configurations for Claude Code development environments. Use when setting up development containers, automatically detecting marketplace.json for plugin marketplace configurations.
/plugin marketplace add taisukeoe/agentic-ai-skills-creator/plugin install marketplace-helper@agentic-skills-creatorThis skill inherits all available tools. When active, it can use any tool Claude has access to.
README.mdreferences/claude-code-installation.mdreferences/codex-cli-installation.mdreferences/devcontainer-spec.mdtemplates/Dockerfile.templatetemplates/devcontainer.json.templatetemplates/post-create.sh.templatetemplates/reinstall-marketplace.sh.templatetemplates/sync-codex-skills.sh.templatetests/scenarios.mdGenerate complete .devcontainer/ configurations for Claude Code development environments with:
User: Set up a devcontainer for this project
Agent: I'll check for marketplace.json and generate the devcontainer configuration.
Check for .claude-plugin/marketplace.json:
ls .claude-plugin/marketplace.json
Mode determination:
marketplace.json exists → full plugin/skill setupFor Marketplace mode, extract:
name - Marketplace name (used for volume naming)plugins - Array of plugin definitionsFor Generic mode, use:
Ask the user explicitly:
Do you want to add Codex CLI (OpenAI) support alongside Claude Code?
- Yes: Adds Volta, Node.js, Codex CLI, and skill sync mechanism
- No (default): Claude Code only
If yes:
~/.codex/ volume mount for config persistencesync-codex-skills.sh script (copies skills to ~/.codex/skills/) [Marketplace mode only]post-create.sh [Marketplace mode only]Note: Both Claude Code and Codex CLI are installed at Docker build time for faster container startup.
Skip this step in Generic mode.
For each plugin in marketplace.json:
source path (e.g., "./plugins/plugin-name").claude-plugin/plugin.json in source directoryskills path from plugin.json or use ./skills/ defaultBuild two lists:
enabledPlugins: {"plugin-name@marketplace-name": true, ...}allowedSkills: ["Skill(skill-1)", "Skill(skill-2)", ...]Skip this step in Generic mode.
Ask the user explicitly:
Do you want to automatically reinstall the marketplace on every container start?
- Yes: Adds
postStartCommandto runreinstall-marketplace.shautomatically- No (recommended for stable development): Run manually when needed
Note: This is a workaround for Claude Code not detecting local plugin changes. Running on every start adds ~5-10 seconds delay.
Use the templates in templates/ directory, substituting placeholders:
| Placeholder | Value |
|---|---|
{{PROJECT_NAME}} | Marketplace name (if exists) or project directory name |
{{PROJECT_DIR}} | Project directory name |
{{CODEX_VOLUME_MOUNT}} | If Codex: ,\n "source=codex-config-{{PROJECT_NAME}},..." else: empty |
{{VOLTA_ENV_BLOCK}} | If Codex: ENV VOLTA_HOME=... ENV PATH=... else: empty |
{{CODEX_INSTALL_BLOCK}} | If Codex: Volta/Codex RUN command, else: empty |
{{CODEX_DIR_LIST}} | If Codex: "$HOME/.codex" else: empty |
{{CODEX_ALIASES}} | If Codex: Codex alias lines, else: empty |
{{CODEX_ALIAS_ECHO}} | If Codex: echo " codex-f - codex --full-auto" else: empty |
{{DEVCONTAINER_READY_MESSAGE}} | "Claude Code devcontainer ready!" or "Claude Code + Codex CLI devcontainer ready!" |
| Placeholder | Value |
|---|---|
{{ENABLED_PLUGINS}} | Object entries like "plugin@market": true |
{{ALLOWED_SKILLS}} | Array entries like "Skill(name)" |
{{PLUGIN_INSTALL_COMMANDS}} | Plugin install commands (with ` |
{{CODEX_SETUP_BLOCK}} | If Codex and Marketplace mode: Codex skill sync in post-create.sh, else: empty |
{{CODEX_SYNC_BLOCK}} | If Codex: Codex sync in reinstall-marketplace.sh, else: empty |
{{POST_START_COMMAND}} | If auto-sync: ,\n "postStartCommand": "bash .devcontainer/reinstall-marketplace.sh" else: empty |
{{SETTINGS_BLOCK}} | Shell commands to create settings.json with enabledPlugins/allowedSkills |
{{MARKETPLACE_REGISTER_BLOCK}} | Marketplace registration and plugin install commands |
{{MARKETPLACE_SYNC_HINT}} | echo "To sync marketplace: bash .devcontainer/reinstall-marketplace.sh" |
| Placeholder | Value |
|---|---|
{{POST_START_COMMAND}} | empty (no postStartCommand) |
{{SETTINGS_BLOCK}} | empty (no plugin settings needed) |
{{MARKETPLACE_REGISTER_BLOCK}} | empty (no marketplace registration) |
{{CODEX_SETUP_BLOCK}} | empty (no skill sync needed) |
{{MARKETPLACE_SYNC_HINT}} | empty |
Templates:
Conditional logic:
postStartCommand from devcontainer.json.devcontainer/ directory if not exists.template suffix)chmod +x .devcontainer/*.shGeneric mode:
Devcontainer files created in .devcontainer/
To use:
1. Open project in VS Code
2. Click "Reopen in Container" when prompted
(or use Command Palette: "Dev Containers: Reopen in Container")
3. Run 'claude' on first use to complete initial setup
Your credentials persist in Docker volumes.
Marketplace mode:
Devcontainer files created in .devcontainer/
To use:
1. Open project in VS Code
2. Click "Reopen in Container" when prompted
(or use Command Palette: "Dev Containers: Reopen in Container")
3. Run 'claude' on first use to complete initial setup
Your credentials persist in Docker volumes.
To manually sync marketplace changes:
bash .devcontainer/reinstall-marketplace.sh
Generic mode:
.devcontainer/
├── devcontainer.json # Container configuration
├── Dockerfile # Ubuntu + Claude Code (+ Volta/Codex if enabled)
└── post-create.sh # Initial setup (config, aliases)
Marketplace mode:
.devcontainer/
├── devcontainer.json # Container configuration
├── Dockerfile # Ubuntu + Claude Code (+ Volta/Codex if enabled)
├── post-create.sh # Initial setup (config, marketplace, Codex sync)
├── reinstall-marketplace.sh # Marketplace sync script (+ Codex sync if enabled)
└── sync-codex-skills.sh # Codex skill sync (only if Codex enabled)
Uses named Docker volumes plus a symlink for complete persistence:
Docker Image (built once):
├── ~/.local/bin/claude # Claude Code binary
└── ~/.volta/ # Volta + Node.js + Codex CLI (if enabled)
Volume 1: claude-config-${PROJECT_NAME} → ~/.claude/
├── .home-claude.json # Setup state (symlink target)
├── .credentials.json # Auth tokens
├── settings.json # User settings
└── plugins/ # Plugin data (Marketplace mode)
Volume 2: claude-data-${PROJECT_NAME} → ~/.local/share/claude/
└── (Claude Code data) # Session data, etc.
Volume 3 (if Codex enabled): codex-config-${PROJECT_NAME} → ~/.codex/
├── config.toml # Codex CLI configuration
├── sessions/ # Session data
└── skills/ # Synced skills from marketplace (Marketplace mode)
Symlink (created by post-create.sh):
~/.claude.json → ~/.claude/.home-claude.json
Why this architecture?
| Location | Purpose | Persistence Method |
|---|---|---|
~/.local/bin/claude | Claude Code binary | Docker image (fast startup) |
~/.volta/ | Codex CLI binary | Docker image (fast startup) |
~/.claude/ | Config, credentials, settings | Volume mount |
~/.local/share/claude/ | Claude session data | Volume mount |
~/.claude.json | Initial setup state | Symlink to volume |
~/.codex/ (optional) | Codex config, sessions, skills | Volume mount |
Important: ~/.claude.json cannot be directly mounted as a volume (Docker creates a directory instead of a file). The symlink approach allows the file to persist inside the ~/.claude/ volume.
The setup creates a persistent alias file in the volume:
post-create.sh creates ~/.claude/.shell-aliases (persists in volume)post-create.sh adds source line to .zshrc (both modes, with duplicate protection)reinstall-marketplace.sh also adds source line to .zshrc on every start (Marketplace mode only)# ~/.claude/.shell-aliases (persisted)
alias claude-y='claude --dangerously-skip-permissions'
# If Codex enabled:
alias codex-f='codex --full-auto'
This survives container rebuilds because the alias file is stored in the volume.
enabledPlugins must be object format (not array):
{
"enabledPlugins": {
"plugin-a@marketplace": true,
"plugin-b@marketplace": true
}
}
reinstall-marketplace.sh is a workaround for Claude Code not automatically detecting local plugin/skill changes.
What it does:
When to run:
bash .devcontainer/reinstall-marketplace.shpostStartCommand (if user opted in)| Error | Cause | Solution |
|---|---|---|
| No plugins found | Empty plugins array | Warn user, generate minimal config |
| Source path invalid | Plugin source doesn't exist | Report error, skip invalid plugins |
| Existing .devcontainer/ | Files already present | Ask before overwriting |
| GID/UID 1000 already exists | Ubuntu base image has existing user | Use getent to detect and rename existing user |
| Permission denied on config | Volume owned by root | Use sudo chown in post-create.sh |
| claude: command not found | PATH not set | Export PATH="$HOME/.local/bin:$PATH" in scripts |
| EISDIR on ~/.claude.json | Volume mounted as directory | Remove directory, use symlink instead |
| JSON Parse error: Unexpected EOF | Empty ~/.claude.json file | Initialize with {} not empty file |
| Raw mode not supported | Plugin commands in non-interactive shell | Only run plugin commands if setup complete |
| Login required after rebuild | ~/.claude.json not persisted | Symlink to file inside volume |