2/23公開【Cursorの履歴を復元する方法(Gemini謹製スクリプト有)】~誰かの休日が守られますように~

【Cursorの履歴を復元する方法(Gemini謹製スクリプト有)】~誰かの休日が守られますように~

先日、Cursorのアップデートに失敗して起動しなくなってしまいました。
手を尽くしたのですが再インストールせざるを得ない状況。

そこで休日返上で履歴の復元にチャレンジしたので、Cursorの履歴保存のしくみと復元方法とスクリプトを共有します。

目次

こんな人向けの記事です

  • PCを買い替えた人・初期化した人
  • Cursorを再インストールしたい人
  • WSL環境の作り直し等で、Cursorのチャット履歴も復元したい人

動作確認環境

  • OS:Windows 11
  • PowerShell:5.1
  • Cursor:2.4(2026年2月時点)
免責事項

Cursorは頻繁にバージョンアップが繰り返されていますので、掲載したスニペットは正常に動作しない可能性があります。
本記事のスニペットをコピペで使用する際は、自己責任ということでご理解ください。

なぜ履歴が消えるのか?

Cursorの会話履歴のフォルダ管理のしくみ

Cursorはチャット履歴を、プロジェクトフォルダごとに分けて管理しています。その保存先は、Windowsであれば以下のパスです。

C:\Users\<ユーザー名>\AppData\Roaming\Cursor\User\workspaceStorage\
バックアップが必要なフォルダ

このフォルダの中には、44e5471f3443e2b32bd8a8166070f6a5 のような 32桁の英数字(ハッシュ値) を名前に持つフォルダが大量に並んでいます。

ハッシュ値になっているフォルダはコレ

このハッシュ値は、プロジェクトフォルダのパス(URI)から自動生成されます。

問題は環境が変わると「ハッシュ値(フォルダ名)」も変わるということ

たとえば、WSLをUbuntu22.04からUbuntu24.04にバージョンアップするケースではURLが変わるため、結果としてハッシュ値(フォルダ名)が変わってしまいます。

環境プロジェクトのURI(例)
旧WSL環境vscode-remote://wsl+Ubuntu-22.04/home/user/myproject
新WSL環境vscode-remote://wsl+Ubuntu-24.04/home/user/myproject

この場合、Cursorは新しい(空っぽの)新ハッシュフォルダを見に行ってしまいます。結果的にCursorは古いハッシュ値(フォルダ名)の会話履歴を読み込むことができなくなってしまいます。

しかし逆に、ハッシュ値(フォルダ名)を入れ替えることで履歴を復元できるはずです。

履歴復元のアプローチ

流れはシンプルです。「新旧のハッシュフォルダを突き合わせて、中身だけ移植する」だけです。

  1. 新しい環境でプロジェクトを一度開き、新ハッシュフォルダを作らせる
  2. バックアップ(旧ハッシュ)の中身(state.vscdb)を、新ハッシュのフォルダに上書きコピーする
  3. globalStorage のDBも合わせて戻すことで、インデックス不整合による「Loading…」フリーズを防ぐ(WSL環境の場合に特に有効)

復元前の準備

STEP
バックアップを取る

以下の例は念の為、会話履歴以外(globalStrage等)もバックアップしていますが、最も重要なのはworkspaceStorageで、これが会話履歴本体です。

$BK = "G:\260213CursorBK" #バックアップ先を指定する
New-Item -ItemType Directory -Force -Path $BK | Out-Null

# 1) チャット履歴(最重要)
$src1 = Join-Path $env:APPDATA "Cursor\User\workspaceStorage"
if (Test-Path $src1) {
  robocopy $src1 (Join-Path $BK "Roaming_Cursor_User_workspaceStorage") /E /COPY:DAT /DCOPY:T /R:1 /W:1 /XJ
}

# 2) Cursor の Roaming 全体(設定など。容量が大きければ後で絞ってOK)
$src2 = Join-Path $env:APPDATA "Cursor"
if (Test-Path $src2) {
  robocopy $src2 (Join-Path $BK "Roaming_Cursor") /E /COPY:DAT /DCOPY:T /R:1 /W:1 /XJ
}

# 3) .cursor(存在する場合。拡張/データが入っていることがある)
$src3 = Join-Path $env:USERPROFILE ".cursor"
if (Test-Path $src3) {
  robocopy $src3 (Join-Path $BK "UserProfile_.cursor") /E /COPY:DAT /DCOPY:T /R:1 /W:1 /XJ
}

# 4) Local 側の Cursor データ(存在する場合)
$src4 = Join-Path $env:LOCALAPPDATA "Cursor"
if (Test-Path $src4) {
  robocopy $src4 (Join-Path $BK "Local_Cursor") /E /COPY:DAT /DCOPY:T /R:1 /W:1 /XJ
}
STEP
ハッシュ(会話履歴のフォルダ名)との対応表を作る

続いてバックアップした古い会話履歴フォルダのハッシュ値(会話履歴のフォルダ名)との対応表を作ります。
これは必ずしも必要ありませんが、特にプロジェクトがたくさんある場合は、Cursorを再インストールした後で生成される新しい会話履歴フォルダのハッシュを古いフォルダのハッシュと入れ替える際に役に立ちます。

$ws = "G:\260213CursorBK\Roaming_Cursor_User_workspaceStorage"

$rows = foreach ($dir in Get-ChildItem $ws -Directory) {
  $wj = Join-Path $dir.FullName "workspace.json"
  if (-not (Test-Path $wj)) { continue }

  try {
    $j = Get-Content $wj -Raw | ConvertFrom-Json
  } catch {
    continue
  }

  $folder = $null
  if ($j.PSObject.Properties.Name -contains "folder")   { $folder = $j.folder }
  if (-not $folder -and ($j.PSObject.Properties.Name -contains "workspace")) { $folder = $j.workspace }

  [pscustomobject]@{
    HashFolder   = $dir.Name
    WorkspaceUri = $folder
    WorkspaceJson= $wj
  }
}

$rows |
  Sort-Object WorkspaceUri |
  Export-Csv -NoTypeInformation -Encoding UTF8 "$ws\_workspace_map.csv"

$rows | Select-Object -First 20 HashFolder, WorkspaceUri

このスクリプトを実行すると、”G:\260213CursorBK\Roaming_Cursor_User_workspaceStorage”内に、「_workspace_map.csv」という名前で、以下のようなCSVデータが生成されるはずです。

CSVの各列の意味

列名何を表しているかユーザーにとっての意味
HashFolderバックアップフォルダ内に作られている「32桁のランダムな文字列(ハッシュ)」のフォルダ名です。Cursorが履歴を管理するための「ハッシュ値」であり、フォルダ名をハッシュ関数でハッシュ化した値です。人間には解読できません。
WorkspaceUriそのハッシュフォルダと紐づいている「プロジェクトの実際の場所(パス)」です「どのプロジェクトの履歴か」を示す最も重要な部分です。ここを見て、自分が復元したいプロジェクトを探します。(→「旧ハッシュ($oldHash)の見つけ方」参照)
WorkspaceJsonパス情報が記録されていた workspace.json というファイルの保存場所です。(ここは基本的に見なくてOKです。スクリプトが読み込んだファイルの場所を示しているだけです)
STEP
Cursorを完全終了させる

スクリプト実行前に必ずCursorを完全終了させてください。 DBファイルがロックされたままだとコピーに失敗します。

通常の × ボタンではバックグラウンドで動き続けることがあります。以下の手順で完全終了させてください。

  1. タスクバー右下の通知領域(システムトレイ)を開く
  2. Cursorのアイコンを右クリック
  3. 「終了」または「Quit」 をクリック
Quitボタン
STEP
バックアップのバックアップ

既存データが上書きされます。 不安な場合は、実行前に新環境側の workspaceStorage フォルダもバックアップしておくと安心です。

旧ハッシュ($oldHash)の見つけ方(WorkspaceUriの探し方)

バックアップフォルダの中にある各ハッシュフォルダには、workspace.json というファイルが1つあります。これをテキストエディタで開くと、そのプロジェクトのパスが記録されています。

{
  "folder": "file:///C%3A/Users/user/myproject"
}

または WSL の場合:

{
  "folder": "vscode-remote://wsl%2BUbuntu-22.04/home/user/myproject"
}

folder の値を見て、復元したいプロジェクトと一致するフォルダを特定します。そのフォルダ名(32桁のハッシュ値)が、後述のスクリプトで $oldHash に設定する値です。

WorkspaceUri(パス)の読み解き方

パターン1:Windowsのローカルフォルダ

file:///e%3A/win_n8n や file:///g%3A/basketball_sentinel

  • 解説: file:/// から始まっているのは、自分のPCのローカルドライブにあるフォルダです。
    %3A は「:(コロン)」のことです。
    つまり、これは E:\win_n8n や G:\basketball_sentinel というフォルダを開いたときの履歴であることを意味しています。

パターン2:WSL(Windows Subsystem for Linux)のフォルダ

vscode-remote://wsl%2Bubuntu/home/ofbita/basketball_sentinel

  • 解説: vscode-remote://wsl から始まっているのは、WSL環境(Linux)の中にあるフォルダです。
    %2B は「+(プラス)」のことです。
    つまり、これは WSLの Ubuntu の中にある /home/ofbita/basketball_sentinel というフォルダを開いたときの履歴です。

パターン3:エクスプローラーからネットワーク経由で開いたWSL

