Skip to content

Conversation

@jshigetomi
Copy link
Collaborator

@jshigetomi jshigetomi commented Nov 21, 2025

PR Summary

This pull request introduces support for a configurable PSContentPath in PowerShell, allowing users to get and set the location where user-specific content (like modules, profiles, and help files) is stored. It adds new cmdlets for managing this path, updates internal logic to use the new path consistently, and ensures backward compatibility and migration from legacy locations.

Key changes include:

New Cmdlets for PSContentPath Management:

  • Added new Get-PSContentPath and Set-PSContentPath cmdlets to allow users to retrieve and configure the PSContentPath easily. These cmdlets include validation and user feedback. [1] [2] [3]

Configuration and Platform Support:

  • Implemented logic in PowerShellConfig and Utils to get and set the PSContentPath, defaulting to platform-appropriate locations (e.g., Documents\PowerShell on Windows, XDG data directory on Unix) if not configured. [1] [2] [3]
  • Introduced a new constant PSUserContentPathEnvVar for configuration key consistency.

Core Engine and Module Path Updates:

  • Updated ModuleIntrinsics to use the new PSContentPath for the personal module path and to exclude both old and new locations during migration scenarios. Ensured the module path falls back to the correct location if not explicitly set. [1] [2] [3]
  • Updated help and profile path utilities to use the new PSContentPath, with defensive fallbacks for edge cases. [1] [2]

Other Improvements and Cleanups:

  • Excluded the new PSContentPath feature from experimental feature listings to avoid confusion.
  • Minor doc and formatting cleanups in related code. [1] [2] [3]

PR Context

This change represents a major milestone for the PowerShell ecosystem—one that has been long requested by the community, discussed extensively, and is finally becoming a reality. The feature originated from community feedback in #15552, aligns with related work in PowerShell/PSResourceGet#1912, and was shaped through detailed specifications in PowerShell/PowerShell-RFC#388.

This feature lays the foundation for flexible, user-configurable PowerShell content storage, addressing scenarios such as roaming profiles and containerized environments.

By enabling customization of content paths, we empower users to adapt PowerShell to modern deployment and security requirements.

PR Checklist

@jshigetomi jshigetomi added the CL-Experimental Indicates that a PR should be marked as an Experimental Feature in the Change Log label Nov 21, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an experimental feature called PSContentPath that changes the default location for PowerShell user content (modules, scripts, help, and profiles) from Documents\PowerShell to LocalAppData\PowerShell on Windows, and provides a configurable path via Get-PSContentPath and Set-PSContentPath cmdlets. The feature includes lazy migration logic to move config files from the old location to the new location when the experimental feature is enabled.

Key changes:

  • Adds experimental feature PSContentPath with new cmdlets to get/set the content path
  • Implements lazy migration from old config directory to new default location (LocalAppData)
  • Updates all content path references to use the centralized Utils.GetPSContentPath() API

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
ExperimentalFeature.cs Adds PSContentPath experimental feature definition
GetSetPSContentPathCommand.cs New cmdlets for getting and setting PSContentPath with validation
PSConfiguration.cs Adds GetPSContentPath/SetPSContentPath methods and lazy migration logic
Utils.cs Adds GetPSContentPath() helper method with fallback logic
CorePsPlatform.cs Adds DefaultPSContentDirectory constant for the new default location
ModuleIntrinsics.cs Updates GetPersonalModulePath and SetModulePath to use new API
HostUtilities.cs Updates profile path logic to use GetPSContentPath
HelpUtils.cs Updates help search path to use GetPSContentPath
InitialSessionState.cs Registers new Get/Set-PSContentPath cmdlets

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@iSazonov
Copy link
Collaborator

If user intention is to migrate content to new location I believe the new cmdlets should help them.
I'd like to get not only current content path but size too Get-PSContentPath -MeasureSize.

@kilasuit
Copy link
Collaborator

kilasuit commented Nov 23, 2025

@jshigetomi - Please mark this PR as a Draft & go through the PR checklist & mark things appropriately add some PR Context as is requested in the PR template.

Until all thats done we shouldn't look to accept this pr.

You can do better than this & should do so in future too.
@iSazonov re this
I'd like to get not only current content path but size too Get-PSContentPath -MeasureSize.
I don't disagree on having that ability too.

@jshigetomi jshigetomi marked this pull request as draft November 23, 2025 04:23
@jshigetomi
Copy link
Collaborator Author

@kilasuit - Thanks for calling me out on that. Definitely intended this as a draft.

@microsoft-github-policy-service microsoft-github-policy-service bot added the Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept label Nov 26, 2025
@microsoft-github-policy-service microsoft-github-policy-service bot removed the Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept label Dec 1, 2025
@iSazonov
Copy link
Collaborator

If we try to automate migration, it will most likely be a breaking change, because we cannot know all the real scenarios.
Historically, MSFT's policy is to avoid such situations. It is great policy.
Automation also eliminates the possibility of having this innovation as an experimental feature, since disabling it will not revert the migration operations performed.

