Claude Code の会話ログを自動退避しても VSCode のタブを壊さない(state.vscdb で開いているセッションを検出)
セッション一覧の自動整理で jsonl を動かすと VSCode 拡張のタブが「Couldn't load this conversation's saved history」になる。拡張が state.vscdb に平文で持つセッション ID をバイト検索して、参照中のログは理由を問わず動かさないガードの実装・テスト・復旧手順。
約8.2万トークンの節約 (API料金換算で約120円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「Claude Code の会話ログを自動退避しても VSCode のタブを壊さない(state.vscdb で開いているセッションを検出)」は、開発プロセスカテゴリのAI指示書(MDファイル)です。セッション一覧の自動整理で jsonl を動かすと VSCode 拡張のタブが「Couldn't load this conversation's saved history」になる。拡張が state.vscdb に平文で持つセッション ID をバイト検索して、参照中のログは理由を問わず動かさないガードの実装・テスト・復旧手順。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約8.2万トークン(API料金換算で約120円)・91%のトークンを節約できます。
- カテゴリ
- 開発プロセス
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約9万トークン
- この巻物使用時
- 約8,000トークン
- 節約量
- 約8.2万トークン (約120円)
- 更新日
- 2026-10-10
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/claude-code-vscode-state-vscdb/raw を読み込んで、この指示書どおりに実装して"
中身
Claude Code の会話ログを自動退避しても VSCode のタブを壊さない(state.vscdb で「まだ開いているセッション」を検出する)
この指示書が解く問題
Claude Code のセッション一覧を自動で整理するために ~/.claude/projects/<project>/<sessionId>.jsonl を別フォルダへ移動する仕組みを入れると、
VSCode 拡張(Claude Code for VS Code)で開いたままのタブを次に触った瞬間に次の赤い帯が出て、会話を続けられなくなる。
Couldn't load this conversation's saved history, so it can't be continued.
Start a new conversation · View output logs · Troubleshooting resources
症状の正体は --resume <sessionId> の not_found。拡張はタブ・ブックマーク・UI でアーカイブしたセッションの ID を
VSCode の状態DB(SQLite)に平文で持ち続けるので、ファイルだけ動かすと「一覧には残るのに中身が無い」状態になる。
拡張自身の自動アーカイブ設定 claudeCode.archiveInactiveSessions は「開いている・実行中・入力待ち・未読のセッションは絶対に対象にしない」と明記している。
自作の退避スクリプトも同じ原則に揃えればよい。
拡張がセッション ID を持っている場所(実測: 拡張 2.1.x)
| ファイル | キー | 中身 |
|---|---|---|
<User>/workspaceStorage/<hash>/state.vscdb | memento/workbench.parts.editor | 開いているエディタ(タブ)のシリアライズ。セッション ID を含む |
| 同上 | Anthropic.claude-code | panelTabSessions[].sessionId(パネルのタブ)、bookmarkedSessions[] |
<User>/globalStorage/state.vscdb | Anthropic.claude-code | hiddenSessionIds[](UI でアーカイブ済み。「Archived sessions」から再開できる) |
<User> は win32 %APPDATA%\Code\User、macOS ~/Library/Application Support/Code/User、Linux ~/.config/Code/User(Insiders は Code - Insiders)。
ID は UTF-8 の平文で入っているので、SQLite を解釈せずバイト列の部分一致で判定できる。読むだけで、書き込みは絶対にしない(VSCode が開いている DB を書き換えると壊れる)。
退避スクリプトに入れるガード(Node.js)
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
function entries(dir) { try { return fs.readdirSync(dir, { withFileTypes: true }); } catch (e) { if (e.code === 'ENOENT') return []; throw e; } }
// VSCode の状態DBのパス一覧。ORGIAST_VSCODE_USER_DIRS はテスト用の上書き(path.delimiter 区切り)。
function vscodeStateFiles() {
const override = process.env.VSCODE_USER_DIRS;
const dirs = override !== undefined ? override.split(path.delimiter).filter(Boolean)
: ['Code', 'Code - Insiders'].map(product => {
if (process.platform === 'win32') return path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), product, 'User');
if (process.platform === 'darwin') return path.join(os.homedir(), 'Library', 'Application Support', product, 'User');
return path.join(process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), product, 'User');
});
const files = [];
for (const dir of dirs) {
files.push(path.join(dir, 'globalStorage', 'state.vscdb'));
for (const entry of entries(path.join(dir, 'workspaceStorage'))) {
if (entry.isDirectory()) files.push(path.join(dir, 'workspaceStorage', entry.name, 'state.vscdb'));
}
}
return files;
}
// 1 パスで 1 回だけ読む。読めない DB があれば「全件見送り」に倒す(フェイルセーフ)。
function vscodeReferences() {
const buffers = []; let unreadable = false, files;
try { files = vscodeStateFiles(); } catch { return { buffers, unreadable: true }; }
for (const file of files) {
try { buffers.push(fs.readFileSync(file)); }
catch (error) { if (error.code !== 'ENOENT') unreadable = true; }
}
return { buffers, unreadable };
}
// 退避ループの中(transcript を読む前)で:
// const refs = vscodeRefs ??= vscodeReferences();
// if (refs.unreadable) { result.vscodeState = 'unreadable'; continue; }
// if (refs.buffers.some(b => b.includes(sessionId))) { result.protected++; continue; }
ポイント:
- 判定は 退避理由を問わず(明示クローズも含めて)かける。ユーザーがタブを ✕ で閉じれば DB から ID が消え、次のパスで通常どおり退避される。
hiddenSessionIdsも保護対象にする。UI でアーカイブ済みのセッションは「Archived sessions」から再開できるので、ファイルを動かすとそこでも同じ赤い帯が出る。- 判定を transcript の読み込みより前に置くと、走査予算も節約できる。
テストの書き方(node:test)
本物の SQLite を作る必要はない。バイト列の部分一致だけが判定なので、ヘッダ風のバイト + "sessionId":"<id>" を含む Buffer を state.vscdb として置けばよい。
fs.writeFileSync(db, Buffer.concat([
Buffer.from('SQLite format 3\0', 'utf8'), Buffer.alloc(48, 7),
Buffer.from('"sessionId":"tab-open"', 'utf8'),
]));
- 参照ありの
tab-*は全理由で残り、参照なしのfree-*は退避される、を--dry-runと実走の両方で assert する。 globalStorage/state.vscdbをディレクトリとして作るとreadFileSyncが EISDIR になるので、「読めない DB → 全件見送り」の分岐もテストできる。- テストの環境変数で DB の探索先を一時ディレクトリに向けること(向けないと実機の DB を読んで flaky になる)。
既に壊れたタブの復旧
- 退避先から元の場所へ戻す(ファイル名はそのまま。サイドカーのディレクトリ
<sessionId>/があれば一緒に戻す)。 - 戻した直後に次の退避パスで再び対象にならないよう、復元した ID を一定時間「稼働中」扱いにするか、上のガードを先に入れてから戻す。
- VSCode 側はタブを一度 ✕ で閉じ、左のセッション一覧から開き直す。赤い帯が出た時に送った最後のメッセージは保存されていないので送り直す。
「退避済みなのに VSCode がまだ参照している ID」の一覧は、退避フォルダの *.jsonl の ID を state.vscdb 群に bytes.find するだけで作れる(Python 10 行)。
副作用と割り切り
- 開きっぱなしのタブは自動では一覧から消えなくなる。一覧の整理は拡張の
claudeCode.archiveInactiveSessionsに任せるのが筋(開いているものは触らず、再開可能なまま隠す)。 lastActivationSessionIdやターミナル履歴に残る ID も保護されるが、せいぜい数件で実害はない。保護側に倒す方が「再開不能」より安い。
よくある質問
+「Claude Code の会話ログを自動退避しても VSCode のタブを壊さない(state.vscdb で開いているセッションを検出)」とは何ですか?
セッション一覧の自動整理で jsonl を動かすと VSCode 拡張のタブが「Couldn't load this conversation's saved history」になる。拡張が state.vscdb に平文で持つセッション ID をバイト検索して、参照中のログは理由を問わず動かさないガードの実装・テスト・復旧手順。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約9万トークンかかりますが、この巻物を使えば約8,000トークンで済みます。差し引き約8.2万トークン(API料金換算で約120円)・91%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
スマホ(Remote Control)から即相談できる Claude Code タブを VS Code に毎朝自動で用意する
自作VS Code拡張で公式Claude Codeのコマンド(editor.openLast/newConversation/renameSessionTab)を叩き、名前付きタブをN本自動補充。夜間はWM_CLOSE→再起動で毎朝揃える。--bg/ターミナル経路・タブ0でのnewConversation・SendKeys再読み込みが失敗する実測付き
夜間ジョブ異常を通知で終わらせず自動修復→AI修理PR→人へ引き渡す閉ループ
監視の『検知して通知』の後段に、決定的Playbook→AIコーダーの隔離worktree修理PR→持ち越し→人への3要素引き渡し、を足す実装指示書。argvで指示を渡すな等の実測の落とし穴つき
ドキュメント駆動開発プロセス CLAUDE.md — 作るものを固めてから書かせる
「AIが暴走して意図と違うものを作る」を根絶する開発プロセス指示書。UI仕様→機能設計→実装の順をAIに強制し、1ファイルごとに承認ゲートを挟む。受託開発・チーム開発向け。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア