Repository navigation
feat: Add GitHub Copilot CLI as a supported tool profile #90 #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e141a4d
a906975
78f6854
efba626
c7af901
09bd78a
0faeb83
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| # Copilot CLI | ||
|
|
||
| GitHub Copilot CLI is the command-line coding assistant for GitHub Copilot. | ||
|
|
||
| ## Configuration | ||
|
|
||
| - **Command**: `copilot --disable-builtin-mcps` | ||
| - **YOLO flag**: `--yolo` (enabled by default) | ||
| - **Config directory**: `~/.copilot` | ||
| - **Settings file**: `~/.copilot/settings.json` | ||
| - **Skills directory**: `~/.copilot/skills` | ||
|
|
||
| The extension also passes through selected project-level Copilot configuration: | ||
| `agents/`, `copilot-instructions.md`, `extensions/`, `hooks/`, `instructions/`, | ||
| `lsp-config.json`, `mcp-config.json`, `providers.json`, `settings.json`, and | ||
| `skills/`. | ||
|
|
||
| ## Authentication | ||
|
|
||
| | Variable | Purpose | | ||
| |----------|---------| | ||
| | `COPILOT_GITHUB_TOKEN` | GitHub token injected by the network gateway | | ||
|
|
||
| The provider declares `~/.copilot/config.json` as its auth file. Enclave uses | ||
| its presence to detect an existing auth session and includes it in auth | ||
| import/export. See [Authentication & Secrets](../../../docs/auth.md). | ||
|
|
||
| The gateway sends the declared token as a Bearer authorization header to | ||
| `api.github.com` and `*.githubcopilot.com`. | ||
|
|
||
| ### Recommended: fine-grained PAT via `COPILOT_GITHUB_TOKEN` | ||
|
|
||
| Prefer `COPILOT_GITHUB_TOKEN` with a fine-grained personal access token that | ||
| only grants the **Copilot Requests** permission. This is the minimum Copilot CLI | ||
| needs and the approach recommended by the Copilot CLI maintainers | ||
| ([github/copilot-cli#953](https://github.com/github/copilot-cli/issues/953)). | ||
|
|
||
| ### OAuth login (`/login`) grants broad scopes | ||
|
|
||
| > **Warning:** The device-code and browser OAuth login (`/login`) issues a token | ||
| > with far more scopes than Copilot needs. Observed token scopes: | ||
| > `codespace`, `gist`, `read:org`, `read:user`, `repo` (read and write), and | ||
| > `write:plugin_gateway_connections`. | ||
|
|
||
| A token with `repo` write access can read and modify private repositories, so | ||
| anyone who obtains the stored OAuth credentials (under | ||
| `~/.local/state/enclave/tools/copilot/`) can act on your GitHub account beyond | ||
| Copilot. Use OAuth only when you accept this risk; otherwise use a fine-grained | ||
| PAT as described above. | ||
|
|
||
| ## Memory and Skills | ||
|
|
||
| Copilot Memory is **disabled by default** (`"memory": false` in the settings | ||
| template). Copilot stores memories on GitHub's servers, not in a local memory | ||
| directory. Account-scoped memories can be retrieved by later sessions in other | ||
| projects, other Enclave state roots, or Copilot outside Enclave. This can expose | ||
| project information across those boundaries and let one project's agent | ||
| influence another through shared memories. In YOLO mode, an agent can store | ||
| memories without a confirmation prompt. | ||
|
|
||
| Enclave's per-project memory isolation applies to local files and cannot isolate | ||
| this server-side memory. The extension therefore does not declare a native | ||
| memory directory or memory-disable arguments; `--no-memory` is not a control for | ||
| Copilot's server-side memory. | ||
|
|
||
| If you accept this cross-project sharing, run `/memory on` inside a Copilot | ||
| session to enable it, or `/memory off` to disable it again. When an Enclave config | ||
| override or patch is active, the changed setting carries forward in that | ||
| project's config store. See [Tool Config Patches](../../../docs/configuration.md#tool-config-patches) | ||
| for settings persistence and precedence. | ||
|
|
||
| For a persistent opt-in, add `"memory": true` to a | ||
| [settings patch](../../../docs/configuration.md#tool-config-patches), for example | ||
| `~/.config/enclave/patches/copilot/settings.json` on Linux: | ||
|
|
||
| ```json | ||
| { | ||
| "memory": true | ||
| } | ||
| ``` | ||
|
|
||
| This global patch enables memory for all projects unless overridden by a | ||
| project-specific setting. It does not make the stored memories project-scoped. | ||
|
|
||
| The extension's `enclave-help` skill is installed alongside managed skills in | ||
| `~/.copilot/skills`. | ||
|
|
||
| ## Network Access | ||
|
|
||
| The Copilot service domains are `api.github.com` and `*.githubcopilot.com`. | ||
| The DNS allowlist also includes the common GitHub, npm, PyPI, Go, CDN, and | ||
| TLS/OCSP infrastructure fragments used by Enclave. | ||
|
|
||
| ## Settings | ||
|
|
||
| The default settings template sets `remoteExport` and `autoUpdate` to `false`, | ||
| `includeCoAuthoredBy`, `storeTokenPlaintext`, and `memory` to `false`, | ||
| `logLevel` to `default`, and `model` to `auto`. See [Memory and Skills](#memory-and-skills) | ||
| before enabling memory. | ||
|
|
||
| ## Files | ||
|
|
||
| | File | Purpose | | ||
| |------|---------| | ||
| | `spec.yaml` | Extension manifest (launch behavior, settings, credentials, network, and provider auth) | | ||
| | `install.sh` | Installs `@github/copilot` and its `copilot` command | | ||
| | `check-update.sh` | Returns the latest npm package version for update probes | | ||
| | `gateway-allowlist.conf` | DNS allowlist for network isolation | | ||
| | `templates/settings.json` | Default Copilot settings template | | ||
| | `entrypoint.d/setup.sh` | Creates `~/.copilot` and sets `COPILOT_HOME` | | ||
| | `skills/enclave-help/SKILL.md` | Bundled skill for answering questions from Enclave's documentation | | ||
| | `go/handler.go` | Registers the Copilot tool handler | | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #!/usr/bin/env bash | ||
| # Copyright (C) 2026 Dirk Fauth and others. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the MIT License, which is available in the project root. | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| npm view @github/copilot@latest version |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| #!/bin/bash | ||
| # Copyright (C) 2026 Dirk Fauth and others. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the MIT License, which is available in the project root. | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
| # shellcheck shell=bash | ||
|
|
||
| # Copilot extension setup | ||
| export COPILOT_HOME="$HOME/.copilot" | ||
| mkdir -p "$COPILOT_HOME" | ||
|
|
||
| # In yolo mode, remember the project workspace as trusted for future sessions. | ||
| if [ "${ENCLAVE_YOLO:-}" = "1" ] && [ -n "${PROJECT_DIR:-}" ] && command -v jq >/dev/null 2>&1; then | ||
| _config="$COPILOT_HOME/config.json" | ||
| if [ -f "$_config" ]; then | ||
| # Copilot rewrites config.json as JSONC (leading // comments); strip them for jq. | ||
| _updated="$(grep -v '^[[:space:]]*//' "$_config" | jq --arg dir "$PROJECT_DIR" \ | ||
| '.trustedFolders = (((.trustedFolders // []) + [$dir]) | unique)' \ | ||
| 2>/dev/null)" && printf '%s\n' "$_updated" > "$_config" | ||
| else | ||
| jq -n --arg dir "$PROJECT_DIR" '{trustedFolders:[$dir]}' > "$_config" | ||
| fi | ||
| unset _config _updated | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Copyright (C) 2026 Dirk Fauth and others. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the MIT License, which is available in the project root. | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| # Enclave DNS Allowlist Configuration - Copilot | ||
| no-resolv | ||
| no-poll | ||
| address=/#/ | ||
|
|
||
| # Common Infrastructure | ||
| conf-file=/etc/dnsmasq.allowlists/fragments/github.conf | ||
| conf-file=/etc/dnsmasq.allowlists/fragments/npm.conf | ||
| conf-file=/etc/dnsmasq.allowlists/fragments/pypi.conf | ||
| conf-file=/etc/dnsmasq.allowlists/fragments/go.conf | ||
| conf-file=/etc/dnsmasq.allowlists/fragments/cdn.conf | ||
| conf-file=/etc/dnsmasq.allowlists/fragments/tls.conf |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This only embeds
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's ok. Nothing is missing, |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // Copyright (C) 2026 Dirk Fauth and others. | ||
| // | ||
| // This program and the accompanying materials are made available under the | ||
| // terms of the MIT License, which is available in the project root. | ||
| // | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| package copilot | ||
|
|
||
| import "enclave/internal/tools" | ||
|
|
||
| func init() { | ||
| tools.RegisterHandler("copilot", Handler{}) | ||
| } | ||
|
|
||
| type Handler struct { | ||
| tools.BaseHandler | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #!/bin/bash | ||
| # Copyright (C) 2026 Dirk Fauth and others. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the MIT License, which is available in the project root. | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| set -e | ||
|
|
||
| enclave-install-npm-tool @github/copilot@latest copilot Copilot |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| --- | ||
| name: enclave-help | ||
| description: Answer questions about Enclave by reading the bundled documentation | ||
| --- | ||
|
|
||
| # Enclave Help | ||
|
|
||
| Answer the user's question about Enclave by reading the relevant documentation | ||
| files bundled at `/usr/share/doc/enclave/`. | ||
|
|
||
| ## Important context | ||
|
|
||
| You are running inside an Enclave container. Host-global configuration | ||
| (e.g. `~/.config/enclave/config.json`, network policies, secrets) lives on the | ||
| host filesystem and is not directly editable from inside the container. | ||
| When a question involves host-side configuration changes, explain what the | ||
| user needs to do on the host or via the `enclave` CLI rather than | ||
| attempting in-container file edits. | ||
|
|
||
| ## Documentation index | ||
|
|
||
| | Path | Topic | | ||
| |------|-------| | ||
| | `docs/README.md` | Documentation index | | ||
| | `docs/ARCHITECTURE.md` | Detailed architecture with diagrams | | ||
| | `docs/cli-reference.md` | CLI flags and options | | ||
| | `docs/configuration.md` | Config files and settings | | ||
| | `docs/networking.md` | Network isolation and gateway | | ||
| | `docs/auth.md` | Authentication and API keys | | ||
| | `docs/persistence.md` | Persistent stores and session data | | ||
| | `docs/tools.md` | Supported agent tools | | ||
| | `docs/extensions/` | Extension system (adding tools, features) | | ||
| | `docs/runtime/` | Runtime behavior (stores, auth sync, network flow) | | ||
| | `docs/security/` | Security model and host hardening | | ||
| | `extensions/tools/<tool>/README.md` | Per-tool documentation | | ||
| | `extensions/features/<feature>/README.md` | Per-feature documentation | | ||
|
|
||
| All paths are relative to `/usr/share/doc/enclave/`. | ||
|
|
||
| ## Steps | ||
|
|
||
| 1. Read the doc(s) most relevant to the user's question. | ||
| 2. Synthesize a clear, concise answer from what you find. | ||
| 3. If the docs don't cover the topic, say so explicitly. |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing from the tool checklist: |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,71 @@ | ||||||||||||||
| # Copyright (C) 2026 Dirk Fauth and others. | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two things from the PR discussion are still unresolved: the OAuth token comes back overly broad in scope, and the browser OAuth flow can't be pinned to a fixed callback port (no enclave/extensions/tools/mistral-vibe/spec.yaml Lines 8 to 13 in 671cca2
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @xai To be honest I am not sure what to do here. Any hints or suggestions?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need |
||||||||||||||
| # | ||||||||||||||
| # This program and the accompanying materials are made available under the | ||||||||||||||
| # terms of the MIT License, which is available in the project root. | ||||||||||||||
| # | ||||||||||||||
| # SPDX-License-Identifier: MIT | ||||||||||||||
|
|
||||||||||||||
| schemaVersion: "1" | ||||||||||||||
| kind: sandbox | ||||||||||||||
| name: copilot | ||||||||||||||
| displayName: Copilot CLI | ||||||||||||||
| description: Copilot CLI | ||||||||||||||
|
|
||||||||||||||
| sandbox: | ||||||||||||||
| entrypoint: { run: [copilot, --disable-builtin-mcps, --disable-client-telemetry] } | ||||||||||||||
| configDir: .copilot | ||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When a user has a config override or patch in their enclave config for copilot, Enclave currently rebuilds the config directory on every start and keeps only declared state. Without this line, Copilot's conversation history and session database are deleted, so |
||||||||||||||
| statePaths: [ | ||||||||||||||
| config.json, | ||||||||||||||
| session-state/, | ||||||||||||||
| sidebar-sessions-state/, | ||||||||||||||
| command-history-state*, | ||||||||||||||
| session-store.db*, | ||||||||||||||
| permissions-config.json, | ||||||||||||||
| mcp-oauth-config/, | ||||||||||||||
| mcp-secrets/, | ||||||||||||||
| installed-plugins/, | ||||||||||||||
| plugin-data/ | ||||||||||||||
| ] | ||||||||||||||
| qemuMinMemoryMiB: 4096 | ||||||||||||||
| skillsDir: .copilot/skills | ||||||||||||||
| settingsFile: copilot-settings.json | ||||||||||||||
| settingsTarget: .copilot/settings.json | ||||||||||||||
| yoloFlag: --yolo | ||||||||||||||
| yoloEnabled: true | ||||||||||||||
| continueArgs: [--continue] | ||||||||||||||
| resumeArgs: [--resume] | ||||||||||||||
| passthroughPaths: [ | ||||||||||||||
| agents/, | ||||||||||||||
| copilot-instructions.md, | ||||||||||||||
| extensions/, | ||||||||||||||
| hooks/, | ||||||||||||||
| instructions/, | ||||||||||||||
| lsp-config.json, | ||||||||||||||
| mcp-config.json, | ||||||||||||||
| providers.json, | ||||||||||||||
| settings.json, | ||||||||||||||
| skills/] | ||||||||||||||
|
Comment on lines
+37
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: trailing whitespace on each of these lines, and most new files lack a final newline. A block list like pi/opencode use reads better here. |
||||||||||||||
|
|
||||||||||||||
| credentials: | ||||||||||||||
| sources: | ||||||||||||||
| copilot-github-token: | ||||||||||||||
| env: [COPILOT_GITHUB_TOKEN] | ||||||||||||||
| placeholder: | ||||||||||||||
| prefix: github_pat_ | ||||||||||||||
| random: { encoding: alphanumeric, length: 82 } | ||||||||||||||
|
|
||||||||||||||
| network: | ||||||||||||||
| serviceDomains: | ||||||||||||||
| api.github.com: copilot-github-token | ||||||||||||||
| "*.githubcopilot.com": copilot-github-token | ||||||||||||||
| serviceAuth: | ||||||||||||||
| copilot-github-token: { headerName: Authorization, valueFormat: "Bearer %s" } | ||||||||||||||
|
|
||||||||||||||
| providers: | ||||||||||||||
| - name: github | ||||||||||||||
| credentials: [copilot-github-token] | ||||||||||||||
| authFiles: [config.json] | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @xai Not sure what to do here. any hints or suggestions?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not auth only, this is the problem I mentioned in the above inline comment. In copilot, If we decide to break |
||||||||||||||
| authSession: | ||||||||||||||
| mode: any | ||||||||||||||
| checks: | ||||||||||||||
| - { file: config.json, type: file_exists } | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "remoteExport": false, | ||
| "autoUpdate": false, | ||
| "logLevel": "default", | ||
| "includeCoAuthoredBy": false, | ||
| "storeTokenPlaintext": false, | ||
| "model": "auto", | ||
| "memory": false | ||
| } | ||
|
Comment on lines
+1
to
+9
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copilot Memory stores memories/facts on GitHub's servers and serves them to every later session of that account: other projects, other enclave state roots, copilot outside Enclave, anything. In my test sessions, a prompt asking copilot to remember a word made the agent store it with user scope under --yolo without any notice, and every later project's session fetched it at start. That is also a nice way for agents in different projects and sessions to collaborate with each other by using the memory feature as a message board. I think the huggingface incident has shown us what can happen with this. So I would argue to disable copilot's memory feature by default. We could use { Here. Users who want the feature nevertheless can run /memory on in a session, and the setting then persists in that project's config store.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added that setting. As users are able to change this, it is a better default for enclave to disable memory. I extended the README to cover this aspect. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't mention the OAuth scope problem from the PR discussion: the device/browser login token comes back with
repo(read+write) andwrite:plugin_gateway_connections, way more than Copilot needs (see the finding). Worth telling users here to preferCOPILOT_GITHUB_TOKENwith a fine-grained PAT and flagging the OAuth risk explicitly, since that's the actual guidance that came out of testing this PR.