Latest commit

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

copilot-proxy

Use your GitHub Copilot subscription as the backend for Claude Code.

A zero-dependency localhost proxy that translates the Anthropic Messages API into the OpenAI Chat Completions format used by GitHub Copilot's API. This lets you run claude (Claude Code CLI) powered entirely by your existing Copilot Business/Enterprise subscription — no separate Anthropic API key required.

┌────────────┐ Anthropic API ┌───────────────┐ OpenAI API ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ copilot-proxy │ ────────────────▶│ GitHub Copilot │
│ (CLI) │◀────────────────────── │ :4141 │◀──────────────── │ API │
└────────────┘ Anthropic SSE events └───────────────┘ OpenAI SSE └─────────────────┘

Features

  • Full API translation — Anthropic Messages API ↔ OpenAI Chat Completions, including streaming SSE
  • All Claude models — Opus 4.6, Sonnet 4.6, Haiku 4.5 (and 4.5 variants)
  • Tool use / function calling — Complete bidirectional translation of tool definitions and results
  • Streaming — Real-time SSE event translation (OpenAI data: → Anthropic event: format)
  • Multi-modal — Image content blocks translated to OpenAI image_url format
  • Zero dependencies — Pure Node.js stdlib (http, https, fs, os, path, child_process)
  • Auto-authentication — Discovers tokens from 5 sources with GitHub Device Flow fallback
  • Token refresh — Automatic retry on 401/403 with token cache invalidation

Quick Start

One-command install

git clone https://github.com/schwarztim/copilot-proxy.git ~/.copilot-proxy
ln -sf ~/.copilot-proxy/claude-copilot ~/.local/bin/claude-copilot

Then just run:

claude-copilot

The launcher handles everything: starts the proxy, seeds the required config, and launches Claude Code.

Manual setup

# 1. Start the proxy
node proxy.mjs
# 2. Point claude at itexport ANTHROPIC_BASE_URL=http://localhost:4141
export ANTHROPIC_API_KEY=sk-ant-copilot-proxy-not-a-real-key
claude

How It Works

Authentication Chain

The proxy discovers your GitHub Copilot token automatically, checking these sources in order:

PrioritySourceDescription
1COPILOT_GITHUB_TOKENEnvironment variable override
2OpenCode auth.json~/.local/share/opencode/auth.json
3macOS KeychainService: copilot-cli
4GitHub CLIgh auth token
5Legacy config~/.config/github-copilot/apps.json
6Device FlowInteractive GitHub OAuth (first-run only)

If no token is found, the proxy starts an interactive GitHub Device Flow to authenticate with the copilot scope.

Model Mapping

Claude Code sends model IDs with dashes (e.g., claude-sonnet-4-6). The Copilot API expects dots (e.g., claude-sonnet-4.6). The proxy handles this automatically, including stripping date suffixes and version tags.

Claude Code sendsCopilot receives
claude-sonnet-4-6claude-sonnet-4.6
claude-opus-4-6claude-opus-4.6
claude-haiku-4-5claude-haiku-4.5
claude-sonnet-4-5-20250929claude-sonnet-4.5
claude-opus-4-5-v1claude-opus-4.5

Non-Claude models (GPT, Gemini) are passed through unchanged.

API Translation

The proxy performs bidirectional translation between the two API formats:

Request (Anthropic → OpenAI)

  • System prompts → role: "system" messages
  • Content blocks → Concatenated text or multipart content
  • tool_use blocks → tool_calls array
  • tool_result blocks → role: "tool" messages
  • Image blocks → image_url with data URI
  • stop_sequencesstop
  • thinkingreasoning_effort

Response (OpenAI → Anthropic)

  • choices[0].message → Anthropic message envelope
  • finish_reason mapping: stopend_turn, lengthmax_tokens, tool_callstool_use
  • Token usage translation with cache token fields

Streaming (OpenAI SSE → Anthropic SSE)

  • message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop
  • delta.contenttext_delta events
  • delta.tool_callsinput_json_delta events with proper block lifecycle

Configuration

Environment VariableDefaultDescription
COPILOT_PROXY_PORT4141Port the proxy listens on
COPILOT_GITHUB_TOKENOverride the GitHub token
ANTHROPIC_BASE_URLSet by launcher; points claude at proxy
ANTHROPIC_API_KEYSet by launcher; sk-ant- prefixed key

Verbose logging

node proxy.mjs --verbose # or -v

Logs model routing, message counts, and token usage to stderr.

Architecture

proxy.mjs (804 lines, zero dependencies)
├── Token Management — Multi-source token discovery + caching
├── GitHub Device Flow — Interactive OAuth for first-run auth
├── Anthropic → OpenAI — Request translation (messages, tools, images)
├── OpenAI → Anthropic — Response translation (non-streaming)
├── Streaming Translator — SSE event-by-event conversion
├── HTTP Server — Routes: /v1/messages, /v1/models, /health
└── Helpers — Logging, JSON parsing
claude-copilot (launcher script)
├── Proxy Lifecycle — Auto-start with health check polling
├── Config Seeding — Onboarding wizard bypass for claude-cli
└── Exec — Replaces process with claude binary

Limitations

  • Copilot subscription required — You need GitHub Copilot Business or Enterprise
  • Rate limits — Subject to Copilot's rate limiting, not Anthropic's
  • Extended thinking — Mapped to reasoning_effort: "high" (not native thinking blocks)
  • Caching — Copilot doesn't support prompt caching; cache token fields are zeroed
  • Beta features — Anthropic beta headers are not forwarded

Troubleshooting

Proxy won't start

cat /tmp/copilot-proxy.log
# Check if port 4141 is in use
lsof -i :4141

Authentication issues

# Verify your token works
curl -s https://api.business.githubcopilot.com/models \
-H "Authorization: Bearer $(gh auth token)" \
-H "Copilot-Integration-Id: copilot-developer-cli"

Claude shows onboarding wizard

# The launcher seeds this automatically, but if needed manually:
claude-copilot --version # Triggers config seeding without starting interactive mode

Requirements

  • Node.js ≥ 18
  • GitHub Copilot Business or Enterprise subscription
  • Claude Code CLI (claude) installed

License

MIT

About

Zero-dependency proxy to run Claude Code via your GitHub Copilot subscription. Translates Anthropic Messages API ↔ OpenAI Chat Completions.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

