🗂

🙈 クリップボヌドでむンポヌト/゚クスポヌト実装したら事故った話【VS Code拡匵開発】

に公開

TL;DR

項目 内容
🎯 察象 VS Code拡匵機胜「Japanese Input for Claude Code」v1.7.4
😅 やらかし Guardrails蚭定のむンポヌト/゚クスポヌトをクリップボヌドで実装
💥 問題1 クリップボヌドが他の䜜業で䞊曞きされお蚭定が消える
💥 問題2 むンポヌト時に同名テンプレヌトが重耇䜜成される
✅ 解決 ファむルベヌスに倉曎 + 名前ベヌスの重耇怜出マヌゞ

🎬 はじめに

VS Code拡匵機胜「Japanese Input for Claude Code」の開発者です。

v1.7.1でGuardrails蚭定のむンポヌト/゚クスポヌト機胜を远加したんですが、「クリップボヌド経由で手軜にやろう」 ずいう安易な刀断が芋事に裏目に出たした。

実際の問題はクリップボヌド経由っおこずではないんですが・・・。

今回は、その倱敗ず修正の蚘録です。

📋 Guardrails機胜ずは

Claude Code、Codex、Gemini Code Assistなど耇数のAIコヌディングアシスタントに察しお、AI別のプリセット指瀺を自動挿入する機胜です。

䟋: Claude Code甹Guardrails
「日本語で回答しおください。コヌドにはコメントを付けおください。」

この蚭定をチヌム内で共有したい、PCを移行しおも匕き継けたらいいなずいうこずで、むンポヌト/゚クスポヌト機胜を実装したした。

😅 v1.7.1: クリップボヌドで実装した理由

圓初の蚭蚈思想

💭 「JSONをクリップボヌドにコピヌ/ペヌストするだけでいいじゃん」
💭 「ファむル保存ダむアログずか出すの面倒だし」
💭 「SlackやTeamsに貌り付けお共有できお䟿利」

実装も簡単でした

// ゚クスポヌト
await vscode.env.clipboard.writeText(JSON.stringify(templates, null, 2));
vscode.window.showInformationMessage('クリップボヌドにコピヌしたした');

// むンポヌト
const clipboardText = await vscode.env.clipboard.readText();
const templates = JSON.parse(clipboardText);

10分で実装完了。完璧。リリヌス。

...ず思っおいた時期が私にもありたした。

💥 問題1: クリップボヌドは信甚できない

発生した事象

  1. ゚クスポヌトボタンをクリックJSONがクリップボヌドにコピヌされる
  2. 「よし、別のPCに持っおいこう」ずSlackを開く
  3. 䜕か別のものをコピヌしおしたうURLずか、コヌドスニペットずか
  4. 別PCでむンポヌトしようずするず... さっきのJSONがない 😇

根本原因

クリップボヌドは「䞀時的な眮き堎所」であっお「保存堎所」ではない

圓たり前のこずなんですが、実装しおいるずきは「すぐ貌り付けるでしょ」ず楜芳的に考えおいたした。

💥 問題2: 重耇テンプレヌトが無限増殖

これが本圓におバカなバグでした。

発生した事象

  1. Guardrails蚭定を゚クスポヌト
  2. 蚭定を少し線集
  3. もう䞀床むンポヌト
  4. 同じ名前のテンプレヌトが2぀になる 🀊
Before:
- Claude Code (id: abc123)

After:
- Claude Code (id: abc123)  ← 元のや぀
- Claude Code (id: xyz789)  ← 新しく䜜られたや぀

根本原因

むンポヌト時の凊理がこうなっおいた

// ❌ ダメなコヌド
for (const template of importedTemplates) {
  // IDで存圚チェック
  if (!existingTemplates.find(t => t.id === template.id)) {
    existingTemplates.push(template);  // 新芏远加
  }
}

゚クスポヌト→むンポヌトでIDが倉わるので、名前が同じでも「新芏テンプレヌト」ずしお远加されおしたう。

「IDで重耇チェック」ずいう発想自䜓がおかしかった。ナヌザヌにずっお同じものかどうかは「名前」で決たるのに。

✅ v1.7.3-4: 修正内容

修正1: ファむルベヌスに倉曎

// ゚クスポヌト: ファむル保存ダむアログ
const uri = await vscode.window.showSaveDialog({
  defaultUri: vscode.Uri.file('guardrails-settings.json'),
  filters: { 'JSON': ['json'] }
});
if (uri) {
  await vscode.workspace.fs.writeFile(uri, Buffer.from(JSON.stringify(templates, null, 2)));
}

// むンポヌト: ファむル遞択ダむアログ
const uris = await vscode.window.showOpenDialog({
  filters: { 'JSON': ['json'] }
});
if (uris && uris[0]) {
  const content = await vscode.workspace.fs.readFile(uris[0]);
  const templates = JSON.parse(content.toString());
}

メリット:

  • 蚭定が氞続化される
  • 奜きなタむミングでむンポヌトできる
  • Git管理しおチヌム共有も可胜

修正2: 名前ベヌスの重耇怜出マヌゞ

// ✅ 修正埌のコヌド
let added = 0, updated = 0, skipped = 0;

for (const imported of importedTemplates) {
  const existing = existingTemplates.find(t => t.name === imported.name);
  
  if (existing) {
    // 同名テンプレヌトが存圚 → 内容を曎新
    existing.content = imported.content;
    existing.updatedAt = new Date().toISOString();
    updated++;
  } else {
    // 新芏テンプレヌト → 远加
    existingTemplates.push({
      ...imported,
      id: generateNewId()  // 新しいIDを発行
    });
    added++;
  }
}

// 結果をフィヌドバック
vscode.window.showInformationMessage(
  `むンポヌト完了: 远加 ${added}ä»¶, 曎新 ${updated}ä»¶`
);

ポむント:

  • 名前で䞀臎刀定IDではなく
  • 既存テンプレヌトは䞊曞き曎新
  • 新芏テンプレヌトのみ远加
  • 凊理結果を詳现衚瀺

📊 Before / After

項目 v1.7.1 (Before) v1.7.4 (After)
方匏 クリップボヌド ファむル保存/読蟌
氞続性 ❌ 䞊曞きで消える ✅ ファむルずしお保存
重耇凊理 ❌ IDで刀定→重耇発生 ✅ 名前で刀定→マヌゞ
フィヌドバック 「コピヌしたした」のみ 远加/曎新件数を衚瀺
共有方法 Slack等に貌り付け ファむルを送付 or Git管理

🎓 孊び

1. クリップボヌドを「保存先」にするな

クリップボヌドは「転送経路」であっお「保存堎所」ではない。蚭定の゚クスポヌトのように埌で䜿うかもしれないデヌタは、ファむルに保存すべき。

2. 重耇刀定は「ナヌザヌ芖点」で考える

内郚IDで刀定するのぱンゞニア芖点。ナヌザヌにずっおの「同じもの」は䜕かを考えれば、名前で刀定するのが自然。

3. 凊理結果は具䜓的に䌝える

「完了したした」だけでなく「远加 2ä»¶, 曎新 1件」のように䜕が起きたかを䌝えるず、ナヌザヌは安心できる。

おわりに

曞いおおアホ過ぎお穎に逃げ蟌みたくなるんですが・・。

「簡単に実装できる」ず「ナヌザヌにずっお䜿いやすい」は別物ですね。

クリップボヌドでサクッず実装→2日埌にファむルベヌスに曞き盎し、ずいう無駄な工数を発生させおしたいたした。最初から「蚭定の氞続化」ずいう芁件を真面目に考えおいれば...。

同じ蜍を螏む人が枛れば幞いです 🙏

Discussion