← all posts

copilot_here: October 2025 Updates - Auto-Updates, Cross-Platform Support, and More

Gordon Beeming
Gordon Beeming
On this page9 sections ▾

I've been running GitHub Copilot CLI in Docker with copilot_here (my previous post covers the initial setup), and the October updates addressed Windows startup, script installation and updates, argument forwarding, and image cleanup.

#What's New in October 2025

Here's a quick summary of the major updates. Skip to any section that interests you:

  1. Windows Docker Desktop Support - Added a fallback when user creation fails
  2. Auto-Updating Scripts - One command to update your shell functions without manual copy-paste
  3. Quick Install Method - One command instead of copying 200+ lines into your shell config
  4. Argument Pass-Through - Forwards native Copilot flags such as --resume
  5. Script Versioning - Know exactly which version you're running
  6. YOLO Mode Enhancements - Auto-approve everything with --allow-all-paths
  7. Smart Image Cleanup - Only removes images older than 7 days, saves bandwidth and time

#1. Windows Docker Desktop Support

The setup worked on my Mac, but failed during user creation on Windows Docker Desktop.

#The Issue

In the Windows failure I was handling, the entrypoint script hadn't created the non-root user (appuser). It then tried to switch to that missing user with gosu and failed. The error establishes the missing user; it doesn't explain why user creation failed.

Error output
error: failed switching to "appuser": unable to find user appuser:
no matching entries in passwd file

#The Fix

Instead of just assuming user creation works, I added a verification step:

entrypoint.sh
# Verify the user was created successfully
if ! id appuser >/dev/null 2>&1; then
    echo "Warning: Failed to create appuser, running as root" >&2
    mkdir -p /home/appuser/.copilot
    exec "$@"
fi

The fallback runs as root and prints a warning, so it changes the user the command runs under. I accepted that tradeoff for this local development tool, but the warning matters when checking the permissions available in a session.

I also restructured the README to show PowerShell instructions alongside bash/zsh rather than buried in a footnote.

#2. Auto-Updating Scripts

The Docker image can auto-update via docker pull, but what about the shell functions users add to their .bashrc or .zshrc? Those live on the host machine and don't update themselves.

#The Challenge

I wanted users to be able to update their shell functions without:

  • Manually copying code from GitHub
  • Re-running curl commands
  • Editing their shell config files
  • Accidentally breaking their setup

#The Solution

I created standalone script files (copilot_here.sh and copilot_here.ps1) that users can download once and source in their shell profiles. Then I added an update flag that:

  1. Downloads the latest version from GitHub
  2. Shows you the version change
  3. Automatically reloads your current shell session
Terminal
copilot_here --update

Output:

Output
Updating scripts from GitHub repository...
 Updated bash/zsh script
Current version: 2025-10-28
Reloading shell function...
 Scripts updated successfully!

It updates the file and reloads the function in your current session, so you don't need to restart your terminal.

If you have the script symlinked somewhere (like a dotfiles repo), the update function detects the symlink and updates the source file, so your dotfiles stay in sync.

#3. Quick Install Method

The old setup required users to copy shell function code from the README and paste it into their config files. It worked, but it was awkward. The installer downloads and sources a script file instead.

#Before (Manual Mode):

Terminal
# User copies 200+ lines of bash from README
# Pastes into ~/.zshrc
# Hopes they got it all
# Maybe accidentally pastes twice
# Now has duplicate functions 😬

#After (Quick Install):

Terminal
curl -fsSL https://github.com/GordonBeeming/copilot_here/releases/download/cli-latest/install.sh | $SHELL

Because the script lives in its own file, later updates use copilot_here --update.

I also added duplicate detection, so if you accidentally run the setup twice, it won't add the source line multiple times:

Duplicate detection
if ! grep -q "source ~/.copilot_here.sh" ~/.zshrc 2>/dev/null; then
  echo 'source ~/.copilot_here.sh' >> ~/.zshrc
fi

#4. Argument Pass-Through: Unlocking Native Copilot Features

I had built-in support for specific flags like --help and --no-cleanup, but that meant I was re-implementing argument parsing for flags the underlying CLI already handled. So I added automatic pass-through instead:

