Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/agents/analysis.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: analysisAgent
description: "Use when understanding/explaining the codebase and when refining or implementing code changes with validation. Keywords: explain code, trace logic, refactor, cleanup, improve, modify files, run checks."
tools: [read, search, edit, execute, todo]
user-invocable: true
---
You are a focused coding specialist for code explanation, refinement, and safe implementation.

Your job is to:
- Understand existing project structure and behavior before making edits.
- Improve or refine code changes safely and with minimal regression risk.
- Explain code paths and implementation details when asked, including read-only analysis tasks.
- Automatically run targeted validation commands after edits when practical.

## Constraints
- DO NOT make unrelated refactors outside the requested scope.
- DO NOT introduce unnecessary dependencies or broad architectural changes unless asked.
- DO NOT leave changes unverified when basic checks are available.
- ONLY make purposeful, traceable edits tied to the request.

## Approach
1. Clarify the requested outcome and identify affected files/components.
2. Inspect existing code paths and conventions before editing.
3. Implement minimal, high-confidence changes.
4. Run relevant checks or tests and inspect errors.
5. Report what changed, why, and any residual risks.

## Output Format
Return:
1. A brief result summary.
2. Files changed with key modifications.
3. Validation performed (commands/tests) and outcomes.
4. Open risks, assumptions, or follow-up suggestions if needed.
21 changes: 20 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@

SHELL ["/bin/bash", "-c"]


# --------------------------------------------
# ENV Defaults (override with Docker Compose or CLI)
# --------------------------------------------
ENV LANGUAGES=node,python,java \

Check warning on line 22 in Dockerfile

View workflow job for this annotation

GitHub Actions / build

Variables should be defined before their use

UndefinedVar: Usage of undefined variable '$COPILOT_GITHUB_TOKEN' More info: https://docs.docker.com/go/dockerfile/rule/undefined-var/

Check warning on line 22 in Dockerfile

View workflow job for this annotation

GitHub Actions / build

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "COPILOT_GITHUB_TOKEN") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 22 in Dockerfile

View workflow job for this annotation

GitHub Actions / build

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "GITLAB_PERSONAL_ACCESS_TOKEN") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 22 in Dockerfile

View workflow job for this annotation

GitHub Actions / build

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "OPENAI_API_KEY") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 22 in Dockerfile

View workflow job for this annotation

GitHub Actions / build

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "VSCODE_PASSWORD") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
NODE_VERSION=20.11.1 \
ASDF_VERSION=v0.14.0 \
PYTHON_VERSION=3.12.1 \
Expand All @@ -28,7 +29,14 @@
VSCODE_PASSWORD=agent \
OPENAI_API_KEY=your_openai_api_key_here \
OPENAI_MODEL=gpt-4 \
GITLAB_PERSONAL_ACCESS_TOKEN=your_gitlab_token_here
GITLAB_PERSONAL_ACCESS_TOKEN=your_gitlab_token_here \
COPILOT_CLI_ENABLED=false \
COPILOT_CLI_MCP_ENABLED=false \
COPILOT_CLI_INSTALL_METHOD=auto \
COPILOT_CLI_VERSION= \
COPILOT_CLI_PREFIX=/usr/local \
COPILOT_GITHUB_TOKEN=${COPILOT_GITHUB_TOKEN} \
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ENV COPILOT_GITHUB_TOKEN=${COPILOT_GITHUB_TOKEN} line bakes whatever COPILOT_GITHUB_TOKEN is set to at build time (including a real GitHub personal access token from the host environment or build args) directly into the final image. Anyone with access to the image or a running container can read this environment variable (e.g., via docker inspect or /proc), leading to credential theft and compromise of the associated GitHub account. Avoid persisting this token in the image and instead pass it only at runtime when needed, ensuring it is not stored in image layers or default ENV values.

Copilot uses AI. Check for mistakes.
BROWSERS_ENABLED=false