copilot-proxy

Use your GitHub Copilot subscription as the backend for Claude Code.

A zero-dependency localhost proxy that translates the Anthropic Messages API into the OpenAI Chat Completions format used by GitHub Copilot's API. This lets you run claude (Claude Code CLI) powered entirely by your existing Copilot Business/Enterprise subscription — no separate Anthropic API key required.

┌────────────┐ Anthropic API ┌───────────────┐ OpenAI API ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ copilot-proxy │ ────────────────▶│ GitHub Copilot │
│ (CLI) │◀────────────────────── │ :4141 │◀──────────────── │ API │
└────────────┘ Anthropic SSE events └───────────────┘ OpenAI SSE └─────────────────┘

Features

  • Full API translation — Anthropic Messages API ↔ OpenAI Chat Completions, including streaming SSE
  • All Claude models — Opus 4.6, Sonnet 4.6, Haiku 4.5 (and 4.5 variants)
  • Tool use / function calling — Complete bidirectional translation of tool definitions and results
  • Streaming — Real-time SSE event translation (OpenAI data: → Anthropic event: format)
  • Multi-modal — Image content blocks translated to OpenAI image_url format
  • Zero dependencies — Pure Node.js stdlib (http, https, fs, os, path, child_process)
  • Auto-authentication — Discovers tokens from 5 sources with GitHub Device Flow fallback
  • Token refresh — Automatic retry on 401/403 with token cache invalidation

Quick Start

One-command install

git clone https://github.com/schwarztim/copilot-proxy.git ~/.copilot-proxy
ln -sf ~/.copilot-proxy/claude-copilot ~/.local/bin/claude-copilot

Then just run:

claude-copilot

The launcher handles everything: starts the proxy, seeds the required config, and launches Claude Code.

Manual setup

# 1. Start the proxy
node proxy.mjs
# 2. Point claude at itexport ANTHROPIC_BASE_URL=http://localhost:4141
export ANTHROPIC_API_KEY=sk-ant-copilot-proxy-not-a-real-key
claude

How It Works

Authentication Chain

The proxy discovers your GitHub Copilot token automatically, checking these sources in order:

PrioritySourceDescription
1COPILOT_GITHUB_TOKENEnvironment variable override
2OpenCode auth.json~/.local/share/opencode/auth.json
3macOS KeychainService: copilot-cli
4GitHub CLIgh auth token
5Legacy config~/.config/github-copilot/apps.json
6Device FlowInteractive GitHub OAuth (first-run only)

If no token is found, the proxy starts an interactive GitHub Device Flow to authenticate with the copilot scope.

Model Mapping

Claude Code sends model IDs with dashes (e.g., claude-sonnet-4-6). The Copilot API expects dots (e.g., claude-sonnet-4.6). The proxy handles this automatically, including stripping date suffixes and version tags.

Claude Code sendsCopilot receives
claude-sonnet-4-6claude-sonnet-4.6
claude-opus-4-6claude-opus-4.6
claude-haiku-4-5claude-haiku-4.5
claude-sonnet-4-5-20250929claude-sonnet-4.5
claude-opus-4-5-v1claude-opus-4.5

Non-Claude models (GPT, Gemini) are passed through unchanged.

API Translation

The proxy performs bidirectional translation between the two API formats:

Request (Anthropic → OpenAI)

  • System prompts → role: "system" messages
  • Content blocks → Concatenated text or multipart content
  • tool_use blocks → tool_calls array
  • tool_result blocks → role: "tool" messages
  • Image blocks → image_url with data URI
  • stop_sequencesstop
  • thinkingreasoning_effort

Response (OpenAI → Anthropic)

  • choices[0].message → Anthropic message envelope
  • finish_reason mapping: stopend_turn, lengthmax_tokens, tool_callstool_use
  • Token usage translation with cache token fields

Streaming (OpenAI SSE → Anthropic SSE)

  • message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop
  • delta.contenttext_delta events
  • delta.tool_callsinput_json_delta events with proper block lifecycle

Configuration

Environment VariableDefaultDescription
COPILOT_PROXY_PORT4141Port the proxy listens on
COPILOT_GITHUB_TOKENOverride the GitHub token
ANTHROPIC_BASE_URLSet by launcher; points claude at proxy
ANTHROPIC_API_KEYSet by launcher; sk-ant- prefixed key

Verbose logging

node proxy.mjs --verbose # or -v

Logs model routing, message counts, and token usage to stderr.

Architecture

proxy.mjs (804 lines, zero dependencies)
├── Token Management — Multi-source token discovery + caching
├── GitHub Device Flow — Interactive OAuth for first-run auth
├── Anthropic → OpenAI — Request translation (messages, tools, images)
├── OpenAI → Anthropic — Response translation (non-streaming)
├── Streaming Translator — SSE event-by-event conversion
├── HTTP Server — Routes: /v1/messages, /v1/models, /health
└── Helpers — Logging, JSON parsing
claude-copilot (launcher script)
├── Proxy Lifecycle — Auto-start with health check polling
├── Config Seeding — Onboarding wizard bypass for claude-cli
└── Exec — Replaces process with claude binary

Limitations

  • Copilot subscription required — You need GitHub Copilot Business or Enterprise
  • Rate limits — Subject to Copilot's rate limiting, not Anthropic's
  • Extended thinking — Mapped to reasoning_effort: "high" (not native thinking blocks)
  • Caching — Copilot doesn't support prompt caching; cache token fields are zeroed
  • Beta features — Anthropic beta headers are not forwarded

Troubleshooting

Proxy won't start

cat /tmp/copilot-proxy.log
# Check if port 4141 is in use
lsof -i :4141

Authentication issues

# Verify your token works
curl -s https://api.business.githubcopilot.com/models \
-H "Authorization: Bearer $(gh auth token)" \
-H "Copilot-Integration-Id: copilot-developer-cli"

Claude shows onboarding wizard

# The launcher seeds this automatically, but if needed manually:
claude-copilot --version # Triggers config seeding without starting interactive mode

Requirements

  • Node.js ≥ 18
  • GitHub Copilot Business or Enterprise subscription
  • Claude Code CLI (claude) installed

License

MIT

About

Zero-dependency proxy to run Claude Code via your GitHub Copilot subscription. Translates Anthropic Messages API ↔ OpenAI Chat Completions.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

