Skip to the content.

CLAUDE.md

Guidance for working in this repository.

What this is

Hosts File Editor — a Windows desktop app for editing the system hosts file (%WinDir%\System32\drivers\etc\hosts). It supports cut/copy/paste/duplicate/enable/disable/move of entries, filtering and sorting, enabling/disabling the entire hosts file, archiving and restoring hosts-file configurations (presets, also reachable from a taskbar Jump List), merging another hosts file with duplicate elimination, auto-pinging endpoints to check availability, and a headless command line (apply/enable/disable/import/merge/list) shared by both editions.

The repository is mid-migration from WinForms to WinUI 3. Two UIs currently ship side by side on top of one shared core library:

When changing behavior, prefer putting shared logic in HostsFileEditor.Core so both UIs benefit. New UI work should go into the WinUI project; touch the WinForm project only for parity fixes unless asked otherwise.

Projects

Project Type TFM Notes
HostsFileEditor.Core Class library net10.0-windows Domain model, file I/O, undo/redo, Win32 interop. No UI dependencies. The important code lives here.
HostsFileEditor.Core.Tests MSTest net10.0-windows Tests for Core. Uses MSTest + Shouldly. InternalsVisibleTo grants access to internals.
HostsFileEditor.WinUI WinUI 3 app net10.0-windows10.0.19041.0 “Modern” UI. DI via Microsoft.Extensions.DependencyInjection, MSIX/AOT/trimmed publish, x64+arm64.
HostsFileEditor.WinForm WinForms app net10.0-windows “Classic” UI. Self-contained, ReadyToRun, win-x64. Uses Equin.ApplicationFramework.BindingListView.
HostsFileEditor.Elevate Helper exe (no window) net10.0-windows Tiny asInvoker exe launched with the runas verb to perform privileged hosts-file writes/moves on demand. Copied into an Elevate\ subfolder beside each app (AOT-published for packages).
HostsFileEditor.Cli Console exe (hfe.exe) net10.0-windows Console-subsystem launcher for the shared CLI (Core/CommandLine/HostsCli) — cmd/PowerShell wait for it, unlike the GUI exes. One-line Main. AOT-published into each app’s publish root (PublishCliLauncher targets); MSIX packages register an hfe app-execution alias.

Solution file is HostsFileEditor.slnx (the new XML solution format). The WinUI project is pinned to the x64 platform in the solution.

Build, test, run

Run from a Visual Studio 2022 Developer PowerShell so makeappx.exe and signtool.exe (Windows SDK) are on PATHdotnet publish signs and packages MSIX via Directory.Build.targets.

dotnet build HostsFileEditor.slnx -c Debug        # build everything
dotnet test  HostsFileEditor.slnx                 # run Core.Tests (with coverage.runsettings)
dotnet build HostsFileEditor.slnx -c Release      # optimized build
dotnet publish -c Release                          # produces signed exe + MSIX into artifacts/
dotnet publish -c Release -bl:logs/publish.binlog  # with binary log for troubleshooting
dotnet clean

Single-project iteration is fastest for Core work:

dotnet build HostsFileEditor.Core/HostsFileEditor.Core.csproj -c Debug
dotnet test  HostsFileEditor.Core.Tests/HostsFileEditor.Core.Tests.csproj

The WinUI project requires an explicit platform/RID; defaults are x64 / win-x64. If a plain dotnet build of the solution complains about platform, build the WinUI csproj with -p:Platform=x64.

Both apps run as a standard user (asInvoker) — required for the Microsoft Store. Editing the real hosts file (save / enable / disable) needs admin, so those operations elevate on demand by launching the HostsFileEditor.Elevate helper with the runas verb (a UAC prompt at save time). Everything else — viewing, archiving, backups — is per-user (%LocalAppData%\HostsFileEditor) and needs no elevation. Tests never touch the real hosts file — see the test hooks below.

Conventions (enforced by build)

Directory.Build.props applies to every project:

.editorconfig is the source of truth for style: 4-space indent, CRLF, file-scoped namespaces, _camelCase private fields, PascalCase constants, I-prefixed interfaces, var preferred, expression-bodied members when on a single line. Run dotnet format HostsFileEditor.slnx before finishing a change.

Per-project NoWarn exists for real constraints (WinForms + AOT/trim limitations in the WinForm project, a few analyzer IDs in Core/WinUI). Read the comment next to a NoWarn before assuming it’s safe to remove.

Core domain model — the important parts

Per-edition extras (not in Core)

Test hooks (do not remove)

Core exposes internal overrides so tests run without elevation or touching the real system:

Tests are MSTest classes ([TestClass]/[TestMethod]) using Shouldly assertions (value.ShouldBe(...)). Keep tests free of any dependency on the live hosts file or admin rights.

WinUI app structure

Packaging (Directory.Build.targets)

dotnet publish runs a SignAndPackage target after publish: signs the binaries (app exe, the Elevate helper, and hfe.exe), builds an MSIX with makeappx, optionally signs the MSIX (SignPackage=true, sideload only — needs the manifest Publisher to match the cert subject; see docs/signing.md), optionally zips, and copies outputs to artifacts\<flavor>\. Per-app PublishElevateHelper/PublishCliLauncher targets AOT-publish the helper exes into the publish output first, and strip targets delete unused runtime libraries (WPF natives from classic, WinApp SDK ML/Widgets libs from modern). Tool paths (signtool.exe/makeappx.exe) resolve from the Windows SDK via several fallbacks (VS dev shell env vars, then registry KitsRoot10). Test signing cert is HostsFileEditorTestCert.pfx (password test) — for local/dev only.

Store release automation (publish-store.ps1)

Both editions ship to the Microsoft Store as separate apps — classic 9NF73PSPK332, modern 9NBQWCDXGF9R. Instead of the Partner Center portal UI, publish-store.ps1 scripts the submissions with StoreBroker — Microsoft’s PowerShell module over the Store submission REST API. (The msstore CLI was tried first and abandoned: its publish builds a project of a recognized type and can’t push our pre-built, externally-signed MSIX to an existing app by product id.)

Gotchas