Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions conductor/archive/fix_global_bin_20260126/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Track fix_global_bin_20260126 Context

- [Specification](./spec.md)
- [Implementation Plan](./plan.md)
- [Metadata](./metadata.json)
8 changes: 8 additions & 0 deletions conductor/archive/fix_global_bin_20260126/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"track_id": "fix_global_bin_20260126",
"type": "bug",
"status": "new",
"created_at": "2026-01-26T10:00:00Z",
"updated_at": "2026-01-26T10:00:00Z",
"description": "修复 bun install -g 全局包在 macOS 和 Windows 上无法使用的问题"
}
36 changes: 36 additions & 0 deletions conductor/archive/fix_global_bin_20260126/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Implementation Plan: 修复 bun install -g 全局包无法使用的问题

修复在 macOS 和 Windows 平台上,使用 `bun install -g` 安装的全局包无法在命令行中使用的问题。

## Phase 1: 问题复现与测试环境搭建
- [x] Task: 创建集成测试脚本复现 `command not found` 错误
- [x] 在 `test/` 目录下创建 `global_install_path.test.ts`
- [x] 编写测试:模拟 `bvm use` 之后尝试运行 `bun install -g` 安装的虚构命令
- [x] 验证在当前环境下 `command -v <cmd>` 失败
- [x] Task: 检查现有的 PATH 注入逻辑
- [x] 审计 `src/commands/setup.ts` 和 `src/rc.ts`
- [x] 审计 `install.sh` 和 `install.ps1` 中的环境配置部分
- [x] Task: Conductor - User Manual Verification 'Phase 1' (Protocol in workflow.md)

## Phase 2: Unix/macOS 路径管理修复
- [x] Task: 增强 `install.sh` 以包含 Bun 全局 bin 目录
- [x] 修改 `install.sh`,确保 `~/.zshrc` 或 `~/.bashrc` 中包含正确的 `BUN_INSTALL/bin` 路径
- [x] Task: 修改 BVM 核心逻辑,动态管理全局 PATH (Unix)
- [x] 在 `bvm use` 执行后,如果检测到环境需要,提示用户重新加载或自动导出路径
- [x] Task: 运行集成测试并验证修复 (Unix)
- [x] 执行 `npx bun test test/global_install_path.test.ts`
- [x] Task: Conductor - User Manual Verification 'Phase 2' (Protocol in workflow.md)

## Phase 3: Windows 路径管理修复
- [x] Task: 增强 `install.ps1` 环境配置
- [x] 修改 `install.ps1`,确保用户 PATH 环境变量中永久包含当前版本 Bun 的 bin 目录
- [x] Task: 修复 BVM Windows Shim 的路径代理 (Windows)
- [x] 确保 Windows 版的 `bvm.cmd` 或 shim 能够处理全局包的查找逻辑
- [x] Task: Conductor - User Manual Verification 'Phase 3' (Protocol in workflow.md)

## Phase 4: 文档更新与回归测试
- [x] Task: 更新 README 和故障排除文档
- [x] 添加关于 `bun install -g` 包管理的说明
- [x] Task: 执行 E2E 测试
- [x] 运行 `npx bun run test` 确保无回归错误
- [x] Task: Conductor - User Manual Verification 'Phase 4' (Protocol in workflow.md)
30 changes: 30 additions & 0 deletions conductor/archive/fix_global_bin_20260126/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Specification: 修复 bun install -g 全局包无法使用的问题

## 1. 概述
修复在 macOS 和 Windows 平台上,使用 `bun install -g` (如 `@anthropic-ai/claude-code`) 安装全局包后,无法在终端直接运行该命令(提示 `command not found`)的缺陷。

## 2. 问题分析
当前 BVM 允许每个 Bun 版本拥有独立的全局包安装目录。然而,当用户通过 BVM 激活某个 Bun 版本时,该版本对应的全局 bin 目录可能未被正确添加到系统的 PATH 环境变量中,导致用户无法直接调用安装的工具。

## 3. 目标
- 确保用户使用 `bvm use <version>` 切换版本后,该版本下已安装的全局包命令立即可用。
- 确保用户在当前版本下新执行 `bun install -g <package>` 后,安装的命令立即可用。
- 保持不同 Bun 版本间全局包的隔离性。

