项目与配置
osdk 将用户默认值、项目声明、环境变量和 CLI 覆盖组合成当前配置。本页给出 项目发现规则、完整可编辑结构、精确合并粒度和信任边界。
配置位置
- 用户配置:
$OSDK_CONFIG_DIR/config.toml;Linux 默认是~/.config/osdk/config.toml。 - 项目配置:
osdk.toml或.osdk.toml。从当前目录向上查找最近一份;同一目录 同时存在时,osdk.toml优先。 .tool-versions:独立向上查找最近一份,只补充项目/用户[tools]尚未声明的键。
osdk config path
osdk config list
osdk config get KEY [-g]
osdk config set KEY VALUE [-g]
osdk config unset KEY [-g]
osdk config migrate [--dry-run] [-g]config path 显示配置目录、用户配置文件和当前发现的项目配置。config list 显示 部分解析结果而非原始 TOML;它不会列出 yes、lang、所有 source 细节等全部字段。
get / set / unset 默认作用于项目配置,-g 才是用户配置——与 git config、 npm config 一致。get 默认返回合并后的生效值(含默认值与环境变量覆盖),-g 只读 用户那一层。
osdk config set jobs 8 # 写入 ./osdk.toml
osdk config set -g jobs 8 # 写入用户配置
osdk config get jobs # 生效值
osdk config unset jobs # 恢复默认可写的是下列标量与列表设置:jobs、offline、yes、verify_signatures、 require_checksums、attestations、prerelease、link_mode、lang、 sources.probe_timeout_ms、shims.include、shims.exclude、shims.expose,以及按 工具限定的 shims.<tool>.{include,exclude,expose}。列表用逗号分隔。工具固定、source 固定和别名不在其中,它们分别由 osdk use、osdk source pin 和 osdk alias 管理。
sources.probe_timeout_ms 写进顶层 [sources] 表,单位毫秒、必须 ≥ 1,默认 1500。 它是每个源一次探测的总预算:模型源探测要在这一份预算内同时发 metadata 请求和一个 有界的 Range 拉取,所以慢网络下 1500 ms 可能把完全可用的本地镜像误判为不可达。此时调 大它,而不是去手改配置文件:
osdk config set -g sources.probe_timeout_ms 4000 # 只放宽源探测,不影响下载本身
osdk config get sources.probe_timeout_msPython 与 npm 各自的探测超时是 [registries.python] / [registries.npm] 下独立的 probe_timeout_ms,当前不在 config set 清单里(那两组列表已在清单中)。
枚举取值与各自类型一致,别名会被规范化后写入(attestations=auto 存为 if-available):
| 设置 | 取值 |
|---|---|
attestations | off、if-available、required |
prerelease | never、if-explicit、allow |
link_mode | auto、hardlink、reflink、copy、symlink |
lang | en、zh |
取值会先解析校验再落盘,非法值不会留下改了一半的文件;unset 会顺带清掉被清空的表头, 不会留下一个空的 [settings]。
写入受管设置会触发信任
config set 写入的键若属于受管键(例如 verify_signatures),会使该 文件需要信任,命令会就地询问,--yes 时自动确认;非交互环境下写入照常成功,但不授予 信任,并提示还需要做什么。写入 jobs、lang 这类安全键不会触发询问。
配置段命名与旧格式迁移
复数顶层段表示具名条目的集合:[tools]、[tasks]、[models]、[skills]、 [sources]、[registries]。单数顶层段表示一个子系统的设置或命名空间:[task] 保存共享 runner 设置,[container] 保存容器设置,[alias.tools] 是别名域下的工具版本 别名,[sys.pkg] 是系统域下的包管理器设置。于是 osdk task 操作 [tasks] 中的一个 任务,而不是要求集合表也改成单数。
旧版四组写法暂时仍可读取,并可一次迁移:
osdk config migrate --dry-run # 预览当前项目
osdk config migrate # 改写当前项目
osdk config migrate --global # 改写用户 config.toml迁移关系是 [aliases] → [alias.tools]、[containers] → [container]、 [task_config] → [task]、[syspkg] → [sys.pkg],以及把临时的 [sys.pkg.packages] 条目扁平到 [sys.pkg]。命令保留注释及其他段;如果一组 新旧写法同时存在,它会拒绝猜测合并顺序并保持文件不变。osdk 的写命令只生成新布局。
项目版本发现
活动版本的来源类型优先级如下;每一类内部再从当前目录向祖先查找:
osdk.toml/.osdk.toml的[tools];.tool-versions;- backend 的生态版本文件;
- Node 的
package.json元数据; - 用户配置的
[tools]。
这意味着较远祖先的 osdk.toml 也会胜过较近目录的 .nvmrc。
| backend | 生态版本文件 |
|---|---|
| Node.js | .nvmrc、.node-version,之后 package.json#engines.node、devEngines.runtime |
| Python | .python-version |
| Java | .java-version、.sdkmanrc |
| Go | go.mod 的 go 指令、.go-version |
| Rust | rust-toolchain.toml、rust-toolchain |
| Maven / Gradle / Kotlin | .mvn-version、.gradle-version、.kotlin-version |
| Bun / Deno | .bun-version、.dvmrc |
普通单值文件读取第一个非空、非注释行,并去掉开头的 v。Rust TOML 读取 [toolchain].channel。Node 的 npm semver range 会解析到最高匹配稳定版;无效 range 会明确失败。
无参数生命周期命令的当前边界
current、shim 和 shell hook 会为每个 backend 读取上述生态文件。但无参数 lock、upgrade 以及没有可用 lock 时的 install,目前主要枚举合并后的 [tools]/.tool-versions,再额外发现 packageManager 和 Node。仅存在 .python-version、.java-version、go.mod、rust-toolchain.toml 等文件时, 这些非 Node 工具不会自动加入无参数生命周期命令;请在 [tools] 中声明或显式传参。
最小项目配置
[tools]
node = "20"
python = "3.12"
go = "1.22"
rust = "1.91.1"
pnpm = "10"
"npm:prettier" = "3"
"cargo:ripgrep" = { version = "14.1", features = ["pcre2"], locked = true }
"go:golang.org/x/tools/gopls" = { version = "0.20", tags = ["netgo"] }
"cargo:cargo-release" = { version = "0.25", lazy = true }
[alias.tools.node]
maintenance = "20"
default = "maintenance"osdk use node@20 会修改最近的项目配置;没有项目配置时在当前目录创建 osdk.toml,并把实际安装结果及注入的 runtime 依赖写入同目录 osdk.lock。两份文件作为 一个元数据事务更新,lock 写入失败会恢复配置。当前平台尚无 lock 区段时,无参数 install/lock 会继承其他平台一致且仍满足声明的版本,但重新解析当前平台的 artifact 与 checksum。osdk use --global node@20 修改用户配置, 不触碰当前项目 lock。 对于 npm:<package>,本地 use 会先查找最近的 package.json;下一节说明其项目感知 行为。 每个 cargo:<crate-or-https-url> 条目都必须对应一个精确、显式请求或配置的 rust 条目;浮动和本地链接的 Rust toolchain 会被拒绝。详见 Cargo 开发工具。 每个 go:<module-or-command-path> 条目也必须对应一个受管 go 选择。osdk 会先解析该 runtime,再把精确版本绑定到工具;详见 Go 开发工具。
在真实项目中使用 npm 工具
在 Node 项目下的任意目录执行以下命令,会把包加入最近 package.json 所在的项目:
osdk use npm:prettier@3包会保留原有的 dependencies、devDependencies、optionalDependencies 或 peerDependencies 区段;新包默认加入 devDependencies。osdk 依次参考项目声明的 packageManager、现有 lock 的归属安装器,最后使用配置的默认值,也可以用 -o installer=npm|pnpm 显式指定。某个安装器失败后不会换另一个安装器重试。祖先目录中没有 package.json 时,该命令保留原有的 osdk 隔离安装与 shim 行为。
项目感知的 use 会更新原生 package.json 与包管理器 lock,再把精确 Node 选择和结构化 npm 条目写入 osdk.toml。它还会写一份紧凑的 osdk.lock,记录 installer、scope、Node 和原生 lock 身份。该 metadata 不包含传递依赖图;原生包管理器 lock 仍是依赖图来源。 项目中应同时保留这四类文件。安装器与激活细节见 npm 开发工具。
为支持 Shell 激活,use 还会在 .osdk/npm-bin/ 下生成本地派生状态。只有已配置 npm 工具的筛选 launcher 会被激活;整个 node_modules/.bin 永远不会加入 PATH。建议把 /.osdk/npm-bin/ 加入 package 根目录的忽略文件;若仓库根包含嵌套 package,则可在 仓库根使用 **/.osdk/npm-bin/,同时继续提交上述四类事实来源文件。
控制哪些命令进 PATH
一个安装往往带来比你想要的更多可执行文件:conda prefix 装着整个依赖闭包,Android NDK 有 172 个可执行文件。[settings.shims] 决定其中哪些生成 shim、进入 PATH。
不生成 shim 不等于没装:文件仍在 install 目录里,osdk exec 和激活的 shell 里照样 可用。
三个列表
| 设置 | 语义 | 作用域 |
|---|---|---|
include | 白名单:非空时,未列出的名字一律不生成 | 全体工具 |
expose | 增量:额外放行默认被挡下的名字,不影响其他任何工具 | 全体工具 |
exclude | 排除,最后生效,可修剪前两者的结果 | 全体工具 |
判定顺序:include 决定候选集合 → expose 追加 → exclude 最后剪除。
expose 会盖过别处的窄 include。两者命中同一个名字时,一边说「要这个」、一边说 「不在名单里」,让 include 赢就等于显式要求被静默丢弃。
include 是全局白名单,不是「加回一个」
这是最容易出错的一点:
# 危险:想取回 make,结果 cargo / go / node 全部失去 shim
osdk config set shims.include "conda:m2-base:make"include 一旦非空就成为对全体工具生效的白名单,列出 1 个名字等于声明「其余都不 要」。实测这一条命令把 646 个 shim 变成了 0。
要取回被挡下的命令,用 expose:
# 安全:只加不减
osdk config set shims.expose "conda:m2-base:make"include 本身没有问题,它表达的是「只要这几个」——当你真的想大幅收窄时才用它,并且 优先用下面的按工具形式。
按工具覆盖
三个列表都可以限定到单个工具,键的形式是 shims.<tool>.<字段>:
osdk config set shims.conda:m2-base.expose "make,sh,bash,tr,awk"
osdk config set shims.android-ndk.include "clang,clang++,llvm-strip"
osdk config set shims.conda:m2-base.exclude "ls,test"
osdk config get shims.conda:m2-base.expose
osdk config unset shims.conda:m2-base.expose写进 TOML 的形态:
[settings.shims.tools."conda:m2-base"]
expose = ["make", "sh", "bash", "tr", "awk"]按工具限定让 include 变得安全:作用域收窄之后,android-ndk 下的 include 只能 影响 NDK 自己的命令,不可能收走 cargo。需要收窄某个工具时,优先用这个形式,而不 是全局 include。
覆盖是逐字段的:写了哪个字段就覆盖哪个,没写的继承全局列表。因此「只调 expose」 不会顺手清掉全局的 exclude。config get 对未指定的字段显示 inherit,以区别于显式 设成空列表。
工具 key 按 backend id 精确匹配,不支持通配;跨工具的模式请用全局列表。
模式语法
三个列表的元素都是模式,规则一致:
| 写法 | 匹配对象 | 例 |
|---|---|---|
不含 : | 命令名 | make、clang* |
含 : | <backend>:<命令名> | conda:m2-base:make、android-ndk:* |
*匹配任意长度,?匹配单个字符;- 大小写不敏感(Windows 可执行文件本就如此);
- 匹配整个名字,不是子串。
在按工具的列表里,两种写法都可用,但既然作用域已经限定,直接写命令名更清楚。
元包:默认一个 shim 都没有
conda:m2-base 这类元包自身不安装任何命令——prefix 里的东西都属于它拉进来的包,所以 默认不生成任何 shim。这是刻意的:否则 msys 版的 ls、test、sort 会盖住 Windows 同名命令。
需要其中几个时用 expose 点名:
osdk config set shims.conda:m2-base.expose "make,sh,bash,tr,awk,grep,printf"
osdk reshim只暴露真正用到的命令,未列出的不会干扰系统命令。
改完要 reshim
config set 只改配置,不动磁盘上的 shim。改完执行:
osdk reshimosdk where --bins <tool> 可以核对结果,它分别列出 published(生成 shim)与 withheld(挡下)两组。
这些设置不需要信任
settings.shims 只决定哪些命令生成 shim,既不执行代码也不改变下载来源,因此写进项目 osdk.toml 不会要求信任。需要信任的键见哪些键需要信任。
完整配置参考
以下示例覆盖当前可编辑 schema。[tools] 的值既可以是版本字符串,也可以是带 backend 选项的结构化对象;包含 :、@ 或 / 的 key 要用引号。省略的字段使用 该文件层反序列化时的默认值;下一节解释这为何不等于继承低优先级层。
[settings]
link_mode = "auto" # auto|hardlink|reflink|copy|symlink
jobs = 8 # 默认 min(可用并行数, 8),无法检测时 4
yes = false
verify_signatures = true
require_checksums = false
attestations = "off" # off|if-available|required
offline = false
lang = "zh" # 可省略;en|zh
prerelease = "if-explicit" # never|if-explicit|allow
[settings.shims]
include = [] # 全局白名单;非空时未列出者一律不生成 shim
exclude = [] # 排除;最后生效
expose = [] # 增量放行;只加不减
# 按工具覆盖,key 是 backend id。未写的字段继承上面的全局列表。
[settings.shims.tools."conda:m2-base"]
expose = ["make", "sh", "tr"]
[settings.node]
corepack = false
[settings.python]
catalog_url = "/approved/python-catalog.json" # HTTP(S) 或本地路径,可省略
catalog_sha256 = "0123456789abcdef..." # 使用 catalog_url 时必填
[settings.java]
catalog_url = "https://mirror.example/disco/v3.0/packages" # 可省略
[sources]
selection = "auto" # auto|pinned|ordered
probe_timeout_ms = 1500
cache_ttl = "6h" # s/sec/secs, m/min/mins, h/hr/hrs, d/day/days
[sources.node]
pin = "official" # 可省略
disable = ["tuna"] # 可省略
env = false # 仅模型 provider 的全局 shell adapter 使用
env_force = false
[[sources.node.custom]]
id = "corp"
kind = "custom" # official|mirror|custom
download_url = "https://mirror.example/sdk/"
index_url = "https://mirror.example/sdk/index.json" # 可省略
headers = [["Header-Name", "value"]] # 可省略
forward_credentials = false
priority = 0
enabled = true
[registries.npm]
urls = [
"https://registry.npmmirror.com/",
"https://registry.npmjs.org/",
]
probe_timeout_ms = 1500
[container]
runtime = "auto" # auto|docker|containerd
builder = "auto" # auto 或经过验证的 Buildx 构建器名称
platform = "runtime" # runtime 或 OS/ARCH[/VARIANT]
probe_timeout_ms = 1500
[tools]
node = "20"
python = "3.12"
pnpm = "10"
"npm:prettier" = "3"
[tools."npm:@scope/native-tool"]
version = "1.2.3"
lazy = true # 裸 install 默认跳过,除非带 --include-lazy
installer = "npm" # auto|npm|pnpm;隐式默认值为 auto
allow_builds = ["@scope/native-tool", "esbuild"]
[tools."npm:only-on-windows-arm"]
version = "1.0.0"
when = { os = "windows", arch = "arm64" } # 单值或数组;两个维度都要命中
[tools.node]
version = "20"
arch = "arm64" # backend 选项:下载哪个产物(语义不变)
when = { os = "windows" } # 过滤:这条在哪生效;两者可共存
[tools."http:https://downloads.example.com/acme-{version}.tar.gz"]
version = "1.2.3"
sha256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
kind = "tar.gz"
strip-components = "1"
bin = "bin/acme"
rename = "acme"
[alias.tools.node]
default = "20"Registry URL 会去重并补尾部 /。只允许带 host 的 HTTP(S) URL;credentials、 query 和 fragment 都会被拒绝。来源的选择语义见下载源与供应链安全, Registry 的选择语义见JavaScript 包管理器。 结构化工具对象要求 version,其他 option 可以是字符串、布尔值或字符串数组;数组 传给 backend 时会转成逗号分隔值。lazy 是 osdk 元数据而非 backend option:裸 install 会跳过它,除非带 --include-lazy;显式点名仍会安装。installer 选择 npm 工具安装器。allow_builds 控制 隔离与全局安装;项目感知的 use 始终禁用 lifecycle scripts。完整安全边界见 npm 开发工具。 http: 条目要求精确语义化版本,并为严格 HTTPS {version} 模板提供 SHA-256; 文件/归档布局与离线重放见直接 HTTPS 制品。
when 是平台过滤,不是 backend option:它在进入 backend 之前就被摘除,不匹配的 条目在合并后的配置里根本不存在,因此求解、lock、shim、激活都不会看到它。维度内是 「任一命中」,两个维度之间是「都要命中」。
为什么嵌套在 when 下,而不是直接写 os / arch
os、arch、libc 在 github: 和 node 上已经是 backend 选项,语义是「下载哪个 平台的产物」——跨架构锁定正依赖它。早先一版把平铺的 arch 读作过滤,结果 [tools.node] arch = "arm64" 在 x64 主机上让 node 整条消失,且没有任何提示。嵌套把 两套词汇分开,也给将来的 libc 留了位置。
when 内只接受已实现的维度,写入未实现的(如 libc)会明确报错,而不是被忽略后把 过滤悄悄放宽成「任意 libc」。无法识别的取值同样直接报错,而不是默默永不匹配。显式 点名一个被过滤的工具会报错并说明限制,osdk current 也会把它连同原因一起列出—— 一个写在配置里却不出现的工具,否则看起来像配置写错了。
字符串简写形式(fd = "npm:fd@10")不支持过滤,需要时改写成上面的表形式。
精确的覆盖与合并语义
总体优先级为:
CLI > OSDK_* 环境变量 > 最近项目配置 > 用户配置 > 内置默认值文件之间不是统一的“逐字段覆盖”:
| 配置区域 | 高优先级文件的行为 |
|---|---|
[settings] | 整段替换;只写一个字段时,其他设置回到 Settings 内置默认值,而不是继承用户文件 |
[sources] 顶层 | selection、probe_timeout_ms、cache_ttl 整段替换;遗漏项回到默认值 |
[sources.<tool>] | 按工具键合并;同一工具的 pin、disable、custom 等整项由高优先级层替换 |
模型 env/env_force | 项目配置不能改变;始终保留用户全局值,避免项目静默改写 shell 凭据环境 |
[registries] | 整段替换;项目 [registries.npm] 不与用户 URL 列表合并 |
[container] | 整段替换;省略的运行时、构建器、平台、超时和 Registry 策略字段使用内置默认值 |
[tools] | 按工具键合并;高优先级同名键覆盖 |
[alias.tools.<tool>] | 按工具和别名键合并;高优先级同名别名覆盖 |
.tool-versions | 只填补合并后 [tools] 中缺失的工具 |
例如,用户配置启用了 verify_signatures = false,而项目仅写:
[settings]
jobs = 2项目层会创建一整套默认 Settings 再设 jobs = 2,因此最终 verify_signatures 回到默认 true。若希望保留非默认组合,应在高优先级的 [settings] 中完整声明。
环境变量覆盖
| 环境变量 | 对应配置 |
|---|---|
OSDK_LINK_MODE | settings.link_mode |
OSDK_JOBS | settings.jobs |
OSDK_YES | settings.yes |
OSDK_VERIFY_SIGNATURES | settings.verify_signatures |
OSDK_REQUIRE_CHECKSUMS | settings.require_checksums |
OSDK_ATTESTATIONS | settings.attestations |
OSDK_OFFLINE | settings.offline |
OSDK_PRERELEASE | settings.prerelease |
OSDK_PYTHON_CATALOG_URL | settings.python.catalog_url |
OSDK_PYTHON_CATALOG_SHA256 | settings.python.catalog_sha256 |
OSDK_JAVA_CATALOG_URL | settings.java.catalog_url |
OSDK_SELECTION | sources.selection;未知值当前回退为 auto |
OSDK_CONTAINER_RUNTIME | container.runtime;`auto |
OSDK_CONTAINER_BUILDER | container.builder;auto 或经过验证的 Buildx 构建器名称 |
OSDK_CONTAINER_PLATFORM | container.platform;runtime 或 OS/ARCH[/VARIANT] |
OSDK_LANG | 输出语言,优先于配置与 locale |
目录变量见存储、Shell 与扩展。
项目配置信任
osdk [--yes] trust [PATH]
osdk trust list
osdk untrust [PATH]PATH 可为配置文件或目录;目录会从该处向上找最近项目配置。
哪些键需要信任
判据仍然按键,但门是按命令的作用域开的:一个命令只会被它实际能碰到、 能让其生效的键挡住。信任的本质是「未经审阅的配置不得做事」,所以从不做事的命令 那里什么也收不到。
四类作用域及其检查的键:
| 作用域 | 到达它的命令 | 检查的键 |
|---|---|---|
| 安装 | install、use、upgrade、lock、self upgrade;以及所选 task 需要获取缺失 tools 时的 run | settings 的校验开关与 catalog、sources、registries、tools.allow_builds |
| 依赖 | bare install、run/exec(默认)、显式 deps | sources、registries、[deps] 内的 index/registry/build/自定义 run |
| 运行任务 | run(非 --dry-run) | [task]:其 shell 决定每个任务由谁解释 |
| 系统包 | pkg apply | [sys.pkg] 中在本机适用的条目 |
| 容器 | 任何 container 操作 | [container] 的 runtime/builder/registries |
受管键与各自的原因:
| 键 | 原因 |
|---|---|
[sources]、[registries] | 改变子进程的下载目的地 |
settings 的 verify_signatures、require_checksums、attestations | 关掉或降级对产物的校验 |
settings 的 python、java | 二者的 catalog_url 决定安装哪份运行时字节 |
[tools] 中显式打开的 allow_builds | 唯一让 npm 生命周期脚本得以运行的开关 |
[deps.<p>] 的 index/registry/自定义 run/build 开关 | 重定向依赖来源或执行任意命令 |
[sys.pkg](仅 pkg apply) | 装到系统全局、可能提权,且不受 osdk.lock 覆盖 |
两个值得注意的收紧:
[sys.pkg]只挡pkg apply,且只在有适用条目时。 一个所有包都声明为os = "linux"的配置,在 Mac 上不挡任何命令;管理器在本机不存在的条目(如 Windows 上的apt:条目)同样不挡——在这里永远不会执行的包不需要审阅。pkg status/plan/doctor本来就只读,同样不要求信任。[models]在任何命令里都不要求信任, 包括写了endpoint的条目。模型 字节是内容,osdk 从不执行它们;下载仍按锁定摘要校验,换端点无法把内容拉取 变成代码执行。
声明安装哪些工具或包本身不需要信任,[tools]、[alias.tools] 都不需要,其中的 npm:、github:、http:、go:、cargo:、pypi:、conda: 条目也不需要:npm 安装默认 传 --ignore-scripts,http: 制品缺 sha256 直接拒绝,go: 以 CGO_ENABLED=0 构建。 这和在 package.json 里加一行依赖是同一件事——新增包、升降版本都不会要求重新信任。
settings.node(只有 corepack 一个 bool)和 settings 的 npm 选择( default_installer,在 npm 与 pnpm 间二选一,且是最低优先级兜底)同样不需要信任。
两处 fail-closed:未知的顶层 section(对会动手的命令)和未登记的 settings 键都判为需要信任。本 build 无法解释的键,不会因为不认识而放行。
被拒绝时 osdk 会逐条列出命中的键及各自原因,而不是只说"未受信任"。
拦截范围:命令作用域决定一切
- 只读查看:
list、current、where、doctor、completions、config get/config list,以及task list/task info/task deps。它们只汇报、展示状态, 不安装、不下载、不执行任何东西,所以即使配置含受管键也不被拒绝。这也正是你 决定要不要信任之前会用的命令——把它们挡住,等于把判断依据和出口一起藏起来。 - 信任管理本身:
trust、untrust,不读取项目配置。 config set/config unset/config migrate:把一份未信任配置改回正常的手段,挡住它就 等于用那份配置本身堵死了唯一出口。- 其余命令按上表的作用域把关。一个命令可以带多个作用域:bare
install同时 到达「安装」与「依赖」,run/exec默认同时到达各自作用域与「依赖」;--no-deps摘掉依赖作用域,--dry-run让 run 一个作用域都不剩。
经 shim 分派的工具是另一条线。 cargo、node 这类命令由 shim 启动,而 shim 只对它自己会走到的键把关(sources、registries 之类决定子进程从哪拉取 的)。像 [sys.pkg]、[task] 这种 shim 永远读不到的表,不会影响你在该目 录下正常使用工具。
信任身份与失效
osdk --yes trust # 最近项目配置
osdk --yes trust ./osdk.toml # 指定文件
osdk trust list # 列出记录及其状态
osdk untrust # 撤销最近项目配置
osdk trust prune --dry-run # 预览将清理哪些死记录
osdk trust prune # 清理配置文件已不存在的记录trust list 给出四种状态,它们的正确处置并不相同:
| 状态 | 含义 | 该做什么 |
|---|---|---|
active | 文件在,受管键与批准一致 | 无需处理 |
changed | 文件在,受管键变了 | 审阅后重新 osdk trust |
missing | 文件没了,父目录还在 | osdk trust prune 可清理 |
unreachable | 父目录也读不到 | 先确认卷是否挂载,不会被 prune |
prune 只删 missing。这一点是刻意的:changed 意味着项目还在、只是需要重新过目, 把它删掉会变成日后一句无从解释的「未受信任」;而 unreachable 在 Windows 上正是 U 盘、 网络共享或 WSL 挂载点掉线的样子,当垃圾清理会在卷恰好没挂载时删掉有效批准。 --dry-run 与实际执行用同一份候选列表,所以预览就是即将发生的事。
持久信任身份由配置的规范路径,与上表所列受管键的规范化 TOML 内容的 BLAKE3 共同 决定。哈希只覆盖受管键,因此两道门用的是同一个判据:一处不需要信任的改动,也不会 让已有记录失效。改工具版本、新增依赖、调 jobs、加注释、改空白或调整键顺序都不会 使记录变为 changed;改动受管键会,移动仓库则使其变为 missing 或 unreachable。 软链接解析到真实目标。trust store 位于 $OSDK_CONFIG_DIR/trusted-configs.toml。
CI 可设置 OSDK_TRUSTED_CONFIG_PATHS,值是操作系统路径分隔符连接的已审阅文件或 目录。匹配文件或位于匹配目录下的项目配置会在本次进程中视为 trusted,不写本地 trust store。trust/untrust 自身只加载用户配置,防止未信任项目影响自己的审批。
osdk config set 和 osdk config unset 同样在信任检查之前执行。否则出口会被它自己 要撤销的那份配置堵死——unset 将无法删掉正导致拒绝的那个键。这两个命令只针对指定 文件里的指定键,不会执行未受信任配置的任何内容。config get 和 config list 同样 不被拒绝:它们只展示那份配置的合并结果,不做任何事。