A small, self-bootstrapping CLI that manages a local
@jeffreycao/copilot-api
proxy: start/stop the daemon, wire model aliases, export env vars for your shell
and for Codex, and report estimated token spend.
TypeScript port of the original Python copilot-api helper. Runs on Linux,
macOS, and Windows.
- Lifecycle:
start/stopthe local proxy with one command - or opt in to the managed lifecycle (auto-start) that starts the proxy when an agent needs it and stops it after an idle window. - Zero setup: auto-installs bun, dependencies, and the proxy on first run. No global installs to manage.
- Codex + Claude wiring: point both CLIs at the local proxy or GitHub
Copilot Direct automatically; write
~/.codex/~/.claudeconfig; build a per-hostCODEX_HOMEfarm (Linux/macOS). - One credential per setup:
agent authmanages the GitHub Copilot token (device flow,ghCLI, or a stored PAT) as the single source of truth for the default setup - and one slot per named profile; PATs work through an automatic passthrough shim. - Named profiles:
agent profilebundles ONE credential + ONE mode (direct or proxy) into both agents, so several sessions run at once - direct beside proxy, or a second GitHub account - each proxy profile with its own daemon on its own port. Launch withcl --profile <name>/cx --profile <name>. - Typed preferences:
agent configgets/sets every knob - lifecycle, ports, proxy feature flags, model ids - with one precedence rule everywhere. - Cost reporting: estimated spend from per-host usage DBs via live OpenRouter pricing.
- Controlled floating: the proxy floats to the newest cooldown-aged release
within configured bounds; every other dependency is pinned via
bun.lock.
# macOS / Linux
curl -fsSL https://github.com/Vivswan/copilot-env/releases/latest/download/install.sh | bash# Windows (runs from any shell -- cmd, PowerShell, or the Run dialog)
powershell -c "irm https://github.com/Vivswan/copilot-env/releases/latest/download/install.ps1 | iex"Installs bun and copilot-env into ~/.copilot-env, bootstraps dependencies, then wires your shell.
-
Recommended: install from the latest GitHub release asset, not from the
mainbranch.mainis for development and can be temporarily ahead of the latest released installer flow. -
Artifact: the installer extracts the official
copilot-env-vX.Y.Z.tar.gzrelease asset when present, verifies that asset's SHA256, and checks the archive source marker against GitHub release metadata before extraction. -
Replaceable: re-run the bootstrapper to replace the previous install with the selected release.
-
Next: restart your shell, then
agent start. -
Optional: run
agent shell --clis --launchersfor Claude/Copilot/Codex CLIs andcl/co/cx. -
Update later:
agent update. -
Uninstall:
agent uninstallremoves everything copilot-env manages (daemons, profiles, agent wiring, shell integration, credentials, data, and the install itself). It does not remove the agent CLIs (claude/copilot/codex) or bun. -
Specific version: replace
latestwith an exact release tag:curl -fsSL https://github.com/Vivswan/copilot-env/releases/download/vX.X.X/install.sh | bashpowershell -c "irm https://github.com/Vivswan/copilot-env/releases/download/vX.X.X/install.ps1 | iex"
| macOS / Linux | Windows | Effect |
|---|---|---|
--dir DIR |
-InstallDir DIR |
Install target (default ~/.copilot-env; overrides COPILOT_ENV_DIR). |
--no-shell-integration |
-NoShellIntegration |
Don't touch your rc / $PROFILE. |
agent init # set up BOTH Codex + Claude (auto-detect direct vs the proxy) + next-step guidance
agent auth # manage the GitHub Copilot credential (--provider copilot|gh-cli|gh-token, --set, --get, --del, --check; --profile <name> addresses a named profile's slot, --list shows every slot)
agent profile # manage named profiles: --add <name> --direct|--proxy (one credential + one mode, both agents), --del <name>, --list, --check <name>
agent config # get/set preferences (--set <key> <value> / --get [key] / --del <key>; see Configuration below)
agent start # launch the daemon and sync aliases (--dry-run to preview, --port to pin, --check to probe, --profile <name> for a profile's daemon)
agent stop # stop the daemon (--profile <name> for one profile's daemon, --all for every daemon)
agent health # full environment diagnosis (--scope full|runtime|proxy|setup|auth|codex|claude, --json, --live)
agent models # list the model ids + names Copilot serves (--proxy / --direct / --json; no flag auto-picks)
agent env # print shell exports for the calling shell (CODEX_HOME / proxy ANTHROPIC_BASE_URL)
agent cost # estimated token spend across all usage DBs (default + profile daemons)
agent update # update to the latest release (--check; cooldown via `agent config --set update-cooldown`)
agent shell # wire rc / $PROFILE; --launchers adds cl/co/cx, --clis installs the CLIs, --remove unwires
agent uninstall # remove copilot-env entirely (--yes headless, --dry-run preview, --force to delete a git checkout)
agent codex # configure Codex; no flag auto-detects the backend, --check reports it
agent codex --direct # force GitHub Copilot Direct (no auto-detect probe)
agent codex --check # print provider mode; exits 0 direct, 2 proxy, 1 other
agent codex --host # per-host CODEX_HOME symlink farm (Linux/macOS); --delete-host to remove
agent codex --mobile # pair the Codex desktop app with the phone remote-control flow (interactive)
agent claude # configure Claude; no flag auto-detects the backend, --check reports it
agent claude --direct # force GitHub Copilot Direct for Claude (no auto-detect probe)
agent claude --check # print Claude provider mode; exits 0 direct, 2 proxy, 1 otherOnce the profile is wired, the same commands run via agent on Windows too (or
directly: powershell -ExecutionPolicy Bypass -File bin\agent.ps1 <cmd>).
The installer wires the agent wrapper into your shell and exports the proxy env.
- macOS / Linux: sources
shell/agents.bashrcfrom~/.bashrc/~/.zshrc. - Windows: dot-sources
shell/agents.ps1from your PowerShell$PROFILE.
The cl / co / cx launchers are opt-in:
clreads the configured Claude provider (agent claude --check), starts the proxy for proxy-backed or not-yet-configured setups (re-syncing the port/token), then Claude.coruns Copilot.cxdoes the same asclfor Codex (agent codex --check), then Codex.cl --profile <name>/cx --profile <name>(leading arguments) launch under a named profile instead: the profile's wiring is honored as-is, its own daemon is ensured when proxy-mode, and the default setup is untouched.
Each has a more-permissive variant that adds the agent's most-relaxed flag: clx (--dangerously-skip-permissions), cox (--allow-all), cxx (--sandbox danger-full-access).
Enable them while installing optional CLIs:
agent shell --clis --launchersOr manage only the launcher block:
agent shell --launchers
agent shell --launchers --removeManual sourcing is also supported:
source ~/.copilot-env/shell/agents.launchers.bashrc. ~/.copilot-env/shell/agents.launchers.ps1By default you manage the proxy yourself with agent start / agent stop.
Opt in to the managed lifecycle instead:
agent config --set auto-start trueWith auto-start on:
- Auto-start: whenever Codex, Claude, or the
cl/cxlaunchers need the proxy and it is down, it is started automatically (the shared credential resolver handles this - no manualagent start). - Idle auto-stop: a watchdog inside the daemon stops the proxy after an
idle window. Inference requests and the resolver's session heartbeats count
as activity; health and liveness pings never keep it alive. Configure the
window with
agent config --set idle-timeout <seconds>(default3600;0disables) or theCOPILOT_API_IDLE_TIMEOUTenv var.
With auto-start off, the launchers prompt before starting a downed proxy;
headless callers (Codex/Claude config hooks) never start it implicitly.
agent config is the typed preference store. Every read site applies the same
precedence: explicit flag/env (per-invocation) > stored config > built-in
default.
agent config --get # print all preferences
agent config --set auto-start true # set one
agent config --del idle-timeout # revert one to its default| Key | Default | Effect |
|---|---|---|
auto-start |
false |
Managed proxy lifecycle: auto-start on agent open + idle auto-stop. |
codex-model-catalog |
false |
Patched Codex model catalog serving Copilot's real context windows (opt-in). |
idle-timeout |
3600 |
Idle auto-stop window in seconds (0 disables). |
min-port / max-port |
1024 / 65535 |
Allowed proxy port range. |
message-websearch-model |
proxy default | Model id the proxy uses for Messages-API web search. |
messages-api |
true |
Proxy Messages-API (Anthropic-shaped) endpoint. |
passthrough |
auto |
PAT passthrough: auto / on / off (see below). |
port |
4141 |
Default proxy port (then next free unless strict-port). |
proxy-logs |
true |
Proxy request logging under <home>/logs (false discards the writes). |
proxy-version |
latest (floated) | Pin the floated proxy to a version/tag. |
release-cooldown |
bunfig minimumReleaseAge |
Proxy float supply-chain cooldown in seconds. |
responses-context-management |
proxy default | Proxy Responses-API server-side context management. |
responses-websearch |
true |
Proxy Responses-API web search. |
responses-websocket |
true |
Proxy Responses-API transport: WebSocket vs HTTP/SSE. |
small-model |
gpt-5-mini |
Small/fast model id the proxy uses. |
strict-port |
false |
Fail start when the default port is busy instead of auto-incrementing. |
update-cooldown |
none | agent update cooldown in days. |
Proxy-side keys (small-model, the responses-*/messages-api flags,
message-websearch-model) are projected into the proxy's own config.json at
agent start, so changing them needs a daemon restart to take effect.
codex-model-catalog applies at the next Codex auth refresh (within ~5
minutes) or agent codex/agent init wiring; turning it off also removes the
generated codex-model-catalog.json and the managed model_catalog_json
reference from the Codex config.
agent auth is the credential front door - one GitHub Copilot credential,
resolved at fetch time (agent configs never store a copy; gh-cli holds no
token of its own and defers to the machine's gh login):
--provider copilot- GitHub device flow (read:userscope).--provider gh-cli- use the machine's existingghlogin.--provider gh-token- store$COPILOT_GITHUB_TOKEN/$GH_TOKEN/$GITHUB_TOKEN(first set wins; headless servers);--set [token]stores one non-interactively.--get/--del/--check- print, clear, or check that a credential resolves.
Classic and fine-grained PATs can't perform the proxy's editor token exchange,
so agent start transparently enables a passthrough shim for PAT-shaped
tokens that uses the PAT as the bearer directly. Force it either way with
agent config --set passthrough on|off.
A profile is an atomic unit - ONE credential + ONE mode (direct or proxy, never both) - always wired into BOTH agents, so several sessions run at once without touching the default setup:
agent profile --add work --proxy --provider gh-token --set # own credential + mode + both agents, one command
cl --profile work # Claude under the profile (its own proxy daemon, own port)
cx --profile work # Codex under the same profile
agent profile --list # NAME MODE PROVIDER DAEMON
agent profile --del work # stop its daemon, clear its credential, strip both agents' wiringNamed profiles hard-fail rather than falling back to the default credential;
re-authenticate one with agent auth --profile <name>. A proxy-mode profile
gets its own daemon in an isolated home (<copilot-api home>/profiles/<name>)
on a stable reserved port, managed via agent start/stop --profile <name>.
Re-running --add with the other mode flag switches the profile's mode.
copilot-env loads local defaults from root .env when running its TypeScript
entry points; already-set shell environment variables take precedence, and env
vars take precedence over stored agent config values.
COPILOT_API_IDLE_TIMEOUT=<seconds>: override the managed-lifecycle idle window for this invocation (beats theidle-timeoutconfig key).COPILOT_API_VERSION=<version|tag>: pin the proxy to a specific release (bypasses the cooldown and float bounds at install;agent startstill refuses a proxy below the version floor. Theproxy-versionconfig key is the persistent equivalent).COPILOT_API_MIN_RELEASE_AGE=<seconds>: override the cooldown window (0= no cooldown), taking precedence over therelease-cooldownconfig key andbunfig.toml'sinstall.minimumReleaseAge.
Without a pin, the proxy float reads npm publish times, picks the newest
version at least the cooldown window old (env var, else release-cooldown
config, else bunfig.toml's install.minimumReleaseAge), and clamps it to
the bounds in copilot-env.config.
Drive the CLI from a checkout (deps + proxy install in-place; no separate cache):
git clone https://github.com/Vivswan/copilot-env.git
cd copilot-env
bash scripts/setup-env.sh # one-shot env/worktree init (bun install --frozen-lockfile)
./bin/agent --help # or: powershell -File bin\agent.ps1 --helpbun run typecheck # tsc --noEmit
bun test # test/**/*.test.ts
bun run lint # biome check src bin test scripts
bun run check # biome check --write src bin test scripts- Env init:
scripts/setup-env.sh(setup-env.ps1on Windows) is the single initializer; the Copilot coding agent and Codespaces / Dev Containers both run it. - More docs: conventions, the proxy float/cooldown model, and a file-by-file
breakdown live in
AGENTS.md.