0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🙈 クリップボードでインポート/エクスポート実装したら事故った話【VS Code拡張開発】

0
Last updated at Posted at 2025-12-29

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日後にファイルベースに書き直し、という無駄な工数を発生させてしまいました。最初から「設定の永続化」という要件を真面目に考えていれば...。

同じ轍を踏む人が減れば幸いです 🙏

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?