# GitHub Copilot

> Set up Comity for GitHub Copilot CLI, the Copilot cloud agent and VS Code with .github/hooks, .github/mcp.json and .vscode/mcp.json.

GitHub Copilot reads repository hooks from `.github/hooks/*.json`: Copilot CLI, the Copilot cloud agent and VS Code agent mode all load them. `comity init --tools copilot` writes one hooks file plus MCP config for Copilot CLI and VS Code.

## Set up

```sh
cd your-repo
comity init --tools copilot
git add .github/hooks/comity.json .github/mcp.json .vscode/mcp.json
git commit -m "Set up Comity for GitHub Copilot"
```

Then:

- **Copilot CLI**: run `comity login` once, then start `copilot` in the repo and confirm folder trust. Copilot CLI loads repository hooks and MCP servers only in trusted folders.
- **VS Code**: open `.vscode/mcp.json` and start the `comity` server.
- **Copilot cloud agent**: see [Cloud agent](#cloud-agent).

## What init writes

### `.github/hooks/comity.json`

Events use PascalCase names, so Copilot sends the VS Code–compatible payload (snake_case fields, Claude tool names such as `Bash` and `Edit`). Each handler has a POSIX `bash` command and a `powershell` variant for Windows. Shown for one event:

```json
{
  "version": 1,
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "command -v comity >/dev/null 2>&1 || exit 0; exec comity hook --tool copilot --event PreToolUse",
        "bash": "command -v comity >/dev/null 2>&1 || exit 0; exec comity hook --tool copilot --event PreToolUse",
        "powershell": "$c = Get-Command comity -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1; if (-not $c) { exit 0 }; & $c.Source hook --tool copilot --event PreToolUse",
        "timeout": 5,
        "matcher": "Bash|Edit|Write|bash|powershell|create|edit|str_replace_editor|apply_patch|run_in_terminal|create_file|replace_string_in_file|multi_replace_string_in_file|insert_edit_into_file"
      }
    ]
  }
}
```

| Event | Matcher | Timeout (s) |
|---|---|---|
| `SessionStart` | | 5 |
| `UserPromptSubmit` | | 5 |
| `PreToolUse` | shell and file-edit tools | 5 |
| `PostToolUse` | shell and file-edit tools | 10 |
| `Stop` | | 10 |
| `SessionEnd` | | 10 |

Copilot `preToolUse` command hooks fail closed: a crash or non-zero exit denies the tool call. Both command variants exit 0 when the CLI isn't installed, and `comity hook` always exits 0.

### `.github/mcp.json` (Copilot CLI)

```json
{
  "mcpServers": {
    "comity": { "type": "local", "command": "node", "args": ["-e", "<launcher>", "mcp"], "tools": ["*"] }
  }
}
```

### `.vscode/mcp.json` (VS Code)

```json
{
  "servers": {
    "comity": { "type": "stdio", "command": "node", "args": ["-e", "<launcher>", "mcp"] }
  }
}
```

Both start `comity mcp`, a local stdio bridge to the Comity server, through a short `node -e` launcher (`<launcher>` above) that finds `comity` on any OS. The files are identical for every teammate, whatever OS ran `comity init`, and Node must be on PATH. The bridge uses the login stored by `comity login` (or `COMITY_TOKEN`/`COMITY_SERVER` when set), so no token goes into the repo and nothing has to be exported or pasted. `comity doctor` warns about `comity mcp` or `cmd /c comity mcp` entries written by an earlier init, because each works on one OS only.

Other servers and inputs in these files are kept. Rerunning init replaces an older token-based `comity` entry and removes the `comity-token` prompt it added to `.vscode/mcp.json`.

## What your agent sees

- **Session start**: the briefing as `additionalContext`.
- **Before a shell command or file edit**: a block denies the call (`permissionDecision: "deny"`) with Comity's reason. The hook prints both Copilot's top-level fields and VS Code's `hookSpecificOutput`.
- **After a tool call**: new conflicts, messages and notices as `additionalContext`.
- **Prompts and pre-tool warnings**: Copilot ignores the output of prompt hooks, and `preToolUse` can't add context. These warnings are queued for the next tool result.

## Cloud agent

The cloud agent runs `.github/hooks/*.json` from the repository in its Linux sandbox. The `bash` command exits quietly unless `comity` is installed there. To coordinate cloud agent jobs:

1. Install the CLI in [`copilot-setup-steps.yml`](https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/customize-cloud-agent/customize-the-agent-environment) (`npm i -g https://api.comity.so/cli/comity-cli.tgz`).
2. Add `COMITY_TOKEN` as a secret in the repository's `copilot` environment.
3. Add the MCP server in the repository's **Settings → Copilot → Cloud agent → MCP configuration**. The cloud agent doesn't read `.github/mcp.json`, and MCP secrets must start with `COPILOT_MCP_`:

```json
{
  "mcpServers": {
    "comity": {
      "type": "http",
      "url": "https://api.comity.so/mcp",
      "headers": { "Authorization": "Bearer $COPILOT_MCP_COMITY_TOKEN" },
      "tools": ["*"]
    }
  }
}
```

Organization admins can also manage MCP servers for the cloud agent at the organization level.

Sessions report the `cloud` surface.

## Claude Code hooks in Copilot CLI

Copilot CLI also runs `.claude/settings.json` hooks. When the repo or `~/.copilot/hooks/` has a hooks file calling `comity hook`, the invocation from `.claude/settings.json` steps aside, so each event is evaluated once. Repos set up only for Claude Code keep working in Copilot CLI through that import.

## Verify

```sh
comity doctor
```

Expect `copilot hooks  all 6 events installed`, `copilot mcp  configured in …/.github/mcp.json` and `vscode mcp  configured in …/.vscode/mcp.json`. In Copilot CLI, `/mcp` should list `comity` as connected.

## Limits

- Prompt-time briefings arrive after the next tool call, because Copilot drops the output of prompt hooks.
- A command `preToolUse` hook that times out lets the tool call through.
- `.vscode/mcp.json` servers that use `${input:…}` aren't forwarded to Copilot CLI sessions started from VS Code. Those sessions use `.github/mcp.json`.
