0022. GitHub Copilot Chat extension and Copilot CLI¶
Status¶
Accepted
Context¶
The image already ships Claude Code (the claude CLI in Layer G, and the
anthropic.claude-code extension) and the Cline extension. Teams that hold GitHub
Copilot subscriptions asked for the same two surfaces: the VS Code Copilot Chat
extension and the terminal copilot CLI. Neither works without network access to
GitHub's Copilot service, and the egress model is deny-by-default
(ADR 0009): the firewall allows exact hostnames only
(resolved to IPs at apply time) and privoxy filters by domain, so both allowlists
need entries.
Decision¶
- CLI: install
@github/copilotfrom npm in a new Layer G2, right after Claude Code, pinned by anARGwith a# renovate: datasource=npmcomment and added to the Renovate "pin to exact version" rule next to Claude Code. The package is a small loader plus an optional-dependency platform binary. On Alpine the loader resolves@github/copilot-linuxmusl-x64or-arm64(both exist), so no glibc shim is needed (ADR 0001).~/.copilotis created and owned by the user in the image. - Persistence:
~/.copilot(login, config, session state) becomes the named volume${project}-copilot, mirroring~/.claude, andfix-permissions.shfixes its ownership. Without it a rebuild logs the user out. - Extension: add
github.copilot-chatto theextensionslist in.devcontainer/devcontainer.jsonand theexamples/template. It is the standalone Chat extension; the separategithub.copilotcompletions extension was not added. - Egress: add a "GitHub Copilot" block to
.devcontainer/egress-allowlist.txtand.devcontainer/proxy.yaml, built from GitHub's Copilot allowlist reference:api.,proxy.andtelemetry.hosts for the individual, business and enterprise plans, the genericapi.githubcopilot.com,copilot-proxy.githubusercontent.com,origin-tracker.githubusercontent.com,copilot-telemetry.githubusercontent.com,collector.github.comanddefault.exp-tas.com.github.comandapi.github.comwere already listed. The inference hosts carry# tag:llmso the dashboard highlights them. In theexamples/templates the block is commented out, like the Anthropic block, so consuming projects opt in per plan.
Rejected:
- Wildcards.
*.githubcopilot.comwould be shorter but the firewall does not support wildcards, and the privoxy entry is a plain domain either way. - Installing the CLI at runtime. It needs
registry.npmjs.orgplus a writable global prefix, and is lost on rebuild. - The
github.copilotextension. Not requested; Chat covers the stated need.
Consequences¶
Accepted:
- The image gets larger: npm reports the musl arm64 platform package at about 207 MB unpacked (the x64 one was not measured). Layer G2 sits before Layer H, so the first build invalidates the layers below it.
@github/copilotreleases often, so the Renovate PR for it will be frequent.- The Chat extension is installed by VS Code at container creation, as for the other extensions; it is not part of the image.
- Per-plan hostnames mean some entries are unused for any one subscription. Two
of them,
proxy.*.githubcopilot.comandtelemetry.*.githubcopilot.com, come from the allowlist reference's*.<plan>.githubcopilot.comwildcards rather than from the reference's host table. - Copilot sends prompts and code to GitHub. Whether that is acceptable is a
project decision; the
examples/allowlists stay opt-in for that reason.
Not verified when this was written:
- The
copilotbinary was not executed by the author (the sandbox denied running a downloaded binary). The BATScopilot --versiontest passed in the pull request's CI build on amd64 (GitHub Actions run 43042993231). The arm64 image is first built by the release workflow, and behavior without a login or network was not observed. - The hostnames were checked against GitHub's reference and DNS, but DNS resolves any name under these zones, so it does not prove a host is used. The dashboard's blocked-request list will show any missing host on first use.
- The dashboard has Copilot CLI support (
COPILOT_DIR), butentrypoint.shdoes not set it, so Copilot token and cost figures are not shown yet.