Recently, the frequency of using AI has greatly increased. Copilot runs out of its monthly quota by mid-month, and Gemini CLI uses up the Pro quota every day. After running out, I found myself becoming very incompetent without AI. I started considering getting a "three princesses" setup for myself, so I chose Codex. However, I hesitated to spend $20 for a membership, and ultimately opted for a $20 monthly Coding membership with Zhipuai (which is really cheap...). Although Codex supports custom providers, there are still some pitfalls, and there isn't much information available online, so I’ll make a simple record.
Installation#
The installation is very simple and can basically be completed with one command.
npm i -g @openai/codex or
brew install codex or
nix-shell -p codex
config.json Configuration#
The default configuration folder for Codex is located in ~/.codex/, which may vary depending on the operating system (Windows might be a bit different). This folder contains the config.json file used for Codex configuration.
First, in version 0.1.2504, many tutorials on configuring config.toml do not work; you can only use json or yaml. There aren’t many official examples for yaml, so it’s best to use json.
Here is the official json example:
{
"model": "o4-mini",
"provider": "openai",
"providers": {
"openai": {
"name": "OpenAI",
"baseURL": "https://api.openai.com/v1",
"envKey": "OPENAI_API_KEY"
},
"azure": {
"name": "AzureOpenAI",
"baseURL": "https://YOUR_PROJECT_NAME.openai.azure.com/openai",
"envKey": "AZURE_OPENAI_API_KEY"
},
"openrouter": {
"name": "OpenRouter",
"baseURL": "https://openrouter.ai/api/v1",
"envKey": "OPENROUTER_API_KEY"
},
"gemini": {
"name": "Gemini",
"baseURL": "https://generativelanguage.googleapis.com/v1beta/openai",
"envKey": "GEMINI_API_KEY"
},
"ollama": {
"name": "Ollama",
"baseURL": "http://localhost:11434/v1",
"envKey": "OLLAMA_API_KEY"
},
"mistral": {
"name": "Mistral",
"baseURL": "https://api.mistral.ai/v1",
"envKey": "MISTRAL_API_KEY"
},
"deepseek": {
"name": "DeepSeek",
"baseURL": "https://api.deepseek.com",
"envKey": "DEEPSEEK_API_KEY"
},
"xai": {
"name": "xAI",
"baseURL": "https://api.x.ai/v1",
"envKey": "XAI_API_KEY"
},
"groq": {
"name": "Groq",
"baseURL": "https://api.groq.com/openai/v1",
"envKey": "GROQ_API_KEY"
},
"arceeai": {
"name": "ArceeAI",
"baseURL": "https://conductor.arcee.ai/v1",
"envKey": "ARCEEAI_API_KEY"
}
},
"history": {
"maxSize": 1000,
"saveHistory": true,
"sensitivePatterns": []
}
}
The provider we need, Zhipuai, is not included. We can either remove the existing provider or directly add a new one. The final config.json file is as follows:
{
"model": "glm-4.5",
"approvalMode": "suggest",
"fullAutoErrorMode": "ask-user",
"notify": true,
"provider": "zhipuai",
"providers": {
"zhipuai": {
"name": "zhipuai",
"baseURL": "https://open.bigmodel.cn/api/coding/paas/v4",
"envKey": "OPENAI_API_KEY"
}
},
"history": {
"maxSize": 1000,
"saveHistory": true,
"sensitivePatterns": []
}
}
It is important to note that the provider cannot use openai; it must strictly use zhipuai. The name must also strictly be zhipuai, otherwise, a 404 or 401 error may occur. The envKey means the name of the environment variable to read. It does not actually require you to input the API here. If you configure ZHIPUAI_API_KEY, it will read ZHIPUAI_API_KEY from the environment variables as the API for that provider. This design is meant to switch between different vendors' models. We only use Zhipuai's model, so keeping OPENAI_API_KEY is also acceptable.
Using in the Project#
Since Codex reads environment variables at startup, as long as you can correctly output the key using echo $OPENAI_API_KEY, it can be used correctly. Codex will also read variables from .env, so there are many ways to configure it. The following introduces the mainstream methods.
1. Current Session#
This method only takes effect in the current command line session. When you close the terminal or start a new terminal session, this variable will become invalid.
How to operate
On Linux or macOS, you can use the export
command:
export OPENAI_API_KEY='your_key'
On Windows, you can use the set
command:
set OPENAI_API_KEY='your_key'
Applicable scope
- Temporary testing and debugging: This method is most convenient when you just want to quickly test a script or command in the current terminal session without wanting to permanently save the key.
- Security considerations: If your device is shared, or you do not want the key to be stored in a file for a long time, this method can prevent key leakage.
2. .bashrc
or .zshrc
#
.bashrc
is the configuration file for the Bash shell, and .zshrc
is the configuration file for the Zsh shell. These files are automatically executed every time a new terminal session is opened. Adding the key to these files ensures that this environment variable is automatically loaded every time the terminal starts.
How to operate
Open the .bashrc
or .zshrc
file with a text editor (like nano
or vim
), and add a line at the end of the file:
export OPENAI_API_KEY='your_key'
After saving and exiting, run source ~/.bashrc
or source ~/.zshrc
to take effect immediately, or simply close and reopen the terminal.
Applicable scope
- Personal development environment: If you are the only user of the device and want to use this key in all terminal sessions, this method is very convenient.
- Long-term use: When you need to frequently use tools that depend on this key, setting it once can make it permanent, saving you the trouble of entering it manually each time.
3. .env
File#
The .env
file is a common format for storing environment variables for a project. Many tools and frameworks (including Codex) support automatically loading environment variables from the .env
file. This method is usually bound to the project directory.
How to operate
Create a file named .env
in your project root directory, and add the following content:
OPENAI_API_KEY='your_key'
Note that there are usually no spaces around the =
.
Applicable scope
- Project-specific configuration: When your key is only used for a specific project, placing the
.env
file in the project directory can maintain the independence of the configuration and avoid conflicts with other projects or global environment variables. - Team collaboration: The
.env
file can serve as a template, making it easy for team members to configure their own keys. For security, it is usually added to.gitignore
to prevent the key from being uploaded to the Git repository. - Framework and library support: Many modern development frameworks and libraries (such as Next.js, React, and Python's
dotenv
library) natively support reading.env
files.
Best Practices:
- If you just want to quickly test something, using the current session method is the simplest.
- If you frequently use Codex on a personal computer and do not want to set it every time, adding the key to
.bashrc
is the most suitable. - If you are working on a specific project and want the configuration to be project-bound, it is recommended to use the
.env
file, which is a safer and more universal approach.