File.ctime got reset when note properties were edited using Claude Code and CLI

I don’t know if this belongs here, because I don’t know if it’s a bug. I just wanted to have some feedback on it.

I was renaming two frontmatter properties across about 53 notes — just a simple find-and-replace on property names in the YAML. I used claude code (and have the CLI installed and active) to do it in bulk, it looks like it modified the files directly on disk. Afterward, I noticed that all 53 notes were showing today’s date as their creation date in my Base views.

The problem is that this seems to have reset file.ctime. Not sure if that’s expected behavior. So Obsidian now thinks all those notes were created today, which completely breaks any query or view that uses file.ctime to filter or sort by creation date — things like “notes created this year” or “on this day” views. Things I use for my review prompts.

Luckily I had a date created frontmatter property that survived, so my workflow wasn’t completely destroyed. But it would be great if Obsidian tracked creation dates internally — recorded the first time it ever saw a note. Does file.ctime rely on the filesystem? That way, no matter what happens to the file outside Obsidian, the original creation date stays intact.

I’ve used the custom property because it seemed more stable as a non-technical person. So, I’m glad I did it that way (for now).

This may or may not in the future, but all my notes have a created and modified property. As you can guess my templates set created when the note is created therefore no dependency on filesystem ctime which can be updated if using external tools. I use the linter plugin to format my notes and have it update modified when I change content on a note. This workflow works for me. YMMV.

I am using a similar (if not identical) approach. I base my queries on when I change something, not on when I touch a note. This is part of the reason I added a user-defined property.

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.