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.
enableFileCheckpointing is one of the query() options. It enables the CLI to take snapshots before and after tools modify files; once enabled, the caller can use q.rewindFiles(userMessageId, ...) to roll back files to the state they were in when a particular user message started processing. These two features must be used together: without checkpointing enabled, rewind is not available.
Enabling File Checkpoint
import { query } from '@qoder-ai/qoder-agent-sdk';
const q = query({
prompt: 'Refactor src/foo.ts into a clearer implementation',
options: {
cwd: '/path/to/project',
enableFileCheckpointing: true,
allowedTools: ['Read', 'Edit', 'Write'],
permissionMode: 'acceptEdits',
},
});
Advanced: when you also need to adjust other CLI configuration via settings
query() options also accepts a settings field — either a Settings object or an absolute path string to a settings file. Its relationship with enableFileCheckpointing:
- When passing a
settings object, the SDK automatically merges general.fileCheckpointing.enabled = true — no need to write it manually.
- When passing a
settings file path string, the SDK will not rewrite the file contents; you need to configure it yourself in that file:
{
"general": {
"fileCheckpointing": {
"enabled": true
}
}
}
Just setting enableFileCheckpointing: true without passing settings is sufficient for scenarios that only need rewind.
Using Explicit User Message IDs
Rewind uses user message IDs as anchor points. For precise rollback, it’s recommended to use structured input and generate your own uuid, so the UI can reliably reference “go back to before that message.”
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 into a two-line summary.',
},
],
},
};
// If your application needs to call rewind later within the same session,
// keep yielding subsequent user inputs here instead of closing the stream.
}
const q = query({
prompt: input(),
options: {
cwd: '/path/to/project',
enableFileCheckpointing: true,
allowedTools: ['Read', 'Write'],
permissionMode: 'acceptEdits',
},
});
Dry Run Preview
A dry run lets you see whether rollback is possible, which files would be affected, and overall insertion/deletion statistics. Dry run does not modify files.
The returned RewindFilesResult contains these fields:
| Field | Type | Description |
|---|
canRewind | boolean | Whether rollback can be performed. In dry run mode failures don’t throw — this field indicates the status |
error | string? | Diagnostic message when canRewind=false, can be displayed directly to the user |
filesChanged | string[]? | Absolute paths of affected files — useful for listing each file that will be reverted in the UI |
insertions | number? | Total lines that were inserted and will be “undone” by the rollback (aggregate) |
deletions | number? | Total lines that were deleted and will be “undone” by the rollback (aggregate) |
The SDK currently only returns the list of affected files and aggregate line-level statistics in RewindFilesResult — it does not return per-file diffs. If you need per-file differences, you can read the disk contents based on filesChanged after the dry run and compare them with the checkpoint, or use git/workspace diffing tools after executing the rewind.
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}`);
}
Executing Rewind
const result = await q.rewindFiles(userMessageId);
console.log(result.filesChanged);
Failure Semantics
| Call Form | Behavior When Rewind Is Not Possible |
|---|
rewindFiles(id, { dryRun: true }) | Resolves with { canRewind: false, error }, convenient for displaying diagnostics in the UI |
rewindFiles(id) (execution mode) | Promise rejects; the caller should use try/catch to display the failure reason |
try {
await q.rewindFiles(userMessageId);
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
}
Options Reference
| Field | Type | Description |
|---|
enableFileCheckpointing | boolean | Enable file checkpointing for use with rewindFiles() |
settings | string | Settings | Settings passed to the CLI; when passing an object, the SDK merges general.fileCheckpointing.enabled |
Return Value Reference
type RewindFilesResult = {
canRewind: boolean;
error?: string;
filesChanged?: string[];
insertions?: number;
deletions?: number;
};
Best Practices
- Save user message IDs: Applications that need rollback capability should save the
uuid when sending messages; do not rely on UI text to look them up.
- Dry run before rewinding: Show the impact scope first, then let the user confirm the rollback.
- Refresh UI after rollback: Rewind only changes files, not conversation history; the UI needs to reload relevant views based on
filesChanged.
- Show
error to the user on failure: The error text when canRewind=false can typically be displayed directly to end users for diagnostics.