Skip to content
Agentmart
Submit a tool

setup-devcontainer

Generate a shared devcontainer (Ubuntu base image, Node, GitHub CLI, one persistent config volume) in the current repo — one container every AI CLI installs…

Skill by ken-guru

IndexedMIT★ 1
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/ken-guru-setup-devcontainer

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Generate a shared devcontainer (Ubuntu base image, Node, GitHub CLI, one persistent config volume) in the current repo — one container every AI CLI installs into, added independently via its four companion setup-<tool>-devcontainer skills — optionally layering on SSH deploy-key/signing-key automation for agent-driven git push and signed commits, and/or an opt-in default-deny network egress firewall (iptables+ipset, allowlist derived from a Network Manifest). Use when the user wants to add a devcontainer to a repo, add SSH key automation to an existing devcontainer, restrict a devcontainer's outbound network, or connect a Local Checkout to a real GitHub repo. Not for adding an AI CLI itself — run the matching setup-<tool>-devcontainer skill for that, after this one.

Use cases: devops, agent-building

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Shell scripts

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/setup-devcontainer

What's inside

Skill name
setup-devcontainer
Description
Generate a shared devcontainer (Ubuntu base image, Node, GitHub CLI, one persistent config volume) in the current repo — one container every AI CLI installs into, added independently via its four companion setup-<tool>-devcontainer skills — optionally layering on SSH deploy-key/signing-key automation for agent-driven git push and signed commits, and/or an opt-in default-deny network egress firewall (iptables+ipset, allowlist derived from a Network Manifest). Use when the user wants to add a devcontainer to a repo, add SSH key automation to an existing devcontainer, restrict a devcontainer's outbound network, or connect a Local Checkout to a real GitHub repo. Not for adding an AI CLI itself — run the matching setup-<tool>-devcontainer skill for that, after this one.
License
MIT
Instructions
419 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts
  • Instructions read files in your home folder (~/.ssh, ~/.aws…)

Files (50)

  • CONTEXT.md
  • SKILL.md
  • adding-a-backing-service.md · docs/
  • adding-firewall-later.md · docs/
  • adding-ssh-later.md · docs/
  • 0001-per-container-ssh-keys.md · docs/adr/
  • 0002-collapse-tool-container-isolation.md · docs/adr/
  • 0003-manual-first-deploy-key-registration.md · docs/adr/
  • 0004-digest-pin-base-image-reject-docker-hardened-images.md · docs/adr/
  • 0005-network-egress-firewall-and-network-manifest.md · docs/adr/
  • 0006-capability-drop-reject-readonly-rootfs-and-seccomp.md · docs/adr/
  • 0007-agent-trust-hub-audit-response.md · docs/adr/
  • connecting-local-checkout.md · docs/
  • check-skill-sync-targets.sh · scripts/
  • render-lib.sh · scripts/lib/
  • patch-if-absent.sh · scripts/
  • patch-json-array-if-absent.sh · scripts/
  • render-devcontainer.sh · scripts/
  • test-devcontainer.sh · scripts/
  • test-firewall-lib.sh · scripts/
  • test-integration.sh · scripts/
  • test-network-manifest-domains.sh · scripts/
  • test-patch-if-absent.sh · scripts/
  • test-patch-json-array-if-absent.sh · scripts/
  • verify-devcontainer.sh · scripts/
  • Dockerfile · templates/
  • README.baseline.md · templates/
  • README.firewall-block.md · templates/
  • README.ssh-block.md · templates/
  • allowed-domains.local.txt · templates/
  • bash-env.sh · templates/
  • devcontainer.json · templates/
  • devcontainer.with-ssh.json · templates/
  • env.baseline.example · templates/
  • env.ssh-block.example · templates/
  • firewall-capability-entries.json · templates/
  • firewall-lib.sh · templates/
  • init-firewall.sh · templates/
  • initialize-base.sh · templates/
  • install-cli-block.sh · templates/
  • network-manifest-domains.sh · templates/
  • network-manifest.json · templates/
  • post-attach.sh · templates/
  • post-create-base.sh · templates/
  • post-create-ssh-block.sh · templates/
  • post-create-warnings-block.sh · templates/
  • post-start-base.sh · templates/
  • post-start-firewall-block.sh · templates/
  • project-mounts.local.json · templates/
  • refresh-allowlist.sh · templates/