# --------------------------------------------
# Locale setup
Expand Down Expand Up @@ -71,6 +79,11 @@
COPY src/scripts /opt/scripts/
RUN chmod +x /opt/scripts/*.sh || true

# --------------------------------------------
# Copilot CLI MCP templates
# --------------------------------------------
COPY src/copilot /opt/copilot/

# --------------------------------------------
# Install languages
# --------------------------------------------
Expand All @@ -80,6 +93,12 @@
# Source bashrc to load asdf and installed languages
RUN . ~/.bashrc

# --------------------------------------------
# Optional: browsers + Copilot CLI
# --------------------------------------------
RUN bash /opt/scripts/install_browsers.sh
RUN bash /opt/scripts/install_copilot_cli.sh
Comment on lines +96 to +100
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

install_browsers.sh and install_copilot_cli.sh run at image build time, but the PR only wires COPILOT_CLI_ENABLED/BROWSERS_ENABLED via runtime docker-compose environment variables. As a result, these opt-in installs can’t be enabled via compose as documented. Use ARG + ENV in the Dockerfile and build.args in docker-compose.yml (or move these installs to container startup).

Copilot uses AI. Check for mistakes.

# --------------------------------------------
# VS Code + extensions + MCPs + settings
# --------------------------------------------
Expand Down
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,61 @@ Each script should support:

---

## 🤖 Copilot CLI + MCP (opt-in)

This image can optionally install GitHub Copilot CLI and seed a CLI-level MCP config for WebdriverIO MCP.

### Enable during build

Use build args (recommended) to enable the install and seed the MCP config:

```bash
COPILOT_CLI_ENABLED=true \
COPILOT_CLI_MCP_ENABLED=true \
docker compose -f docker-compose.yml up --build
```
Comment on lines +142 to +148
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “Enable during build” snippet sets env vars for docker compose up --build, but the compose file doesn’t pass these as build.args, and the Dockerfile doesn’t declare ARGs for them. This means the Copilot/browser installs won’t actually be enabled during build as documented. Update the docs to show the correct build-arg usage (or update compose/Dockerfile to match the documented flow).

Copilot uses AI. Check for mistakes.

Optional build flags:

- `COPILOT_CLI_INSTALL_METHOD` = `auto` | `script` | `npm`
- `COPILOT_CLI_VERSION` = specific version (optional)
- `COPILOT_CLI_PREFIX` = install prefix (default `/usr/local`)
- `BROWSERS_ENABLED=true` to install Google Chrome (`google-chrome-stable`) for MCP browser automation

### MCP seed template

The template lives at [src/copilot/mcp-config.json](src/copilot/mcp-config.json) and is copied to:

```
~/.copilot/mcp-config.json
```

### Authenticate and verify

Inside the container:

```bash
copilot --version
copilot
```

If prompted, run `/login` and follow the instructions. You can also set `GH_TOKEN` or `GITHUB_TOKEN`.

### Minimal demo (headless browser + screenshot)

With MCP seeded and browsers enabled, run a simple flow from Copilot CLI:

1. Start a session
2. Navigate to a URL
3. Take a screenshot
4. Close the session

Example prompt to Copilot CLI:

"Use wdio-mcp to open a headless browser, navigate to https://example.com, take a screenshot at /workspace/example.png, then close the session."

---

---

## 📄 Roadmap
Expand Down
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ services:
VSCODE_PASSWORD: "${VSCODE_PASSWORD}"
OPENAI_API_KEY: "${OPENAI_API_KEY}"
OPENAI_MODEL: "${OPENAI_MODEL}"
COPILOT_CLI_ENABLED: "${COPILOT_CLI_ENABLED:-false}"
COPILOT_CLI_MCP_ENABLED: "${COPILOT_CLI_MCP_ENABLED:-false}"
COPILOT_CLI_INSTALL_METHOD: "${COPILOT_CLI_INSTALL_METHOD:-auto}"
COPILOT_CLI_VERSION: "${COPILOT_CLI_VERSION:-}"
COPILOT_CLI_PREFIX: "${COPILOT_CLI_PREFIX:-/usr/local}"
BROWSERS_ENABLED: "${BROWSERS_ENABLED:-false}"
Comment on lines +20 to +25
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These variables are set under environment: (container runtime), but the Copilot/Chrome installs happen during docker build (Dockerfile RUN bash /opt/scripts/...). As written, toggling COPILOT_CLI_ENABLED / BROWSERS_ENABLED here won’t change what gets installed in the image. Add build.args for these flags (and consume them via ARG in the Dockerfile), or perform the installs at container startup.

Copilot uses AI. Check for mistakes.
GITLAB_PERSONAL_ACCESS_TOKEN: "${GITLAB_PERSONAL_ACCESS_TOKEN}"
volumes:
- ./src/workspace:/workspace
Expand Down
11 changes: 11 additions & 0 deletions env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ VSCODE_PASSWORD=agent
OPENAI_API_KEY=your_openai_api_key_here
OPENAI_MODEL=gpt-4

# Copilot CLI (opt-in, build args recommended)
COPILOT_CLI_ENABLED=false
COPILOT_CLI_MCP_ENABLED=false
COPILOT_CLI_INSTALL_METHOD=auto
COPILOT_CLI_VERSION=
COPILOT_CLI_PREFIX=/usr/local
COPILOT_GITHUB_TOKEN=your_github_personal_access_token_here

# Browser runtime for MCPs (opt-in, build args recommended)
BROWSERS_ENABLED=false

# MCP - sequentialthinking
DISABLE_THOUGHT_LOGGING=false

Expand Down
19 changes: 19 additions & 0 deletions src/copilot/mcp-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"mcpServers": {
"wdio-mcp": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@wdio/mcp@0.1.0"],
"tools": [
"start_browser",
"navigate",
"get_visible_elements",
"click_element",
"set_value",
"scroll",
"take_screenshot",
"close_session"
]
}
}
}
35 changes: 35 additions & 0 deletions src/scripts/install_browsers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail

echo "Installing browser runtime (opt-in)"

: "${BROWSERS_ENABLED:=false}"

if [[ "${BROWSERS_ENABLED}" != "true" ]]; then
echo "BROWSERS_ENABLED is not true; skipping browser install."
exit 0
fi

apt-get update

# Install Google Chrome from the official APT repository to avoid snap-based Chromium packages
apt-get install -y --no-install-recommends wget gnupg ca-certificates

install -m 0755 -d /etc/apt/keyrings
wget -qO- https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /etc/apt/keyrings/google-chrome.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/google-chrome.gpg] https://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list

apt-get update
apt-get install -y --no-install-recommends google-chrome-stable

apt-get clean && rm -rf /var/lib/apt/lists/*

if command -v google-chrome >/dev/null 2>&1; then
echo "Google Chrome installed: $(google-chrome --version || true)"
elif command -v chromium-browser >/dev/null 2>&1; then
echo "Chromium installed: $(chromium-browser --version || true)"
elif command -v chromium >/dev/null 2>&1; then
echo "Chromium installed: $(chromium --version || true)"
else
echo "Browser install completed, but no supported browser binary found on PATH." >&2
fi
74 changes: 74 additions & 0 deletions src/scripts/install_copilot_cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env bash
set -euo pipefail

echo "Installing GitHub Copilot CLI (opt-in)"

: "${COPILOT_CLI_ENABLED:=false}"
: "${COPILOT_CLI_INSTALL_METHOD:=auto}"
: "${COPILOT_CLI_INSTALL_URL:=https://gh.io/copilot-install}"
: "${COPILOT_CLI_PREFIX:=/usr/local}"
: "${COPILOT_CLI_VERSION:=}"
: "${COPILOT_CLI_MCP_ENABLED:=false}"
: "${COPILOT_CLI_MCP_CONFIG_TEMPLATE:=/opt/copilot/mcp-config.json}"
: "${COPILOT_CLI_MCP_CONFIG_PATH:=/root/.copilot/mcp-config.json}"
: "${COPILOT_GITHUB_TOKEN:=your_github_personal_access_token_here }"

Comment on lines +14 to +15
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

COPILOT_GITHUB_TOKEN default value has trailing spaces and a } (your_github_personal_access_token_here }). This won’t match the placeholder check later and can cause an unintended auth attempt with an invalid token. Make the default empty (or make the placeholder string consistent with the later comparison).

Copilot uses AI. Check for mistakes.
if [[ "${COPILOT_CLI_ENABLED}" != "true" ]]; then
echo "COPILOT_CLI_ENABLED is not true; skipping Copilot CLI installation."
exit 0
fi

install_via_script() {
echo "Installing Copilot CLI via official install script..."
if [[ -n "${COPILOT_CLI_VERSION}" ]]; then
curl -fsSL "${COPILOT_CLI_INSTALL_URL}" | VERSION="${COPILOT_CLI_VERSION}" PREFIX="${COPILOT_CLI_PREFIX}" bash
else
curl -fsSL "${COPILOT_CLI_INSTALL_URL}" | PREFIX="${COPILOT_CLI_PREFIX}" bash
Comment on lines +24 to +26
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The install_via_script function downloads a remote shell script via curl from COPILOT_CLI_INSTALL_URL and pipes it directly into bash without any integrity or authenticity verification. If the URL, DNS, or network is compromised—or if COPILOT_CLI_INSTALL_URL is overridden to a malicious endpoint—an attacker-controlled script will execute with build-time privileges and can fully compromise the resulting image and any secrets available during the build. To mitigate this, fetch a specific, pinned installer artifact and verify it using a checksum or vendor signature before execution instead of executing the HTTP response body directly via a pipe.

Copilot uses AI. Check for mistakes.
fi
}

install_via_npm() {
echo "Installing Copilot CLI via npm..."
if ! command -v npm >/dev/null 2>&1; then
echo "npm not found; cannot install Copilot CLI via npm." >&2
return 1
fi
if [[ -n "${COPILOT_CLI_VERSION}" ]]; then
npm install -g "@github/copilot@${COPILOT_CLI_VERSION}"
else
npm install -g @github/copilot
fi
}

if [[ "${COPILOT_CLI_INSTALL_METHOD}" == "script" ]]; then
install_via_script
elif [[ "${COPILOT_CLI_INSTALL_METHOD}" == "npm" ]]; then
install_via_npm
else
install_via_script || install_via_npm
fi

if command -v copilot >/dev/null 2>&1; then
echo "Copilot CLI installed: $(copilot --version)"
else
echo "Copilot CLI installation finished, but 'copilot' is not on PATH." >&2
fi

if [[ -n "${COPILOT_GITHUB_TOKEN}" && "${COPILOT_GITHUB_TOKEN}" != "your_github_personal_access_token_here" ]]; then
echo "Logging into Copilot CLI with provided GitHub token to cache credentials..."
echo "${COPILOT_GITHUB_TOKEN}" | copilot auth login --with-token || echo "Copilot CLI login failed; please check your token and login manually." >&2
else
Comment on lines +57 to +60
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running copilot auth login --with-token during docker build will cache credentials into the image layer (under root’s home), which risks leaking access tokens to anyone who can pull the image. Prefer removing build-time login entirely and require interactive login at runtime, or use BuildKit secrets and ensure no credentials are persisted into the final image.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, swap login part to entrypoint.sh

echo "COPILOT_GITHUB_TOKEN is not set or is the default placeholder; skipping Copilot CLI login."
fi

if [[ "${COPILOT_CLI_MCP_ENABLED}" == "true" ]]; then
if [[ -f "${COPILOT_CLI_MCP_CONFIG_TEMPLATE}" ]]; then
echo "Seeding Copilot CLI MCP config..."
mkdir -p "$(dirname "${COPILOT_CLI_MCP_CONFIG_PATH}")"
cp "${COPILOT_CLI_MCP_CONFIG_TEMPLATE}" "${COPILOT_CLI_MCP_CONFIG_PATH}"
else
echo "MCP config template not found at ${COPILOT_CLI_MCP_CONFIG_TEMPLATE}; skipping seed." >&2
fi
else
echo "COPILOT_CLI_MCP_ENABLED is not true; skipping MCP config seed."
fi