Contributing to Pakko
Prerequisites
- Visual Studio 2026 with the .NET desktop and Desktop development with C++ workloads, plus the MSVC v143 (14.44) x64 and ARM64 build tools (the shell extension targets v143; the Native AOT link of the four exes, T-F355, uses the same C++ tools)
- .NET 10 SDK (
global.jsonpins the 10.0.100 feature band or later) - Language: C# 14 (set once in
Directory.Build.props) - PowerShell 7 (
pwsh) forscripts/*.ps1(T-F371) - Windows 10 1809+ or Windows 11
Building and testing
# Build the core library (works from any terminal)
dotnet build src/Archiver.Core
# Run all tests (excludes a handful of real multi-second Zip64/performance tests and a couple of
# genuinely large, on-demand-only tests)
dotnet test --filter "Category!=Slow&Category!=VeryLarge"
# Run the Zip64 tests too, before a release or when touching Zip64-adjacent code
dotnet test --filter "Category=Slow"
Always run dotnet test with no path argument — all projects must stay green after every change.
The WinUI 3 application (Archiver.App) is debugged from Visual Studio 2026.
dotnet build src/Archiver.Core and dotnet test work freely from the terminal — as does
dotnet build src/Archiver.App, which compiles the WinUI project (useful as a quick
compile-check on ViewModel/XAML changes without opening Visual Studio), though full MSIX
packaging/signing/running still needs Deploy.ps1 or Visual Studio.
Never verify an on-device UI or interaction change against a package installed by a bare
dotnet build. Its incremental packaging step can silently skip repackaging a changed DLL into the installed.msix— confirmed to go as far as running a stale event handler's old logic entirely, while still reporting "Build succeeded" and showing a fresh-looking title-bar build timestamp. Always run the full.\scripts\Deploy.ps1(it wipes oldAppPackagesoutput before rebuilding) before trusting any on-device check. Seescripts/README.mdfor usage.
Static analysis
Directory.Build.props enables AnalysisLevel=latest-recommended + EnforceCodeStyleInBuild
repo-wide, so a plain dotnet build/dotnet test already surfaces real .NET analyzer findings
(reviewed severity overrides for known-noisy families live in .editorconfig) — no separate step
needed to see these locally.
For the same SonarSource rule engine SonarCloud runs in CI (S3869, S6562, etc.), install the free
SonarLint extension for your editor — Visual Studio,
VS Code, or
Rider. It flags the same issues live in the
editor, before a commit ever reaches CI. See docs/TASKS.md's T-F137 entry for the rationale.
Test fixtures
tests/Archiver.Core.Tests.GenerateFixtures is a standalone console project that creates
the binary ZIP fixtures consumed by Archiver.Core.Tests. Fixtures are pre-generated and
committed to the repository — you do not need to regenerate them on a normal clone.
Regenerate fixtures when:
- Adding new tests that require new fixture files
- Existing fixtures become corrupted
dotnet run --project tests/Archiver.Core.Tests.GenerateFixtures
Output goes to tests/Archiver.Core.Tests/Fixtures/.
Local MSIX deployment
For local development and testing you need a signed MSIX. See scripts/README.md
for full details. The short version:
Once per machine — create and install a self-signed developer certificate:
.\scripts\Setup-DevCert.ps1Copy the thumbprint it prints.
After each build — package and sideload:
.\scripts\Deploy.ps1 # or: .\scripts\Deploy.ps1 -Thumbprint "<thumbprint>"Visual Studio shortcut — Release builds in VS trigger
Deploy.ps1 -DeployOnlyautomatically via a post-build event. No manual script needed after first setup; just build in Release and the new MSIX is installed automatically. Use.\scripts\Deploy.ps1from the terminal for a full build + deploy outside of Visual Studio.
CI: every push to
mainand every pull request also builds and tests automatically via.github/workflows/build.yml— this doesn't replace the local steps above, it just means a red test suite or a broken build/sign step gets caught before merge. Seescripts/README.md's "Continuous Integration" section for what it builds and how it's signed.
Testing the Explorer hand-off
After installing the MSIX, run the installed Archiver.Shell.exe --open-ui --extract <archive>
and check that Pakko opens with the archive in its list — the exact command is in
scripts/README.md, Step 3. (Pakko registers no pakko:// URI scheme since
T-F232.)
Project structure
| Project | Role |
|---|---|
Archiver.Core |
Compression/extraction logic and the tar.exe AppContainer sandbox — no UI dependencies, no NuGet packages |
Archiver.App.Core |
WinUI-free helpers for Archiver.App (Archive Browser tree/breadcrumb building, real-filesystem browsing, file-activation routing) — kept separate so they're unit-testable without a WinUI test host |
Archiver.App |
WinUI 3 main application |
Archiver.Shell |
Shell-triggered operation entry point (silent CLI, launched by the shell extension); shows progress via the Windows Shell's built-in IProgressDialog, in-process |
Archiver.ShellExtension |
C++ COM DLL implementing IExplorerCommand (the actual right-click context menu) — built via MSBuild, not dotnet build; see .claude/rules/shell-extension.md |
Archiver.CLI |
Standalone console frontend (T-F09), built as pakko.exe — no WinUI; ships as its own self-contained per-architecture download via scripts/Publish-Cli.ps1 (and winget), and since T-F317 also inside the MSIX behind the pakko execution alias; see docs/CLI.md |
Archiver.Messages |
Core's error/skip messages in 37 languages, shared by Archiver.Shell and Archiver.App (T-F209) |
Archiver.Core.Tests |
Unit tests for core compression/extraction logic |
Archiver.Core.IntegrationTests |
Tests that shell out to the real C:\Windows\System32\tar.exe (tagged [Integration]) |
Archiver.Core.PerformanceTests |
ZIP compression/extraction performance-regression tests vs. a vendored, sandboxed 7za.exe reference (T-F114); see docs/TESTING.md |
Archiver.App.Core.Tests |
Unit tests for Archiver.App.Core's WinUI-free helpers |
Archiver.Shell.Tests |
Argument parser tests for Archiver.Shell |
Archiver.ShellExtension.Tests |
C++ Google Test suite for Archiver.ShellExtension's COM-free logic — run separately, not covered by dotnet test; see .claude/rules/shell-extension.md |
Archiver.Messages.Tests |
Translation parity for Archiver.Messages and its culture resolver |
Archiver.CLI.Tests |
Parser/mapper/help-text unit tests for Archiver.CLI plus a Subprocess/ layer that launches the real built pakko.exe; see docs/CLI.md |
Archiver.Core.Tests.GenerateFixtures |
Fixture generator (see above) |
There is no
Archiver.ProgressWindowproject — an earlier design (a second WinUI 3 satellite.exetalking toArchiver.Shellover a named pipe) was removed; seedocs/DECISIONS.md(T-F65).