copilot-proxy

Use your GitHub Copilot subscription as the backend for Claude Code.

A zero-dependency localhost proxy that translates the Anthropic Messages API into the OpenAI Chat Completions format used by GitHub Copilot's API. This lets you run claude (Claude Code CLI) powered entirely by your existing Copilot Business/Enterprise subscription — no separate Anthropic API key required.

┌────────────┐ Anthropic API ┌───────────────┐ OpenAI API ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ copilot-proxy │ ────────────────▶│ GitHub Copilot │
│ (CLI) │◀────────────────────── │ :4141 │◀──────────────── │ API │
└────────────┘ Anthropic SSE events └───────────────┘ OpenAI SSE └─────────────────┘

Features

  • Full API translation — Anthropic Messages API ↔ OpenAI Chat Completions, including streaming SSE
  • All Claude models — Opus 4.6, Sonnet 4.6, Haiku 4.5 (and 4.5 variants)
  • Tool use / function calling — Complete bidirectional translation of tool definitions and results
  • Streaming — Real-time SSE event translation (OpenAI data: → Anthropic event: format)
  • Multi-modal — Image content blocks translated to OpenAI image_url format
  • Zero dependencies — Pure Node.js stdlib (http, https, fs, os, path, child_process)
  • Auto-authentication — Discovers tokens from 5 sources with GitHub Device Flow fallback
  • Token refresh — Automatic retry on 401/403 with token cache invalidation

Quick Start

One-command install

git clone https://github.com/schwarztim/copilot-proxy.git ~/.copilot-proxy
ln -sf ~/.copilot-proxy/claude-copilot ~/.local/bin/claude-copilot

Then just run:

claude-copilot

The launcher handles everything: starts the proxy, seeds the required config, and launches Claude Code.

Manual setup

# 1. Start the proxy
node proxy.mjs
# 2. Point claude at itexport ANTHROPIC_BASE_URL=http://localhost:4141
export ANTHROPIC_API_KEY=sk-ant-copilot-proxy-not-a-real-key
claude

How It Works

Authentication Chain

The proxy discovers your GitHub Copilot token automatically, checking these sources in order:

PrioritySourceDescription
1COPILOT_GITHUB_TOKENEnvironment variable override
2OpenCode auth.json~/.local/share/opencode/auth.json
3macOS KeychainService: copilot-cli
4GitHub CLIgh auth token
5Legacy config~/.config/github-copilot/apps.json
6Device FlowInteractive GitHub OAuth (first-run only)

If no token is found, the proxy starts an interactive GitHub Device Flow to authenticate with the copilot scope.

Model Mapping

Claude Code sends model IDs with dashes (e.g., claude-sonnet-4-6). The Copilot API expects dots (e.g., claude-sonnet-4.6). The proxy handles this automatically, including stripping date suffixes and version tags.

Claude Code sendsCopilot receives
claude-sonnet-4-6claude-sonnet-4.6
claude-opus-4-6claude-opus-4.6
claude-haiku-4-5claude-haiku-4.5
claude-sonnet-4-5-20250929claude-sonnet-4.5
claude-opus-4-5-v1claude-opus-4.5

Non-Claude models (GPT, Gemini) are passed through unchanged.

API Translation

The proxy performs bidirectional translation between the two API formats:

Request (Anthropic → OpenAI)

  • System prompts → role: "system" messages
  • Content blocks → Concatenated text or multipart content
  • tool_use blocks → tool_calls array
  • tool_result blocks → role: "tool" messages
  • Image blocks → image_url with data URI
  • stop_sequencesstop
  • thinkingreasoning_effort

Response (OpenAI → Anthropic)

  • choices[0].message → Anthropic message envelope
  • finish_reason mapping: stopend_turn, lengthmax_tokens, tool_callstool_use
  • Token usage translation with cache token fields

Streaming (OpenAI SSE → Anthropic SSE)

  • message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop
  • delta.contenttext_delta events
  • delta.tool_callsinput_json_delta events with proper block lifecycle

Configuration

Environment VariableDefaultDescription
COPILOT_PROXY_PORT4141Port the proxy listens on
COPILOT_GITHUB_TOKENOverride the GitHub token
ANTHROPIC_BASE_URLSet by launcher; points claude at proxy
ANTHROPIC_API_KEYSet by launcher; sk-ant- prefixed key

Verbose logging

node proxy.mjs --verbose # or -v

Logs model routing, message counts, and token usage to stderr.

Architecture

proxy.mjs (804 lines, zero dependencies)
├── Token Management — Multi-source token discovery + caching
├── GitHub Device Flow — Interactive OAuth for first-run auth
├── Anthropic → OpenAI — Request translation (messages, tools, images)
├── OpenAI → Anthropic — Response translation (non-streaming)
├── Streaming Translator — SSE event-by-event conversion
├── HTTP Server — Routes: /v1/messages, /v1/models, /health
└── Helpers — Logging, JSON parsing
claude-copilot (launcher script)
├── Proxy Lifecycle — Auto-start with health check polling
├── Config Seeding — Onboarding wizard bypass for claude-cli
└── Exec — Replaces process with claude binary

Limitations

  • Copilot subscription required — You need GitHub Copilot Business or Enterprise
  • Rate limits — Subject to Copilot's rate limiting, not Anthropic's
  • Extended thinking — Mapped to reasoning_effort: "high" (not native thinking blocks)
  • Caching — Copilot doesn't support prompt caching; cache token fields are zeroed
  • Beta features — Anthropic beta headers are not forwarded

Troubleshooting

Proxy won't start

cat /tmp/copilot-proxy.log
# Check if port 4141 is in use
lsof -i :4141

Authentication issues

# Verify your token works
curl -s https://api.business.githubcopilot.com/models \
-H "Authorization: Bearer $(gh auth token)" \
-H "Copilot-Integration-Id: copilot-developer-cli"

Claude shows onboarding wizard

# The launcher seeds this automatically, but if needed manually:
claude-copilot --version # Triggers config seeding without starting interactive mode

Requirements

  • Node.js ≥ 18
  • GitHub Copilot Business or Enterprise subscription
  • Claude Code CLI (claude) installed

License

MIT

About

Zero-dependency proxy to run Claude Code via your GitHub Copilot subscription. Translates Anthropic Messages API ↔ OpenAI Chat Completions.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