SKILL.md (first lines)

# Setup Devcontainer

Generates `.devcontainer/` from the templates in [templates/](templates/):
one **Shared Container** — a single `devcontainer.json` and `Dockerfile` —
that every selected AI CLI installs into via its own independent skill, run
separately after this one. See [CONTEXT.md](CONTEXT.md) for this skill's
vocabulary (Shared Container, Local Checkout, Shared Checkout, Scaffold,
CLI Skill, Own-Block Contract, Project-Owned Block, Capability Seam, Network
Manifest, Project Mounts).

This skill owns the container definition (`devcontainer.json`, `Dockerfile`)
and the shared parts of `post-create.sh`/`post-start.sh`/`README.md`
entirely — no CLI skill ever edits them directly, except for one narrow,
explicit exception (the Capability Seam, `runArgs`, used by
`setup-codex-devcontainer`).

## 1. Resolve the workspace root, then detect the target repo

Before anything else, make sure you're standing in the directory VS Code will actually open for
this devcontainer. Every check and file write from here on — including the stale-container check
in step 2 — trusts `$(pwd)`; getting this wrong lets a stale container or a misplaced
`.devcontainer/` slip through silently instead of being caught.

```bash
git rev-parse --is-inside-work-tree 2>/dev/null
```

- **Fails**: not a git repo yet (the Local Checkout case below, before `git init`). Skip this
  check entirely and continue to detecting the repo.
- **Succeeds**: compare the current checkout's root against the repo's main working tree:

  ```bash
  git rev-parse --show-toplevel
  git rev-parse --git-common-dir
  ```

  `--git-common-dir` is the shared `.git` directory; its parent is the *main* checkout's root,
  which is what differs in a linked worktree (each worktree has its own top level but shares this
  common dir).

  - **Parent of `--git-common-dir` matches `--show-toplevel`**: already at the repo root, or in a
    plain subdirectory of it. `cd` to `--show-toplevel` and continue — every `$(pwd)` reference
    later in this skill is now correct, no further changes needed.
  - **They differ**: this is a **linked git worktree** — a separate checkout directory sharing
    this repo's history, common in isolated per-task agent sessions. Don't guess which one VS Code
    will open (worktree-per-devcontainer is a legitimate setup too). Stop and ask: "This looks
    like a git worktree, not necessarily the folder you'll open in VS Code for the devcontainer.
    Which folder will that be? If it's not this one, re-run this skill from there instead — the
    checks below (stale containers, existing config) only ever look at the current directory."

```bash
git remote get-url origin
```

Parse `owner/repo` from it (works for both `git@github.com:owner/repo.git` and
`https://github.com/owner/repo` forms) — this is `{{REPO_SLUG}}`. `{{REPO_NAME}}` is the `repo`
part alone, used in the volume names.

If there's no `origin` remote yet, ask one question: "Does a GitHub repository already exist for
this project? If yes, name it (`owner/repo`) — the container's `GH_TOKEN` will need access to it.
If no, or you're not ready to connect yet, this becomes a local-only **Local Checkout** —
connectable to GitHub later (see 'Connecting a Local Checkout to a real GitHub repo')."

- **Named an existing repo**: resolve `{{REPO_SLUG}}`/`{{REPO_NAME}}` from it, same as the
  existing-`origin` case above.
