Windows Codex desktop app creates an empty .git folder, then spawns git process repetitively

Open 💬 13 comments Opened Jun 22, 2026 by MinetaS
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

Version 26.616.51431 • Released Jun 21, 2026

What subscription do you have?

Pro 5x

What platform is your computer?

Microsoft Windows NT 10.0.22631.0 x64

What issue are you seeing?

When the project is not a Git repository, Codex creates an empty .git folder, then subsequently spawns Git processes with this cmdline:

"C:\Program Files\Git\cmd\git.exe" -c core.hooksPath=NUL -c core.fsmonitor=true rev-parse --show-toplevel
"C:\Program Files\Git\cmd\git.exe" config --null --get core.fsmonitor
(and more)

This list seems to match "Observed Commands" section reported in #29408.

What steps can reproduce the bug?

It's difficult to find out which kinds of prompt exactly reproduce the bug, but at some point Windows sandbox touches .agents, .codex, .git which eventually leads to multiple empty directories.

Sandbox log (timezone is UTC+9):

[2026-06-23 06:42:35.134 codex.exe] START: C:\Users\***\.codex\.sandbox-bin\codex.exe --codex-run-as-fs-helper
[2026-06-22T21:42:35.235850600+00:00] applied deny ACE to protect C:\Users\***\***\.agents
[2026-06-22T21:42:35.236659900+00:00] applied deny ACE to protect C:\Users\***\***\.codex
[2026-06-22T21:42:35.237416+00:00] applied deny ACE to protect C:\Users\***\***\.git

What is the expected behavior?

  1. Codex should not create .agents, .codex, .git empty directories randomly.
  2. Codex should not repeatedly spawn Git processes when .git folder is empty or malformed.

Additional information

I believe this issue is the first that enlightens the connection between an unexpected sandbox behavior and the Git process issue.

View original on GitHub ↗

13 Comments

github-actions[bot] contributor · 28 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #29408
  • #29110
  • #28631

Powered by Codex Action

MinetaS · 27 days ago

#28631 reported a similar bug but it's about VS Code extension on Linux/WSL.
This issue is about Windows desktop app, but the underlying cause may be likely identical.

rasael · 25 days ago

I have the same issue, and it is problematic because the parent directory is where the real .git and .codex directories are located. As a result, the generated empty folder must be removed before new threads can correctly see my skills and git status again.

My current workaround is to delete those folders and reload the skills, but I have dozens of submodules under the parent directory, so this is quite annoying.

GuilhermeCouto · 25 days ago

I have the same issue, my codex creates a .git folder inside of my project folder(1 level below the project folder with original .git) and bugs my IDE

Apen · 23 days ago

Same problem here. My workaround is a PowerShell script that finds empty .git folders and "git init"s them.
Before that, I had a loooot of Git processes spawning continuously; now, a few at the beginning and after nothing.

privacyguy123 · 21 days ago

Same bug is back in todays build for me - the previous fix was to delete an orphaned .git folder in .codex but there isn't one there anymore.

rasael · 21 days ago

While waiting for a fix, I've taken the workaround script tip from @Apen and vibed a PowerShell script to identify and delete those empty folders. I now run it before any new thread and resumed 'normal' operation with codex.

The script searches from the root and enumerates all empty .git, .codex, .agents empty folders it finds and then deletes them; really saves me a lot of time.

privacyguy123 · 21 days ago
While waiting for a fix, I've taken the workaround script tip from @Apen and vibed a PowerShell script to identify and delete those empty folders. I now run it before any new thread and resumed 'normal' operation with codex. The script searches from the root and enumerates all empty .git, .codex, .agents empty folders it finds and then deletes them; really saves me a lot of time.

Where is this script?

Realistically where would I even have empty .git folders created "by mistake"?

rasael · 21 days ago
Where is this script?

I reccomend you vibe code with codex yourself, tailored for your specific case.

Here is my version, tailored for a multi module project:

<#
.SYNOPSIS
Finds and permanently deletes empty .agents, .codex, and .git folders.

.DESCRIPTION
Run this script from the repo root. The repo root is treated as the folder that
contains this script. The scan walks only through folders whose names do not
start with a dot, skips src and target folders, and it marks empty .agents,
.codex, and .git child folders for deletion. The candidate folder names and
excluded traversal folder names are configurable through the $CandidateNames and
$ExcludedTraversalNames lists near the top of the script.

.PARAMETER ForceDelete
Deletes the marked empty folders without prompting for confirmation.
#>
[CmdletBinding()]
param(
    [Alias('Force')]
    [switch] $ForceDelete
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

# Treat the folder containing this script as the repo root, no matter where the
# caller's current PowerShell location happens to be.
$RepoRoot = (Resolve-Path -LiteralPath $PSScriptRoot).ProviderPath

# Metadata folder names that should be deleted when they are empty.
$CandidateNames = @('.agents', '.codex', '.git')

# Directory names that should not be traversed while searching.
$ExcludedTraversalNames = @('src', 'target')

# Print a heartbeat every N scanned folders so long runs look alive.
$ProgressInterval = 250

function Test-EmptyDirectory {
    param(
        [Parameter(Mandatory = $true)]
        [string] $Path
    )

    if (-not (Test-Path -LiteralPath $Path -PathType Container)) {
        return $false
    }

    try {
        # Reading one child is enough to prove the directory is not empty.
        $firstItem = Get-ChildItem -LiteralPath $Path -Force -ErrorAction Stop | Select-Object -First 1
        return $null -eq $firstItem
    }
    catch {
        Write-Warning "Could not inspect folder: $Path"
        return $false
    }
}

function Get-ScannableDirectory {
    param(
        [Parameter(Mandatory = $true)]
        [string] $Root
    )

    # Use an explicit stack so traversal can stream paths as they are found.
    $stack = [System.Collections.Generic.Stack[string]]::new()
    $stack.Push($Root)

    while ($stack.Count -gt 0) {
        $current = $stack.Pop()
        $currentItem = Get-Item -LiteralPath $current -Force -ErrorAction Stop

        if (($currentItem.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -ne 0) {
            continue
        }

        # Emit the current folder before discovering its children.
        $current

        $children = Get-ChildItem -LiteralPath $current -Directory -Force -ErrorAction SilentlyContinue |
            Where-Object {
                # Do not descend into dot folders, configured exclusions, or links.
                $_.Name -notlike '.*' -and
                $_.Name -notin $ExcludedTraversalNames -and
                (($_.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -eq 0)
            } |
            Sort-Object -Property FullName -Descending

        foreach ($child in $children) {
            $stack.Push($child.FullName)
        }
    }
}

# Track marked folders separately from already-seen paths so duplicate discovery
# cannot print or delete the same path twice.
$markedFolders = [System.Collections.Generic.List[string]]::new()
$seenFolders = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
$scannedFolderCount = 0

Write-Host "Scanning under:"
Write-Host "  $RepoRoot"
Write-Host "Empty metadata folders will be printed as they are found."
Write-Host ''

# Stream the traversal so progress and found-folder output appears immediately.
Get-ScannableDirectory -Root $RepoRoot | ForEach-Object {
    $folder = $_
    $scannedFolderCount++

    if (($scannedFolderCount % $ProgressInterval) -eq 0) {
        Write-Host "Scanned $scannedFolderCount folders..."
    }

    foreach ($candidateName in $CandidateNames) {
        $candidatePath = Join-Path -Path $folder -ChildPath $candidateName

        # Mark only configured metadata folders that currently exist and are empty.
        if (Test-EmptyDirectory -Path $candidatePath) {
            $resolvedPath = (Resolve-Path -LiteralPath $candidatePath).ProviderPath

            if ($seenFolders.Add($resolvedPath)) {
                Write-Host "Found: $resolvedPath"
                $markedFolders.Add($resolvedPath)
            }
        }
    }
}

Write-Host ''
Write-Host "Scan complete. Scanned $scannedFolderCount folder(s)."

# Keep the final confirmation list stable and deterministic.
$markedFolders = @($markedFolders | Sort-Object -Unique)

if ($markedFolders.Count -eq 0) {
    Write-Host "No empty .agents, .codex, or .git folders found under:"
    Write-Host "  $RepoRoot"
    exit 0
}

Write-Host "The following empty folders are marked for permanent deletion:"
foreach ($folder in $markedFolders) {
    Write-Host "  $folder"
}

# The default path requires a typed confirmation; -ForceDelete skips only this
# prompt, not the final emptiness check before deletion.
if ($ForceDelete) {
    Write-Host ''
    Write-Host 'Force delete option supplied. Deleting without confirmation.'
}
else {
    Write-Host ''
    $confirmation = Read-Host 'Type DELETE to permanently remove these folders'

    if ($confirmation -cne 'DELETE') {
        Write-Host 'Cancelled. No folders were deleted.'
        exit 0
    }
}

$deletedCount = 0
$skippedCount = 0

foreach ($folder in $markedFolders) {
    # Re-check just before deleting so changed folders are skipped safely.
    if (Test-EmptyDirectory -Path $folder) {
        try {
            Remove-Item -LiteralPath $folder -Force -ErrorAction Stop
            Write-Host "Deleted: $folder"
            $deletedCount++
        }
        catch {
            Write-Warning "Could not delete folder: $folder"
            $skippedCount++
        }
    }
    else {
        Write-Warning "Skipped because it is no longer empty or no longer exists: $folder"
        $skippedCount++
    }
}

Write-Host ''
Write-Host "Done. Deleted $deletedCount folder(s). Skipped $skippedCount folder(s)." 
Realistically where would I even have empty .git folders created "by mistake"?

In my case codex creates those 2-3 empty folders for every module I open in codex

Scan complete. Scanned 2635 folder(s).
The following empty folders are marked for permanent deletion:
  R:\eda\cted\commons-desktop\commons-desktop-api\.agents
  R:\eda\cted\commons-desktop\commons-desktop-api\.codex
  R:\eda\cted\commons-desktop\commons-desktop-api\.git
  R:\eda\cted\commons-desktop\commons-desktop-graph\.agents
  R:\eda\cted\commons-desktop\commons-desktop-graph\.git
  R:\eda\cted\game\game-ui\.agents
  R:\eda\cted\game\game-ui\.codex
  R:\eda\cted\game\game-ui\.git
  R:\eda\cted\php-dashboard\.agents
  R:\eda\cted\php-dashboard\.git

note that the main .git file would be at R:\eda\cted\.git, and so is the main .codex folder.

privacyguy123 · 20 days ago

You must admit this is an absolutely gross fix - why are orphaned .git folders being created in the first place?

MinetaS · 20 days ago

I ended up with creating empty .agents, .codex, .git files (not folders) with proper ACLs to mitigate this for now.

It's kind of unfortunate that this has not been noticed by OpenAI teams yet. I'm seeing several duplicate issues which means there are quite amount of users impacted by this specific bug in sense of the performance degradation. Hopefully this will be addressed soon.

rolandorojas · 15 days ago

It looks like this behavior also triggers Windows Defender to continuously scan the git-hammered folder. In my case, this doubles or triples the performance hit caused by the bug.

It's extremely noticeable. I can hear my fans spinning and a second after closing Codex, everything quiets down.

amerina · 11 days ago

this problem fuck me every day😭,can god resolve this,because company us tfs still