copilot-proxy

Use your GitHub Copilot subscription as the backend for Claude Code.

A zero-dependency localhost proxy that translates the Anthropic Messages API into the OpenAI Chat Completions format used by GitHub Copilot's API. This lets you run claude (Claude Code CLI) powered entirely by your existing Copilot Business/Enterprise subscription — no separate Anthropic API key required.

┌────────────┐ Anthropic API ┌───────────────┐ OpenAI API ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ copilot-proxy │ ────────────────▶│ GitHub Copilot │
│ (CLI) │◀────────────────────── │ :4141 │◀──────────────── │ API │
└────────────┘ Anthropic SSE events └───────────────┘ OpenAI SSE └─────────────────┘

Features

  • Full API translation — Anthropic Messages API ↔ OpenAI Chat Completions, including streaming SSE
  • All Claude models — Opus 4.6, Sonnet 4.6, Haiku 4.5 (and 4.5 variants)
  • Tool use / function calling — Complete bidirectional translation of tool definitions and results
  • Streaming — Real-time SSE event translation (OpenAI data: → Anthropic event: format)
  • Multi-modal — Image content blocks translated to OpenAI image_url format
  • Zero dependencies — Pure Node.js stdlib (http, https, fs, os, path, child_process)
  • Auto-authentication — Discovers tokens from 5 sources with GitHub Device Flow fallback
  • Token refresh — Automatic retry on 401/403 with token cache invalidation

Quick Start

One-command install

git clone https://github.com/schwarztim/copilot-proxy.git ~/.copilot-proxy
ln -sf ~/.copilot-proxy/claude-copilot ~/.local/bin/claude-copilot

Then just run:

claude-copilot

The launcher handles everything: starts the proxy, seeds the required config, and launches Claude Code.

Manual setup

# 1. Start the proxy
node proxy.mjs
# 2. Point claude at itexport ANTHROPIC_BASE_URL=http://localhost:4141
export ANTHROPIC_API_KEY=sk-ant-copilot-proxy-not-a-real-key
claude

How It Works

Authentication Chain

The proxy discovers your GitHub Copilot token automatically, checking these sources in order:

PrioritySourceDescription
1COPILOT_GITHUB_TOKENEnvironment variable override
2OpenCode auth.json~/.local/share/opencode/auth.json
3macOS KeychainService: copilot-cli
4GitHub CLIgh auth token
5Legacy config~/.config/github-copilot/apps.json
6Device FlowInteractive GitHub OAuth (first-run only)

If no token is found, the proxy starts an interactive GitHub Device Flow to authenticate with the copilot scope.

Model Mapping

Claude Code sends model IDs with dashes (e.g., claude-sonnet-4-6). The Copilot API expects dots (e.g., claude-sonnet-4.6). The proxy handles this automatically, including stripping date suffixes and version tags.

Claude Code sendsCopilot receives
claude-sonnet-4-6claude-sonnet-4.6
claude-opus-4-6claude-opus-4.6
claude-haiku-4-5claude-haiku-4.5
claude-sonnet-4-5-20250929claude-sonnet-4.5
claude-opus-4-5-v1claude-opus-4.5

Non-Claude models (GPT, Gemini) are passed through unchanged.

API Translation

The proxy performs bidirectional translation between the two API formats:

Request (Anthropic → OpenAI)

  • System prompts → role: "system" messages
  • Content blocks → Concatenated text or multipart content
  • tool_use blocks → tool_calls array
  • tool_result blocks → role: "tool" messages
  • Image blocks → image_url with data URI
  • stop_sequencesstop
  • thinkingreasoning_effort

Response (OpenAI → Anthropic)

  • choices[0].message → Anthropic message envelope
  • finish_reason mapping: stopend_turn, lengthmax_tokens, tool_callstool_use
  • Token usage translation with cache token fields

Streaming (OpenAI SSE → Anthropic SSE)

  • message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop
  • delta.contenttext_delta events
  • delta.tool_callsinput_json_delta events with proper block lifecycle

Configuration

Environment VariableDefaultDescription
COPILOT_PROXY_PORT4141Port the proxy listens on
COPILOT_GITHUB_TOKENOverride the GitHub token
ANTHROPIC_BASE_URLSet by launcher; points claude at proxy
ANTHROPIC_API_KEYSet by launcher; sk-ant- prefixed key

Verbose logging

node proxy.mjs --verbose # or -v

Logs model routing, message counts, and token usage to stderr.

Architecture

proxy.mjs (804 lines, zero dependencies)
├── Token Management — Multi-source token discovery + caching
├── GitHub Device Flow — Interactive OAuth for first-run auth
├── Anthropic → OpenAI — Request translation (messages, tools, images)
├── OpenAI → Anthropic — Response translation (non-streaming)
├── Streaming Translator — SSE event-by-event conversion
├── HTTP Server — Routes: /v1/messages, /v1/models, /health
└── Helpers — Logging, JSON parsing
claude-copilot (launcher script)
├── Proxy Lifecycle — Auto-start with health check polling
├── Config Seeding — Onboarding wizard bypass for claude-cli
└── Exec — Replaces process with claude binary

Limitations

  • Copilot subscription required — You need GitHub Copilot Business or Enterprise
  • Rate limits — Subject to Copilot's rate limiting, not Anthropic's
  • Extended thinking — Mapped to reasoning_effort: "high" (not native thinking blocks)
  • Caching — Copilot doesn't support prompt caching; cache token fields are zeroed
  • Beta features — Anthropic beta headers are not forwarded

Troubleshooting

Proxy won't start

cat /tmp/copilot-proxy.log
# Check if port 4141 is in use
lsof -i :4141

Authentication issues

# Verify your token works
curl -s https://api.business.githubcopilot.com/models \
-H "Authorization: Bearer $(gh auth token)" \
-H "Copilot-Integration-Id: copilot-developer-cli"

Claude shows onboarding wizard

# The launcher seeds this automatically, but if needed manually:
claude-copilot --version # Triggers config seeding without starting interactive mode

Requirements

  • Node.js ≥ 18
  • GitHub Copilot Business or Enterprise subscription
  • Claude Code CLI (claude) installed

License

MIT

About

Zero-dependency proxy to run Claude Code via your GitHub Copilot subscription. Translates Anthropic Messages API ↔ OpenAI Chat Completions.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