- **Local Checkout**: `{{REPO_SLUG}}` stays empty. `{{REPO_NAME}}` falls back to the local working
  directory's basename (`basename "$(pwd)"`), sanitized to Docker's naming rules (lowercase,
  invalid characters replaced with `-`) — state the resolved name back to the user as part of
  your summary; don't decide it silently. Also ask, as a separate yes/no question: "Initialize
  this workspace with `git init`?" Record the answer as `{{LOCAL_CHECKOUT_GIT_INIT}}`
  (`"true"`/`"false"`). If yes, resolve `{{GIT_DEFAULT_BRANCH}}` from the host's
  `git config --global init.defaultBranch` — substitute it as an empty string if the host has
  none configured; always substitute this placeholder with *something*, even `""`.

Done when you have `{{REPO_SLUG}}` (possibly empty) and `{{REPO_NAME}}` — plus, if Local Checkout,
`{{LOCAL_CHECKOUT_GIT_INIT}}` and, if that's yes, `{{GIT_DEFAULT_BRANCH}}`.

## 2. Discover existing setup

```bash
test -f .devcontainer/devcontainer.json && echo "devcontainer already exists"
```

- **Already exists**: this repo already has a Shared Container from a prior run. Nothing to
  regenerate — CLI installs are handled entirely by the setup-`<tool>`-devcontainer skills, and
  adding SSH to an existing devcontainer is [Adding SSH to a tool
  later](docs/adding-ssh-later.md). Stop here unless the user is specifically asking to
  reconfigure the base devcontainer itself.

  Exception: if `devcontainer.json` sets `workspaceFolder` without a matching `workspaceMount`,
  it predates the fix below and will fail to mount the repo at all. Patch it in place (add
  `"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"`
  next to `workspaceFolder`) and check for a stale container from the earlier failed attempt (see
  below) — a restart alone won't pick up the fix, since the mount is baked in at container
  creation.

  Exception: if `devcontainer.json` has no `containerEnv.BASH_ENV` entry, it predates the fix that
  makes `GH_TOKEN` (and the rest of `.devcontainer/.env`) visible to an AI CLI's own tool calls —
  without it, `GH_TOKEN` only ever reaches the three lifecycle scripts (postCreate/postStart/
  postAttach), never a `gh` command an agent runs itself, even right after a token was added and
  the container rebuilt. Patch it in place: add `.devcontainer/bash-env.sh` (copy of
  [templates/bash-env.sh](templates/bash-env.sh), chmod +x), add
  `"containerEnv": {"BASH_ENV": "/workspace/.devcontainer/bash-env.sh"}` to `devcontainer.json`,
  and add the `devcontainer-env-load` block from
  [templates/post-create-base.sh](templates/post-create-base.sh) to `.devcontainer/post-create.sh`
  if it isn't already there. Needs **Dev Containers: Rebuild Container** to take effect.

  Warning, not an exception (nothing here auto-patches this one): if `devcontainer.json` has no
  `build.target` field, it predates the Baseline Containment hardening (`--cap-drop=ALL` plus a
  small `--cap-add` allowlist, unconditionally; the opt-in network firewall; the digest-pinned,
  multi-stage `Dockerfile`) — the whole container still runs with Docker's full default capability
  set and an unpinned, single-stage image, regardless of anything the setup-`<tool>`-devcontainer
  skills or the "later" docs above do to it. There's no automated backfill for this (a deliberate
  choice, not an oversight — see the skill's own git history for the reasoning). Tell the user
  plainly: to actually get the hardening, delete `.devcontainer/` and regenerate from scratch,
  rerunning any `setup-<tool>-devcontainer` skills and redoing the SSH/firewall answers afterward.
- **Doesn't exist**: fresh setup, continue to step 3.

Also check for a leftover container from an unrelated prior setup of this same workspace folder —

From ken-guru/skills, MIT.

More from ken-guru/skills

Signals

Stars
1
Forks
1
Open issues
6
Last commit (this folder)
Oct 21, 2026 (8 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from ken-guru

Cite this page

setup-devcontainer skill. Agent Mart. https://agentmart.dev/skills/ken-guru-setup-devcontainer (last updated 2026-10-24)