## 4. 解决方案 (待验证)
1. **PATH 注入优化**: 确保 `bvm use` 操作会更新 Shell 的 PATH,指向 `<BUN_INSTALL>/bin`。
2. **动态 Shim**: BVM 的 Shim 机制可能需要扩展,以代理 `$BUN_INSTALL/bin` 下的所有可执行文件。

## 5. 验收标准
### macOS / Unix
- [ ] 安装 BVM 并安装一个 Bun 版本。
- [ ] 执行 `bun install -g @anthropic-ai/claude-code`。
- [ ] 执行 `claude` 命令,应能正常启动。

### Windows
- [ ] 安装 BVM 并安装一个 Bun 版本。
- [ ] 执行 `bun install -g @anthropic-ai/claude-code`。
- [ ] 执行 `claude` 命令,应能正常启动。

## 6. 不在范围
- 跨 Bun 版本的全局包自动迁移或共享。
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Track fix_windows_global_shim_resolution_20260126 Context

- [Specification](./spec.md)
- [Implementation Plan](./plan.md)
- [Metadata](./metadata.json)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"track_id": "fix_windows_global_shim_resolution_20260126",
"type": "bug",
"status": "new",
"created_at": "2026-01-26T10:30:00Z",
"updated_at": "2026-01-26T10:30:00Z",
"description": "修复 Windows 下全局包 Shim 的相对路径解析错误"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Implementation Plan: 修复 Windows 下全局包 Shim 的相对路径解析错误

## Phase 1: 调查与复现 (Investigation)
- [x] Task: 分析 Bun 生成的 Shim 文件结构
- [x] 在 Windows 环境(或模拟)下,检查 `bun install -g` 生成的 `.cmd` 和 `.ps1` 文件内容。
- [x] 记录相对路径的层级深度,对比 BVM `current` 目录结构。
- [x] Task: 创建最小复现脚本 (Reproduction Script)
- [x] 编写一个 PowerShell 脚本,模拟 BVM 的目录结构(`versions/vX`, `current` junction)。
- [x] 手动创建一个模拟 Bun Shim 的 `.cmd` 文件。
- [x] 验证通过 Junction 调用时路径解析是否失效。
- [x] Task: Conductor - User Manual Verification 'Phase 1' (Protocol in workflow.md)

## Phase 2: 方案原型验证 (Prototyping)
- [x] Task: 验证 "Shim Patching" (绝对路径) 方案
- [x] 编写脚本修改 Shim 文件,将 `..\` 替换为绝对路径。
- [x] 验证修改后的 Shim 是否能通过 `current` 路径正常运行。
- [x] Task: 验证 "Junction Bypass" (绕过) 方案
- [x] 测试是否可以直接将 `PATH` 指向真实版本路径(而非 `current`),验证是否解决问题。
- [x] Task: 选择最佳方案并撰写技术决策文档 (ADR)。
- [x] Task: Conductor - User Manual Verification 'Phase 2' (Protocol in workflow.md)

## Phase 3: 实现修复 (Implementation)
- [x] Task: 实现 Shim 修正工具 (Shim Fixer)
- [x] 在 `src/utils/windows-shim-fixer.ts` 中实现逻辑:扫描指定目录的 `.cmd` 文件,修复相对路径。
- [x] Task: 集成到 BVM 核心流程
- [x] 在 `bvm install` 和 `bvm use` 成功后,自动触发 Shim Fixer(仅 Windows)。
- [x] (可选) 添加 `bvm fix-shims` 命令供用户手动调用。
- [x] Task: Conductor - User Manual Verification 'Phase 3' (Protocol in workflow.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Specification: 修复 Windows 下全局包 Shim 的相对路径解析错误

## 1. 概述
在 Windows 平台上,用户通过 BVM 安装的 Bun 全局包(如 `claude`)在运行时可能抛出 `Module not found` 错误。初步分析显示,这是由于 Bun 生成的 Shim 脚本使用了相对路径(如 `..\..\..\node_modules\...`),而 BVM 的版本管理依赖于目录连接点(Junction,即 `.bvm\current`),导致相对路径解析时跳转到了错误的物理位置。

## 2. 问题分析 (Hypothesis)
- **现象**: 运行 `claude` 报错,路径指向错误的位置(如 `C:\Users\Administrator\.bvm\current\..\..\..\node_modules...`)。
- **原因**: Windows 的 Junction 在处理 `..` (父目录) 时,可能基于“链接所在的路径”而非“链接指向的目标真实路径”进行解析,或者反之,导致层级计算错误。
- **影响**: 所有依赖 BVM `current` 机制并在 Windows 上使用 `bun install -g` 的用户。

## 3. 目标
- **核心目标**: 确保在 Windows 上通过 BVM 安装和管理的全局包能够正常运行,不报路径错误。
- **阶段性目标**:
1. **复现**: 确立一个最小可复现案例 (Reproduction Case)。
2. **根因确认**: 分析 Bun 生成的 `.cmd` / `.ps1` 文件内容,确认相对路径的具体计算逻辑。
3. **方案验证**: 测试 "Shim Patching"(改为绝对路径)或 "Wrapper Proxy" 等修复方案的可行性。

## 4. 交付物
- 一个包含复现步骤和根因分析的技术报告。
- 修复方案的原型代码。
- 如果可行,直接集成修复到 BVM 核心。

## 5. 验收标准
- [ ] 在 Windows 测试环境中,安装 BVM 和 Bun。
- [ ] 运行 `bun install -g @anthropic-ai/claude-code`。
- [ ] 运行 `claude` 命令,不再报错。
- [ ] 确认修复方案不会破坏 Unix/macOS 的现有逻辑。

## 6. 不在范围
- 修复 Bun 自身的 Shim 生成逻辑。
5 changes: 5 additions & 0 deletions conductor/archive/release_v1_1_31_20260126/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Track release_v1_1_31_20260126 Context

- [Specification](./spec.md)
- [Implementation Plan](./plan.md)
- [Metadata](./metadata.json)
8 changes: 8 additions & 0 deletions conductor/archive/release_v1_1_31_20260126/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"track_id": "release_v1_1_31_20260126",
"type": "chore",
"status": "new",
"created_at": "2026-01-26T11:00:00Z",
"updated_at": "2026-01-26T11:00:00Z",
"description": "Release BVM v1.1.31 (Patch Fixes)"
}
23 changes: 23 additions & 0 deletions conductor/archive/release_v1_1_31_20260126/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Implementation Plan: Release BVM v1.1.31

## Phase 1: Preparation & Synchronization
- [ ] Task: Update Version
- [ ] Bump `package.json` version to `1.1.31`.
- [ ] Task: Synchronize Runtime & Installer
- [ ] Run `bun run scripts/sync-runtime.ts` to update `install.sh` and `install.ps1`.
- [ ] Verify `install.sh` contains `DEFAULT_BVM_VERSION="v1.1.31"`.
- [ ] Verify `install.ps1` contains `$DEFAULT_BVM_VER = "v1.1.31"`.
- [ ] Task: Conductor - User Manual Verification 'Phase 1'

## Phase 2: Build & Verify
- [ ] Task: Build Distribution
- [ ] Run `npm run build` (This also runs sync-runtime, but explicit step above ensures correctness).
- [ ] Run `bun run scripts/check-integrity.ts` to ensure consistency.
- [ ] Task: Conductor - User Manual Verification 'Phase 2'

## Phase 3: Commit & Finalize
- [ ] Task: Commit Release
- [ ] Stage `package.json`, `install.sh`, `install.ps1`, `dist/`.
- [ ] Commit message: `chore(release): v1.1.31`.
- [ ] Create Git Tag `v1.1.31`.
- [ ] Task: Conductor - User Manual Verification 'Phase 3'
20 changes: 20 additions & 0 deletions conductor/archive/release_v1_1_31_20260126/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Specification: Release BVM v1.1.31

## 1. Overview
Release version 1.1.31 of BVM-Core. This is a patch release focusing on critical fixes for global package management on Windows and general usability improvements.

## 2. Changes
- **Fix (Windows):** Resolved `Module not found` errors for global packages by automatically injecting absolute paths into Bun-generated shims (overcoming Junction relative path limits).
- **Feat (UX):** Added automatic PATH verification in `bvm use`. Warns users if `~/.bvm/current/bin` is missing from their PATH.
- **Docs:** Updated installation scripts to explicitly mention global binary path requirements.

## 3. Protocol (Architectural)
- **Synchronization:** `install.sh` and `install.ps1` MUST be updated with `v1.1.31` using `sync-runtime.ts`.
- **Integrity:** `check-integrity.ts` must pass.
- **Build:** `dist/index.js` must be rebuilt.

## 4. Deliverables
- Updated `package.json` (v1.1.31).
- Updated `install.sh` (DEFAULT_BVM_VERSION="v1.1.31").
- Updated `install.ps1` ($DEFAULT_BVM_VER="v1.1.31").
- Git Tag `v1.1.31`.
2 changes: 2 additions & 0 deletions conductor/tracks.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,5 @@ This file tracks all major tracks for the project. Each track has its own detail




\n---\n\n- [~] **Track: Release BVM v1.1.32**\n*Link: [./conductor/tracks/release_v1_1_32_20260126/](./conductor/tracks/release_v1_1_32_20260126/)*
5 changes: 5 additions & 0 deletions conductor/tracks/release_v1_1_32_20260126/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Track release_v1_1_32_20260126 Context

- [Specification](./spec.md)
- [Implementation Plan](./plan.md)
- [Metadata](./metadata.json)
8 changes: 8 additions & 0 deletions conductor/tracks/release_v1_1_32_20260126/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"track_id": "release_v1_1_32_20260126",
"type": "chore",
"status": "new",
"created_at": "2026-01-26T11:30:00Z",
"updated_at": "2026-01-26T11:30:00Z",
"description": "Release BVM v1.1.32"
}
20 changes: 20 additions & 0 deletions conductor/tracks/release_v1_1_32_20260126/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Implementation Plan: Release BVM v1.1.32

## Phase 1: Update Version
- [ ] Task: Bump version to 1.1.32
- [ ] Update `package.json`.
- [ ] Run `sync-runtime`.
- [ ] Task: Conductor - User Manual Verification 'Phase 1'

## Phase 2: Build & Verify
- [ ] Task: Build
- [ ] Run `npm run build`.
- [ ] Run `check-integrity`.
- [ ] Task: Conductor - User Manual Verification 'Phase 2'

## Phase 3: Finalize
- [ ] Task: Commit & Push
- [ ] Commit changes.
- [ ] Tag `v1.1.32`.
- [ ] Push to `test`.
- [ ] Task: Conductor - User Manual Verification 'Phase 3'
15 changes: 15 additions & 0 deletions conductor/tracks/release_v1_1_32_20260126/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Specification: Release BVM v1.1.32

## 1. Overview
Release version 1.1.32 of BVM-Core.

## 2. Changes
- Bump version to 1.1.32 to trigger new release cycle.

## 3. Protocol
- Synchronize version in `package.json`, `install.sh`, `install.ps1`.
- Build dist artifacts.
- Verify integrity.

## 4. Deliverables
- Git Tag `v1.1.32`.
4 changes: 3 additions & 1 deletion install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function Detect-NetworkZone {
$BVM_REGION = Detect-NetworkZone
$REGISTRY = if ($BVM_REGION -eq "cn") { "registry.npmmirror.com" } else { "registry.npmjs.org" }

$DEFAULT_BVM_VER = "v1.1.30"
$DEFAULT_BVM_VER = "v1.1.32"
$BVM_VER = if ($env:BVM_INSTALL_VERSION) { $env:BVM_INSTALL_VERSION } else { "" }
if (-not $BVM_VER) {
try {
Expand Down Expand Up @@ -187,3 +187,5 @@ $env:Path = "$BVM_SHIMS_DIR;$BVM_BIN_DIR;$BVM_CURRENT_BIN;$env:Path"

Write-Host "`n[OK] BVM installed successfully!" -ForegroundColor Green
Write-Host "IMPORTANT: Please close this terminal and open a NEW one to apply changes." -ForegroundColor Cyan
Write-Host "NOTE: Global packages (bun install -g) are isolated per version." -ForegroundColor Yellow
Write-Host " Ensure $($BVM_DIR)\current\bin is in your PATH." -ForegroundColor Yellow
4 changes: 2 additions & 2 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -e

# --- Configuration ---
DEFAULT_BVM_VERSION="v1.1.30" # Fallback
DEFAULT_BVM_VERSION="v1.1.32" # Fallback
FALLBACK_BUN_VERSION="1.3.6"
BVM_SRC_VERSION="${BVM_INSTALL_VERSION}" # If empty, will resolve dynamically

Expand Down Expand Up @@ -253,4 +253,4 @@ case "$CURRENT_SHELL" in
fish) DP="$HOME/.config/fish/config.fish" ;;
*) DP="$HOME/.profile" ;;
esac
echo -e "\nTo start using bvm:\n ${YELLOW}1. Refresh your shell:${RESET}\n source $DP\n\n ${YELLOW}2. Verify:${RESET}\n bvm --version"
echo -e "\nTo start using bvm:\n ${YELLOW}1. Refresh your shell:${RESET}\n source $DP\n\n ${YELLOW}2. Verify:${RESET}\n bvm --version\n\n ${YELLOW}3. Note:${RESET}\n Global packages (bun install -g) are isolated per version.\n Ensure ~/.bvm/current/bin is in your PATH."
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bvm-core",
"version": "1.1.30",
"version": "1.1.32",
"description": "The native version manager for Bun. Cross-platform, shell-agnostic, and zero-dependency.",
"main": "dist/index.js",
"bin": {
Expand Down
26 changes: 26 additions & 0 deletions src/commands/use.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,32 @@ export async function useBunVersion(targetVersion?: string, options: { silent?:
// Update the 'current' directory symlink for immediate global effect
await createSymlink(installPath, BVM_CURRENT_DIR);

// Verify if current/bin is in PATH
try {
const currentBinPath = join(BVM_CURRENT_DIR, 'bin');
// Normalize paths for comparison (handle separators)
const normalizedCurrentBin = currentBinPath.replace(/\\/g, '/');
const delimiter = require('path').delimiter;
const pathEntries = (process.env.PATH || '').split(delimiter);

const isPathConfigured = pathEntries.some(p => {
const normalizedP = p.replace(/\\/g, '/');
// Check for exact match or if it ends with .bvm/current/bin
return normalizedP.includes(normalizedCurrentBin) || normalizedP.endsWith('/.bvm/current/bin');
});

if (!isPathConfigured && !options.silent) {
if (spinner) spinner.stop(); // Stop spinner to print warning cleanly
console.log(colors.yellow(`\n⚠️ Warning: Global bin directory is not in your PATH.`));
console.log(colors.yellow(` Global packages (e.g., 'bun install -g') may not be found.`));
console.log(colors.gray(` Please add the following to your PATH:`));
console.log(colors.white(` ${currentBinPath}`));
if (spinner) spinner.start(); // Restart spinner if needed, or just leave it stopped as we are done
}
} catch (e: any) {
// console.error("Path check error:", e);
}

if (spinner) {
spinner.succeed(colors.green(`Now using Bun ${normalizedFinalResolvedVersion} (immediate effect).`));
}
Expand Down
31 changes: 30 additions & 1 deletion src/templates/win/bvm-shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,36 @@ process.env.BUN_INSTALL = versionDir;
process.env.PATH = binDir + path.delimiter + process.env.PATH;

const child = spawn(realExecutable, ARGS, { stdio: 'inherit', shell: false });
child.on('exit', (code) => process.exit(code ?? 0));
child.on('exit', (code) => {
if (code === 0 && (CMD === 'bun' || CMD === 'bunx')) {
const isGlobal = ARGS.includes('-g') || ARGS.includes('--global');
const isInstall = ARGS.includes('install') || ARGS.includes('add') || ARGS.includes('remove') || ARGS.includes('upgrade');

if (isGlobal && isInstall) {
try {
fixShims(binDir, versionDir);
} catch(e) {}
}
}
process.exit(code ?? 0);
});

function fixShims(binDir, versionDir) {
try {
const files = fs.readdirSync(binDir);
for (const file of files) {
if (file.endsWith('.cmd')) {
const filePath = path.join(binDir, file);
let content = fs.readFileSync(filePath, 'utf8');
if (content.includes('%~dp0\\..')) {
content = content.split('%~dp0\\..').join(versionDir);
fs.writeFileSync(filePath, content, 'utf8');
}
}
}
} catch(e) {}
}

child.on('error', (err) => {
console.error("BVM Error: Failed to start child process: " + err.message);
process.exit(1);
Expand Down
Loading