⚠️ 免责声明
本文档由 Claude (MiniMax-M3 模型) 根据与 l (Li Junhao) 的聊天过程生成, 未经 l 全文校对 。术语可能与 l 习惯用词不一致, 部分事实可能与 x-cmd/pkg 实际实现有出入。记录的是设计层面 的思考, 不是定稿。
🔄 Reframe 说明 : 本 issue 范围已 reframe。早期草稿把 conda 当 x-cmd/pkg 的上游, 已废弃 。conda / pixi / nix 的引入走 x-cmd/env (env.yml), 不是 x-cmd/pkg。x-cmd/pkg 维持"手作精品店"定位, 自己 build 缺包, 不接 conda。
TL;DR
x-cmd/pkg 是刀, x-cmd/env 是刀架。conda 进刀架 (env.yml 的 pixi: section), 不进刀身 (x-cmd/pkg 的索引)。
x-cmd 已经有一批 backend wrappers: x pixi / x asdf / x nix 等。x-cmd/env 是这些 wrappers 的编排层 , 通过 env.yml 把它们缝成一个统一 shell 环境。conda / pixi / nix 的引入走 env.yml, 不动 x-cmd/pkg。
背景
x-cmd 现在的 pkg 体系 (x-cmd/pkg) 是一个手作精品店 : ~500 个 CLI 工具, agent-用为主, 静态依赖, RPATH-relative 自包含。这条定位继续保留, 不动 。
但实际场景里, 用户经常需要超出这个范围的东西:
重 ABI 栈 (pytorch + cudatoolkit + numpy 矩阵) — 需要 SAT 求解
Hermetic 构建 — 需要 Nix 的内容寻址
pkgx 生态 — 用户已经用, 想统一入口
OS 驱动 / 系统级包 — conda 也不覆盖, 走系统包管理器
这些需求不能塞进 x-cmd/pkg (跟它的"少而精、静态优先"定位冲突), 但也不能让用户开八个 shell / 装八个 pkg 系统 。
x-cmd/env 就是这件事的入口 : 一个 env.yml, 把多个 pkg backend 编排起来。
x-cmd 的两层架构
x-cmd/
├── pkg/ # Layer 1: 自有体系
│ 定位: 500 个 agent CLI, 静态依赖, RPATH-relative
│ 策略: 缺什么 build 什么, 不接 conda
│
└── env/ # Layer 2: 编排器
输入: env.yml
里面: var / pkg / pkgx / pixi / nix
输出: 组合好的 shell 环境
x-cmd/pkg
conda-forge
数量
500
100k+
比例
1×
200×
定位
agent 用的 CLI
通用生态
依赖策略
尽可能静态
多层传递
缺货时
自己 build
直接拉
这不是缺陷, 是定位 。x-cmd/pkg 的 supply chain 不是通用工厂, 是手作 ——每个包靠"动态库减到最少 / 静态优先"获得简洁性。
env.yml schema 草案
var : # 环境变量
EDITOR : vim
PATH : ...
pkg : # x-cmd/pkg — 自有体系, 静态依赖
- jq
- ripgrep
- python : " 3.10.0" # pin (用户显式锁版本)
pkgx : # pkgx — pkgx 生态擅长的部分
- deno
pixi : # x pixi — 科学计算 + SAT 求解
- pytorch
- numpy : " >=2.0"
nix : # x nix — 内容寻址、hermetic
- hello
asdf : # x asdf — 多语言 runtime 版本管理
- nodejs : " 20.0.0"
各 backend 定位
backend
已有 wrapper
适用场景
不适用场景
pkg:
内建
日常 CLI / agent 工具 / 静态依赖链
重型 ABI 栈 / hermetic 复现
pkgx:
(待补 x pkgx)
pkgx 生态特有的工具
pkgx 没有的
pixi:
x pixi ✓
pytorch / tensorflow / conda-forge 独有 / 多包 SAT
静态简单包 (走 pkg: 更轻)
nix:
x nix ✓
hermetic 构建 / byte-identical 复现
简单工具 (走 pkg: 更快)
asdf:
x asdf ✓
多语言 runtime 版本管理 (nodejs / python / rust)
系统级包
用户按需混用 ——一个 env.yml 可以同时有 pkg: jq 和 pixi: pytorch, 不互斥。
x-cmd/pkg 不动什么
✅ RPATH-relative + 静态优先 — x-cmd/pkg 的核心设计, 保留
✅ 局部版本共存 + 锁版本 — x-cmd/pkg 的算法, 保留
✅ 三个范式 (选 / 锁-by-hash / 锁-by-string) — 概念清晰化, 保留
✅ "build 时消灭依赖 hell" — 仍然是 x-cmd/pkg 的算法原则
✅ SONAME 池 + per-sphere — 仍然适用 (per-sphere 的 l/ 池跨 pkg sphere, 但 不跨 env backend )
x-cmd/env 要做什么
env.yml 解析 : 读取用户 yaml, 识别各 backend section
dispatch 到具体 backend :
pkg: → x pkg add (走 x-cmd/pkg 自维护索引)
pkgx: → 调用 pkgx CLI
pixi: → 调用 pixi add / 生成临时 pixi.toml 调 pixi install
nix: → 调用 nix profile install 或临时生成 nix 表达式
PATH 合成 : 把各 backend 安装的 bin 都拉进一个统一 PATH, 优先级用户配
变量注入 : 把 var: 块的 env vars 注入到 shell
shell 激活 : x env use / x env try 子命令, 启动一个 shell session 让 vars/PATH 生效
关键设计决策 (跟早期 issue 的演化对比)
旧 issue 假设
新框架结论
"x-cmd/pkg 接 conda-forge 当上游"
❌ 不接 — conda 走 env, pkg 自己 build
"RPATH-relative 重写 conda 包 populate"
❌ 不在 pkg 做 — conda 包在 pixi/conda-forge 里跑自己的 RPATH, x-cmd 不介入
"SAT 求解器接入 pkg"
❌ SAT 在 pixi backend 里, 不进 x-cmd/pkg
"Nix / pkgx 路径分析"
✅ 保留 — 但放 env 层讨论, 不在 pkg 层
"x-cmd/pkg 的三个范式 (选/锁-by-hash/锁-by-string)"
✅ 保留 — 这是 x-cmd/pkg 自己的算法, 跟 env backend 无关
"RPATH-relative + 静态优先"
✅ 保留 — x-cmd/pkg 的核心, 跟 env backend 无关
不在 env.yml 里要做的事
不替用户做决策 — 用户显式选哪个 backend, env 不"自动推荐"
不解决跨 backend 的 ABI 兼容 — pkg: numpy 和 pixi: numpy 在不同 sphere, 各自 RPATH 锁定自己版本, 不会冲突 (跟局部版本共存同源)
不替用户写 env.yml — 用户自己配, AI 可以辅助生成
TODO
关键不变量
env layer 的所有设计 应该满足:
不修改各 backend 的内部模型 — pkg / pkgx / pixi / nix 各自怎么装怎么管是它们的事
只编排, 不翻译 — env 不替任何 backend 重新实现
用户显式选 backend — 不"自动猜"
跨 backend 不假设共享 — pkg: 装的不跟 pixi: 装的"等价"或"互通", 各自独立
与现有 issue 的关系
关联阅读
背景叙事 (story): [pkg] pixi/conda 上游包接入 — 背景叙事 (story) #19
pixi 主仓库 (本机镜像 /Users/l/.x-repo/github.com/x-cmd-sourcecode/pixi):
入口: crates/pixi_command_dispatcher/src/solve_conda/mod.rs:318 (Solver.solve(task)? 是 SAT 唯一入口)
并行模型: crates/pixi_command_dispatcher/src/solve_binary.rs:60-73 (conda_solve_semaphore)
通道优先级: docs/advanced/channel_logic.md
x-cmd/pkg 相关 issue (x-cmd/pkg 自己不动 conda, 这些只供设计参考):
0119.npm-pip-source.yml — 源镜像 env var 模式
0125.版本号问题.yml — 版本号规范化
同类设计先例: asdf / rtx / mise (多个 runtime 编排, 单一 manifest), devbox (类似 Nix 但更轻)
TL;DR
x-cmd 已经有一批 backend wrappers:
x pixi/x asdf/x nix等。x-cmd/env 是这些 wrappers 的编排层, 通过 env.yml 把它们缝成一个统一 shell 环境。conda / pixi / nix 的引入走 env.yml, 不动 x-cmd/pkg。背景
x-cmd 现在的 pkg 体系 (
x-cmd/pkg) 是一个手作精品店: ~500 个 CLI 工具, agent-用为主, 静态依赖, RPATH-relative 自包含。这条定位继续保留, 不动。但实际场景里, 用户经常需要超出这个范围的东西:
pytorch+cudatoolkit+numpy矩阵) — 需要 SAT 求解这些需求不能塞进 x-cmd/pkg (跟它的"少而精、静态优先"定位冲突), 但也不能让用户开八个 shell / 装八个 pkg 系统。
x-cmd/env 就是这件事的入口: 一个
env.yml, 把多个 pkg backend 编排起来。x-cmd 的两层架构
这不是缺陷, 是定位。x-cmd/pkg 的 supply chain 不是通用工厂, 是手作——每个包靠"动态库减到最少 / 静态优先"获得简洁性。
env.yml schema 草案
各 backend 定位
pkg:pkgx:x pkgx)pixi:x pixi✓pkg:更轻)nix:x nix✓pkg:更快)asdf:x asdf✓用户按需混用——一个 env.yml 可以同时有
pkg: jq和pixi: pytorch, 不互斥。x-cmd/pkg 不动什么
l/池跨 pkg sphere, 但 不跨 env backend)x-cmd/env 要做什么
pkg:→x pkg add(走 x-cmd/pkg 自维护索引)pkgx:→ 调用 pkgx CLIpixi:→ 调用pixi add/ 生成临时pixi.toml调pixi installnix:→ 调用nix profile install或临时生成 nix 表达式var:块的 env vars 注入到 shellx env use/x env try子命令, 启动一个 shell session 让 vars/PATH 生效关键设计决策 (跟早期 issue 的演化对比)
不在 env.yml 里要做的事
pkg: numpy和pixi: numpy在不同 sphere, 各自 RPATH 锁定自己版本, 不会冲突 (跟局部版本共存同源)TODO
x env use <env.yml>子命令: 读 yaml, dispatch 各 backend, 合成 PATHx env try <env.yml>子命令: session-only, 退出失效x env info子命令: 当前活跃 env, 各 backend 已装内容pkgx install包装pixi.toml调pixi install/pixi addnix profile install或临时 nix expr 包装var:块直接注入, 还是写到~/.pam_environment/~/.config/environment.d/pkg:包被pixi:引用)关键不变量
env layer 的所有设计应该满足:
pkg:装的不跟pixi:装的"等价"或"互通", 各自独立与现有 issue 的关系
关联阅读
/Users/l/.x-repo/github.com/x-cmd-sourcecode/pixi):crates/pixi_command_dispatcher/src/solve_conda/mod.rs:318(Solver.solve(task)?是 SAT 唯一入口)crates/pixi_command_dispatcher/src/solve_binary.rs:60-73(conda_solve_semaphore)docs/advanced/channel_logic.md0119.npm-pip-source.yml— 源镜像 env var 模式0125.版本号问题.yml— 版本号规范化