1. 第一次跑 Gemini CLI,为什么配置总是对不上
很多人第一次装完 Gemini CLI,敲下gemini之后遇到的不是「模型开始回答」,而是一连串让人摸不着头脑的现象:明明在.env里写了GEMINI_API_KEY,CLI 却提示没有认证;在settings.json里改了主题,重启后还是老样子;命令行加了--model,结果会话里用的还是默认模型。这些问题的根源,几乎都指向同一件事——Gemini CLI 的配置是有层级的,不同来源的配置会互相覆盖。
Gemini CLI 的配置体系可以类比成「洋葱模型」。最里面是程序硬编码的默认值,往外依次是用户设置文件、项目设置文件、系统设置文件、环境变量,最外层是命令行参数。越靠外层,优先级越高,越能覆盖内层。你写的东西没生效,大概率是被更外层的东西盖掉了,或者你写错了层。
这篇指南面向第一次上手 Gemini CLI 的开发者,把三件事讲透:settings.json里到底有哪些字段值得配、环境变量的加载顺序和优先级怎么算、命令行参数如何临时覆盖前两者。每一节都给出可以直接复制的配置片段和逐项验证命令,跑一遍就能确认自己的配置到底生效在哪一层。如果你正在用 Gemini CLI 做日常编码,或者准备把它接进团队的项目流程,这套配置逻辑值得先花二十分钟理清楚,后面能省下大量「为什么又不生效」的排查时间。
需要先说明的是,Gemini CLI 默认走的是官方端点。如果你希望用统一的入口管理多个模型的调用、把 API Key 集中托管,可以把它指向兼容的 API 网关。本文的配置示例会以标准字段为主,你替换 Base URL 和 Key 即可,字段结构完全一致。
2. settings.json 字段全解析与可复制配置片段
settings.json是 Gemini CLI 持久化配置的核心。它有三个位置,优先级从低到高分别是:用户级~/.gemini/settings.json、项目级<项目根>/.gemini/settings.json、系统级/etc/gemini-cli/settings.json(Linux)、C:\ProgramData\gemini-cli\settings.json(Windows)、/Library/Application Support/GeminiCli/settings.json(macOS)。系统级路径可以用GEMINI_CLI_SYSTEM_SETTINGS_PATH环境变量覆盖。
一个容易踩的坑:项目级会覆盖用户级,系统级会覆盖用户级和项目级。所以如果你在用户级配了theme,项目里又配了另一个,进项目后看到的是项目里的那个。排查「配置不生效」时,第一件事就是确认当前生效的是哪一层。
下面是一份可以直接复制、覆盖大部分常用场景的settings.json。我把它放在项目根目录的.gemini/settings.json,这样只对当前项目生效,不会污染全局。
{ "theme": "GitHub", "contextFileName": ["GEMINI.md", "AGENTS.md"], "fileFiltering": { "respectGitIgnore": true, "enableRecursiveFileSearch": true }, "coreTools": ["ReadFileTool", "GlobTool", "ShellTool(ls)"], "excludeTools": ["ShellTool(rm -rf)"], "autoAccept": false, "vimMode": false, "sandbox": "docker", "checkpointing": { "enabled": true }, "preferredEditor": "vscode", "maxSessionTurns": 30, "summarizeToolOutput": { "run_shell_command": { "tokenBudget": 2000 } }, "excludedProjectEnvVars": ["DEBUG", "DEBUG_MODE", "NODE_ENV"], "includeDirectories": ["../shared-library", "~/common-utils"], "loadMemoryFromIncludeDirectories": true, "chatCompression": { "contextPercentageThreshold": 0.6 }, "showLineNumbers": true, "usageStatisticsEnabled": false, "hideTips": false, "hideBanner": false, "mcpServers": { "myPythonServer": { "command": "python", "args": ["mcp_server.py", "--port", "8080"], "cwd": "./mcp_tools/python", "timeout": 5000, "includeTools": ["safe_tool", "file_reader"] } } }逐项说明几个最值得关注的字段。contextFileName决定 CLI 去读哪个上下文文件,默认是GEMINI.md,你可以改成数组同时接受AGENTS.md,方便和别的工具共用一份指令。fileFiltering.respectGitIgnore设为true时,node_modules/、dist/、.env这些被 git 忽略的文件会自动从@补全和文件发现里排除,避免把一堆无关文件塞进上下文。coreTools是白名单,只把列出的工具给模型;excludeTools是黑名单。注意官方明确提示:excludeTools对run_shell_command的命令限制是基于简单字符串匹配的,容易被绕过,它不是安全机制,真正要限制就用coreTools显式选择。
mcpServers用来接 MCP 服务器。每个服务器可以配command、args、env、cwd、timeout、trust,以及includeTools/excludeTools做工具级白名单和黑名单。当多个服务器暴露同名工具时,CLI 会用服务器别名做前缀,比如serverAlias__实际工具名,避免冲突。excludeTools优先于includeTools,同时出现在两个列表里的工具会被排除。
还有一个很实用的特性:settings.json里的字符串值可以用$VAR_NAME或${VAR_NAME}引用环境变量,加载时自动解析。比如:
{ "mcpServers": { "myDockerServer": { "command": "docker", "args": ["run", "-i", "--rm", "-e", "API_KEY", "ghcr.io/foo/bar"], "env": { "API_KEY": "$MY_API_TOKEN" } } } }这样 Key 就不用硬编码进配置文件,配合环境变量管理更干净。验证配置是否被正确解析,可以用/memory show看当前加载的上下文,或者直接改一个显眼的字段(比如theme)重启 CLI 观察是否变化。
3. 环境变量优先级与 .env 加载顺序实战
环境变量是配置里最灵活、也最容易出问题的一层。Gemini CLI 会自动从.env文件加载环境变量,加载顺序是这样的:先看当前工作目录的.env,没找到就向上逐级搜索父目录,直到项目根(通过.git文件夹识别)或家目录;如果还是没找到,就找~/.env。
这里有个关键细节:部分环境变量会从项目.env里被自动排除,默认是DEBUG和DEBUG_MODE,目的是防止项目里的调试开关干扰 CLI 自身行为。但来自.gemini/.env的环境变量永远不会被排除。你可以通过settings.json里的excludedProjectEnvVars自定义这个排除列表。如果你确实需要为 CLI 单独设置DEBUG,就把它写进.gemini/.env。
常用的环境变量有这么几个。GEMINI_API_KEY是 API Key,可以写在 shell 配置文件(~/.bashrc、~/.zshrc)或.env里。GEMINI_MODEL指定默认模型,会覆盖硬编码默认值。GEMINI_SANDBOX是settings.json里sandbox设置的替代方案,接受true、false、docker、podman或自定义命令字符串。NO_COLOR设为任意值可以禁用所有颜色输出。CLI_TITLE自定义 CLI 标题。
如果你用的是兼容的 API 网关,把 Base URL 和 Key 通过环境变量注入是最省事的做法。下面是一份.gemini/.env示例,注意这个位置的文件不会被排除规则影响:
# .gemini/.env GEMINI_API_KEY=sk-your-key-here GEMINI_MODEL=gemini-2.5-flash GEMINI_SANDBOX=docker NO_COLOR=验证环境变量是否被正确加载,可以这样操作。先确认当前 shell 里有没有这个变量:
echo $GEMINI_API_KEY如果为空,说明 shell 没读到。再确认 CLI 实际用的是哪个模型,启动后看页脚或执行:
gemini --version想看更详细的加载过程,临时开调试:
DEBUG=1 gemini注意这里是在命令行临时注入DEBUG,而不是写进项目.env,因为项目.env里的DEBUG会被排除。如果你希望它长期生效,写进.gemini/.env。
优先级要记牢:环境变量会覆盖用户、项目、系统三层设置文件,但会被命令行参数覆盖。所以当你发现settings.json里的sandbox没生效,先检查是不是GEMINI_SANDBOX环境变量把它盖掉了。反过来,如果你想让某个配置对所有项目生效又不想改文件,环境变量是最快的办法。
4. 命令行参数覆盖关系与逐项验证命令
命令行参数是优先级最高的一层,只对当前这次会话生效,适合做临时覆盖和调试。它的好处是不动任何文件,退出即失效,特别适合「我就想试一下换个模型」这种场景。
常用的参数里,--model(-m)指定本次会话的模型,--prompt(-p)直接传提示并以非交互模式运行,--prompt-interactive(-i)用给定提示启动交互会话。--sandbox(-s)为本次会话启用沙盒,--sandbox-image设置沙盒镜像 URI。--debug(-d)开调试输出。--all-files(-a)递归把当前目录所有文件作为上下文。--yolo自动批准所有工具调用,--approval-mode设置批准模式,可选default、auto_edit、yolo。注意--approval-mode=yolo和--yolo不能同时用,官方建议用前者这个统一的新方式。
--include-directories可以在工作区里加入额外目录,支持多次指定或逗号分隔,最多加 5 个。--extensions(-e)指定本次会话用的扩展,gemini -e none可以禁用所有扩展。--list-extensions(-l)列出所有可用扩展后退出。
下面这组命令可以逐项验证覆盖关系。先看默认模型:
gemini -p "用一句话说明你是什么模型"再用参数临时换模型,观察输出是否变化:
gemini -m gemini-1.5-pro-latest -p "用一句话说明你是什么模型"验证沙盒是否启用,可以跑一个会写文件的命令,看是否被限制在沙盒内:
gemini -s -p "在当前目录创建一个 test.txt 并写入 hello"验证多目录上下文:
gemini --include-directories /path/to/project1,/path/to/project2 -p "列出你能看到的目录"验证批准模式,用auto_edit让编辑类工具自动通过、其他工具仍然询问:
gemini --approval-mode auto_edit如果你要把 CLI 接进兼容网关,命令行也能直接覆盖端点相关配置。比如临时指定模型和 Key:
GEMINI_API_KEY=sk-your-key gemini -m gemini-2.5-flash -p "hello"这里环境变量和命令行参数同时出现,命令行参数优先级更高。实测下来,把「临时调试用命令行、长期配置用 settings.json、敏感信息用环境变量」这三条分开,配置混乱的情况会少很多。
5. 常见报错排查:401、local proxy failed 与 reading choices
配置过程中最耗时间的不是写配置,而是报错之后不知道从哪查。下面按真实报错逐条拆解。
401 Unauthorized / API key not valid。这是最常见的认证类报错,通常有三种原因:Key 没被读到、Key 写错了层、Key 本身无效。排查顺序是先用echo $GEMINI_API_KEY确认 shell 里有没有值;再确认.env文件的位置对不对——项目.env会被向上搜索,但.gemini/.env优先级更高且不受排除规则影响;最后确认 Key 没有多余空格或引号。如果你用的是兼容网关,还要确认 Base URL 和 Key 是配套的,别把 A 家的 Key 配到 B 家的端点上。
local proxy failed / connection refused。这类报错说明 CLI 尝试连接某个本地端点失败了。常见于你配置了自定义端点但服务没起来,或者端口写错。检查settings.json或环境变量里的端点地址,确认服务在监听。如果你在容器或沙盒里跑,还要确认网络可达。注意不要配置任何绕过网络合规要求的方案,走正规的 API 入口即可。
Error reading choices / unexpected token in JSON。这个报错通常出现在 MCP 服务器返回的数据格式不对,或者settings.json本身有语法错误。先用python -m json.tool .gemini/settings.json校验 JSON 合法性,逗号、引号、括号是最容易出错的地方。如果是 MCP 相关,检查服务器的command和args是否能独立跑通,把timeout适当调大。
OAuth / 认证流程卡住。如果你走的是 OAuth 认证,卡在浏览器回调或 token 交换,先确认本地回调端口没被占用,再确认系统时间准确(时间偏差会导致 token 校验失败)。如果反复失败,清掉缓存的凭据重新走一遍流程。
配置不生效的通用排查法。按优先级从高到低问自己四个问题:命令行参数有没有覆盖?环境变量有没有覆盖?项目级settings.json有没有覆盖用户级?系统级有没有覆盖前面所有?用/memory show看上下文加载情况,用DEBUG=1 gemini看详细日志。把每一层的实际值列出来对照,问题基本就定位了。
如果你在配置 MCP 服务器,记得把三件套写全:Base URL、Key、Model ID。缺任何一个都可能导致连接失败或工具不可用。下面是一个 MCP 服务器配置的完整示例,注意env里用$VAR引用环境变量:
{ "mcpServers": { "myServer": { "command": "node", "args": ["mcp_server.js", "--verbose"], "env": { "API_KEY": "$MY_API_TOKEN" }, "timeout": 5000, "trust": false } } }trust设为true会绕过该服务器的所有工具调用确认,生产环境慎用。includeTools和excludeTools用来做工具级过滤,excludeTools优先。
6. 把配置固定下来:从临时调试到长期可用
配置调通之后,下一步是把它固定成可复用的形态。我的做法是分三层管理:敏感信息(Key、端点)放.gemini/.env,不进版本库;项目相关的行为配置(工具白名单、上下文文件、MCP 服务器)放项目级.gemini/settings.json,跟代码一起提交;个人偏好(主题、vim 模式、行号)放用户级~/.gemini/settings.json,不污染项目。
这样团队协作时,新人 clone 下来只需要补一个.gemini/.env填 Key,其余配置直接生效。上下文文件用GEMINI.md写项目规范,比如编码风格、依赖策略、特定文件的注意事项,CLI 会分层加载并拼接成系统提示。用/memory refresh强制重新扫描,用/memory show确认最终拼接结果。
如果你希望把多个模型的调用统一到一个入口管理,把 API Key 集中托管、按项目分配额度,可以把它指向兼容的 API 网关。配置方式和上面完全一致,只是把 Base URL 和 Key 换成网关提供的值。需要的话可以从 API Keys 页面拿到 Key,接入细节看接入文档,想先验证模型效果可以直接在模型对话里试,长期做编码和 Agent 任务的话 Coding Plan 更合适。
最后留一个实用习惯:每次改完配置,用一条最小命令验证,比如gemini -p "ok",确认能正常返回再继续。配置这东西,改一处验一处,比一次性改一堆再排查要快得多。