Running the Copilot CLI in Standalone Server Mode
This page is a detailed reference for starting the GitHub Copilot CLI as a long-lived, standalone TCP server that other processes — the Python SDK, the API server, or your own clients — connect to over a socket.
The canonical command is:
copilot --server --port 3000 --log-level all --allow-all-tools --allow-all-paths --allow-all-urls
Why this is not in
copilot --help--serverand--portare operational flags for running the CLI as a service. They are intentionally omitted from thecopilot --helplisting (which focuses on interactive and-p/--promptusage), but they are fully supported. The closely related--acpflag shown in--helpstarts an Agent Client Protocol server instead, which is a different protocol and is not what the SDK'sRuntimeConnectionconnects to.
When to Use Server Mode
By default the SDK spawns the copilot CLI for you over stdio, so you do
not need server mode for the tutorials. Start a standalone server when you
want to:
- Share one runtime across many clients — multiple scripts or API workers connect to a single warm CLI process instead of each spawning its own.
- Decouple processes — run the CLI in its own container (see Docker) and connect the API server to it over the network.
- Inspect traffic centrally — one place to collect logs and OpenTelemetry signals.
graph LR
subgraph Clients
A[Python SDK script]
B[API server]
C[Your own client]
end
A -->|TCP localhost:3000| S[copilot --server]
B -->|TCP localhost:3000| S
C -->|TCP localhost:3000| S
S -->|HTTPS| D[GitHub Copilot API]
style S fill:#90caf9
style D fill:#64b5f6
Anatomy of the Command
| Flag | Meaning |
|---|---|
--server |
Run the CLI as a long-lived server instead of an interactive session. |
--port 3000 |
TCP port the server listens on. Pick any free port. |
--log-level all |
Verbose logging. See Log Levels for the full set. |
--allow-all-tools |
Allow every tool to run without an interactive confirmation prompt. Required for unattended (non-interactive) operation. |
--allow-all-paths |
Disable file-path verification and allow access to any path on the filesystem. |
--allow-all-urls |
Allow access to all URLs without confirmation. |
--model <model> |
(Optional) Default model the server uses, e.g. --model gpt-5-mini. Overridable per request and via COPILOT_MODEL. |
The three
--allow-all-*flags can be replaced by the single shortcut--allow-all(or--yolo), which is exactly equivalent to--allow-all-tools --allow-all-paths --allow-all-urls.
Why the --allow-all-* flags are needed
A standalone server runs unattended — there is no human at a terminal to
answer permission prompts. The --allow-all-* flags pre-approve tool, file,
and network access so the server can act on requests without blocking. For
tighter control you can swap them for the granular flags described under
Scoping Permissions.
Starting the Server
1. Authenticate
The server needs a GitHub account with Copilot access. Use either method:
# Option A: GitHub CLI (the server reuses these credentials)
gh auth login
# Option B: Personal access token
export COPILOT_GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
COPILOT_GITHUB_TOKEN, GH_TOKEN, and GITHUB_TOKEN are honored in that order
of precedence.
2. Run the command
copilot \
--server \
--port 3000 \
--log-level all \
--allow-all-tools --allow-all-paths --allow-all-urls \
--model gpt-5-mini
3. Confirm the startup output
On a successful start the server prints:
CLI server listening on port 3000
Warning: No COPILOT_CONNECTION_TOKEN was set, so connections will be accepted from any client
The first line confirms the listener is up. The second line is a security notice — see Securing the Server. The process then stays in the foreground until you stop it.
Verifying the Server Is Listening
From another terminal:
# Show the listening socket
lsof -nP -iTCP:3000 -sTCP:LISTEN
# Or probe the port
nc -z -v 127.0.0.1 3000
A successful probe reports Connection to 127.0.0.1 port 3000 succeeded!. On a
local run the server binds to the loopback interface (127.0.0.1), so it is
reachable from the same host by default. To reach it from another container or
host, see Running with Docker and Make and
Securing the Server.
Connecting from the SDK
Point any SDK client at the running server instead of letting it spawn its own
CLI over stdio. Pass a RuntimeConnection:
from copilot import CopilotClient, RuntimeConnection
client = CopilotClient(
connection=RuntimeConnection.for_uri("localhost:3000")
)
await client.start()
The tutorial scripts expose this as a --cli-url flag:
cd src/python
uv run python scripts/tutorials/01_chat_bot.py \
--prompt "What is GitHub Copilot?" \
--cli-url localhost:3000
The API server reads the same value from the COPILOT_CLI_URL environment
variable (e.g. COPILOT_CLI_URL=127.0.0.1:3000).
Log Levels
--log-level accepts the following values (copilot help logging):
| Level | Output |
|---|---|
none |
No logging output |
error |
Only error messages |
warning |
Error and warning messages |
info |
Error, warning, and info messages |
debug |
All messages including debug |
all |
Same as debug |
default |
Same as info |
Use --log-dir <directory> to redirect log files (default: ~/.copilot/logs/).
--log-level all is convenient while learning; drop to info or warning for
quieter production logs.
For OpenTelemetry diagnostic logging (
OTEL_LOG_LEVEL) and exporting traces and metrics, seecopilot help monitoring.
Scoping Permissions Instead of Allow-All
--allow-all-* is the simplest choice for local experimentation, but the CLI
supports fine-grained permissions (copilot help permissions). Replace the
broad flags with targeted ones to reduce the server's blast radius:
# Allow all git commands except `git push`
copilot --server --port 3000 \
--allow-tool='shell(git:*)' --deny-tool='shell(git push)'
# Allow only file edits and a single domain
copilot --server --port 3000 \
--allow-tool='write' \
--allow-url=github.com
Key rules:
- Denial always wins.
--deny-tool/--deny-urltake precedence over any allow rule, including--allow-all-tools. --available-tools/--excluded-toolsdecide which tools the model can see;--allow-tool/--deny-tooldecide which run without a prompt.- URL rules are protocol-aware. Allowing
github.compermitshttps://only; addhttp://explicitly if needed. - Path access defaults to the working directory (plus the system temp dir).
--allow-all-pathsremoves that restriction;--disallow-temp-dirtightens it.
Choosing the Model
The --model flag sets the default model for the server. It can also be set
through the environment:
export COPILOT_MODEL="gpt-5-mini"
copilot --server --port 3000 --allow-all
Precedence: the --model flag overrides COPILOT_MODEL, which overrides the
persisted config default. Use --model auto to let Copilot pick automatically.
Securing the Server
Without a token, any client that can reach the port can use the server with your Copilot identity. The startup warning highlights this. To require authentication:
- Set a shared secret in the server's environment:
export COPILOT_CONNECTION_TOKEN="your-shared-secret"
copilot --server --port 3000 --allow-all --model gpt-5-mini
- Pass the same token from every client:
from copilot import CopilotClient, RuntimeConnection
client = CopilotClient(
connection=RuntimeConnection.for_uri(
"localhost:3000",
connection_token="your-shared-secret",
)
)
Additional hardening:
- Keep it on localhost. Do not bind or forward the port to untrusted
networks. Combined with
--allow-all-*, an exposed server is effectively remote code execution as your user. - Do not pass
--no-auto-loginfor SDK scenarios — the server would start without credentials, and sessions fail withSession was not created with authentication info or custom provider.
Running with Docker and Make
Make target
The repository wraps the command in a Make target:
cd src/python
export COPILOT_GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
make copilot # runs `copilot --server --port 3000 ... --model $(COPILOT_MODEL)`
The model defaults to gpt-5-mini and can be overridden with
make copilot COPILOT_MODEL=gpt-5.2.
Dedicated container
copilot.Dockerfile
builds a Node.js image that runs only the CLI server and exposes port 3000:
CMD ["bash", "-c", "copilot --server --port 3000 --log-level all --allow-all-tools --allow-all-paths --allow-all-urls --model ${COPILOT_MODEL}"]
Docker Compose
compose.docker.yaml
runs the CLI server and the API as separate services. The API connects to the
server by service name over the Compose network:
services:
copilot:
# ...
ports:
- "3000:3000"
api:
environment:
- COPILOT_CLI_URL=copilot:3000 # connect to the copilot service
depends_on:
copilot:
condition: service_healthy
A monolith profile runs both the CLI server and the API inside one container,
where the API reaches the server via 127.0.0.1:3000. The
monolithic Dockerfile
uses supervisord to manage both processes.
For a full container walkthrough, see the CopilotReportForge Running Containers Locally guide.
Stopping the Server
The server runs in the foreground. Stop it with Ctrl+C. If it was started in
the background or in a container:
# Find and stop a local process
lsof -nP -iTCP:3000 -sTCP:LISTEN # note the PID
kill <PID>
# Docker Compose
docker compose down
Troubleshooting
| Symptom | Cause / Fix |
|---|---|
address already in use on startup |
Another process holds the port. Stop it (lsof -nP -iTCP:3000 -sTCP:LISTEN) or start with a different --port. |
No COPILOT_CONNECTION_TOKEN was set warning |
Expected without a token; fine for local testing. Set COPILOT_CONNECTION_TOKEN to restrict access. |
Session was not created with authentication info or custom provider |
The server has no credentials — usually from --no-auto-login. Remove that flag and authenticate via gh auth login or COPILOT_GITHUB_TOKEN. |
| Client cannot connect from another container | Use the service name (copilot:3000), not localhost, and ensure the port is published. |
| Tools hang waiting for approval | The server is missing --allow-all-tools (or a matching --allow-tool rule) for unattended use. |
See Also
- Getting Started — environment setup and the quick version of this section.
- Architecture — how the SDK, CLI server, and Copilot API interact.
- 01: CLI Chatbot — first script, including
--cli-urlusage and connection-token notes. copilot help permissions,copilot help logging,copilot help monitoring,copilot help environment— built-in reference topics.