Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Pachanga12/Kopia_Desk_Beta_1/llms.txt

Use this file to discover all available pages before exploring further.

Once the UI has computed which files are new or changed, these six methods carry out the actual backup. Before starting, journalPeek() checks whether a previous run was interrupted; if so, journalCheck() cleans up any partial writes. The recommended copy pattern is: call planConcurrency() to pick the right parallelism for the destination drive, optionally call backupCopyVersions() to preserve the files that are about to be overwritten, then call backupCopyFiles() to copy everything in parallel. When the operation finishes, logSave() persists the results as a timestamped JSON report.

journalPeek(destRoot)

Inspects the journal directory on the backup drive and reports whether any previous backup run was interrupted, without deleting or modifying any files. The UI calls this on startup so it can warn the user before beginning a new backup run. The journal directory is located at <destRoot>/KopiaDesk_Backup/.kopia-data/journal/. Journal files use an append-only JSONL format: the first line records all planned destinations; subsequent lines record each file as it is successfully written. If the process is killed before backupCopyFiles() completes, the journal remains on disk with the pending entries still absent. journalPeek() reads these files to count the files that were planned but never completed.
destRoot
string
required
Root path of the backup drive, e.g. "E:\\". The journal directory is derived from this path.
Returns: Promise<{ found: number, pendingFiles: number, lastInterruptedAt: string | null }>
found
number
required
Number of journal files found. 0 means no previous backup was interrupted.
pendingFiles
number
required
Total number of files that were planned but not confirmed as written across all found journal files. A value greater than 0 indicates at least one incomplete backup.
lastInterruptedAt
string | null
required
ISO 8601 timestamp of the most recent interrupted backup’s start time, or null if none was found or all journals lacked a startedAt field.
const { found, pendingFiles, lastInterruptedAt } = await window.kopiaAPI.journalPeek('E:\\');
if (found > 0) {
  console.log(`Interrupted backup detected: ${pendingFiles} files pending since ${lastInterruptedAt}`);
}
// { found: 1, pendingFiles: 14, lastInterruptedAt: '2024-11-15T10:30:00.000Z' }
journalPeek() returns { found: 0, pendingFiles: 0, lastInterruptedAt: null } when the journal directory does not exist—this is the normal state after a clean backup completes, since backupCopyFiles() deletes the journal file on success.

journalCheck(destRoot)

Reads all journal files in the backup drive’s journal directory, deletes any partially-written files that were planned but never confirmed, and then removes the journal files themselves. Call this method only after journalPeek() has confirmed that an interrupted backup exists and the user has acknowledged the cleanup.
destRoot
string
required
Root path of the backup drive, e.g. "E:\\".
Returns: Promise<{ found: number, filesCleaned: number, lastInterruptedAt: string | null }>
found
number
required
Number of journal files that were processed and deleted.
filesCleaned
number
required
Number of partially-written backup files that were removed from the backup drive.
lastInterruptedAt
string | null
required
ISO 8601 timestamp from the most recent processed journal’s startedAt field, or null if not available.
// First peek to see if cleanup is needed:
const peek = await window.kopiaAPI.journalPeek('E:\\');
if (peek.found > 0) {
  // Show confirmation UI, then on user confirmation:
  const result = await window.kopiaAPI.journalCheck('E:\\');
  console.log(`Cleaned ${result.filesCleaned} partial files from ${result.found} interrupted backup(s)`);
  // { found: 1, filesCleaned: 14, lastInterruptedAt: '2024-11-15T10:30:00.000Z' }
}
journalCheck() permanently deletes files from the backup drive. Always call journalPeek() first and present the result to the user before invoking this method.

planConcurrency(driveRoot, avgFileSize)

Queries PowerShell for the physical disk’s MediaType and BusType via Get-Partition and Get-PhysicalDisk, then applies the pickConcurrency heuristic from lib/core.js to suggest the number of parallel copy workers that will give the best throughput on that drive.
driveRoot
string
required
Root path of the destination drive, e.g. "E:\\". The drive letter is extracted with a regex (/^([A-Za-z])/) before being passed to the PowerShell script.
avgFileSize
number
required
Average file size of the files that will be copied, in bytes. Used by pickConcurrency to decide whether to favour the high or low end of each drive type’s concurrency range. Files smaller than 2 MB are treated as “many small files” and receive higher concurrency.
Returns: Promise<{ concurrency: number, driveInfo: DriveInfo }>
concurrency
number
required
Recommended number of parallel copy workers based on pickConcurrency:
Drive typeSmall files (< 2 MB avg)Large files
HDD (mediaType === "HDD")21
SSD or NVMe84
Unknown / USB42
driveInfo
object
required
Raw drive type data returned by PowerShell. Falls back to { mediaType: "Unknown", busType: "Unknown" } if the PowerShell call fails or times out.
const { concurrency, driveInfo } = await window.kopiaAPI.planConcurrency('E:\\', 500000);
// { concurrency: 4, driveInfo: { mediaType: 'SSD', busType: 'SATA' } }

