Skip to content

Instantly share code, notes, and snippets.

@ntcho
Last active April 11, 2025 20:24
Show Gist options
  • Save ntcho/93082b1f60d567071ba7dd5f1d0716ba to your computer and use it in GitHub Desktop.
Save ntcho/93082b1f60d567071ba7dd5f1d0716ba to your computer and use it in GitHub Desktop.
Recover files from VSCode file history
// Find and recover the first/last entry from VSCode edit history
import fs from "fs-extra";
import os from "os";
import path from "path";
const recoverDir = "/path/to/recover"
// Path to search for history files
const prevRoot = "file://" + recoverDir;
// Path to save recovered files
const nextRoot = "./recovered";
// VSCode history directory
// TODO: make this cross-platform (currently only works on MacOS)
const historyDir = os.homedir() + "/Library/Application Support/Code/User/History";
// List of files found with prevRoot
const historyEntries = {};
// Read all edit history metadata files (entries.json)
await Promise.all(
fs.readdirSync(historyDir).map(async (d) => {
const file = `${historyDir}/${d}/entries.json`;
if (!fs.existsSync(file)) return;
const metadata = await fs.readJSON(file);
if (metadata && metadata.resource.startsWith(prevRoot)) {
historyEntries[d] = {
...metadata,
entries: metadata.entries.sort((a, b) => a.timestamp - b.timestamp),
};
}
})
);
console.log(`Found ${Object.keys(historyEntries).length} files with edit history:`);
console.log(
Object.values(historyEntries)
.map((e) => String(e.resource).substring(prevRoot.length))
.sort()
.join("\n")
);
// Copy last/first entries to nextRoot
await Promise.all(
Object.entries(historyEntries).map(async ([fileId, { resource, entries }]) => {
const getPathMap = (entry) => [
path.join(historyDir, fileId, entry.id),
path.join(nextRoot, resource.substring(prevRoot.length)),
];
// find the last entry
const [prevPath, nextPath] = getPathMap(entries.at(-1));
// copy the last entry to current dir
fs.copy(prevPath, nextPath, (err) => {
if (err) console.error(`Error copying ${prevPath} -> ${nextPath}:`, err);
});
// check whether there is more then 1 entry
if (entries.length <= 1) return;
// find the first entry (intial state)
let [prevPathInit, nextPathInit] = getPathMap(entries.at(0));
// check whether the file has any content
const stats = fs.statSync(prevPathInit);
if (stats.size === 0) return;
const parsed = path.parse(nextPathInit);
nextPathInit = path.join(parsed.dir, parsed.name + "_init" + parsed.ext);
fs.copy(prevPathInit, nextPathInit, (err) => {
if (err) console.error(`Error copying ${prevPathInit} -> ${nextPathInit}:`, err);
});
})
);

Recover files from VSCode file history

Did you just rm -rf ./code? If you use VSCode, you are in the right place to recover your code. (don't ask why I wrote this script)

Edit the recoverDir in the script below, and run node ./recover.js and your files will be copied with the original folder structure.

You will need Node and npm install fs-extra. The script is only tested on MacOS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment