Node.js 環境の mise 移行と spec-workflow ダッシュボード公開手順
このドキュメントは、Node.js のバージョン管理を Volta + nvm から mise に移行し、加えて spec-workflow ダッシュボードを Tailscale 内で共有可能にする までの作業記録です。
背景
移行の動機
- Volta は非メンテナンス: 公式に Issue #2080 で非メンテナンス宣言済み。後継として mise への移行が公式推奨されている
- nvm 由来の不具合: Claude Desktop が古い
nvm v20.0.0(npm 互換性のないバージョン)を拾ってしまい、desktop-commanderMCP が起動失敗していた - Python は uv で管理済み: Python は
uvが担当している前提のため、Node.js だけ別ツールに移行する
採用した構成
| 役割 | ツール |
|---|---|
| Python のバージョン・パッケージ・仮想環境 | uv(既存) |
| Node.js のバージョン管理 | mise(新規) |
| Yarn 4.x | corepack(Node.js 同梱) |
mise は polyglot(Python も管理可能)だが、Python は引き続き uv に専任させ、mise には node のみ 任せる構成とした(重複・混乱回避のため)。
移行作業
1. Windows: mise インストールと設定
インストール
winget install jdx.mise --accept-package-agreements --accept-source-agreementsPowerShell プロファイルでアクティベート
$PROFILE(C:\Users\mouri\Documents\PowerShell\Microsoft.PowerShell_profile.ps1)に追加:
# mise activation
Invoke-Expression (&mise activate pwsh | Out-String)⚠️ Windows では
pwshを使う(powershellではない)。
Node.js を mise でインストール
mise use --global node@24User PATH に mise shims を追加
GUI アプリ(Claude Desktop 等)からも mise の Node.js が使えるようにする:
$shimsPath = "C:\Users\mouri\AppData\Local\mise\shims"
$userPath = [System.Environment]::GetEnvironmentVariable("Path", "User")
$pathEntries = $userPath -split ";" | Where-Object { $_ -ne "" }
if ($pathEntries -notcontains $shimsPath) {
$newUserPath = ($shimsPath + ";" + ($pathEntries -join ";")).TrimEnd(";")
[System.Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")
}不要な PATH エントリを削除
# User PATH から nvm/volta を削除
$userPath = [System.Environment]::GetEnvironmentVariable("Path", "User")
$newUserPath = ($userPath -split ";" | Where-Object { $_ -notmatch "nvm" -and $_ -notmatch "Volta" -and $_ -notmatch "Yarn" }) -join ";"
[System.Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")Machine PATH(
C:\ProgramData\nvm等)は管理者権限が必要なため別途手動で削除。機能には影響しない。
2. Windows: グローバルパッケージ再インストール
Volta が管理していたツールを mise の npm で再インストール:
npm install -g yarn @anthropic-ai/claude-code @github/copilot @google/gemini-cli ccusage openclawcorepack 有効化(Yarn 4 自動利用)
corepack enableプロジェクトに "packageManager": "yarn@4.7.0" の指定があれば、yarn 実行時に corepack が自動で 4.7.0 を呼び出す。
3. Windows: Volta アンインストール
winget uninstall Volta.Volta --silent
Remove-Item -Recurse -Force "C:\Users\mouri\AppData\Local\Volta" -ErrorAction SilentlyContinue4. WSL (Ubuntu): mise インストール
curl https://mise.run | sh.bashrc / .zshrc の整備
~/.bashrc から nvm / volta の行を削除して、以下を追加:
export MISE_GLOBAL_CONFIG_FILE="$HOME/.config/mise/config.toml"
# mise activation
eval "$($HOME/.local/bin/mise activate bash)"
MISE_GLOBAL_CONFIG_FILEを設定する理由: WSL から/mnt/c/Users/<user>/.config/mise/config.toml(Windows config)を読み込んでしまうのを防ぐため。
Windows config の信頼設定(WARN 抑制)
mise trust /mnt/c/Users/mouri/.config/mise/config.tomlNode.js とパッケージインストール
mise use --global node@24
npm install -g yarn @anthropic-ai/claude-code @github/copilot @google/gemini-cli ccusage openclaw
corepack enable古い .volta / .nvm 削除
rm -rf $HOME/.volta $HOME/.nvm5. プロジェクトに .mise.toml 追加
broadcast-Overlay-claude/.mise.toml:
[tools]
node = "24"これによりプロジェクトに cd するだけで mise が自動的に node@24 をアクティブにする。
既存の Volta pin(package.json)
package.json の以下のフィールドは Volta 削除後でも害にならないため残置:
"volta": {
"node": "24.13.0"
}全 worktree 共通の
package.jsonのため、他 AI / 他 worktree に影響を与えないよう変更しない。
動作確認
コマンド解決の確認(Claude Desktop と同等の clean PATH 環境)
# Process PATH = Machine + User PATH(シェル init なし)
$cleanPath = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = "cmd.exe"
$psi.Arguments = '/c "where node && node --version"'
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.EnvironmentVariables["Path"] = $cleanPath
$proc = [System.Diagnostics.Process]::Start($psi)
$proc.WaitForExit()
$proc.StandardOutput.ReadToEnd()期待結果:
C:\Users\mouri\AppData\Local\mise\shims\node.exe
v24.15.0Claude Desktop の desktop-commander 動作確認
Claude Desktop アプリ再起動後、desktop-commander MCP が mise 配下の Node.js で正常起動することを確認。
spec-workflow ダッシュボード
構成
[Claude Code (project A)] → [spec-workflow MCP A] ─┐
[Claude Code (project B)] → [spec-workflow MCP B] ─┼→ [Dashboard :5000]
└→ [Tailscale Serve]
https://gretel.taila816bf.ts.net@pimzino/spec-workflow-mcp は MCP サーバ(stdio) と ダッシュボード(HTTP:5000) の 2 コンポーネント構成。各プロジェクトで MCP が起動すると、自動的に同じダッシュボードに登録される。
グローバルインストール
npm install -g @pimzino/spec-workflow-mcp
mise reshim # mise shim 再生成Tailscale Serve 設定
一度だけ: テイルネットで Serve を有効化
ブラウザで https://login.tailscale.com/f/serve にアクセスして「Enable HTTPS」をクリック。
Serve 設定
tailscale serve --bg --https=443 http://127.0.0.1:5000CORS 無効化が必須
ダッシュボードはデフォルトで以下のオリジンしか許可しない:
http://localhost:5000, http://127.0.0.1:5000, http://localhost:5173, http://127.0.0.1:5173Tailscale URL(https://gretel.taila816bf.ts.net)は含まれないため、環境変数 SPEC_WORKFLOW_CORS_ENABLED=false で無効化する。テイルネット内のみのアクセスのため安全。
dashboard には allowed origins を追加する CLI/env オプションが存在しないため、CORS を無効化するのが現実解。
起動スクリプト
C:\Users\mouri\bin\start-spec-dashboard.ps1:
$env:SPEC_WORKFLOW_CORS_ENABLED = "false"
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
Invoke-Expression (& mise activate pwsh | Out-String)
Write-Host "Local: http://127.0.0.1:5000"
Write-Host "Tailnet: https://gretel.taila816bf.ts.net"
spec-workflow-mcp --dashboard --no-openWindows タスクスケジューラで自動起動
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File ""C:\Users\mouri\bin\start-spec-dashboard.ps1"""
$trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
$settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries `
-StartWhenAvailable `
-RestartInterval (New-TimeSpan -Minutes 1) `
-RestartCount 3
$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive -RunLevel Limited
Register-ScheduledTask `
-TaskName "SpecWorkflowDashboard" `
-Action $action `
-Trigger $trigger `
-Settings $settings `
-Principal $principal `
-Force管理コマンド
# 状態確認
Get-ScheduledTask -TaskName "SpecWorkflowDashboard"
Get-ScheduledTaskInfo -TaskName "SpecWorkflowDashboard"
# 即実行(テスト)
Start-ScheduledTask -TaskName "SpecWorkflowDashboard"
# 削除
Unregister-ScheduledTask -TaskName "SpecWorkflowDashboard" -Confirm:$false他プロジェクトをダッシュボードに追加
各プロジェクトのルートに .mcp.json を置く(チームと共有可能):
{
"mcpServers": {
"spec-workflow": {
"type": "stdio",
"command": "spec-workflow-mcp",
"args": ["."]
}
}
}または claude mcp add:
cd <project-dir>
claude mcp add spec-workflow spec-workflow-mcp -- <project-dir>Claude Code 起動時に MCP がダッシュボードに自動登録される。
トラブルシューティング
mise where node が空 / node: command not found(WSL)
MISE_GLOBAL_CONFIG_FILEが未設定だと、Windows mount の config を読みにいく~/.bashrcでexport MISE_GLOBAL_CONFIG_FILE="$HOME/.config/mise/config.toml"を設定- プロジェクトディレクトリで
.mise.tomlが信頼されていない場合はmise trust <path>で許可
claude 等のコマンドが project node version で見つからない
mise は Node.js バージョンごとに global packages を持つ。プロジェクトの .mise.toml で異なる version を pin すると、その version では未インストールになる。対応:
.mise.tomlをnode = "24"(メジャー指定)にして global と一致させる- または各 version で
npm install -gし直す
Yarn が古いバージョン (1.x) を返す
- Machine PATH に
C:\Program Files (x86)\Yarn\bin\が残っている - 管理者権限で legacy Yarn をアンインストール、または Machine PATH からエントリを削除
- アクティベート済みシェルでは corepack 経由で 4.x が動作するので影響なし
ダッシュボードで index-XXX.js が 500 を返す
- CORS ブロック。
SPEC_WORKFLOW_CORS_ENABLED=falseで無効化 - 起動スクリプトで env 変数を設定してから dashboard を起動する