UPDATE: Claude and I have been doing some thinking on this issue. This is a summary Claude wrote up of everything we did after my trials and testings.
If you use Claude Code to help manage your Obsidian vault on Windows, you may or may not have noticed that notes Claude edits end up showing today’s date in any Bases views or Dataview queries that rely on file.ctime. It looks like Claude is creating brand new files when it’s actually just editing ones that have been in your vault for years.
The root cause is a Windows thing, not really a Claude thing. When Node.js (which powers Claude Code) writes to a file, it opens it using a Windows flag called CREATE_ALWAYS. Despite the name, this doesn’t literally delete and recreate the file — but Windows does reset the CreationTime as part of that operation, even on an existing file. On Linux/Mac this isn’t an issue because ctime means something different there, but on Windows it corrupts your creation timestamps.
The fix: a PostToolUse hook
Claude Code supports hooks — shell commands that run automatically after tool calls. We can use this to run a PowerShell script after every Edit or Write that reads the date created frontmatter property and restores the file’s CreationTime to match.
First, create the script at .claude/hooks/restore-ctime.ps1 inside your vault:
try {
$inputJson = [Console]::In.ReadToEnd()
$data = $inputJson | ConvertFrom-Json
$filePath = $data.tool_input.file_path
if (-not $filePath -or -not ($filePath -like '*.md')) { exit 0 }
if (-not (Test-Path $filePath)) { exit 0 }
$content = Get-Content $filePath -Raw -Encoding UTF8
if ($content -match '(?m)^date created:\s*(\d{4}-\d{2}-\d{2}[^\r\n]*)') {
$dateStr = $matches[1].Trim()
if ($dateStr) {
$date = [DateTime]::Parse($dateStr)
(Get-Item $filePath).CreationTime = $date
}
}
} catch {}
exit 0
Then wire it up in .claude/settings.local.json inside your vault (create it if it doesn’t exist):
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File
'C:/path/to/your/vault/.claude/hooks/restore-ctime.ps1'"
}
]
}
]
}
}
Restart Claude Code and it’s live. Every time Claude edits a note that has a date created (this is my user defined and template integrated name) property in its frontmatter, the script silently restores CreationTime to match. Notes without date created are left alone.
A couple of caveats:
-
This only works if you’re consistently filling in date created in your frontmatter. If the property is empty or missing, the script skips the file.
-
For notes that were already affected before you set this up, you can restore them manually with PowerShell:
(Get-Item 'path/to/note.md').CreationTime = [DateTime]::Parse('your-original-date')
-
This is Windows-specific. Mac/Linux users don’t have this problem.
Hopefully this saves someone else the headache of figuring out why all their “old” notes suddenly look brand new.
NOTE: The code is what Claude created and inserted into my vault. I have the original saved as .archive just in case. I’ve tested it and it’s worked. Use if you like. But I wanted to at least share what I’d found.