copilot-proxy

Use your GitHub Copilot subscription as the backend for Claude Code.

A zero-dependency localhost proxy that translates the Anthropic Messages API into the OpenAI Chat Completions format used by GitHub Copilot's API. This lets you run claude (Claude Code CLI) powered entirely by your existing Copilot Business/Enterprise subscription — no separate Anthropic API key required.

┌────────────┐ Anthropic API ┌───────────────┐ OpenAI API ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ copilot-proxy │ ────────────────▶│ GitHub Copilot │
│ (CLI) │◀────────────────────── │ :4141 │◀──────────────── │ API │
└────────────┘ Anthropic SSE events └───────────────┘ OpenAI SSE └─────────────────┘

Features

  • Full API translation — Anthropic Messages API ↔ OpenAI Chat Completions, including streaming SSE
  • All Claude models — Opus 4.6, Sonnet 4.6, Haiku 4.5 (and 4.5 variants)
  • Tool use / function calling — Complete bidirectional translation of tool definitions and results
  • Streaming — Real-time SSE event translation (OpenAI data: → Anthropic event: format)
  • Multi-modal — Image content blocks translated to OpenAI image_url format
  • Zero dependencies — Pure Node.js stdlib (http, https, fs, os, path, child_process)
  • Auto-authentication — Discovers tokens from 5 sources with GitHub Device Flow fallback
  • Token refresh — Automatic retry on 401/403 with token cache invalidation

Quick Start

One-command install

git clone https://github.com/schwarztim/copilot-proxy.git ~/.copilot-proxy
ln -sf ~/.copilot-proxy/claude-copilot ~/.local/bin/claude-copilot

Then just run:

claude-copilot

The launcher handles everything: starts the proxy, seeds the required config, and launches Claude Code.

Manual setup

# 1. Start the proxy
node proxy.mjs
# 2. Point claude at itexport ANTHROPIC_BASE_URL=http://localhost:4141
export ANTHROPIC_API_KEY=sk-ant-copilot-proxy-not-a-real-key
claude

How It Works

Authentication Chain

The proxy discovers your GitHub Copilot token automatically, checking these sources in order:

PrioritySourceDescription
1COPILOT_GITHUB_TOKENEnvironment variable override
2OpenCode auth.json~/.local/share/opencode/auth.json
3macOS KeychainService: copilot-cli
4GitHub CLIgh auth token
5Legacy config~/.config/github-copilot/apps.json
6Device FlowInteractive GitHub OAuth (first-run only)

If no token is found, the proxy starts an interactive GitHub Device Flow to authenticate with the copilot scope.

Model Mapping

Claude Code sends model IDs with dashes (e.g., claude-sonnet-4-6). The Copilot API expects dots (e.g., claude-sonnet-4.6). The proxy handles this automatically, including stripping date suffixes and version tags.

Claude Code sendsCopilot receives
claude-sonnet-4-6claude-sonnet-4.6
claude-opus-4-6claude-opus-4.6
claude-haiku-4-5claude-haiku-4.5
claude-sonnet-4-5-20250929claude-sonnet-4.5
claude-opus-4-5-v1claude-opus-4.5

Non-Claude models (GPT, Gemini) are passed through unchanged.

API Translation

The proxy performs bidirectional translation between the two API formats:

Request (Anthropic → OpenAI)

  • System prompts → role: "system" messages
  • Content blocks → Concatenated text or multipart content
  • tool_use blocks → tool_calls array
  • tool_result blocks → role: "tool" messages
  • Image blocks → image_url with data URI
  • stop_sequencesstop
  • thinkingreasoning_effort

Response (OpenAI → Anthropic)

  • choices[0].message → Anthropic message envelope
  • finish_reason mapping: stopend_turn, lengthmax_tokens, tool_callstool_use
  • Token usage translation with cache token fields

Streaming (OpenAI SSE → Anthropic SSE)

  • message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop
  • delta.contenttext_delta events
  • delta.tool_callsinput_json_delta events with proper block lifecycle

Configuration

Environment VariableDefaultDescription
COPILOT_PROXY_PORT4141Port the proxy listens on
COPILOT_GITHUB_TOKENOverride the GitHub token
ANTHROPIC_BASE_URLSet by launcher; points claude at proxy
ANTHROPIC_API_KEYSet by launcher; sk-ant- prefixed key

Verbose logging

node proxy.mjs --verbose # or -v

Logs model routing, message counts, and token usage to stderr.

Architecture

proxy.mjs (804 lines, zero dependencies)
├── Token Management — Multi-source token discovery + caching
├── GitHub Device Flow — Interactive OAuth for first-run auth
├── Anthropic → OpenAI — Request translation (messages, tools, images)
├── OpenAI → Anthropic — Response translation (non-streaming)
├── Streaming Translator — SSE event-by-event conversion
├── HTTP Server — Routes: /v1/messages, /v1/models, /health
└── Helpers — Logging, JSON parsing
claude-copilot (launcher script)
├── Proxy Lifecycle — Auto-start with health check polling
├── Config Seeding — Onboarding wizard bypass for claude-cli
└── Exec — Replaces process with claude binary

Limitations

  • Copilot subscription required — You need GitHub Copilot Business or Enterprise
  • Rate limits — Subject to Copilot's rate limiting, not Anthropic's
  • Extended thinking — Mapped to reasoning_effort: "high" (not native thinking blocks)
  • Caching — Copilot doesn't support prompt caching; cache token fields are zeroed
  • Beta features — Anthropic beta headers are not forwarded

Troubleshooting

Proxy won't start

cat /tmp/copilot-proxy.log
# Check if port 4141 is in use
lsof -i :4141

Authentication issues

# Verify your token works
curl -s https://api.business.githubcopilot.com/models \
-H "Authorization: Bearer $(gh auth token)" \
-H "Copilot-Integration-Id: copilot-developer-cli"

Claude shows onboarding wizard

# The launcher seeds this automatically, but if needed manually:
claude-copilot --version # Triggers config seeding without starting interactive mode

Requirements

  • Node.js ≥ 18
  • GitHub Copilot Business or Enterprise subscription
  • Claude Code CLI (claude) installed

License

MIT

About

Zero-dependency proxy to run Claude Code via your GitHub Copilot subscription. Translates Anthropic Messages API ↔ OpenAI Chat Completions.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