backupCopyFiles(tasks, options)

Copies an array of files to the backup drive with a bounded parallel worker pool. A journal is started on the destination drive before any files are written and deleted on success; if the process is interrupted mid-copy the journal remains on disk so journalPeek() / journalCheck() can detect and clean up partial writes on the next run.
tasks
CopyTask[]
required
Array of file copy instructions.
options
object
Optional copy behaviour flags.
Returns: Promise<{ copied: number, errors: ErrorEntry[], deduped: number }>
copied
number
required
Total number of files successfully processed (includes both copied and deduped files).
errors
ErrorEntry[]
required
Files that could not be copied.
deduped
number
required
Number of files skipped via hard-link deduplication (only non-zero when options.dedup is true).

Progress events

While backupCopyFiles() is running it emits a progress IPC event after each file completes. Subscribe with window.kopiaAPI.onProgress() before calling this method.
FieldTypeDescription
phase"backup"Constant identifier for this operation type
currentnumberNumber of files completed so far
totalnumberTotal number of tasks in this call
filestringrelativeDest of the file just processed
percentnumberMath.round((current / total) * 100)
const unsubscribe = window.kopiaAPI.onProgress(({ phase, percent, file }) => {
  console.log(`${phase} ${percent}% — ${file}`);
});

const result = await window.kopiaAPI.backupCopyFiles(
  [
    {
      srcPath: 'C:\\Users\\User\\Pictures\\photo.jpg',
      destRoot: 'E:\\',
      relativeDest: 'KopiaDesk_Backup\\Pictures\\photo.jpg'
    }
  ],
  { concurrency: 4, dedup: true }
);

unsubscribe();
// result: { copied: 1, errors: [], deduped: 0 }
Always call unsubscribe() after the operation completes. Leaving the listener attached means your callback will fire for the next backup or restore operation as well.

backupCopyVersions(tasks)

Gzip-compresses existing backup files to a .gz sibling before they are overwritten by the new copy. Call this method before backupCopyFiles() so that the previous version of each changed file is preserved. Files that are listed in the manifest but are no longer physically present on the backup drive are counted as skipped, not errors.
tasks
VersionTask[]
required
Array of versioning instructions. srcPath points to the current file on the backup drive (the one about to be overwritten), not the source on the local PC.
Returns: Promise<{ copied: number, skipped: number, errors: ErrorEntry[] }>
copied
number
required
Number of files successfully compressed and written.
skipped
number
required
Number of entries where srcPath did not exist on the backup drive. These are not errors; the file simply has no prior version to preserve.
errors
ErrorEntry[]
required
Files that existed but could not be compressed. See ErrorEntry definition under backupCopyFiles.
// Preserve previous versions before overwriting them:
await window.kopiaAPI.backupCopyVersions(versionTasks);
// Then copy the new versions:
await window.kopiaAPI.backupCopyFiles(copyTasks, { concurrency: 4 });

logSave(destRoot, sourceName, report)

Persists an operation report object as a formatted JSON file in the backup drive’s .kopia-data/logs/ directory. The file name encodes both the sanitised source name and a timestamp derived from new Date().toISOString() (colons and dots replaced with hyphens). Saved path: <destRoot>/KopiaDesk_Backup/.kopia-data/logs/<safeName(sourceName)>_<timestamp>.json
destRoot
string
required
Root of the destination drive, e.g. "E:\\".
sourceName
string
required
Human-readable source folder name. Sanitised through safeName() (illegal filename characters replaced with _, maximum 120 characters) before use in the file path.
report
object
required
Any JSON-serialisable object. Typically includes totals (files copied, errors, duration) assembled by renderer/app.js after the backup run.
Returns: Promise<string> — the absolute path to the saved log file.
const logPath = await window.kopiaAPI.logSave('E:\\', 'Pictures', {
  startedAt: '2024-11-15T10:30:00.000Z',
  finishedAt: '2024-11-15T10:31:45.000Z',
  copied: 42,
  errors: [],
  deduped: 3
});
// 'E:\\KopiaDesk_Backup\\.kopia-data\\logs\\Pictures_2024-11-15T10-31-45-000Z.json'

Build docs developers (and LLMs) love