Lightweight GitHub Copilot client with device login
Project description
Copilot Python Client
Synchronous GitHub Copilot client and CLI with device flow auth, token exchange, model management, and streaming chat.
Package/CLI version: 1.0.0
Installation
- Python 3.10+
- From PyPI (recommended):
pip install copilot-client
- From GitHub:
pip install "git+https://github.com/AlpMeteSenel/copilot-python-client.git"
CLI (copilot-client)
The CLI is installed as copilot-client (same version as the package). Credentials live in ~/.copilot_client/config.json and are reused across commands.
- Authenticate via device flow or paste a token:
copilot-client auth - List available models:
copilot-client models - Interactive chat:
copilot-client chat --model gpt-5-mini --system "Be concise"
Quickstart (programmatic)
import os
from copilot_client import CopilotClient
# Use an existing Copilot access token or fetch one via device flow (see below)
client = CopilotClient(copilot_access_token=os.environ["COPILOT_TOKEN"])
print(client.get_user())
print(client.chat([{ "role": "user", "content": "Say hi" }]))
Auth options
- Device flow:
code = CopilotClient.start_device_flow() print(f"Open {code.verification_uri} and enter {code.user_code}") github_token = CopilotClient.poll_device_flow(code.device_code, poll_interval=code.interval) client = CopilotClient(copilot_access_token=github_token) print("Copilot token:", client.copilot_token)
- Existing Copilot access token:
client = CopilotClient(copilot_access_token=os.environ["COPILOT_TOKEN"])
End-to-end walkthrough
from pathlib import Path
import base64
from copilot_client import CopilotClient
# Start device flow and exchange for a Copilot token
code = CopilotClient.start_device_flow()
print(f"Open {code.verification_uri} and enter {code.user_code}")
token = CopilotClient.poll_device_flow(code.device_code, poll_interval=code.interval)
client = CopilotClient(copilot_access_token=token)
print("copilot_token", client.copilot_token)
print("user", client.get_user())
models = client.list_models()
print([[m["id"], (m.get("policy", {}).get("state", "no policy"))] for m in models])
if models:
try:
print("enable_model", client.enable_model(models[0]["id"]))
except Exception as exc:
print("enable_model skipped", exc)
reply = client.chat([{"role": "user", "content": "Summarize GitHub in 2 bullets"}], system_message="Be concise")
print("chat", reply)
print("chat_stream", end=" ")
for chunk in client.chat_stream([{ "role": "user", "content": "Name two Python async primitives"}], model="copilot-nes-xtab"):
if chunk["type"] == "text-delta":
print(chunk["text"], end="")
print()
image_path = Path("husky.jpg") # replace with your image path
image_base64 = base64.b64encode(image_path.read_bytes()).decode("ascii")
vision_message = [{
"role": "user",
"content": [
{"type": "text", "text": "What is on this image?"},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_base64}", "detail": "high"}},
],
}]
for chunk in client.chat_stream(vision_message, model="gpt-5-mini", vision=True):
if chunk["type"] == "text-delta":
print(chunk["text"], end="")
print()
Core usage
- Models: list with
client.list_models(); enable those needing consent viaclient.enable_model(model_id). - Chat (non-streaming):
client.chat([...], model="gpt-5-mini", system_message="Be concise", max_output_tokens=200). - Chat (streaming): iterate over
client.chat_stream([...], model="copilot-nes-xtab")and printchunk["text"]whenchunk["type"] == "text-delta". - User info:
client.get_user().
enable_model only activates models that require explicit consent; many will already be enabled.
Errors
All methods raise CopilotError on non-2xx responses. Auth issues raise CopilotAuthError; rate limits raise CopilotRateLimitError.
Tips
chat_stream(..., vision=True)forwards the Copilot vision header when prompts include images.- Copilot access tokens are exchanged automatically for Copilot bearer tokens and refreshed every 30 minutes.
Credits
Built by Alp Mete Senel. Contributions and issues are welcome.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file copilot_client-1.0.0.tar.gz.
File metadata
- Download URL: copilot_client-1.0.0.tar.gz
- Upload date:
- Size: 10.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67c388605960bd26af80232963d51b328d38e367d97996a79a91c2a30e6c967b
|
|
| MD5 |
4e6981bd8f10f65966a9720ffff68c97
|
|
| BLAKE2b-256 |
9e3d930b2aae353ceac02d064184b4a4a93874bdca012c6df1cb76f10bd9c5f7
|
File details
Details for the file copilot_client-1.0.0-py3-none-any.whl.
File metadata
- Download URL: copilot_client-1.0.0-py3-none-any.whl
- Upload date:
- Size: 9.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9cd6e82462c52b7fcf58641d80bacc5cd0871e43dbea8e2690b46414c5fbd5bc
|
|
| MD5 |
3bcc755e0f3aaba2794393214f0885d8
|
|
| BLAKE2b-256 |
7090207dae176fb03769a9f9de4e6cd4f72dc18be5c082d88c6a8305800f48b6
|