copilot-proxy

Use your GitHub Copilot subscription as the backend for Claude Code.

A zero-dependency localhost proxy that translates the Anthropic Messages API into the OpenAI Chat Completions format used by GitHub Copilot's API. This lets you run claude (Claude Code CLI) powered entirely by your existing Copilot Business/Enterprise subscription — no separate Anthropic API key required.

┌────────────┐ Anthropic API ┌───────────────┐ OpenAI API ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ copilot-proxy │ ────────────────▶│ GitHub Copilot │
│ (CLI) │◀────────────────────── │ :4141 │◀──────────────── │ API │
└────────────┘ Anthropic SSE events └───────────────┘ OpenAI SSE └─────────────────┘

Features

  • Full API translation — Anthropic Messages API ↔ OpenAI Chat Completions, including streaming SSE
  • All Claude models — Opus 4.6, Sonnet 4.6, Haiku 4.5 (and 4.5 variants)
  • Tool use / function calling — Complete bidirectional translation of tool definitions and results
  • Streaming — Real-time SSE event translation (OpenAI data: → Anthropic event: format)
  • Multi-modal — Image content blocks translated to OpenAI image_url format
  • Zero dependencies — Pure Node.js stdlib (http, https, fs, os, path, child_process)
  • Auto-authentication — Discovers tokens from 5 sources with GitHub Device Flow fallback
  • Token refresh — Automatic retry on 401/403 with token cache invalidation

Quick Start

One-command install

git clone https://github.com/schwarztim/copilot-proxy.git ~/.copilot-proxy
ln -sf ~/.copilot-proxy/claude-copilot ~/.local/bin/claude-copilot

Then just run:

claude-copilot

The launcher handles everything: starts the proxy, seeds the required config, and launches Claude Code.

Manual setup

# 1. Start the proxy
node proxy.mjs
# 2. Point claude at itexport ANTHROPIC_BASE_URL=http://localhost:4141
export ANTHROPIC_API_KEY=sk-ant-copilot-proxy-not-a-real-key
claude

How It Works

Authentication Chain

The proxy discovers your GitHub Copilot token automatically, checking these sources in order:

PrioritySourceDescription
1COPILOT_GITHUB_TOKENEnvironment variable override
2OpenCode auth.json~/.local/share/opencode/auth.json
3macOS KeychainService: copilot-cli
4GitHub CLIgh auth token
5Legacy config~/.config/github-copilot/apps.json
6Device FlowInteractive GitHub OAuth (first-run only)

If no token is found, the proxy starts an interactive GitHub Device Flow to authenticate with the copilot scope.

Model Mapping

Claude Code sends model IDs with dashes (e.g., claude-sonnet-4-6). The Copilot API expects dots (e.g., claude-sonnet-4.6). The proxy handles this automatically, including stripping date suffixes and version tags.

Claude Code sendsCopilot receives
claude-sonnet-4-6claude-sonnet-4.6
claude-opus-4-6claude-opus-4.6
claude-haiku-4-5claude-haiku-4.5
claude-sonnet-4-5-20250929claude-sonnet-4.5
claude-opus-4-5-v1claude-opus-4.5

Non-Claude models (GPT, Gemini) are passed through unchanged.

API Translation

The proxy performs bidirectional translation between the two API formats:

Request (Anthropic → OpenAI)

  • System prompts → role: "system" messages
  • Content blocks → Concatenated text or multipart content
  • tool_use blocks → tool_calls array
  • tool_result blocks → role: "tool" messages
  • Image blocks → image_url with data URI
  • stop_sequencesstop
  • thinkingreasoning_effort

Response (OpenAI → Anthropic)

  • choices[0].message → Anthropic message envelope
  • finish_reason mapping: stopend_turn, lengthmax_tokens, tool_callstool_use
  • Token usage translation with cache token fields

Streaming (OpenAI SSE → Anthropic SSE)

  • message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop
  • delta.contenttext_delta events
  • delta.tool_callsinput_json_delta events with proper block lifecycle

Configuration

Environment VariableDefaultDescription
COPILOT_PROXY_PORT4141Port the proxy listens on
COPILOT_GITHUB_TOKENOverride the GitHub token
ANTHROPIC_BASE_URLSet by launcher; points claude at proxy
ANTHROPIC_API_KEYSet by launcher; sk-ant- prefixed key

Verbose logging

node proxy.mjs --verbose # or -v

Logs model routing, message counts, and token usage to stderr.

Architecture

proxy.mjs (804 lines, zero dependencies)
├── Token Management — Multi-source token discovery + caching
├── GitHub Device Flow — Interactive OAuth for first-run auth
├── Anthropic → OpenAI — Request translation (messages, tools, images)
├── OpenAI → Anthropic — Response translation (non-streaming)
├── Streaming Translator — SSE event-by-event conversion
├── HTTP Server — Routes: /v1/messages, /v1/models, /health
└── Helpers — Logging, JSON parsing
claude-copilot (launcher script)
├── Proxy Lifecycle — Auto-start with health check polling
├── Config Seeding — Onboarding wizard bypass for claude-cli
└── Exec — Replaces process with claude binary

Limitations

  • Copilot subscription required — You need GitHub Copilot Business or Enterprise
  • Rate limits — Subject to Copilot's rate limiting, not Anthropic's
  • Extended thinking — Mapped to reasoning_effort: "high" (not native thinking blocks)
  • Caching — Copilot doesn't support prompt caching; cache token fields are zeroed
  • Beta features — Anthropic beta headers are not forwarded

Troubleshooting

Proxy won't start

cat /tmp/copilot-proxy.log
# Check if port 4141 is in use
lsof -i :4141

Authentication issues

# Verify your token works
curl -s https://api.business.githubcopilot.com/models \
-H "Authorization: Bearer $(gh auth token)" \
-H "Copilot-Integration-Id: copilot-developer-cli"

Claude shows onboarding wizard

# The launcher seeds this automatically, but if needed manually:
claude-copilot --version # Triggers config seeding without starting interactive mode

Requirements

  • Node.js ≥ 18
  • GitHub Copilot Business or Enterprise subscription
  • Claude Code CLI (claude) installed

License

MIT

About

Zero-dependency proxy to run Claude Code via your GitHub Copilot subscription. Translates Anthropic Messages API ↔ OpenAI Chat Completions.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