file://wsl.localhost/Ubuntu/home/ofbita/llm_worker

  • 解説: これもWSL内のフォルダですが、Cursorの「WSLに接続」機能を使わず、Windowsのエクスプローラーから \\wsl.localhost\... のように無理やり開いたときのパスです。

パターン4:SSH(遠隔サーバー)のフォルダ

vscode-remote://ssh-remote%2B7b22686f.../etc

  • 解説: ssh-remote から始まっているのは、VPSやクラウドサーバーなどにSSHでリモート接続したときのフォルダです。
    途中の長い文字列は、接続先のサーバー情報が暗号化されたものです。

大量にある場合の一括確認コマンド

# ↓ 自分のバックアップフォルダのパスに書き換えてください
$backupWs = "G:\260213CursorBK\Roaming_Cursor_User_workspaceStorage"

Get-ChildItem $backupWs -Directory | ForEach-Object {
    $jsonPath = Join-Path $_.FullName "workspace.json"
    if (Test-Path $jsonPath) {
        $content = Get-Content $jsonPath -Raw | ConvertFrom-Json
        [PSCustomObject]@{
            Hash   = $_.Name
            Folder = $content.folder
        }
    }
} | Format-Table -AutoSize

実行すると以下のように一覧が出るので、目的のプロジェクトのハッシュをすぐに特定できます。

PowerShellでの実行イメージ

PowerShellでの実行イメージ

復元スクリプト

さて、ここまでの作業で以下の必要な変数を埋めることができると思います。
これを使ってGeminiさんに作成してもらったスクリプトに当てはめれば復元できるはずです。

Windowsローカル版・日本語パス完全対応バージョン

書き換えが必要な3箇所

変数説明
$backupWsバックアップ先のフォルダパスG:\260213CursorBK\Roaming_Cursor_User_workspaceStorage
$oldHash旧環境のハッシュ(32桁の英数字)44e5471f3443e2b32bd8a8166070f6a5
$folderPartプロジェクトフォルダ名の一部(検索用)CSV整形(日本語・スペースOK)
# ==========================================
# Cursor チャット履歴復元
# Windowsローカル・日本語パス完全対応版
# ==========================================

# ===== ここを書き換えてください(3箇所) =====
$backupWs   = "G:\260213CursorBK\Roaming_Cursor_User_workspaceStorage"
$oldHash    = "44e5471f3443e2b32bd8a8166070f6a5" # 旧ハッシュ
$folderPart = "CSV整形"                          # プロジェクト名の一部(日本語・スペースOK)
# =============================================

# --- 処理開始 ---
$newWsRoot = Join-Path $env:APPDATA "Cursor\User\workspaceStorage"

# URLエンコード処理(日本語・スペースを %XX 形式に変換する安全な方式)
$encodedPart = [Uri]::EscapeDataString($folderPart).ToUpper()

Write-Host "検索中... キーワード: '$folderPart' (または '$encodedPart')" -ForegroundColor Gray

# 新ハッシュを探す
$newHash = Get-ChildItem $newWsRoot -Directory | Where-Object {
    $jsonPath = Join-Path $_.FullName "workspace.json"
    if (Test-Path $jsonPath) {
        $content = Get-Content $jsonPath -Raw
        if ($content -match "file:///") {
            return ($content -match [Regex]::Escape($folderPart) -or $content -match $encodedPart)
        }
    }
    return $false
} | Select-Object -First 1 -ExpandProperty Name

if (-not $newHash) {
    Write-Error "新環境でプロジェクトが見つかりません。Cursorで一度フォルダを開きましたか?`n(検索キー: $folderPart / $encodedPart)"
    exit
}

Write-Host "新ハッシュを発見: $newHash" -ForegroundColor Green

$srcDir = Join-Path $backupWs $oldHash
$dstDir = Join-Path $newWsRoot $newHash

if (-not (Test-Path $srcDir)) {
    Write-Error "バックアップ元が見つかりません: $srcDir"
    exit
}

# 退避(既存データを _OLD フォルダへ)
New-Item -ItemType Directory -Force -Path (Join-Path $dstDir "_OLD") | Out-Null
Get-ChildItem -Path $dstDir -Filter "state.vscdb*" | Move-Item -Force -Destination (Join-Path $dstDir "_OLD")

# コピー(旧DBを新フォルダへ上書き)
Get-ChildItem -Path $srcDir -Filter "state.vscdb*" | Copy-Item -Destination $dstDir -Force

Write-Host "復元完了!Cursorを起動してください。" -ForegroundColor Cyan

WSL環境バージョン

WSLの場合は、globalStorage のDBも合わせて戻さないと 「Loading…」フリーズ が発生することがあります。

書き換えが必要な4箇所

