PowerShell Became Open Source and Cross-Platform in 2016
Microsoft's August 2016 announcement put PowerShell on GitHub and introduced it on Linux and macOS, changing its scope well beyond Windows administration.
On August 18, 2016, Microsoft announced that PowerShell was becoming an open-source project and made early alpha packages available for Linux and macOS. The source appeared on GitHub under the MIT license, turning a Windows-centered automation environment into a cross-platform project developed in public.
The object pipeline was already the defining difference
PowerShell pipelines pass .NET objects between commands rather than requiring every command to flatten its output into lines of text. A later stage can address properties such as process names, identifiers, or memory values without reparsing columns intended for a human display.
Cross-platform support extended that model to Linux and macOS, but it did not make every Windows-specific cmdlet portable. The engine, language, and broad module ecosystem can run across systems; modules that depend on Windows-only services or APIs still remain platform-specific.
Open development changed the feedback loop
Hosting the code, issues, and pull requests publicly made it possible for users outside Microsoft to inspect implementation choices, report platform-specific behavior, and contribute fixes. The move also accompanied a shift from the Windows-only product lineage toward the separately installable project now called PowerShell 7.
Windows PowerShell 5.1 did not simply disappear. It remains a Windows component built on the older .NET Framework and is still required by some legacy modules. PowerShell 7 is the actively developed cross-platform edition, installed side by side under the pwsh executable.
Why the announcement was historically significant
Microsoft had already begun releasing major developer technologies as open source, but PowerShell was an especially visible systems-administration tool. Bringing it to Unix-like systems acknowledged that contemporary infrastructure spans operating systems and that one automation language can be useful across those boundaries without pretending the underlying platforms are identical.
The runtime swap that actually made cross-platform possible
Windows PowerShell’s original engine is built directly on the .NET Framework, a Windows-only runtime - no amount of source-code openness alone would have made that combination run on Linux or macOS. What actually enabled cross-platform support was pairing PowerShell with .NET Core instead, Microsoft’s separately developed, genuinely cross-platform .NET runtime; this new combination shipped under the name PowerShell Core, reaching general availability as version 6.0 in early 2018 following the 2016 open-source announcement. The distinction still matters today: PowerShell 7 (the current cross-platform line) runs on .NET, while Windows PowerShell 5.1 remains a separate, Windows-only, .NET Framework-based component still bundled with Windows itself.
Why this specific technical dependency chain matters for anyone scripting across both
Because Windows PowerShell 5.1 and modern cross-platform PowerShell 7 run on genuinely different underlying runtimes, not every module or script written for one is guaranteed to behave identically on the other, even though the scripting language itself looks nearly the same on the surface. A module wrapping a Windows-only COM object or relying on a .NET Framework-specific API can fail or behave differently under PowerShell 7’s .NET-based runtime - worth checking explicitly, especially for any automation originally written years ago for classic Windows PowerShell, before assuming it will simply work unmodified once moved over to run under the newer, genuinely cross-platform engine on a different, non-Windows operating system entirely, rather than the original, native Windows environment the script or module was first written, tested, and actually verified against.
The announcement and the product were separate milestones
The August 2016 announcement combined several changes that are easy to collapse into one headline: the source repository was opened, an open-source license was selected, and early builds for Linux and macOS were made available. Those were related, but source availability by itself did not make the existing Windows PowerShell executable portable. The later runtime transition mattered because the previous Windows edition depended on the Windows-only .NET Framework. PowerShell Core 6.0 reached general availability in January 2018 on .NET Core 2.0, making the cross-platform path a supported product rather than only an announcement-era experiment.
Microsoft now distinguishes Windows PowerShell from PowerShell as separate products. Windows PowerShell 5.1 is the built-in Desktop edition on Windows and runs on .NET Framework. PowerShell 6 and later use the Core edition and modern .NET, and can be installed side by side with 5.1. Current documentation describes supported platforms and lifecycle by the specific PowerShell and .NET version, so old statements such as “runs on every Linux” should not be treated as timeless compatibility guarantees.
Object pipelines do not erase platform boundaries
PowerShell’s pipeline carries objects between PowerShell commands. A downstream cmdlet can select an object’s property instead of scraping a column layout intended for a person:
Get-Process |
Where-Object { $_.CPU -gt 10 } |
Select-Object ProcessName, Id, CPU
This is different from assuming that every command in a pipeline speaks an object protocol. When a pipeline crosses into a native executable, PowerShell must translate data to the native program’s argument and stream conventions. The native program may print text rather than structured .NET objects. Cross-platform scripts should define that boundary explicitly: use PowerShell cmdlets when their semantics fit, and parse native output only when its format is stable and documented.
The object model is useful across operating systems, but the objects and commands available depend on the operating system, runtime, and installed modules. A cmdlet that manages Windows services or registry keys has no automatic equivalent on Linux merely because the shell engine starts there. Likewise, filesystem path conventions, case behavior, permissions, process APIs, and service managers differ.
A practical migration check before changing the executable
First identify which product and runtime are running rather than inferring it from the prompt:
$PSVersionTable | Select-Object PSVersion, PSEdition, OS, Platform
Get-Command -Name Get-Service, Get-Process -ErrorAction SilentlyContinue
Get-Module -ListAvailable | Select-Object Name, Version, CompatiblePSEditions
The exact modules and properties returned vary by platform. Use the module’s manifest and vendor documentation as the compatibility authority; a module manifest can declare compatible editions, but that is not a proof that every operational dependency is present or that behavior is equivalent. Test in the actual target OS and account context.
A safe migration inventory records the PowerShell executable path, engine version, edition, .NET runtime, profile files, module paths, scheduled tasks or services that invoke scripts, and any modules that depend on COM, Windows-only .NET types, WMI/CIM providers, registry providers, or Windows authentication. Then run representative scripts under both 5.1 and the target 7.x version, checking output types, errors, exit codes, native command invocation, remoting, and filesystem paths.
PowerShell 7 can offer a compatibility mechanism for some Windows PowerShell modules on Windows, but that does not make such modules portable to macOS or Linux. It also does not remove the need to test serialization boundaries or module-specific dependencies. Keep deployment rollback simple: install side by side, invoke the intended executable explicitly, and change scheduled jobs only after their compatibility tests pass.
What open source changed, and what it did not
Opening the repository made implementation and issue tracking visible to users outside Microsoft and created a public route for contributions. It did not transfer responsibility for the release process to the community, guarantee that every feature request would be accepted, or convert platform-specific APIs into portable ones. Cross-platform engineering still involves deliberate runtime, API, packaging, and test decisions.
The historical significance is therefore twofold. PowerShell’s licensing and development process changed in 2016; the runtime and supported product line evolved afterward. For operators, the practical result is not “one script works everywhere,” but a shell with a shared language surface and object-oriented pipeline that can be deployed on multiple operating systems when the commands, modules, APIs, and runtime dependencies used by that workload support them.
Related:
- Bill Joy’s C Shell Joins Berkeley’s 2BSD Distribution
- Zsh 1.0: Paul Falstad’s 1990 Announcement of a ksh/tcsh-Like Shell
Sources:
- PowerShell on Linux and Open Source - Microsoft PowerShell Blog
- PowerShell repository - GitHub
- PowerShell Core 6.0: Generally Available - PowerShell Team Blog
- PowerShell editions - Microsoft Learn
- Migrating from Windows PowerShell 5.1 to PowerShell 7 - Microsoft Learn
- Differences between Windows PowerShell 5.1 and PowerShell 7.x - Microsoft Learn