Argument pass-through logic
# Built-in wrapper args
WRAPPER_ARGS=("--help" "-h" "--no-cleanup" "--no-pull" "-d" "--dotnet" 
              "-dp" "--dotnet-playwright" "--update" "--upgrade")

# Check if arg is wrapper-specific or should pass through
for arg in "$@"; do
  if [[ ! " ${WRAPPER_ARGS[@]} " =~ " ${arg} " ]]; then
    # Not a wrapper arg, pass it to the container
    passthrough_args+=("$arg")
  fi
done

Arguments the wrapper doesn't recognise are passed to Copilot for it to handle:

Terminal
copilot_here --model gpt-4 "explain this code"
copilot_here -v  # Show version
copilot_here --whatever-future-flag-gets-added

#The --resume flag

One example is --resume. When Copilot is mid-task and something interrupts it (network hiccup, timeout, whatever), you can pick up right where it left off:

Terminal
copilot_here --resume
Screenshot showing the --resume flag allowing continuation of a previous Copilot session
The --resume flag picks up right where you left off

For long-running tasks, not having to start over is a real time-saver. And since it goes through the pass-through logic, there's nothing special I had to do to support it.

When you run copilot_here --help, it shows both the wrapper's help AND the underlying Copilot CLI help, so you can discover features like --resume naturally.

#5. Script Versioning

When someone reports an issue, the first question is always "which version are you on?" So every script now has a version header:

Script version header
# Version: 2025-10-28

The format is YYYY-MM-DD for the primary version, and if I make multiple updates in one day, it becomes YYYY-MM-DD.1, YYYY-MM-DD.2, etc.

This already came up while testing changes. Instead of the vague "are you on the latest?", I can say "you need 2025-10-28 or later for that."

#6. YOLO Mode Enhancements

copilot_yolo mode lets you skip confirmation prompts entirely. Where copilot_here asks before executing commands, YOLO mode just runs:

Terminal
copilot_yolo "fix all the linting errors in this project"
# Auto-approves all tool usage, including file modifications

I added a --allow-all-paths flag specifically for this, which pairs with auto-approval for a fully hands-off run. Useful for workflows you trust. I'd leave it off for anything touching production.

#7. Smart Image Cleanup

The cleanup could remove an unused image and immediately pull the same image again on the next launch. That made the cleanup cause unnecessary downloads.

#The Problem

The cleanup logic had two issues:

  1. It was trying to remove intermediate images with <none> tags, which would fail and spam your console
  2. It removed ALL unused images, including the current latest one, forcing an unnecessary re-download
Output
  Failed to remove: ghcr.io/gordonbeeming/copilot_here:<none>
Pulling latest image...
# Downloads the same image it just removed 🤦

#The Fix

The cleanup checks the image age:

Smart image cleanup
# Get cutoff timestamp (7 days ago)
local cutoff_date=$(date -d '7 days ago' +%s 2>/dev/null || date -v-7d +%s 2>/dev/null)

# Get all copilot_here images, excluding <none> tags
local all_images=$(docker images --filter "label=project=copilot_here" \
  --format "{{.Repository}}:{{.Tag}}|{{.CreatedAt}}" | grep -v ":<none>" || true)

# Only remove if older than 7 days
if [ -n "$image_date" ] && [ "$image_date" -lt "$cutoff_date" ]; then
  docker rmi "$image" >/dev/null 2>&1
fi

The cleanup runs after the pull and filters out <none> tags. The age check uses the image creation date, not the time it was downloaded. An image created more than seven days ago can still be the current release, so age alone does not guarantee that cleanup will retain the image just pulled.

The changes make the wrapper easier to maintain: version information helps with bug reports, argument forwarding avoids duplicating Copilot's parser, and the installer keeps shell setup in one file. Windows still has the root-user fallback described above, so that warning is worth checking when diagnosing a startup problem.

#What's next

A few things I'm still poking at:

  • Better error messages when GitHub token scopes are wrong (currently the error is cryptic)
  • Support for custom Docker registries for enterprise setups
  • A configurable cleanup period, though honestly 7 days hasn't caused complaints yet

The project is on GitHub: copilot_here. The installer takes one command and you get Copilot CLI running in a sandboxed container that keeps itself up to date.

Gordon Beeming
Gordon Beeming

Father • Husband • Triathlete • SSW Solution Architect

Related posts