copilot-proxy

Use your GitHub Copilot subscription as the backend for Claude Code.

A zero-dependency localhost proxy that translates the Anthropic Messages API into the OpenAI Chat Completions format used by GitHub Copilot's API. This lets you run claude (Claude Code CLI) powered entirely by your existing Copilot Business/Enterprise subscription — no separate Anthropic API key required.

┌────────────┐ Anthropic API ┌───────────────┐ OpenAI API ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ copilot-proxy │ ────────────────▶│ GitHub Copilot │
│ (CLI) │◀────────────────────── │ :4141 │◀──────────────── │ API │
└────────────┘ Anthropic SSE events └───────────────┘ OpenAI SSE └─────────────────┘

Features

  • Full API translation — Anthropic Messages API ↔ OpenAI Chat Completions, including streaming SSE
  • All Claude models — Opus 4.6, Sonnet 4.6, Haiku 4.5 (and 4.5 variants)
  • Tool use / function calling — Complete bidirectional translation of tool definitions and results
  • Streaming — Real-time SSE event translation (OpenAI data: → Anthropic event: format)
  • Multi-modal — Image content blocks translated to OpenAI image_url format
  • Zero dependencies — Pure Node.js stdlib (http, https, fs, os, path, child_process)
  • Auto-authentication — Discovers tokens from 5 sources with GitHub Device Flow fallback
  • Token refresh — Automatic retry on 401/403 with token cache invalidation

Quick Start

One-command install

git clone https://github.com/schwarztim/copilot-proxy.git ~/.copilot-proxy
ln -sf ~/.copilot-proxy/claude-copilot ~/.local/bin/claude-copilot

Then just run:

claude-copilot

The launcher handles everything: starts the proxy, seeds the required config, and launches Claude Code.

Manual setup

# 1. Start the proxy
node proxy.mjs
# 2. Point claude at itexport ANTHROPIC_BASE_URL=http://localhost:4141
export ANTHROPIC_API_KEY=sk-ant-copilot-proxy-not-a-real-key
claude

How It Works

Authentication Chain

The proxy discovers your GitHub Copilot token automatically, checking these sources in order:

PrioritySourceDescription
1COPILOT_GITHUB_TOKENEnvironment variable override
2OpenCode auth.json~/.local/share/opencode/auth.json
3macOS KeychainService: copilot-cli
4GitHub CLIgh auth token
5Legacy config~/.config/github-copilot/apps.json
6Device FlowInteractive GitHub OAuth (first-run only)

If no token is found, the proxy starts an interactive GitHub Device Flow to authenticate with the copilot scope.

Model Mapping

Claude Code sends model IDs with dashes (e.g., claude-sonnet-4-6). The Copilot API expects dots (e.g., claude-sonnet-4.6). The proxy handles this automatically, including stripping date suffixes and version tags.

Claude Code sendsCopilot receives
claude-sonnet-4-6claude-sonnet-4.6
claude-opus-4-6claude-opus-4.6
claude-haiku-4-5claude-haiku-4.5
claude-sonnet-4-5-20250929claude-sonnet-4.5
claude-opus-4-5-v1claude-opus-4.5

Non-Claude models (GPT, Gemini) are passed through unchanged.

API Translation

The proxy performs bidirectional translation between the two API formats:

Request (Anthropic → OpenAI)

  • System prompts → role: "system" messages
  • Content blocks → Concatenated text or multipart content
  • tool_use blocks → tool_calls array
  • tool_result blocks → role: "tool" messages
  • Image blocks → image_url with data URI
  • stop_sequencesstop
  • thinkingreasoning_effort

Response (OpenAI → Anthropic)

  • choices[0].message → Anthropic message envelope
  • finish_reason mapping: stopend_turn, lengthmax_tokens, tool_callstool_use
  • Token usage translation with cache token fields

Streaming (OpenAI SSE → Anthropic SSE)

  • message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop
  • delta.contenttext_delta events
  • delta.tool_callsinput_json_delta events with proper block lifecycle

Configuration

Environment VariableDefaultDescription
COPILOT_PROXY_PORT4141Port the proxy listens on
COPILOT_GITHUB_TOKENOverride the GitHub token
ANTHROPIC_BASE_URLSet by launcher; points claude at proxy
ANTHROPIC_API_KEYSet by launcher; sk-ant- prefixed key

Verbose logging

node proxy.mjs --verbose # or -v

Logs model routing, message counts, and token usage to stderr.

Architecture

proxy.mjs (804 lines, zero dependencies)
├── Token Management — Multi-source token discovery + caching
├── GitHub Device Flow — Interactive OAuth for first-run auth
├── Anthropic → OpenAI — Request translation (messages, tools, images)
├── OpenAI → Anthropic — Response translation (non-streaming)
├── Streaming Translator — SSE event-by-event conversion
├── HTTP Server — Routes: /v1/messages, /v1/models, /health
└── Helpers — Logging, JSON parsing
claude-copilot (launcher script)
├── Proxy Lifecycle — Auto-start with health check polling
├── Config Seeding — Onboarding wizard bypass for claude-cli
└── Exec — Replaces process with claude binary

Limitations

  • Copilot subscription required — You need GitHub Copilot Business or Enterprise
  • Rate limits — Subject to Copilot's rate limiting, not Anthropic's
  • Extended thinking — Mapped to reasoning_effort: "high" (not native thinking blocks)
  • Caching — Copilot doesn't support prompt caching; cache token fields are zeroed
  • Beta features — Anthropic beta headers are not forwarded

Troubleshooting

Proxy won't start

cat /tmp/copilot-proxy.log
# Check if port 4141 is in use
lsof -i :4141

Authentication issues

# Verify your token works
curl -s https://api.business.githubcopilot.com/models \
-H "Authorization: Bearer $(gh auth token)" \
-H "Copilot-Integration-Id: copilot-developer-cli"

Claude shows onboarding wizard

# The launcher seeds this automatically, but if needed manually:
claude-copilot --version # Triggers config seeding without starting interactive mode

Requirements

  • Node.js ≥ 18
  • GitHub Copilot Business or Enterprise subscription
  • Claude Code CLI (claude) installed

License

MIT

About

Zero-dependency proxy to run Claude Code via your GitHub Copilot subscription. Translates Anthropic Messages API ↔ OpenAI Chat Completions.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