To avoid these problems, I see one way - to put the new paths in the first place and keep the old ones in the second.
Then installing a new OS system or updating pwsh on existing OS systems won't break anything. At least there is a low risk, which is always present when updating versions.
New modules (resources) will be installed using new paths. If this breaks something, users can either migrate their environment or just disable the new feature without extra steps (coping files back).

Gradually, all the resources will end up in new folders.

Then, at the second stage (v7.7?), we will be able to disable the old paths by default, but users will be able to turn them back on explicitly.
At the third stage (v7.8?), the old paths can be excluded from the code altogether.

@kilasuit
Copy link
Collaborator

Question: Should Get-PSContentPath support a -Legacy parameter to return the old Documents/OneDrive path?

I think this makes sense too.

Then, at the second stage (v7.7?), we will be able to disable the old paths by default, but users will be able to turn them back on explicitly.
At the third stage (v7.8?), the old paths can be excluded from the code altogether.

I think the plan would be that this is all contained within 7.6.x as not to drag this out for more years but that's something that @jshigetomi & team can confirm on, but that was my expectation at least

@doctordns
Copy link
Collaborator

It's probably too late, but I wondered if setting the content path for a given PWSH session could not be set in JSON such as powershell,config.json It would decrease the need for cmdlets. A community module could add functions to get-/set) if really needed.

@kilasuit
Copy link
Collaborator

@doctordns if added to powershell.config.json it would not negate or decrease the need for a cmdlet here as tbh most don't seem AFAIK to make use of that file, though happy to be wrong on that.
Also no this cannot be a community module, it needs to be a Microsoft one and if needed can be shipped seperately to the gallery and pulled in to the release via this PSGalleryModules.csproj file

@jshigetomi
Copy link
Collaborator Author

jshigetomi commented Dec 18, 2025

@iSazonov

Gradually, all the resources will end up in new folders.

I am concerned about this step. I believe users will not know about this feature and not enable the experimental feature to begin the gradual moving of resources.

To help with this transition we can eventually disable the old path by default like you said. But this would out of the box break users who haven't migrated, which I suspect could be the majority. The fix in that situation would be to Set-PSContentPath -Path "ONEDRIVE".

Maybe we can start off the PSContentPath feature to be OneDrive out of the box. This way it doesn't break users but allows them to customize their path to a desired location. They can then use something like the following to set it easily in default known locations.

Set-PSContentPath -LocalAppData  ## These parameters don't exist yet but open to adding them
Set-PSContentPath -OneDrive

@jshigetomi
Copy link
Collaborator Author

@doctordns

It's probably too late, but I wondered if setting the content path for a given PWSH session could not be set in JSON such as powershell,config.json It would decrease the need for cmdlets. A community module could add functions to get-/set) if really needed.

I believe a file of some sort is necessary to persist the PSContentPath setting across all pwsh sessions. The user config file, powershell.config.json, was chosen because it already existed to handle PSModulePath and Experimental Features.
Is there something else you had in mind that could achieve this?

@jshigetomi
Copy link
Collaborator Author

jshigetomi commented Dec 18, 2025

@kilasuit

I think the plan would be that this is all contained within 7.6.x as not to drag this out for more years but that's something that @jshigetomi & team can confirm on, but that was my expectation at least

I think the plan as of now is to introduce it in 7.7 preview and stabilize it in 7.7 rc. Definitely do not want to drag this on for more years than it already has.

@iSazonov
Copy link
Collaborator

I am concerned about this step. I believe users will not know about this feature and not enable the experimental feature to begin the gradual moving of resources.

Notice, experimental feature is enabled by default. But really we could avoid experimental feature at all and make it as regular.

I believe that any migration involving copying folders, enabling or disabling any settings, will always cause massive problems for users.

Currently we look one standard folder, then second and so on. If we put the new APPDATA folder before Documents folder the new folder will have higher priority and will work transparently. So we have no need to make it as experimental. For better UX install cmdlet could warn about this new default and maybe explicitly allow old behavior (what if anybody uses OneDrive cloud replication?).

@jshigetomi
Copy link
Collaborator Author

jshigetomi commented Dec 19, 2025

@iSazonov
In this PR I wrote it so that it disables PSContentPath by default.

Interesting idea on making it non-experimental and putting AppData before OneDrive. I will bring it up in our design meeting.

I do see a need to remove OneDrive from the path entirely and users need a way to do that.

@iSazonov
Copy link
Collaborator

iSazonov commented Dec 19, 2025

I do see a need to remove OneDrive from the path entirely and users need a way to do that.

At some point in the past, I used OneDrive to replicate installed modules. Not now. But do we know how many users use this scenario? And why should we deprive them of this opportunity?
To avoid complaints, I would prefer the soft path as I described it - by default, use APPDATA to install resources, put resources in the old folder only with the explicit switch in install cmdlets, and leave the old folder in the second place to search.
At the same stage, I would add telemetry to collect statistics on the use of modules from the old folder. Then we will have objective information in order to decide what to do with this folder at the next stage - whether to add an option to disable/enable it and, if so, what the default value should be.

In this PR I wrote it so that it disables PSContentPath by default.

Few people will turn it on. It's useless. Especially in Preview versions.

@jshigetomi
Copy link
Collaborator Author

@iSazonov

I do see a need to remove OneDrive from the path entirely and users need a way to do that.

By this I meant to give an option to remove OneDrive. One of the main goals of this is to provide a way for users to avoid syncing with OneDrive.

I do like the soft path you said. In that scenario Set-PSContentPath -Remove could remove OneDrive as a location for pwsh.

@kilasuit
Copy link
Collaborator

kilasuit commented Dec 20, 2025

I think the plan as of now is to introduce it in 7.7 preview and stabilize it in 7.7 rc.

@jshigetomi - I feel like this has to come in as part of 7.6.x stream of releases as it also allows for it to be in the 7.7.x branches for previews & backported to a 7.6.x release as not to wait yet another full year or more before it making it's way to most users especially as 7.6.x is the LTS releases it makes sense this being in one of those releases.

Honestly, I'd really, really, like to see it in as part of 7.6.0 GA & have no doubt that the mass majority of the community would also want it in that release or available to that release branch so that maybe 7.6.1 or 7.6.2 etc it can come in and then move from being Experimental to being Stable & allow for backportability to other supported versions if needed. Timeframe for that is of course up to the team to determine but I'd really rather not let this drag even longer than needed as this is a pain point for many orgs that have document compliance needs & this then forces them to store these longer than necessary.

Because we really do not need to let this drag out any longer than it needs to, however I do think it should be experimental in 7.6.0 GA so that we can gather telemetry around those turning it off and marked stable in another 7.6.x release. This gives broadest range of users and also shortens the time required for feedback from other partner teams in and out of Microsoft as well as in the community. I don't think that this really needs to wait till 7.7.0 GA or worse 7.8.0 GA to get to the mass majority of users.

Whilst I see where @iSazonov is coming from about migrations, this should be able to be pretty seemless, as long as other aspects like how PSContentPath is applied powershell.config.json or via CLI Parameter or via GPO setting & which takes priority and is properly documented, with a best attempt` migration script provided to the Gallery or Microsoft Artifacts Registry, here as a released & signed script package, or to all them and blogged about. I'm pretty sure that we can get enough testers in different environments if we can get blogs and emails out about testing it early enough and make use of any MVP/RD/MGCI and community distribution lists & blogs to get a wide ranging sample of test users & organisations.

I personally use a mix of OneDrive Consumer & Business, it's typically the Business OneDrive users that have complaints, so I can help with building the test matrix which overall is the key here to getting this in and getting it done right & first time, which I'm pretty sure the direction of travel with this will see us meet that requirement. If it would help @jshigetomi I could & I'm sure @iSazonov could provide example user stories for this to test against the migration scenario, as others too in the community that I already have in mind to contact that I will be reaching out to when this lands in a release. I can also help with setting up 1 or more test environment/s using bicep, DSC and Azure if I could get enough access to an Azure subscription to do so, as this is one of my area's of expertise which maybe yourself or @SteveL-MSFT can work with me on as a way of POC for this, though again those in my list to contact probably already have test environments to use with this too so may not need me to create one as such but I'm mentioning it for full visibility as to how wide ranging this issue is and the impact it could have that I already am aware of, which I hope is of help here.

@kilasuit
Copy link
Collaborator

Whilst I can also help, in the area's I've mentioned, I know there are many others that could do too and it would be good for others to step up and take the lead on their own experiments as to enable us to get this in sooner rather than later. Of course, I realise that this has to be correctly prioritised by all that wanna get involved in making this happen, with their other workloads. But I really would like it, if, we could make it happen before April next year.

@microsoft-github-policy-service microsoft-github-policy-service bot added the Review - Needed The PR is being reviewed label Jan 3, 2026
@jshigetomi
Copy link
Collaborator Author

After discussing with the PowerShell team I think the best approach is to make this not an experimental feature.
It will only introduce the new infrastructure to customize PowerShell content path and point it at OneDrive by default to prevent breaking users. For most users nothing would change and for those users that want to relocate, they can do so.

The benefits of this approach include the following:

  • There is no behavioral change on the users' part so this is an infrastructure change not an experimental feature.
  • Removing the experimental feature aspect of this will simplify the code significantly.
  • Keeps the opt-in aspect of this feature where users decide whether to switch locations.

The plan is now to introduce an experimental feature in the next PR that sets the default to LocalAppData.

@jshigetomi jshigetomi changed the title Add Experimental Feature PSContentPath Add PSContentPath Infrastructure Jan 12, 2026
@jshigetomi jshigetomi closed this Jan 13, 2026
@jshigetomi jshigetomi reopened this Jan 13, 2026
@jshigetomi jshigetomi added CL-Engine Indicates that a PR should be marked as an engine change in the Change Log and removed CL-Experimental Indicates that a PR should be marked as an Experimental Feature in the Change Log labels Jan 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CL-Engine Indicates that a PR should be marked as an engine change in the Change Log Review - Needed The PR is being reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants