> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ファイル Checkpoint と Rewind

`enableFileCheckpointing` を使用すると、CLI がツールによるファイル変更の前後でスナップショットを取得します。その後、ホストは `q.rewindFiles(userMessageId, ...)` でファイルを特定のユーザーメッセージの処理開始時の状態へ Rewind できます。この2つは連携して使用する必要があります：checkpoint が有効でなければ、Rewind は使用できません。

<div id="ファイル-checkpoint-の有効化" />

## ファイル checkpoint の有効化

```typescript theme={null}
import { query } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: 'Refactor src/foo.ts into a cleaner implementation',
  options: {
    cwd: '/path/to/project',
    enableFileCheckpointing: true,
    allowedTools: ['Read', 'Edit', 'Write'],
    permissionMode: 'acceptEdits',
  },
});
```

> **応用: `settings` で他の CLI 設定も同時に変更する場合**
>
> `query()` の options には `settings` フィールドもあり、`Settings` オブジェクトまたは settings ファイルの絶対パス文字列を渡せます。`enableFileCheckpointing` との関係は以下の通りです：
>
> * `settings` オブジェクトを渡す場合、SDK は `general.fileCheckpointing.enabled = true` を自動的にマージします（手動で書く必要はありません）。
> * `settings` ファイルパス文字列を渡す場合、SDK はファイル内容を書き換えないため、そのファイル内で自分で設定する必要があります：
>
> ```json theme={null}
> {
>   "general": {
>     "fileCheckpointing": {
>       "enabled": true
>     }
>   }
> }
> ```
>
> rewind のみを使用するシナリオでは、`enableFileCheckpointing: true` を設定するだけで十分です。`settings` を渡す必要はありません。

***

<div id="明示的な-user-message-id-の使用" />

## 明示的な user message id の使用

Rewind はユーザーメッセージ ID をアンカーポイントとして使用します。正確な Rewind が必要な場合は、構造化入力を使用して自分で `uuid` を生成することを推奨します。これにより UI が安定的に「そのメッセージの前に戻る」を特定できます。

```typescript theme={null}
import { randomUUID } from 'node:crypto';
import { query } from '@qoder-ai/qoder-agent-sdk';

const userMessageId = randomUUID();

async function* input() {
  yield {
    type: 'user' as const,
    uuid: userMessageId,
    parent_tool_use_id: null,
    message: {
      role: 'user' as const,
      content: [
        {
          type: 'text' as const,
          text: 'Rewrite notes.txt as a two-line summary.',
        },
      ],
    },
  };

  // 同じセッション内で後から rewind を呼び出す必要がある場合は、
  // ストリームを閉じずにここで後続のユーザー入力を yield し続けてください。
}

const q = query({
  prompt: input(),
  options: {
    cwd: '/path/to/project',
    enableFileCheckpointing: true,
    allowedTools: ['Read', 'Write'],
    permissionMode: 'acceptEdits',
  },
});
```

***

<div id="dry-run-プレビュー" />

## Dry run プレビュー

先に dry run を行うことで、Rewind 可能かどうか、影響を受けるファイル、挿入/削除の統計を確認できます。Dry run はファイルを変更しません。

返される `RewindFilesResult` には以下のフィールドが含まれます：

| フィールド          | 型           | 説明                                                    |
| -------------- | ----------- | ----------------------------------------------------- |
| `canRewind`    | `boolean`   | ロールバックを実行できるかどうか。dry run の失敗時はエラーをスローせず、このフィールドで示します  |
| `error`        | `string?`   | `canRewind=false` 時の診断メッセージ。ユーザーに直接表示できます             |
| `filesChanged` | `string[]?` | 影響を受けるファイルの絶対パスのリスト。UI でロールバックされる各ファイルを一覧表示するのに使用できます |
| `insertions`   | `number?`   | ロールバックで「元に戻す」挿入行の合計数（集計値）                             |
| `deletions`    | `number?`   | ロールバックで「元に戻す」削除行の合計数（集計値）                             |

> SDK は現在、`RewindFilesResult` で影響を受けるファイルのリストと行レベルの集計統計のみを返します。ファイルごとの diff は返しません。ファイルごとの差分を表示する必要がある場合は、dry run 後に `filesChanged` をもとにディスクの内容を読み取ってチェックポイントと比較するか、rewind 実行後に git/ワークスペースの差分ツールを使用してください。

```typescript theme={null}
const preview = await q.rewindFiles(userMessageId, { dryRun: true });

if (!preview.canRewind) {
  // Show the diagnostic message in the UI.
  console.error(preview.error);
  return;
}

// Overall stats across all affected files.
console.log({
  files: preview.filesChanged?.length ?? 0,
  insertions: preview.insertions ?? 0,
  deletions: preview.deletions ?? 0,
});

// Per-file listing — useful for a confirmation dialog.
for (const file of preview.filesChanged ?? []) {
  console.log(`will be reverted: ${file}`);
}
```

***

<div id="rewind-の実行" />

## Rewind の実行

```typescript theme={null}
const result = await q.rewindFiles(userMessageId);
console.log(result.filesChanged);
```

***

<div id="失敗のセマンティクス" />

## 失敗のセマンティクス

| 呼び出し形式                              | Rewind 不可時の動作                                             |
| ----------------------------------- | --------------------------------------------------------- |
| `rewindFiles(id, { dryRun: true })` | `{ canRewind: false, error }` で resolve し、UI に診断情報を表示可能   |
| `rewindFiles(id)`（実行モード）            | Promise が reject されるため、呼び出し元は `try/catch` で失敗理由を表示することを推奨 |

```typescript theme={null}
try {
  await q.rewindFiles(userMessageId);
} catch (error) {
  console.error(error instanceof Error ? error.message : String(error));
}
```

***

<div id="options-クイックリファレンス" />

## Options クイックリファレンス

| フィールド                     | 型                    | 説明                                                                        |
| ------------------------- | -------------------- | ------------------------------------------------------------------------- |
| `enableFileCheckpointing` | `boolean`            | ファイル checkpoint を有効化し、`rewindFiles()` で使用                                 |
| `settings`                | `string \| Settings` | CLI に渡す settings；オブジェクトの場合 SDK が `general.fileCheckpointing.enabled` をマージ |

***

<div id="戻り値リファレンス" />

## 戻り値リファレンス

```typescript theme={null}
type RewindFilesResult = {
  canRewind: boolean;
  error?: string;
  filesChanged?: string[];
  insertions?: number;
  deletions?: number;
};
```

***

<div id="ベストプラクティス" />

## ベストプラクティス

* **user message id を保存する**：Rewind 機能が必要なホストアプリケーションはメッセージ送信時に `uuid` を保存し、UI テキストの特定に依存しないでください。
* **Rewind 前に dry run を行う**：まず影響範囲を表示し、その後ユーザーに Rewind の実行を確認させてください。
* **Rewind 後に UI をリフレッシュ**：Rewind はファイルのみを変更し、会話履歴は変更しません。UI は `filesChanged` に基づいて関連ビューを再読み込みする必要があります。
* **失敗時にユーザーに `error` を表示**：`canRewind=false` 時の `error` テキストは通常、エンドユーザーに直接表示して診断に使用できます。