copilot-proxy

Use your GitHub Copilot subscription as the backend for Claude Code.

A zero-dependency localhost proxy that translates the Anthropic Messages API into the OpenAI Chat Completions format used by GitHub Copilot's API. This lets you run claude (Claude Code CLI) powered entirely by your existing Copilot Business/Enterprise subscription — no separate Anthropic API key required.

┌────────────┐ Anthropic API ┌───────────────┐ OpenAI API ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ copilot-proxy │ ────────────────▶│ GitHub Copilot │
│ (CLI) │◀────────────────────── │ :4141 │◀──────────────── │ API │
└────────────┘ Anthropic SSE events └───────────────┘ OpenAI SSE └─────────────────┘

Features

  • Full API translation — Anthropic Messages API ↔ OpenAI Chat Completions, including streaming SSE
  • All Claude models — Opus 4.6, Sonnet 4.6, Haiku 4.5 (and 4.5 variants)
  • Tool use / function calling — Complete bidirectional translation of tool definitions and results
  • Streaming — Real-time SSE event translation (OpenAI data: → Anthropic event: format)
  • Multi-modal — Image content blocks translated to OpenAI image_url format
  • Zero dependencies — Pure Node.js stdlib (http, https, fs, os, path, child_process)
  • Auto-authentication — Discovers tokens from 5 sources with GitHub Device Flow fallback
  • Token refresh — Automatic retry on 401/403 with token cache invalidation

Quick Start

One-command install

git clone https://github.com/schwarztim/copilot-proxy.git ~/.copilot-proxy
ln -sf ~/.copilot-proxy/claude-copilot ~/.local/bin/claude-copilot

Then just run:

claude-copilot

The launcher handles everything: starts the proxy, seeds the required config, and launches Claude Code.

Manual setup

# 1. Start the proxy
node proxy.mjs
# 2. Point claude at itexport ANTHROPIC_BASE_URL=http://localhost:4141
export ANTHROPIC_API_KEY=sk-ant-copilot-proxy-not-a-real-key
claude

How It Works

Authentication Chain

The proxy discovers your GitHub Copilot token automatically, checking these sources in order:

PrioritySourceDescription
1COPILOT_GITHUB_TOKENEnvironment variable override
2OpenCode auth.json~/.local/share/opencode/auth.json
3macOS KeychainService: copilot-cli
4GitHub CLIgh auth token
5Legacy config~/.config/github-copilot/apps.json
6Device FlowInteractive GitHub OAuth (first-run only)

If no token is found, the proxy starts an interactive GitHub Device Flow to authenticate with the copilot scope.

Model Mapping

Claude Code sends model IDs with dashes (e.g., claude-sonnet-4-6). The Copilot API expects dots (e.g., claude-sonnet-4.6). The proxy handles this automatically, including stripping date suffixes and version tags.

Claude Code sendsCopilot receives
claude-sonnet-4-6claude-sonnet-4.6
claude-opus-4-6claude-opus-4.6
claude-haiku-4-5claude-haiku-4.5
claude-sonnet-4-5-20250929claude-sonnet-4.5
claude-opus-4-5-v1claude-opus-4.5

Non-Claude models (GPT, Gemini) are passed through unchanged.

API Translation

The proxy performs bidirectional translation between the two API formats:

Request (Anthropic → OpenAI)

  • System prompts → role: "system" messages
  • Content blocks → Concatenated text or multipart content
  • tool_use blocks → tool_calls array
  • tool_result blocks → role: "tool" messages
  • Image blocks → image_url with data URI
  • stop_sequencesstop
  • thinkingreasoning_effort

Response (OpenAI → Anthropic)

  • choices[0].message → Anthropic message envelope
  • finish_reason mapping: stopend_turn, lengthmax_tokens, tool_callstool_use
  • Token usage translation with cache token fields

Streaming (OpenAI SSE → Anthropic SSE)

  • message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop
  • delta.contenttext_delta events
  • delta.tool_callsinput_json_delta events with proper block lifecycle

Configuration

Environment VariableDefaultDescription
COPILOT_PROXY_PORT4141Port the proxy listens on
COPILOT_GITHUB_TOKENOverride the GitHub token
ANTHROPIC_BASE_URLSet by launcher; points claude at proxy
ANTHROPIC_API_KEYSet by launcher; sk-ant- prefixed key

Verbose logging

node proxy.mjs --verbose # or -v

Logs model routing, message counts, and token usage to stderr.

Architecture

proxy.mjs (804 lines, zero dependencies)
├── Token Management — Multi-source token discovery + caching
├── GitHub Device Flow — Interactive OAuth for first-run auth
├── Anthropic → OpenAI — Request translation (messages, tools, images)
├── OpenAI → Anthropic — Response translation (non-streaming)
├── Streaming Translator — SSE event-by-event conversion
├── HTTP Server — Routes: /v1/messages, /v1/models, /health
└── Helpers — Logging, JSON parsing
claude-copilot (launcher script)
├── Proxy Lifecycle — Auto-start with health check polling
├── Config Seeding — Onboarding wizard bypass for claude-cli
└── Exec — Replaces process with claude binary

Limitations

  • Copilot subscription required — You need GitHub Copilot Business or Enterprise
  • Rate limits — Subject to Copilot's rate limiting, not Anthropic's
  • Extended thinking — Mapped to reasoning_effort: "high" (not native thinking blocks)
  • Caching — Copilot doesn't support prompt caching; cache token fields are zeroed
  • Beta features — Anthropic beta headers are not forwarded

Troubleshooting

Proxy won't start

cat /tmp/copilot-proxy.log
# Check if port 4141 is in use
lsof -i :4141

Authentication issues

# Verify your token works
curl -s https://api.business.githubcopilot.com/models \
-H "Authorization: Bearer $(gh auth token)" \
-H "Copilot-Integration-Id: copilot-developer-cli"

Claude shows onboarding wizard

# The launcher seeds this automatically, but if needed manually:
claude-copilot --version # Triggers config seeding without starting interactive mode

Requirements

  • Node.js ≥ 18
  • GitHub Copilot Business or Enterprise subscription
  • Claude Code CLI (claude) installed

License

MIT

About

Zero-dependency proxy to run Claude Code via your GitHub Copilot subscription. Translates Anthropic Messages API ↔ OpenAI Chat Completions.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages