Skip to content

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-commander MCP が起動失敗していた
  • Python は uv で管理済み: Python は uv が担当している前提のため、Node.js だけ別ツールに移行する

採用した構成

役割ツール
Python のバージョン・パッケージ・仮想環境uv(既存)
Node.js のバージョン管理mise(新規)
Yarn 4.xcorepack(Node.js 同梱)

mise は polyglot(Python も管理可能)だが、Python は引き続き uv に専任させ、mise には node のみ 任せる構成とした(重複・混乱回避のため)。

移行作業

1. Windows: mise インストールと設定

インストール

powershell
winget install jdx.mise --accept-package-agreements --accept-source-agreements

PowerShell プロファイルでアクティベート

$PROFILEC:\Users\mouri\Documents\PowerShell\Microsoft.PowerShell_profile.ps1)に追加:

powershell
# mise activation
Invoke-Expression (&mise activate pwsh | Out-String)

⚠️ Windows では pwsh を使う(powershell ではない)。

Node.js を mise でインストール

powershell
mise use --global node@24

User PATH に mise shims を追加

GUI アプリ(Claude Desktop 等)からも mise の Node.js が使えるようにする:

powershell
$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 エントリを削除

powershell
# 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 で再インストール:

powershell
npm install -g yarn @anthropic-ai/claude-code @github/copilot @google/gemini-cli ccusage openclaw

corepack 有効化(Yarn 4 自動利用)

powershell
corepack enable

プロジェクトに "packageManager": "yarn@4.7.0" の指定があれば、yarn 実行時に corepack が自動で 4.7.0 を呼び出す。

3. Windows: Volta アンインストール

powershell
winget uninstall Volta.Volta --silent
Remove-Item -Recurse -Force "C:\Users\mouri\AppData\Local\Volta" -ErrorAction SilentlyContinue

4. WSL (Ubuntu): mise インストール

bash
curl https://mise.run | sh

.bashrc / .zshrc の整備

~/.bashrc から nvm / volta の行を削除して、以下を追加:

bash
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 抑制)

bash
mise trust /mnt/c/Users/mouri/.config/mise/config.toml

Node.js とパッケージインストール

bash
mise use --global node@24
npm install -g yarn @anthropic-ai/claude-code @github/copilot @google/gemini-cli ccusage openclaw
corepack enable

古い .volta / .nvm 削除

bash
rm -rf $HOME/.volta $HOME/.nvm

5. プロジェクトに .mise.toml 追加

broadcast-Overlay-claude/.mise.toml:

toml
[tools]
node = "24"

これによりプロジェクトに cd するだけで mise が自動的に node@24 をアクティブにする。

既存の Volta pin(package.json

package.json の以下のフィールドは Volta 削除後でも害にならないため残置:

json
"volta": {
  "node": "24.13.0"
}

全 worktree 共通の package.json のため、他 AI / 他 worktree に影響を与えないよう変更しない。

動作確認

コマンド解決の確認(Claude Desktop と同等の clean PATH 環境)

powershell
# 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.0

Claude 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-mcpMCP サーバ(stdio)ダッシュボード(HTTP:5000) の 2 コンポーネント構成。各プロジェクトで MCP が起動すると、自動的に同じダッシュボードに登録される。

グローバルインストール

powershell
npm install -g @pimzino/spec-workflow-mcp
mise reshim  # mise shim 再生成

Tailscale Serve 設定

一度だけ: テイルネットで Serve を有効化

ブラウザで https://login.tailscale.com/f/serve にアクセスして「Enable HTTPS」をクリック。

Serve 設定

powershell
tailscale serve --bg --https=443 http://127.0.0.1:5000

CORS 無効化が必須

ダッシュボードはデフォルトで以下のオリジンしか許可しない:

http://localhost:5000, http://127.0.0.1:5000, http://localhost:5173, http://127.0.0.1:5173

Tailscale 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:

powershell
$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-open

Windows タスクスケジューラで自動起動

powershell
$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

管理コマンド

powershell
# 状態確認
Get-ScheduledTask -TaskName "SpecWorkflowDashboard"
Get-ScheduledTaskInfo -TaskName "SpecWorkflowDashboard"

# 即実行(テスト)
Start-ScheduledTask -TaskName "SpecWorkflowDashboard"

# 削除
Unregister-ScheduledTask -TaskName "SpecWorkflowDashboard" -Confirm:$false

他プロジェクトをダッシュボードに追加

各プロジェクトのルートに .mcp.json を置く(チームと共有可能):

json
{
  "mcpServers": {
    "spec-workflow": {
      "type": "stdio",
      "command": "spec-workflow-mcp",
      "args": ["."]
    }
  }
}

または claude mcp add

powershell
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 を読みにいく
  • ~/.bashrcexport 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.tomlnode = "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 を起動する

参考