copilot_here is a shell tool designed to run GitHub Copilot CLI commands inside a sandboxed Docker container, ensuring your host machine remains clean and secure. The tool provides shell function wrappers for Bash, Zsh, and PowerShell, seamlessly proxying Copilot CLI commands through a containerized environment.
Key Features:
Sandboxed Environment: Isolates GitHub Copilot CLI in a Docker container to enhance security.
Shell Wrappers: Provides functions for Bash, Zsh, and PowerShell to simplify command execution.
Automatic Authentication: Uses existing gh CLI credentials for seamless authentication.
Mounting Control: Grants file system access only to specified directories, improving security.
Execution Modes: Offers Safe Mode (requires confirmation) and YOLO Mode (auto-approves), catering to different usage needs.
Image Variants: Supports multiple container images with various toolsets (e.g., .NET, Playwright, Rust).
Audience & Benefit:
Ideal for developers seeking a secure, isolated environment for GitHub Copilot CLI. Benefits include enhanced security by isolating tools, avoiding global Node.js installations, and maintaining a clean host machine. Persistent configuration ensures trusted folders and preferences are remembered across sessions.
Installable via winget.
README
copilot_here: A Secure, Portable Copilot CLI Environment
Run the GitHub Copilot CLI from any directory on your machine, inside a sandboxed Docker container that automatically uses your existing gh authentication.
๐ What is this?
This project solves a simple problem: you want to use the awesome GitHub Copilot CLI, but you also want a clean, portable, and secure environment for it.
The copilot_here shell function is a lightweight wrapper around a Docker container. When you run it in a terminal, it:
Enhances security by isolating the tool in a container, granting it file system access only to the directory you're currently in. ๐ก๏ธ
Keeps your machine clean by avoiding a global Node.js installation.
Authenticates automatically by using your host machine's existing gh CLI credentials.
Validates token permissions by checking for required scopes and warning you about overly permissive tokens.
Persists its configuration, so it remembers which folders you've trusted across sessions.
Stays up-to-date by automatically pulling the latest image version on every run.
You must be logged in to the GitHub CLI. You can check by running gh auth status. Your token must have the copilot and read:packages scopes. If it doesn't, run gh auth refresh -h github.com -s copilot,read:packages to add them.
Choose your platform below. The scripts include both Safe Mode (asks for confirmation) and YOLO Mode (auto-approves) functions. You can use either or both depending on your needs.
Execution Modes
Safe Mode (copilot_here) - Always asks for confirmation before executing commands. Recommended for general development work where you want control over what gets executed.
YOLO Mode (copilot_yolo) - Automatically approves all tool usage without confirmation. Convenient for trusted workflows but use with caution as it can execute commands without prompting.
Image Variants
All images support both AMD64 (x86_64) and ARM64 (Apple Silicon, etc.) architectures.
All functions support switching between Docker image variants using flags:
Format:path/to/dir:ro or path/to/dir:rw (one per line)
Management Commands:
Use --save-mount, --save-mount-global, --remove-mount, and --list-mounts to manage persistent mounts.
Image Management
You can configure the default image tag to use (e.g., dotnet, dotnet-playwright, or a specific SHA) so you don't have to pass flags every time.
Management Commands:
--list-images - List all available Docker images
--show-image - Show current default image configuration
--set-image - Set default image in local config
--set-image-global - Set default image in global config
--clear-image - Clear default image from local config
--clear-image-global - Clear default image from global config
Configuration Files:
Global: ~/.config/copilot_here/image.conf
Local: .copilot_here/image.conf
Custom image behavior:
Custom image refs are accepted for CLI/config values, including local refs like my-local-image:dev
Default behavior is to pull before run
Use --no-pull to force local-only execution
Model Management
You can configure the default AI model to use so you don't have to pass --model every time.
Management Commands:
--list-models - List available AI models (queries Copilot CLI error message)
--show-model - Show current default model configuration
--set-model - Set default model in local config
--set-model-global - Set default model in global config
--clear-model - Clear default model from local config
--clear-model-global - Clear default model from global config
Special value: Use default as the model ID to explicitly use Copilot CLI's default model. This is useful for overriding a global setting at the local level.
Note: The --list-models command uses a workaround by triggering an invalid model error, which causes the Copilot CLI to list valid models. This is a temporary approach until a proper API is available.
Configuration Files:
Global: ~/.config/copilot_here/model.conf
Local: .copilot_here/model.conf
Configuration Priority:
CLI argument (--model )
Local config (.copilot_here/model.conf)
Container Runtime Management
copilot_here supports multiple container runtimes: Docker, OrbStack, and Podman. The system automatically detects the available runtime, but you can also configure a preferred runtime.
Management Commands:
--show-runtime - Show current container runtime configuration
--list-runtimes - List all available container runtimes on your system
--set-runtime - Set runtime in local config (values: docker, podman, or auto)
--set-runtime-global - Set runtime in global config
Configuration Files:
Global: ~/.config/copilot_here/runtime.conf
Local: .copilot_here/runtime.conf
Configuration Priority:
Local config (.copilot_here/runtime.conf)
Global config (~/.config/copilot_here/runtime.conf)
Auto-detection (tries Docker first, then Podman)
Supported Runtimes:
Docker - Standard Docker Engine or Docker Desktop
OrbStack - Automatically detected when Docker context is set to OrbStack
# Set model for current project
copilot_here --set-model gpt-5
# Set model globally for all projects
copilot_here --set-model-global claude-sonnet-4.5
# Override saved model for one session
copilot_here --model gpt-5-mini
# View current configuration
copilot_here --show-model
Custom Docker Flags (SANDBOX_FLAGS)
Pass additional Docker flags using the SANDBOX_FLAGS environment variable (compatible with Gemini CLI):
Airlock Mode:
When using --enable-airlock, the --network flag changes the proxy's external network while maintaining app container isolation. The app container remains on the internal airlock network and can only access the proxy, which then routes to your specified network.
# Example: Proxy connects to custom network while app stays isolated
docker network create my-services
SANDBOX_FLAGS="--network my-services" copilot_here --enable-airlock
๐ก๏ธ Airlock (Network Isolation)
Airlock provides an additional layer of security by routing all network traffic from the Copilot CLI through a proxy that enforces an allowlist of permitted hosts and paths. This ensures that the AI can only communicate with approved endpoints.
Key Features:
Enforce Mode: Blocks all network requests not matching the allowlist
Monitor Mode: Logs all network activity without blocking (useful for auditing)
Configurable Rules: Define allowed hosts and paths per-project or globally
enforce (e): Blocks requests not matching the allowlist
monitor (m): Allows all requests but logs them for review
When enabling Airlock for the first time, you'll be prompted to choose between enforce and monitor mode.
Logging:
When enable_logging is true (or in monitor mode), request logs are saved to .copilot_here/logs/ (excluded from git by default).
Network Topology View
graph LR
subgraph Docker_Host [๐ณ Docker Host]
style Docker_Host fill:#F8F9FA,stroke:#1A1A1A,color:#1A1A1A
subgraph Airlock_Net [๐ Network: airlock_net]
style Airlock_Net fill:#E9ECEF,stroke:#1A1A1A,stroke-width:2px,stroke-dasharray: 5 5,color:#1A1A1A
App[("๐ค Copilot Container(Single Homed)")]
style App fill:#FFFFFF,stroke:#0063B2,stroke-width:2px,color:#1A1A1A
ProxyInt["Proxy Interface(eth0)"]
style ProxyInt fill:none,stroke:none,color:#1A1A1A
end
subgraph Proxy_Container [๐ก๏ธ Secure Proxy Container]
style Proxy_Container fill:#46CBFF,stroke:#0063B2,stroke-width:3px,color:#1A1A1A
ProxyApp["Proxy Process"]
style ProxyApp fill:#F8F9FA,stroke:#0063B2,color:#1A1A1A
end
App == "1. Traffic via Airlock" ==> ProxyApp
end
Internet((โ๏ธ Internet / GitHub))
style Internet fill:#F8F9FA,stroke:#1A1A1A,stroke-width:2px,color:#1A1A1A
ProxyApp == "2. Traffic via Bridge" ==> Internet
linkStyle 0 stroke:#0063B2,stroke-width:3px,color:#0063B2
linkStyle 1 stroke:#0063B2,stroke-width:3px,color:#0063B2
๐ The Sealed Chamber (Airlock Network):
The copilot_here container is launched into a private, internal-only network. It has zero direct access to the internet. If an application tries to bypass the proxy, the connection simply fails because there is no route out.
๐ก๏ธ The Sentry (Secure Proxy):
The Proxy is the only component with a "key" to the outside world. It sits with one foot in the Airlock (to listen for requests) and one foot in the Bridge network (to reach GitHub).
โ The Controlled Exit:
Traffic can only leave the Airlock if it explicitly asks the Proxy to carry it. The Proxy inspects the destination against your allow-list and decides whether to let the request pass or block it.
๐ณ Brokered Docker Socket (DinD) (Beta)
> ๐งช Beta: The brokered Docker socket is safer than mounting /var/run/docker.sock directly. Every Docker API call passes through a host-owned allowlist. Body-level inspection (rejecting --privileged and host bind mounts at request time) is the next phase. See docs/known-issues.md for what's in scope today.
The --dind flag lets the AI inside the container spawn sibling containers on the host's runtime. This unblocks Testcontainers integration tests, on-the-fly image builds, and any workflow where the agent needs docker run. The container never sees the real socket: a host-side broker inside the copilot_here binary forwards only the requests that match a JSON allowlist.
Why it's safer than mounting the socket directly:
Every Docker API call passes through the host process. The host stays in control of which endpoints reach the daemon.
Dangerous endpoint families are denied by default: swarm, services, tasks, nodes, secrets, configs, plugins, session, distribution, auth, events.
The allowlist is configured per-project (.copilot_here/docker-broker.json) or globally (~/.config/copilot_here/docker-broker.json).
enforce mode blocks unmatched requests with a 403. monitor mode allows everything but logs each call to a JSONL file you can audit.
Quick start:
# One-off session, using the embedded default rules.
copilot_here --dind --dotnet -p "run the integration tests"
# Persist to local project config.
copilot_here --enable-docker-broker
copilot_here --show-docker-broker-rules
# Allow specific images to be spawned (the broker is strict default-deny).
copilot_here --add-docker-broker-image 'mcr.microsoft.com/mssql/server:*'
copilot_here --add-docker-broker-image 'testcontainers/ryuk:*'
# Tweak the rules in $EDITOR.
copilot_here --edit-docker-broker-rules
Setup Commands:
--enable-docker-broker - Enable the broker for current project
--enable-global-docker-broker - Enable the broker globally
--disable-docker-broker - Disable the broker for current project
--disable-global-docker-broker - Disable the broker globally
Trusted Image Commands:
--add-docker-broker-image - Add an image glob to the local trusted list (e.g. 'alpine:*')
--add-global-docker-broker-image - Same, global config
--remove-docker-broker-image - Remove an image glob from local
--remove-global-docker-broker-image - Remove from global
--allow-privileged-global-docker-broker / --deny-privileged-global-docker-broker - Same, global config
Management Commands:
--show-docker-broker-rules - Display defaults plus the active local and global config
--edit-docker-broker-rules - Edit local rules in $EDITOR
--edit-global-docker-broker-rules - Edit global rules in $EDITOR
Modes:
Mode
Behavior
enforce (default)
Blocks any Docker API call that doesn't match the allowlist with a 403.
monitor
Allows everything but logs each call to .copilot_here/logs/docker-broker.jsonl when enable_logging: true.
Runtime support: Docker, OrbStack (uses the standard /var/run/docker.sock on macOS, so no extra setup), Podman (rootless and rootful, detected via podman info). Set DOCKER_HOST if you need to override.
DinD with airlock: Allowed, with a loud warning at startup. The broker inspects every POST /containers/create body, and in airlock mode it rewrites HostConfig.NetworkMode so spawned siblings land on the same internal-only airlock network as the workload. The workload then reaches them by Docker DNS instead of crossing the airlock boundary. This is still beta; check the known issues before relying on it for strict isolation.
Read this before turning it on: the broker reads every POST /containers/create body and rejects unsafe settings: Privileged: true, host network/PID/IPC namespaces, forbidden bind mounts (/, /etc, /var, /var/run/docker.sock, and similar), and dangerous Linux capabilities (SYS_ADMIN, SYS_MODULE, and friends). It also enforces a strict default-deny image allowlist: every image the AI tries to spawn must match an explicit pattern in body_inspection.allowed_images, otherwise the call is refused. See docs/known-issues.md for the remaining limitations and operational caveats.
๐งญ copilot_here vs Docker Sandboxes
A reasonable question once you've seen Docker Sandboxes (sbx): which one do I actually pick? Short answer: both are good, they're tuned for different situations, and they can sit on the same machine without stepping on each other.
๐ The facts
copilot_here
Docker Sandboxes (sbx)
Isolation model
Container on your existing runtime (shared kernel)
microVM per sandbox (its own kernel)
Container runtime
Docker, OrbStack, Podman (rootless and rootful), auto-detected
Docker-authored CLI, ships with its own microVM stack
Workspace mount
Project directory read/write. Extra folders via --mount are read-only by default, --mount-rw to opt in
Workspace read/write. --branch puts each agent in its own git worktree under .sbx/
You bounce between Claude, Codex, Gemini and friends today, and want one sandbox tool that already supports all of them out of the box.
You want microVM isolation (separate kernel) rather than container isolation.
You want long-lived, named sandboxes and parallel agents on the same repo via branch mode.
You want nested Docker inside the sandbox with no extra configuration.
Reach for copilot_here when:
You're focused on the GitHub Copilot CLI today and want tight, Copilot-shaped default network rules rather than broad wildcards. (Other agents are on the roadmap; the scaffolding is in the repo.)
You want ephemeral, per-run containers that reuse the host gh auth rather than long-lived sandbox state.
You want explicit per-folder opt-in for anything beyond the project dir. Extra mounts default to read-only unless you pass --mount-rw.
Your container runtime is Podman, rootless Podman, or OrbStack, and you'd rather not install a Docker-authored CLI. copilot_here auto-detects Docker, OrbStack, and Podman, and --set-runtime pins your choice.
๐ง Explain it like I'm in 5th grade
Docker Sandboxes (sbx) is like renting each AI agent its own tiny apartment. Own front door. Own kitchen. Own phone line. If the agent makes a mess, the mess stays in the apartment. It's great when you hire a bunch of different AI agents and you want strong walls around every one of them.
copilot_here is like giving the agent a locked room inside your house. The walls are not as thick, but the door is bolted, it can only touch the one drawer you unlocked (your project folder), and there is a bouncer at the front door checking every phone call (the Airlock). It is small, fast to start, and easy to read the source code of.
The everyday version of "when do I pick which?":
Pick Docker Sandboxes when you use lots of different AI agents and you want the strongest walls.
Pick copilot_here when you are mostly using the GitHub Copilot CLI, you want a small inspectable sandbox that reuses your existing GitHub login, and you want strict, Copilot-shaped network rules by default. It's also an easy choice if your container runtime is already Podman or OrbStack rather than Docker.
Both can live on the same machine. Use whichever fits the job.
Package Managers
Homebrew (macOS):
brew tap gordonbeeming/tap
brew install --cask copilot-here
Homebrew (Linux):
brew tap gordonbeeming/tap
brew install copilot_here
WinGet (Windows):
winget install GordonBeeming.CopilotHere
.NET Global Tool:
dotnet tool install -g copilot_here
For Linux/macOS (Bash/Zsh)
Quick Install (Recommended):
If you already have the copilot_here binary on your PATH, you can install shell integrations for bash/zsh/fish (and on Windows: PowerShell + cmd) with:
copilot_here --install-shells
Otherwise, download and run the install script:
# Source the installer to load functions immediately
source <(curl -fsSL https://github.com/GordonBeeming/copilot_here/releases/download/cli-latest/install.sh)
To update later, just run: copilot_here --update
Manual Install (Alternative):
If you prefer not to use the quick install method, you can manually copy the script file:
Add to your shell profile (~/.zshrc or ~/.bashrc):
source ~/.copilot_here.sh
Reload your shell:
source ~/.zshrc # or source ~/.bashrc
Note: If you want to disable the auto-update functionality, you can remove the --update-scripts and --upgrade-scripts case blocks from the downloaded script file.
For Windows (PowerShell)
Quick Install (Recommended):
Download and source the script in your PowerShell profile:
# Create profile if it doesn't exist
if (-not (Test-Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force | Out-Null }
# Remove old entries and add new one
$profileContent = Get-Content $PROFILE -Raw
$profileContent = $profileContent -replace '(?m)^.*copilot_here\.ps1.*$', ''
$profileContent = $profileContent.TrimEnd() + "`n`n. `"$env:USERPROFILE\.copilot_here.ps1`""
Set-Content -Path $PROFILE -Value $profileContent
Or manually edit your profile:
notepad $PROFILE
# Remove any old copilot_here.ps1 entries and add:
# . "$env:USERPROFILE\.copilot_here.ps1"
Reload your PowerShell profile:
. $PROFILE
Note: The auto-update functionality can be removed by editing the downloaded script file.
Usage
Once set up, using it is simple on any platform. All commands work identically on Linux, macOS, and Windows.
Interactive Mode
Start a full chat session with the welcome banner:
# Base image (default)
copilot_here
# With .NET image
copilot_here --dotnet
# With .NET + Playwright image
copilot_here --dotnet-playwright
# With Rust image
copilot_here --rust
# Get help
copilot_here --help
copilot_yolo --help
Non-Interactive Mode
Pass a prompt directly to get a quick response.
Safe Mode (asks for confirmation before executing):
# Base image
copilot_here "suggest a git command to view the last 5 commits"
copilot_here "explain the code in ./my-script.js"
# .NET image
copilot_here --dotnet "build and test this .NET project"
copilot_here --dotnet "explain this C# code"
# .NET + Playwright image
copilot_here --dotnet-playwright "run playwright tests for this app"
# Skip cleanup and pull for faster startup
copilot_here --no-cleanup --no-pull "quick question about this code"
# Use specific model
copilot_here --model claude-sonnet-4.5 "explain this algorithm"
Accessing Session Information
Inside any copilot_here container, you can view detailed information about your session:
# View formatted session info (image, mounts, mode, etc.)
session-info
# Or manually format with Python (works in all images without rebuild)
echo $COPILOT_HERE_SESSION_INFO | python3 -m json.tool
# View raw JSON
echo $COPILOT_HERE_SESSION_INFO
# Query specific fields with jq
echo $COPILOT_HERE_SESSION_INFO | jq .image.tag
echo $COPILOT_HERE_SESSION_INFO | jq .mounts
echo $COPILOT_HERE_SESSION_INFO | jq .airlock.network_config # If airlock enabled
The COPILOT_HERE_SESSION_INFO environment variable contains:
Version: copilot_here build version
Image: Tag and full image name
Mode: "standard" or "yolo"
Working Directory: Container working directory path
Mounts: All mounted paths with their modes (ro/rw) and sources
Airlock: Network proxy status and configuration (if enabled)
This makes it easy for AI assistants to understand the environment without scrolling through startup logs.
> Note: The session-info command will be available in containers after the next image rebuild. Until then, use echo $COPILOT_HERE_SESSION_INFO | python3 -m json.tool for formatted output.
YOLO Mode (auto-approves execution):
# Base image
copilot_yolo "write a function that reverses a string"
copilot_yolo "run the tests and fix any failures"
# .NET image
copilot_yolo --dotnet "create a new ASP.NET Core API project"
copilot_yolo --dotnet "add unit tests for this controller"
# .NET + Playwright image
copilot_yolo --dotnet-playwright "write playwright tests for the login page"
# Skip cleanup for faster execution
copilot_yolo --no-cleanup "generate a README for this project"
๐ณ Docker Image Variants
This project provides multiple Docker image variants for different development scenarios. All images include the GitHub Copilot CLI and inherit the base security and authentication features.
Available Images
Tag
Flag
Description
latest
(default)
Base image with Node.js 20, Git, and essential tools
dotnet
--dotnet
.NET 8, 9 & 10 SDKs
dotnet-8
--dotnet8
.NET 8 SDK only
dotnet-9
--dotnet9
.NET 9 SDK only
dotnet-10
--dotnet10
.NET 10 SDK only
playwright
--playwright
Playwright with Chromium browser
dotnet-playwright
--dotnet-playwright
.NET + Playwright combined
rust
--rust
Rust toolchain
dotnet-rust
--dotnet-rust
.NET + Rust combined
golang
--golang
Go toolchain
java
--java
Java JDK 25 with Maven, Gradle & PlantUML
(custom)
--image
Any custom Docker image
Choosing the Right Image
Use latest for general development, scripting, and Node.js projects
Use dotnet when working with .NET projects without browser testing needs
Use playwright when working with Node.js projects that need browser automation
Use dotnet-playwright when you need both .NET and browser automation capabilities
Use rust for Rust development
Use dotnet-rust for projects combining .NET and Rust
Use golang for Go development
Use java for Java development with Maven or Gradle
Use --image to bring your own custom Docker image with additional tools (including local tags like my-local-image:dev)
๐ป Supported Systems
Operating System
Shell
Supported
Tested
macOS
Zsh
โ
โ
macOS
Bash
โ
โ
Linux
Bash
โ
โ
Linux
Zsh
โ
Windows 10/11
PowerShell 5.1
โ
โ
Windows 10/11
PowerShell 7+
โ
โ
> Note: "Tested" represents systems personally tested by the maintainer. The tool likely works on other compatible systems too, but hasn't been verified yet. If you successfully use it on an untested configuration, please let us know!