microsoft / microsoft/foundry-local

The default model cache location cannot be reclaimed by any Windows uninstall: MSI, setup.exe and MSIX all leave gigabytes behind

Open
#912 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
2.6k
Forks
369
Avg merge
2d 17h
Merged PRs (30d)
39

Description

## Summary

Foundry Local defaults its model cache to `%USERPROFILE%\.`, a dot-directory at
the root of the user profile. For a 7B class model that is several gigabytes per
application.

Nothing on Windows will ever remove it. This is not a gap in one packaging technology, it
is true of all of them, and in each case it is the documented and intended behaviour of
that technology rather than a bug we could ask them to fix:

| Installer | What uninstall removes | Reclaims the model cache |
|---|---|---|
| Windows Installer (MSI) | Components it installed and registered | **No.** Runtime created user data is deliberately left in place |
| setup.exe / custom bootstrapper | Whatever the author wrote | **No,** unless someone writes and tests a custom removal step |
| MSIX | Package payload, plus the package's own app data | **No.** The cache is outside package identity, and MSIX has no custom uninstall actions by design |

So an application can be cleanly uninstalled, leave no trace of itself in Programs and
Features, and still leave 7 GB in the user profile permanently. The user has no reason to
associate the leftover directory with the application they just removed, and in fact
nothing in the directory name mentions Foundry Local at all.

**What we are asking for:** default the cache to a location that the platform can reclaim.
For packaged applications that means somewhere under package identity. For unpackaged
applications it means `%LocalAppData%` plus a documented removal path, since nothing will
do it automatically.

## Why "the application should clean up after itself" does not work

This is the obvious objection, so it is worth addressing directly. It fails for both
packaging models, for different reasons.

**MSIX has no custom uninstall actions, by design.** A packaged application cannot run code
at uninstall. That is a deliberate part of the model and a large part of why MSIX uninstall
is reliable: the platform removes the package payload and the package's own app data, and
nothing else runs. The platform will happily clean up `LocalCache` and `LocalState` under
the package identity. It cannot clean up a dot-directory in the profile root, because as
far as Windows is concerned that has nothing to do with the application.

**Windows Installer deliberately preserves user data.** Removing files created at runtime
is not what uninstall does, and the guidance is explicit that user data should be
preserved. Reclaiming the cache would need a bespoke custom action, pointed at a path the
author first had to discover by reading the SDK's source or inspecting the disk, kept in
step with any future change to the layout, and run on a path that is per user while the
uninstall may not be. Uninstall paths are also the least tested code in most products.

So in both cases the application either cannot do it, or can only do it by writing fragile
code against an undocumented layout. The only thing that reliably fixes it is the default.

## The location is also outside every cleanup mechanism

Because it is a dot-directory in the profile root rather than a Windows application data
location, it is invisible to everything a user would reach for:

- **Settings, Apps** cannot attribute it to an application, because it does not belong to
one as far as the platform knows.
- **Settings, Storage** shows it as undifferentiated user files.
- **Storage Sense** and **Disk Cleanup** do not consider profile dot-directories.
- **Reset and Repair** for a packaged application clears `LocalCache` and `LocalState`, and
does not touch this.

The result is several gigabytes per application that is unattributable, unreclaimable, and
invisible to the tools whose whole job is finding and reclaiming disk space.

## Asks

1. **Default packaged applications to a location under package identity.** `LocalCache` is
the natural fit, since a downloaded model is precisely a large regenerable cache: it is
removed automatically on uninstall, it is cleared by Reset, and Windows may reclaim it
under storage pressure, all of which are correct behaviours for a file that can be
downloaded again.
2. **Default unpackaged applications to `%LocalAppData%`**, so the data is where Windows
developers and Windows tooling expect application data to live.
3. **Document a supported removal path**, because unpackaged applications will still need
to remove it deliberately. Today an author has to reverse engineer the layout, and any
code they write against it can break silently.
4. **Provide a way to enumerate caches and report total size.** Without this there is no
way for an application, or a user, to discover what Foundry Local is consuming or to
reclaim it. This is also what would let a support engineer answer "why is this disk
full".

Item 1 is the important one, and it is a change of default rather than new functionality:
`Configuration` already exposes `AppDataDir` and `ModelCacheDir`, and we verified with a
probe that setting `AppDataDir` relocates everything, including `cache\models` and `logs`,
with the profile-root default never being created. The capability is there. The default is
the defect.

Contributor guide

Open the contributing guide

Research direction

Start by tracing the defaults exposed through Configuration.AppDataDir and Configuration.ModelCacheDir, then confirm how packaged and unpackaged Windows applications resolve those paths. Use the existing probe described in the issue to verify cache and log relocation. Done means packaged applications default under package identity, unpackaged applications default under %LocalAppData%, and a supported removal path is documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
desktop, operating-systems
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.