agentenv 是做什么的?
agentenv 读取一个本地的 TOML 配置文件,该文件保存普通值和凭据的引用。凭据值存在于环境变量、平台凭据存储或外部命令中——绝不在文件中。CLI 读取值、以保留格式的验证方式编辑文件,并将选定值注入临时环境来启动目标进程。
在使用前,先用 command -v agentenv 确认 CLI 可用。如果缺失,请直接说明并停止;不要通过直接读取配置文件来重构其行为。
硬性规则
- 绝不打印、记录、持久化或汇总已解析的凭据值。不要使用
agentenv run启动一个会暴露自身环境的目标——包括env、printenv、set、sh -c 'echo $VAR'或将环境写入文件等行为均属违规。 - 绝不将秘密值写入配置文件。
set用于普通值;credential add仅写入定义;credential set是存储值的唯一路径,它存储在平台凭据存储中,而非文件。 - 如果配置文件、条目、字段或凭据缺失,请明确报告。不要猜测字段名、静默切换配置文件或替换为其他凭据。
- 通过 CLI 读取配置,而不要直接打开 TOML 文件,这样才能应用配置文件选择、凭据间接引用和验证。
- 在
credential fill将值写入浏览器字段后,不要读取该字段、评估其值或截取显示它的屏幕截图。填充结果是你唯一可以报告的内容。
读取配置
从上到下执行;跳过本次会话中已完成的步骤。
agentenv project status --json— 发现最近的项目文件及其信任状态,然后再读取依赖于配置文件的信息。即使退出码为5或6,其报告也会写入标准输出;退出码2时标准输出为空。agentenv list --json— 发现配置文件和条目。agentenv list --profiles列出配置文件名称但不选择任何一个。agentenv show <entry> --json— 在使用前检查不熟悉的条目。凭据字段显示为reference成员(credential://<name>或credential://<name>?as=<ENV>),绝不显示值。agentenv get <path>— 读取一个普通标量。对于数组或表,使用--json。读取凭据字段会返回引用字符串,而不是秘密。agentenv find <needle> --json— 搜索条目名称、字段名称、描述和字符串值,用于你不知配置项位置时。添加--all-profiles可搜索所有配置文件。
路径是所选配置文件中点分隔的字段段,例如 llm.model。如果段包含标点或空格需要加引号:servers."my host".port。配置文件不属于路径的一部分;通过 --profile <NAME> 选择它(优先级顺序:--profile,然后 AGENTENV_PROFILE,然后是受信任的项目文件固定配置,最后是文件中的 default_profile)。这适用于读取、run、set 和 unset。--create-profile 需要显式的 --profile,且绝不使用固定配置。
项目级作用域配置
agentenv 从工作目录向文件系统根目录遍历时,发现最近的常规 .agentenv.toml 文件。该文件具有封闭的、仅选择型的模式:version = 1,可选的非空 profile,以及可选的 [requires.<entry>] 表(带非空 reason 和可选的、非空条目级 fields)。其大小限制为 64 KiB,且不能包含值、凭据定义、inject 表或 credential:// 字符串。
项目文件在内容被精确批准前是惰性的。使用 agentenv project status、agentenv project allow 和 agentenv project revoke 来检查、批准和撤销批准。批准保存在用户状态目录中,即仓库外部;编辑文件会使其再次变为不受信任状态。不受信任的文件不影响除一条标准错误通知外的任何普通命令。
对于 project 组之外的命令,使用 --no-project 或非空的 AGENTENV_NO_PROJECT 来绕过文件发现。该绕过绝不适用于 project status、project allow 或 project revoke,这些命令始终发现最近的文件。
project status --json 特意将其报告写入标准输出,当项目状态不可用、无效或不受信任时退出码为 5,当要求不满足或无法检查时退出码为 6。这是对失败 JSON 时空标准输出规则的例外。退出码 2 涵盖配置错误,包括项目文件验证错误,并且此命令的标准输出为空。
运行需要凭据的命令
使用 run 加一个或多个 --with <entry> 标志,目标放在 -- 之后:
agentenv run --with llm -- llm-client request
agentenv run --with llm --with kubernetes -- deploy-tool sync
每个 --with 条目贡献其凭据引用及其 inject 表(该表将环境名称映射到该条目的普通字段)。凭据以其 inject_as 名称注入,除非引用带有 ?as=<ENV> 覆盖。要了解目标将接收哪些环境名称,请从 agentenv credential list --json 读取 inject_as,并从 agentenv show <entry> --json 读取 inject 表和 reference 成员。
目标的 stdin/stdout/stderr 会原样传递,且其退出状态被返回。冲突的注入(两个来源指向一个环境名称)会在任何解析或启动之前以退出码 4 中止。
添加 --pure 以使用精心裁剪的最小环境启动目标:固定的平台基础(PATH、HOME、区域设置、AGENTENV_* 等进程关键名称),加上通过可重复的 --keep <NAME> 显式携带的变量,再加上注入——除此之外不来自调用 shell 的任何内容。如果父进程中某个保留名称未设置,会在标准错误上报告,然后运行继续。--pure 仅过滤目标的环境;它不是沙箱,目标内部的嵌套 agentenv 调用仍解析相同的配置。凭据解析不受 --pure 影响:command 提供器的子进程保留完整的父环境。
写入配置
当用户要求记录配置时使用这些:
agentenv init # 创建配置文件;拒绝覆盖
agentenv set <path> <value> # 写入一个值;创建中间表
agentenv set <path> <value> --type int|float|bool|json
agentenv set llm.model gpt-5 --description "默认 LLM。" # 同时创建条目
agentenv set <path> <value> --profile dev --create-profile "Dev 配置文件。"
agentenv unset <path> # 移除一个字段或表
每个条目都需要一个描述;创建新的顶层条目需要在同一条 set 命令中使用 --description。未知配置文件会报错,除非你为显式的 --profile 传递了 --create-profile。每次写入都会先验证整个文件,如果结果无效则拒绝,因此被拒绝的写入会使文件字节完全相同——报告诊断信息,而不是盲目重试变体。
验证拒绝在字符串字段(名称或后缀为 token、password、secret、api_key 或 private_key)中使用明文值:此类字段必须包含 credential:// 引用。当用户交给你一个秘密要保存时,应将其定义并存储为凭据(下一节),然后引用它。
管理凭据
agentenv credential list --json # 定义 + 浅层状态;不解析任何内容
agentenv credential check <name> # 解析一个凭据;仅报告可用性
agentenv credential add <name> --description "<文本>" --provider env \
--env-var <NAME> --inject-as <ENV>
agentenv credential add <name> --description "<文本>" --provider keychain \
--service <服务> --account <账户> --inject-as <ENV>
agentenv credential add <name> --description "<文本>" --provider command \
--argv <参数> [--argv <参数> ...] --inject-as <ENV>
agentenv credential set <name> --input dialog --json # 打开本地输入窗口;等待其结果
新凭据的顺序:先用 credential add 添加定义,然后对于 keychain 提供器使用 credential set 存储值,最后在条目字段中引用为 credential://<name>。环境变量和命令凭据从其外部系统获取值;credential set 不适用于它们。
对于本地钥匙串输入,启动 credential set <name> --input dialog --json 而不带 PTY。告知用户在本地窗口中输入值并保存。保持命令运行并等待其完成,包括跨工具会话的等待;打开的窗口不是已完成的保存。绝不要检查、捕获、读取或自动化活动输入窗口或剪贴板。用户在那里输入并检查值,命令仅返回完成元数据。
仅在退出码 0 且 JSON 返回 status: "stored" 时继续依赖的任务。status: "cancelled" 表示输入在未确认保存的情况下结束;报告它并停止依赖的操作。status: "failed" 包含非秘密的 reason;报告诊断信息。store-unconfirmed 表示可能已发生写入,因此不要声称先前的值未更改或自动重试。启动/配置错误可能在 JSON 发出前退出;将非零退出或缺失结果视为失败。正在进行的保存会在命令返回前完成;即使用户在该写入期间请求关闭,已确认的写入也会报告 stored。
对话框需要运行 agentenv 的机器上有图形会话。在远程或无头主机上,解释该限制,并让用户在该主机的终端中自行运行 agentenv credential set <name> --input terminal,然后确认完成。不要用 Agent 拥有的 PTY 或 stdin 管道替代。绝不要在聊天中请求值,或将其放置在 argv、环境变量、命令管道或文件中。终端输入支持本地显示切换,因此其屏幕输出必须保持在 Agent 工具之外。
优先使用 keychain 或 command 提供器进行本地使用;env 会将值暴露给继承环境的每个进程,适用于 CI。
Docker Compose 配对
将非秘密设置保留在 .env 中。仅将凭据注入到需要它们的进程,然后让 Compose 接收注入的变量:
agentenv run --with llm -- docker compose up
services:
app:
image: alpine:3.20
environment:
- OPENAI_API_KEY
Compose 也支持 ${OPENAI_API_KEY} 插值。不要使用包含秘密的 env_file:;它会将凭据持久化到文件中。
将凭据填入浏览器字段
当你驱动的页面需要在一个输入字段中使用存储的凭据时,使用 credential fill。它通过浏览器的调试协议写入值;你继续使用自己的浏览器工具进行导航和提交。
agentenv credential fill --capabilities --json
agentenv credential fill <name> --backend cdp --endpoint http://127.0.0.1:<port> \
--page-url <确切页面 URL> --selector '<目标输入字段的 CSS 选择器>' --json
步骤:
- 确认
--capabilities列出cdp后端可用。你的浏览器必须暴露一个回环 Chrome DevTools 协议端点(使用--remote-debugging-port和非默认--user-data-dir启动的 Chromium,或你的浏览器工具已使用的端点)。如果没有,请说明;不要启动浏览器或粘贴值。 - 使用你的浏览器工具导航到页面,然后传递页面的确切 URL 和一个仅匹配目标输入字段的 CSS 选择器。当 URL 携带易变的查询参数时添加
--page-match origin-path;对于通往事发字段的每个 iframe 添加--frame-selector;如果同一 URL 在多个上下文中打开则添加--context-index。 - 关闭该选项卡的 DevTools,在填充期间保持追踪、屏幕录制、HAR 和视频录制关闭;agentenv 仅因打开的 DevTools 窗口失败,因为其他记录器无法被检测到。
- 运行命令。成功仅打印
{"version":1,"backend":"cdp","effect":"field-filled"};字段的先前内容已被替换,页面收到了正常的输入事件。继续使用你自己的工具提交。
只有允许 environment 用法的凭据才能被填充;值必须是单行,最多 8,192 字节,不含控制字符、行分隔符或双向控制字符(否则为 value-unsupported)。命令提供器在没有终端的情况下运行,其尾随的一个换行符会被剥离;空值、NUL 或非 UTF-8 提供器输出被视为凭据错误(退出码 4)。整个操作(包括首次访问时的钥匙串授权对话框)在 --timeout-ms 下运行(默认 30,000);当用户需要点击通过此类对话框时请提高超时。credential fill 不会验证字段、提交表单或登录;报告效果,而不是你未观察到的成功。
失败原因在标准错误上(credential-fill: <原因>: <消息>)。退出码 8,未发生更改:backend-unavailable、permission、connect-failed、version-unsupported、recording-conflict、context-absent、page-absent、page-ambiguous、frame-absent、frame-ambiguous、frame-invalid、target-absent、target-ambiguous、target-hidden、target-disabled、target-readonly、target-unfillable、target-changed、value-unsupported、timeout、cancelled。退出码 11,字段可能含有该值:timeout、cancelled 或 delivery-failed(在值已发送后),以及 cleanup-unconfirmed(在值已交付后)。
特权执行
当请求使用配置的 sudo-target 时,请在计划、检查、执行、创建或轮换该目标之前阅读 references/sudo-execution.md。