変数説明
$backupWsworkspaceStorage のバックアップパスG:\260213CursorBK\Roaming_Cursor_User_workspaceStorage
$backupGsglobalStorage のバックアップパスG:\260213CursorBK\Roaming_Cursor_User_globalStorage
$oldHash旧環境のハッシュ(32桁の英数字)b5ed5e9f85b2d7c3a1234567890abcde
$folderPartプロジェクト名の一部(検索用)myproject
# ==========================================
# Cursor チャット履歴復元
# WSL環境対応版(globalStorage含む)
# ==========================================

# ===== ここを書き換えてください(4箇所) =====
$backupWs   = "G:\260213CursorBK\Roaming_Cursor_User_workspaceStorage"
$backupGs   = "G:\260213CursorBK\Roaming_Cursor_User_globalStorage"
$oldHash    = "b5ed5e9f85b2d7c3a1234567890abcde" # 旧ハッシュ
$folderPart = "myproject"                        # プロジェクト名の一部(英語推奨・日本語も可)
# =============================================

$newWsRoot = Join-Path $env:APPDATA "Cursor\User\workspaceStorage"

# URLエンコード処理(日本語・スペースを %XX 形式に変換する安全な方式)
$encodedPart = [Uri]::EscapeDataString($folderPart).ToUpper()

Write-Host "検索中... キーワード: '$folderPart' (または '$encodedPart')" -ForegroundColor Gray

# 新ハッシュを探す(WSLパスを対象)
$newHash = Get-ChildItem $newWsRoot -Directory | Where-Object {
    $jsonPath = Join-Path $_.FullName "workspace.json"
    if (Test-Path $jsonPath) {
        $content = Get-Content $jsonPath -Raw
        if ($content -match "vscode-remote://") {
            return ($content -match [Regex]::Escape($folderPart) -or $content -match $encodedPart)
        }
    }
    return $false
} | Select-Object -First 1 -ExpandProperty Name

if (-not $newHash) {
    Write-Error "新環境でプロジェクトが見つかりません。Cursorで一度WSLフォルダを開きましたか?"
    exit
}

Write-Host "新ハッシュを発見: $newHash" -ForegroundColor Green

# --- workspaceStorage の復元 ---
$srcDir = Join-Path $backupWs $oldHash
$dstDir = Join-Path $newWsRoot $newHash

if (-not (Test-Path $srcDir)) {
    Write-Error "バックアップ元が見つかりません: $srcDir"
    exit
}

New-Item -ItemType Directory -Force -Path (Join-Path $dstDir "_OLD") | Out-Null
Get-ChildItem -Path $dstDir -Filter "state.vscdb*" | Move-Item -Force -Destination (Join-Path $dstDir "_OLD")
Get-ChildItem -Path $srcDir  -Filter "state.vscdb*" | Copy-Item -Destination $dstDir -Force

Write-Host "[1/2] workspaceStorage の復元完了" -ForegroundColor Green

# --- globalStorage の復元(Loading...フリーズ防止) ---
$newGsRoot  = Join-Path $env:APPDATA "Cursor\User\globalStorage"
$targetVsdb = "state.vscdb"

if (Test-Path $backupGs) {
    $srcGs = Join-Path $backupGs $targetVsdb
    $dstGs = Join-Path $newGsRoot $targetVsdb
    if (Test-Path $srcGs) {
        Copy-Item $srcGs -Destination $dstGs -Force
        Write-Host "[2/2] globalStorage の復元完了" -ForegroundColor Green
    } else {
        Write-Warning "globalStorage のバックアップが見つかりませんでした(スキップ)"
    }
} else {
    Write-Warning "globalStorage バックアップフォルダが存在しません(スキップ)"
}

Write-Host "復元完了!Cursorを起動してください。" -ForegroundColor Cyan

実際にやってみます

復元前の準備」が終わっていることを必ず確認してくださいね。

STEP
上記スクリプトをコピーしてメモ帳に貼り付けて必要な個所を書き換える

今回はWSL環境対応版です。実質調べるのは「バックアップ場所」($backupWs$backupGs)と「旧ハッシュ値」($oldHash)のみです。($folderPartは正直不要な気もしますが、余計なトークン使うのでそこはGeminiさんと議論はしていません。)

メモ帳で書き換える場所
STEP
メモ帳からテキストをコピーしてPowerShellに貼り付ける
実行結果画面

以上です。
Cursorを起動し、対象のプロジェクトを開いたとき、チャット履歴パネルに過去の会話が表示されていれば成功です。

Before

履歴が読み込まれていないCursorの実際の画面

After

履歴が読み込まれた後のCursorの実際の画面
困ったときのヒント
  • Cursorを完全に終了させること。 手順は「復元前の準備」を参照してください。
  • WSL版でのディストリビューション名wsl -l -v コマンドで確認できます。$folderPart の検索キーワードにディストリビューション名の一部(例:Ubuntu-24)を含めることで、さらに絞り込みが可能です。
  • URLをコピーしました!
目次