codex-pal
Bring your models to Codex—from one-command profiles to Python-orchestrated multi-agent workflows.
codex-pal lets Codex CLI use OpenAI-compatible Chat Completions providers
through codex-relay. For everyday
use, it is a small profile-based launcher that leaves your global Codex
configuration untouched. For automation, the same profiles can be composed as
asynchronous Python agents.
Why codex-pal?
- Native Codex experience — keep the normal terminal UI, tools, sandbox,
project context, and
codex exec --jsonprotocol. - No global config changes — provider settings are injected per invocation;
~/.codex/config.tomlremains untouched. - Reusable provider profiles — keep model, relay, approval, sandbox, and context settings under memorable names.
- Safe multi-provider relays — managed relays are serialized and identified by configuration, so one profile cannot silently use another provider.
- Thin Python orchestration — run profiles sequentially or concurrently without introducing another agent runtime or Python dependency stack.
Quick start
Codex CLI must already be installed and available on PATH.
One provider, one command
pipx install codex-pal
export DEEPSEEK_API_KEY=...
codex-pal deepseek
The first launch creates a reusable deepseek profile and then hands the
terminal to Codex. The same pattern works for kimi, qwen, zai, mistral,
groq, xai, and openrouter.
Multiple models, programmable agents
Install codex-pal into the Python environment running the orchestrator:
python -m pip install codex-pal
export MOONSHOT_API_KEY=...
export DASHSCOPE_API_KEY=...
codex-pal architect config \
--provider kimi \
--model kimi-k3 \
--port 4444 \
--sandbox read-only
codex-pal reviewer config \
--provider qwen \
--model qwen3.7-max \
--port 4445 \
--sandbox read-only
import asyncio
from pathlib import Path
from codex_pal import Agent, AgentTask, run_parallel
async def main():
repo = Path("/path/to/project")
results = await run_parallel([
AgentTask(
Agent("architect", cwd=repo),
"Map the architecture and propose an implementation plan. Do not edit files.",
),
AgentTask(
Agent("reviewer", cwd=repo),
"Find high-confidence correctness issues. Do not edit files.",
),
])
for result in results:
print(result.profile, result.events)
asyncio.run(main())
See the Python Multi-Agent API for staged workflows, worktree isolation, event handling, custom providers, and the complete API reference.
How it works
Profile (provider, model, policy)
|
v
codex-pal
/ \
v v
Codex CLI -> codex-relay -> model provider
native UX Responses-to-Chat bridge
For each launch, codex-pal starts or reuses the appropriate relay, injects
Codex configuration with -c, and then runs Codex directly. Relay-backed
providers also get a temporary model catalog so Codex's /model picker lists
provider-specific models.
Managed local relays record their upstream identity. Concurrent launches are
serialized per port, and a differently configured profile is rejected instead
of being routed to the wrong provider. Remote relays remain available through
--relay-url.
Install
PyPI
For CLI use:
pipx install codex-pal
For the Python API, install into your application environment:
python -m pip install codex-pal
The PyPI package installs codex-relay as a runtime dependency. codex-pal
finds that dependency beside its own executable—including inside pipx's private
environment—before searching PATH. To expose codex-relay as a standalone
command too, use pipx install codex-pal --include-deps.
crates.io
Cargo does not install dependency binaries onto PATH, so install both tools:
cargo install codex-pal codex-relay
Profiles and CLI usage
Human-friendly profiles
export DEEPSEEK_API_KEY=...
codex-pal deepseek
export DASHSCOPE_API_KEY=...
codex-pal qwen
export OPENROUTER_API_KEY=...
codex-pal openrouter
The first run creates a profile under ~/.config/codex-pal/config.toml when
the profile name matches a built-in provider. Later runs reuse it.
Configure or modify a profile:
codex-pal deepseek config --model deepseek-v4-pro --port 4555
codex-pal deepseek show
codex-pal profiles
codex-pal providers
codex-pal deepseek status
codex-pal deepseek stop
codex-pal deepseek restart
Custom profile:
export EXAMPLE_API_KEY=...
codex-pal work-llm config \
--provider custom \
--upstream https://llm.example.com/v1 \
--api-key-env EXAMPLE_API_KEY \
--model vendor/model
codex-pal work-llm
Complete explicit interface
Use run when every setting should be supplied by arguments:
codex-pal run \
--provider deepseek \
--model deepseek-v4-pro \
--port 4444 \
--approval never \
--sandbox workspace-write
Custom one-shot launch:
codex-pal run \
--provider custom \
--upstream https://llm.example.com/v1 \
--api-key-env EXAMPLE_API_KEY \
--model vendor/model
Useful flags:
codex-pal relay status --port 4444
codex-pal relay stop --port 4444
codex-pal relay-config --provider openrouter
codex-pal run --provider deepseek --model deepseek-v4-pro --print-codex-command
codex-pal run --provider deepseek --model deepseek-v4-pro --ask
codex-pal run --provider deepseek --model deepseek-v4-pro --no-sandbox
Remote relays
Use an existing remote codex-relay service instead of starting a local sidecar:
codex-pal run \
--provider deepseek \
--model deepseek-v4-pro \
--relay-url https://relay.example.com
codex-pal deepseek --relay-url https://relay.example.com
codex-pal deepseek config --relay-url https://relay.example.com
--relay-url accepts either the relay root URL or its /v1 base URL. When it
is set, codex-pal skips local relay process management and points Codex at
the remote relay.
Forwarding Codex commands
Arguments left after codex-pal consumes its profile or launch options are
appended to the codex invocation, so Codex subcommands and flags can be used
directly:
codex-pal run --provider deepseek --model deepseek-v4-pro exec --skip-git-repo-check "summarize this repo"
codex-pal deepseek exec --skip-git-repo-check "summarize this repo"
codex-pal deepseek --oss
Use -- when you need to force a later argument to be handled by Codex even if
it looks like a codex-pal option:
codex-pal deepseek -- --model gpt-5.5
Python multi-agent API
The PyPI package includes a standard-library-only asyncio wrapper. Each Agent
uses an existing profile, keeping CLI and Python configuration in one place:
from codex_pal import Agent
result = await Agent("architect", cwd="/path/to/project").run(
"Analyze this repository and propose a refactoring plan. Do not edit files."
)
Agent.run() invokes the equivalent of codex-pal <profile> exec --json -,
sends the prompt over stdin, and returns decoded JSONL events. cwd can point
at a separate Git worktree for each writing agent. run_parallel() composes
independent profiles without replacing Codex or introducing a second agent
runtime.
Read the full Python Multi-Agent API guide.
Provider Profiles
| Provider | Upstream | API key env |
|---|---|---|
deepseek |
https://api.deepseek.com/v1 |
DEEPSEEK_API_KEY |
z, zai |
https://api.z.ai/api/paas/v4 |
ZAI_API_KEY |
kimi, moonshot |
https://api.moonshot.cn/v1 |
MOONSHOT_API_KEY |
qwen, dashscope |
https://dashscope.aliyuncs.com/compatible-mode/v1 |
DASHSCOPE_API_KEY |
mistral |
https://api.mistral.ai/v1 |
MISTRAL_API_KEY |
groq |
https://api.groq.com/openai/v1 |
GROQ_API_KEY |
xai, grok |
https://api.x.ai/v1 |
XAI_API_KEY |
openrouter |
https://openrouter.ai/api/v1 |
OPENROUTER_API_KEY |
Default models:
| Provider | Default model |
|---|---|
openai |
gpt-5.5 |
deepseek |
deepseek-v4-pro |
z, zai |
glm-5.2 |
kimi, moonshot |
kimi-k3 |
qwen, dashscope |
qwen3.7-max |
mistral |
mistral-medium-3-5+2 |
groq |
openai/gpt-oss-120b |
xai, grok |
grok-4.3 |
openrouter |
openrouter/auto |
Development
cargo test
cargo fmt --check
maturin build
Release
Releases are tag-driven from GitHub Actions.
One-time setup:
- Create a GitHub environment named
release. - Add an environment secret named
CARGO_REGISTRY_TOKENwith a crates.io API token. - On PyPI, create a pending Trusted Publisher for:
- project:
codex-pal - owner:
MetaFARS - repository:
codex-pal - workflow:
release.yml - environment:
release
- project:
Publish:
git tag v0.1.1
git push origin v0.1.1
The release workflow builds all wheels and the sdist, publishes to PyPI via Trusted Publishing, publishes the Rust crate to crates.io, and creates a GitHub Release with the built artifacts.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
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 codex_pal-0.2.1.tar.gz.
File metadata
- Download URL: codex_pal-0.2.1.tar.gz
- Upload date:
- Size: 56.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4dbe3d35df8be22d10885170a77a1040dac7753d0f6b812d4dc07c70a2ebdda2
|
|
| MD5 |
e36a579e41e34d5ff5e71db80d451dfd
|
|
| BLAKE2b-256 |
4e415e1f1093fa6849c6046b810b2bb205586b605c9596b331c4e52fffad7147
|
File details
Details for the file codex_pal-0.2.1-py3-none-win_arm64.whl.
File metadata
- Download URL: codex_pal-0.2.1-py3-none-win_arm64.whl
- Upload date:
- Size: 644.6 kB
- Tags: Python 3, Windows ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5dd3038e508ba07dc51c2166667f68e9c59ca42a1c3ec178cbd6b57d666bc26
|
|
| MD5 |
8e5cbedb46215d08ed66d09c8f777b04
|
|
| BLAKE2b-256 |
88e66c89c8bd01e70d7c12cfbc45a2a3849d01c371eda1992bd053bb2d77f4ad
|
File details
Details for the file codex_pal-0.2.1-py3-none-win_amd64.whl.
File metadata
- Download URL: codex_pal-0.2.1-py3-none-win_amd64.whl
- Upload date:
- Size: 674.7 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cde8e8d9c707619eb6667480eeb081dd90084ce8bf9f1318960548bb28d8e999
|
|
| MD5 |
a14543e79d50ec0f95b48af293527121
|
|
| BLAKE2b-256 |
23333fd99c7863bef0c85598a2cd5fd7834c682c4d5f31c80d8b0dfaea42bf8d
|
File details
Details for the file codex_pal-0.2.1-py3-none-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: codex_pal-0.2.1-py3-none-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 884.4 kB
- Tags: Python 3, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69311a9302213b86d0958714939de954f025bf07213535d7916d5ddf9ad1dfeb
|
|
| MD5 |
2497f8771a5be6eb2702791606a07350
|
|
| BLAKE2b-256 |
df01fe6db806c4134e4cc06ecaa47be77e30d4b32a95404b72b691f1a919925f
|
File details
Details for the file codex_pal-0.2.1-py3-none-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: codex_pal-0.2.1-py3-none-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 860.8 kB
- Tags: Python 3, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c275c4661c31906ed9b687711bbe4bd6ffc97dabfe08b8e6505ee9f6f5cf8fbc
|
|
| MD5 |
4926ebf064b9e15c3608acc1d84959e3
|
|
| BLAKE2b-256 |
0577c855cd2929fcd64cce82548ae09ca38a23a3d7acca4ed94f843d0875956c
|
File details
Details for the file codex_pal-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: codex_pal-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 820.5 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12419844f3875c2fc32697b891cd5e7ce3e07a6064b2a061082a6b9beb8f6351
|
|
| MD5 |
fec10fe1d9b8f031704327a2d6887a24
|
|
| BLAKE2b-256 |
0b07ffc304c6ccfa5624a32b666a583c118e59340c8820f4b7affeac0088091a
|
File details
Details for the file codex_pal-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: codex_pal-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 802.3 kB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
624003fc9f38bf3e38c7aa5438e5c3ba12e4339dab89464f01ab667c0e917ae4
|
|
| MD5 |
15b6182ebe78cce552888600c25aa1ef
|
|
| BLAKE2b-256 |
bc907dbeb51006e52c1cfd6d1b015b9d7b800c5b124b28cfef4b39270b7bd0a0
|
File details
Details for the file codex_pal-0.2.1-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: codex_pal-0.2.1-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 748.6 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cf442be14e7ff9fe5d23b082a7466a9119495d2d09a4521874a9ad024d0cb7d
|
|
| MD5 |
59092187ef03d63aff9fa904eb43d485
|
|
| BLAKE2b-256 |
5ea1f7c28f92a26cb3e65386992208111e53dd9d09eae40d94399827290dc89a
|
File details
Details for the file codex_pal-0.2.1-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: codex_pal-0.2.1-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 769.1 kB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89e0a1819315474d4f274a1296fbb7c09203b74ee3623692a48f5d5dc70f1536
|
|
| MD5 |
b009f07380ad138cfa94b07ffe11e11b
|
|
| BLAKE2b-256 |
b02edb5f6a52c71e4362c503e227097e6bfb3dd43356def8487597624eb8590c
|